Beispiel #1
0
    def download(self, file_id, revision_id=None):
        file_id = int(file_id)
        revision_id = int(revision_id) if revision_id!='latest' else None
        user = tmpl_context.current_user
        workspace = tmpl_context.workspace

        content_api = ContentApi(user)
        revision_to_send = None
        if revision_id:
            item = content_api.get_one_from_revision(file_id,  self._item_type, workspace, revision_id)
        else:
            item = content_api.get_one(file_id, self._item_type, workspace)

        revision_to_send = None
        if item.revision_to_serialize<=0:
            for revision in item.revisions:
                if not revision_to_send:
                    revision_to_send = revision

                if revision.revision_id>revision_to_send.revision_id:
                    revision_to_send = revision
        else:
            for revision in item.revisions:
                if revision.revision_id==item.revision_to_serialize:
                    revision_to_send = revision
                    break

        content_type = 'application/x-download'
        if revision_to_send.file_mimetype:
            content_type = str(revision_to_send.file_mimetype)
            tg.response.headers['Content-type'] = str(revision_to_send.file_mimetype)

        tg.response.headers['Content-Type'] = content_type
        tg.response.headers['Content-Disposition'] = str('attachment; filename="{}"'.format(revision_to_send.file_name))
        return revision_to_send.file_content
Beispiel #2
0
    def treeview_children(self,
                          id='#',
                          ignore_id=None,
                          allowed_content_types=None):
        """
        id must be "#" or something like "workspace_3__document_8"
        """
        if id == '#':
            return self.treeview_root()

        ignore_item_ids = [int(ignore_id)] if ignore_id else []
        workspace, content = convert_id_into_instances(id)

        viewable_content_types = []
        if allowed_content_types:
            viewable_content_types = allowed_content_types.split(',')
        else:
            viewable_content_types = self._get_treeviewable_content_types_or_none(
            )
        contents = ContentApi(tmpl_context.current_user).get_child_folders(
            content, workspace, [], ignore_item_ids, viewable_content_types)
        # This allow to show contents and folders group by type
        sorted_contents = ContentApi.sort_content(contents)

        dictified_contents = Context(CTX.MENU_API).toDict(sorted_contents, 'd')
        return dictified_contents
Beispiel #3
0
 def download_pdf_one(self,
                      page_id: str,
                      revision_id: str=None,
                      *args, **kwargs):
     file_id = int(tg.request.controller_state.routing_args.get('file_id'))
     revision_id = int(revision_id) if revision_id != 'latest' else None
     page = int(page_id)
     cache_path = CFG.get_instance().PREVIEW_CACHE_DIR
     preview_manager = PreviewManager(cache_path, create_folder=True)
     user = tmpl_context.current_user
     content_api = ContentApi(user,
                              show_archived=True,
                              show_deleted=True)
     file = content_api.get_one(file_id, self._item_type)
     if revision_id:
         file_path = content_api.get_one_revision_filepath(revision_id)
     else:
         file = content_api.get_one(file_id, self._item_type)
         file_path = content_api.get_one_revision_filepath(file.revision_id)
     path = preview_manager.get_pdf_preview(file_path=file_path,
                                            page=page)
     file_suffix = ''
     if page > -1:
         file_suffix = '.page-{}'.format(page + 1)
     tg.response.headers['Content-Disposition'] = \
         'attachment; filename="{}{}.pdf"'.format(
             file.label,
             file_suffix,
         )
     with open(path, 'rb') as pdf:
         return pdf.read()
Beispiel #4
0
    def download_pdf_one(self, page_id, *args, **kwargs):
        file_id = int(tg.request.controller_state.routing_args.get('file_id'))
        page_id = int(page_id)
        # page_id = int(tg.request.controller_state.routing_args.get('page_id'))

        # For now it's done through database content
        # but soon it'll be with disk access

        user = tmpl_context.current_user
        content_api = ContentApi(
            user,
            show_archived=True,
            show_deleted=True,
        )
        file_name = content_api.get_one(file_id, self._item_type).file_name

        cache_path = '/home/alexis/Pictures/cache/'

        preview_manager = PreviewManager(cache_path, create_folder=True)
        path = preview_manager.get_pdf_preview(
            file_path='/home/alexis/Pictures/cache/{}'.format(file_name),
            page=page_id,
        )

        tg.response.headers['Content-Disposition'] = \
            str('attachment; filename="{}"'.format(file_name))
        with open(path, 'rb') as pdf:
            return pdf.read()
Beispiel #5
0
    def test_set_status_ok(self):
        uapi = UserApi(None)
        groups = [
            GroupApi(None).get_one(Group.TIM_USER),
            GroupApi(None).get_one(Group.TIM_MANAGER),
            GroupApi(None).get_one(Group.TIM_ADMIN)
        ]

        user = uapi.create_user(email='this.is@user',
                                groups=groups,
                                save_now=True)

        workspace = WorkspaceApi(user).create_workspace('test workspace',
                                                        save_now=True)
        api = ContentApi(user)
        c = api.create(ContentType.Folder, workspace, None, 'parent', True)
        with new_revision(c):
            for new_status in [
                    'open', 'closed-validated', 'closed-unvalidated',
                    'closed-deprecated'
            ]:
                api.set_status(c, new_status)

                eq_(new_status, c.status)
                eq_(ActionDescription.STATUS_UPDATE, c.revision_type)
Beispiel #6
0
    def post(self, label='', content='', parent_id=None):
        """
        Creates a new thread. Actually, on POST, the content will be included
        in a user comment instead of being the thread description
        :param label:
        :param content:
        :return:
        """
        # TODO - SECURE THIS
        workspace = tmpl_context.workspace

        api = ContentApi(tmpl_context.current_user)

        with DBSession.no_autoflush:
            thread = api.create(ContentType.Thread, workspace,
                                tmpl_context.folder, label)
            # FIXME - DO NOT DUPLCIATE FIRST MESSAGE
            # thread.description = content
            api.save(thread, ActionDescription.CREATION, do_notify=False)

            comment = api.create(ContentType.Comment, workspace, thread, label)
            comment.label = ''
            comment.description = content

            if not self._path_validation.validate_new_content(thread):
                return render_invalid_integrity_chosen_path(
                    thread.get_label(), )

        api.save(comment, ActionDescription.COMMENT, do_notify=False)
        api.do_notify(thread)

        tg.flash(_('Thread created'), CST.STATUS_OK)
        tg.redirect(
            self._std_url.format(tmpl_context.workspace_id,
                                 tmpl_context.folder_id, thread.content_id))
