def update_file_info(self,
                      context,
                      request: TracimRequest,
                      hapic_data=None) -> ContentInContext:  # nopep8
     """
     update thread
     """
     app_config = request.registry.settings['CFG']
     api = ContentApi(
         current_user=request.current_user,
         session=request.dbsession,
         config=app_config,
     )
     content = api.get_one(hapic_data.path.content_id,
                           content_type=ContentType.Any)
     with new_revision(session=request.dbsession,
                       tm=transaction.manager,
                       content=content):
         api.update_content(
             item=content,
             new_label=hapic_data.body.label,
             new_content=hapic_data.body.raw_content,
         )
         api.save(content)
     return api.get_content_in_context(content)
Exemple #2
0
class FileResource(DAVNonCollection):
    """
    FileResource resource corresponding to tracim's files
    """
    def __init__(
            self,
            path: str,
            environ: dict,
            content: Content,
            user: User,
            session: Session,
    ) -> None:
        super(FileResource, self).__init__(path, environ)

        self.content = content
        self.user = user
        self.session = session
        self.content_api = ContentApi(
            current_user=self.user,
            config=self.provider.app_config,
            session=self.session,
        )

        # this is the property that windows client except to check if the file is read-write or read-only,
        # but i wasn't able to set this property so you'll have to look into it >.>
        # self.setPropertyValue('Win32FileAttributes', '00000021')

    def __repr__(self) -> str:
        return "<DAVNonCollection: FileResource (%d)>" % self.content.revision_id

    def getContentLength(self) -> int:
        return self.content.depot_file.file.content_length

    def getContentType(self) -> str:
        return self.content.file_mimetype

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

    def getDisplayName(self) -> str:
        return self.content.file_name

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

    def getContent(self) -> typing.BinaryIO:
        filestream = compat.BytesIO()
        filestream.write(self.content.depot_file.file.read())
        filestream.seek(0)

        return filestream

    def beginWrite(self, contentType: str=None) -> FakeFileStream:
        return FakeFileStream(
            content=self.content,
            content_api=self.content_api,
            file_name=self.content.get_label_as_file(),
            workspace=self.content.workspace,
            path=self.path,
            session=self.session,
        )

    def moveRecursive(self, destpath):
        """As we support recursive move, copymovesingle won't be called, though with copy it'll be called
            but i have to check if the client ever call that function..."""
        destpath = normpath(destpath)

        invalid_path = False

        # if content is either deleted or archived, we'll check that we try moving it to the parent
        # if yes, then we'll unarchive / undelete them, else the action's not allowed
        if self.content.is_deleted or self.content.is_archived:
            # we remove all archived and deleted from the path and we check to the destpath
            # has to be equal or else path not valid
            # ex: /a/b/.deleted/resource, to be valid destpath has to be = /a/b/resource (no other solution)
            current_path = re.sub(r'/\.(deleted|archived)', '', self.path)

            if current_path == destpath:
                ManageActions(
                    action_type=ActionDescription.UNDELETION if self.content.is_deleted else ActionDescription.UNARCHIVING,
                    api=self.content_api,
                    content=self.content,
                    session=self.session,
                ).action()
            else:
                invalid_path = True
        # if the content is not deleted / archived, check if we're trying to delete / archive it by
        # moving it to a .deleted / .archived folder
        elif basename(dirname(destpath)) in ['.deleted', '.archived']:
            # same test as above ^
            dest_path = re.sub(r'/\.(deleted|archived)', '', destpath)

            if dest_path == self.path:
                ManageActions(
                    action_type=ActionDescription.DELETION if '.deleted' in destpath else ActionDescription.ARCHIVING,
                    api=self.content_api,
                    content=self.content,
                    session=self.session,
                ).action()
            else:
                invalid_path = True
        # else we check if the path is good (not at the root path / not in a deleted/archived path)
        # and we move the content
        else:
            invalid_path = any(x in destpath for x in ['.deleted', '.archived'])
            invalid_path = invalid_path or any(x in self.path for x in ['.deleted', '.archived'])
            invalid_path = invalid_path or dirname(destpath) == self.environ['http_authenticator.realm']

            if not invalid_path:
                self.move_file(destpath)

        if invalid_path:
            raise DAVError(HTTP_FORBIDDEN)

    def move_file(self, destpath: str) -> None:
        """
        Move file mean changing the path to access to a file. This can mean
        simple renaming(1), moving file from a directory to one another(2)
        but also renaming + moving file from a directory to one another at
        the same time (3).

        (1): move /dir1/file1 -> /dir1/file2
        (2): move /dir1/file1 -> /dir2/file1
        (3): move /dir1/file1 -> /dir2/file2
        :param destpath: destination path of webdav move
        :return: nothing
        """

        workspace = self.content.workspace
        parent = self.content.parent

        with new_revision(
            content=self.content,
            tm=transaction.manager,
            session=self.session,
        ):
            # INFO - G.M - 2018-03-09 - First, renaming file if needed
            if basename(destpath) != self.getDisplayName():
                new_given_file_name = transform_to_bdd(basename(destpath))
                new_file_name, new_file_extension = \
                    os.path.splitext(new_given_file_name)

                self.content_api.update_content(
                    self.content,
                    new_file_name,
                )
                self.content.file_extension = new_file_extension
                self.content_api.save(self.content)

            # INFO - G.M - 2018-03-09 - Moving file if needed
            workspace_api = WorkspaceApi(
                current_user=self.user,
                session=self.session,
                config=self.provider.app_config,
                )
            content_api = ContentApi(
                current_user=self.user,
                session=self.session,
                config=self.provider.app_config
            )

            destination_workspace = self.provider.get_workspace_from_path(
                destpath,
                workspace_api,
            )
            destination_parent = self.provider.get_parent_from_path(
                destpath,
                content_api,
                destination_workspace,
            )
            if destination_parent != parent or destination_workspace != workspace:  # nopep8
                #  INFO - G.M - 12-03-2018 - Avoid moving the file "at the same place"  # nopep8
                #  if the request does not result in a real move.
                self.content_api.move(
                    item=self.content,
                    new_parent=destination_parent,
                    must_stay_in_same_workspace=False,
                    new_workspace=destination_workspace
                )

        transaction.commit()

    def copyMoveSingle(self, destpath, isMove):
        if isMove:
            # INFO - G.M - 12-03-2018 - This case should not happen
            # As far as moveRecursive method exist, all move should not go
            # through this method. If such case appear, try replace this to :
            ####
            # self.move_file(destpath)
            # return
            ####

            raise NotImplemented

        new_file_name = None
        new_file_extension = None

        # Inspect destpath
        if basename(destpath) != self.getDisplayName():
            new_given_file_name = transform_to_bdd(basename(destpath))
            new_file_name, new_file_extension = \
                os.path.splitext(new_given_file_name)

        workspace_api = WorkspaceApi(
            current_user=self.user,
            session=self.session,
            config=self.provider.app_config,
        )
        content_api = ContentApi(
            current_user=self.user,
            session=self.session,
            config=self.provider.app_config
        )
        destination_workspace = self.provider.get_workspace_from_path(
            destpath,
            workspace_api,
        )
        destination_parent = self.provider.get_parent_from_path(
            destpath,
            content_api,
            destination_workspace,
        )
        workspace = self.content.workspace
        parent = self.content.parent
        new_content = self.content_api.copy(
            item=self.content,
            new_label=new_file_name,
            new_parent=destination_parent,
        )
        self.content_api.copy_children(self.content, new_content)
        transaction.commit()

    def supportRecursiveMove(self, destPath):
        return True

    def delete(self):
        ManageActions(
            action_type=ActionDescription.DELETION,
            api=self.content_api,
            content=self.content,
            session=self.session,
        ).action()
Exemple #3
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()