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
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
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
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()
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()