Beispiel #7
0
    def __init__(self, path: str, environ: dict, content: Content):
        super(File, self).__init__(path, environ)

        self.content = content
        self.user = UserApi(None).get_one_by_email(
            environ['http_authenticator.username'])
        self.content_api = ContentApi(self.user)
Beispiel #8
0
    def test_mark_read(self):
        uapi = UserApi(None)
        groups = [GroupApi(None).get_one(Group.TIM_USER),
                  GroupApi(None).get_one(Group.TIM_MANAGER),
                  GroupApi(None).get_one(Group.TIM_ADMIN)]
        user_a = uapi.create_user(email='this.is@user',
                                 groups=groups, save_now=True)
        user_b = uapi.create_user(email='*****@*****.**',
                                 groups=groups, save_now=True)

        wapi = WorkspaceApi(user_a)
        workspace = wapi.create_workspace(
            'test workspace',
            save_now=True)

        role_api = RoleApi(user_a)
        role_api.create_one(user_b, workspace, UserRoleInWorkspace.READER, False)
        cont_api_a = ContentApi(user_a)
        cont_api_b = ContentApi(user_b)

        page_1 = cont_api_a.create(ContentType.Page, workspace, None,
                                   'this is a page', do_save=True)

        for rev in page_1.revisions:
            eq_(user_b not in rev.read_by.keys(), True)

        cont_api_b.mark_read(page_1)

        for rev in page_1.revisions:
            eq_(user_b in rev.read_by.keys(), True)
Beispiel #9
0
    def get_one(self, page_id, revision_id=None):
        page_id = int(page_id)
        user = tmpl_context.current_user
        workspace = tmpl_context.workspace

        current_user_content = Context(CTX.CURRENT_USER).toDict(user)
        current_user_content.roles.sort(key=lambda role: role.workspace.name)

        content_api = ContentApi(
            user,
            show_deleted=True,
            show_archived=True,
        )
        if revision_id:
            page = content_api.get_one_from_revision(page_id, ContentType.Page,
                                                     workspace, revision_id)
        else:
            page = content_api.get_one(page_id, ContentType.Page, workspace)

        fake_api_breadcrumb = self.get_breadcrumb(page_id)
        fake_api_content = DictLikeClass(breadcrumb=fake_api_breadcrumb,
                                         current_user=current_user_content)
        fake_api = Context(CTX.FOLDER).toDict(fake_api_content)

        dictified_page = Context(CTX.PAGE).toDict(page, 'page')
        return DictLikeClass(result=dictified_page, fake_api=fake_api)
Beispiel #10
0
    def get_one(self, thread_id, inverted: str = ''):
        thread_id = int(thread_id)
        user = tmpl_context.current_user
        workspace = tmpl_context.workspace

        current_user_content = Context(CTX.CURRENT_USER).toDict(user)
        current_user_content.roles.sort(key=lambda role: role.workspace.name)

        content_api = ContentApi(user)
        thread = content_api.get_one(thread_id, ContentType.Thread, workspace)

        fake_api_breadcrumb = self.get_breadcrumb(thread_id)
        fake_api_content = DictLikeClass(breadcrumb=fake_api_breadcrumb,
                                         current_user=current_user_content)
        fake_api = Context(CTX.FOLDER).toDict(fake_api_content)

        dictified_thread = Context(CTX.THREAD).toDict(thread, 'thread')

        if inverted:
            dictified_thread.thread.history = reversed(
                dictified_thread.thread.history)

        return DictLikeClass(result=dictified_thread,
                             fake_api=fake_api,
                             inverted=inverted)
Beispiel #11
0
    def test_create_comment_ok(self):
        uapi = UserApi(None)
        groups = [
            GroupApi(None).get_one(Group.TIM_USER),
            GroupApi(None).get_one(Group.TIM_MANAGER),
            GroupApi(None).get_one(Group.TIM_ADMIN)
        ]

        user = uapi.create_user(email='this.is@user',
                                groups=groups,
                                save_now=True)

        workspace = WorkspaceApi(user).create_workspace('test workspace',
                                                        save_now=True)

        api = ContentApi(user)
        p = api.create(ContentType.Page, workspace, None, 'this_is_a_page')
        c = api.create_comment(workspace, p, 'this is the comment', True)

        eq_(Content, c.__class__)
        eq_(p.content_id, c.parent_id)
        eq_(user, c.owner)
        eq_(workspace, c.workspace)
        eq_(ContentType.Comment, c.type)
        eq_('this is the comment', c.description)
        eq_('', c.label)
        eq_(ActionDescription.COMMENT, c.revision_type)
Beispiel #12
0
 def get_one(self,
             page_id: str='-1',
             revision_id: str=None,
             size: int=300,
             *args, **kwargs):
     file_id = int(tg.request.controller_state.routing_args.get('file_id'))
     page = int(page_id)
     revision_id = int(revision_id) if revision_id != 'latest' else None
     cache_path = CFG.get_instance().PREVIEW_CACHE_DIR
     preview_manager = PreviewManager(cache_path, create_folder=True)
     user = tmpl_context.current_user
     content_api = ContentApi(user,
                              show_archived=True,
                              show_deleted=True)
     if revision_id:
         file_path = content_api.get_one_revision_filepath(revision_id)
     else:
         file = content_api.get_one(file_id, self._item_type)
         file_path = content_api.get_one_revision_filepath(file.revision_id)
     try:
         path = preview_manager.get_jpeg_preview(file_path=file_path,
                                                 page=page,
                                                 height=size,
                                                 width=size)
         with open(path, 'rb') as large:
             result = large.read()
     except PreviewGeneratorException:
         result = None
     return result
