def setUp(self):
        super(LinkedRegistrationsTestCase, self).setUp()
        self.mock_archive = mock.patch('website.archiver.tasks.archive')

        self.non_contributor = AuthUserFactory()
        self.read_contributor = AuthUserFactory()
        self.rw_contributor = AuthUserFactory()
        self.admin_contributor = AuthUserFactory()

        self.public_linked_registration = RegistrationFactory(is_public=True, creator=self.rw_contributor)
        self.private_linked_registration = RegistrationFactory(is_public=False, creator=self.rw_contributor)

        self.mock_archive.start()

        public_node = NodeFactory(creator=self.admin_contributor, is_public=True)
        public_node.add_contributor(self.rw_contributor, auth=Auth(self.admin_contributor))
        public_node.add_contributor(self.read_contributor, permissions=['read'], auth=Auth(self.admin_contributor))
        public_node.add_pointer(self.public_linked_registration, auth=Auth(self.admin_contributor))
        public_node.add_pointer(self.private_linked_registration, auth=Auth(self.rw_contributor))
        public_node.save()
        self.public_registration = public_node.register_node(get_default_metaschema(), Auth(self.admin_contributor), '', None)
        self.public_registration.is_public = True
        self.public_registration.save()

        private_node = NodeFactory(creator=self.admin_contributor)
        private_node.add_contributor(self.rw_contributor, auth=Auth(self.admin_contributor))
        private_node.add_contributor(self.read_contributor, permissions=['read'], auth=Auth(self.admin_contributor))
        private_node.add_pointer(self.public_linked_registration, auth=Auth(self.admin_contributor))
        private_node.add_pointer(self.private_linked_registration, auth=Auth(self.rw_contributor))
        private_node.save()
        self.private_registration = private_node.register_node(get_default_metaschema(), Auth(self.admin_contributor), '', None)
Ejemplo n.º 2
0
    def test_s3_set_bucket_registered(self):
        registration = self.project.register_node(get_default_metaschema(), self.consolidated_auth, "", "")

        url = registration.api_url_for("s3_post_node_settings")
        res = self.app.post_json(url, {"s3_bucket": "hammertofall"}, auth=self.user.auth, expect_errors=True)

        assert_equal(res.status_code, http.BAD_REQUEST)
Ejemplo n.º 3
0
 def test_does_not_get_copied_to_registrations(self, mock_archive):
     registration = self.project.register_node(
         schema=get_default_metaschema(),
         auth=Auth(user=self.project.creator),
         data='hodor',
     )
     assert_false(registration.has_addon('gitlab'))
Ejemplo n.º 4
0
 def test_does_not_get_copied_to_registrations(self, mock_errors, mock_archive):
     registration = self.node.register_node(
         schema=get_default_metaschema(),
         auth=Auth(user=self.node.creator),
         data='hodor'
     )
     assert_false(registration.has_addon('figshare'))
Ejemplo n.º 5
0
 def test_copied_from_id_trashed(self, mock_archive):
     file_node = self.get_test_file()
     second_file_node = self.get_second_test_file()
     file_node.copied_from = second_file_node
     self.project.register_node(schema=get_default_metaschema(), auth=Auth(self.user), data=None)
     trashed_node = second_file_node.delete()
     assert_false(trashed_node.copied_from)
Ejemplo n.º 6
0
    def test_archived_from_url_without_copied_from(self, mock_archive):
        file_node = self.get_test_file()

        registered_node = self.project.register_node(
            schema=get_default_metaschema(),
            auth=Auth(self.user),
            data=None,
        )
        archived_from_url = views.get_archived_from_url(registered_node, file_node)
        assert_false(archived_from_url)
Ejemplo n.º 7
0
 def test_copied_from_id_trashed(self, mock_archive):
     file_node = self.get_test_file()
     second_file_node = self.get_second_test_file()
     file_node.copied_from = second_file_node
     self.project.register_node(
         schema=get_default_metaschema(),
         auth=Auth(self.user),
         data=None,
     )
     trashed_node = second_file_node.delete()
     assert_false(trashed_node.copied_from)
Ejemplo n.º 8
0
    def test_archived_from_url_without_copied_from(self, mock_archive):
        file_node = self.get_test_file()

        registered_node = self.project.register_node(
            schema=get_default_metaschema(),
            auth=Auth(self.user),
            data=None,
        )
        archived_from_url = views.get_archived_from_url(
            registered_node, file_node)
        assert_false(archived_from_url)
