def download(self, file_id, revision_id=None): file_id = int(file_id) revision_id = int(revision_id) if revision_id!='latest' else None user = tmpl_context.current_user workspace = tmpl_context.workspace content_api = ContentApi(user) revision_to_send = None if revision_id: item = content_api.get_one_from_revision(file_id, self._item_type, workspace, revision_id) else: item = content_api.get_one(file_id, self._item_type, workspace) revision_to_send = None if item.revision_to_serialize<=0: for revision in item.revisions: if not revision_to_send: revision_to_send = revision if revision.revision_id>revision_to_send.revision_id: revision_to_send = revision else: for revision in item.revisions: if revision.revision_id==item.revision_to_serialize: revision_to_send = revision break content_type = 'application/x-download' if revision_to_send.file_mimetype: content_type = str(revision_to_send.file_mimetype) tg.response.headers['Content-type'] = str(revision_to_send.file_mimetype) tg.response.headers['Content-Type'] = content_type tg.response.headers['Content-Disposition'] = str('attachment; filename="{}"'.format(revision_to_send.file_name)) return revision_to_send.file_content
def treeview_children(self, id='#', ignore_id=None, allowed_content_types=None): """ id must be "#" or something like "workspace_3__document_8" """ if id == '#': return self.treeview_root() ignore_item_ids = [int(ignore_id)] if ignore_id else [] workspace, content = convert_id_into_instances(id) viewable_content_types = [] if allowed_content_types: viewable_content_types = allowed_content_types.split(',') else: viewable_content_types = self._get_treeviewable_content_types_or_none( ) contents = ContentApi(tmpl_context.current_user).get_child_folders( content, workspace, [], ignore_item_ids, viewable_content_types) # This allow to show contents and folders group by type sorted_contents = ContentApi.sort_content(contents) dictified_contents = Context(CTX.MENU_API).toDict(sorted_contents, 'd') return dictified_contents
def download_pdf_one(self, page_id: str, revision_id: str=None, *args, **kwargs): file_id = int(tg.request.controller_state.routing_args.get('file_id')) revision_id = int(revision_id) if revision_id != 'latest' else None page = int(page_id) cache_path = CFG.get_instance().PREVIEW_CACHE_DIR preview_manager = PreviewManager(cache_path, create_folder=True) user = tmpl_context.current_user content_api = ContentApi(user, show_archived=True, show_deleted=True) file = content_api.get_one(file_id, self._item_type) if revision_id: file_path = content_api.get_one_revision_filepath(revision_id) else: file = content_api.get_one(file_id, self._item_type) file_path = content_api.get_one_revision_filepath(file.revision_id) path = preview_manager.get_pdf_preview(file_path=file_path, page=page) file_suffix = '' if page > -1: file_suffix = '.page-{}'.format(page + 1) tg.response.headers['Content-Disposition'] = \ 'attachment; filename="{}{}.pdf"'.format( file.label, file_suffix, ) with open(path, 'rb') as pdf: return pdf.read()
def download_pdf_one(self, page_id, *args, **kwargs): file_id = int(tg.request.controller_state.routing_args.get('file_id')) page_id = int(page_id) # page_id = int(tg.request.controller_state.routing_args.get('page_id')) # For now it's done through database content # but soon it'll be with disk access user = tmpl_context.current_user content_api = ContentApi( user, show_archived=True, show_deleted=True, ) file_name = content_api.get_one(file_id, self._item_type).file_name cache_path = '/home/alexis/Pictures/cache/' preview_manager = PreviewManager(cache_path, create_folder=True) path = preview_manager.get_pdf_preview( file_path='/home/alexis/Pictures/cache/{}'.format(file_name), page=page_id, ) tg.response.headers['Content-Disposition'] = \ str('attachment; filename="{}"'.format(file_name)) with open(path, 'rb') as pdf: return pdf.read()
def test_set_status_ok(self): uapi = UserApi(None) groups = [ GroupApi(None).get_one(Group.TIM_USER), GroupApi(None).get_one(Group.TIM_MANAGER), GroupApi(None).get_one(Group.TIM_ADMIN) ] user = uapi.create_user(email='this.is@user', groups=groups, save_now=True) workspace = WorkspaceApi(user).create_workspace('test workspace', save_now=True) api = ContentApi(user) c = api.create(ContentType.Folder, workspace, None, 'parent', True) with new_revision(c): for new_status in [ 'open', 'closed-validated', 'closed-unvalidated', 'closed-deprecated' ]: api.set_status(c, new_status) eq_(new_status, c.status) eq_(ActionDescription.STATUS_UPDATE, c.revision_type)
def post(self, label='', content='', parent_id=None): """ Creates a new thread. Actually, on POST, the content will be included in a user comment instead of being the thread description :param label: :param content: :return: """ # TODO - SECURE THIS workspace = tmpl_context.workspace api = ContentApi(tmpl_context.current_user) with DBSession.no_autoflush: thread = api.create(ContentType.Thread, workspace, tmpl_context.folder, label) # FIXME - DO NOT DUPLCIATE FIRST MESSAGE # thread.description = content api.save(thread, ActionDescription.CREATION, do_notify=False) comment = api.create(ContentType.Comment, workspace, thread, label) comment.label = '' comment.description = content if not self._path_validation.validate_new_content(thread): return render_invalid_integrity_chosen_path( thread.get_label(), ) api.save(comment, ActionDescription.COMMENT, do_notify=False) api.do_notify(thread) tg.flash(_('Thread created'), CST.STATUS_OK) tg.redirect( self._std_url.format(tmpl_context.workspace_id, tmpl_context.folder_id, thread.content_id))
def __init__(self, path: str, environ: dict, content: Content): super(File, self).__init__(path, environ) self.content = content self.user = UserApi(None).get_one_by_email( environ['http_authenticator.username']) self.content_api = ContentApi(self.user)
def test_mark_read(self): uapi = UserApi(None) groups = [GroupApi(None).get_one(Group.TIM_USER), GroupApi(None).get_one(Group.TIM_MANAGER), GroupApi(None).get_one(Group.TIM_ADMIN)] user_a = uapi.create_user(email='this.is@user', groups=groups, save_now=True) user_b = uapi.create_user(email='*****@*****.**', groups=groups, save_now=True) wapi = WorkspaceApi(user_a) workspace = wapi.create_workspace( 'test workspace', save_now=True) role_api = RoleApi(user_a) role_api.create_one(user_b, workspace, UserRoleInWorkspace.READER, False) cont_api_a = ContentApi(user_a) cont_api_b = ContentApi(user_b) page_1 = cont_api_a.create(ContentType.Page, workspace, None, 'this is a page', do_save=True) for rev in page_1.revisions: eq_(user_b not in rev.read_by.keys(), True) cont_api_b.mark_read(page_1) for rev in page_1.revisions: eq_(user_b in rev.read_by.keys(), True)
def get_one(self, page_id, revision_id=None): page_id = int(page_id) user = tmpl_context.current_user workspace = tmpl_context.workspace current_user_content = Context(CTX.CURRENT_USER).toDict(user) current_user_content.roles.sort(key=lambda role: role.workspace.name) content_api = ContentApi( user, show_deleted=True, show_archived=True, ) if revision_id: page = content_api.get_one_from_revision(page_id, ContentType.Page, workspace, revision_id) else: page = content_api.get_one(page_id, ContentType.Page, workspace) fake_api_breadcrumb = self.get_breadcrumb(page_id) fake_api_content = DictLikeClass(breadcrumb=fake_api_breadcrumb, current_user=current_user_content) fake_api = Context(CTX.FOLDER).toDict(fake_api_content) dictified_page = Context(CTX.PAGE).toDict(page, 'page') return DictLikeClass(result=dictified_page, fake_api=fake_api)
def get_one(self, thread_id, inverted: str = ''): thread_id = int(thread_id) user = tmpl_context.current_user workspace = tmpl_context.workspace current_user_content = Context(CTX.CURRENT_USER).toDict(user) current_user_content.roles.sort(key=lambda role: role.workspace.name) content_api = ContentApi(user) thread = content_api.get_one(thread_id, ContentType.Thread, workspace) fake_api_breadcrumb = self.get_breadcrumb(thread_id) fake_api_content = DictLikeClass(breadcrumb=fake_api_breadcrumb, current_user=current_user_content) fake_api = Context(CTX.FOLDER).toDict(fake_api_content) dictified_thread = Context(CTX.THREAD).toDict(thread, 'thread') if inverted: dictified_thread.thread.history = reversed( dictified_thread.thread.history) return DictLikeClass(result=dictified_thread, fake_api=fake_api, inverted=inverted)
def test_create_comment_ok(self): uapi = UserApi(None) groups = [ GroupApi(None).get_one(Group.TIM_USER), GroupApi(None).get_one(Group.TIM_MANAGER), GroupApi(None).get_one(Group.TIM_ADMIN) ] user = uapi.create_user(email='this.is@user', groups=groups, save_now=True) workspace = WorkspaceApi(user).create_workspace('test workspace', save_now=True) api = ContentApi(user) p = api.create(ContentType.Page, workspace, None, 'this_is_a_page') c = api.create_comment(workspace, p, 'this is the comment', True) eq_(Content, c.__class__) eq_(p.content_id, c.parent_id) eq_(user, c.owner) eq_(workspace, c.workspace) eq_(ContentType.Comment, c.type) eq_('this is the comment', c.description) eq_('', c.label) eq_(ActionDescription.COMMENT, c.revision_type)
def get_one(self, page_id: str='-1', revision_id: str=None, size: int=300, *args, **kwargs): file_id = int(tg.request.controller_state.routing_args.get('file_id')) page = int(page_id) revision_id = int(revision_id) if revision_id != 'latest' else None cache_path = CFG.get_instance().PREVIEW_CACHE_DIR preview_manager = PreviewManager(cache_path, create_folder=True) user = tmpl_context.current_user content_api = ContentApi(user, show_archived=True, show_deleted=True) if revision_id: file_path = content_api.get_one_revision_filepath(revision_id) else: file = content_api.get_one(file_id, self._item_type) file_path = content_api.get_one_revision_filepath(file.revision_id) try: path = preview_manager.get_jpeg_preview(file_path=file_path, page=page, height=size, width=size) with open(path, 'rb') as large: result = large.read() except PreviewGeneratorException: result = None return result
def get_one(self, page_id: str = '-1', revision_id: str = None, size: int = 300, *args, **kwargs): file_id = int(tg.request.controller_state.routing_args.get('file_id')) page = int(page_id) revision_id = int(revision_id) if revision_id != 'latest' else None cache_path = CFG.get_instance().PREVIEW_CACHE_DIR preview_manager = PreviewManager(cache_path, create_folder=True) user = tmpl_context.current_user content_api = ContentApi(user, show_archived=True, show_deleted=True) if revision_id: file_path = content_api.get_one_revision_filepath(revision_id) else: file = content_api.get_one(file_id, self._item_type) file_path = content_api.get_one_revision_filepath(file.revision_id) try: path = preview_manager.get_jpeg_preview(file_path=file_path, page=page, height=size, width=size) with open(path, 'rb') as large: result = large.read() except PreviewGeneratorException: result = None return result
def add_event( self, calendar: Calendar, event: iCalendarEvent, event_name: str, owner: User, ) -> Content: """ Create Content event type. :param calendar: Event calendar owner :param event: ICS event :param event_name: Event name (ID) like 20160602T083511Z-18100-1001-1-71_Bastien-20160602T083516Z.ics :param owner: Event Owner :return: Created Content """ workspace = None if isinstance(calendar, WorkspaceCalendar): workspace = calendar.related_object elif isinstance(calendar, UserCalendar): pass else: raise UnknownCalendarType('Type "{0}" is not implemented'.format( type(calendar))) content = ContentApi(owner).create(content_type=ContentType.Event, workspace=workspace, do_save=False) self.populate_content_with_event(content, event, event_name) content.revision_type = ActionDescription.CREATION DBSession.add(content) DBSession.flush() transaction.commit() return content
def _build_sibling_list_of_tree_items(self, workspace: Workspace, content: Content, children: [NodeTreeItem], select_active_node = False, allowed_content_types: list = [], ignored_item_ids: list = []) -> (Content, [NodeTreeItem]): api = ContentApi(tmpl_context.current_user) tree_items = [] parent = content.parent if content else None viewable_content_types = self._get_treeviewable_content_types_or_none() child_contents = api.get_child_folders(parent, workspace, allowed_content_types, ignored_item_ids, viewable_content_types) for child in child_contents: children_to_add = children if child==content else [] if child==content and select_active_node: # The item is the requested node, so we select it is_selected = True elif content not in child_contents and select_active_node and child==content: # The item is not present in the list, so we select its parent node is_selected = True else: is_selected = False new_item = NodeTreeItem(child, children_to_add, is_selected) tree_items.append(new_item) # This allow to show contents and folders group by type tree_items = ContentApi.sort_tree_items(tree_items) return parent, tree_items
def get_one(self, file_id, revision_id=None): file_id = int(file_id) user = tmpl_context.current_user workspace = tmpl_context.workspace workspace_id = tmpl_context.workspace_id current_user_content = Context(CTX.CURRENT_USER, current_user=user).toDict(user) current_user_content.roles.sort(key=lambda role: role.workspace.name) content_api = ContentApi(user) if revision_id: file = content_api.get_one_from_revision(file_id, self._item_type, workspace, revision_id) else: file = content_api.get_one(file_id, self._item_type, workspace) fake_api_breadcrumb = self.get_breadcrumb(file_id) fake_api_content = DictLikeClass(breadcrumb=fake_api_breadcrumb, current_user=current_user_content) fake_api = Context(CTX.FOLDER, current_user=user).toDict(fake_api_content) dictified_file = Context(self._get_one_context, current_user=user).toDict(file, 'file') return DictLikeClass(result=dictified_file, fake_api=fake_api)
def home(self): user = tmpl_context.current_user current_user_content = Context(CTX.CURRENT_USER).toDict(user) fake_api = Context(CTX.CURRENT_USER).toDict( {'current_user': current_user_content}) last_active_contents = ContentApi(user).get_last_active( None, ContentType.Any, None) fake_api.last_actives = Context(CTX.CONTENT_LIST).toDict( last_active_contents, 'contents', 'nb') unread_contents = ContentApi(user).get_last_unread( None, ContentType.Any, None) fake_api.last_unread = Context(CTX.CONTENT_LIST).toDict( unread_contents, 'contents', 'nb') # INFO - D.A. - 2015-05-20 # For now, we do not have favorties and read/unread status # so we only show: # - workspaces # - last activity # - oldest open stuff items = ContentApi(user).get_all_without_exception( ContentType.Any, None)[:4] fake_api.favorites = Context(CTX.CONTENT_LIST).toDict( items, 'contents', 'nb') return DictLikeClass(fake_api=fake_api)
def test_unit__cant_get_non_access_content__ok__nominal_case(self): admin = DBSession.query(User)\ .filter(User.email == '*****@*****.**').one() bob = DBSession.query(User)\ .filter(User.email == '*****@*****.**').one() bob_workspace = WorkspaceApi(bob).create_workspace( 'bob_workspace', save_now=True, ) admin_workspace = WorkspaceApi(admin).create_workspace( 'admin_workspace', save_now=True, ) bob_page = ContentApi(bob).create( content_type=ContentType.Page, workspace=bob_workspace, label='bob_page', do_save=True, ) admin_page = ContentApi(bob).create( content_type=ContentType.Page, workspace=admin_workspace, label='admin_page', do_save=True, ) bob_viewable = ContentApi(bob).get_all() eq_(1, len(bob_viewable), 'Bob should view only one content') eq_( 'bob_page', bob_viewable[0].label, 'Bob should not view "{0}" content'.format( bob_viewable[0].label, ))
def __init__(self, is_case_sensitive: bool = False): """ :param is_case_sensitive: If True, consider name with different case as different. """ self._is_case_sensitive = is_case_sensitive self._workspace_api = UnsafeWorkspaceApi(None) self._content_api = ContentApi(None)
def current_folder(cls) -> Content: content_api = ContentApi(tg.tmpl_context.current_user) folder_id = int(tg.request.controller_state.routing_args.get('folder_id')) folder = content_api.get_one(folder_id, ContentType.Folder, tg.tmpl_context.workspace) tg.tmpl_context.folder_id = folder_id tg.tmpl_context.folder = folder return folder
def mark_all_read(self): ''' Mark as read all the content that hasn't been read redirects the user to "/home" ''' user = tg.tmpl_context.current_user content_api = ContentApi(user) content_api.mark_read__all() tg.redirect("/home")
def _current_item_manually(cls, item_id: int, item_type: str) -> Content: # in case thread or page or other stuff is instanciated, then force # the associated item to be available through generic name tmpl_context.item to be available content_api = ContentApi(tg.tmpl_context.current_user) item = content_api.get_one(item_id, item_type, tg.tmpl_context.workspace) tg.tmpl_context.item_id = item.content_id tg.tmpl_context.item = item return item
def treeview_root(self, id='#', current_id=None, all_workspaces=True, folder_allowed_content_types='', ignore_id=None, ignore_workspace_id=None): all_workspaces = bool(int(all_workspaces)) # ignore_workspace_id is a string like 3,12,78,15 ignored_ids = [int(id) for id in ignore_workspace_id.split(',')] if ignore_workspace_id else None if not current_id: # Default case is to return list of workspaces api = WorkspaceApi(tmpl_context.current_user) workspaces = api.get_all_for_user(tmpl_context.current_user, ignored_ids) dictified_workspaces = Context(CTX.MENU_API).toDict(workspaces, 'd') return dictified_workspaces allowed_content_types = ContentType.allowed_types_from_str(folder_allowed_content_types) ignored_item_ids = [int(ignore_id)] if ignore_id else [] # Now complex case: we must return a structured tree # including the selected node, all parents (and their siblings) workspace, content = convert_id_into_instances(current_id) # The following step allow to select the parent folder when content itself is not visible in the treeview if content and content.type!=ContentType.Folder and CFG.CST.TREEVIEW_ALL!=CFG.get_instance().WEBSITE_TREEVIEW_CONTENT: content = content.parent if content.parent else None # This is the init of the recursive-like build of the tree content_parent = content tree_items = [] # The first step allow to load child of selected item # (for example, when you select a folder in the windows explorer, # then the selected folder is expanded by default) content_api = ContentApi(tmpl_context.current_user) child_folders = content_api.get_child_folders(content_parent, workspace, allowed_content_types, ignored_item_ids) if len(child_folders)>0: first_child = child_folders[0] content_parent, tree_items = self._build_sibling_list_of_tree_items(workspace, first_child, tree_items, False, allowed_content_types, ignored_item_ids) content_parent, tree_items = self._build_sibling_list_of_tree_items(workspace, content_parent, tree_items, True, allowed_content_types, ignored_item_ids) while content_parent: # Do the same for the parent level content_parent, tree_items = self._build_sibling_list_of_tree_items(workspace, content_parent, tree_items) # Now, we have a tree_items list that is the root folders list, # so we now have to put it as a child of a list of workspaces should_select_workspace = not content full_tree = self._build_sibling_list_of_workspaces(workspace, tree_items, should_select_workspace, all_workspaces) return Context(CTX.MENU_API_BUILD_FROM_TREE_ITEM).toDict(full_tree, 'd')
def post(self, label='', content=''): workspace = tmpl_context.workspace api = ContentApi(tmpl_context.current_user) page = api.create(ContentType.Page, workspace, tmpl_context.folder, label) page.description = content api.save(page, ActionDescription.CREATION, do_notify=True) tg.flash(_('Page created'), CST.STATUS_OK) tg.redirect(tg.url('/workspaces/{}/folders/{}/pages/{}').format(tmpl_context.workspace_id, tmpl_context.folder_id, page.content_id))
def __init__(self, path: str, environ: dict, workspace: data.Workspace): super(Workspace, self).__init__(path, environ) self.workspace = workspace self.content = None self.user = UserApi(None).get_one_by_email( environ['http_authenticator.username']) self.content_api = ContentApi(self.user, show_temporary=True) self._file_count = 0
def getMemberList(self) -> [_DAVResource]: members = [] content_api = ContentApi(self.user) visible_children = content_api.get_all( self.content.content_id, ContentType.Any, self.workspace, ) for content in visible_children: content_path = '%s/%s' % ( self.path, transform_to_display(content.get_label_as_file())) try: if content.type == ContentType.Folder: members.append( Folder(content_path, self.environ, self.workspace, content)) elif content.type == ContentType.File: self._file_count += 1 members.append(File(content_path, self.environ, content)) else: self._file_count += 1 members.append( OtherFile(content_path, self.environ, content)) except Exception as exc: logger.exception( 'Unable to construct member {}'.format(content_path, ), exc_info=True, ) if self._file_count > 0 and self.provider.show_history(): members.append( HistoryFolder(path=self.path + '/' + ".history", environ=self.environ, content=self.content, workspace=self.workspace, type=HistoryType.Standard)) if self.provider.show_delete(): members.append( DeletedFolder(path=self.path + '/' + ".deleted", environ=self.environ, content=self.content, workspace=self.workspace)) if self.provider.show_archive(): members.append( ArchivedFolder(path=self.path + '/' + ".archived", environ=self.environ, content=self.content, workspace=self.workspace)) return members
def mark_read(self, workspace_id, **kwargs): user = tmpl_context.current_user workspace_api = WorkspaceApi(user) workspace = workspace_api.get_one(workspace_id) content_api = ContentApi(user) content_api.mark_read__workspace(workspace) tg.redirect('/workspaces/{}'.format(workspace_id)) return DictLikeClass(fake_api=fake_api)
def test_mark_read__all(self): uapi = UserApi(None) groups = [ GroupApi(None).get_one(Group.TIM_USER), GroupApi(None).get_one(Group.TIM_MANAGER), GroupApi(None).get_one(Group.TIM_ADMIN) ] user_a = uapi.create_user(email='this.is@user', groups=groups, save_now=True) user_b = uapi.create_user(email='*****@*****.**', groups=groups, save_now=True) wapi = WorkspaceApi(user_a) workspace = wapi.create_workspace('test workspace', save_now=True) role_api = RoleApi(user_a) role_api.create_one(user_b, workspace, UserRoleInWorkspace.READER, False) cont_api_a = ContentApi(user_a) cont_api_b = ContentApi(user_b) page_2 = cont_api_a.create(ContentType.Page, workspace, None, 'this is page1', do_save=True) page_3 = cont_api_a.create(ContentType.Thread, workspace, None, 'this is page2', do_save=True) page_4 = cont_api_a.create(ContentType.File, workspace, None, 'this is page3', do_save=True) for rev in page_2.revisions: eq_(user_b not in rev.read_by.keys(), True) for rev in page_3.revisions: eq_(user_b not in rev.read_by.keys(), True) for rev in page_4.revisions: eq_(user_b not in rev.read_by.keys(), True) DBSession.refresh(page_2) DBSession.refresh(page_3) DBSession.refresh(page_4) cont_api_b.mark_read__all() for rev in page_2.revisions: eq_(user_b in rev.read_by.keys(), True) for rev in page_3.revisions: eq_(user_b in rev.read_by.keys(), True) for rev in page_4.revisions: eq_(user_b in rev.read_by.keys(), True)
def getMemberList(self) -> [_DAVResource]: members = [] content_api = ContentApi(self.user) visible_children = content_api.get_all( self.content.content_id, ContentType.Any, self.workspace, ) for content in visible_children: content_path = '%s/%s' % (self.path, transform_to_display(content.get_label_as_file())) if content.type == ContentType.Folder: members.append(Folder(content_path, self.environ, self.workspace, content)) elif content.type == ContentType.File: self._file_count += 1 members.append(File(content_path, self.environ, content)) else: self._file_count += 1 members.append(OtherFile(content_path, self.environ, content)) if self._file_count > 0 and self.provider.show_history(): members.append( HistoryFolder( path=self.path + '/' + ".history", environ=self.environ, content=self.content, workspace=self.workspace, type=HistoryType.Standard ) ) if self.provider.show_delete(): members.append( DeletedFolder( path=self.path + '/' + ".deleted", environ=self.environ, content=self.content, workspace=self.workspace ) ) if self.provider.show_archive(): members.append( ArchivedFolder( path=self.path + '/' + ".archived", environ=self.environ, content=self.content, workspace=self.workspace ) ) return members
def _create_content_and_test(self, name, workspace, *args, **kwargs) -> Content: """ All extra parameters (*args, **kwargs) are for Content init :return: Created Content instance """ content = Content(*args, **kwargs) content.label = name content.workspace = workspace DBSession.add(content) DBSession.flush() eq_(1, ContentApi.get_canonical_query().filter(Content.label == name).count()) return ContentApi.get_canonical_query().filter(Content.label == name).one()
def __init__(self, path, environ, workspace: data.Workspace, content: data.Content = None, type: str = HistoryType.Standard): super(HistoryFolder, self).__init__(path, environ, workspace, content) self._is_archived = type == HistoryType.Archived self._is_deleted = type == HistoryType.Deleted self.content_api = ContentApi(current_user=self.user, show_archived=self._is_archived, show_deleted=self._is_deleted)
def test_set_status_unknown_status(self): uapi = UserApi(None) groups = [GroupApi(None).get_one(Group.TIM_USER), GroupApi(None).get_one(Group.TIM_MANAGER), GroupApi(None).get_one(Group.TIM_ADMIN)] user = uapi.create_user(email='this.is@user', groups=groups, save_now=True) workspace = WorkspaceApi(user).create_workspace('test workspace', save_now=True) api = ContentApi(user) c = api.create(ContentType.Folder, workspace, None, 'parent', True) api.set_status(c, 'unknown-status')
def put(self, folder_id, label, can_contain_folders=False, can_contain_threads=False, can_contain_files=False, can_contain_pages=False): # TODO - SECURE THIS workspace = tmpl_context.workspace api = ContentApi(tmpl_context.current_user) next_url = '' try: folder = api.get_one(int(folder_id), ContentType.Folder, workspace) subcontent = dict( folder = True if can_contain_folders=='on' else False, thread = True if can_contain_threads=='on' else False, file = True if can_contain_files=='on' else False, page = True if can_contain_pages=='on' else False ) if label != folder.label: # TODO - D.A. - 2015-05-25 - Allow to set folder description api.update_content(folder, label, folder.description) api.set_allowed_content(folder, subcontent) api.save(folder) tg.flash(_('Folder updated'), CST.STATUS_OK) next_url = self.url(folder.content_id) except Exception as e: tg.flash(_('Folder not updated: {}').format(str(e)), CST.STATUS_ERROR) next_url = self.url(int(folder_id)) tg.redirect(next_url)
def post(self, content: str = ''): # TODO - SECURE THIS workspace = tmpl_context.workspace thread = tmpl_context.thread api = ContentApi(tmpl_context.current_user) comment = api.create_comment(workspace, thread, content, True) next_str = '/workspaces/{}/folders/{}/threads/{}' next_url = tg.url(next_str).format(tmpl_context.workspace_id, tmpl_context.folder_id, tmpl_context.thread_id) tg.flash(_('Comment added'), CST.STATUS_OK) tg.redirect(next_url)
def test_get_all_with_parent_id(self): uapi = UserApi(None) groups = [ GroupApi(None).get_one(Group.TIM_USER), GroupApi(None).get_one(Group.TIM_MANAGER), GroupApi(None).get_one(Group.TIM_ADMIN) ] user = uapi.create_user(email='this.is@user', groups=groups, save_now=True) workspace = WorkspaceApi(user).create_workspace('test workspace', save_now=True) api = ContentApi(user) item = api.create(ContentType.Folder, workspace, None, 'parent', True) item2 = api.create(ContentType.File, workspace, item, 'file1', True) item3 = api.create(ContentType.File, workspace, None, 'file2', True) parent_id = item.content_id child_id = item2.content_id uid = user.user_id wid = workspace.workspace_id transaction.commit() # Refresh instances after commit user = uapi.get_one(uid) workspace = WorkspaceApi(user).get_one(wid) api = ContentApi(user) items = api.get_all(None, ContentType.Any, workspace) eq_(3, len(items)) items2 = api.get_all(parent_id, ContentType.File, workspace) eq_(1, len(items2)) eq_(child_id, items2[0].content_id)
def get_all_fake(self, context_workspace: Workspace, context_folder: Content) -> [Content]: """ fake methods are used in other controllers in order to simulate a client/server api. the "client" controller method will include the result into its own fake_api object which will be available in the templates :param context_workspace: the workspace which would be taken from tmpl_context if we were in the normal behavior :return: """ workspace = context_workspace content_api = ContentApi(tmpl_context.current_user) items = content_api.get_all(context_folder.content_id, self._item_type, workspace) dictified_items = Context(self._get_all_context).toDict(items) return DictLikeClass(result = dictified_items)
def post(self, label='', content=''): workspace = tmpl_context.workspace api = ContentApi(tmpl_context.current_user) page = api.create(ContentType.Page, workspace, tmpl_context.folder, label) page.description = content api.save(page, ActionDescription.CREATION, do_notify=True) tg.flash(_('Page created'), CST.STATUS_OK) tg.redirect( tg.url('/workspaces/{}/folders/{}/pages/{}').format( tmpl_context.workspace_id, tmpl_context.folder_id, page.content_id))
def post(self, content=''): # TODO - SECURE THIS workspace = tmpl_context.workspace thread = tmpl_context.thread api = ContentApi(tmpl_context.current_user) comment = api.create_comment(workspace, thread, content, True) next_url = tg.url('/workspaces/{}/folders/{}/threads/{}').format(tmpl_context.workspace_id, tmpl_context.folder_id, tmpl_context.thread_id) tg.flash(_('Comment added'), CST.STATUS_OK) tg.redirect(next_url)
def update_event( self, calendar: Calendar, event: iCalendarEvent, event_name: str, current_user: User, ) -> Content: """ Update Content Event :param calendar: Event calendar owner :param event: ICS event :param event_name: Event name (ID) like 20160602T083511Z-18100-1001-1-71_Bastien-20160602T083516Z.ics :param current_user: Current modification asking user :return: Updated Content """ workspace = None if isinstance(calendar, WorkspaceCalendar): workspace = calendar.related_object elif isinstance(calendar, UserCalendar): pass else: raise UnknownCalendarType('Type "{0}" is not implemented' .format(type(calendar))) content_api = ContentApi( current_user, force_show_all_types=True, disable_user_workspaces_filter=True ) content = content_api.find_one_by_unique_property( property_name='name', property_value=event_name, workspace=workspace ) with new_revision(content): self.populate_content_with_event( content, event, event_name ) content.revision_type = ActionDescription.EDITION DBSession.flush() transaction.commit() return content
def get_all_fake(self, context_workspace: Workspace, parent_id=None): """ fake methods are used in other controllers in order to simulate a client/server api. the "client" controller method will include the result into its own fake_api object which will be available in the templates :param context_workspace: the workspace which would be taken from tmpl_context if we were in the normal behavior :return: """ workspace = context_workspace content_api = ContentApi(tmpl_context.current_user) parent_folder = content_api.get_one(parent_id, ContentType.Folder) folders = content_api.get_child_folders(parent_folder, workspace) folders = Context(CTX.FOLDERS).toDict(folders) return DictLikeClass(result = folders)
def get_all_fake(self, context_workspace: Workspace, parent_id=None): """ fake methods are used in other controllers in order to simulate a client/server api. the "client" controller method will include the result into its own fake_api object which will be available in the templates :param context_workspace: the workspace which would be taken from tmpl_context if we were in the normal behavior :return: """ workspace = context_workspace content_api = ContentApi(tmpl_context.current_user) parent_folder = content_api.get_one(parent_id, ContentType.Folder) folders = content_api.get_child_folders(parent_folder, workspace) folders = Context(CTX.FOLDERS).toDict(folders) return DictLikeClass(result=folders)
def __init__(self, is_case_sensitive: bool=False): """ :param is_case_sensitive: If True, consider name with different case as different. """ self._is_case_sensitive = is_case_sensitive self._workspace_api = UnsafeWorkspaceApi(None) self._content_api = ContentApi(None)
def get_one(self, thread_id): thread_id = int(thread_id) user = tmpl_context.current_user workspace = tmpl_context.workspace current_user_content = Context(CTX.CURRENT_USER).toDict(user) current_user_content.roles.sort(key=lambda role: role.workspace.name) content_api = ContentApi(user) thread = content_api.get_one(thread_id, ContentType.Thread, workspace) fake_api_breadcrumb = self.get_breadcrumb(thread_id) fake_api_content = DictLikeClass(breadcrumb=fake_api_breadcrumb, current_user=current_user_content) fake_api = Context(CTX.FOLDER).toDict(fake_api_content) dictified_thread = Context(CTX.THREAD).toDict(thread, 'thread') return DictLikeClass(result = dictified_thread, fake_api=fake_api)
def edit(self, folder_id): """ Show the edit form (do not really edit the data) :param item_id: :return: """ folder_id = int(folder_id) user = tmpl_context.current_user workspace = tmpl_context.workspace content_api = ContentApi(user) folder = content_api.get_one(folder_id, ContentType.Folder, workspace) dictified_folder = Context(CTX.FOLDER).toDict(folder, 'folder') return DictLikeClass(result = dictified_folder)
def put(self, item_id, folder_id='0'): """ :param item_id: :param folder_id: id of the folder, in a style like 'workspace_14__content_1586' :return: """ # TODO - SECURE THIS workspace = tmpl_context.workspace item_id = int(item_id) new_workspace, new_parent = convert_id_into_instances(folder_id) if new_workspace != workspace: # check that user is at least # - content manager in current workspace # - content manager in new workspace user = tmpl_context.current_user if user.get_role(workspace) < UserRoleInWorkspace.CONTENT_MANAGER: tg.flash(_('You are not allowed ' 'to move this folder'), CST.STATUS_ERROR) tg.redirect(self.parent_controller.url(item_id)) if user.get_role(new_workspace) < UserRoleInWorkspace.CONTENT_MANAGER: tg.flash(_('You are not allowed to move ' 'this folder to this workspace'), CST.STATUS_ERROR) tg.redirect(self.parent_controller.url(item_id)) api = ContentApi(tmpl_context.current_user) item = api.get_one(item_id, ContentType.Any, workspace) api.move_recursively(item, new_parent, new_workspace) next_url = tg.url('/workspaces/{}/folders/{}'.format( new_workspace.workspace_id, item_id)) if new_parent: tg.flash(_('Item moved to {} (workspace {})').format( new_parent.label, new_workspace.label), CST.STATUS_OK) else: tg.flash(_('Item moved to workspace {}').format( new_workspace.label)) tg.redirect(next_url) else: # Default move inside same workspace api = ContentApi(tmpl_context.current_user) item = api.get_one(item_id, ContentType.Any, workspace) api.move(item, new_parent) next_url = self.parent_controller.url(item_id) if new_parent: tg.flash(_('Item moved to {}').format(new_parent.label), CST.STATUS_OK) else: tg.flash(_('Item moved to workspace root')) tg.redirect(next_url)
def test_get_all_with_filter(self): uapi = UserApi(None) groups = [GroupApi(None).get_one(Group.TIM_USER), GroupApi(None).get_one(Group.TIM_MANAGER), GroupApi(None).get_one(Group.TIM_ADMIN)] user = uapi.create_user(email='this.is@user', groups=groups, save_now=True) workspace = WorkspaceApi(user).create_workspace('test workspace', save_now=True) api = ContentApi(user) item = api.create(ContentType.Folder, workspace, None, 'thefolder', True) item2 = api.create(ContentType.File, workspace, None, 'thefile', True) uid = user.user_id wid = workspace.workspace_id transaction.commit() # Refresh instances after commit user = uapi.get_one(uid) workspace = WorkspaceApi(user).get_one(wid) api = ContentApi(user) items = api.get_all(None, ContentType.Any, workspace) eq_(2, len(items)) items2 = api.get_all(None, ContentType.File, workspace) eq_(1, len(items2)) eq_('thefile', items2[0].label) items3 = api.get_all(None, ContentType.Folder, workspace) eq_(1, len(items3)) eq_('thefolder', items3[0].label)
def test_set_status_ok(self): uapi = UserApi(None) groups = [GroupApi(None).get_one(Group.TIM_USER), GroupApi(None).get_one(Group.TIM_MANAGER), GroupApi(None).get_one(Group.TIM_ADMIN)] user = uapi.create_user(email='this.is@user', groups=groups, save_now=True) workspace = WorkspaceApi(user).create_workspace('test workspace', save_now=True) api = ContentApi(user) c = api.create(ContentType.Folder, workspace, None, 'parent', True) for new_status in ['open', 'closed-validated', 'closed-unvalidated', 'closed-deprecated']: api.set_status(c, new_status) eq_(new_status, c.status) eq_(ActionDescription.STATUS_UPDATE, c.revision_type)
def __init__(self, path: str, environ: dict, workspace: data.Workspace): super(Workspace, self).__init__(path, environ) self.workspace = workspace self.content = None self.user = UserApi(None).get_one_by_email(environ['http_authenticator.username']) self.content_api = ContentApi(self.user, show_temporary=True) self._file_count = 0
def put_unread(self, item_id): item_id = int(item_id) content_api = ContentApi(tmpl_context.current_user, True, True) # Here we do not filter deleted items item = content_api.get_one(item_id, self._item_type, tmpl_context.workspace) item_url = self._std_url.format(item.workspace_id, item.parent_id, item.content_id) try: msg = _('{} marked unread.').format(self._item_type_label) content_api.mark_unread(item) tg.flash(msg, CST.STATUS_OK) tg.redirect(item_url) except ValueError as e: logger.debug(self, 'Exception: {}'.format(e.__str__)) msg = _('{} not marked unread: {}').format(self._item_type_label, str(e)) tg.flash(msg, CST.STATUS_ERROR) tg.redirect(item_url)
def edit(self, item_id): """ Show the edit form (do not really edit the data) :param item_id: :return: """ current_user_content = Context(CTX.CURRENT_USER).toDict(tmpl_context.current_user) fake_api = Context(CTX.FOLDER).toDict(DictLikeClass(current_user=current_user_content)) item_id = int(item_id) user = tmpl_context.current_user workspace = tmpl_context.workspace content_api = ContentApi(user) item = content_api.get_one(item_id, ContentType.Any, workspace) dictified_item = Context(CTX.DEFAULT).toDict(item, 'item') return DictLikeClass(result = dictified_item, fake_api=fake_api)
def edit(self, item_id): """ Show the edit form (do not really edit the data) :param item_id: :return: """ # the follwing line allow to define the template to use in child classes. tg.override_template(self.edit, self.TEMPLATE_EDIT) item_id = int(item_id) user = tmpl_context.current_user workspace = tmpl_context.workspace content_api = ContentApi(user) item = content_api.get_one(item_id, self._item_type, workspace) dictified_item = Context(self._get_one_context).toDict(item, 'item') return DictLikeClass(result = dictified_item)
def test_children(self): admin = DBSession.query(User).filter(User.email == '*****@*****.**').one() self._create_thread_and_test( workspace_name='workspace_1', folder_name='folder_1', thread_name='thread_1', user=admin ) workspace = DBSession.query(Workspace).filter(Workspace.label == 'workspace_1').one() folder = ContentApi.get_canonical_query().filter(Content.label == 'folder_1').one() eq_([folder, ], list(workspace.get_valid_children()))
def search(self, keywords = ''): from tracim.lib.content import ContentApi user = tmpl_context.current_user api = ContentApi(user) items = [] keyword_list = api.get_keywords(keywords) result = api.search(keyword_list) if result: items = result.limit(ContentApi.SEARCH_DEFAULT_RESULT_NB).all() current_user_content = Context(CTX.CURRENT_USER).toDict(user) fake_api = Context(CTX.CURRENT_USER).toDict({'current_user': current_user_content}) search_results = Context(CTX.SEARCH).toDict(items, 'results', 'result_nb') search_results.keywords = keyword_list return DictLikeClass(fake_api=fake_api, search=search_results)