Beispiel #13
0
 def get_one(self,
             page_id: str = '-1',
             revision_id: str = None,
             size: int = 300,
             *args,
             **kwargs):
     file_id = int(tg.request.controller_state.routing_args.get('file_id'))
     page = int(page_id)
     revision_id = int(revision_id) if revision_id != 'latest' else None
     cache_path = CFG.get_instance().PREVIEW_CACHE_DIR
     preview_manager = PreviewManager(cache_path, create_folder=True)
     user = tmpl_context.current_user
     content_api = ContentApi(user, show_archived=True, show_deleted=True)
     if revision_id:
         file_path = content_api.get_one_revision_filepath(revision_id)
     else:
         file = content_api.get_one(file_id, self._item_type)
         file_path = content_api.get_one_revision_filepath(file.revision_id)
     try:
         path = preview_manager.get_jpeg_preview(file_path=file_path,
                                                 page=page,
                                                 height=size,
                                                 width=size)
         with open(path, 'rb') as large:
             result = large.read()
     except PreviewGeneratorException:
         result = None
     return result
Beispiel #14
0
    def add_event(
        self,
        calendar: Calendar,
        event: iCalendarEvent,
        event_name: str,
        owner: User,
    ) -> Content:
        """
        Create Content event type.
        :param calendar: Event calendar owner
        :param event: ICS event
        :param event_name: Event name (ID) like
        20160602T083511Z-18100-1001-1-71_Bastien-20160602T083516Z.ics
        :param owner: Event Owner
        :return: Created Content
        """
        workspace = None
        if isinstance(calendar, WorkspaceCalendar):
            workspace = calendar.related_object
        elif isinstance(calendar, UserCalendar):
            pass
        else:
            raise UnknownCalendarType('Type "{0}" is not implemented'.format(
                type(calendar)))

        content = ContentApi(owner).create(content_type=ContentType.Event,
                                           workspace=workspace,
                                           do_save=False)
        self.populate_content_with_event(content, event, event_name)
        content.revision_type = ActionDescription.CREATION
        DBSession.add(content)
        DBSession.flush()
        transaction.commit()

        return content
Beispiel #15
0
    def _build_sibling_list_of_tree_items(self,
                                          workspace: Workspace,
                                          content: Content,
                                          children: [NodeTreeItem],
                                          select_active_node = False,
                                          allowed_content_types: list = [],
                                          ignored_item_ids: list = []) -> (Content, [NodeTreeItem]):
        api = ContentApi(tmpl_context.current_user)
        tree_items = []

        parent = content.parent if content else None

        viewable_content_types = self._get_treeviewable_content_types_or_none()
        child_contents = api.get_child_folders(parent, workspace, allowed_content_types, ignored_item_ids, viewable_content_types)
        for child in child_contents:
            children_to_add = children if child==content else []
            if child==content and select_active_node:
                # The item is the requested node, so we select it
                is_selected = True
            elif content not in child_contents and select_active_node and child==content:
                # The item is not present in the list, so we select its parent node
                is_selected = True
            else:
                is_selected = False

            new_item = NodeTreeItem(child, children_to_add, is_selected)
            tree_items.append(new_item)

        # This allow to show contents and folders group by type
        tree_items = ContentApi.sort_tree_items(tree_items)

        return parent, tree_items
Beispiel #16
0
    def get_one(self, file_id, revision_id=None):
        file_id = int(file_id)
        user = tmpl_context.current_user
        workspace = tmpl_context.workspace
        workspace_id = tmpl_context.workspace_id

        current_user_content = Context(CTX.CURRENT_USER,
                                       current_user=user).toDict(user)
        current_user_content.roles.sort(key=lambda role: role.workspace.name)

        content_api = ContentApi(user)
        if revision_id:
            file = content_api.get_one_from_revision(file_id, self._item_type,
                                                     workspace, revision_id)
        else:
            file = content_api.get_one(file_id, self._item_type, workspace)

        fake_api_breadcrumb = self.get_breadcrumb(file_id)
        fake_api_content = DictLikeClass(breadcrumb=fake_api_breadcrumb,
                                         current_user=current_user_content)
        fake_api = Context(CTX.FOLDER,
                           current_user=user).toDict(fake_api_content)

        dictified_file = Context(self._get_one_context,
                                 current_user=user).toDict(file, 'file')
        return DictLikeClass(result=dictified_file, fake_api=fake_api)
Beispiel #17
0
    def home(self):
        user = tmpl_context.current_user

        current_user_content = Context(CTX.CURRENT_USER).toDict(user)
        fake_api = Context(CTX.CURRENT_USER).toDict(
            {'current_user': current_user_content})

        last_active_contents = ContentApi(user).get_last_active(
            None, ContentType.Any, None)
        fake_api.last_actives = Context(CTX.CONTENT_LIST).toDict(
            last_active_contents, 'contents', 'nb')

        unread_contents = ContentApi(user).get_last_unread(
            None, ContentType.Any, None)
        fake_api.last_unread = Context(CTX.CONTENT_LIST).toDict(
            unread_contents, 'contents', 'nb')

        # INFO - D.A. - 2015-05-20
        # For now, we do not have favorties and read/unread status
        # so we only show:
        # - workspaces
        # - last activity
        # - oldest open stuff

        items = ContentApi(user).get_all_without_exception(
            ContentType.Any, None)[:4]
        fake_api.favorites = Context(CTX.CONTENT_LIST).toDict(
            items, 'contents', 'nb')
        return DictLikeClass(fake_api=fake_api)
Beispiel #18
0
    def test_unit__cant_get_non_access_content__ok__nominal_case(self):
        admin = DBSession.query(User)\
            .filter(User.email == '*****@*****.**').one()
        bob = DBSession.query(User)\
            .filter(User.email == '*****@*****.**').one()

        bob_workspace = WorkspaceApi(bob).create_workspace(
            'bob_workspace',
            save_now=True,
        )
        admin_workspace = WorkspaceApi(admin).create_workspace(
            'admin_workspace',
            save_now=True,
        )

        bob_page = ContentApi(bob).create(
            content_type=ContentType.Page,
            workspace=bob_workspace,
            label='bob_page',
            do_save=True,
        )

        admin_page = ContentApi(bob).create(
            content_type=ContentType.Page,
            workspace=admin_workspace,
            label='admin_page',
            do_save=True,
        )

        bob_viewable = ContentApi(bob).get_all()
        eq_(1, len(bob_viewable), 'Bob should view only one content')
        eq_(
            'bob_page',
            bob_viewable[0].label, 'Bob should not view "{0}" content'.format(
                bob_viewable[0].label, ))
