Exemple #1
0
    def test_func__create_new_content_with_notification__ok__nominal_case(self):
        uapi = UserApi(
            current_user=None,
            session=self.session,
            config=self.app_config,
        )
        current_user = uapi.get_one_by_email('*****@*****.**')
        # Create new user with notification enabled on w1 workspace
        wapi = WorkspaceApi(
            current_user=current_user,
            session=self.session,
            config=self.app_config,
        )
        workspace = wapi.get_one_by_label('Recipes')
        user = uapi.get_one_by_email('*****@*****.**')
        wapi.enable_notifications(user, workspace)

        api = ContentApi(
            current_user=user,
            session=self.session,
            config=self.app_config,
        )
        item = api.create(
            ContentType.Folder,
            workspace,
            None,
            'parent',
            do_save=True,
            do_notify=False,
        )
        item2 = api.create(
            ContentType.File,
            workspace,
            item,
            'file1',
            do_save=True,
            do_notify=True,
        )
        # Send mail async from redis queue
        redis = get_redis_connection(
            self.app_config
        )
        queue = get_rq_queue(
            redis,
            'mail_sender',
        )
        worker = SimpleWorker([queue], connection=queue.connection)
        worker.work(burst=True)
        # check mail received
        response = requests.get('http://127.0.0.1:8025/api/v1/messages')
        response = response.json()
        headers = response[0]['Content']['Headers']
        assert headers['From'][0] == '"Bob i. via Tracim" <test_user_from+3@localhost>'  # nopep8
        assert headers['To'][0] == 'Global manager <*****@*****.**>'
        assert headers['Subject'][0] == '[TRACIM] [Recipes] file1 (Open)'
        assert headers['References'][0] == 'test_user_refs+22@localhost'
        assert headers['Reply-to'][0] == '"Bob i. & all members of Recipes" <test_user_reply+22@localhost>'  # nopep8
Exemple #2
0
 def create_generic_empty_content(
         self,
         context,
         request: TracimRequest,
         hapic_data=None,
 ) -> ContentInContext:
     """
     create a generic empty content
     """
     app_config = request.registry.settings['CFG']
     creation_data = hapic_data.body
     api = ContentApi(
         current_user=request.current_user,
         session=request.dbsession,
         config=app_config
     )
     parent = None
     if creation_data.parent_id:
         try:
             parent = api.get_one(content_id=creation_data.parent_id, content_type=ContentType.Any)  # nopep8
         except ContentNotFound as exc:
             raise ParentNotFound(
                 'Parent with content_id {} not found'.format(creation_data.parent_id)
             ) from exc
     content = api.create(
         label=creation_data.label,
         content_type=creation_data.content_type,
         workspace=request.current_workspace,
         parent=parent,
     )
     api.save(content, ActionDescription.CREATION)
     content = api.get_content_in_context(content)
     return content