Ejemplo n.º 9
0
    def test_s3_set_bucket_registered(self):
        registration = self.project.register_node(
            get_default_metaschema(), Auth(self.user), DraftRegistrationFactory(branched_from=self.project), ''
        )

        url = registration.api_url_for('s3_set_config')
        res = self.app.put_json(
            url, {'s3_bucket': 'hammertofall'}, auth=self.user.auth,
            expect_errors=True,
        )

        assert_equal(res.status_code, http_status.HTTP_400_BAD_REQUEST)
Ejemplo n.º 10
0
    def test_s3_set_bucket_registered(self):
        registration = self.project.register_node(
            get_default_metaschema(), Auth(self.user), '', ''
        )

        url = registration.api_url_for('s3_set_config')
        res = self.app.put_json(
            url, {'s3_bucket': 'hammertofall'}, auth=self.user.auth,
            expect_errors=True,
        )

        assert_equal(res.status_code, http.BAD_REQUEST)
Ejemplo n.º 11
0
    def test_s3compat_set_bucket_registered(self):
        registration = self.project.register_node(
            get_default_metaschema(), Auth(self.user), '', ''
        )

        url = registration.api_url_for('s3compat_set_config')
        res = self.app.put_json(
            url, {'s3compat_bucket': 'hammertofall'}, auth=self.user.auth,
            expect_errors=True,
        )

        assert_equal(res.status_code, http.BAD_REQUEST)
Ejemplo n.º 12
0
    def test_archived_from_url(self, mock_archive):
        file_node = self.get_test_file()
        second_file_node = self.get_second_test_file()
        file_node.copied_from = second_file_node

        registered_node = self.project.register_node(schema=get_default_metaschema(), auth=Auth(self.user), data=None)

        archived_from_url = views.get_archived_from_url(registered_node, file_node)
        view_url = self.project.web_url_for(
            "addon_view_or_download_file", provider=file_node.provider, path=file_node.copied_from._id
        )
        assert_true(archived_from_url)
        assert_urls_equal(archived_from_url, view_url)
Ejemplo n.º 13
0
    def test_s3_set_bucket_registered(self):
        registration = self.project.register_node(get_default_metaschema(),
                                                  self.consolidated_auth, '',
                                                  '')

        url = registration.api_url_for('s3_post_node_settings')
        res = self.app.post_json(
            url,
            {'s3_bucket': 'hammertofall'},
            auth=self.user.auth,
            expect_errors=True,
        )

        assert_equal(res.status_code, http.BAD_REQUEST)
Ejemplo n.º 14
0
    def test_archived_from_url(self, mock_archive):
        file_node = self.get_test_file()
        second_file_node = self.get_second_test_file()
        file_node.copied_from = second_file_node

        registered_node = self.project.register_node(
            schema=get_default_metaschema(),
            auth=Auth(self.user),
            data=None,
        )

        archived_from_url = views.get_archived_from_url(registered_node, file_node)
        view_url = self.project.web_url_for('addon_view_or_download_file', provider=file_node.provider, path=file_node.copied_from._id)
        assert_true(archived_from_url)
        assert_urls_equal(archived_from_url, view_url)
Ejemplo n.º 15
0
    def test_link_repo_registration(self, mock_branches):
        bitbucket_mock = self.bitbucket
        mock_branches.return_value = bitbucket_mock.branches.return_value

        registration = self.project.register_node(
            schema=get_default_metaschema(),
            auth=self.consolidated_auth,
            data='')

        url = registration.api_url + 'bitbucket/settings/'
        res = self.app.post_json(url, {
            'bitbucket_user': '******',
            'bitbucket_repo': 'night at the opera',
        },
                                 auth=self.auth,
                                 expect_errors=True).maybe_follow()

        assert_equal(res.status_code, 400)