Beispiel #19
0
 def __init__(self, is_case_sensitive: bool = False):
     """
     :param is_case_sensitive: If True, consider name with different
     case as different.
     """
     self._is_case_sensitive = is_case_sensitive
     self._workspace_api = UnsafeWorkspaceApi(None)
     self._content_api = ContentApi(None)
Beispiel #20
0
    def current_folder(cls) -> Content:
        content_api = ContentApi(tg.tmpl_context.current_user)
        folder_id = int(tg.request.controller_state.routing_args.get('folder_id'))
        folder = content_api.get_one(folder_id, ContentType.Folder, tg.tmpl_context.workspace)

        tg.tmpl_context.folder_id = folder_id
        tg.tmpl_context.folder = folder

        return folder
Beispiel #21
0
    def current_folder(cls) -> Content:
        content_api = ContentApi(tg.tmpl_context.current_user)
        folder_id = int(tg.request.controller_state.routing_args.get('folder_id'))
        folder = content_api.get_one(folder_id, ContentType.Folder, tg.tmpl_context.workspace)

        tg.tmpl_context.folder_id = folder_id
        tg.tmpl_context.folder = folder

        return folder
Beispiel #22
0
    def mark_all_read(self):
        '''
        Mark as read all the content that hasn't been read
        redirects the user to "/home"
        '''
        user = tg.tmpl_context.current_user
        content_api = ContentApi(user)
        content_api.mark_read__all()

        tg.redirect("/home")
Beispiel #23
0
    def _current_item_manually(cls, item_id: int, item_type: str) -> Content:
        # in case thread or page or other stuff is instanciated, then force
        # the associated item to be available through generic name tmpl_context.item to be available
        content_api = ContentApi(tg.tmpl_context.current_user)
        item = content_api.get_one(item_id, item_type, tg.tmpl_context.workspace)

        tg.tmpl_context.item_id = item.content_id
        tg.tmpl_context.item = item

        return item
Beispiel #24
0
    def _current_item_manually(cls, item_id: int, item_type: str) -> Content:
        # in case thread or page or other stuff is instanciated, then force
        # the associated item to be available through generic name tmpl_context.item to be available
        content_api = ContentApi(tg.tmpl_context.current_user)
        item = content_api.get_one(item_id, item_type, tg.tmpl_context.workspace)

        tg.tmpl_context.item_id = item.content_id
        tg.tmpl_context.item = item

        return item
Beispiel #25
0
    def treeview_root(self, id='#',
                      current_id=None,
                      all_workspaces=True,
                      folder_allowed_content_types='',
                      ignore_id=None,
                      ignore_workspace_id=None):
        all_workspaces = bool(int(all_workspaces))

        # ignore_workspace_id is a string like 3,12,78,15
        ignored_ids = [int(id) for id in ignore_workspace_id.split(',')] if ignore_workspace_id else None

        if not current_id:
            # Default case is to return list of workspaces
            api = WorkspaceApi(tmpl_context.current_user)
            workspaces = api.get_all_for_user(tmpl_context.current_user,
                                              ignored_ids)
            dictified_workspaces = Context(CTX.MENU_API).toDict(workspaces, 'd')
            return dictified_workspaces

        allowed_content_types = ContentType.allowed_types_from_str(folder_allowed_content_types)
        ignored_item_ids = [int(ignore_id)] if ignore_id else []

        # Now complex case: we must return a structured tree
        # including the selected node, all parents (and their siblings)
        workspace, content = convert_id_into_instances(current_id)

        # The following step allow to select the parent folder when content itself is not visible in the treeview
        if content and content.type!=ContentType.Folder and CFG.CST.TREEVIEW_ALL!=CFG.get_instance().WEBSITE_TREEVIEW_CONTENT:
            content = content.parent if content.parent else None

        # This is the init of the recursive-like build of the tree
        content_parent = content
        tree_items = []

        # The first step allow to load child of selected item
        # (for example, when you select a folder in the windows explorer,
        # then the selected folder is expanded by default)
        content_api = ContentApi(tmpl_context.current_user)
        child_folders = content_api.get_child_folders(content_parent, workspace, allowed_content_types, ignored_item_ids)

        if len(child_folders)>0:
            first_child = child_folders[0]
            content_parent, tree_items = self._build_sibling_list_of_tree_items(workspace, first_child, tree_items, False, allowed_content_types, ignored_item_ids)

        content_parent, tree_items = self._build_sibling_list_of_tree_items(workspace, content_parent, tree_items, True, allowed_content_types, ignored_item_ids)
        while content_parent:
            # Do the same for the parent level
            content_parent, tree_items = self._build_sibling_list_of_tree_items(workspace, content_parent, tree_items)
        # Now, we have a tree_items list that is the root folders list,
        # so we now have to put it as a child of a list of workspaces
        should_select_workspace = not content

        full_tree = self._build_sibling_list_of_workspaces(workspace, tree_items, should_select_workspace, all_workspaces)

        return Context(CTX.MENU_API_BUILD_FROM_TREE_ITEM).toDict(full_tree, 'd')
Beispiel #26
0
    def post(self, label='', content=''):
        workspace = tmpl_context.workspace

        api = ContentApi(tmpl_context.current_user)

        page = api.create(ContentType.Page, workspace, tmpl_context.folder, label)
        page.description = content
        api.save(page, ActionDescription.CREATION, do_notify=True)

        tg.flash(_('Page created'), CST.STATUS_OK)
        tg.redirect(tg.url('/workspaces/{}/folders/{}/pages/{}').format(tmpl_context.workspace_id, tmpl_context.folder_id, page.content_id))
Beispiel #27
0
    def __init__(self, path: str, environ: dict, workspace: data.Workspace):
        super(Workspace, self).__init__(path, environ)

        self.workspace = workspace
        self.content = None
        self.user = UserApi(None).get_one_by_email(
            environ['http_authenticator.username'])

        self.content_api = ContentApi(self.user, show_temporary=True)

        self._file_count = 0