Exemple #3
0
class WorkspaceResource(DAVCollection):
    """
    Workspace resource corresponding to tracim's workspaces.
    Direct children can only be folders, though files might come later on and are supported
    """

    def __init__(self,
                 path: str,
                 environ: dict,
                 workspace: Workspace,
                 user: User,
                 session: Session
    ) -> None:
        super(WorkspaceResource, self).__init__(path, environ)

        self.workspace = workspace
        self.content = None
        self.user = user
        self.session = session
        self.content_api = ContentApi(
            current_user=self.user,
            session=session,
            config=self.provider.app_config,
            show_temporary=True
        )

        self._file_count = 0

    def __repr__(self) -> str:
        return "<DAVCollection: Workspace (%d)>" % self.workspace.workspace_id

    def getPreferredPath(self):
        return self.path

    def getCreationDate(self) -> float:
        return mktime(self.workspace.created.timetuple())

    def getDisplayName(self) -> str:
        return self.workspace.label

    def getLastModified(self) -> float:
        return mktime(self.workspace.updated.timetuple())

    def getMemberNames(self) -> [str]:
        retlist = []

        children = self.content_api.get_all(
            parent_id=self.content.id if self.content is not None else None,
            workspace=self.workspace
        )

        for content in children:
            # the purpose is to display .history only if there's at least one content's type that has a history
            if content.type != ContentType.Folder:
                self._file_count += 1
            retlist.append(content.get_label_as_file())

        return retlist

    def getMember(self, content_label: str) -> _DAVResource:

        return self.provider.getResourceInst(
            '%s/%s' % (self.path, transform_to_display(content_label)),
            self.environ
        )

    def createEmptyResource(self, file_name: str):
        """
        [For now] we don't allow to create files right under workspaces.
        Though if we come to allow it, deleting the error's raise will make it possible.
        """
        # TODO : remove commentary here raise DAVError(HTTP_FORBIDDEN)
        if '/.deleted/' in self.path or '/.archived/' in self.path:
            raise DAVError(HTTP_FORBIDDEN)

        content = None

        # Note: To prevent bugs, check here again if resource already exist
        path = os.path.join(self.path, file_name)
        resource = self.provider.getResourceInst(path, self.environ)
        if resource:
            content = resource.content

        return FakeFileStream(
            session=self.session,
            file_name=file_name,
            content_api=self.content_api,
            workspace=self.workspace,
            content=content,
            parent=self.content,
            path=self.path + '/' + file_name
        )

    def createCollection(self, label: str) -> 'FolderResource':
        """
        Create a new folder for the current workspace. As it's not possible for the user to choose
        which types of content are allowed in this folder, we allow allow all of them.

        This method return the DAVCollection created.
        """

        if '/.deleted/' in self.path or '/.archived/' in self.path:
            raise DAVError(HTTP_FORBIDDEN)

        folder = self.content_api.create(
            content_type=ContentType.Folder,
            workspace=self.workspace,
            label=label,
            parent=self.content
        )

        subcontent = dict(
            folder=True,
            thread=True,
            file=True,
            page=True
        )

        self.content_api.set_allowed_content(folder, subcontent)
        self.content_api.save(folder)

        transaction.commit()

        return FolderResource('%s/%s' % (self.path, transform_to_display(label)),
                              self.environ,
                              content=folder,
                              session=self.session,
                              user=self.user,
                              workspace=self.workspace,
                              )

    def delete(self):
        """For now, it is not possible to delete a workspace through the webdav client."""
        raise DAVError(HTTP_FORBIDDEN)

    def supportRecursiveMove(self, destpath):
        return True

    def moveRecursive(self, destpath):
        if dirname(normpath(destpath)) == self.environ['http_authenticator.realm']:
            self.workspace.label = basename(normpath(destpath))
            transaction.commit()
        else:
            raise DAVError(HTTP_FORBIDDEN)

    def getMemberList(self) -> [_DAVResource]:
        members = []

        children = self.content_api.get_all(False, ContentType.Any, self.workspace)

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

            if content.type == ContentType.Folder:
                members.append(
                    FolderResource(
                        path=content_path,
                        environ=self.environ,
                        workspace=self.workspace,
                        user=self.user,
                        content=content,
                        session=self.session,
                    )
                )
            elif content.type == ContentType.File:
                self._file_count += 1
                members.append(
                    FileResource(
                        path=content_path,
                        environ=self.environ,
                        content=content,
                        user=self.user,
                        session=self.session,
                    )
                )
            else:
                self._file_count += 1
                members.append(
                    OtherFileResource(
                        content_path,
                        self.environ,
                        content,
                        session=self.session,
                        user=self.user,
                    ))

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

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

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

        return members