Ejemplo n.º 16
0
    def test_registration_wiki_pages_created_pre_registration_get_cloned(self):
        project = self.set_up_project_with_wiki_page()
        registration = project.register_node(get_default_metaschema(), Auth(self.user), '', None)
        # reset wiki pages for test
        registration.wiki_pages_versions = project.wiki_pages_versions
        registration.wiki_pages_current = project.wiki_pages_current
        registration.save()

        main()
        registration.reload()
        wiki_versions = registration.wiki_pages_versions[self.wiki.page_name]

        current_wiki = NodeWikiPage.load(registration.wiki_pages_current[self.current_wiki.page_name])
        assert_equal(current_wiki.node, registration)
        assert_not_equal(current_wiki._id, self.current_wiki._id)

        wiki_version = NodeWikiPage.load(wiki_versions[0])
        assert_equal(wiki_version.node, registration)
        assert_not_equal(wiki_version._id, self.current_wiki._id)
Ejemplo n.º 17
0
    def test_registration_wiki_pages_created_pre_registration_get_cloned(self):
        project = self.set_up_project_with_wiki_page()
        registration = project.register_node(get_default_metaschema(), Auth(self.user), "", None)
        # reset wiki pages for test
        registration.wiki_pages_versions = project.wiki_pages_versions
        registration.wiki_pages_current = project.wiki_pages_current
        registration.save()

        main()
        registration.reload()
        wiki_versions = registration.wiki_pages_versions[self.wiki.page_name]

        current_wiki = NodeWikiPage.load(registration.wiki_pages_current[self.current_wiki.page_name])
        assert_equal(current_wiki.node, registration)
        assert_not_equal(current_wiki._id, self.current_wiki._id)

        wiki_version = NodeWikiPage.load(wiki_versions[0])
        assert_equal(wiki_version.node, registration)
        assert_not_equal(wiki_version._id, self.current_wiki._id)
    def test_link_repo_registration(self, mock_branches):

        mock_branches.return_value = [
            Branch.from_json(
                dumps({
                    'name': 'master',
                    'commit': {
                        'sha':
                        '6dcb09b5b57875f334f61aebed695e2e4193db5e',
                        'url':
                        'https://api.github.com/repos/octocat/Hello-World/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc',
                    }
                })),
            Branch.from_json(
                dumps({
                    'name': 'develop',
                    'commit': {
                        'sha':
                        '6dcb09b5b57875asdasedawedawedwedaewdwdass',
                        'url':
                        'https://api.github.com/repos/octocat/Hello-World/commits/cdcb09b5b57875asdasedawedawedwedaewdwdass',
                    }
                }))
        ]

        registration = self.project.register_node(
            schema=get_default_metaschema(),
            auth=self.consolidated_auth,
            draft_registration=DraftRegistrationFactory(
                branched_from=self.project))

        url = registration.api_url + 'github/settings/'
        res = self.app.post_json(url, {
            'github_user': '******',
            'github_repo': 'night at the opera',
        },
                                 auth=self.auth,
                                 expect_errors=True).maybe_follow()

        assert_equal(res.status_code, 400)
Ejemplo n.º 19
0
    def test_link_repo_registration(self, mock_branches):
        bitbucket_mock = self.bitbucket
        mock_branches.return_value = bitbucket_mock.branches.return_value

        registration = self.project.register_node(
            schema=get_default_metaschema(),
            auth=self.consolidated_auth,
            data=''
        )

        url = registration.api_url + 'bitbucket/settings/'
        res = self.app.post_json(
            url,
            {
                'bitbucket_user': '******',
                'bitbucket_repo': 'night at the opera',
            },
            auth=self.auth,
            expect_errors=True
        ).maybe_follow()

        assert_equal(res.status_code, 400)
Ejemplo n.º 20
0
    def test_link_repo_registration(self, mock_branches):

        mock_branches.return_value = [
            Branch.from_json(dumps({
                'name': 'master',
                'commit': {
                    'sha': '6dcb09b5b57875f334f61aebed695e2e4193db5e',
                    'url': 'https://api.gitlab.com/repos/octocat/Hello-World/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc',
                }
            })),
            Branch.from_json(dumps({
                'name': 'develop',
                'commit': {
                    'sha': '6dcb09b5b57875asdasedawedawedwedaewdwdass',
                    'url': 'https://api.gitlab.com/repos/octocat/Hello-World/commits/cdcb09b5b57875asdasedawedawedwedaewdwdass',
                }
            }))
        ]

        registration = self.project.register_node(
            schema=get_default_metaschema(),
            auth=self.consolidated_auth,
            data=''
        )

        url = registration.api_url + 'gitlab/settings/'
        res = self.app.post_json(
            url,
            {
                'gitlab_user': '******',
                'gitlab_repo': 'night at the opera',
            },
            auth=self.auth,
            expect_errors=True
        ).maybe_follow()

        assert_equal(res.status_code, 400)