Beispiel #28
0
    def getMemberList(self) -> [_DAVResource]:
        members = []
        content_api = ContentApi(self.user)
        visible_children = content_api.get_all(
            self.content.content_id,
            ContentType.Any,
            self.workspace,
        )

        for content in visible_children:
            content_path = '%s/%s' % (
                self.path, transform_to_display(content.get_label_as_file()))

            try:
                if content.type == ContentType.Folder:
                    members.append(
                        Folder(content_path, self.environ, self.workspace,
                               content))
                elif content.type == ContentType.File:
                    self._file_count += 1
                    members.append(File(content_path, self.environ, content))
                else:
                    self._file_count += 1
                    members.append(
                        OtherFile(content_path, self.environ, content))
            except Exception as exc:
                logger.exception(
                    'Unable to construct member {}'.format(content_path, ),
                    exc_info=True,
                )

        if self._file_count > 0 and self.provider.show_history():
            members.append(
                HistoryFolder(path=self.path + '/' + ".history",
                              environ=self.environ,
                              content=self.content,
                              workspace=self.workspace,
                              type=HistoryType.Standard))

        if self.provider.show_delete():
            members.append(
                DeletedFolder(path=self.path + '/' + ".deleted",
                              environ=self.environ,
                              content=self.content,
                              workspace=self.workspace))

        if self.provider.show_archive():
            members.append(
                ArchivedFolder(path=self.path + '/' + ".archived",
                               environ=self.environ,
                               content=self.content,
                               workspace=self.workspace))

        return members
Beispiel #29
0
    def mark_read(self, workspace_id, **kwargs):

        user = tmpl_context.current_user
        workspace_api = WorkspaceApi(user)
        workspace = workspace_api.get_one(workspace_id)

        content_api = ContentApi(user)
        content_api.mark_read__workspace(workspace)

        tg.redirect('/workspaces/{}'.format(workspace_id))
        return DictLikeClass(fake_api=fake_api)
Beispiel #30
0
    def test_mark_read__all(self):
        uapi = UserApi(None)
        groups = [
            GroupApi(None).get_one(Group.TIM_USER),
            GroupApi(None).get_one(Group.TIM_MANAGER),
            GroupApi(None).get_one(Group.TIM_ADMIN)
        ]
        user_a = uapi.create_user(email='this.is@user',
                                  groups=groups,
                                  save_now=True)
        user_b = uapi.create_user(email='*****@*****.**',
                                  groups=groups,
                                  save_now=True)

        wapi = WorkspaceApi(user_a)
        workspace = wapi.create_workspace('test workspace', save_now=True)

        role_api = RoleApi(user_a)
        role_api.create_one(user_b, workspace, UserRoleInWorkspace.READER,
                            False)
        cont_api_a = ContentApi(user_a)
        cont_api_b = ContentApi(user_b)

        page_2 = cont_api_a.create(ContentType.Page,
                                   workspace,
                                   None,
                                   'this is page1',
                                   do_save=True)
        page_3 = cont_api_a.create(ContentType.Thread,
                                   workspace,
                                   None,
                                   'this is page2',
                                   do_save=True)
        page_4 = cont_api_a.create(ContentType.File,
                                   workspace,
                                   None,
                                   'this is page3',
                                   do_save=True)

        for rev in page_2.revisions:
            eq_(user_b not in rev.read_by.keys(), True)
        for rev in page_3.revisions:
            eq_(user_b not in rev.read_by.keys(), True)
        for rev in page_4.revisions:
            eq_(user_b not in rev.read_by.keys(), True)

        DBSession.refresh(page_2)
        DBSession.refresh(page_3)
        DBSession.refresh(page_4)

        cont_api_b.mark_read__all()

        for rev in page_2.revisions:
            eq_(user_b in rev.read_by.keys(), True)
        for rev in page_3.revisions:
            eq_(user_b in rev.read_by.keys(), True)
        for rev in page_4.revisions:
            eq_(user_b in rev.read_by.keys(), True)
Beispiel #31
0
    def getMemberList(self) -> [_DAVResource]:
        members = []
        content_api = ContentApi(self.user)
        visible_children = content_api.get_all(
            self.content.content_id,
            ContentType.Any,
            self.workspace,
        )

        for content in visible_children:
            content_path = '%s/%s' % (self.path, transform_to_display(content.get_label_as_file()))

            if content.type == ContentType.Folder:
                members.append(Folder(content_path, self.environ, self.workspace, content))
            elif content.type == ContentType.File:
                self._file_count += 1
                members.append(File(content_path, self.environ, content))
            else:
                self._file_count += 1
                members.append(OtherFile(content_path, self.environ, content))

        if self._file_count > 0 and self.provider.show_history():
            members.append(
                HistoryFolder(
                    path=self.path + '/' + ".history",
                    environ=self.environ,
                    content=self.content,
                    workspace=self.workspace,
                    type=HistoryType.Standard
                )
            )

        if self.provider.show_delete():
            members.append(
                DeletedFolder(
                    path=self.path + '/' + ".deleted",
                    environ=self.environ,
                    content=self.content,
                    workspace=self.workspace
                )
            )

        if self.provider.show_archive():
            members.append(
                ArchivedFolder(
                    path=self.path + '/' + ".archived",
                    environ=self.environ,
                    content=self.content,
                    workspace=self.workspace
                )
            )

        return members
Beispiel #32
0
    def _create_content_and_test(self, name, workspace, *args, **kwargs) -> Content:
        """
        All extra parameters (*args, **kwargs) are for Content init
        :return: Created Content instance
        """
        content = Content(*args, **kwargs)
        content.label = name
        content.workspace = workspace
        DBSession.add(content)
        DBSession.flush()

        eq_(1, ContentApi.get_canonical_query().filter(Content.label == name).count())
        return ContentApi.get_canonical_query().filter(Content.label == name).one()
Beispiel #33
0
    def _create_content_and_test(self, name, workspace, *args, **kwargs) -> Content:
        """
        All extra parameters (*args, **kwargs) are for Content init
        :return: Created Content instance
        """
        content = Content(*args, **kwargs)
        content.label = name
        content.workspace = workspace
        DBSession.add(content)
        DBSession.flush()

        eq_(1, ContentApi.get_canonical_query().filter(Content.label == name).count())
        return ContentApi.get_canonical_query().filter(Content.label == name).one()
