class TestNodeLinkDetail(ApiTestCase):

    def setUp(self):
        super(TestNodeLinkDetail, self).setUp()
        self.user = AuthUserFactory()
        self.private_project = ProjectFactory(creator=self.user, is_public=False)
        self.pointer_project = ProjectFactory(creator=self.user, is_public=False)
        self.pointer = self.private_project.add_pointer(self.pointer_project, auth=Auth(self.user), save=True)
        self.private_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.private_project._id, self.pointer._id)

        self.user_two = AuthUserFactory()

        self.public_project = ProjectFactory(creator=self.user, is_public=True)
        self.public_pointer_project = ProjectFactory(is_public=True)
        self.public_pointer = self.public_project.add_pointer(self.public_pointer_project,
                                                              auth=Auth(self.user),
                                                              save=True)
        self.public_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.public_project._id, self.public_pointer._id)

    def test_returns_embedded_public_node_pointer_detail_logged_out(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        res_json = res.json['data']
        embedded = res_json['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.public_pointer_project._id)

    def test_returns_public_node_pointer_detail_logged_in(self):
        res = self.app.get(self.public_url, auth=self.user.auth)
        res_json = res.json['data']
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        embedded = res_json['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.public_pointer_project._id)

    def test_returns_private_node_pointer_detail_logged_out(self):
        res = self.app.get(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    def test_returns_private_node_pointer_detail_logged_in_contributor(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        res_json = res.json['data']
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        embedded = res_json['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.pointer_project._id)

    def test_returns_private_node_pointer_detail_logged_in_non_contributor(self):
        res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    def test_self_link_points_to_node_link_detail_url(self):
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        url = res.json['data']['links']['self']
        assert_in(self.public_url, url)
Exemple #2
0
    def test_view_project_pointer_count_excludes_folders(self):
        pointer_project = ProjectFactory(is_public=True)  # project that points to another project
        pointed_project = self.node  # project that other project points to
        pointer_project.add_pointer(pointed_project, Auth(pointer_project.creator), save=True)

        # Project is in a organizer collection
        folder = CollectionFactory(creator=pointed_project.creator)
        folder.add_pointer(pointed_project, Auth(pointed_project.creator), save=True)

        result = _view_project(pointed_project, Auth(pointed_project.creator))
        # pointer_project is included in count, but not folder
        assert_equal(result["node"]["points"], 1)
Exemple #3
0
    def test_view_project_pointer_count_excludes_folders(self):
        user = UserFactory()
        pointer_project = ProjectFactory(is_public=True)  # project that points to another project
        pointed_project = ProjectFactory(creator=user)  # project that other project points to
        pointer_project.add_pointer(pointed_project, Auth(pointer_project.creator), save=True)

        # Project is in a dashboard folder
        folder = FolderFactory(creator=pointed_project.creator)
        folder.add_pointer(pointed_project, Auth(pointed_project.creator), save=True)

        result = _view_project(pointed_project, Auth(pointed_project.creator))
        # pointer_project is included in count, but not folder
        assert_equal(result['node']['points'], 1)
Exemple #4
0
    def test_view_project_pointer_count_excludes_folders(self):
        user = UserFactory()
        pointer_project = ProjectFactory(is_public=True)  # project that points to another project
        pointed_project = ProjectFactory(creator=user)  # project that other project points to
        pointer_project.add_pointer(pointed_project, Auth(pointer_project.creator), save=True)

        # Project is in a dashboard folder
        folder = FolderFactory(creator=pointed_project.creator)
        folder.add_pointer(pointed_project, Auth(pointed_project.creator), save=True)

        result = _view_project(pointed_project, Auth(pointed_project.creator))
        # pointer_project is included in count, but not folder
        assert_equal(result['node']['points'], 1)
Exemple #5
0
class TestExplorePublicActivity(OsfTestCase):
    def setUp(self):
        super(TestExplorePublicActivity, self).setUp()
        self.project = ProjectFactory(is_public=True)
        self.registration = RegistrationFactory(project=self.project)
        self.private_project = ProjectFactory(title="Test private project")

        # Add project to new and noteworthy projects
        self.new_and_noteworthy_links_node = ProjectFactory()
        self.new_and_noteworthy_links_node._id = settings.NEW_AND_NOTEWORTHY_LINKS_NODE
        self.new_and_noteworthy_links_node.add_pointer(
            self.project,
            auth=Auth(self.new_and_noteworthy_links_node.creator),
            save=True)

    @mock.patch('website.discovery.views.KeenClient')
    def test_new_and_noteworthy_and_registrations_show_in_explore_activity(
            self, mock_client):

        mock_client.count.return_value = {
            'result': [{
                'result': 5,
                'node.id': self.project._id
            }, {
                'result': 5,
                'node.id': self.registration._id
            }]
        }

        mock_client.count_unique.return_value = {
            'result': [{
                'result': 2,
                'node.id': self.project._id
            }, {
                'result': 2,
                'node.id': self.registration._id
            }]
        }

        url = self.project.web_url_for('activity')
        res = self.app.get(url)

        assert_in(str(self.project.title), res)
        assert_in(str(self.project.date_created.date()), res)
        assert_in(str(self.registration.title), res)
        assert_in(str(self.registration.registered_date.date()), res)
        assert_not_in(str(self.private_project.title), res)
Exemple #6
0
    def test_view_project_pointer_count_excludes_folders(self):
        pointer_project = ProjectFactory(
            is_public=True)  # project that points to another project
        pointed_project = self.node  # project that other project points to
        pointer_project.add_pointer(pointed_project,
                                    Auth(pointer_project.creator),
                                    save=True)

        # Project is in a organizer collection
        folder = CollectionFactory(creator=pointed_project.creator)
        folder.add_pointer(pointed_project,
                           Auth(pointed_project.creator),
                           save=True)

        result = _view_project(pointed_project, Auth(pointed_project.creator))
        # pointer_project is included in count, but not folder
        assert_equal(result['node']['points'], 1)
Exemple #7
0
    def test_get_wiki_url_pointer_component(self):
        """Regression test for issues
        https://github.com/CenterForOpenScience/osf/issues/363 and
        https://github.com/CenterForOpenScience/openscienceframework.org/issues/574

        """
        user = UserFactory()
        pointed_node = NodeFactory(creator=user)
        project = ProjectFactory(creator=user)
        auth = Auth(user=user)
        project.add_pointer(pointed_node, auth=auth, save=True)

        serialized = _serialize_wiki_toc(project, auth)
        assert_equal(
            serialized[0]['url'],
            pointed_node.web_url_for('project_wiki_view', wname='home', _guid=True)
        )
Exemple #8
0
    def test_get_wiki_url_pointer_component(self):
        """Regression test for issues
        https://github.com/CenterForOpenScience/osf/issues/363 and
        https://github.com/CenterForOpenScience/openscienceframework.org/issues/574

        """
        user = UserFactory()
        pointed_node = NodeFactory(creator=user)
        project = ProjectFactory(creator=user)
        auth = Auth(user=user)
        project.add_pointer(pointed_node, auth=auth, save=True)

        serialized = _serialize_wiki_toc(project, auth)
        assert_equal(
            serialized[0]['url'],
            pointed_node.web_url_for('project_wiki_page', wname='home', _guid=True)
        )
Exemple #9
0
    def test_get_node_name(self):
        user = UserFactory()
        auth = Auth(user=user)
        another_user = UserFactory()
        another_auth = Auth(user=another_user)

        # Public (Can View)
        public_project = ProjectFactory(is_public=True)
        collector = rubeus.NodeFileCollector(node=public_project,
                                             auth=another_auth)
        node_name = u'{0}: {1}'.format(
            public_project.project_or_component.capitalize(),
            sanitize.unescape_entities(public_project.title))
        assert_equal(collector._get_node_name(public_project), node_name)

        # Private  (Can't View)
        registration_private = RegistrationFactory(creator=user)
        registration_private.is_public = False
        registration_private.save()
        collector = rubeus.NodeFileCollector(node=registration_private,
                                             auth=another_auth)
        assert_equal(collector._get_node_name(registration_private),
                     u'Private Registration')

        content = ProjectFactory(creator=user)
        node = ProjectFactory(creator=user)

        forked_private = node.fork_node(auth=auth)
        forked_private.is_public = False
        forked_private.save()
        collector = rubeus.NodeFileCollector(node=forked_private,
                                             auth=another_auth)
        assert_equal(collector._get_node_name(forked_private), u'Private Fork')

        pointer_private = node.add_pointer(content, auth=auth)
        pointer_private.is_public = False
        pointer_private.save()
        collector = rubeus.NodeFileCollector(node=pointer_private,
                                             auth=another_auth)
        assert_equal(collector._get_node_name(pointer_private),
                     u'Private Link')

        private_project = ProjectFactory(is_public=False)
        collector = rubeus.NodeFileCollector(node=private_project,
                                             auth=another_auth)
        assert_equal(collector._get_node_name(private_project),
                     u'Private Component')

        private_node = NodeFactory(is_public=False)
        collector = rubeus.NodeFileCollector(node=private_node,
                                             auth=another_auth)
        assert_equal(collector._get_node_name(private_node),
                     u'Private Component')
Exemple #10
0
class TestExplorePublicActivity(OsfTestCase):

    def setUp(self):
        super(TestExplorePublicActivity, self).setUp()
        self.project = ProjectFactory(is_public=True)
        self.registration = RegistrationFactory(project=self.project)
        self.private_project = ProjectFactory(title="Test private project")
        self.popular_project = ProjectFactory(is_public=True)
        self.popular_registration = RegistrationFactory(project=self.project)

        # Add project to new and noteworthy projects
        self.new_and_noteworthy_links_node = ProjectFactory()
        self.new_and_noteworthy_links_node._id = settings.NEW_AND_NOTEWORTHY_LINKS_NODE
        self.new_and_noteworthy_links_node.add_pointer(self.project, auth=Auth(self.new_and_noteworthy_links_node.creator), save=True)

        # Set up popular projects and registrations
        self.popular_links_node = ProjectFactory()
        self.popular_links_node._id = settings.POPULAR_LINKS_NODE
        self.popular_links_node.add_pointer(self.popular_project, auth=Auth(self.popular_links_node.creator), save=True)

        self.popular_links_registrations = ProjectFactory()
        self.popular_links_registrations._id = settings.POPULAR_LINKS_REGISTRATIONS
        self.popular_links_registrations.add_pointer(self.popular_registration, auth=Auth(self.popular_links_registrations.creator), save=True)

    def tearDown(self):
        super(TestExplorePublicActivity, self).tearDown()
        Node.remove()

    def test_explore_page_loads_when_settings_not_configured(self):

        old_settings_values = settings.POPULAR_LINKS_NODE, settings.NEW_AND_NOTEWORTHY_LINKS_NODE, settings.POPULAR_LINKS_REGISTRATIONS

        settings.POPULAR_LINKS_NODE = 'notanode'
        settings.NEW_AND_NOTEWORTHY_LINKS_NODE = 'alsototallywrong'
        settings.POPULAR_LINKS_REGISTRATIONS = 'nopenope'

        url = self.project.web_url_for('activity')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

        settings.POPULAR_LINKS_NODE, settings.NEW_AND_NOTEWORTHY_LINKS_NODE, settings.POPULAR_LINKS_REGISTRATIONS = old_settings_values

    def test_new_and_noteworthy_and_popular_nodes_show_in_explore_activity(self):

        url = self.project.web_url_for('activity')
        res = self.app.get(url)

        # New and Noteworthy
        assert_in(str(self.project.title), res)
        assert_in(str(self.project.date_created.date()), res)
        assert_in(str(self.registration.title), res)
        assert_in(str(self.registration.registered_date.date()), res)
        assert_not_in(str(self.private_project.title), res)

        # Popular Projects and Registrations
        assert_in(str(self.popular_project.title), res)
        assert_in(str(self.popular_project.date_created.date()), res)
        assert_in(str(self.popular_registration.title), res)
        assert_in(str(self.popular_registration.registered_date.date()), res)
Exemple #11
0
    def test_get_node_name(self):
        user = UserFactory()
        auth = Auth(user=user)
        another_user = UserFactory()
        another_auth = Auth(user=another_user)

        # Public (Can View)
        public_project = ProjectFactory(is_public=True)
        collector = rubeus.NodeFileCollector(node=public_project, auth=another_auth)
        node_name = u"{0}: {1}".format(
            public_project.project_or_component.capitalize(), sanitize.unescape_entities(public_project.title)
        )
        assert_equal(collector._get_node_name(public_project), node_name)

        # Private  (Can't View)
        registration_private = RegistrationFactory(creator=user)
        registration_private.is_public = False
        registration_private.save()
        collector = rubeus.NodeFileCollector(node=registration_private, auth=another_auth)
        assert_equal(collector._get_node_name(registration_private), u"Private Registration")

        content = ProjectFactory(creator=user)
        node = ProjectFactory(creator=user)

        forked_private = node.fork_node(auth=auth)
        forked_private.is_public = False
        forked_private.save()
        collector = rubeus.NodeFileCollector(node=forked_private, auth=another_auth)
        assert_equal(collector._get_node_name(forked_private), u"Private Fork")

        pointer_private = node.add_pointer(content, auth=auth)
        pointer_private.is_public = False
        pointer_private.save()
        collector = rubeus.NodeFileCollector(node=pointer_private, auth=another_auth)
        assert_equal(collector._get_node_name(pointer_private), u"Private Link")

        private_project = ProjectFactory(is_public=False)
        collector = rubeus.NodeFileCollector(node=private_project, auth=another_auth)
        assert_equal(collector._get_node_name(private_project), u"Private Component")

        private_node = NodeFactory(is_public=False)
        collector = rubeus.NodeFileCollector(node=private_node, auth=another_auth)
        assert_equal(collector._get_node_name(private_node), u"Private Component")
class TestNodeChildrenList(ApiTestCase):
    def setUp(self):
        super(TestNodeChildrenList, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory()
        self.project.add_contributor(self.user, permissions=[permissions.READ, permissions.WRITE])
        self.project.save()
        self.component = NodeFactory(parent=self.project, creator=self.user)
        self.pointer = ProjectFactory()
        self.project.add_pointer(self.pointer, auth=Auth(self.user), save=True)
        self.private_project_url = '/{}nodes/{}/children/'.format(API_BASE, self.project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project.save()
        self.public_component = NodeFactory(parent=self.public_project, creator=self.user, is_public=True)
        self.public_project_url = '/{}nodes/{}/children/'.format(API_BASE, self.public_project._id)

        self.user_two = AuthUserFactory()

    def test_node_children_list_does_not_include_pointers(self):
        res = self.app.get(self.private_project_url, auth=self.user.auth)
        assert_equal(len(res.json['data']), 1)

    def test_return_public_node_children_list_logged_out(self):
        res = self.app.get(self.public_project_url)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(len(res.json['data']), 1)
        assert_equal(res.json['data'][0]['id'], self.public_component._id)

    def test_return_public_node_children_list_logged_in(self):
        res = self.app.get(self.public_project_url, auth=self.user_two.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(len(res.json['data']), 1)
        assert_equal(res.json['data'][0]['id'], self.public_component._id)

    def test_return_private_node_children_list_logged_out(self):
        res = self.app.get(self.private_project_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert 'detail' in res.json['errors'][0]

    def test_return_private_node_children_list_logged_in_contributor(self):
        res = self.app.get(self.private_project_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(len(res.json['data']), 1)
        assert_equal(res.json['data'][0]['id'], self.component._id)

    def test_return_private_node_children_list_logged_in_non_contributor(self):
        res = self.app.get(self.private_project_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert 'detail' in res.json['errors'][0]

    def test_node_children_list_does_not_include_unauthorized_projects(self):
        private_component = NodeFactory(parent=self.project)
        res = self.app.get(self.private_project_url, auth=self.user.auth)
        assert_equal(len(res.json['data']), 1)

    def test_node_children_list_does_not_include_deleted(self):
        child_project = NodeFactory(parent=self.public_project, creator=self.user)
        child_project.save()

        res = self.app.get(self.public_project_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        ids = [node['id'] for node in res.json['data']]
        assert_in(child_project._id, ids)
        assert_equal(2, len(ids))

        child_project.is_deleted = True
        child_project.save()

        res = self.app.get(self.public_project_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        ids = [node['id'] for node in res.json['data']]
        assert_not_in(child_project._id, ids)
        assert_equal(1, len(ids))

    def test_node_children_list_does_not_include_node_links(self):
        pointed_to = ProjectFactory(is_public=True)

        self.public_project.add_pointer(pointed_to, auth=Auth(self.public_project.creator))

        res = self.app.get(self.public_project_url, auth=self.user.auth)
        ids = [node['id'] for node in res.json['data']]
        assert_in(self.public_component._id, ids)  # sanity check

        assert_equal(len(ids), len([e for e in self.public_project.nodes if e.primary]))
        assert_not_in(pointed_to._id, ids)

    def test_cannot_access_retracted_children(self):
        registration = RegistrationFactory(creator=self.user, project=self.public_project)
        retraction = RetractedRegistrationFactory(registration=registration, user=self.user)
        url = '/{}nodes/{}/children/'.format(API_BASE, registration._id)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)
class TestBulkDeleteNodeLinks(ApiTestCase):

    def setUp(self):
        super(TestBulkDeleteNodeLinks, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(creator=self.user, is_public=False)
        self.pointer_project = ProjectFactory(creator=self.user, is_public=True)
        self.pointer_project_two = ProjectFactory(creator=self.user, is_public=True)

        self.pointer = self.project.add_pointer(self.pointer_project, auth=Auth(self.user), save=True)
        self.pointer_two = self.project.add_pointer(self.pointer_project_two, auth=Auth(self.user), save=True)

        self.private_payload = {
              "data": [
                {"type": "node_links", "id": self.pointer._id},
                {"type": "node_links", "id": self.pointer_two._id}
              ]
            }

        self.private_url = '/{}nodes/{}/node_links/'.format(API_BASE, self.project._id)

        self.user_two = AuthUserFactory()

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project_two = ProjectFactory(is_public=True, creator=self.user)

        self.public_pointer = self.public_project.add_pointer(self.public_pointer_project,
                                                              auth=Auth(self.user),
                                                              save=True)
        self.public_pointer_two = self.public_project.add_pointer(self.public_pointer_project_two,
                                                              auth=Auth(self.user),
                                                              save=True)

        self.public_payload = {
              'data': [
                {'type': 'node_links', 'id': self.public_pointer._id},
                {'type': 'node_links', 'id': self.public_pointer_two._id}
              ]
            }

        self.public_url = '/{}nodes/{}/node_links/'.format(API_BASE, self.public_project._id)

    def test_bulk_delete_node_links_blank_request(self):
        res = self.app.delete_json_api(self.public_url, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)

    def test_bulk_delete_pointer_limits(self):
        res = self.app.delete_json_api(self.public_url, {'data': [self.public_payload['data'][0]] * 101},
                                       auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Bulk operation limit is 100, got 101.')
        assert_equal(res.json['errors'][0]['source']['pointer'], '/data')

    def test_bulk_delete_dict_inside_data(self):
        res = self.app.delete_json_api(self.public_url, {'data': {'id': self.public_project._id, 'type': 'node_links'}},
                                       auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Expected a list of items but got type "dict".')

    def test_bulk_delete_pointers_no_type(self):
        payload = {'data': [
            {'id': self.public_pointer._id},
            {'id': self.public_pointer_two._id}
        ]}
        res = self.app.delete_json_api(self.public_url, payload, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['source']['pointer'], "/data/type")

    def test_bulk_delete_pointers_incorrect_type(self):
        payload = {'data': [
            {'id': self.public_pointer._id, 'type': 'Incorrect type.'},
            {'id': self.public_pointer_two._id, 'type': 'Incorrect type.'}
        ]}
        res = self.app.delete_json_api(self.public_url, payload, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 409)

    def test_bulk_delete_pointers_no_id(self):
        payload = {'data': [
            {'type': 'node_links'},
            {'type': 'node_links'}
        ]}
        res = self.app.delete_json_api(self.public_url, payload, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['source']['pointer'], "/data/id")

    def test_bulk_delete_pointers_no_data(self):
        res = self.app.delete_json_api(self.public_url, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Request must contain array of resource identifier objects.')

    def test_bulk_delete_pointers_payload_is_empty_dict(self):
        res = self.app.delete_json_api(self.public_url, {}, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Request must include /data.')

    def test_cannot_delete_if_registration(self):
        registration = RegistrationFactory(project=self.public_project)

        url = '/{}nodes/{}/node_links/'.format(API_BASE, registration._id)

        res = self.app.delete_json_api(url, self.public_payload, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 404)

    def test_bulk_deletes_public_node_pointers_logged_out(self):
        res = self.app.delete_json_api(self.public_url, self.public_payload, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    def test_bulk_deletes_public_node_pointers_fails_if_bad_auth(self):
        node_count_before = len(self.public_project.nodes_pointer)
        res = self.app.delete_json_api(self.public_url, self.public_payload,
                                       auth=self.user_two.auth, expect_errors=True, bulk=True)
        # This is could arguably be a 405, but we don't need to go crazy with status codes
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])
        self.public_project.reload()
        assert_equal(node_count_before, len(self.public_project.nodes_pointer))

    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project')
    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project', index=-1)
    def test_bulk_deletes_public_node_pointers_succeeds_as_owner(self):
        node_count_before = len(self.public_project.nodes_pointer)
        res = self.app.delete_json_api(self.public_url, self.public_payload, auth=self.user.auth, bulk=True)
        self.public_project.reload()
        assert_equal(res.status_code, 204)
        assert_equal(node_count_before - 2, len(self.public_project.nodes_pointer))

        self.public_project.reload()

    def test_bulk_deletes_private_node_pointers_logged_out(self):
        res = self.app.delete_json_api(self.private_url, self.private_payload, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.POINTER_REMOVED, 'project', index=-1)
    @assert_logs(NodeLog.POINTER_REMOVED, 'project')
    def test_bulk_deletes_private_node_pointers_logged_in_contributor(self):
        res = self.app.delete_json_api(self.private_url, self.private_payload, auth=self.user.auth, bulk=True)
        self.project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)
        assert_equal(len(self.project.nodes_pointer), 0)

    def test_bulk_deletes_private_node_pointers_logged_in_non_contributor(self):
        res = self.app.delete_json_api(self.private_url, self.private_payload,
                                       auth=self.user_two.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project', index=-1)
    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project')
    def test_return_bulk_deleted_public_node_pointer(self):
        res = self.app.delete_json_api(self.public_url, self.public_payload, auth=self.user.auth, bulk=True)
        self.public_project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)

        pointer_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.public_project._id, self.public_pointer._id)

        #check that deleted pointer can not be returned
        res = self.app.get(pointer_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    @assert_logs(NodeLog.POINTER_REMOVED, 'project', index=-1)
    @assert_logs(NodeLog.POINTER_REMOVED, 'project')
    def test_return_bulk_deleted_private_node_pointer(self):
        res = self.app.delete_json_api(self.private_url, self.private_payload, auth=self.user.auth, bulk=True)
        self.project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)

        pointer_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.project._id, self.pointer._id)

        #check that deleted pointer can not be returned
        res = self.app.get(pointer_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    # Regression test for https://openscience.atlassian.net/browse/OSF-4322
    def test_bulk_delete_link_that_is_not_linked_to_correct_node(self):
        project = ProjectFactory(creator=self.user)
        # The node link belongs to a different project
        res = self.app.delete_json_api(
            self.private_url, self.public_payload,
            auth=self.user.auth,
            expect_errors=True,
            bulk=True
        )
        assert_equal(res.status_code, 400)
        errors = res.json['errors']
        assert_equal(len(errors), 1)
        assert_equal(errors[0]['detail'], 'Node link does not belong to the requested node.')
Exemple #14
0
class TestWikiViews(OsfTestCase):

    def setUp(self):
        super(TestWikiViews, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=True, creator=self.user)
        self.consolidate_auth = Auth(user=self.project.creator)

    def test_wiki_url_get_returns_200(self):
        url = self.project.web_url_for('project_wiki_page', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_url_for_pointer_returns_200(self):
        # TODO: explain how this tests a pointer
        project = ProjectFactory(is_public=True)
        self.project.add_pointer(project, Auth(self.project.creator), save=True)
        url = self.project.web_url_for('project_wiki_page', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_content_returns_200(self):
        node = ProjectFactory(is_public=True)
        url = node.api_url_for('wiki_page_content', wname='somerandomid')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_url_for_component_returns_200(self):
        component = NodeFactory(project=self.project, is_public=True)
        url = component.web_url_for('project_wiki_page', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_serialize_wiki_toc(self):
        project = ProjectFactory()
        auth = Auth(project.creator)
        NodeFactory(project=project, creator=project.creator)
        no_wiki = NodeFactory(project=project, creator=project.creator)
        project.save()

        serialized = _serialize_wiki_toc(project, auth=auth)
        assert_equal(len(serialized), 2)
        no_wiki.delete_addon('wiki', auth=auth)
        serialized = _serialize_wiki_toc(project, auth=auth)
        assert_equal(len(serialized), 1)

    def test_get_wiki_url_pointer_component(self):
        """Regression test for issues
        https://github.com/CenterForOpenScience/osf/issues/363 and
        https://github.com/CenterForOpenScience/openscienceframework.org/issues/574

        """
        user = UserFactory()
        pointed_node = NodeFactory(creator=user)
        project = ProjectFactory(creator=user)
        auth = Auth(user=user)
        project.add_pointer(pointed_node, auth=auth, save=True)

        serialized = _serialize_wiki_toc(project, auth)
        assert_equal(
            serialized[0]['url'],
            pointed_node.web_url_for('project_wiki_page', wname='home', _guid=True)
        )

    def test_project_wiki_edit_post(self):
        self.project.update_node_wiki(
            'home',
            content='old content',
            auth=Auth(self.project.creator)
        )
        url = self.project.web_url_for('project_wiki_edit_post', wname='home')
        res = self.app.post(url, {'content': 'new content'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        # page was updated with new content
        new_wiki = self.project.get_wiki_page('home')
        assert_equal(new_wiki.content, 'new content')

    def test_project_wiki_edit_post_with_new_wname_and_no_content(self):
        page_name = fake.catch_phrase()

        old_wiki_page_count = NodeWikiPage.find().count()
        url = self.project.web_url_for('project_wiki_edit_post', wname=page_name)
        # User submits to edit form with no content
        res = self.app.post(url, {'content': ''}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        new_wiki_page_count = NodeWikiPage.find().count()
        # A new wiki page was created in the db
        assert_equal(new_wiki_page_count, old_wiki_page_count + 1)

        # Node now has the new wiki page associated with it
        self.project.reload()
        new_page = self.project.get_wiki_page(page_name)
        assert_is_not_none(new_page)

    def test_project_wiki_edit_post_with_new_wname_and_content(self):
        page_name, page_content = fake.catch_phrase(), fake.bs()

        old_wiki_page_count = NodeWikiPage.find().count()
        url = self.project.web_url_for('project_wiki_edit_post', wname=page_name)
        # User submits to edit form with no content
        res = self.app.post(url, {'content': page_content}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        new_wiki_page_count = NodeWikiPage.find().count()
        # A new wiki page was created in the db
        assert_equal(new_wiki_page_count, old_wiki_page_count + 1)

        # Node now has the new wiki page associated with it
        self.project.reload()
        new_page = self.project.get_wiki_page(page_name)
        assert_is_not_none(new_page)
        # content was set
        assert_equal(new_page.content, page_content)

    def test_project_wiki_edit_post_with_non_ascii_title(self):
        # regression test for https://github.com/CenterForOpenScience/openscienceframework.org/issues/1040
        # wname doesn't exist in the db, so it will be created
        new_wname = u'øˆ∆´ƒøßå√ß'
        url = self.project.web_url_for('project_wiki_edit_post', wname=new_wname)
        res = self.app.post(url, {'content': 'new content'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        wiki = self.project.get_wiki_page(new_wname)
        assert_equal(wiki.page_name, new_wname)

        # updating content should return correct url as well.
        res = self.app.post(url, {'content': 'updated content'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

    def test_project_wiki_edit_post_with_special_characters(self):
        new_wname = 'title: ' + SPECIAL_CHARACTERS_ALLOWED
        new_wiki_content = 'content: ' + SPECIAL_CHARACTERS_ALL
        url = self.project.web_url_for('project_wiki_edit_post', wname=new_wname)
        res = self.app.post(url, {'content': new_wiki_content}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        wiki = self.project.get_wiki_page(new_wname)
        assert_equal(wiki.page_name, new_wname)
        assert_equal(wiki.content, new_wiki_content)
        assert_equal(res.status_code, 200)

    def test_wiki_edit_get_home(self):
        url = self.project.web_url_for('project_wiki_edit', wname='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_project_wiki_compare_returns_200(self):
        self.project.update_node_wiki('home', 'updated content', Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_compare', wname='home', wver=1)
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_project_wiki_compare_with_invalid_wname(self):
        url = self.project.web_url_for('project_wiki_compare', wname='this-doesnt-exist', wver=1)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_wiki_page_creation_strips_whitespace(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1080
        # wname has a trailing space
        url = self.project.web_url_for('project_wiki_edit', wname='cupcake ')
        res = self.app.post(url, {'content': 'blah'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        self.project.reload()
        wiki = self.project.get_wiki_page('cupcake')
        assert_is_not_none(wiki)

    def test_wiki_validate_name(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='Capslock')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_wiki_validate_name_cannot_create_home(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='home')
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_project_wiki_validate_name_mixed_casing(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='CaPsLoCk')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_not_in('capslock', self.project.wiki_pages_current)
        self.project.update_node_wiki('CaPsLoCk', 'hello', self.consolidate_auth)
        assert_in('capslock', self.project.wiki_pages_current)

    def test_project_wiki_validate_name_diplay_correct_capitalization(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='CaPsLoCk')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_in('CaPsLoCk', res)

    def test_project_wiki_validate_name_conflict_different_casing(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='CAPSLOCK')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        self.project.update_node_wiki('CaPsLoCk', 'hello', self.consolidate_auth)
        assert_in('capslock', self.project.wiki_pages_current)
        url = self.project.api_url_for('project_wiki_validate_name', wname='capslock')
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_project_dashboard_shows_no_wiki_content_text(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104
        project = ProjectFactory(creator=self.user)
        url = project.web_url_for('view_project')
        res = self.app.get(url, auth=self.user.auth)
        assert_in('No wiki content', res)

    def test_project_dashboard_wiki_wname_get_shows_non_ascii_characters(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104
        text = u'你好'
        self.project.update_node_wiki('home', text, Auth(self.user))

        # can view wiki preview from project dashboard
        url = self.project.web_url_for('view_project')
        res = self.app.get(url, auth=self.user.auth)
        assert_in(text, res)

    def test_project_wiki_home_api_route(self):
        url = self.project.api_url_for('project_wiki_home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equals(res.status_code, 302)
        # TODO: should this route exist? it redirects you to the web_url_for, not api_url_for.
        # page_url = self.project.api_url_for('project_wiki_page', wname='home')
        # assert_in(page_url, res.location)

    def test_project_wiki_home_web_route(self):
        page_url = self.project.web_url_for('project_wiki_page', wname='home', _guid=True)
        url = self.project.web_url_for('project_wiki_home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equals(res.status_code, 302)
        assert_in(page_url, res.location)

    def test_wiki_id_url_get_returns_302_and_resolves(self):
        name = 'page by id'
        self.project.update_node_wiki(name, 'some content', Auth(self.project.creator))
        page = self.project.get_wiki_page(name)
        page_url = self.project.web_url_for('project_wiki_page', wname=page.page_name, _guid=True)
        url = self.project.web_url_for('project_wiki_id_page', wid=page._primary_key, _guid=True)
        res = self.app.get(url)
        assert_equal(res.status_code, 302)
        assert_in(page_url, res.location)
        res = res.follow()
        assert_equal(res.status_code, 200)
        assert_in(page_url, res.request.url)

    def test_wiki_id_url_get_returns_404(self):
        url = self.project.web_url_for('project_wiki_id_page', wid='12345', _guid=True)
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_home_is_capitalized_in_web_view(self):
        url = self.project.web_url_for('project_wiki_home', wid='home', _guid=True)
        res = self.app.get(url, auth=self.user.auth).follow(auth=self.user.auth)
        page_name_elem = res.html.find('span', {'id': 'pageName'})
        assert_in('Home', page_name_elem.text)
Exemple #15
0
class TestBulkDeleteNodeLinks(ApiTestCase):

    def setUp(self):
        super(TestBulkDeleteNodeLinks, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(creator=self.user, is_public=False)
        self.pointer_project = ProjectFactory(creator=self.user, is_public=True)
        self.pointer_project_two = ProjectFactory(creator=self.user, is_public=True)

        self.pointer = self.project.add_pointer(self.pointer_project, auth=Auth(self.user), save=True)
        self.pointer_two = self.project.add_pointer(self.pointer_project_two, auth=Auth(self.user), save=True)

        self.private_payload = {
              "data": [
                {"type": "node_links", "id": self.pointer._id},
                {"type": "node_links", "id": self.pointer_two._id}
              ]
            }

        self.private_url = '/{}nodes/{}/node_links/'.format(API_BASE, self.project._id)

        self.user_two = AuthUserFactory()

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project_two = ProjectFactory(is_public=True, creator=self.user)

        self.public_pointer = self.public_project.add_pointer(self.public_pointer_project,
                                                              auth=Auth(self.user),
                                                              save=True)
        self.public_pointer_two = self.public_project.add_pointer(self.public_pointer_project_two,
                                                              auth=Auth(self.user),
                                                              save=True)

        self.public_payload = {
              'data': [
                {'type': 'node_links', 'id': self.public_pointer._id},
                {'type': 'node_links', 'id': self.public_pointer_two._id}
              ]
            }

        self.public_url = '/{}nodes/{}/node_links/'.format(API_BASE, self.public_project._id)

    def test_bulk_delete_node_links_blank_request(self):
        res = self.app.delete_json_api(self.public_url, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)

    def test_bulk_delete_pointer_limits(self):
        res = self.app.delete_json_api(self.public_url, {'data': [self.public_payload['data'][0]] * 101},
                                       auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Bulk operation limit is 100, got 101.')
        assert_equal(res.json['errors'][0]['source']['pointer'], '/data')

    def test_bulk_delete_dict_inside_data(self):
        res = self.app.delete_json_api(self.public_url, {'data': {'id': self.public_project._id, 'type': 'node_links'}},
                                       auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Expected a list of items but got type "dict".')

    def test_bulk_delete_pointers_no_type(self):
        payload = {'data': [
            {'id': self.public_pointer._id},
            {'id': self.public_pointer_two._id}
        ]}
        res = self.app.delete_json_api(self.public_url, payload, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['source']['pointer'], "/data/type")

    def test_bulk_delete_pointers_incorrect_type(self):
        payload = {'data': [
            {'id': self.public_pointer._id, 'type': 'Incorrect type.'},
            {'id': self.public_pointer_two._id, 'type': 'Incorrect type.'}
        ]}
        res = self.app.delete_json_api(self.public_url, payload, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 409)

    def test_bulk_delete_pointers_no_id(self):
        payload = {'data': [
            {'type': 'node_links'},
            {'type': 'node_links'}
        ]}
        res = self.app.delete_json_api(self.public_url, payload, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['source']['pointer'], "/data/id")

    def test_bulk_delete_pointers_no_data(self):
        res = self.app.delete_json_api(self.public_url, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Request must contain array of resource identifier objects.')

    def test_bulk_delete_pointers_payload_is_empty_dict(self):
        res = self.app.delete_json_api(self.public_url, {}, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Request must include /data.')

    def test_cannot_delete_if_registration(self):
        registration = RegistrationFactory(project=self.public_project)

        url = '/{}registrations/{}/node_links/'.format(API_BASE, registration._id)

        res = self.app.delete_json_api(url, self.public_payload, auth=self.user.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 405)

    def test_bulk_deletes_public_node_pointers_logged_out(self):
        res = self.app.delete_json_api(self.public_url, self.public_payload, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    def test_bulk_deletes_public_node_pointers_fails_if_bad_auth(self):
        node_count_before = len(self.public_project.nodes_pointer)
        res = self.app.delete_json_api(self.public_url, self.public_payload,
                                       auth=self.user_two.auth, expect_errors=True, bulk=True)
        # This is could arguably be a 405, but we don't need to go crazy with status codes
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])
        self.public_project.reload()
        assert_equal(node_count_before, len(self.public_project.nodes_pointer))

    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project')
    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project', index=-1)
    def test_bulk_deletes_public_node_pointers_succeeds_as_owner(self):
        node_count_before = len(self.public_project.nodes_pointer)
        res = self.app.delete_json_api(self.public_url, self.public_payload, auth=self.user.auth, bulk=True)
        self.public_project.reload()
        assert_equal(res.status_code, 204)
        assert_equal(node_count_before - 2, len(self.public_project.nodes_pointer))

        self.public_project.reload()

    def test_bulk_deletes_private_node_pointers_logged_out(self):
        res = self.app.delete_json_api(self.private_url, self.private_payload, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.POINTER_REMOVED, 'project', index=-1)
    @assert_logs(NodeLog.POINTER_REMOVED, 'project')
    def test_bulk_deletes_private_node_pointers_logged_in_contributor(self):
        res = self.app.delete_json_api(self.private_url, self.private_payload, auth=self.user.auth, bulk=True)
        self.project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)
        assert_equal(len(self.project.nodes_pointer), 0)

    def test_bulk_deletes_private_node_pointers_logged_in_non_contributor(self):
        res = self.app.delete_json_api(self.private_url, self.private_payload,
                                       auth=self.user_two.auth, expect_errors=True, bulk=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project', index=-1)
    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project')
    def test_return_bulk_deleted_public_node_pointer(self):
        res = self.app.delete_json_api(self.public_url, self.public_payload, auth=self.user.auth, bulk=True)
        self.public_project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)

        pointer_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.public_project._id, self.public_pointer._id)

        #check that deleted pointer can not be returned
        res = self.app.get(pointer_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    @assert_logs(NodeLog.POINTER_REMOVED, 'project', index=-1)
    @assert_logs(NodeLog.POINTER_REMOVED, 'project')
    def test_return_bulk_deleted_private_node_pointer(self):
        res = self.app.delete_json_api(self.private_url, self.private_payload, auth=self.user.auth, bulk=True)
        self.project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)

        pointer_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.project._id, self.pointer._id)

        #check that deleted pointer can not be returned
        res = self.app.get(pointer_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    # Regression test for https://openscience.atlassian.net/browse/OSF-4322
    def test_bulk_delete_link_that_is_not_linked_to_correct_node(self):
        project = ProjectFactory(creator=self.user)
        # The node link belongs to a different project
        res = self.app.delete_json_api(
            self.private_url, self.public_payload,
            auth=self.user.auth,
            expect_errors=True,
            bulk=True
        )
        assert_equal(res.status_code, 400)
        errors = res.json['errors']
        assert_equal(len(errors), 1)
        assert_equal(errors[0]['detail'], 'Node link does not belong to the requested node.')
Exemple #16
0
class TestNodeLinksList(ApiTestCase):

    def setUp(self):
        super(TestNodeLinksList, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=False, creator=self.user)
        self.pointer_project = ProjectFactory(is_public=False, creator=self.user)
        self.project.add_pointer(self.pointer_project, auth=Auth(self.user))
        self.private_url = '/{}nodes/{}/node_links/'.format(API_BASE, self.project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project.add_pointer(self.public_pointer_project, auth=Auth(self.user))
        self.public_url = '/{}nodes/{}/node_links/'.format(API_BASE, self.public_project._id)

        self.user_two = AuthUserFactory()

    def test_return_embedded_public_node_pointers_logged_out(self):
        res = self.app.get(self.public_url)
        res_json = res.json['data']
        assert_equal(len(res_json), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')

        embedded = res_json[0]['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.public_pointer_project._id)

    def test_return_embedded_public_node_pointers_logged_in(self):
        res = self.app.get(self.public_url, auth=self.user_two.auth)
        res_json = res.json['data']
        assert_equal(len(res_json), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        embedded = res_json[0]['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.public_pointer_project._id)

    def test_return_private_node_pointers_logged_out(self):
        res = self.app.get(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    def test_return_private_node_pointers_logged_in_contributor(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        res_json = res.json['data']
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(len(res_json), 1)
        embedded = res_json[0]['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.pointer_project._id)

    def test_return_private_node_pointers_logged_in_non_contributor(self):
        res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    def test_deleted_links_not_returned(self):
        res = self.app.get(self.public_url, expect_errors=True)
        res_json = res.json['data']
        original_length = len(res_json)

        self.public_pointer_project.is_deleted = True
        self.public_pointer_project.save()

        res = self.app.get(self.public_url)
        res_json = res.json['data']
        assert_equal(len(res_json), original_length - 1)
Exemple #17
0
class TestExplorePublicActivity(OsfTestCase):
    def setUp(self):
        super(TestExplorePublicActivity, self).setUp()
        self.project = ProjectFactory(is_public=True)
        self.registration = RegistrationFactory(project=self.project)
        self.private_project = ProjectFactory(title="Test private project")
        self.popular_project = ProjectFactory(is_public=True)
        self.popular_registration = RegistrationFactory(project=self.project)

        # Add project to new and noteworthy projects
        self.new_and_noteworthy_links_node = ProjectFactory()
        self.new_and_noteworthy_links_node._id = settings.NEW_AND_NOTEWORTHY_LINKS_NODE
        self.new_and_noteworthy_links_node.add_pointer(
            self.project,
            auth=Auth(self.new_and_noteworthy_links_node.creator),
            save=True)

        # Set up popular projects and registrations
        self.popular_links_node = ProjectFactory()
        self.popular_links_node._id = settings.POPULAR_LINKS_NODE
        self.popular_links_node.add_pointer(
            self.popular_project,
            auth=Auth(self.popular_links_node.creator),
            save=True)

        self.popular_links_registrations = ProjectFactory()
        self.popular_links_registrations._id = settings.POPULAR_LINKS_REGISTRATIONS
        self.popular_links_registrations.add_pointer(
            self.popular_registration,
            auth=Auth(self.popular_links_registrations.creator),
            save=True)

    def tearDown(self):
        super(TestExplorePublicActivity, self).tearDown()
        Node.remove()

    def test_explore_page_loads_when_settings_not_configured(self):

        old_settings_values = settings.POPULAR_LINKS_NODE, settings.NEW_AND_NOTEWORTHY_LINKS_NODE, settings.POPULAR_LINKS_REGISTRATIONS

        settings.POPULAR_LINKS_NODE = 'notanode'
        settings.NEW_AND_NOTEWORTHY_LINKS_NODE = 'alsototallywrong'
        settings.POPULAR_LINKS_REGISTRATIONS = 'nopenope'

        url = self.project.web_url_for('activity')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

        settings.POPULAR_LINKS_NODE, settings.NEW_AND_NOTEWORTHY_LINKS_NODE, settings.POPULAR_LINKS_REGISTRATIONS = old_settings_values

    def test_new_and_noteworthy_and_popular_nodes_show_in_explore_activity(
            self):

        url = self.project.web_url_for('activity')
        res = self.app.get(url)

        # New and Noteworthy
        assert_in(str(self.project.title), res)
        assert_in(str(self.project.date_created.date()), res)
        assert_in(str(self.registration.title), res)
        assert_in(str(self.registration.registered_date.date()), res)
        assert_not_in(str(self.private_project.title), res)

        # Popular Projects and Registrations
        assert_in(str(self.popular_project.title), res)
        assert_in(str(self.popular_project.date_created.date()), res)
        assert_in(str(self.popular_registration.title), res)
        assert_in(str(self.popular_registration.registered_date.date()), res)
Exemple #18
0
class TestWikiViews(OsfTestCase):

    def setUp(self):
        super(TestWikiViews, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=True, creator=self.user)
        self.consolidate_auth = Auth(user=self.project.creator)

    def test_wiki_url_get_returns_200(self):
        url = self.project.web_url_for('project_wiki_view', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_url_404_with_no_write_permission(self):
        url = self.project.web_url_for('project_wiki_view', wname='somerandomid')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 404)

    @mock.patch('website.addons.wiki.utils.broadcast_to_sharejs')
    def test_wiki_deleted_404_with_no_write_permission(self, mock_sharejs):
        self.project.update_node_wiki('funpage', 'Version 1', Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_view', wname='funpage')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)
        delete_url = self.project.api_url_for('project_wiki_delete', wname='funpage')
        self.app.delete(delete_url, auth=self.user.auth)
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_wiki_url_with_path_get_returns_200(self):
        self.project.update_node_wiki('funpage', 'Version 1', Auth(self.user))
        self.project.update_node_wiki('funpage', 'Version 2', Auth(self.user))
        self.project.save()

        url = self.project.web_url_for(
            'project_wiki_view',
            wname='funpage',
        ) + '?view&compare=1&edit'
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_wiki_url_with_edit_get_returns_404_with_no_write_permission(self):
        self.project.update_node_wiki('funpage', 'Version 1', Auth(self.user))
        self.project.update_node_wiki('funpage', 'Version 2', Auth(self.user))
        self.project.save()

        url = self.project.web_url_for(
            'project_wiki_view',
            wname='funpage',
            compare=1,
        )
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

        url = self.project.web_url_for(
            'project_wiki_view',
            wname='funpage',
        ) + '?edit'
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_wiki_url_for_pointer_returns_200(self):
        # TODO: explain how this tests a pointer
        project = ProjectFactory(is_public=True)
        self.project.add_pointer(project, Auth(self.project.creator), save=True)
        url = self.project.web_url_for('project_wiki_view', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_draft_returns_200(self):
        url = self.project.api_url_for('wiki_page_draft', wname='somerandomid')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_wiki_content_returns_200(self):
        url = self.project.api_url_for('wiki_page_content', wname='somerandomid')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    @mock.patch('website.addons.wiki.model.NodeWikiPage.rendered_before_update', new_callable=mock.PropertyMock)
    def test_wiki_content_use_python_render(self, mock_rendered_before_update):
        content = 'Some content'
        self.project.update_node_wiki('somerandomid', content, Auth(self.user))
        self.project.save()

        mock_rendered_before_update.return_value = True
        url = self.project.api_url_for('wiki_page_content', wname='somerandomid')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(content, res.json['wiki_content'])
        assert_in(content, res.json['wiki_rendered'])

        mock_rendered_before_update.return_value = False
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(content, res.json['wiki_content'])
        assert_equal('', res.json['wiki_rendered'])


    def test_wiki_url_for_component_returns_200(self):
        component = NodeFactory(project=self.project, is_public=True)
        url = component.web_url_for('project_wiki_view', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_serialize_wiki_toc(self):
        project = ProjectFactory()
        auth = Auth(project.creator)
        NodeFactory(project=project, creator=project.creator)
        no_wiki = NodeFactory(project=project, creator=project.creator)
        project.save()

        serialized = _serialize_wiki_toc(project, auth=auth)
        assert_equal(len(serialized), 2)
        no_wiki.delete_addon('wiki', auth=auth)
        serialized = _serialize_wiki_toc(project, auth=auth)
        assert_equal(len(serialized), 1)

    def test_get_wiki_url_pointer_component(self):
        """Regression test for issues
        https://github.com/CenterForOpenScience/osf/issues/363 and
        https://github.com/CenterForOpenScience/openscienceframework.org/issues/574

        """
        user = UserFactory()
        pointed_node = NodeFactory(creator=user)
        project = ProjectFactory(creator=user)
        auth = Auth(user=user)
        project.add_pointer(pointed_node, auth=auth, save=True)

        serialized = _serialize_wiki_toc(project, auth)
        assert_equal(
            serialized[0]['url'],
            pointed_node.web_url_for('project_wiki_view', wname='home', _guid=True)
        )

    def test_project_wiki_edit_post(self):
        self.project.update_node_wiki(
            'home',
            content='old content',
            auth=Auth(self.project.creator)
        )
        url = self.project.web_url_for('project_wiki_edit_post', wname='home')
        res = self.app.post(url, {'content': 'new content'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        # page was updated with new content
        new_wiki = self.project.get_wiki_page('home')
        assert_equal(new_wiki.content, 'new content')

    def test_project_wiki_edit_post_with_new_wname_and_no_content(self):
        # note: forward slashes not allowed in page_name
        page_name = fake.catch_phrase().replace('/', ' ')

        old_wiki_page_count = NodeWikiPage.find().count()
        url = self.project.web_url_for('project_wiki_edit_post', wname=page_name)
        # User submits to edit form with no content
        res = self.app.post(url, {'content': ''}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        new_wiki_page_count = NodeWikiPage.find().count()
        # A new wiki page was created in the db
        assert_equal(new_wiki_page_count, old_wiki_page_count + 1)

        # Node now has the new wiki page associated with it
        self.project.reload()
        new_page = self.project.get_wiki_page(page_name)
        assert_is_not_none(new_page)

    def test_project_wiki_edit_post_with_new_wname_and_content(self):
        # note: forward slashes not allowed in page_name
        page_name = fake.catch_phrase().replace('/' , ' ')
        page_content = fake.bs()

        old_wiki_page_count = NodeWikiPage.find().count()
        url = self.project.web_url_for('project_wiki_edit_post', wname=page_name)
        # User submits to edit form with no content
        res = self.app.post(url, {'content': page_content}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        new_wiki_page_count = NodeWikiPage.find().count()
        # A new wiki page was created in the db
        assert_equal(new_wiki_page_count, old_wiki_page_count + 1)

        # Node now has the new wiki page associated with it
        self.project.reload()
        new_page = self.project.get_wiki_page(page_name)
        assert_is_not_none(new_page)
        # content was set
        assert_equal(new_page.content, page_content)

    def test_project_wiki_edit_post_with_non_ascii_title(self):
        # regression test for https://github.com/CenterForOpenScience/openscienceframework.org/issues/1040
        # wname doesn't exist in the db, so it will be created
        new_wname = u'øˆ∆´ƒøßå√ß'
        url = self.project.web_url_for('project_wiki_edit_post', wname=new_wname)
        res = self.app.post(url, {'content': 'new content'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        wiki = self.project.get_wiki_page(new_wname)
        assert_equal(wiki.page_name, new_wname)

        # updating content should return correct url as well.
        res = self.app.post(url, {'content': 'updated content'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

    def test_project_wiki_edit_post_with_special_characters(self):
        new_wname = 'title: ' + SPECIAL_CHARACTERS_ALLOWED
        new_wiki_content = 'content: ' + SPECIAL_CHARACTERS_ALL
        url = self.project.web_url_for('project_wiki_edit_post', wname=new_wname)
        res = self.app.post(url, {'content': new_wiki_content}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        wiki = self.project.get_wiki_page(new_wname)
        assert_equal(wiki.page_name, new_wname)
        assert_equal(wiki.content, new_wiki_content)
        assert_equal(res.status_code, 200)

    def test_wiki_edit_get_home(self):
        url = self.project.web_url_for('project_wiki_view', wname='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_project_wiki_view_scope(self):
        self.project.update_node_wiki('home', 'Version 1', Auth(self.user))
        self.project.update_node_wiki('home', 'Version 2', Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_view', wname='home', view=2)
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        url = self.project.web_url_for('project_wiki_view', wname='home', view=3)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        url = self.project.web_url_for('project_wiki_view', wname='home', view=0)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)

    def test_project_wiki_compare_returns_200(self):
        self.project.update_node_wiki('home', 'updated content', Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_view', wname='home') + '?compare'
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_project_wiki_compare_scope(self):
        self.project.update_node_wiki('home', 'Version 1', Auth(self.user))
        self.project.update_node_wiki('home', 'Version 2', Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_view', wname='home', compare=2)
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        url = self.project.web_url_for('project_wiki_view', wname='home', compare=3)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        url = self.project.web_url_for('project_wiki_view', wname='home', compare=0)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)

    def test_wiki_page_creation_strips_whitespace(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1080
        # wname has a trailing space
        url = self.project.web_url_for('project_wiki_view', wname='cupcake ')
        res = self.app.post(url, {'content': 'blah'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        self.project.reload()
        wiki = self.project.get_wiki_page('cupcake')
        assert_is_not_none(wiki)

    def test_wiki_validate_name(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='Capslock')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_wiki_validate_name_cannot_create_home(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='home')
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_project_wiki_validate_name_mixed_casing(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='CaPsLoCk')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_not_in('capslock', self.project.wiki_pages_current)
        self.project.update_node_wiki('CaPsLoCk', 'hello', self.consolidate_auth)
        assert_in('capslock', self.project.wiki_pages_current)

    def test_project_wiki_validate_name_diplay_correct_capitalization(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='CaPsLoCk')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_in('CaPsLoCk', res)

    def test_project_wiki_validate_name_conflict_different_casing(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='CAPSLOCK')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        self.project.update_node_wiki('CaPsLoCk', 'hello', self.consolidate_auth)
        assert_in('capslock', self.project.wiki_pages_current)
        url = self.project.api_url_for('project_wiki_validate_name', wname='capslock')
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_project_dashboard_shows_no_wiki_content_text(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104
        project = ProjectFactory(creator=self.user)
        url = project.web_url_for('view_project')
        res = self.app.get(url, auth=self.user.auth)
        assert_in('No wiki content', res)

    def test_project_dashboard_wiki_wname_get_shows_non_ascii_characters(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104
        text = u'你好'
        self.project.update_node_wiki('home', text, Auth(self.user))

        # can view wiki preview from project dashboard
        url = self.project.web_url_for('view_project')
        res = self.app.get(url, auth=self.user.auth)
        assert_in(text, res)

    def test_project_wiki_home_api_route(self):
        url = self.project.api_url_for('project_wiki_home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equals(res.status_code, 302)
        # TODO: should this route exist? it redirects you to the web_url_for, not api_url_for.
        # page_url = self.project.api_url_for('project_wiki_view', wname='home')
        # assert_in(page_url, res.location)

    def test_project_wiki_home_web_route(self):
        page_url = self.project.web_url_for('project_wiki_view', wname='home', _guid=True)
        url = self.project.web_url_for('project_wiki_home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equals(res.status_code, 302)
        assert_in(page_url, res.location)

    def test_wiki_id_url_get_returns_302_and_resolves(self):
        name = 'page by id'
        self.project.update_node_wiki(name, 'some content', Auth(self.project.creator))
        page = self.project.get_wiki_page(name)
        page_url = self.project.web_url_for('project_wiki_view', wname=page.page_name, _guid=True)
        url = self.project.web_url_for('project_wiki_id_page', wid=page._primary_key, _guid=True)
        res = self.app.get(url)
        assert_equal(res.status_code, 302)
        assert_in(page_url, res.location)
        res = res.follow()
        assert_equal(res.status_code, 200)
        assert_in(page_url, res.request.url)

    def test_wiki_id_url_get_returns_404(self):
        url = self.project.web_url_for('project_wiki_id_page', wid='12345', _guid=True)
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_home_is_capitalized_in_web_view(self):
        url = self.project.web_url_for('project_wiki_home', wid='home', _guid=True)
        res = self.app.get(url, auth=self.user.auth).follow(auth=self.user.auth)
        page_name_elem = res.html.find('span', {'id': 'pageName'})
        assert_in('Home', page_name_elem.text)

    def test_wiki_widget_no_content(self):
        url = self.project.api_url_for('wiki_widget', wid='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_is_none(res.json['wiki_content'])

    def test_wiki_widget_short_content_no_cutoff(self):
        short_content = 'a' * 150
        self.project.update_node_wiki('home', short_content, Auth(self.user))
        url = self.project.api_url_for('wiki_widget', wid='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_in(short_content, res.json['wiki_content'])
        assert_not_in('...', res.json['wiki_content'])
        assert_false(res.json['more'])

    def test_wiki_widget_long_content_cutoff(self):
        long_content = 'a' * 600
        self.project.update_node_wiki('home', long_content, Auth(self.user))
        url = self.project.api_url_for('wiki_widget', wid='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_less(len(res.json['wiki_content']), 520)  # wiggle room for closing tags
        assert_in('...', res.json['wiki_content'])
        assert_true(res.json['more'])

    @mock.patch('website.addons.wiki.model.NodeWikiPage.rendered_before_update', new_callable=mock.PropertyMock)
    def test_wiki_widget_use_python_render(self, mock_rendered_before_update):
        # New pages use js renderer
        mock_rendered_before_update.return_value = False
        self.project.update_node_wiki('home', 'updated content', Auth(self.user))
        url = self.project.api_url_for('wiki_widget', wid='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_false(res.json['use_python_render'])

        # Old pages use python renderer
        mock_rendered_before_update.return_value = True
        res = self.app.get(url, auth=self.user.auth)
        assert_true(res.json['use_python_render'])

    def test_read_only_users_cannot_view_edit_pane(self):
        url = self.project.web_url_for('project_wiki_view', wname='home')
        # No write permissions
        res = self.app.get(url)
        assert_equal(res.status_code, 200)
        assert_not_in('data-osf-panel="Edit"', res.text)
        # Write permissions
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_in('data-osf-panel="Edit"', res.text)
class TestDeleteNodeLink(ApiTestCase):

    def setUp(self):
        super(TestDeleteNodeLink, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(creator=self.user, is_public=False)
        self.pointer_project = ProjectFactory(creator=self.user, is_public=True)
        self.pointer = self.project.add_pointer(self.pointer_project, auth=Auth(self.user), save=True)
        self.private_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.project._id, self.pointer._id)

        self.user_two = AuthUserFactory()

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer = self.public_project.add_pointer(self.public_pointer_project,
                                                              auth=Auth(self.user),
                                                              save=True)
        self.public_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.public_project._id, self.public_pointer._id)

    def test_delete_node_link_no_permissions_for_target_node(self):
        pointer_project = ProjectFactory(creator=self.user_two, is_public=False)
        pointer = self.public_project.add_pointer(pointer_project, auth=Auth(self.user), save=True)
        assert_in(pointer, self.public_project.nodes)
        url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.public_project._id, pointer._id)
        res = self.app.delete_json_api(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 204)

        self.public_project.reload()
        assert_not_in(pointer, self.public_project.nodes)

    def test_cannot_delete_if_registration(self):
        registration = RegistrationFactory(project=self.public_project)

        url = '/{}registrations/{}/node_links/'.format(
            API_BASE,
            registration._id,
        )
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        pointer_id = res.json['data'][0]['id']

        url = '/{}nodes/{}/node_links/{}/'.format(
            API_BASE,
            registration._id,
            pointer_id,
        )
        res = self.app.delete(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_deletes_public_node_pointer_logged_out(self):
        res = self.app.delete(self.public_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0].keys())

    def test_deletes_public_node_pointer_fails_if_bad_auth(self):
        node_count_before = len(self.public_project.nodes_pointer)
        res = self.app.delete(self.public_url, auth=self.user_two.auth, expect_errors=True)
        # This is could arguably be a 405, but we don't need to go crazy with status codes
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])
        self.public_project.reload()
        assert_equal(node_count_before, len(self.public_project.nodes_pointer))

    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project')
    def test_deletes_public_node_pointer_succeeds_as_owner(self):
        node_count_before = len(self.public_project.nodes_pointer)
        res = self.app.delete(self.public_url, auth=self.user.auth)
        self.public_project.reload()
        assert_equal(res.status_code, 204)
        assert_equal(node_count_before - 1, len(self.public_project.nodes_pointer))

    def test_deletes_private_node_pointer_logged_out(self):
        res = self.app.delete(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.POINTER_REMOVED, 'project')
    def test_deletes_private_node_pointer_logged_in_contributor(self):
        res = self.app.delete(self.private_url, auth=self.user.auth)
        self.project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)
        assert_equal(len(self.project.nodes_pointer), 0)

    def test_deletes_private_node_pointer_logged_in_non_contributor(self):
        res = self.app.delete(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project')
    def test_return_deleted_public_node_pointer(self):
        res = self.app.delete(self.public_url, auth=self.user.auth)
        self.public_project.reload() # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)

        #check that deleted pointer can not be returned
        res = self.app.get(self.public_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    @assert_logs(NodeLog.POINTER_REMOVED, 'project')
    def test_return_deleted_private_node_pointer(self):
        res = self.app.delete(self.private_url, auth=self.user.auth)
        self.project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)

        #check that deleted pointer can not be returned
        res = self.app.get(self.private_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    # Regression test for https://openscience.atlassian.net/browse/OSF-4322
    def test_delete_link_that_is_not_linked_to_correct_node(self):
        project = ProjectFactory(creator=self.user)
        # The node link belongs to a different project
        res = self.app.delete(
            '/{}nodes/{}/node_links/{}/'.format(API_BASE, project._id, self.public_pointer._id),
            auth=self.user.auth,
            expect_errors=True
        )
        assert_equal(res.status_code, 404)
        errors = res.json['errors']
        assert_equal(len(errors), 1)
        assert_equal(errors[0]['detail'], 'Node link does not belong to the requested node.')
class TestPopulateNewAndNoteworthy(OsfTestCase):
    def setUp(self):
        super(TestPopulateNewAndNoteworthy, self).setUp()
        self.pop1 = ProjectFactory()
        self.pop2 = ProjectFactory()
        self.pop3 = ProjectFactory()
        self.pop4 = ProjectFactory()
        self.pop5 = ProjectFactory()

        self.nn1 = ProjectFactory(is_public=True)
        self.nn2 = ProjectFactory(is_public=True)
        self.nn3 = ProjectFactory(is_public=True)
        self.nn4 = ProjectFactory(is_public=True)
        self.nn5 = ProjectFactory(is_public=True)

        self.user = UserFactory()

        today = datetime.datetime.now()
        self.last_month = (
            today -
            dateutil.relativedelta.relativedelta(months=1)).isoformat()

        popular_json = {
            "popular_node_ids": [
                self.pop1._id, self.pop2._id, self.pop3._id, self.pop4._id,
                self.pop5._id
            ]
        }
        self.popular_json_body = json.dumps(popular_json)

    def tearDown(self):
        super(TestPopulateNewAndNoteworthy, self).tearDown()
        Node.remove()

    def test_get_new_and_noteworthy_nodes(self):
        new_noteworthy = script.get_new_and_noteworthy_nodes()
        assert_equal(set(new_noteworthy), {
            self.nn1._id, self.nn2._id, self.nn3._id, self.nn4._id,
            self.nn5._id
        })

    def test_populate_new_and_noteworthy(self):
        self.popular_links_node = ProjectFactory(creator=self.user)
        self.popular_links_node._id = POPULAR_LINKS_NODE
        self.popular_links_node.save()
        self.new_and_noteworthy_links_node = ProjectFactory()
        self.new_and_noteworthy_links_node._id = NEW_AND_NOTEWORTHY_LINKS_NODE
        self.new_and_noteworthy_links_node.save()

        popular_nodes = [self.pop1, self.pop2, self.pop3, self.pop4, self.pop5]

        for node in popular_nodes:
            self.popular_links_node.add_pointer(node,
                                                auth=Auth(self.user),
                                                save=True)

        assert_equal(len(self.popular_links_node.nodes), 5)
        assert_equal(len(self.new_and_noteworthy_links_node.nodes), 0)

        script.main(dry_run=False)
        self.popular_links_node.reload()
        self.new_and_noteworthy_links_node.reload()

        assert_equal(len(self.popular_links_node.nodes),
                     0)  # verifies remove pointer is working
        assert_equal(len(self.new_and_noteworthy_links_node.nodes), 5)

        script.main(dry_run=False)

        self.popular_links_node.reload()
        self.new_and_noteworthy_links_node.reload()

        popular_node_links = [
            pointer.node._id for pointer in self.popular_links_node.nodes
        ]
        assert_equal(popular_node_links, [])

        new_and_noteworthy_node_links = {
            pointer.node._id
            for pointer in self.new_and_noteworthy_links_node.nodes
        }

        assert_equal(set(new_and_noteworthy_node_links), {
            self.nn1._id, self.nn2._id, self.nn3._id, self.nn4._id,
            self.nn5._id
        })
class TestNodeLinksList(ApiTestCase):
    def setUp(self):
        super(TestNodeLinksList, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=False, creator=self.user)
        self.pointer_project = ProjectFactory(is_public=False, creator=self.user)
        self.project.add_pointer(self.pointer_project, auth=Auth(self.user))
        self.private_url = "/{}nodes/{}/node_links/".format(API_BASE, self.project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project.add_pointer(self.public_pointer_project, auth=Auth(self.user))
        self.public_url = "/{}nodes/{}/node_links/".format(API_BASE, self.public_project._id)

        self.user_two = AuthUserFactory()

    def test_return_public_node_pointers_logged_out(self):
        res = self.app.get(self.public_url)
        res_json = res.json["data"]
        assert_equal(len(res_json), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, "application/vnd.api+json")
        expected_path = node_url_for(self.public_pointer_project._id)
        actual_path = urlparse(res_json[0]["relationships"]["target_node"]["links"]["related"]["href"]).path
        assert_equal(expected_path, actual_path)

    def test_return_public_node_pointers_logged_in(self):
        res = self.app.get(self.public_url, auth=self.user_two.auth)
        res_json = res.json["data"]
        assert_equal(len(res_json), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, "application/vnd.api+json")
        expected_path = node_url_for(self.public_pointer_project._id)
        actual_path = urlparse(res_json[0]["relationships"]["target_node"]["links"]["related"]["href"]).path
        assert_equal(expected_path, actual_path)

    def test_return_private_node_pointers_logged_out(self):
        res = self.app.get(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in("detail", res.json["errors"][0])

    def test_return_private_node_pointers_logged_in_contributor(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        res_json = res.json["data"]
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, "application/vnd.api+json")
        assert_equal(len(res_json), 1)
        expected_path = node_url_for(self.pointer_project._id)
        actual_path = urlparse(res_json[0]["relationships"]["target_node"]["links"]["related"]["href"]).path
        assert_equal(expected_path, actual_path)

    def test_return_private_node_pointers_logged_in_non_contributor(self):
        res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in("detail", res.json["errors"][0])

    def test_deleted_links_not_returned(self):
        res = self.app.get(self.public_url, expect_errors=True)
        res_json = res.json["data"]
        original_length = len(res_json)

        self.public_pointer_project.is_deleted = True
        self.public_pointer_project.save()

        res = self.app.get(self.public_url)
        res_json = res.json["data"]
        assert_equal(len(res_json), original_length - 1)
Exemple #22
0
class TestNodeChildrenList(ApiTestCase):
    def setUp(self):
        super(TestNodeChildrenList, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory()
        self.project.add_contributor(
            self.user, permissions=[permissions.READ, permissions.WRITE])
        self.project.save()
        self.component = NodeFactory(parent=self.project, creator=self.user)
        self.pointer = ProjectFactory()
        self.project.add_pointer(self.pointer, auth=Auth(self.user), save=True)
        self.private_project_url = '/{}nodes/{}/children/'.format(
            API_BASE, self.project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project.save()
        self.public_component = NodeFactory(parent=self.public_project,
                                            creator=self.user,
                                            is_public=True)
        self.public_project_url = '/{}nodes/{}/children/'.format(
            API_BASE, self.public_project._id)

        self.user_two = AuthUserFactory()

    def test_node_children_list_does_not_include_pointers(self):
        res = self.app.get(self.private_project_url, auth=self.user.auth)
        assert_equal(len(res.json['data']), 1)

    def test_return_public_node_children_list_logged_out(self):
        res = self.app.get(self.public_project_url)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(len(res.json['data']), 1)
        assert_equal(res.json['data'][0]['id'], self.public_component._id)

    def test_return_public_node_children_list_logged_in(self):
        res = self.app.get(self.public_project_url, auth=self.user_two.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(len(res.json['data']), 1)
        assert_equal(res.json['data'][0]['id'], self.public_component._id)

    def test_return_private_node_children_list_logged_out(self):
        res = self.app.get(self.private_project_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert 'detail' in res.json['errors'][0]

    def test_return_private_node_children_list_logged_in_contributor(self):
        res = self.app.get(self.private_project_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(len(res.json['data']), 1)
        assert_equal(res.json['data'][0]['id'], self.component._id)

    def test_return_private_node_children_list_logged_in_non_contributor(self):
        res = self.app.get(self.private_project_url,
                           auth=self.user_two.auth,
                           expect_errors=True)
        assert_equal(res.status_code, 403)
        assert 'detail' in res.json['errors'][0]

    def test_node_children_list_does_not_include_unauthorized_projects(self):
        private_component = NodeFactory(parent=self.project)
        res = self.app.get(self.private_project_url, auth=self.user.auth)
        assert_equal(len(res.json['data']), 1)

    def test_node_children_list_does_not_include_deleted(self):
        child_project = NodeFactory(parent=self.public_project,
                                    creator=self.user)
        child_project.save()

        res = self.app.get(self.public_project_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        ids = [node['id'] for node in res.json['data']]
        assert_in(child_project._id, ids)
        assert_equal(2, len(ids))

        child_project.is_deleted = True
        child_project.save()

        res = self.app.get(self.public_project_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        ids = [node['id'] for node in res.json['data']]
        assert_not_in(child_project._id, ids)
        assert_equal(1, len(ids))

    def test_node_children_list_does_not_include_node_links(self):
        pointed_to = ProjectFactory(is_public=True)

        self.public_project.add_pointer(pointed_to,
                                        auth=Auth(self.public_project.creator))

        res = self.app.get(self.public_project_url, auth=self.user.auth)
        ids = [node['id'] for node in res.json['data']]
        assert_in(self.public_component._id, ids)  # sanity check

        assert_equal(len(ids),
                     len([e for e in self.public_project.nodes if e.primary]))
        assert_not_in(pointed_to._id, ids)
Exemple #23
0
class TestWikiViews(OsfTestCase):

    def setUp(self):
        super(TestWikiViews, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=True, creator=self.user)
        self.consolidate_auth = Auth(user=self.project.creator)

    def test_wiki_url_get_returns_200(self):
        url = self.project.web_url_for('project_wiki_view', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_url_404_with_no_write_permission(self):
        url = self.project.web_url_for('project_wiki_view', wname='somerandomid')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 404)

    @mock.patch('website.addons.wiki.utils.broadcast_to_sharejs')
    def test_wiki_deleted_404_with_no_write_permission(self, mock_sharejs):
        self.project.update_node_wiki('funpage', 'Version 1', Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_view', wname='funpage')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)
        delete_url = self.project.api_url_for('project_wiki_delete', wname='funpage')
        self.app.delete(delete_url, auth=self.user.auth)
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_wiki_url_with_path_get_returns_200(self):
        self.project.update_node_wiki('funpage', 'Version 1', Auth(self.user))
        self.project.update_node_wiki('funpage', 'Version 2', Auth(self.user))
        self.project.save()

        url = self.project.web_url_for(
            'project_wiki_view',
            wname='funpage',
        ) + '?view&compare=1&edit'
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_wiki_url_with_edit_get_returns_404_with_no_write_permission(self):
        self.project.update_node_wiki('funpage', 'Version 1', Auth(self.user))
        self.project.update_node_wiki('funpage', 'Version 2', Auth(self.user))
        self.project.save()

        url = self.project.web_url_for(
            'project_wiki_view',
            wname='funpage',
            compare=1,
        )
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

        url = self.project.web_url_for(
            'project_wiki_view',
            wname='funpage',
        ) + '?edit'
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_wiki_url_for_pointer_returns_200(self):
        # TODO: explain how this tests a pointer
        project = ProjectFactory(is_public=True)
        self.project.add_pointer(project, Auth(self.project.creator), save=True)
        url = self.project.web_url_for('project_wiki_view', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_draft_returns_200(self):
        url = self.project.api_url_for('wiki_page_draft', wname='somerandomid')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_wiki_content_returns_200(self):
        url = self.project.api_url_for('wiki_page_content', wname='somerandomid')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    @mock.patch('website.addons.wiki.model.NodeWikiPage.rendered_before_update', new_callable=mock.PropertyMock)
    def test_wiki_content_use_python_render(self, mock_rendered_before_update):
        content = 'Some content'
        self.project.update_node_wiki('somerandomid', content, Auth(self.user))
        self.project.save()

        mock_rendered_before_update.return_value = True
        url = self.project.api_url_for('wiki_page_content', wname='somerandomid')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(content, res.json['wiki_content'])
        assert_in(content, res.json['wiki_rendered'])

        mock_rendered_before_update.return_value = False
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(content, res.json['wiki_content'])
        assert_equal('', res.json['wiki_rendered'])


    def test_wiki_url_for_component_returns_200(self):
        component = NodeFactory(project=self.project, is_public=True)
        url = component.web_url_for('project_wiki_view', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_serialize_wiki_toc(self):
        project = ProjectFactory()
        auth = Auth(project.creator)
        NodeFactory(parent=project, creator=project.creator)
        no_wiki = NodeFactory(parent=project, creator=project.creator)
        project.save()

        serialized = _serialize_wiki_toc(project, auth=auth)
        assert_equal(len(serialized), 2)
        no_wiki.delete_addon('wiki', auth=auth)
        serialized = _serialize_wiki_toc(project, auth=auth)
        assert_equal(len(serialized), 1)

    def test_get_wiki_url_pointer_component(self):
        """Regression test for issues
        https://github.com/CenterForOpenScience/osf/issues/363 and
        https://github.com/CenterForOpenScience/openscienceframework.org/issues/574

        """
        user = UserFactory()
        pointed_node = NodeFactory(creator=user)
        project = ProjectFactory(creator=user)
        auth = Auth(user=user)
        project.add_pointer(pointed_node, auth=auth, save=True)

        serialized = _serialize_wiki_toc(project, auth)
        assert_equal(
            serialized[0]['url'],
            pointed_node.web_url_for('project_wiki_view', wname='home', _guid=True)
        )

    def test_project_wiki_edit_post(self):
        self.project.update_node_wiki(
            'home',
            content='old content',
            auth=Auth(self.project.creator)
        )
        url = self.project.web_url_for('project_wiki_edit_post', wname='home')
        res = self.app.post(url, {'content': 'new content'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        # page was updated with new content
        new_wiki = self.project.get_wiki_page('home')
        assert_equal(new_wiki.content, 'new content')

    def test_project_wiki_edit_post_with_new_wname_and_no_content(self):
        # note: forward slashes not allowed in page_name
        page_name = fake.catch_phrase().replace('/', ' ')

        old_wiki_page_count = NodeWikiPage.find().count()
        url = self.project.web_url_for('project_wiki_edit_post', wname=page_name)
        # User submits to edit form with no content
        res = self.app.post(url, {'content': ''}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        new_wiki_page_count = NodeWikiPage.find().count()
        # A new wiki page was created in the db
        assert_equal(new_wiki_page_count, old_wiki_page_count + 1)

        # Node now has the new wiki page associated with it
        self.project.reload()
        new_page = self.project.get_wiki_page(page_name)
        assert_is_not_none(new_page)

    def test_project_wiki_edit_post_with_new_wname_and_content(self):
        # note: forward slashes not allowed in page_name
        page_name = fake.catch_phrase().replace('/' , ' ')
        page_content = fake.bs()

        old_wiki_page_count = NodeWikiPage.find().count()
        url = self.project.web_url_for('project_wiki_edit_post', wname=page_name)
        # User submits to edit form with no content
        res = self.app.post(url, {'content': page_content}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        new_wiki_page_count = NodeWikiPage.find().count()
        # A new wiki page was created in the db
        assert_equal(new_wiki_page_count, old_wiki_page_count + 1)

        # Node now has the new wiki page associated with it
        self.project.reload()
        new_page = self.project.get_wiki_page(page_name)
        assert_is_not_none(new_page)
        # content was set
        assert_equal(new_page.content, page_content)

    def test_project_wiki_edit_post_with_non_ascii_title(self):
        # regression test for https://github.com/CenterForOpenScience/openscienceframework.org/issues/1040
        # wname doesn't exist in the db, so it will be created
        new_wname = u'øˆ∆´ƒøßå√ß'
        url = self.project.web_url_for('project_wiki_edit_post', wname=new_wname)
        res = self.app.post(url, {'content': 'new content'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        wiki = self.project.get_wiki_page(new_wname)
        assert_equal(wiki.page_name, new_wname)

        # updating content should return correct url as well.
        res = self.app.post(url, {'content': 'updated content'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

    def test_project_wiki_edit_post_with_special_characters(self):
        new_wname = 'title: ' + SPECIAL_CHARACTERS_ALLOWED
        new_wiki_content = 'content: ' + SPECIAL_CHARACTERS_ALL
        url = self.project.web_url_for('project_wiki_edit_post', wname=new_wname)
        res = self.app.post(url, {'content': new_wiki_content}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        wiki = self.project.get_wiki_page(new_wname)
        assert_equal(wiki.page_name, new_wname)
        assert_equal(wiki.content, new_wiki_content)
        assert_equal(res.status_code, 200)

    def test_wiki_edit_get_home(self):
        url = self.project.web_url_for('project_wiki_view', wname='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_project_wiki_view_scope(self):
        self.project.update_node_wiki('home', 'Version 1', Auth(self.user))
        self.project.update_node_wiki('home', 'Version 2', Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_view', wname='home', view=2)
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        url = self.project.web_url_for('project_wiki_view', wname='home', view=3)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        url = self.project.web_url_for('project_wiki_view', wname='home', view=0)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)

    def test_project_wiki_compare_returns_200(self):
        self.project.update_node_wiki('home', 'updated content', Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_view', wname='home') + '?compare'
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_project_wiki_compare_scope(self):
        self.project.update_node_wiki('home', 'Version 1', Auth(self.user))
        self.project.update_node_wiki('home', 'Version 2', Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_view', wname='home', compare=2)
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        url = self.project.web_url_for('project_wiki_view', wname='home', compare=3)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        url = self.project.web_url_for('project_wiki_view', wname='home', compare=0)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)

    def test_wiki_page_creation_strips_whitespace(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1080
        # wname has a trailing space
        url = self.project.web_url_for('project_wiki_view', wname='cupcake ')
        res = self.app.post(url, {'content': 'blah'}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        self.project.reload()
        wiki = self.project.get_wiki_page('cupcake')
        assert_is_not_none(wiki)

    def test_wiki_validate_name(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='Capslock')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_wiki_validate_name_cannot_create_home(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='home')
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_project_wiki_validate_name_mixed_casing(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='CaPsLoCk')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_not_in('capslock', self.project.wiki_pages_current)
        self.project.update_node_wiki('CaPsLoCk', 'hello', self.consolidate_auth)
        assert_in('capslock', self.project.wiki_pages_current)

    def test_project_wiki_validate_name_diplay_correct_capitalization(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='CaPsLoCk')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_in('CaPsLoCk', res)

    def test_project_wiki_validate_name_conflict_different_casing(self):
        url = self.project.api_url_for('project_wiki_validate_name', wname='CAPSLOCK')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        self.project.update_node_wiki('CaPsLoCk', 'hello', self.consolidate_auth)
        assert_in('capslock', self.project.wiki_pages_current)
        url = self.project.api_url_for('project_wiki_validate_name', wname='capslock')
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_project_dashboard_shows_no_wiki_content_text(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104
        project = ProjectFactory(creator=self.user)
        url = project.web_url_for('view_project')
        res = self.app.get(url, auth=self.user.auth)
        assert_in('No wiki content', res)

    def test_project_dashboard_wiki_wname_get_shows_non_ascii_characters(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104
        text = u'你好'
        self.project.update_node_wiki('home', text, Auth(self.user))

        # can view wiki preview from project dashboard
        url = self.project.web_url_for('view_project')
        res = self.app.get(url, auth=self.user.auth)
        assert_in(text, res)

    def test_project_wiki_home_api_route(self):
        url = self.project.api_url_for('project_wiki_home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equals(res.status_code, 302)
        # TODO: should this route exist? it redirects you to the web_url_for, not api_url_for.
        # page_url = self.project.api_url_for('project_wiki_view', wname='home')
        # assert_in(page_url, res.location)

    def test_project_wiki_home_web_route(self):
        page_url = self.project.web_url_for('project_wiki_view', wname='home', _guid=True)
        url = self.project.web_url_for('project_wiki_home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equals(res.status_code, 302)
        assert_in(page_url, res.location)

    def test_wiki_id_url_get_returns_302_and_resolves(self):
        name = 'page by id'
        self.project.update_node_wiki(name, 'some content', Auth(self.project.creator))
        page = self.project.get_wiki_page(name)
        page_url = self.project.web_url_for('project_wiki_view', wname=page.page_name, _guid=True)
        url = self.project.web_url_for('project_wiki_id_page', wid=page._primary_key, _guid=True)
        res = self.app.get(url)
        assert_equal(res.status_code, 302)
        assert_in(page_url, res.location)
        res = res.follow()
        assert_equal(res.status_code, 200)
        assert_in(page_url, res.request.url)

    def test_wiki_id_url_get_returns_404(self):
        url = self.project.web_url_for('project_wiki_id_page', wid='12345', _guid=True)
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_home_is_capitalized_in_web_view(self):
        url = self.project.web_url_for('project_wiki_home', wid='home', _guid=True)
        res = self.app.get(url, auth=self.user.auth).follow(auth=self.user.auth)
        page_name_elem = res.html.find('span', {'id': 'pageName'})
        assert_in('Home', page_name_elem.text)

    def test_wiki_widget_no_content(self):
        url = self.project.api_url_for('wiki_widget', wid='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_is_none(res.json['wiki_content'])

    def test_wiki_widget_short_content_no_cutoff(self):
        short_content = 'a' * 150
        self.project.update_node_wiki('home', short_content, Auth(self.user))
        url = self.project.api_url_for('wiki_widget', wid='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_in(short_content, res.json['wiki_content'])
        assert_not_in('...', res.json['wiki_content'])
        assert_false(res.json['more'])

    def test_wiki_widget_long_content_cutoff(self):
        long_content = 'a' * 600
        self.project.update_node_wiki('home', long_content, Auth(self.user))
        url = self.project.api_url_for('wiki_widget', wid='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_less(len(res.json['wiki_content']), 520)  # wiggle room for closing tags
        assert_in('...', res.json['wiki_content'])
        assert_true(res.json['more'])

    @mock.patch('website.addons.wiki.model.NodeWikiPage.rendered_before_update', new_callable=mock.PropertyMock)
    def test_wiki_widget_use_python_render(self, mock_rendered_before_update):
        # New pages use js renderer
        mock_rendered_before_update.return_value = False
        self.project.update_node_wiki('home', 'updated content', Auth(self.user))
        url = self.project.api_url_for('wiki_widget', wid='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_false(res.json['use_python_render'])

        # Old pages use python renderer
        mock_rendered_before_update.return_value = True
        res = self.app.get(url, auth=self.user.auth)
        assert_true(res.json['use_python_render'])

    def test_read_only_users_cannot_view_edit_pane(self):
        url = self.project.web_url_for('project_wiki_view', wname='home')
        # No write permissions
        res = self.app.get(url)
        assert_equal(res.status_code, 200)
        assert_not_in('data-osf-panel="Edit"', res.text)
        # Write permissions
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_in('data-osf-panel="Edit"', res.text)
class TestNodeLinksList(ApiTestCase):

    def setUp(self):
        super(TestNodeLinksList, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=False, creator=self.user)
        self.pointer_project = ProjectFactory(is_public=False, creator=self.user)
        self.project.add_pointer(self.pointer_project, auth=Auth(self.user))
        self.private_url = '/{}nodes/{}/node_links/'.format(API_BASE, self.project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project.add_pointer(self.public_pointer_project, auth=Auth(self.user))
        self.public_url = '/{}nodes/{}/node_links/'.format(API_BASE, self.public_project._id)

        self.user_two = AuthUserFactory()

    def test_return_embedded_public_node_pointers_logged_out(self):
        res = self.app.get(self.public_url)
        res_json = res.json['data']
        assert_equal(len(res_json), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')

        embedded = res_json[0]['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.public_pointer_project._id)

    def test_return_embedded_public_node_pointers_logged_in(self):
        res = self.app.get(self.public_url, auth=self.user_two.auth)
        res_json = res.json['data']
        assert_equal(len(res_json), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        embedded = res_json[0]['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.public_pointer_project._id)

    def test_return_private_node_pointers_logged_out(self):
        res = self.app.get(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    def test_return_private_node_pointers_logged_in_contributor(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        res_json = res.json['data']
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(len(res_json), 1)
        embedded = res_json[0]['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.pointer_project._id)

    def test_return_private_node_pointers_logged_in_non_contributor(self):
        res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    def test_deleted_links_not_returned(self):
        res = self.app.get(self.public_url, expect_errors=True)
        res_json = res.json['data']
        original_length = len(res_json)

        self.public_pointer_project.is_deleted = True
        self.public_pointer_project.save()

        res = self.app.get(self.public_url)
        res_json = res.json['data']
        assert_equal(len(res_json), original_length - 1)

    def test_cannot_access_retracted_node_links_list(self):
        registration = RegistrationFactory(creator=self.user, project=self.public_project)
        url = '/{}nodes/{}/node_links/'.format(API_BASE, registration._id)
        retraction = RetractedRegistrationFactory(registration=registration, user=registration.creator)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)
class TestNodeLinksList(ApiTestCase):
    def setUp(self):
        super(TestNodeLinksList, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=False, creator=self.user)
        self.pointer_project = ProjectFactory(is_public=False, creator=self.user)
        self.project.add_pointer(self.pointer_project, auth=Auth(self.user))
        self.private_url = "/{}nodes/{}/node_links/".format(API_BASE, self.project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project.add_pointer(self.public_pointer_project, auth=Auth(self.user))
        self.public_url = "/{}nodes/{}/node_links/".format(API_BASE, self.public_project._id)

        self.user_two = AuthUserFactory()

    def test_return_embedded_public_node_pointers_logged_out(self):
        res = self.app.get(self.public_url)
        res_json = res.json["data"]
        assert_equal(len(res_json), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, "application/vnd.api+json")

        embedded = res_json[0]["embeds"]["target_node"]["data"]["id"]
        assert_equal(embedded, self.public_pointer_project._id)

    def test_return_embedded_public_node_pointers_logged_in(self):
        res = self.app.get(self.public_url, auth=self.user_two.auth)
        res_json = res.json["data"]
        assert_equal(len(res_json), 1)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, "application/vnd.api+json")
        embedded = res_json[0]["embeds"]["target_node"]["data"]["id"]
        assert_equal(embedded, self.public_pointer_project._id)

    def test_return_private_node_pointers_logged_out(self):
        res = self.app.get(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in("detail", res.json["errors"][0])

    def test_return_private_node_pointers_logged_in_contributor(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        res_json = res.json["data"]
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, "application/vnd.api+json")
        assert_equal(len(res_json), 1)
        embedded = res_json[0]["embeds"]["target_node"]["data"]["id"]
        assert_equal(embedded, self.pointer_project._id)

    def test_return_private_node_pointers_logged_in_non_contributor(self):
        res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in("detail", res.json["errors"][0])

    def test_deleted_links_not_returned(self):
        res = self.app.get(self.public_url, expect_errors=True)
        res_json = res.json["data"]
        original_length = len(res_json)

        self.public_pointer_project.is_deleted = True
        self.public_pointer_project.save()

        res = self.app.get(self.public_url)
        res_json = res.json["data"]
        assert_equal(len(res_json), original_length - 1)

    def test_cannot_access_retracted_node_links_list(self):
        registration = RegistrationFactory(creator=self.user, project=self.public_project)
        url = "/{}nodes/{}/node_links/".format(API_BASE, registration._id)
        retraction = RetractedRegistrationFactory(registration=registration, user=registration.creator)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)
class TestPopulateNewAndNoteworthy(OsfTestCase):

    def setUp(self):
        super(TestPopulateNewAndNoteworthy, self).setUp()
        self.pop1 = ProjectFactory()
        self.pop2 = ProjectFactory()
        self.pop3 = ProjectFactory()
        self.pop4 = ProjectFactory()
        self.pop5 = ProjectFactory()

        self.nn1 = ProjectFactory(is_public=True)
        self.nn2 = ProjectFactory(is_public=True)
        self.nn3 = ProjectFactory(is_public=True)
        self.nn4 = ProjectFactory(is_public=True)
        self.nn5 = ProjectFactory(is_public=True)

        self.user = UserFactory()

        today = datetime.datetime.now()
        self.last_month = (today - dateutil.relativedelta.relativedelta(months=1)).isoformat()

        popular_json = {"popular_node_ids": [self.pop1._id, self.pop2._id, self.pop3._id, self.pop4._id, self.pop5._id]}
        self.popular_json_body = json.dumps(popular_json)

    def tearDown(self):
        super(TestPopulateNewAndNoteworthy, self).tearDown()
        Node.remove()

    def test_get_new_and_noteworthy_nodes(self):
        new_noteworthy = script.get_new_and_noteworthy_nodes()
        assert_equal(set(new_noteworthy), {self.nn1._id, self.nn2._id, self.nn3._id, self.nn4._id, self.nn5._id})

    def test_populate_new_and_noteworthy(self):
        self.popular_links_node = ProjectFactory(creator=self.user)
        self.popular_links_node._id = POPULAR_LINKS_NODE
        self.popular_links_node.save()
        self.new_and_noteworthy_links_node = ProjectFactory()
        self.new_and_noteworthy_links_node._id = NEW_AND_NOTEWORTHY_LINKS_NODE
        self.new_and_noteworthy_links_node.save()

        popular_nodes = [self.pop1, self.pop2, self.pop3, self.pop4, self.pop5]

        for node in popular_nodes:
            self.popular_links_node.add_pointer(node, auth=Auth(self.user), save=True)

        assert_equal(len(self.popular_links_node.nodes), 5)
        assert_equal(len(self.new_and_noteworthy_links_node.nodes), 0)


        script.main(dry_run=False)
        self.popular_links_node.reload()
        self.new_and_noteworthy_links_node.reload()

        assert_equal(len(self.popular_links_node.nodes), 0)  # verifies remove pointer is working
        assert_equal(len(self.new_and_noteworthy_links_node.nodes), 5)

        script.main(dry_run=False)

        self.popular_links_node.reload()
        self.new_and_noteworthy_links_node.reload()

        popular_node_links = [pointer.node._id for pointer in self.popular_links_node.nodes]
        assert_equal(popular_node_links, [])

        new_and_noteworthy_node_links = {pointer.node._id for pointer in self.new_and_noteworthy_links_node.nodes}

        assert_equal(set(new_and_noteworthy_node_links), {self.nn1._id, self.nn2._id, self.nn3._id, self.nn4._id, self.nn5._id})
class TestNodeLogList(ApiTestCase):
    def setUp(self):
        super(TestNodeLogList, self).setUp()
        self.user = AuthUserFactory()
        self.contrib = AuthUserFactory()
        self.creator = AuthUserFactory()
        self.user_auth = Auth(self.user)
        self.NodeLogFactory = ProjectFactory()
        self.pointer = ProjectFactory()

        self.private_project = ProjectFactory(is_public=False, creator=self.user)
        self.private_url = '/{}nodes/{}/logs/'.format(API_BASE, self.private_project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_url = '/{}nodes/{}/logs/'.format(API_BASE, self.public_project._id)

    def tearDown(self):
        super(TestNodeLogList, self).tearDown()
        NodeLog.remove()

    def test_add_tag(self):
        user_auth = Auth(self.user)
        self.public_project.add_tag("Jeff Spies", auth=user_auth)
        assert_equal("tag_added", self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'], 'tag_added')
        assert_equal("Jeff Spies", self.public_project.logs[OSF_LATEST].params['tag'])

    def test_remove_tag(self):
        user_auth = Auth(self.user)
        self.public_project.add_tag("Jeff Spies", auth=user_auth)
        assert_equal("tag_added", self.public_project.logs[OSF_LATEST].action)
        self.public_project.remove_tag("Jeff Spies", auth=self.user_auth)
        assert_equal("tag_removed", self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'], 'tag_removed')
        assert_equal("Jeff Spies", self.public_project.logs[OSF_LATEST].params['tag'])

    def test_project_created(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(self.public_project.logs[OSF_FIRST].action, "project_created")
        assert_equal(self.public_project.logs[OSF_FIRST].action,res.json['data'][API_LATEST]['attributes']['action'])

    def test_log_create_on_public_project(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_datetime_equal(parse_date(res.json['data'][API_FIRST]['attributes']['date']),
                              self.public_project.logs[OSF_FIRST].date)
        assert_equal(res.json['data'][API_FIRST]['attributes']['action'], self.public_project.logs[OSF_FIRST].action)

    def test_log_create_on_private_project(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_datetime_equal(datetime.datetime.strptime(res.json['data'][API_FIRST]['attributes']['date'], "%Y-%m-%dT%H:%M:%S.%f"),
                              self.private_project.logs[OSF_FIRST].date)
        assert_equal(res.json['data'][API_FIRST]['attributes']['action'], self.private_project.logs[OSF_FIRST].action)

    def test_add_addon(self):
        self.public_project.add_addon('github', auth=self.user_auth)
        assert_equal('addon_added', self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'], 'addon_added')

    def test_project_add_remove_contributor(self):
        self.public_project.add_contributor(self.contrib, auth=self.user_auth)
        assert_equal('contributor_added', self.public_project.logs[OSF_LATEST].action)
        self.public_project.remove_contributor(self.contrib, auth=self.user_auth)
        assert_equal('contributor_removed', self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'], 'contributor_removed')
        assert_equal(res.json['data'][1]['attributes']['action'], 'contributor_added')

    def test_remove_addon(self):
        self.public_project.add_addon('github', auth=self.user_auth)
        assert_equal('addon_added', self.public_project.logs[OSF_LATEST].action)
        self.public_project.delete_addon('github', auth=self.user_auth)
        assert_equal('addon_removed', self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'], 'addon_removed')

    def test_add_pointer(self):
        self.public_project.add_pointer(self.pointer, auth=Auth(self.user), save=True)
        assert_equal('pointer_created', self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'], 'pointer_created')
Exemple #28
0
class TestNodeLogList(ApiTestCase):
    def setUp(self):
        super(TestNodeLogList, self).setUp()
        self.user = AuthUserFactory()
        self.contrib = AuthUserFactory()
        self.creator = AuthUserFactory()
        self.user_auth = Auth(self.user)
        self.NodeLogFactory = ProjectFactory()
        self.pointer = ProjectFactory()

        self.private_project = ProjectFactory(is_public=False,
                                              creator=self.user)
        self.private_url = '/{}nodes/{}/logs/'.format(API_BASE,
                                                      self.private_project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_url = '/{}nodes/{}/logs/'.format(API_BASE,
                                                     self.public_project._id)

    def tearDown(self):
        super(TestNodeLogList, self).tearDown()
        NodeLog.remove()

    def test_add_tag(self):
        user_auth = Auth(self.user)
        self.public_project.add_tag("Jeff Spies", auth=user_auth)
        assert_equal("tag_added", self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'],
                     'tag_added')
        assert_equal("Jeff Spies",
                     self.public_project.logs[OSF_LATEST].params['tag'])

    def test_remove_tag(self):
        user_auth = Auth(self.user)
        self.public_project.add_tag("Jeff Spies", auth=user_auth)
        assert_equal("tag_added", self.public_project.logs[OSF_LATEST].action)
        self.public_project.remove_tag("Jeff Spies", auth=self.user_auth)
        assert_equal("tag_removed",
                     self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'],
                     'tag_removed')
        assert_equal("Jeff Spies",
                     self.public_project.logs[OSF_LATEST].params['tag'])

    def test_project_created(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(self.public_project.logs[OSF_FIRST].action,
                     "project_created")
        assert_equal(self.public_project.logs[OSF_FIRST].action,
                     res.json['data'][API_LATEST]['attributes']['action'])

    def test_log_create_on_public_project(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_datetime_equal(
            parse_date(res.json['data'][API_FIRST]['attributes']['date']),
            self.public_project.logs[OSF_FIRST].date)
        assert_equal(res.json['data'][API_FIRST]['attributes']['action'],
                     self.public_project.logs[OSF_FIRST].action)

    def test_log_create_on_private_project(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_datetime_equal(
            datetime.datetime.strptime(
                res.json['data'][API_FIRST]['attributes']['date'],
                "%Y-%m-%dT%H:%M:%S.%f"),
            self.private_project.logs[OSF_FIRST].date)
        assert_equal(res.json['data'][API_FIRST]['attributes']['action'],
                     self.private_project.logs[OSF_FIRST].action)

    def test_add_addon(self):
        self.public_project.add_addon('github', auth=self.user_auth)
        assert_equal('addon_added',
                     self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'],
                     'addon_added')

    def test_project_add_remove_contributor(self):
        self.public_project.add_contributor(self.contrib, auth=self.user_auth)
        assert_equal('contributor_added',
                     self.public_project.logs[OSF_LATEST].action)
        self.public_project.remove_contributor(self.contrib,
                                               auth=self.user_auth)
        assert_equal('contributor_removed',
                     self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'],
                     'contributor_removed')
        assert_equal(res.json['data'][1]['attributes']['action'],
                     'contributor_added')

    def test_remove_addon(self):
        self.public_project.add_addon('github', auth=self.user_auth)
        assert_equal('addon_added',
                     self.public_project.logs[OSF_LATEST].action)
        self.public_project.delete_addon('github', auth=self.user_auth)
        assert_equal('addon_removed',
                     self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'],
                     'addon_removed')

    def test_add_pointer(self):
        self.public_project.add_pointer(self.pointer,
                                        auth=Auth(self.user),
                                        save=True)
        assert_equal('pointer_created',
                     self.public_project.logs[OSF_LATEST].action)
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), len(self.public_project.logs))
        assert_equal(res.json['data'][API_LATEST]['attributes']['action'],
                     'pointer_created')
class TestNodeForkCreate(ApiTestCase):

    def setUp(self):
        super(TestNodeForkCreate, self).setUp()
        self.user = AuthUserFactory()
        self.user_two = AuthUserFactory()
        self.user_three = AuthUserFactory()
        self.private_project = ProjectFactory(creator=self.user)

        self.fork_data = {
            'data': {
                'type': 'nodes'
            }
        }

        self.fork_data_with_title = {
            'data': {
                'type': 'nodes',
                'attributes':
                    {'title': 'My Forked Project'}
            }
        }

        self.private_project_url = '/{}nodes/{}/forks/'.format(API_BASE, self.private_project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project_url = '/{}nodes/{}/forks/'.format(API_BASE, self.public_project._id)

    def tearDown(self):
        super(TestNodeForkCreate, self).tearDown()
        Node.remove()

    def test_create_fork_from_public_project_with_new_title(self):
        res = self.app.post_json_api(self.public_project_url, self.fork_data_with_title, auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.public_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'], self.fork_data_with_title['data']['attributes']['title'])

    def test_create_fork_from_private_project_with_new_title(self):
        res = self.app.post_json_api(self.private_project_url, self.fork_data_with_title, auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.private_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'], self.fork_data_with_title['data']['attributes']['title'])

    def test_can_fork_public_node_logged_in(self):
        res = self.app.post_json_api(self.public_project_url, self.fork_data, auth=self.user_two.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.public_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'], 'Fork of ' + self.public_project.title)

    def test_cannot_fork_public_node_logged_out(self):
        res = self.app.post_json_api(self.public_project_url, self.fork_data, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.')

    def test_can_fork_public_node_logged_in_contributor(self):
        res = self.app.post_json_api(self.public_project_url, self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.public_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'], 'Fork of ' + self.public_project.title)

    def test_cannot_fork_private_node_logged_out(self):
        res = self.app.post_json_api(self.private_project_url, self.fork_data, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.')

    def test_cannot_fork_private_node_logged_in_non_contributor(self):
        res = self.app.post_json_api(self.private_project_url, self.fork_data, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.')

    def test_can_fork_private_node_logged_in_contributor(self):
        res = self.app.post_json_api(self.private_project_url + '?embed=children&embed=node_links&embed=logs&embed=contributors&embed=forked_from', self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)

        data = res.json['data']
        assert_equal(data['attributes']['title'], 'Fork of ' + self.private_project.title)

        fork_contributors = data['embeds']['contributors']['data'][0]['embeds']['users']['data']
        assert_equal(fork_contributors['attributes']['family_name'], self.user.family_name)
        assert_equal(fork_contributors['id'], self.user._id)

        forked_from = data['embeds']['forked_from']['data']
        assert_equal(forked_from['id'], self.private_project._id)

    def test_fork_private_components_no_access(self):
        url = self.public_project_url + '?embed=children'
        private_component = NodeFactory(parent=self.public_project, creator=self.user_two, is_public=False)
        res = self.app.post_json_api(url, self.fork_data, auth=self.user_three.auth)
        assert_equal(res.status_code, 201)
        # Private components that you do not have access to are not forked
        assert_equal(res.json['data']['embeds']['children']['links']['meta']['total'], 0)

    def test_fork_components_you_can_access(self):
        url = self.private_project_url + '?embed=children'
        new_component = NodeFactory(parent=self.private_project, creator=self.user)
        res = self.app.post_json_api(url, self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['embeds']['children']['links']['meta']['total'], 1)
        assert_equal(res.json['data']['embeds']['children']['data'][0]['id'], new_component.forks[0]._id)

    def test_fork_private_node_links(self):
        private_pointer = ProjectFactory(creator=self.user_two)
        actual_pointer = self.private_project.add_pointer(private_pointer, auth=Auth(self.user_two), save=True)

        url = self.private_project_url + '?embed=node_links'

        # Node link is forked, but shows up as a private node link
        res = self.app.post_json_api(url, self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)

        assert_equal(res.json['data']['embeds']['node_links']['data'][0]['embeds']['target_node']['errors'][0]['detail'],
                     'You do not have permission to perform this action.')
        assert_equal(res.json['data']['embeds']['node_links']['links']['meta']['total'], 1)

        self.private_project.rm_pointer(actual_pointer, auth=Auth(self.user_two))

    def test_fork_node_links_you_can_access(self):
        pointer = ProjectFactory(creator=self.user)
        self.private_project.add_pointer(pointer, auth=Auth(self.user_two), save=True)

        url = self.private_project_url + '?embed=node_links'

        res = self.app.post_json_api(url, self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)

        assert_equal(res.json['data']['embeds']['node_links']['data'][0]['embeds']['target_node']['data']['id'], pointer._id)
        assert_equal(res.json['data']['embeds']['node_links']['links']['meta']['total'], 1)

    def test_can_fork_registration(self):
        registration = RegistrationFactory(project=self.private_project, user=self.user)

        url = '/{}registrations/{}/forks/'.format(API_BASE, registration._id)
        res = self.app.post_json_api(url, self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], registration.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'], 'Fork of ' + registration.title)

    def test_read_only_contributor_can_fork_private_registration(self):
        read_only_user = AuthUserFactory()

        self.private_project.add_contributor(read_only_user, permissions=[permissions.READ], save=True)
        res = self.app.post_json_api(self.private_project_url, self.fork_data, auth=read_only_user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.private_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'], 'Fork of ' + self.private_project.title)
class TestDeleteNodeLink(ApiTestCase):

    def setUp(self):
        super(TestDeleteNodeLink, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(creator=self.user, is_public=False)
        self.pointer_project = ProjectFactory(creator=self.user, is_public=True)
        self.pointer = self.project.add_pointer(self.pointer_project, auth=Auth(self.user), save=True)
        self.private_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.project._id, self.pointer._id)

        self.user_two = AuthUserFactory()

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_pointer = self.public_project.add_pointer(self.public_pointer_project,
                                                              auth=Auth(self.user),
                                                              save=True)
        self.public_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.public_project._id, self.public_pointer._id)

    def test_delete_node_link_no_permissions_for_target_node(self):
        pointer_project = ProjectFactory(creator=self.user_two, is_public=False)
        pointer = self.public_project.add_pointer(pointer_project, auth=Auth(self.user), save=True)
        assert_in(pointer, self.public_project.nodes)
        url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.public_project._id, pointer._id)
        res = self.app.delete_json_api(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 204)

        self.public_project.reload()
        assert_not_in(pointer, self.public_project.nodes)

    def test_cannot_delete_if_registration(self):
        registration = RegistrationFactory(project=self.public_project)

        url = '/{}registrations/{}/node_links/'.format(
            API_BASE,
            registration._id,
        )
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        pointer_id = res.json['data'][0]['id']

        url = '/{}nodes/{}/node_links/{}/'.format(
            API_BASE,
            registration._id,
            pointer_id,
        )
        res = self.app.delete(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_deletes_public_node_pointer_logged_out(self):
        res = self.app.delete(self.public_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0].keys())

    def test_deletes_public_node_pointer_fails_if_bad_auth(self):
        node_count_before = len(self.public_project.nodes_pointer)
        res = self.app.delete(self.public_url, auth=self.user_two.auth, expect_errors=True)
        # This is could arguably be a 405, but we don't need to go crazy with status codes
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])
        self.public_project.reload()
        assert_equal(node_count_before, len(self.public_project.nodes_pointer))

    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project')
    def test_deletes_public_node_pointer_succeeds_as_owner(self):
        node_count_before = len(self.public_project.nodes_pointer)
        res = self.app.delete(self.public_url, auth=self.user.auth)
        self.public_project.reload()
        assert_equal(res.status_code, 204)
        assert_equal(node_count_before - 1, len(self.public_project.nodes_pointer))

    def test_deletes_private_node_pointer_logged_out(self):
        res = self.app.delete(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.POINTER_REMOVED, 'project')
    def test_deletes_private_node_pointer_logged_in_contributor(self):
        res = self.app.delete(self.private_url, auth=self.user.auth)
        self.project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)
        assert_equal(len(self.project.nodes_pointer), 0)

    def test_deletes_private_node_pointer_logged_in_non_contributor(self):
        res = self.app.delete(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.POINTER_REMOVED, 'public_project')
    def test_return_deleted_public_node_pointer(self):
        res = self.app.delete(self.public_url, auth=self.user.auth)
        self.public_project.reload() # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)

        #check that deleted pointer can not be returned
        res = self.app.get(self.public_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    @assert_logs(NodeLog.POINTER_REMOVED, 'project')
    def test_return_deleted_private_node_pointer(self):
        res = self.app.delete(self.private_url, auth=self.user.auth)
        self.project.reload()  # Update the model to reflect changes made by post request
        assert_equal(res.status_code, 204)

        #check that deleted pointer can not be returned
        res = self.app.get(self.private_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    # Regression test for https://openscience.atlassian.net/browse/OSF-4322
    def test_delete_link_that_is_not_linked_to_correct_node(self):
        project = ProjectFactory(creator=self.user)
        # The node link belongs to a different project
        res = self.app.delete(
            '/{}nodes/{}/node_links/{}/'.format(API_BASE, project._id, self.public_pointer._id),
            auth=self.user.auth,
            expect_errors=True
        )
        assert_equal(res.status_code, 404)
        errors = res.json['errors']
        assert_equal(len(errors), 1)
        assert_equal(errors[0]['detail'], 'Node link does not belong to the requested node.')
class TestNodeForksList(ApiTestCase):
    def setUp(self):
        super(TestNodeForksList, self).setUp()
        self.user = AuthUserFactory()
        self.private_project = ProjectFactory()
        self.private_project.add_contributor(self.user, permissions=[permissions.READ, permissions.WRITE])
        self.private_project.save()
        self.component = NodeFactory(parent=self.private_project, creator=self.user)
        self.pointer = ProjectFactory(creator=self.user)
        self.private_project.add_pointer(self.pointer, auth=Auth(self.user), save=True)
        self.private_fork = ForkFactory(project=self.private_project, user=self.user)
        self.private_project_url = '/{}nodes/{}/forks/'.format(API_BASE, self.private_project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project.save()
        self.public_component = NodeFactory(parent=self.public_project, creator=self.user, is_public=True)
        self.public_project_url = '/{}nodes/{}/forks/'.format(API_BASE, self.public_project._id)
        self.public_fork = ForkFactory(project=self.public_project, user=self.user)
        self.user_two = AuthUserFactory()

    def test_can_access_public_node_forks_list_when_unauthenticated(self):
        res = self.app.get(self.public_project_url)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), 0)
        # Fork defaults to private
        assert_equal(self.public_fork.is_public, False)

        self.public_fork.is_public = True
        self.public_fork.save()

        res = self.app.get(self.public_project_url)
        assert_equal(len(res.json['data']), 1)
        assert_equal(self.public_fork.is_public, True)
        data = res.json['data'][0]
        assert_equal(data['attributes']['title'], 'Fork of ' + self.public_project.title)
        assert_equal(data['id'], self.public_fork._id)
        assert_equal(data['attributes']['registration'], False)
        assert_equal(data['attributes']['fork'], True)

    def test_can_access_public_node_forks_list_authenticated_contributor(self):
        res = self.app.get(self.public_project_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(self.public_fork.is_public, False)
        assert_equal(len(res.json['data']), 1)
        data = res.json['data'][0]
        assert_equal(data['attributes']['title'], 'Fork of ' + self.public_project.title)
        assert_equal(data['id'], self.public_fork._id)
        assert_equal(data['attributes']['registration'], False)
        assert_equal(data['attributes']['fork'], True)

    def test_can_access_public_node_forks_list_authenticated_non_contributor(self):
        res = self.app.get(self.public_project_url, auth=self.user_two.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), 0)
        # Fork defaults to private
        assert_equal(self.public_fork.is_public, False)

        self.public_fork.is_public = True
        self.public_fork.save()

        res = self.app.get(self.public_project_url)
        assert_equal(len(res.json['data']), 1)
        assert_equal(self.public_fork.is_public, True)
        data = res.json['data'][0]
        assert_equal(data['attributes']['title'], 'Fork of ' + self.public_project.title)
        assert_equal(data['id'], self.public_fork._id)
        assert_equal(data['attributes']['registration'], False)
        assert_equal(data['attributes']['fork'], True)

    def test_cannot_access_private_node_forks_list_unauthenticated(self):
        res = self.app.get(self.private_project_url, expect_errors=True)

        assert_equal(res.status_code, 401)
        assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.')

    def test_authenticated_contributor_can_access_private_node_forks_list(self):
        res = self.app.get(self.private_project_url + '?embed=children&embed=node_links&embed=logs&embed=contributors&embed=forked_from', auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), 1)
        data = res.json['data'][0]
        assert_equal(data['attributes']['title'], 'Fork of ' + self.private_project.title)
        assert_equal(data['id'], self.private_fork._id)

        fork_contributors = data['embeds']['contributors']['data'][0]['embeds']['users']['data']
        assert_equal(fork_contributors['attributes']['family_name'], self.user.family_name)
        assert_equal(fork_contributors['id'], self.user._id)

        forked_children = data['embeds']['children']['data'][0]
        assert_equal(forked_children['id'], self.component.forks[0]._id)
        assert_equal(forked_children['attributes']['title'], self.component.title)

        forked_node_links = data['embeds']['node_links']['data'][0]['embeds']['target_node']['data']
        assert_equal(forked_node_links['id'], self.pointer._id)
        assert_equal(forked_node_links['attributes']['title'], self.pointer.title)

        expected_logs = [log.action for log in self.private_project.logs]
        expected_logs.append(self.component.logs[0].action)
        expected_logs.append('node_forked')
        expected_logs.append('node_forked')

        forked_logs = data['embeds']['logs']['data']
        assert_equal(set(expected_logs), set(log['attributes']['action'] for log in forked_logs))
        assert_equal(len(forked_logs), 6)

        forked_from = data['embeds']['forked_from']['data']
        assert_equal(forked_from['id'], self.private_project._id)

    def test_authenticated_non_contributor_cannot_access_private_node_forks_list(self):
        res = self.app.get(self.private_project_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.')
Exemple #32
0
class TestNodeForksList(ApiTestCase):
    def setUp(self):
        super(TestNodeForksList, self).setUp()
        self.user = AuthUserFactory()
        self.private_project = ProjectFactory()
        self.private_project.add_contributor(
            self.user, permissions=[permissions.READ, permissions.WRITE])
        self.private_project.save()
        self.component = NodeFactory(parent=self.private_project,
                                     creator=self.user)
        self.pointer = ProjectFactory(creator=self.user)
        self.private_project.add_pointer(self.pointer,
                                         auth=Auth(self.user),
                                         save=True)
        self.private_fork = ForkFactory(project=self.private_project,
                                        user=self.user)
        self.private_project_url = '/{}nodes/{}/forks/'.format(
            API_BASE, self.private_project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project.save()
        self.public_component = NodeFactory(parent=self.public_project,
                                            creator=self.user,
                                            is_public=True)
        self.public_project_url = '/{}nodes/{}/forks/'.format(
            API_BASE, self.public_project._id)
        self.public_fork = ForkFactory(project=self.public_project,
                                       user=self.user)
        self.user_two = AuthUserFactory()

    def test_can_access_public_node_forks_list_when_unauthenticated(self):
        res = self.app.get(self.public_project_url)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), 0)
        # Fork defaults to private
        assert_equal(self.public_fork.is_public, False)

        self.public_fork.is_public = True
        self.public_fork.save()

        res = self.app.get(self.public_project_url)
        assert_equal(len(res.json['data']), 1)
        assert_equal(self.public_fork.is_public, True)
        data = res.json['data'][0]
        assert_equal(data['attributes']['title'],
                     'Fork of ' + self.public_project.title)
        assert_equal(data['id'], self.public_fork._id)
        assert_equal(data['attributes']['registration'], False)
        assert_equal(data['attributes']['fork'], True)

    def test_can_access_public_node_forks_list_authenticated_contributor(self):
        res = self.app.get(self.public_project_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(self.public_fork.is_public, False)
        assert_equal(len(res.json['data']), 1)
        data = res.json['data'][0]
        assert_equal(data['attributes']['title'],
                     'Fork of ' + self.public_project.title)
        assert_equal(data['id'], self.public_fork._id)
        assert_equal(data['attributes']['registration'], False)
        assert_equal(data['attributes']['fork'], True)

    def test_can_access_public_node_forks_list_authenticated_non_contributor(
            self):
        res = self.app.get(self.public_project_url, auth=self.user_two.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), 0)
        # Fork defaults to private
        assert_equal(self.public_fork.is_public, False)

        self.public_fork.is_public = True
        self.public_fork.save()

        res = self.app.get(self.public_project_url)
        assert_equal(len(res.json['data']), 1)
        assert_equal(self.public_fork.is_public, True)
        data = res.json['data'][0]
        assert_equal(data['attributes']['title'],
                     'Fork of ' + self.public_project.title)
        assert_equal(data['id'], self.public_fork._id)
        assert_equal(data['attributes']['registration'], False)
        assert_equal(data['attributes']['fork'], True)

    def test_cannot_access_private_node_forks_list_unauthenticated(self):
        res = self.app.get(self.private_project_url, expect_errors=True)

        assert_equal(res.status_code, 401)
        assert_equal(res.json['errors'][0]['detail'],
                     'Authentication credentials were not provided.')

    def test_authenticated_contributor_can_access_private_node_forks_list(
            self):
        res = self.app.get(
            self.private_project_url +
            '?embed=children&embed=node_links&embed=logs&embed=contributors&embed=forked_from',
            auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']), 1)
        data = res.json['data'][0]
        assert_equal(data['attributes']['title'],
                     'Fork of ' + self.private_project.title)
        assert_equal(data['id'], self.private_fork._id)

        fork_contributors = data['embeds']['contributors']['data'][0][
            'embeds']['users']['data']
        assert_equal(fork_contributors['attributes']['family_name'],
                     self.user.family_name)
        assert_equal(fork_contributors['id'], self.user._id)

        forked_children = data['embeds']['children']['data'][0]
        assert_equal(forked_children['id'], self.component.forks[0]._id)
        assert_equal(forked_children['attributes']['title'],
                     self.component.title)

        forked_node_links = data['embeds']['node_links']['data'][0]['embeds'][
            'target_node']['data']
        assert_equal(forked_node_links['id'], self.pointer._id)
        assert_equal(forked_node_links['attributes']['title'],
                     self.pointer.title)

        expected_logs = [log.action for log in self.private_project.logs]
        expected_logs.append(self.component.logs[0].action)
        expected_logs.append('node_forked')
        expected_logs.append('node_forked')

        forked_logs = data['embeds']['logs']['data']
        assert_equal(set(expected_logs),
                     set(log['attributes']['action'] for log in forked_logs))
        assert_equal(len(forked_logs), 6)

        forked_from = data['embeds']['forked_from']['data']
        assert_equal(forked_from['id'], self.private_project._id)

    def test_authenticated_non_contributor_cannot_access_private_node_forks_list(
            self):
        res = self.app.get(self.private_project_url,
                           auth=self.user_two.auth,
                           expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'],
                     'You do not have permission to perform this action.')
Exemple #33
0
class TestNodeForkCreate(ApiTestCase):
    def setUp(self):
        super(TestNodeForkCreate, self).setUp()
        self.user = AuthUserFactory()
        self.user_two = AuthUserFactory()
        self.user_three = AuthUserFactory()
        self.private_project = ProjectFactory(creator=self.user)

        self.fork_data = {'data': {'type': 'nodes'}}

        self.fork_data_with_title = {
            'data': {
                'type': 'nodes',
                'attributes': {
                    'title': 'My Forked Project'
                }
            }
        }

        self.private_project_url = '/{}nodes/{}/forks/'.format(
            API_BASE, self.private_project._id)

        self.public_project = ProjectFactory(is_public=True, creator=self.user)
        self.public_project_url = '/{}nodes/{}/forks/'.format(
            API_BASE, self.public_project._id)

    def tearDown(self):
        super(TestNodeForkCreate, self).tearDown()
        Node.remove()

    def test_create_fork_from_public_project_with_new_title(self):
        res = self.app.post_json_api(self.public_project_url,
                                     self.fork_data_with_title,
                                     auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.public_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'],
                     self.fork_data_with_title['data']['attributes']['title'])

    def test_create_fork_from_private_project_with_new_title(self):
        res = self.app.post_json_api(self.private_project_url,
                                     self.fork_data_with_title,
                                     auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.private_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'],
                     self.fork_data_with_title['data']['attributes']['title'])

    def test_can_fork_public_node_logged_in(self):
        res = self.app.post_json_api(self.public_project_url,
                                     self.fork_data,
                                     auth=self.user_two.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.public_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'],
                     'Fork of ' + self.public_project.title)

    def test_cannot_fork_public_node_logged_out(self):
        res = self.app.post_json_api(self.public_project_url,
                                     self.fork_data,
                                     expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_equal(res.json['errors'][0]['detail'],
                     'Authentication credentials were not provided.')

    def test_can_fork_public_node_logged_in_contributor(self):
        res = self.app.post_json_api(self.public_project_url,
                                     self.fork_data,
                                     auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.public_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'],
                     'Fork of ' + self.public_project.title)

    def test_cannot_fork_private_node_logged_out(self):
        res = self.app.post_json_api(self.private_project_url,
                                     self.fork_data,
                                     expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_equal(res.json['errors'][0]['detail'],
                     'Authentication credentials were not provided.')

    def test_cannot_fork_private_node_logged_in_non_contributor(self):
        res = self.app.post_json_api(self.private_project_url,
                                     self.fork_data,
                                     auth=self.user_two.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'],
                     'You do not have permission to perform this action.')

    def test_can_fork_private_node_logged_in_contributor(self):
        res = self.app.post_json_api(
            self.private_project_url +
            '?embed=children&embed=node_links&embed=logs&embed=contributors&embed=forked_from',
            self.fork_data,
            auth=self.user.auth)
        assert_equal(res.status_code, 201)

        data = res.json['data']
        assert_equal(data['attributes']['title'],
                     'Fork of ' + self.private_project.title)

        fork_contributors = data['embeds']['contributors']['data'][0][
            'embeds']['users']['data']
        assert_equal(fork_contributors['attributes']['family_name'],
                     self.user.family_name)
        assert_equal(fork_contributors['id'], self.user._id)

        forked_from = data['embeds']['forked_from']['data']
        assert_equal(forked_from['id'], self.private_project._id)

    def test_fork_private_components_no_access(self):
        url = self.public_project_url + '?embed=children'
        private_component = NodeFactory(parent=self.public_project,
                                        creator=self.user_two,
                                        is_public=False)
        res = self.app.post_json_api(url,
                                     self.fork_data,
                                     auth=self.user_three.auth)
        assert_equal(res.status_code, 201)
        # Private components that you do not have access to are not forked
        assert_equal(
            res.json['data']['embeds']['children']['links']['meta']['total'],
            0)

    def test_fork_components_you_can_access(self):
        url = self.private_project_url + '?embed=children'
        new_component = NodeFactory(parent=self.private_project,
                                    creator=self.user)
        res = self.app.post_json_api(url, self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(
            res.json['data']['embeds']['children']['links']['meta']['total'],
            1)
        assert_equal(res.json['data']['embeds']['children']['data'][0]['id'],
                     new_component.forks[0]._id)
        assert_equal(
            res.json['data']['embeds']['children']['data'][0]['attributes']
            ['title'], new_component.title)

    def test_fork_private_node_links(self):
        private_pointer = ProjectFactory(creator=self.user_two)
        actual_pointer = self.private_project.add_pointer(private_pointer,
                                                          auth=Auth(
                                                              self.user_two),
                                                          save=True)

        url = self.private_project_url + '?embed=node_links'

        # Node link is forked, but shows up as a private node link
        res = self.app.post_json_api(url, self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)

        assert_equal(
            res.json['data']['embeds']['node_links']['data'][0]['embeds']
            ['target_node']['errors'][0]['detail'],
            'You do not have permission to perform this action.')
        assert_equal(
            res.json['data']['embeds']['node_links']['links']['meta']['total'],
            1)

        self.private_project.rm_pointer(actual_pointer,
                                        auth=Auth(self.user_two))

    def test_fork_node_links_you_can_access(self):
        pointer = ProjectFactory(creator=self.user)
        self.private_project.add_pointer(pointer,
                                         auth=Auth(self.user_two),
                                         save=True)

        url = self.private_project_url + '?embed=node_links'

        res = self.app.post_json_api(url, self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)

        assert_equal(
            res.json['data']['embeds']['node_links']['data'][0]['embeds']
            ['target_node']['data']['id'], pointer._id)
        assert_equal(
            res.json['data']['embeds']['node_links']['links']['meta']['total'],
            1)

    def test_can_fork_registration(self):
        registration = RegistrationFactory(project=self.private_project,
                                           user=self.user)

        url = '/{}registrations/{}/forks/'.format(API_BASE, registration._id)
        res = self.app.post_json_api(url, self.fork_data, auth=self.user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], registration.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'],
                     'Fork of ' + registration.title)

    def test_read_only_contributor_can_fork_private_registration(self):
        read_only_user = AuthUserFactory()

        self.private_project.add_contributor(read_only_user,
                                             permissions=[permissions.READ],
                                             save=True)
        res = self.app.post_json_api(self.private_project_url,
                                     self.fork_data,
                                     auth=read_only_user.auth)
        assert_equal(res.status_code, 201)
        assert_equal(res.json['data']['id'], self.private_project.forks[0]._id)
        assert_equal(res.json['data']['attributes']['title'],
                     'Fork of ' + self.private_project.title)
Exemple #34
0
class TestWikiViews(OsfTestCase):
    def setUp(self):
        super(TestWikiViews, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(is_public=True, creator=self.user)
        self.consolidate_auth = Auth(user=self.project.creator)

    def test_wiki_url_get_returns_200(self):
        url = self.project.web_url_for('project_wiki_page', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_url_for_pointer_returns_200(self):
        # TODO: explain how this tests a pointer
        project = ProjectFactory(is_public=True)
        self.project.add_pointer(project,
                                 Auth(self.project.creator),
                                 save=True)
        url = self.project.web_url_for('project_wiki_page', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_content_returns_200(self):
        node = ProjectFactory(is_public=True)
        url = node.api_url_for('wiki_page_content', wname='somerandomid')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_wiki_url_for_component_returns_200(self):
        component = NodeFactory(project=self.project, is_public=True)
        url = component.web_url_for('project_wiki_page', wname='home')
        res = self.app.get(url)
        assert_equal(res.status_code, 200)

    def test_serialize_wiki_toc(self):
        project = ProjectFactory()
        auth = Auth(project.creator)
        NodeFactory(project=project, creator=project.creator)
        no_wiki = NodeFactory(project=project, creator=project.creator)
        project.save()

        serialized = _serialize_wiki_toc(project, auth=auth)
        assert_equal(len(serialized), 2)
        no_wiki.delete_addon('wiki', auth=auth)
        serialized = _serialize_wiki_toc(project, auth=auth)
        assert_equal(len(serialized), 1)

    def test_get_wiki_url_pointer_component(self):
        """Regression test for issues
        https://github.com/CenterForOpenScience/osf/issues/363 and
        https://github.com/CenterForOpenScience/openscienceframework.org/issues/574

        """
        user = UserFactory()
        pointed_node = NodeFactory(creator=user)
        project = ProjectFactory(creator=user)
        auth = Auth(user=user)
        project.add_pointer(pointed_node, auth=auth, save=True)

        serialized = _serialize_wiki_toc(project, auth)
        assert_equal(
            serialized[0]['url'],
            pointed_node.web_url_for('project_wiki_page',
                                     wname='home',
                                     _guid=True))

    def test_project_wiki_edit_post(self):
        self.project.update_node_wiki('home',
                                      content='old content',
                                      auth=Auth(self.project.creator))
        url = self.project.web_url_for('project_wiki_edit_post', wname='home')
        res = self.app.post(url, {
            'content': 'new content'
        },
                            auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        # page was updated with new content
        new_wiki = self.project.get_wiki_page('home')
        assert_equal(new_wiki.content, 'new content')

    def test_project_wiki_edit_post_with_new_wname_and_no_content(self):
        page_name = fake.catch_phrase()

        old_wiki_page_count = NodeWikiPage.find().count()
        url = self.project.web_url_for('project_wiki_edit_post',
                                       wname=page_name)
        # User submits to edit form with no content
        res = self.app.post(url, {'content': ''}, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        new_wiki_page_count = NodeWikiPage.find().count()
        # A new wiki page was created in the db
        assert_equal(new_wiki_page_count, old_wiki_page_count + 1)

        # Node now has the new wiki page associated with it
        self.project.reload()
        new_page = self.project.get_wiki_page(page_name)
        assert_is_not_none(new_page)

    def test_project_wiki_edit_post_with_new_wname_and_content(self):
        page_name, page_content = fake.catch_phrase(), fake.bs()

        old_wiki_page_count = NodeWikiPage.find().count()
        url = self.project.web_url_for('project_wiki_edit_post',
                                       wname=page_name)
        # User submits to edit form with no content
        res = self.app.post(url, {
            'content': page_content
        },
                            auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        new_wiki_page_count = NodeWikiPage.find().count()
        # A new wiki page was created in the db
        assert_equal(new_wiki_page_count, old_wiki_page_count + 1)

        # Node now has the new wiki page associated with it
        self.project.reload()
        new_page = self.project.get_wiki_page(page_name)
        assert_is_not_none(new_page)
        # content was set
        assert_equal(new_page.content, page_content)

    def test_project_wiki_edit_post_with_non_ascii_title(self):
        # regression test for https://github.com/CenterForOpenScience/openscienceframework.org/issues/1040
        # wname doesn't exist in the db, so it will be created
        new_wname = u'øˆ∆´ƒøßå√ß'
        url = self.project.web_url_for('project_wiki_edit_post',
                                       wname=new_wname)
        res = self.app.post(url, {
            'content': 'new content'
        },
                            auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        wiki = self.project.get_wiki_page(new_wname)
        assert_equal(wiki.page_name, new_wname)

        # updating content should return correct url as well.
        res = self.app.post(url, {
            'content': 'updated content'
        },
                            auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

    def test_project_wiki_edit_post_with_special_characters(self):
        new_wname = 'title: ' + SPECIAL_CHARACTERS_ALLOWED
        new_wiki_content = 'content: ' + SPECIAL_CHARACTERS_ALL
        url = self.project.web_url_for('project_wiki_edit_post',
                                       wname=new_wname)
        res = self.app.post(url, {
            'content': new_wiki_content
        },
                            auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)
        self.project.reload()
        wiki = self.project.get_wiki_page(new_wname)
        assert_equal(wiki.page_name, new_wname)
        assert_equal(wiki.content, new_wiki_content)
        assert_equal(res.status_code, 200)

    def test_wiki_edit_get_home(self):
        url = self.project.web_url_for('project_wiki_edit', wname='home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_project_wiki_compare_returns_200(self):
        self.project.update_node_wiki('home', 'updated content',
                                      Auth(self.user))
        self.project.save()
        url = self.project.web_url_for('project_wiki_compare',
                                       wname='home',
                                       wver=1)
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_project_wiki_compare_with_invalid_wname(self):
        url = self.project.web_url_for('project_wiki_compare',
                                       wname='this-doesnt-exist',
                                       wver=1)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_wiki_page_creation_strips_whitespace(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1080
        # wname has a trailing space
        url = self.project.web_url_for('project_wiki_edit', wname='cupcake ')
        res = self.app.post(url, {
            'content': 'blah'
        }, auth=self.user.auth).follow()
        assert_equal(res.status_code, 200)

        self.project.reload()
        wiki = self.project.get_wiki_page('cupcake')
        assert_is_not_none(wiki)

    def test_wiki_validate_name(self):
        url = self.project.api_url_for('project_wiki_validate_name',
                                       wname='Capslock')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)

    def test_wiki_validate_name_cannot_create_home(self):
        url = self.project.api_url_for('project_wiki_validate_name',
                                       wname='home')
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_project_wiki_validate_name_mixed_casing(self):
        url = self.project.api_url_for('project_wiki_validate_name',
                                       wname='CaPsLoCk')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_not_in('capslock', self.project.wiki_pages_current)
        self.project.update_node_wiki('CaPsLoCk', 'hello',
                                      self.consolidate_auth)
        assert_in('capslock', self.project.wiki_pages_current)

    def test_project_wiki_validate_name_diplay_correct_capitalization(self):
        url = self.project.api_url_for('project_wiki_validate_name',
                                       wname='CaPsLoCk')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_in('CaPsLoCk', res)

    def test_project_wiki_validate_name_conflict_different_casing(self):
        url = self.project.api_url_for('project_wiki_validate_name',
                                       wname='CAPSLOCK')
        res = self.app.get(url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        self.project.update_node_wiki('CaPsLoCk', 'hello',
                                      self.consolidate_auth)
        assert_in('capslock', self.project.wiki_pages_current)
        url = self.project.api_url_for('project_wiki_validate_name',
                                       wname='capslock')
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_project_dashboard_shows_no_wiki_content_text(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104
        project = ProjectFactory(creator=self.user)
        url = project.web_url_for('view_project')
        res = self.app.get(url, auth=self.user.auth)
        assert_in('No wiki content', res)

    def test_project_dashboard_wiki_wname_get_shows_non_ascii_characters(self):
        # Regression test for:
        # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104
        text = u'你好'
        self.project.update_node_wiki('home', text, Auth(self.user))

        # can view wiki preview from project dashboard
        url = self.project.web_url_for('view_project')
        res = self.app.get(url, auth=self.user.auth)
        assert_in(text, res)

    def test_project_wiki_home_api_route(self):
        url = self.project.api_url_for('project_wiki_home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equals(res.status_code, 302)
        # TODO: should this route exist? it redirects you to the web_url_for, not api_url_for.
        # page_url = self.project.api_url_for('project_wiki_page', wname='home')
        # assert_in(page_url, res.location)

    def test_project_wiki_home_web_route(self):
        page_url = self.project.web_url_for('project_wiki_page',
                                            wname='home',
                                            _guid=True)
        url = self.project.web_url_for('project_wiki_home')
        res = self.app.get(url, auth=self.user.auth)
        assert_equals(res.status_code, 302)
        assert_in(page_url, res.location)

    def test_wiki_id_url_get_returns_302_and_resolves(self):
        name = 'page by id'
        self.project.update_node_wiki(name, 'some content',
                                      Auth(self.project.creator))
        page = self.project.get_wiki_page(name)
        page_url = self.project.web_url_for('project_wiki_page',
                                            wname=page.page_name,
                                            _guid=True)
        url = self.project.web_url_for('project_wiki_id_page',
                                       wid=page._primary_key,
                                       _guid=True)
        res = self.app.get(url)
        assert_equal(res.status_code, 302)
        assert_in(page_url, res.location)
        res = res.follow()
        assert_equal(res.status_code, 200)
        assert_in(page_url, res.request.url)

    def test_wiki_id_url_get_returns_404(self):
        url = self.project.web_url_for('project_wiki_id_page',
                                       wid='12345',
                                       _guid=True)
        res = self.app.get(url, expect_errors=True)
        assert_equal(res.status_code, 404)

    def test_home_is_capitalized_in_web_view(self):
        url = self.project.web_url_for('project_wiki_home',
                                       wid='home',
                                       _guid=True)
        res = self.app.get(url,
                           auth=self.user.auth).follow(auth=self.user.auth)
        page_name_elem = res.html.find('span', {'id': 'pageName'})
        assert_in('Home', page_name_elem.text)
Exemple #35
0
class TestNodeLinkDetail(ApiTestCase):

    def setUp(self):
        super(TestNodeLinkDetail, self).setUp()
        self.user = AuthUserFactory()
        self.private_project = ProjectFactory(creator=self.user, is_public=False)
        self.pointer_project = ProjectFactory(creator=self.user, is_public=False)
        self.pointer = self.private_project.add_pointer(self.pointer_project, auth=Auth(self.user), save=True)
        self.private_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.private_project._id, self.pointer._id)

        self.user_two = AuthUserFactory()

        self.public_project = ProjectFactory(creator=self.user, is_public=True)
        self.public_pointer_project = ProjectFactory(is_public=True)
        self.public_pointer = self.public_project.add_pointer(self.public_pointer_project,
                                                              auth=Auth(self.user),
                                                              save=True)
        self.public_url = '/{}nodes/{}/node_links/{}/'.format(API_BASE, self.public_project._id, self.public_pointer._id)

    def test_returns_embedded_public_node_pointer_detail_logged_out(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        res_json = res.json['data']
        embedded = res_json['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.public_pointer_project._id)

    def test_returns_public_node_pointer_detail_logged_in(self):
        res = self.app.get(self.public_url, auth=self.user.auth)
        res_json = res.json['data']
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        embedded = res_json['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.public_pointer_project._id)

    def test_returns_private_node_pointer_detail_logged_out(self):
        res = self.app.get(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 200)
        target_node = res.json['data']['embeds']['target_node']
        assert_in('errors', target_node)
        assert_equal(target_node['errors'][0]['detail'], 'Authentication credentials were not provided.')

    def test_returns_private_node_pointer_detail_logged_in_contributor(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        res_json = res.json['data']
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        embedded = res_json['embeds']['target_node']['data']['id']
        assert_equal(embedded, self.pointer_project._id)

    def test_returns_private_node_pointer_detail_logged_in_non_contributor(self):
        res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 200)
        target_node = res.json['data']['embeds']['target_node']
        assert_in('errors', target_node)
        assert_equal(target_node['errors'][0]['detail'], 'You do not have permission to perform this action.')

    def test_self_link_points_to_node_link_detail_url(self):
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        url = res.json['data']['links']['self']
        assert_in(self.public_url, url)

    def test_node_links_bad_version(self):
        url = '{}?version=2.1'.format(self.public_url)
        res = self.app.get(url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)
        assert_equal(res.json['errors'][0]['detail'], 'This feature is deprecated as of version 2.1')