def delete_content( self, context, request: TracimRequest, hapic_data=None, ) -> None: """ Move a content to the trash. After that, the content will be invisible by default. This action requires the user to be a content manager. Note: the content is still accessible but becomes read-only. """ app_config = request.registry.settings['CFG'] path_data = hapic_data.path api = ContentApi( show_archived=True, show_deleted=True, current_user=request.current_user, session=request.dbsession, config=app_config, ) content = api.get_one(path_data.content_id, content_type=content_type_list.Any_SLUG) with new_revision(session=request.dbsession, tm=transaction.manager, content=content): api.delete(content) return
def delete_comment(self, context, request: TracimRequest, hapic_data=None): """ Delete comment """ app_config = request.registry.settings['CFG'] api = ContentApi( show_archived=True, show_deleted=True, current_user=request.current_user, session=request.dbsession, config=app_config, ) wapi = WorkspaceApi( current_user=request.current_user, session=request.dbsession, config=app_config, ) workspace = wapi.get_one(hapic_data.path.workspace_id) parent = api.get_one(hapic_data.path.content_id, content_type=content_type_list.Any_SLUG, workspace=workspace) comment = api.get_one( hapic_data.path.comment_id, content_type=content_type_list.Comment.slug, workspace=workspace, parent=parent, ) with new_revision(session=request.dbsession, tm=transaction.manager, content=comment): api.delete(comment) return
def delete_content( self, context, request: TracimRequest, hapic_data=None, ) -> None: """ Move a content to the trash. After that, the content will be invisible by default. This action requires the user to be a content manager. Note: the content is still accessible but becomes read-only. """ app_config = request.registry.settings['CFG'] path_data = hapic_data.path api = ContentApi( show_archived=True, show_deleted=True, current_user=request.current_user, session=request.dbsession, config=app_config, ) content = api.get_one( path_data.content_id, content_type=content_type_list.Any_SLUG ) with new_revision( session=request.dbsession, tm=transaction.manager, content=content ): api.delete(content) return
def delete_comment(self, context, request: TracimRequest, hapic_data=None): """ Delete comment """ app_config = request.registry.settings['CFG'] api = ContentApi( show_archived=True, show_deleted=True, current_user=request.current_user, session=request.dbsession, config=app_config, ) wapi = WorkspaceApi( current_user=request.current_user, session=request.dbsession, config=app_config, ) workspace = wapi.get_one(hapic_data.path.workspace_id) parent = api.get_one( hapic_data.path.content_id, content_type=content_type_list.Any_SLUG, workspace=workspace ) comment = api.get_one( hapic_data.path.comment_id, content_type=content_type_list.Comment.slug, workspace=workspace, parent=parent, ) with new_revision( session=request.dbsession, tm=transaction.manager, content=comment ): api.delete(comment) return
def insert(self): admin = self._session.query(User) \ .filter(User.email == '*****@*****.**') \ .one() bob = self._session.query(User) \ .filter(User.email == '*****@*****.**') \ .one() john_the_reader = self._session.query(User) \ .filter(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_slug=content_type_list.Folder.slug, workspace=business_workspace, label='Tools', do_save=True, do_notify=False, ) menu_workspace = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=business_workspace, label='Menus', do_save=True, do_notify=False, ) dessert_folder = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=recipe_workspace, label='Desserts', do_save=True, do_notify=False, ) salads_folder = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=recipe_workspace, label='Salads', do_save=True, do_notify=False, ) other_folder = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=other_workspace, label='Infos', do_save=True, do_notify=False, ) # Pages, threads, .. tiramisu_page = content_api.create( content_type_slug=content_type_list.Page.slug, 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_slug=content_type_list.Thread.slug, 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_slug=content_type_list.File.slug, 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_slug=content_type_list.File.slug, 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_slug=content_type_list.Folder.slug, workspace=recipe_workspace, label='Fruits Desserts', parent=dessert_folder, do_save=True, ) menu_page = content_api.create( content_type_slug=content_type_list.Page.slug, workspace=business_workspace, parent=menu_workspace, label='Current Menu', do_save=True, ) new_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, workspace=recipe_workspace, parent=fruits_desserts_folder, label='New Fruit Salad', do_save=True, ) old_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, 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_slug=content_type_list.Page.slug, 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_slug=content_type_list.Page.slug, workspace=other_workspace, label='New Fruit Salad', do_save=True, ) old_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, 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_slug=content_type_list.Page.slug, 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()
class FileResource(DAVNonCollection): """ FileResource resource corresponding to tracim's files """ def __init__(self, path: str, environ: dict, content: Content, tracim_context: "WebdavTracimContext") -> None: super(FileResource, self).__init__(path, environ) self.tracim_context = tracim_context self.content = content self.user = tracim_context.current_user self.session = tracim_context.dbsession self.content_api = ContentApi( current_user=self.user, config=tracim_context.app_config, session=self.session, namespaces_filter=[self.content.content_namespace], ) # 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.cached_revision_id @webdav_check_right(is_reader) def getContentLength(self) -> int: return self.content.depot_file.file.content_length @webdav_check_right(is_reader) def getContentType(self) -> str: return self.content.file_mimetype @webdav_check_right(is_reader) def getCreationDate(self) -> float: return mktime(self.content.created.timetuple()) @webdav_check_right(is_reader) def getDisplayName(self) -> str: return webdav_convert_file_name_to_display(self.content.file_name) @webdav_check_right(is_reader) def getDisplayInfo(self): return {"type": self.content.type.capitalize()} def getLastModified(self) -> float: return mktime(self.content.updated.timetuple()) @webdav_check_right(is_reader) def getContent(self) -> typing.BinaryIO: return self.content.depot_file.file @webdav_check_right(is_contributor) def beginWrite(self, contentType: str = None) -> FakeFileStream: try: self.content_api.check_upload_size( int(self.environ["CONTENT_LENGTH"]), self.content.workspace) except ( FileSizeOverMaxLimitation, FileSizeOverWorkspaceEmptySpace, FileSizeOverOwnerEmptySpace, ) as exc: raise DAVError(HTTP_REQUEST_ENTITY_TOO_LARGE, contextinfo=str(exc)) return FakeFileStream( content=self.content, content_api=self.content_api, file_name=self.content.file_name, 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) self.tracim_context.set_destpath(destpath) if normpath(dirname(destpath)) == normpath(dirname(self.path)): # INFO - G.M - 2018-12-12 - renaming case checker = is_contributor else: # INFO - G.M - 2018-12-12 - move case checker = can_move_content try: checker.check(self.tracim_context) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) invalid_path = False invalid_path = 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 destpath = normpath(destpath) self.tracim_context.set_destpath(destpath) if normpath(dirname(destpath)) == normpath(dirname(self.path)): # INFO - G.M - 2018-12-12 - renaming case checker = is_contributor else: # INFO - G.M - 2018-12-12 - move case checker = can_move_content try: checker.check(self.tracim_context) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) try: 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_filename = webdav_convert_file_name_to_bdd( basename(destpath)) regex_file_extension = re.compile("(?P<label>.*){}".format( re.escape(self.content.file_extension))) same_extension = regex_file_extension.match(new_filename) if same_extension: new_label = same_extension.group("label") new_file_extension = self.content.file_extension else: new_label, new_file_extension = os.path.splitext( new_filename) self.content_api.update_content(self.content, new_label=new_label) self.content.file_extension = new_file_extension self.content_api.save(self.content) # INFO - G.M - 2018-03-09 - Moving file if needed destination_workspace = self.tracim_context.candidate_workspace try: destination_parent = self.tracim_context.candidate_parent_content except ContentNotFound: destination_parent = None if destination_parent != parent or destination_workspace != workspace: # INFO - G.M - 12-03-2018 - Avoid moving the file "at the same place" # 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, ) self.content_api.execute_update_content_actions(self.content) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) from exc 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 NotImplementedError("Feature not available") destpath = normpath(destpath) self.tracim_context.set_destpath(destpath) try: can_move_content.check(self.tracim_context) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) content_in_context = self.content_api.get_content_in_context( self.content) try: self.content_api.check_upload_size(content_in_context.size or 0, self.content.workspace) except ( FileSizeOverMaxLimitation, FileSizeOverWorkspaceEmptySpace, FileSizeOverOwnerEmptySpace, ) as exc: raise DAVError(HTTP_REQUEST_ENTITY_TOO_LARGE, contextinfo=str(exc)) new_filename = webdav_convert_file_name_to_bdd(basename(destpath)) regex_file_extension = re.compile("(?P<label>.*){}".format( re.escape(self.content.file_extension))) same_extension = regex_file_extension.match(new_filename) if same_extension: new_label = same_extension.group("label") new_file_extension = self.content.file_extension else: new_label, new_file_extension = os.path.splitext(new_filename) self.tracim_context.set_destpath(destpath) destination_workspace = self.tracim_context.candidate_workspace try: destination_parent = self.tracim_context.candidate_parent_content except ContentNotFound: destination_parent = None try: new_content = self.content_api.copy( item=self.content, new_label=new_label, new_file_extension=new_file_extension, new_parent=destination_parent, new_workspace=destination_workspace, ) self.content_api.execute_created_content_actions(new_content) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) from exc transaction.commit() def supportRecursiveMove(self, destpath): return True @webdav_check_right(is_content_manager) def delete(self): try: with new_revision(session=self.session, tm=transaction.manager, content=self.content): self.content_api.delete(self.content) self.content_api.execute_update_content_actions(self.content) self.content_api.save(self.content) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) from exc transaction.commit()
class FolderResource(DAVCollection): """ FolderResource resource corresponding to tracim's folders. Direct children can only be content (folder, html-document, file, etc...) By default when creating new folders, we allow them to contain all types of content """ def __init__( self, path: str, environ: dict, workspace: Workspace, content: Content, tracim_context: "WebdavTracimContext", ): DAVCollection.__init__(self, path, environ) self.content_container = ContentOnlyContainer( path, environ, provider=self.provider, content=content, label=workspace.filemanager_filename, workspace=workspace, tracim_context=tracim_context, ) self.tracim_context = tracim_context self.content_api = ContentApi( current_user=tracim_context.current_user, session=tracim_context.dbsession, config=tracim_context.app_config, show_temporary=True, namespaces_filter=[ContentNamespaces.CONTENT], ) self.content = content self.session = tracim_context.dbsession def __repr__(self) -> str: return "<DAVCollection: Folder (%s)>" % self.content.label @webdav_check_right(is_reader) def getCreationDate(self) -> float: return mktime(self.content.created.timetuple()) @webdav_check_right(is_reader) def getDisplayName(self) -> str: return webdav_convert_file_name_to_display(self.content.file_name) @webdav_check_right(is_reader) def getDisplayInfo(self): return {"type": self.content.type.capitalize()} def getLastModified(self) -> float: return mktime(self.content.updated.timetuple()) @webdav_check_right(is_content_manager) def delete(self): try: with new_revision(session=self.session, tm=transaction.manager, content=self.content): self.content_api.delete(self.content) self.content_api.execute_update_content_actions(self.content) self.content_api.save(self.content) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) from exc transaction.commit() def supportRecursiveMove(self, destpath: str): return True 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) self.tracim_context.set_destpath(destpath) if normpath(dirname(destpath)) == normpath(dirname(self.path)): # INFO - G.M - 2018-12-12 - renaming case checker = is_contributor else: # INFO - G.M - 2018-12-12 - move case checker = can_move_content try: checker.check(self.tracim_context) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) # we check if the path is good (not at the root path /) # and we move the content invalid_path = dirname( destpath) == self.environ["http_authenticator.realm"] if not invalid_path: self.move_folder(destpath) if invalid_path: raise DAVError(HTTP_FORBIDDEN) def move_folder(self, destpath: str): destpath = normpath(destpath) self.tracim_context.set_destpath(destpath) if normpath(dirname(destpath)) == normpath(dirname(self.path)): # INFO - G.M - 2018-12-12 - renaming case checker = is_contributor else: # INFO - G.M - 2018-12-12 - move case checker = can_move_content try: checker.check(self.tracim_context) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) destination_workspace = self.tracim_context.candidate_workspace try: destination_parent = self.tracim_context.candidate_parent_content except ContentNotFound: destination_parent = None try: with new_revision(content=self.content, tm=transaction.manager, session=self.session): # renaming file if needed if basename(destpath) != self.getDisplayName(): self.content_api.update_content( self.content, webdav_convert_file_name_to_bdd(basename(destpath))) self.content_api.save(self.content) # move file if needed if (destination_workspace != self.content.workspace or destination_parent != self.content.parent): self.content_api.move( self.content, new_parent=destination_parent, new_workspace=destination_workspace, must_stay_in_same_workspace=False, ) self.content_api.execute_update_content_actions(self.content) except TracimException as exc: raise DAVError(HTTP_FORBIDDEN, contextinfo=str(exc)) from exc transaction.commit() @webdav_check_right(is_contributor) def createEmptyResource(self, file_name: str): return self.content_container.createEmptyResource(file_name=file_name) @webdav_check_right(is_content_manager) def createCollection(self, label: str) -> "FolderResource": return self.content_container.createCollection(label=label) def getMemberNames(self) -> [str]: return self.content_container.getMemberNames() def getMember(self, label: str) -> _DAVResource: return self.content_container.getMember(label=label) def getMemberList(self) -> [_DAVResource]: return self.content_container.getMemberList()
def insert(self): admin = self._session.query(User).filter(User.email == "*****@*****.**").one() bob = self._session.query(User).filter(User.email == "*****@*****.**").one() john_the_reader = ( self._session.query(User).filter(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 content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=business_workspace, label="Tools", do_save=True, do_notify=False, ) menu_workspace = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=business_workspace, label="Menus", do_save=True, do_notify=False, ) dessert_folder = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=recipe_workspace, label="Desserts", do_save=True, do_notify=False, ) content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=recipe_workspace, label="Salads", do_save=True, do_notify=False, ) content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=other_workspace, label="Infos", do_save=True, do_notify=False, ) # Pages, threads, .. tiramisu_page = content_api.create( content_type_slug=content_type_list.Page.slug, 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>", new_label="Tiramisu Recipes!!!", ) content_api.save(tiramisu_page, do_notify=False) best_cake_thread = content_api.create( content_type_slug=content_type_list.Thread.slug, 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_slug=content_type_list.File.slug, 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_slug=content_type_list.File.slug, 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_slug=content_type_list.Folder.slug, workspace=recipe_workspace, label="Fruits Desserts", parent=dessert_folder, do_save=True, do_notify=False, ) content_api.create( content_type_slug=content_type_list.Page.slug, workspace=business_workspace, parent=menu_workspace, label="Current Menu", do_save=True, do_notify=False, ) content_api.create( content_type_slug=content_type_list.Page.slug, workspace=recipe_workspace, parent=fruits_desserts_folder, label="New Fruit Salad", do_save=True, do_notify=False, ) old_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, 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, do_notify=False) bad_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, 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, do_notify=False) # File at the root for test content_api.create( content_type_slug=content_type_list.Page.slug, workspace=other_workspace, label="New Fruit Salad", do_save=True, do_notify=False, ) old_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, workspace=other_workspace, 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, do_notify=False) bad_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, workspace=other_workspace, 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, do_notify=False) 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>", do_save=True, do_notify=False, ) bob_content_api.create_comment( parent=best_cake_thread, content="<p>What about Apple Pie? There are Awesome!</p>", do_save=True, do_notify=False, ) reader_content_api.create_comment( parent=best_cake_thread, content="<p>You are right, but Kouign-amann are clearly better.</p>", do_save=True, do_notify=False, ) 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, do_notify=False) 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>", new_label="Tiramisu Recipe", ) bob_content_api.save(tiramisu_page, do_notify=False) self._session.flush()
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_slug=content_type_list.Folder.slug, workspace=business_workspace, label='Tools', do_save=True, do_notify=False, ) menu_workspace = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=business_workspace, label='Menus', do_save=True, do_notify=False, ) dessert_folder = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=recipe_workspace, label='Desserts', do_save=True, do_notify=False, ) salads_folder = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=recipe_workspace, label='Salads', do_save=True, do_notify=False, ) other_folder = content_api.create( content_type_slug=content_type_list.Folder.slug, workspace=other_workspace, label='Infos', do_save=True, do_notify=False, ) # Pages, threads, .. tiramisu_page = content_api.create( content_type_slug=content_type_list.Page.slug, 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_slug=content_type_list.Thread.slug, 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_slug=content_type_list.File.slug, 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_slug=content_type_list.File.slug, 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_slug=content_type_list.Folder.slug, workspace=recipe_workspace, label='Fruits Desserts', parent=dessert_folder, do_save=True, ) menu_page = content_api.create( content_type_slug=content_type_list.Page.slug, workspace=business_workspace, parent=menu_workspace, label='Current Menu', do_save=True, ) new_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, workspace=recipe_workspace, parent=fruits_desserts_folder, label='New Fruit Salad', do_save=True, ) old_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, 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_slug=content_type_list.Page.slug, 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_slug=content_type_list.Page.slug, workspace=other_workspace, label='New Fruit Salad', do_save=True, ) old_fruit_salad = content_api.create( content_type_slug=content_type_list.Page.slug, 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_slug=content_type_list.Page.slug, 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()
def test_api___simple_search_ok__filter_by_deleted_archived_active(self) -> None: dbsession = get_tm_session(self.session_factory, transaction.manager) admin = dbsession.query(User).filter(User.email == "*****@*****.**").one() uapi = UserApi(current_user=admin, session=dbsession, config=self.app_config) gapi = GroupApi(current_user=admin, session=dbsession, config=self.app_config) groups = [gapi.get_one_with_name("trusted-users")] user = uapi.create_user( "*****@*****.**", password="******", do_save=True, do_notify=False, groups=groups, ) workspace_api = WorkspaceApi( current_user=admin, session=dbsession, config=self.app_config, show_deleted=True ) workspace = workspace_api.create_workspace("test", save_now=True) rapi = RoleApi(current_user=admin, session=dbsession, config=self.app_config) rapi.create_one(user, workspace, UserRoleInWorkspace.WORKSPACE_MANAGER, False) api = ContentApi(session=dbsession, current_user=user, config=self.app_config) api.create( content_type_slug="html-document", workspace=workspace, label="stringtosearch active", do_save=True, ) api.create( content_type_slug="html-document", workspace=workspace, label="stringtosearch active 2", do_save=True, ) deleted_content = api.create( content_type_slug="html-document", workspace=workspace, label="stringtosearch deleted", do_save=True, ) with new_revision(session=dbsession, tm=transaction.manager, content=deleted_content): api.delete(deleted_content) api.save(deleted_content) archived_content = api.create( content_type_slug="html-document", workspace=workspace, label="stringtosearch archived", do_save=True, ) with new_revision(session=dbsession, tm=transaction.manager, content=archived_content): api.archive(archived_content) api.save(archived_content) transaction.commit() # get all params = { "search_string": "stringtosearch", "show_deleted": 1, "show_archived": 1, "show_active": 1, } self.testapp.authorization = ("Basic", ("*****@*****.**", "*****@*****.**")) res = self.testapp.get("/api/v2/search/content".format(), status=200, params=params) search_result = res.json_body assert search_result assert search_result["total_hits"] == 4 assert search_result["is_total_hits_accurate"] is False assert len(search_result["contents"]) == 4 # get only active params = {"search_string": "stringtosearch"} self.testapp.authorization = ("Basic", ("*****@*****.**", "*****@*****.**")) res = self.testapp.get("/api/v2/search/content".format(), status=200, params=params) default_search_result = res.json_body assert default_search_result assert default_search_result["total_hits"] == 2 assert default_search_result["is_total_hits_accurate"] is False assert len(default_search_result["contents"]) == 2 assert default_search_result["contents"][0]["label"] == "stringtosearch active 2" assert default_search_result["contents"][1]["label"] == "stringtosearch active" params = { "search_string": "stringtosearch", "show_active": 1, "show_deleted": 0, "show_archived": 0, } self.testapp.authorization = ("Basic", ("*****@*****.**", "*****@*****.**")) res = self.testapp.get("/api/v2/search/content".format(), status=200, params=params) only_active_search_result = res.json_body assert only_active_search_result == default_search_result params = { "search_string": "stringtosearch", "show_active": 1, "show_deleted": 1, "show_archived": 0, } self.testapp.authorization = ("Basic", ("*****@*****.**", "*****@*****.**")) res = self.testapp.get("/api/v2/search/content".format(), status=200, params=params) search_result = res.json_body assert search_result assert search_result["total_hits"] == 3 assert search_result["is_total_hits_accurate"] is False assert len(search_result["contents"]) == 3 assert search_result["contents"][0]["label"].startswith("stringtosearch deleted") assert search_result["contents"][1]["label"] == "stringtosearch active 2" assert search_result["contents"][2]["label"] == "stringtosearch active" params = { "search_string": "stringtosearch", "show_active": 0, "show_deleted": 0, "show_archived": 1, } self.testapp.authorization = ("Basic", ("*****@*****.**", "*****@*****.**")) res = self.testapp.get("/api/v2/search/content".format(), status=200, params=params) search_result = res.json_body assert search_result assert search_result["total_hits"] == 1 assert search_result["is_total_hits_accurate"] is False assert len(search_result["contents"]) == 1 assert search_result["contents"][0]["label"].startswith("stringtosearch archived")