Beispiel #34
0
    def __init__(self,
                 path,
                 environ,
                 workspace: data.Workspace,
                 content: data.Content = None,
                 type: str = HistoryType.Standard):
        super(HistoryFolder, self).__init__(path, environ, workspace, content)

        self._is_archived = type == HistoryType.Archived
        self._is_deleted = type == HistoryType.Deleted

        self.content_api = ContentApi(current_user=self.user,
                                      show_archived=self._is_archived,
                                      show_deleted=self._is_deleted)
Beispiel #35
0
    def test_set_status_unknown_status(self):
        uapi = UserApi(None)
        groups = [GroupApi(None).get_one(Group.TIM_USER),
                  GroupApi(None).get_one(Group.TIM_MANAGER),
                  GroupApi(None).get_one(Group.TIM_ADMIN)]

        user = uapi.create_user(email='this.is@user',
                                groups=groups, save_now=True)

        workspace = WorkspaceApi(user).create_workspace('test workspace',
                                                        save_now=True)
        api = ContentApi(user)
        c = api.create(ContentType.Folder, workspace, None, 'parent', True)
        api.set_status(c, 'unknown-status')
Beispiel #36
0
    def put(self, folder_id, label, can_contain_folders=False, can_contain_threads=False, can_contain_files=False, can_contain_pages=False):
        # TODO - SECURE THIS
        workspace = tmpl_context.workspace

        api = ContentApi(tmpl_context.current_user)
        next_url = ''

        try:
            folder = api.get_one(int(folder_id), ContentType.Folder, workspace)
            subcontent = dict(
                folder = True if can_contain_folders=='on' else False,
                thread = True if can_contain_threads=='on' else False,
                file = True if can_contain_files=='on' else False,
                page = True if can_contain_pages=='on' else False
            )
            if label != folder.label:
                # TODO - D.A. - 2015-05-25 - Allow to set folder description
                api.update_content(folder, label, folder.description)
            api.set_allowed_content(folder, subcontent)
            api.save(folder)

            tg.flash(_('Folder updated'), CST.STATUS_OK)

            next_url = self.url(folder.content_id)

        except Exception as e:
            tg.flash(_('Folder not updated: {}').format(str(e)), CST.STATUS_ERROR)
            next_url = self.url(int(folder_id))

        tg.redirect(next_url)
Beispiel #37
0
    def post(self, content: str = ''):
        # TODO - SECURE THIS
        workspace = tmpl_context.workspace
        thread = tmpl_context.thread

        api = ContentApi(tmpl_context.current_user)

        comment = api.create_comment(workspace, thread, content, True)
        next_str = '/workspaces/{}/folders/{}/threads/{}'
        next_url = tg.url(next_str).format(tmpl_context.workspace_id,
                                           tmpl_context.folder_id,
                                           tmpl_context.thread_id)
        tg.flash(_('Comment added'), CST.STATUS_OK)
        tg.redirect(next_url)
Beispiel #38
0
    def test_get_all_with_parent_id(self):
        uapi = UserApi(None)
        groups = [
            GroupApi(None).get_one(Group.TIM_USER),
            GroupApi(None).get_one(Group.TIM_MANAGER),
            GroupApi(None).get_one(Group.TIM_ADMIN)
        ]

        user = uapi.create_user(email='this.is@user',
                                groups=groups,
                                save_now=True)
        workspace = WorkspaceApi(user).create_workspace('test workspace',
                                                        save_now=True)

        api = ContentApi(user)
        item = api.create(ContentType.Folder, workspace, None, 'parent', True)
        item2 = api.create(ContentType.File, workspace, item, 'file1', True)
        item3 = api.create(ContentType.File, workspace, None, 'file2', True)
        parent_id = item.content_id
        child_id = item2.content_id
        uid = user.user_id
        wid = workspace.workspace_id
        transaction.commit()

        # Refresh instances after commit
        user = uapi.get_one(uid)
        workspace = WorkspaceApi(user).get_one(wid)
        api = ContentApi(user)

        items = api.get_all(None, ContentType.Any, workspace)
        eq_(3, len(items))

        items2 = api.get_all(parent_id, ContentType.File, workspace)
        eq_(1, len(items2))
        eq_(child_id, items2[0].content_id)
Beispiel #39
0
    def get_all_fake(self, context_workspace: Workspace, context_folder: Content) -> [Content]:
        """
        fake methods are used in other controllers in order to simulate a client/server api.
        the "client" controller method will include the result into its own fake_api object
        which will be available in the templates

        :param context_workspace: the workspace which would be taken from tmpl_context if we were in the normal behavior
        :return:
        """
        workspace = context_workspace
        content_api = ContentApi(tmpl_context.current_user)
        items = content_api.get_all(context_folder.content_id, self._item_type, workspace)

        dictified_items = Context(self._get_all_context).toDict(items)
        return DictLikeClass(result = dictified_items)
Beispiel #40
0
    def post(self, label='', content=''):
        workspace = tmpl_context.workspace

        api = ContentApi(tmpl_context.current_user)

        page = api.create(ContentType.Page, workspace, tmpl_context.folder,
                          label)
        page.description = content
        api.save(page, ActionDescription.CREATION, do_notify=True)

        tg.flash(_('Page created'), CST.STATUS_OK)
        tg.redirect(
            tg.url('/workspaces/{}/folders/{}/pages/{}').format(
                tmpl_context.workspace_id, tmpl_context.folder_id,
                page.content_id))
Beispiel #41
0
    def get_all_fake(self, context_workspace: Workspace, context_folder: Content) -> [Content]:
        """
        fake methods are used in other controllers in order to simulate a client/server api.
        the "client" controller method will include the result into its own fake_api object
        which will be available in the templates

        :param context_workspace: the workspace which would be taken from tmpl_context if we were in the normal behavior
        :return:
        """
        workspace = context_workspace
        content_api = ContentApi(tmpl_context.current_user)
        items = content_api.get_all(context_folder.content_id, self._item_type, workspace)

        dictified_items = Context(self._get_all_context).toDict(items)
        return DictLikeClass(result = dictified_items)
Beispiel #42
0
    def post(self, content=''):
        # TODO - SECURE THIS
        workspace = tmpl_context.workspace
        thread = tmpl_context.thread


        api = ContentApi(tmpl_context.current_user)

        comment = api.create_comment(workspace, thread, content, True)

        next_url = tg.url('/workspaces/{}/folders/{}/threads/{}').format(tmpl_context.workspace_id,
                                                                              tmpl_context.folder_id,
                                                                              tmpl_context.thread_id)
        tg.flash(_('Comment added'), CST.STATUS_OK)
        tg.redirect(next_url)