Exemple #4
0
    def insert(self):
        admin = self._session.query(models.User) \
            .filter(models.User.email == '*****@*****.**') \
            .one()
        bob = self._session.query(models.User) \
            .filter(models.User.email == '*****@*****.**') \
            .one()
        admin_workspace_api = WorkspaceApi(
            current_user=admin,
            session=self._session,
        )
        bob_workspace_api = WorkspaceApi(
            current_user=bob,
            session=self._session,
        )
        content_api = ContentApi(
            current_user=admin,
            session=self._session,
        )
        role_api = RoleApi(
            current_user=admin,
            session=self._session,
        )

        # Workspaces
        w1 = admin_workspace_api.create_workspace('w1', save_now=True)
        w2 = bob_workspace_api.create_workspace('w2', save_now=True)
        w3 = admin_workspace_api.create_workspace('w3', save_now=True)

        # Workspaces roles
        role_api.create_one(
            user=bob,
            workspace=w1,
            role_level=UserRoleInWorkspace.CONTENT_MANAGER,
            with_notif=False,
        )

        # Folders
        w1f1 = content_api.create(
            content_type=ContentType.Folder,
            workspace=w1,
            label='w1f1',
            do_save=True,
        )
        w1f2 = content_api.create(
            content_type=ContentType.Folder,
            workspace=w1,
            label='w1f2',
            do_save=True,
        )

        w2f1 = content_api.create(
            content_type=ContentType.Folder,
            workspace=w2,
            label='w2f1',
            do_save=True,
        )
        w2f2 = content_api.create(
            content_type=ContentType.Folder,
            workspace=w2,
            label='w2f2',
            do_save=True,
        )

        w3f1 = content_api.create(
            content_type=ContentType.Folder,
            workspace=w3,
            label='w3f3',
            do_save=True,
        )

        # Pages, threads, ..
        w1f1p1 = content_api.create(
            content_type=ContentType.Page,
            workspace=w1,
            parent=w1f1,
            label='w1f1p1',
            do_save=True,
        )
        w1f1t1 = content_api.create(
            content_type=ContentType.Thread,
            workspace=w1,
            parent=w1f1,
            label='w1f1t1',
            do_save=False,
        )
        w1f1t1.description = 'w1f1t1 description'
        self._session.add(w1f1t1)
        w1f1d1_txt = content_api.create(
            content_type=ContentType.File,
            workspace=w1,
            parent=w1f1,
            label='w1f1d1',
            do_save=False,
        )
        w1f1d1_txt.file_extension = '.txt'
        w1f1d1_txt.depot_file = FileIntent(
            b'w1f1d1 content',
            'w1f1d1.txt',
            'text/plain',
        )
        self._session.add(w1f1d1_txt)
        w1f1d2_html = content_api.create(
            content_type=ContentType.File,
            workspace=w1,
            parent=w1f1,
            label='w1f1d2',
            do_save=False,
        )
        w1f1d2_html.file_extension = '.html'
        w1f1d2_html.depot_file = FileIntent(
            b'<p>w1f1d2 content</p>',
            'w1f1d2.html',
            'text/html',
        )
        self._session.add(w1f1d2_html)
        w1f1f1 = content_api.create(
            content_type=ContentType.Folder,
            workspace=w1,
            label='w1f1f1',
            parent=w1f1,
            do_save=True,
        )

        w2f1p1 = content_api.create(
            content_type=ContentType.Page,
            workspace=w2,
            parent=w2f1,
            label='w2f1p1',
            do_save=True,
        )
        self._session.flush()
