def move_folder(self, destpath): workspace_api = WorkspaceApi( current_user=self.user, session=self.session, config=self.provider.app_config, ) workspace = self.provider.get_workspace_from_path( normpath(destpath), workspace_api ) parent = self.provider.get_parent_from_path( normpath(destpath), self.content_api, workspace ) with new_revision( content=self.content, tm=transaction.manager, session=self.session, ): if basename(destpath) != self.getDisplayName(): self.content_api.update_content(self.content, transform_to_bdd(basename(destpath))) self.content_api.save(self.content) else: if workspace.workspace_id == self.content.workspace.workspace_id: self.content_api.move(self.content, parent) else: self.content_api.move_recursively(self.content, parent, workspace) transaction.commit()
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 moveRecursive(self, destpath: str): """ 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_folder(destpath) if invalid_path: raise DAVError(HTTP_FORBIDDEN)
def moveRecursive(self, destpath: str): """ 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( ActionDescription.UNDELETION if self.content.is_deleted else ActionDescription.UNARCHIVING, self.content_api, self.content ).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( ActionDescription.DELETION if '.deleted' in destpath else ActionDescription.ARCHIVING, self.content_api, self.content ).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_folder(destpath) if invalid_path: raise DAVError(HTTP_FORBIDDEN)
def exists(self, path, environ) -> bool: """ Called by wsgidav to check if a certain path is linked to a _DAVResource """ path = normpath(path) working_path = self.reduce_path(path) root_path = environ['http_authenticator.realm'] parent_path = dirname(working_path) user = environ['tracim_user'] session = environ['tracim_dbsession'] if path == root_path: return True workspace = self.get_workspace_from_path( path, WorkspaceApi( current_user=user, session=session, config=self.app_config, ) ) if parent_path == root_path or workspace is None: return workspace is not None # TODO bastien: Arnaud avait mis a True, verif le comportement # lorsque l'on explore les dossiers archive et deleted content_api = ContentApi( current_user=user, session=session, config=self.app_config, show_archived=False, show_deleted=False ) revision_id = re.search(r'/\.history/[^/]+/\((\d+) - [a-zA-Z]+\) ([^/].+)$', path) is_archived = self.is_path_archive(path) is_deleted = self.is_path_delete(path) if revision_id: revision_id = revision_id.group(1) content = content_api.get_one_revision(revision_id) else: content = self.get_content_from_path(working_path, content_api, workspace) return content is not None \ and content.is_deleted == is_deleted \ and content.is_archived == is_archived
def move_folder(self, destpath): workspace_api = WorkspaceApi(self.user) workspace = self.provider.get_workspace_from_path( normpath(destpath), workspace_api ) parent = self.provider.get_parent_from_path( normpath(destpath), self.content_api, workspace ) with new_revision(self.content): if basename(destpath) != self.getDisplayName(): self.content_api.update_content(self.content, transform_to_bdd(basename(destpath))) self.content_api.save(self.content) else: if workspace.workspace_id == self.content.workspace.workspace_id: self.content_api.move(self.content, parent) else: self.content_api.move_recursively(self.content, parent, workspace) transaction.commit()
def exists(self, path, environ) -> bool: """ Called by wsgidav to check if a certain path is linked to a _DAVResource """ path = normpath(path) working_path = self.reduce_path(path) root_path = environ['http_authenticator.realm'] parent_path = dirname(working_path) if path == root_path: return True user = UserApi(None).get_one_by_email(environ['http_authenticator.username']) workspace = self.get_workspace_from_path(path, WorkspaceApi(user)) if parent_path == root_path or workspace is None: return workspace is not None # TODO bastien: Arnaud avait mis a True, verif le comportement # lorsque l'on explore les dossiers archive et deleted content_api = ContentApi(user, show_archived=False, show_deleted=False) revision_id = re.search(r'/\.history/[^/]+/\((\d+) - [a-zA-Z]+\) ([^/].+)$', path) is_archived = self.is_path_archive(path) is_deleted = self.is_path_delete(path) if revision_id: revision_id = revision_id.group(1) content = content_api.get_one_revision(revision_id) else: content = self.get_content_from_path(working_path, content_api, workspace) return content is not None \ and content.is_deleted == is_deleted \ and content.is_archived == is_archived
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 getResourceInst(self, path: str, environ: dict): """ Called by wsgidav whenever a request is called to get the _DAVResource corresponding to the path """ if not self.exists(path, environ): return None path = normpath(path) root_path = environ['http_authenticator.realm'] # If the requested path is the root, then we return a Root resource if path == root_path: return sql_resources.Root(path, environ) user = UserApi(None).get_one_by_email( environ['http_authenticator.username']) workspace_api = WorkspaceApi(user) workspace = self.get_workspace_from_path(path, workspace_api) # If the request path is in the form root/name, then we return a Workspace resource parent_path = dirname(path) if parent_path == root_path: if not workspace: return None return sql_resources.Workspace(path, environ, workspace) # And now we'll work on the path to establish which type or resource is requested content_api = ContentApi( user, show_archived=False, # self._show_archive, show_deleted=False, # self._show_delete ) content = self.get_content_from_path(path=path, content_api=content_api, workspace=workspace) # Easy cases : path either end with /.deleted, /.archived or /.history, then we return corresponding resources if path.endswith( SpecialFolderExtension.Archived) and self._show_archive: return sql_resources.ArchivedFolder(path, environ, workspace, content) if path.endswith(SpecialFolderExtension.Deleted) and self._show_delete: return sql_resources.DeletedFolder(path, environ, workspace, content) if path.endswith( SpecialFolderExtension.History) and self._show_history: is_deleted_folder = re.search(r'/\.deleted/\.history$', path) is not None is_archived_folder = re.search(r'/\.archived/\.history$', path) is not None type = HistoryType.Deleted if is_deleted_folder \ else HistoryType.Archived if is_archived_folder \ else HistoryType.Standard return sql_resources.HistoryFolder(path, environ, workspace, content, type) # Now that's more complicated, we're trying to find out if the path end with /.history/file_name is_history_file_folder = re.search(r'/\.history/([^/]+)$', path) is not None if is_history_file_folder and self._show_history: return sql_resources.HistoryFileFolder(path=path, environ=environ, content=content) # And here next step : is_history_file = re.search( r'/\.history/[^/]+/\((\d+) - [a-zA-Z]+\) .+', path) is not None if self._show_history and is_history_file: revision_id = re.search( r'/\.history/[^/]+/\((\d+) - [a-zA-Z]+\) ([^/].+)$', path).group(1) content_revision = content_api.get_one_revision(revision_id) content = self.get_content_from_revision(content_revision, content_api) if content.type == ContentType.File: return sql_resources.HistoryFile(path, environ, content, content_revision) else: return sql_resources.HistoryOtherFile(path, environ, content, content_revision) # And if we're still going, the client is asking for a standard Folder/File/Page/Thread so we check the type7 # and return the corresponding resource if content is None: return None if content.type == ContentType.Folder: return sql_resources.Folder(path, environ, content.workspace, content) elif content.type == ContentType.File: return sql_resources.File(path, environ, content) else: return sql_resources.OtherFile(path, environ, content)
def getResourceInst(self, path: str, environ: dict): """ Called by wsgidav whenever a request is called to get the _DAVResource corresponding to the path """ if not self.exists(path, environ): return None path = normpath(path) root_path = environ['http_authenticator.realm'] # If the requested path is the root, then we return a Root resource if path == root_path: return sql_resources.Root(path, environ) user = UserApi(None).get_one_by_email(environ['http_authenticator.username']) workspace_api = WorkspaceApi(user) workspace = self.get_workspace_from_path(path, workspace_api) # If the request path is in the form root/name, then we return a Workspace resource parent_path = dirname(path) if parent_path == root_path: if not workspace: return None return sql_resources.Workspace(path, environ, workspace) # And now we'll work on the path to establish which type or resource is requested content_api = ContentApi( user, show_archived=False, # self._show_archive, show_deleted=False, # self._show_delete ) content = self.get_content_from_path( path=path, content_api=content_api, workspace=workspace ) # Easy cases : path either end with /.deleted, /.archived or /.history, then we return corresponding resources if path.endswith(SpecialFolderExtension.Archived) and self._show_archive: return sql_resources.ArchivedFolder(path, environ, workspace, content) if path.endswith(SpecialFolderExtension.Deleted) and self._show_delete: return sql_resources.DeletedFolder(path, environ, workspace, content) if path.endswith(SpecialFolderExtension.History) and self._show_history: is_deleted_folder = re.search(r'/\.deleted/\.history$', path) is not None is_archived_folder = re.search(r'/\.archived/\.history$', path) is not None type = HistoryType.Deleted if is_deleted_folder \ else HistoryType.Archived if is_archived_folder \ else HistoryType.Standard return sql_resources.HistoryFolder(path, environ, workspace, content, type) # Now that's more complicated, we're trying to find out if the path end with /.history/file_name is_history_file_folder = re.search(r'/\.history/([^/]+)$', path) is not None if is_history_file_folder and self._show_history: return sql_resources.HistoryFileFolder( path=path, environ=environ, content=content ) # And here next step : is_history_file = re.search(r'/\.history/[^/]+/\((\d+) - [a-zA-Z]+\) .+', path) is not None if self._show_history and is_history_file: revision_id = re.search(r'/\.history/[^/]+/\((\d+) - [a-zA-Z]+\) ([^/].+)$', path).group(1) content_revision = content_api.get_one_revision(revision_id) content = self.get_content_from_revision(content_revision, content_api) if content.type == ContentType.File: return sql_resources.HistoryFile(path, environ, content, content_revision) else: return sql_resources.HistoryOtherFile(path, environ, content, content_revision) # And if we're still going, the client is asking for a standard Folder/File/Page/Thread so we check the type7 # and return the corresponding resource if content is None: return None if content.type == ContentType.Folder: return sql_resources.Folder(path, environ, content.workspace, content) elif content.type == ContentType.File: return sql_resources.File(path, environ, content) else: return sql_resources.OtherFile(path, environ, content)