def reverse_func(state, schema): """ Reverses NodeWikiPage migration. Repoints guids back to each NodeWikiPage, repoints comment_targets, comments_viewed_timestamps, and deletes all WikiVersions and WikiPages """ nwp_content_type_id = ContentType.objects.get_for_model(NodeWikiPage).id nodes = AbstractNode.objects.exclude(wiki_pages_versions={}) progress_bar = progressbar.ProgressBar(maxval=nodes.count() or 100).start() for i, node in enumerate(nodes, 1): progress_bar.update(i) for wiki_key, version_list in node.wiki_pages_versions.iteritems(): if version_list: for index, version in enumerate(version_list): nwp = NodeWikiPage.objects.filter(former_guid=version).include(None)[0] # All NodeWikiPages associated with a certain wiki key on a node point to the same WikiPage. wp = WikiPage.load(version) guid = migrate_guid_referent(Guid.load(version), nwp, nwp_content_type_id) guid.save() nwp = guid.referent # Moved only for last item in wiki_pages_versions array for every page_name, NWP->WP is a many-to-one mapping. NWP->WV is a one-to-one mapping. move_comment_target(Guid.load(wp._id), nwp) update_comments_viewed_timestamp(node, wp._id, nwp) progress_bar.finish() WikiVersion.objects.all().delete() WikiPage.objects.all().delete() logger.info('NodeWikiPages restored and WikiVersions and WikiPages removed.')
def get_paginated_response(self, data): """Add number of unread comments to links.meta when viewing list of comments filtered by a target node, file or wiki page.""" response = super(CommentPagination, self).get_paginated_response(data) response_dict = response.data kwargs = self.request.parser_context['kwargs'].copy() if self.request.query_params.get('related_counts', False): target_id = self.request.query_params.get('filter[target]', None) node_id = kwargs.get('node_id', None) node = AbstractNode.load(node_id) user = self.request.user if target_id and not user.is_anonymous and node.is_contributor_or_group_member(user): root_target = Guid.load(target_id) if root_target: page = getattr(root_target.referent, 'root_target_page', None) if page: if not len(data): unread = 0 else: unread = Comment.find_n_unread(user=user, node=node, page=page, root_id=target_id) if self.request.version < '2.1': response_dict['links']['meta']['unread'] = unread else: response_dict['meta']['unread'] = unread return Response(response_dict)
def persistent_file_download(auth, **kwargs): id_or_guid = kwargs.get('fid_or_guid') file = BaseFileNode.active.filter(_id=id_or_guid).first() if not file: guid = Guid.load(id_or_guid) if guid: file = guid.referent else: raise HTTPError(http_status.HTTP_404_NOT_FOUND, data={ 'message_short': 'File Not Found', 'message_long': 'The requested file could not be found.' }) if not file.is_file: raise HTTPError( http_status.HTTP_400_BAD_REQUEST, data={'message_long': 'Downloading folders is not permitted.'}) auth_redirect = check_contributor_auth(file.target, auth, include_public=True, include_view_only_anon=True) if auth_redirect: return auth_redirect query_params = request.args.to_dict() return redirect(file.generate_waterbutler_url(**query_params), code=http_status.HTTP_302_FOUND)
def get_file_guids(cls, materialized_path, provider, node=None): guids = [] path = materialized_path.strip('/') file_obj = cls.load(path) if not file_obj: file_obj = TrashedFileNode.load(path) # At this point, file_obj may be an OsfStorageFile, an OsfStorageFolder, or a # TrashedFileNode. TrashedFileNodes do not have *File and *Folder subclasses, since # only osfstorage trashes folders. To search for children of TrashFileNodes # representing ex-OsfStorageFolders, we will reimplement the `children` method of the # Folder class here. if not file_obj.is_file: children = [] if isinstance(file_obj, TrashedFileNode): children = file_obj.trashed_children.all() else: children = file_obj.children for item in children: guids.extend(cls.get_file_guids(item.path, provider, node=node)) else: try: guid = Guid.find(Q('referent', 'eq', file_obj))[0] except IndexError: guid = None if guid: guids.append(guid._id) return sorted(guids)
def _update_comments_timestamp(auth, node, page=Comment.OVERVIEW, root_id=None): if node.is_contributor(auth.user): enqueue_postcommit_task(ban_url, (node, ), {}, celery=False, once_per_request=True) if root_id is not None: guid_obj = Guid.load(root_id) if guid_obj is not None: enqueue_postcommit_task(ban_url, (guid_obj.referent, ), {}, celery=False, once_per_request=True) # update node timestamp if page == Comment.OVERVIEW: root_id = node._id auth.user.comments_viewed_timestamp[root_id] = timezone.now() auth.user.save() return { root_id: auth.user.comments_viewed_timestamp[root_id].isoformat() } else: return {}
def get_paginated_response(self, data): """Add number of unread comments to links.meta when viewing list of comments filtered by a target node, file or wiki page.""" response = super(CommentPagination, self).get_paginated_response(data) response_dict = response.data kwargs = self.request.parser_context['kwargs'].copy() if self.request.query_params.get('related_counts', False): target_id = self.request.query_params.get('filter[target]', None) node_id = kwargs.get('node_id', None) node = Node.load(node_id) user = self.request.user if target_id and not user.is_anonymous and node.is_contributor(user): root_target = Guid.load(target_id) if root_target: page = getattr(root_target.referent, 'root_target_page', None) if page: if not len(data): unread = 0 else: unread = Comment.find_n_unread(user=user, node=node, page=page, root_id=target_id) if self.request.version < '2.1': response_dict['links']['meta']['unread'] = unread else: response_dict['meta']['unread'] = unread return Response(response_dict)
def _update_comments_timestamp(auth, node, page=Comment.OVERVIEW, root_id=None): if node.is_contributor_or_group_member(auth.user): enqueue_postcommit_task(ban_url, (node, ), {}, celery=False, once_per_request=True) if root_id is not None: guid_obj = Guid.load(root_id) if guid_obj is not None: # FIXME: Doesn't work because we're not using Vanish anymore # enqueue_postcommit_task(ban_url, (self.get_node(),), {}, celery=False, once_per_request=True) pass # update node timestamp if page == Comment.OVERVIEW: root_id = node._id auth.user.comments_viewed_timestamp[root_id] = timezone.now() auth.user.save() return { root_id: auth.user.comments_viewed_timestamp[root_id].isoformat() } else: return {}
def update_file_guid_referent(self, node, event_type, payload, user=None): if event_type not in ('addon_file_moved', 'addon_file_renamed'): return # Nothing to do source, destination = payload['source'], payload['destination'] source_node, destination_node = Node.load(source['node']['_id']), Node.load(destination['node']['_id']) if source['provider'] in settings.ADDONS_BASED_ON_IDS: if event_type == 'addon_file_renamed': return # Node has not changed and provider has not changed # Must be a move if source['provider'] == destination['provider'] and source_node == destination_node: return # Node has not changed and provider has not changed file_guids = BaseFileNode.resolve_class(source['provider'], BaseFileNode.ANY).get_file_guids( materialized_path=source['materialized'] if source['provider'] != 'osfstorage' else source['path'], provider=source['provider'], node=source_node ) for guid in file_guids: obj = Guid.load(guid) if source_node != destination_node and Comment.find(Q('root_target._id', 'eq', guid)).count() != 0: update_comment_node(guid, source_node, destination_node) if source['provider'] != destination['provider'] or source['provider'] != 'osfstorage': old_file = BaseFileNode.load(obj.referent._id) obj.referent = create_new_file(obj, source, destination, destination_node) obj.save() if old_file and not TrashedFileNode.load(old_file._id): old_file.delete()
def public_comment_reply(self, user, public_comment, public_project): reply_target = Guid.load(public_comment._id) return CommentFactory( node=public_project, target=reply_target, user=user )
def test_update_wiki_updates_comments_and_user_comments_viewed_timestamp( self): project = ProjectFactory(creator=self.user, is_public=True) wiki = NodeWikiFactory(node=project, page_name='test') comment = CommentFactory(node=project, target=Guid.load(wiki._id), user=UserFactory()) # user views comments -- sets user.comments_viewed_timestamp url = project.api_url_for('update_comments_timestamp') res = self.app.put_json(url, { 'page': 'wiki', 'rootId': wiki._id }, auth=self.user.auth) assert res.status_code == 200 self.user.reload() assert wiki._id in self.user.comments_viewed_timestamp # user updates the wiki project.update_node_wiki('test', 'Updating wiki', self.auth) comment.reload() self.user.reload() new_version_id = project.wiki_pages_current['test'] assert new_version_id in self.user.comments_viewed_timestamp assert wiki._id not in self.user.comments_viewed_timestamp assert comment.target.referent._id == new_version_id
def test_update_wiki_updates_contributor_comments_viewed_timestamp(self): contributor = AuthUserFactory() project = ProjectFactory(creator=self.user, is_public=True) project.add_contributor(contributor) project.save() wiki_page = WikiFactory(node=project, page_name='test') wiki = WikiVersionFactory(wiki_page=wiki_page) comment = CommentFactory(node=project, target=Guid.load(wiki_page._id), user=self.user) # user views comments -- sets user.comments_viewed_timestamp url = project.api_url_for('update_comments_timestamp') res = self.app.put_json(url, { 'page': 'wiki', 'rootId': wiki_page._id }, auth=self.user.auth) assert res.status_code == 200 self.user.reload() assert wiki_page._id in self.user.comments_viewed_timestamp # contributor views comments -- sets contributor.comments_viewed_timestamp res = self.app.put_json(url, { 'page': 'wiki', 'rootId': wiki_page._id }, auth=contributor.auth) contributor.reload() assert wiki_page._id in contributor.comments_viewed_timestamp # user updates the wiki project.update_node_wiki('test', 'Updating wiki', self.auth) comment.reload() contributor.reload() new_version_id = project.get_wiki_version('test')._id assert wiki_page._id in contributor.comments_viewed_timestamp assert comment.target.referent._id == wiki_page._id
def update_file_guid_referent(self, node, event_type, payload, user=None): if event_type not in ('addon_file_moved', 'addon_file_renamed'): return # Nothing to do source, destination = payload['source'], payload['destination'] source_node, destination_node = Node.load(source['node']['_id']), Node.load(destination['node']['_id']) if source['provider'] in settings.ADDONS_BASED_ON_IDS: if event_type == 'addon_file_renamed': return # Node has not changed and provider has not changed # Must be a move if source['provider'] == destination['provider'] and source_node == destination_node: return # Node has not changed and provider has not changed file_guids = BaseFileNode.resolve_class(source['provider'], BaseFileNode.ANY).get_file_guids( materialized_path=source['materialized'] if source['provider'] != 'osfstorage' else source['path'], provider=source['provider'], node=source_node ) for guid in file_guids: obj = Guid.load(guid) if source_node != destination_node and Comment.objects.filter(root_target___id=guid).count() != 0: update_comment_node(guid, source_node, destination_node) if source['provider'] != destination['provider'] or source['provider'] != 'osfstorage': old_file = BaseFileNode.load(obj.referent._id) obj.referent = create_new_file(obj, source, destination, destination_node) obj.save() if old_file and not TrashedFileNode.load(old_file._id): old_file.delete()
def persistent_file_download(auth, **kwargs): id_or_guid = kwargs.get('fid_or_guid') file = BaseFileNode.active.filter(_id=id_or_guid).first() if not file: guid = Guid.load(id_or_guid) if guid: file = guid.referent else: raise HTTPError(httplib.NOT_FOUND, data={ 'message_short': 'File Not Found', 'message_long': 'The requested file could not be found.' }) if not file.is_file: raise HTTPError(httplib.BAD_REQUEST, data={ 'message_long': 'Downloading folders is not permitted.' }) auth_redirect = check_contributor_auth(file.target, auth, include_public=True, include_view_only_anon=True) if auth_redirect: return auth_redirect query_params = request.args.to_dict() return redirect( file.generate_waterbutler_url(**query_params), code=httplib.FOUND )
def test_find_unread_includes_comment_replies(self): project = ProjectFactory() user = UserFactory() project.add_contributor(user, save=True) comment = CommentFactory(node=project, user=user) CommentFactory(node=project, target=Guid.load(comment._id), user=project.creator) n_unread = Comment.find_n_unread(user=user, node=project, page='node') assert n_unread == 1
def get_target(self, target_id): guid = Guid.load(target_id) if not guid: raise NotFound target = guid.referent if getattr(target, 'is_registration', False) and not getattr(target, 'archiving', False): raise ValidationError('Registrations cannot be changed.') return target
def test_referent_can_be_set(self, Factory): obj = Factory() obj1 = Factory() guid = Guid.load(obj._id) assert guid.referent == obj # sanity check guid.referent = obj1 assert guid.referent == obj1
def test_wiki_has_comments_link(self): self._set_up_public_project_with_wiki_page() res = self.app.get(self.public_url) assert_equal(res.status_code, 200) url = res.json['data']['relationships']['comments']['links']['related']['href'] comment = CommentFactory(node=self.public_project, target=Guid.load(self.public_wiki._id), user=self.user) res = self.app.get(url) assert_equal(res.status_code, 200) assert_equal(res.json['data'][0]['type'], 'comments')
def registration_comment_reply( self, user, registration, registration_comment ): reply_target = Guid.load(registration_comment._id) return CommentFactory( node=registration, target=reply_target, user=user )
def get_target(self, node_id, target_id): target = Guid.load(target_id) if not target or not getattr(target.referent, 'belongs_to_node', None): raise ValueError('Invalid comment target.') elif not target.referent.belongs_to_node(node_id): raise ValueError('Cannot post to comment target on another node.') elif isinstance(target.referent, BaseFileNode) and target.referent.provider not in osf_settings.ADDONS_COMMENTABLE: raise ValueError('Comments are not supported for this file provider.') return target
def get_redirect_url(self, **kwargs): guid = Guid.load(kwargs['guids']) if guid: referent = guid.referent if getattr(referent, 'absolute_api_v2_url', None): return referent.absolute_api_v2_url else: raise EndpointNotImplementedError() return None
def test_private_node_only_logged_in_contributor_commenter_can_delete_own_reply( self, app, user, private_project, comment): reply_target = Guid.load(comment._id) reply = CommentFactory(node=private_project, target=reply_target, user=user) reply_url = '/{}comments/{}/'.format(API_BASE, reply._id) res = app.delete_json_api(reply_url, auth=user.auth) assert res.status_code == 204
def comment(self, user, contributor, private_project, wiki): comment = CommentFactory(node=private_project, target=Guid.load(wiki._id), user=contributor) comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} comment.save() return comment
def test_private_node_only_logged_in_contributor_commenter_can_delete_own_reply( self, app, user, private_project, comment): reply_target = Guid.load(comment._id) reply = CommentFactory( node=private_project, target=reply_target, user=user ) reply_url = '/{}comments/{}/'.format(API_BASE, reply._id) res = app.delete_json_api(reply_url, auth=user.auth) assert res.status_code == 204
def move_comment_target(current_guid, desired_target): """ Move the comment's target from the current target to the desired target Specifically for repointing WikiPage comments -> NodeWikiPage comments """ desired_target_guid_id = Guid.load(desired_target.former_guid).id if Comment.objects.filter(Q(root_target=current_guid) | Q(target=current_guid)).exists(): Comment.objects.filter(root_target=current_guid).update(root_target_id=desired_target_guid_id) Comment.objects.filter(target=current_guid).update(target_id=desired_target_guid_id) return
def test_resolve_guid_no_referent(self): guid = Guid.load(self.node._id) guid.referent = None guid.save() res = self.app.get( self.node.web_url_for('node_setting', _guid=True), auth=self.node.creator.auth, expect_errors=True, ) assert res.status_code == 404
def public_comment(self, user, contributor, public_project, public_wiki): public_comment = CommentFactory(node=public_project, target=Guid.load(public_wiki._id), user=contributor) public_comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} public_comment.save() return public_comment
def test_public_node_non_contrib_commenter_can_delete_wiki_comment( self, app, user, non_contrib): project = ProjectFactory(is_public=True, comment_level='public') test_wiki = NodeWikiFactory(node=project, user=user) comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contrib) url = '/{}comments/{}/'.format(API_BASE, comment._id) res = app.delete_json_api(url, auth=non_contrib.auth) assert res.status_code == 204
def test_public_node_non_contrib_commenter_can_delete_wiki_comment( self, app, user, non_contrib): project = ProjectFactory(is_public=True, comment_level='public') test_wiki = NodeWikiFactory(node=project, user=user) comment = CommentFactory( node=project, target=Guid.load(test_wiki._id), user=non_contrib ) url = '/{}comments/{}/'.format(API_BASE, comment._id) res = app.delete_json_api(url, auth=non_contrib.auth) assert res.status_code == 204
def test_wiki_has_comments_link(self): self._set_up_public_project_with_wiki_page() res = self.app.get(self.public_url) assert_equal(res.status_code, 200) url = res.json['data']['relationships']['comments']['links'][ 'related']['href'] comment = CommentFactory(node=self.public_project, target=Guid.load(self.public_wiki._id), user=self.user) res = self.app.get(url) assert_equal(res.status_code, 200) assert_equal(res.json['data'][0]['type'], 'comments')
def test_public_node_non_contrib_commenter_can_update_wiki_comment( self, app, user, non_contrib, set_up_payload): project = ProjectFactory(is_public=True) test_wiki = NodeWikiFactory(node=project, user=user) comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contrib) url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = set_up_payload(comment._id) res = app.put_json_api(url, payload, auth=non_contrib.auth) assert res.status_code == 200 assert payload['data']['attributes']['content'] == res.json['data'][ 'attributes']['content']
def wrapped(*args, **kwargs): guid = kwargs.get('guid') target = getattr(Guid.load(guid), 'referent', None) if not target: raise HTTPError( httplib.NOT_FOUND, data={ 'message_short': 'Guid not resolved', 'message_long': 'No object with that guid could be found', } ) kwargs['target'] = target return func(*args, **kwargs)
def wrapped(*args, **kwargs): guid = kwargs.get('guid') target = getattr(Guid.load(guid), 'referent', None) if not target: raise HTTPError(httplib.NOT_FOUND, data={ 'message_short': 'Guid not resolved', 'message_long': 'No object with that guid could be found', }) kwargs['target'] = target return func(*args, **kwargs)
def test_private_node_only_logged_in_contributor_commenter_can_undelete_own_reply( self, app, user, private_project, comment, set_up_payload): reply_target = Guid.load(comment._id) reply = CommentFactory(node=private_project, target=reply_target, user=user) reply_url = '/{}comments/{}/'.format(API_BASE, reply._id) reply.is_deleted = True reply.save() payload = set_up_payload(reply._id, has_content=False) res = app.patch_json_api(reply_url, payload, auth=user.auth) assert res.status_code == 200 assert not res.json['data']['attributes']['deleted'] assert res.json['data']['attributes']['content'] == reply.content
def wrapped(*args, **kwargs): if kwargs.get('nid') or kwargs.get('pid'): _inject_nodes(kwargs) target = kwargs.get('node') or getattr(Guid.load(kwargs.get('guid')), 'referent', None) if getattr(target, 'is_registration', False) and not getattr(target, 'archiving', False): raise HTTPError( http.BAD_REQUEST, data={ 'message_short': 'Registrations cannot be changed', 'message_long': "The operation you're trying to do cannot be applied to registered projects, which are not allowed to be changed", } ) return func(*args, **kwargs)
def public_comment(self, user, contributor, public_project, public_wiki): public_comment = CommentFactory( node=public_project, target=Guid.load(public_wiki._id), user=contributor ) public_comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} public_comment.save() return public_comment
def comment(self, user, contributor, private_project, wiki): comment = CommentFactory( node=private_project, target=Guid.load(wiki._id), user=contributor ) comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} comment.save() return comment
def test_public_node_non_contrib_commenter_can_update_wiki_comment( self, app, user, non_contrib, set_up_payload): project = ProjectFactory(is_public=True) test_wiki = NodeWikiFactory(node=project, user=user) comment = CommentFactory( node=project, target=Guid.load(test_wiki._id), user=non_contrib ) url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = set_up_payload(comment._id) res = app.put_json_api(url, payload, auth=non_contrib.auth) assert res.status_code == 200 assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content']
def test_private_node_only_logged_in_contributor_commenter_can_undelete_own_reply( self, app, user, private_project, comment, set_up_payload): reply_target = Guid.load(comment._id) reply = CommentFactory( node=private_project, target=reply_target, user=user ) reply_url = '/{}comments/{}/'.format(API_BASE, reply._id) reply.is_deleted = True reply.save() payload = set_up_payload(reply._id, has_content=False) res = app.patch_json_api(reply_url, payload, auth=user.auth) assert res.status_code == 200 assert not res.json['data']['attributes']['deleted'] assert res.json['data']['attributes']['content'] == reply.content
def _set_up_public_project_comment_reports(self, comment_level='public'): self.public_project = ProjectFactory.create(is_public=True, creator=self.user, comment_level=comment_level) self.public_project.add_contributor(contributor=self.contributor, save=True) with mock.patch('osf.models.AbstractNode.update_search'): self.public_wiki = NodeWikiFactory(node=self.public_project, user=self.user) self.public_comment = CommentFactory.build(node=self.public_project, target=Guid.load(self.public_wiki._id), user=self.contributor) self.public_comment.reports = self.public_comment.reports or {} self.public_comment.reports[self.user._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } self.public_comment.save() self.public_url = '/{}comments/{}/reports/'.format(API_BASE, self.public_comment._id)
def add_pointer(auth): """Add a single pointer to a node using only JSON parameters """ to_node_id = request.json.get('toNodeID') pointer_to_move = request.json.get('pointerID') if not (to_node_id and pointer_to_move): raise HTTPError(http.BAD_REQUEST) pointer = AbstractNode.load(pointer_to_move) to_node = Guid.load(to_node_id).referent try: _add_pointers(to_node, [pointer], auth) except ValueError: raise HTTPError(http.BAD_REQUEST)
def wrapped(*args, **kwargs): response = None target = None guid = Guid.load(kwargs.get('guid')) if guid: target = getattr(guid, 'referent', None) else: _inject_nodes(kwargs) target = target or kwargs.get('node') kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs) response = check_contributor_auth(target, kwargs['auth'], include_public, include_view_only_anon) return response or func(*args, **kwargs)
def _update_comments_timestamp(auth, node, page=Comment.OVERVIEW, root_id=None): if node.is_contributor(auth.user): enqueue_postcommit_task(ban_url, (node, ), {}, celery=False, once_per_request=True) if root_id is not None: guid_obj = Guid.load(root_id) if guid_obj is not None: enqueue_postcommit_task(ban_url, (guid_obj.referent, ), {}, celery=False, once_per_request=True) # update node timestamp if page == Comment.OVERVIEW: root_id = node._id auth.user.comments_viewed_timestamp[root_id] = timezone.now() auth.user.save() return {root_id: auth.user.comments_viewed_timestamp[root_id].isoformat()} else: return {}
def test_nulling_out_guid(self, Factory): obj = Factory() guid = Guid.load(obj._id) obj.guid = None obj.save() obj.refresh_from_db() # queryset cache returns the old version guid.refresh_from_db() assert obj.guid != guid assert guid.guid != obj.guid.guid
def remove_duplicates(duplicate_array, file_type): """ :param duplicate_array, expecting an array of dictionaries of format [{'guid_to_repoint': guid, 'to_remove': file__id, 'preserving': file__id}] """ for duplicate in duplicate_array: guid = Guid.load(duplicate['guid_to_repoint']) preserving = BaseFileNode.objects.get(_id=duplicate['preserving']) to_remove = BaseFileNode.objects.get(_id=duplicate['to_remove']) if guid: guid.referent = preserving guid.save() to_remove.delete() logger.info('Duplicates removed of type {}'.format(file_type))
def wrapped(*args, **kwargs): response = None target = None guid = Guid.load(kwargs.get('guid')) if guid: target = getattr(guid, 'referent', None) else: _inject_nodes(kwargs) target = target or kwargs.get('node') kwargs['auth'] = Auth.from_kwargs(request.args.to_dict(), kwargs) response = check_contributor_auth(target, kwargs['auth'], include_public, include_view_only_anon, include_groups) return response or func(*args, **kwargs)
def _build(cls, target_class, *args, **kwargs): node = kwargs.pop('node', None) or NodeFactory() user = kwargs.pop('user', None) or node.creator target = kwargs.pop('target', None) or Guid.load(node._id) content = kwargs.pop('content', None) or 'Test comment.' instance = target_class( node=node, user=user, target=target, content=content, *args, **kwargs ) if isinstance(target.referent, target_class): instance.root_target = target.referent.root_target else: instance.root_target = target return instance