Exemple #5
0
    def insert(self):
        admin = self._session.query(models.User) \
            .filter(models.User.email == '*****@*****.**') \
            .one()
        bob = self._session.query(models.User) \
            .filter(models.User.email == '*****@*****.**') \
            .one()
        john_the_reader = self._session.query(models.User) \
            .filter(models.User.email == '*****@*****.**') \
            .one()

        admin_workspace_api = WorkspaceApi(
            current_user=admin,
            session=self._session,
            config=self._config,
        )
        bob_workspace_api = WorkspaceApi(current_user=bob,
                                         session=self._session,
                                         config=self._config)
        content_api = ContentApi(current_user=admin,
                                 session=self._session,
                                 config=self._config)
        bob_content_api = ContentApi(current_user=bob,
                                     session=self._session,
                                     config=self._config)
        reader_content_api = ContentApi(current_user=john_the_reader,
                                        session=self._session,
                                        config=self._config)
        role_api = RoleApi(
            current_user=admin,
            session=self._session,
            config=self._config,
        )

        # Workspaces
        business_workspace = admin_workspace_api.create_workspace(
            'Business',
            description='All importants documents',
            save_now=True,
        )
        recipe_workspace = admin_workspace_api.create_workspace(
            'Recipes',
            description='Our best recipes',
            save_now=True,
        )
        other_workspace = bob_workspace_api.create_workspace(
            'Others',
            description='Other Workspace',
            save_now=True,
        )

        # Workspaces roles
        role_api.create_one(
            user=bob,
            workspace=recipe_workspace,
            role_level=UserRoleInWorkspace.CONTENT_MANAGER,
            with_notif=False,
        )
        role_api.create_one(
            user=john_the_reader,
            workspace=recipe_workspace,
            role_level=UserRoleInWorkspace.READER,
            with_notif=False,
        )
        # Folders

        tool_workspace = content_api.create(
            content_type=ContentType.Folder,
            workspace=business_workspace,
            label='Tools',
            do_save=True,
            do_notify=False,
        )
        menu_workspace = content_api.create(
            content_type=ContentType.Folder,
            workspace=business_workspace,
            label='Menus',
            do_save=True,
            do_notify=False,
        )

        dessert_folder = content_api.create(
            content_type=ContentType.Folder,
            workspace=recipe_workspace,
            label='Desserts',
            do_save=True,
            do_notify=False,
        )
        salads_folder = content_api.create(
            content_type=ContentType.Folder,
            workspace=recipe_workspace,
            label='Salads',
            do_save=True,
            do_notify=False,
        )
        other_folder = content_api.create(
            content_type=ContentType.Folder,
            workspace=other_workspace,
            label='Infos',
            do_save=True,
            do_notify=False,
        )

        # Pages, threads, ..
        tiramisu_page = content_api.create(
            content_type=ContentType.Page,
            workspace=recipe_workspace,
            parent=dessert_folder,
            label='Tiramisu Recipes!!!',
            do_save=True,
            do_notify=False,
        )
        with new_revision(
                session=self._session,
                tm=transaction.manager,
                content=tiramisu_page,
        ):
            content_api.update_content(
                item=tiramisu_page,
                new_content=
                '<p>To cook a greet Tiramisu, you need many ingredients.</p>',  # nopep8
                new_label='Tiramisu Recipes!!!',
            )
            content_api.save(tiramisu_page)

        best_cake_thread = content_api.create(
            content_type=ContentType.Thread,
            workspace=recipe_workspace,
            parent=dessert_folder,
            label='Best Cake',
            do_save=False,
            do_notify=False,
        )
        best_cake_thread.description = 'Which is the best cake?'
        self._session.add(best_cake_thread)
        apple_pie_recipe = content_api.create(
            content_type=ContentType.File,
            workspace=recipe_workspace,
            parent=dessert_folder,
            label='Apple_Pie',
            do_save=False,
            do_notify=False,
        )
        apple_pie_recipe.file_extension = '.txt'
        apple_pie_recipe.depot_file = FileIntent(
            b'Apple pie Recipe',
            'apple_Pie.txt',
            'text/plain',
        )
        self._session.add(apple_pie_recipe)
        Brownie_recipe = content_api.create(
            content_type=ContentType.File,
            workspace=recipe_workspace,
            parent=dessert_folder,
            label='Brownie Recipe',
            do_save=False,
            do_notify=False,
        )
        Brownie_recipe.file_extension = '.html'
        Brownie_recipe.depot_file = FileIntent(
            b'<p>Brownie Recipe</p>',
            'brownie_recipe.html',
            'text/html',
        )
        self._session.add(Brownie_recipe)
        fruits_desserts_folder = content_api.create(
            content_type=ContentType.Folder,
            workspace=recipe_workspace,
            label='Fruits Desserts',
            parent=dessert_folder,
            do_save=True,
        )

        menu_page = content_api.create(
            content_type=ContentType.Page,
            workspace=business_workspace,
            parent=menu_workspace,
            label='Current Menu',
            do_save=True,
        )

        new_fruit_salad = content_api.create(
            content_type=ContentType.Page,
            workspace=recipe_workspace,
            parent=fruits_desserts_folder,
            label='New Fruit Salad',
            do_save=True,
        )
        old_fruit_salad = content_api.create(
            content_type=ContentType.Page,
            workspace=recipe_workspace,
            parent=fruits_desserts_folder,
            label='Fruit Salad',
            do_save=True,
            do_notify=False,
        )
        with new_revision(
                session=self._session,
                tm=transaction.manager,
                content=old_fruit_salad,
        ):
            content_api.archive(old_fruit_salad)
        content_api.save(old_fruit_salad)

        bad_fruit_salad = content_api.create(
            content_type=ContentType.Page,
            workspace=recipe_workspace,
            parent=fruits_desserts_folder,
            label='Bad Fruit Salad',
            do_save=True,
            do_notify=False,
        )
        with new_revision(
                session=self._session,
                tm=transaction.manager,
                content=bad_fruit_salad,
        ):
            content_api.delete(bad_fruit_salad)
        content_api.save(bad_fruit_salad)

        # File at the root for test
        new_fruit_salad = content_api.create(
            content_type=ContentType.Page,
            workspace=other_workspace,
            label='New Fruit Salad',
            do_save=True,
        )
        old_fruit_salad = content_api.create(
            content_type=ContentType.Page,
            workspace=other_workspace,
            label='Fruit Salad',
            do_save=True,
        )
        with new_revision(
                session=self._session,
                tm=transaction.manager,
                content=old_fruit_salad,
        ):
            content_api.archive(old_fruit_salad)
        content_api.save(old_fruit_salad)

        bad_fruit_salad = content_api.create(
            content_type=ContentType.Page,
            workspace=other_workspace,
            label='Bad Fruit Salad',
            do_save=True,
        )
        with new_revision(
                session=self._session,
                tm=transaction.manager,
                content=bad_fruit_salad,
        ):
            content_api.delete(bad_fruit_salad)
        content_api.save(bad_fruit_salad)

        content_api.create_comment(
            parent=best_cake_thread,
            content=
            '<p>What is for you the best cake ever? </br> I personnally vote for Chocolate cupcake!</p>',  # nopep8
            do_save=True,
        )
        bob_content_api.create_comment(
            parent=best_cake_thread,
            content='<p>What about Apple Pie? There are Awesome!</p>',
            do_save=True,
        )
        reader_content_api.create_comment(
            parent=best_cake_thread,
            content=
            '<p>You are right, but Kouign-amann are clearly better.</p>',
            do_save=True,
        )
        with new_revision(
                session=self._session,
                tm=transaction.manager,
                content=best_cake_thread,
        ):
            bob_content_api.update_content(
                item=best_cake_thread,
                new_content='What is the best cake?',
                new_label='Best Cakes?',
            )
            bob_content_api.save(best_cake_thread)

        with new_revision(
                session=self._session,
                tm=transaction.manager,
                content=tiramisu_page,
        ):
            bob_content_api.update_content(
                item=tiramisu_page,
                new_content=
                '<p>To cook a great Tiramisu, you need many ingredients.</p>',  # nopep8
                new_label='Tiramisu Recipe',
            )
            bob_content_api.save(tiramisu_page)
        self._session.flush()