Ejemplo n.º 21
0
 def test_quickfiles_cannot_be_registered(self, quickfiles, auth):
     with pytest.raises(NodeStateError):
         quickfiles.register_node(get_default_metaschema(), auth, '', None)
Ejemplo n.º 22
0
    def _create(cls,
                target_class,
                project=None,
                is_public=False,
                schema=None,
                data=None,
                archive=False,
                embargo=None,
                registration_approval=None,
                retraction=None,
                *args,
                **kwargs):
        save_kwargs(**kwargs)
        user = None
        if project:
            user = project.creator
        user = kwargs.get('user') or kwargs.get(
            'creator') or user or UserFactory()
        kwargs['creator'] = user
        # Original project to be registered
        project = project or target_class(*args, **kwargs)
        if user._id not in project.permissions:
            project.add_contributor(
                contributor=user,
                permissions=permissions.CREATOR_PERMISSIONS,
                log=False,
                save=False)
        project.save()

        # Default registration parameters
        schema = schema or get_default_metaschema()
        data = data or {'some': 'data'}
        auth = Auth(user=user)
        register = lambda: project.register_node(
            schema=schema, auth=auth, data=data)

        def add_approval_step(reg):
            if embargo:
                reg.embargo = embargo
            elif registration_approval:
                reg.registration_approval = registration_approval
            elif retraction:
                reg.retraction = retraction
            else:
                reg.require_approval(reg.creator)
            reg.save()
            reg.sanction.add_authorizer(reg.creator)
            reg.sanction.save()

        if archive:
            reg = register()
            add_approval_step(reg)
        else:
            with patch('framework.tasks.handlers.enqueue_task'):
                reg = register()
                add_approval_step(reg)
            with patch.object(reg.archive_job, 'archive_tree_finished',
                              Mock(return_value=True)):
                reg.archive_job.status = ARCHIVER_SUCCESS
                reg.archive_job.save()
                reg.sanction.state = Sanction.APPROVED
                reg.sanction.save()
        ArchiveJob(
            src_node=project,
            dst_node=reg,
            initiator=user,
        )
        if is_public:
            reg.is_public = True
        reg.save()
        return reg
Ejemplo n.º 23
0
import mock
import datetime

from django.http import HttpRequest
from nose import SkipTest
from nose.tools import assert_equal, assert_not_equal, assert_in

from framework.auth import Auth
from framework.celery_tasks.handlers import celery_teardown_request

from website.archiver import ARCHIVER_SUCCESS
from website.archiver import listeners as archiver_listeners
from website.project.sanctions import Sanction

from tests.base import get_default_metaschema
DEFAULT_METASCHEMA = get_default_metaschema()


def requires_module(module):
    def decorator(fn):
        @functools.wraps(fn)
        def wrapper(*args, **kwargs):
            try:
                __import__(module)
            except ImportError:
                raise SkipTest()
            return fn(*args, **kwargs)

        return wrapper

    return decorator