Beispiel #43
0
    def update_event(
            self,
            calendar: Calendar,
            event: iCalendarEvent,
            event_name: str,
            current_user: User,
    ) -> Content:
        """
        Update Content Event
        :param calendar: Event calendar owner
        :param event: ICS event
        :param event_name: Event name (ID) like
        20160602T083511Z-18100-1001-1-71_Bastien-20160602T083516Z.ics
        :param current_user: Current modification asking user
        :return: Updated Content
        """
        workspace = None
        if isinstance(calendar, WorkspaceCalendar):
            workspace = calendar.related_object
        elif isinstance(calendar, UserCalendar):
            pass
        else:
            raise UnknownCalendarType('Type "{0}" is not implemented'
                                      .format(type(calendar)))

        content_api = ContentApi(
            current_user,
            force_show_all_types=True,
            disable_user_workspaces_filter=True
        )
        content = content_api.find_one_by_unique_property(
            property_name='name',
            property_value=event_name,
            workspace=workspace
        )

        with new_revision(content):
            self.populate_content_with_event(
                content,
                event,
                event_name
            )
            content.revision_type = ActionDescription.EDITION

        DBSession.flush()
        transaction.commit()

        return content
Beispiel #44
0
    def get_all_fake(self, context_workspace: Workspace, parent_id=None):
        """
        fake methods are used in other controllers in order to simulate a client/server api.
        the "client" controller method will include the result into its own fake_api object
        which will be available in the templates

        :param context_workspace: the workspace which would be taken from tmpl_context if we were in the normal behavior
        :return:
        """
        workspace = context_workspace
        content_api = ContentApi(tmpl_context.current_user)
        parent_folder = content_api.get_one(parent_id, ContentType.Folder)
        folders = content_api.get_child_folders(parent_folder, workspace)

        folders = Context(CTX.FOLDERS).toDict(folders)
        return DictLikeClass(result = folders)
Beispiel #45
0
    def get_all_fake(self, context_workspace: Workspace, parent_id=None):
        """
        fake methods are used in other controllers in order to simulate a client/server api.
        the "client" controller method will include the result into its own fake_api object
        which will be available in the templates

        :param context_workspace: the workspace which would be taken from tmpl_context if we were in the normal behavior
        :return:
        """
        workspace = context_workspace
        content_api = ContentApi(tmpl_context.current_user)
        parent_folder = content_api.get_one(parent_id, ContentType.Folder)
        folders = content_api.get_child_folders(parent_folder, workspace)

        folders = Context(CTX.FOLDERS).toDict(folders)
        return DictLikeClass(result=folders)
Beispiel #46
0
 def __init__(self, is_case_sensitive: bool=False):
     """
     :param is_case_sensitive: If True, consider name with different
     case as different.
     """
     self._is_case_sensitive = is_case_sensitive
     self._workspace_api = UnsafeWorkspaceApi(None)
     self._content_api = ContentApi(None)
Beispiel #47
0
    def get_one(self, thread_id):
        thread_id = int(thread_id)
        user = tmpl_context.current_user
        workspace = tmpl_context.workspace

        current_user_content = Context(CTX.CURRENT_USER).toDict(user)
        current_user_content.roles.sort(key=lambda role: role.workspace.name)

        content_api = ContentApi(user)
        thread = content_api.get_one(thread_id, ContentType.Thread, workspace)

        fake_api_breadcrumb = self.get_breadcrumb(thread_id)
        fake_api_content = DictLikeClass(breadcrumb=fake_api_breadcrumb, current_user=current_user_content)
        fake_api = Context(CTX.FOLDER).toDict(fake_api_content)

        dictified_thread = Context(CTX.THREAD).toDict(thread, 'thread')
        return DictLikeClass(result = dictified_thread, fake_api=fake_api)
Beispiel #48
0
    def edit(self, folder_id):
        """
        Show the edit form (do not really edit the data)

        :param item_id:
        :return:
        """

        folder_id = int(folder_id)
        user = tmpl_context.current_user
        workspace = tmpl_context.workspace

        content_api = ContentApi(user)
        folder = content_api.get_one(folder_id, ContentType.Folder, workspace)

        dictified_folder = Context(CTX.FOLDER).toDict(folder, 'folder')
        return DictLikeClass(result = dictified_folder)
Beispiel #49
0
    def put(self, item_id, folder_id='0'):
        """
        :param item_id:
        :param folder_id: id of the folder, in a style like 'workspace_14__content_1586'
        :return:
        """
        # TODO - SECURE THIS
        workspace = tmpl_context.workspace
        item_id = int(item_id)
        new_workspace, new_parent = convert_id_into_instances(folder_id)

        if new_workspace != workspace:
            # check that user is at least
            # - content manager in current workspace
            # - content manager in new workspace
            user = tmpl_context.current_user

            if user.get_role(workspace) < UserRoleInWorkspace.CONTENT_MANAGER:
                tg.flash(_('You are not allowed '
                           'to move this folder'), CST.STATUS_ERROR)
                tg.redirect(self.parent_controller.url(item_id))

            if user.get_role(new_workspace) < UserRoleInWorkspace.CONTENT_MANAGER:
                tg.flash(_('You are not allowed to move '
                           'this folder to this workspace'), CST.STATUS_ERROR)
                tg.redirect(self.parent_controller.url(item_id))

            api = ContentApi(tmpl_context.current_user)
            item = api.get_one(item_id, ContentType.Any, workspace)
            api.move_recursively(item, new_parent, new_workspace)

            next_url = tg.url('/workspaces/{}/folders/{}'.format(
                new_workspace.workspace_id, item_id))
            if new_parent:
                tg.flash(_('Item moved to {} (workspace {})').format(
                    new_parent.label,
                    new_workspace.label), CST.STATUS_OK)
            else:
                tg.flash(_('Item moved to workspace {}').format(
                    new_workspace.label))

            tg.redirect(next_url)

        else:
            # Default move inside same workspace
            api = ContentApi(tmpl_context.current_user)
            item = api.get_one(item_id, ContentType.Any, workspace)
            api.move(item, new_parent)
            next_url = self.parent_controller.url(item_id)
            if new_parent:
                tg.flash(_('Item moved to {}').format(new_parent.label), CST.STATUS_OK)
            else:
                tg.flash(_('Item moved to workspace root'))

            tg.redirect(next_url)