Ejemplo n.º 24
0
def mock_archive(project,
                 schema=None,
                 auth=None,
                 data=None,
                 parent=None,
                 embargo=False,
                 embargo_end_date=None,
                 retraction=False,
                 justification=None,
                 autoapprove_retraction=False,
                 autocomplete=True,
                 autoapprove=False):
    """ A context manager for registrations. When you want to call Node#register_node in
    a test but do not want to deal with any of this side effects of archiver, this
    helper allows for creating a registration in a safe fashion.

    :param bool embargo: embargo the registration (rather than RegistrationApproval)
    :param bool autocomplete: automatically finish archival?
    :param bool autoapprove: automatically approve registration approval?
    :param bool retraction: retract the registration?
    :param str justification: a justification for the retraction
    :param bool autoapprove_retraction: automatically approve retraction?

    Example use:

    project = ProjectFactory()
    with mock_archive(project) as registration:
        assert_true(registration.is_registration)
        assert_true(registration.archiving)
        assert_true(registration.is_pending_registration)

    with mock_archive(project, autocomplete=True) as registration:
        assert_true(registration.is_registration)
        assert_false(registration.archiving)
        assert_true(registration.is_pending_registration)

    with mock_archive(project, autocomplete=True, autoapprove=True) as registration:
        assert_true(registration.is_registration)
        assert_false(registration.archiving)
        assert_false(registration.is_pending_registration)
    """
    schema = schema or get_default_metaschema()
    auth = auth or Auth(project.creator)
    data = data or ''

    with mock.patch('framework.celery_tasks.handlers.enqueue_task'):
        registration = project.register_node(
            schema=schema,
            auth=auth,
            data=data,
            parent=parent,
        )
    if embargo:
        embargo_end_date = embargo_end_date or (timezone.now() +
                                                datetime.timedelta(days=20))
        registration.root.embargo_registration(project.creator,
                                               embargo_end_date)
    else:
        registration.root.require_approval(project.creator)
    if autocomplete:
        root_job = registration.root.archive_job
        root_job.status = ARCHIVER_SUCCESS
        root_job.sent = False
        root_job.done = True
        root_job.save()
        sanction = registration.root.sanction
        with contextlib.nested(
                mock.patch.object(root_job, 'archive_tree_finished',
                                  mock.Mock(return_value=True)),
                mock.patch('website.archiver.tasks.archive_success.delay',
                           mock.Mock())):
            archiver_listeners.archive_callback(registration)
    if autoapprove:
        sanction = registration.root.sanction
        sanction.state = Sanction.APPROVED
        # save or _on_complete no worky
        sanction.save()
        sanction._on_complete(project.creator)
        sanction.save()

    if retraction:
        justification = justification or "Because reasons"
        retraction = registration.retract_registration(
            project.creator, justification=justification)
        if autoapprove_retraction:
            retraction.state = Sanction.APPROVED
            retraction._on_complete(project.creator)
        retraction.save()
        registration.save()
    yield registration
Ejemplo n.º 25
0
    def _create(cls, target_class, project=None, is_public=False,
                schema=None, data=None,
                archive=False, embargo=None, registration_approval=None, retraction=None,
                *args, **kwargs):
        save_kwargs(**kwargs)
        user = None
        if project:
            user = project.creator
        user = kwargs.get('user') or kwargs.get('creator') or user or UserFactory()
        kwargs['creator'] = user
        # Original project to be registered
        project = project or target_class(*args, **kwargs)
        if user._id not in project.permissions:
            project.add_contributor(
                contributor=user,
                permissions=permissions.CREATOR_PERMISSIONS,
                log=False,
                save=False
            )
        project.save()

        # Default registration parameters
        schema = schema or get_default_metaschema()
        data = data or {'some': 'data'}
        auth = Auth(user=user)
        register = lambda: project.register_node(
            schema=schema,
            auth=auth,
            data=data
        )

        def add_approval_step(reg):
            if embargo:
                reg.embargo = embargo
            elif registration_approval:
                reg.registration_approval = registration_approval
            elif retraction:
                reg.retraction = retraction
            else:
                reg.require_approval(reg.creator)
            reg.save()
            reg.sanction.add_authorizer(reg.creator, reg)
            reg.sanction.save()

        if archive:
            reg = register()
            add_approval_step(reg)
        else:
            with patch('framework.celery_tasks.handlers.enqueue_task'):
                reg = register()
                add_approval_step(reg)
            with patch.object(reg.archive_job, 'archive_tree_finished', Mock(return_value=True)):
                reg.archive_job.status = ARCHIVER_SUCCESS
                reg.archive_job.save()
                reg.sanction.state = Sanction.APPROVED
                reg.sanction.save()
        ArchiveJob(
            src_node=project,
            dst_node=reg,
            initiator=user,
        )
        if is_public:
            reg.is_public = True
        reg.save()
        return reg
Ejemplo n.º 26
0
import mock
import datetime

from django.http import HttpRequest
from nose import SkipTest
from nose.tools import assert_equal, assert_not_equal, assert_in

from framework.auth import Auth
from framework.celery_tasks.handlers import celery_teardown_request

from website.archiver import ARCHIVER_SUCCESS
from website.archiver import listeners as archiver_listeners
from website.project.sanctions import Sanction

from tests.base import get_default_metaschema
DEFAULT_METASCHEMA = get_default_metaschema()

def requires_module(module):
    def decorator(fn):
        @functools.wraps(fn)
        def wrapper(*args, **kwargs):
            try:
                __import__(module)
            except ImportError:
                raise SkipTest()
            return fn(*args, **kwargs)
        return wrapper
    return decorator


def assert_logs(log_action, node_key, index=-1):
Ejemplo n.º 27
0
def mock_archive(project, schema=None, auth=None, data=None, parent=None,
                 embargo=False, embargo_end_date=None,
                 retraction=False, justification=None, autoapprove_retraction=False,
                 autocomplete=True, autoapprove=False):
    """ A context manager for registrations. When you want to call Node#register_node in
    a test but do not want to deal with any of this side effects of archiver, this
    helper allows for creating a registration in a safe fashion.

    :param bool embargo: embargo the registration (rather than RegistrationApproval)
    :param bool autocomplete: automatically finish archival?
    :param bool autoapprove: automatically approve registration approval?
    :param bool retraction: retract the registration?
    :param str justification: a justification for the retraction
    :param bool autoapprove_retraction: automatically approve retraction?

    Example use:

    project = ProjectFactory()
    with mock_archive(project) as registration:
        assert_true(registration.is_registration)
        assert_true(registration.archiving)
        assert_true(registration.is_pending_registration)

    with mock_archive(project, autocomplete=True) as registration:
        assert_true(registration.is_registration)
        assert_false(registration.archiving)
        assert_true(registration.is_pending_registration)

    with mock_archive(project, autocomplete=True, autoapprove=True) as registration:
        assert_true(registration.is_registration)
        assert_false(registration.archiving)
        assert_false(registration.is_pending_registration)
    """
    schema = schema or get_default_metaschema()
    auth = auth or Auth(project.creator)
    data = data or ''

    with mock.patch('framework.celery_tasks.handlers.enqueue_task'):
        registration = project.register_node(
            schema=schema,
            auth=auth,
            data=data,
            parent=parent,
        )
    if embargo:
        embargo_end_date = embargo_end_date or (
            timezone.now() + datetime.timedelta(days=20)
        )
        registration.root.embargo_registration(
            project.creator,
            embargo_end_date
        )
    else:
        registration.root.require_approval(project.creator)
    if autocomplete:
        root_job = registration.root.archive_job
        root_job.status = ARCHIVER_SUCCESS
        root_job.sent = False
        root_job.done = True
        root_job.save()
        sanction = registration.root.sanction
        with contextlib.nested(
            mock.patch.object(root_job, 'archive_tree_finished', mock.Mock(return_value=True)),
            mock.patch('website.archiver.tasks.archive_success.delay', mock.Mock())
        ):
            archiver_listeners.archive_callback(registration)
    if autoapprove:
        sanction = registration.root.sanction
        sanction.state = Sanction.APPROVED
        # save or _on_complete no worky
        sanction.save()
        sanction._on_complete(project.creator)
        sanction.save()

    if retraction:
        justification = justification or "Because reasons"
        retraction = registration.retract_registration(project.creator, justification=justification)
        if autoapprove_retraction:
            retraction.state = Sanction.APPROVED
            retraction._on_complete(project.creator)
        retraction.save()
        registration.save()
    yield registration
Ejemplo n.º 28
0
 def test_node_register_page_registration(self, mock_archive):
     reg = self.node.register_node(get_default_metaschema(), self.auth, '', None)
     url = reg.web_url_for('node_register_page')
     res = self.app.get(url, auth=self.user.auth)
     assert_equal(res.status_code, http.OK)
Ejemplo n.º 29
0
 def test_quickfiles_cannot_be_registered(self, quickfiles, auth):
     with pytest.raises(NodeStateError):
         quickfiles.register_node(get_default_metaschema(), auth, factories.DraftRegistrationFactory(branched_from=quickfiles), None)
Ejemplo n.º 30
0
 def test_view_project_embed_registrations_includes_contribution_count(self, mock_archive):
     self.project.register_node(get_default_metaschema(), Auth(user=self.project.creator), '', None)
     data = _view_project(node=self.project, auth=Auth(self.project.creator), embed_registrations=True)
     assert_is_not_none(data['node']['registrations'][0]['nlogs'])