Beispiel #50
0
    def test_get_all_with_filter(self):
        uapi = UserApi(None)
        groups = [GroupApi(None).get_one(Group.TIM_USER),
                  GroupApi(None).get_one(Group.TIM_MANAGER),
                  GroupApi(None).get_one(Group.TIM_ADMIN)]

        user = uapi.create_user(email='this.is@user',
                                groups=groups, save_now=True)
        workspace = WorkspaceApi(user).create_workspace('test workspace',
                                                        save_now=True)

        api = ContentApi(user)
        item = api.create(ContentType.Folder, workspace, None,
                          'thefolder', True)
        item2 = api.create(ContentType.File, workspace, None, 'thefile', True)
        uid = user.user_id
        wid = workspace.workspace_id
        transaction.commit()

        # Refresh instances after commit
        user = uapi.get_one(uid)
        workspace = WorkspaceApi(user).get_one(wid)
        api = ContentApi(user)

        items = api.get_all(None, ContentType.Any, workspace)
        eq_(2, len(items))

        items2 = api.get_all(None, ContentType.File, workspace)
        eq_(1, len(items2))
        eq_('thefile', items2[0].label)

        items3 = api.get_all(None, ContentType.Folder, workspace)
        eq_(1, len(items3))
        eq_('thefolder', items3[0].label)
Beispiel #51
0
    def test_set_status_ok(self):
        uapi = UserApi(None)
        groups = [GroupApi(None).get_one(Group.TIM_USER),
                  GroupApi(None).get_one(Group.TIM_MANAGER),
                  GroupApi(None).get_one(Group.TIM_ADMIN)]

        user = uapi.create_user(email='this.is@user',
                                groups=groups, save_now=True)

        workspace = WorkspaceApi(user).create_workspace('test workspace',
                                                        save_now=True)
        api = ContentApi(user)
        c = api.create(ContentType.Folder, workspace, None, 'parent', True)
        for new_status in ['open', 'closed-validated', 'closed-unvalidated',
                           'closed-deprecated']:
            api.set_status(c, new_status)
            eq_(new_status, c.status)
            eq_(ActionDescription.STATUS_UPDATE, c.revision_type)
Beispiel #52
0
    def __init__(self, path: str, environ: dict, workspace: data.Workspace):
        super(Workspace, self).__init__(path, environ)

        self.workspace = workspace
        self.content = None
        self.user = UserApi(None).get_one_by_email(environ['http_authenticator.username'])

        self.content_api = ContentApi(self.user, show_temporary=True)

        self._file_count = 0
Beispiel #53
0
    def put_unread(self, item_id):
        item_id = int(item_id)
        content_api = ContentApi(tmpl_context.current_user, True, True) # Here we do not filter deleted items
        item = content_api.get_one(item_id, self._item_type, tmpl_context.workspace)

        item_url = self._std_url.format(item.workspace_id, item.parent_id, item.content_id)

        try:
            msg = _('{} marked unread.').format(self._item_type_label)
            content_api.mark_unread(item)

            tg.flash(msg, CST.STATUS_OK)
            tg.redirect(item_url)

        except ValueError as e:
            logger.debug(self, 'Exception: {}'.format(e.__str__))
            msg = _('{} not marked unread: {}').format(self._item_type_label, str(e))
            tg.flash(msg, CST.STATUS_ERROR)
            tg.redirect(item_url)
Beispiel #54
0
    def edit(self, item_id):
        """
        Show the edit form (do not really edit the data)

        :param item_id:
        :return:
        """
        current_user_content = Context(CTX.CURRENT_USER).toDict(tmpl_context.current_user)
        fake_api = Context(CTX.FOLDER).toDict(DictLikeClass(current_user=current_user_content))

        item_id = int(item_id)
        user = tmpl_context.current_user
        workspace = tmpl_context.workspace

        content_api = ContentApi(user)
        item = content_api.get_one(item_id, ContentType.Any, workspace)

        dictified_item = Context(CTX.DEFAULT).toDict(item, 'item')
        return DictLikeClass(result = dictified_item, fake_api=fake_api)
Beispiel #55
0
    def edit(self, item_id):
        """
        Show the edit form (do not really edit the data)

        :param item_id:
        :return:
        """

        # the follwing line allow to define the template to use in child classes.
        tg.override_template(self.edit, self.TEMPLATE_EDIT)

        item_id = int(item_id)
        user = tmpl_context.current_user
        workspace = tmpl_context.workspace

        content_api = ContentApi(user)
        item = content_api.get_one(item_id, self._item_type, workspace)

        dictified_item = Context(self._get_one_context).toDict(item, 'item')
        return DictLikeClass(result = dictified_item)
Beispiel #56
0
 def test_children(self):
     admin = DBSession.query(User).filter(User.email == '*****@*****.**').one()
     self._create_thread_and_test(
         workspace_name='workspace_1',
         folder_name='folder_1',
         thread_name='thread_1',
         user=admin
     )
     workspace = DBSession.query(Workspace).filter(Workspace.label == 'workspace_1').one()
     folder = ContentApi.get_canonical_query().filter(Content.label == 'folder_1').one()
     eq_([folder, ], list(workspace.get_valid_children()))
Beispiel #57
0
    def search(self, keywords = ''):
        from tracim.lib.content import ContentApi

        user = tmpl_context.current_user
        api = ContentApi(user)

        items = []
        keyword_list = api.get_keywords(keywords)

        result = api.search(keyword_list)
        if result:
            items = result.limit(ContentApi.SEARCH_DEFAULT_RESULT_NB).all()

        current_user_content = Context(CTX.CURRENT_USER).toDict(user)
        fake_api = Context(CTX.CURRENT_USER).toDict({'current_user': current_user_content})

        search_results = Context(CTX.SEARCH).toDict(items, 'results', 'result_nb')
        search_results.keywords = keyword_list

        return DictLikeClass(fake_api=fake_api, search=search_results)