def node(self, user_admin_contrib, user_write_contrib, user_read_contrib):
     node = RegistrationFactory(creator=user_admin_contrib, is_public=False)
     node.add_contributor(user_write_contrib, auth=Auth(user_admin_contrib))
     node.add_contributor(
         user_read_contrib,
         auth=Auth(user_admin_contrib),
         permissions=['read'])
     node.save()
     return node
 def node(self, user, write_contrib, read_contrib):
     registration = RegistrationFactory(creator=user)
     registration.add_contributor(
         write_contrib,
         permissions=[
             permissions.READ,
             permissions.WRITE])
     registration.add_contributor(read_contrib, permissions=[permissions.READ])
     registration.save()
     return registration
 def project(self, admin_contributor_bib, write_contributor_non_bib, read_contributor_bib):
     project = ProjectFactory(creator=admin_contributor_bib)
     reg = RegistrationFactory(
         creator=admin_contributor_bib,
         project=project
     )
     reg.add_contributor(write_contributor_non_bib, [READ, WRITE], visible=False)
     reg.add_contributor(read_contributor_bib, [READ])
     reg.save()
     return reg
 def test_can_create_linked_registration_relationship_to_private_registration_if_read_only(self):
     registration = RegistrationFactory()
     registration.add_contributor(self.admin_contributor, auth=Auth(registration.creator), permissions=['read'])
     registration.save()
     res = self.make_request(
         node_id=self.private_node._id,
         reg_id=registration._id,
         auth=self.admin_contributor.auth
     )
     assert_equal(res.status_code, 201)
     linked_registrations = [r['id'] for r in res.json['data']]
     assert_in(registration._id, linked_registrations)
Пример #5
0
 def private_registration(
         self, user, private_project, read_only_contributor,
         read_write_contributor):
     private_registration = RegistrationFactory(
         project=private_project, creator=user)
     private_registration.add_contributor(
         read_only_contributor, permissions=[
             permissions.READ])
     private_registration.add_contributor(
         read_write_contributor, permissions=[
             permissions.WRITE])
     private_registration.save()
     return private_registration
 def test_can_create_linked_registration_relationship_to_private_registration_if_rw(
         self, make_request, user_admin_contrib, node_private):
     registration = RegistrationFactory()
     registration.add_contributor(
         user_admin_contrib,
         auth=Auth(registration.creator))
     registration.save()
     res = make_request(
         node_id=node_private._id,
         reg_id=registration._id,
         auth=user_admin_contrib.auth
     )
     assert res.status_code == 201
     linked_registrations = [r['id'] for r in res.json['data']]
     assert registration._id in linked_registrations
Пример #7
0
    def test_total_biographic_contributor_in_registration(self):
        user3 = AuthUserFactory()
        registration = RegistrationFactory(is_public=True, creator=self.user)
        registration.add_contributor(self.user_two, auth=Auth(self.user))
        registration.add_contributor(
            user3, auth=Auth(self.user), visible=False)
        registration.save()
        registration_url = '/{0}registrations/{1}/?embed=contributors'.format(
            API_BASE, registration._id)

        res = self.app.get(registration_url)
        assert_true(
            res.json['data']['embeds']['contributors']['links']['meta']['total_bibliographic']
        )
        assert_equal(
            res.json['data']['embeds']['contributors']['links']['meta']['total_bibliographic'],
        2)
Пример #8
0
    def test_metadata_for_node_only_includes_visible_contribs(self, datacite_client):
        visible_contrib = AuthUserFactory()
        visible_contrib2 = AuthUserFactory()
        visible_contrib2.given_name = u'ヽ༼ ಠ益ಠ ༽ノ'
        visible_contrib2.family_name = u'ლ(´◉❥◉`ლ)'
        visible_contrib2.save()
        invisible_contrib = AuthUserFactory()
        invisible_contrib.given_name = 'Shady'
        invisible_contrib.family_name = 'McCoy'
        invisible_contrib.save()
        registration = RegistrationFactory(is_public=True)

        registration.add_contributor(visible_contrib, visible=True)
        registration.add_contributor(invisible_contrib, visible=False)
        registration.add_contributor(visible_contrib2, visible=True)
        registration.save()

        metadata_xml = datacite_client.build_metadata(registration)
        # includes visible contrib name
        assert u'<givenName>{}</givenName>'.format(visible_contrib.given_name) in metadata_xml
        assert u'<familyName>{}</familyName>'.format(visible_contrib.family_name) in metadata_xml

        # doesn't include invisible contrib name
        assert u'<givenName>{}</givenName>'.format(invisible_contrib.given_name) not in metadata_xml
        assert u'<familyName>{}</familyName>'.format(invisible_contrib.family_name) not in metadata_xml
class TestInstitutionRegistrationList(ApiTestCase):
    def setUp(self):
        super(TestInstitutionRegistrationList, self).setUp()
        self.institution = InstitutionFactory()
        self.registration1 = RegistrationFactory(is_public=True)
        self.registration1.affiliated_institutions.add(self.institution)
        self.registration1.save()
        self.user1 = AuthUserFactory()
        self.user2 = AuthUserFactory()
        self.registration2 = RegistrationFactory(creator=self.user1,
                                                 is_public=False)
        self.registration2.affiliated_institutions.add(self.institution)
        self.registration2.add_contributor(self.user2, auth=Auth(self.user1))
        self.registration2.save()
        self.registration3 = RegistrationFactory(creator=self.user2,
                                                 is_public=False)
        self.registration3.affiliated_institutions.add(self.institution)
        self.registration3.save()

        self.institution_node_url = '/{0}institutions/{1}/registrations/'.format(
            API_BASE, self.institution._id)

    def test_return_all_public_nodes(self):
        res = self.app.get(self.institution_node_url)

        assert_equal(res.status_code, 200)
        ids = [each['id'] for each in res.json['data']]

        assert_in(self.registration1._id, ids)
        assert_not_in(self.registration2._id, ids)
        assert_not_in(self.registration3._id, ids)

    def test_does_not_return_private_nodes_with_auth(self):
        res = self.app.get(self.institution_node_url, auth=self.user1.auth)

        assert_equal(res.status_code, 200)
        ids = [each['id'] for each in res.json['data']]

        assert_in(self.registration1._id, ids)
        assert_not_in(self.registration2._id, ids)
        assert_not_in(self.registration3._id, ids)

    def test_doesnt_return_retractions_without_auth(self):
        self.registration2.is_public = True
        self.registration2.save()
        retraction = WithdrawnRegistrationFactory(
            registration=self.registration2, user=self.user1)
        assert_true(self.registration2.is_retracted)

        res = self.app.get(self.institution_node_url)

        assert_equal(res.status_code, 200)
        ids = [each['id'] for each in res.json['data']]

        assert_not_in(self.registration2._id, ids)

    def test_doesnt_return_retractions_with_auth(self):
        retraction = WithdrawnRegistrationFactory(
            registration=self.registration2, user=self.user1)

        assert_true(self.registration2.is_retracted)

        res = self.app.get(self.institution_node_url, auth=self.user1.auth)

        assert_equal(res.status_code, 200)
        ids = [each['id'] for each in res.json['data']]

        assert_not_in(self.registration2._id, ids)

    def test_total_biographic_contributor_in_institution_registration(self):
        user3 = AuthUserFactory()
        registration3 = RegistrationFactory(is_public=True, creator=self.user1)
        registration3.affiliated_institutions.add(self.institution)
        registration3.add_contributor(self.user2, auth=Auth(self.user1))
        registration3.add_contributor(user3,
                                      auth=Auth(self.user1),
                                      visible=False)
        registration3.save()
        registration3_url = '/{0}registrations/{1}/?embed=contributors'.format(
            API_BASE, registration3._id)

        res = self.app.get(registration3_url)
        assert_true(res.json['data']['embeds']['contributors']['links']['meta']
                    ['total_bibliographic'])
        assert_equal(
            res.json['data']['embeds']['contributors']['links']['meta']
            ['total_bibliographic'], 2)
 def private_registration(self, user, private_project, read_only_contributor, read_write_contributor):
     private_registration = RegistrationFactory(project=private_project, creator=user)
     private_registration.add_contributor(read_only_contributor, permissions=[permissions.READ])
     private_registration.add_contributor(read_write_contributor, permissions=[permissions.WRITE])
     private_registration.save()
     return private_registration
Пример #11
0
class TestMetadataGeneration(OsfTestCase):

    def setUp(self):
        OsfTestCase.setUp(self)
        self.visible_contrib = AuthUserFactory()
        visible_contrib2 = AuthUserFactory(given_name=u'ヽ༼ ಠ益ಠ ༽ノ', family_name=u'ლ(´◉❥◉`ლ)')
        self.invisible_contrib = AuthUserFactory()
        self.node = RegistrationFactory(is_public=True)
        self.identifier = Identifier(referent=self.node, category='catid', value='cat:7')
        self.node.add_contributor(self.visible_contrib, visible=True)
        self.node.add_contributor(self.invisible_contrib, visible=False)
        self.node.add_contributor(visible_contrib2, visible=True)
        self.node.save()

    # This test is not used as datacite is currently used for nodes, leaving here for future reference
    def test_datacite_metadata_for_preprint_has_correct_structure(self):
        provider = PreprintProviderFactory()
        license =  NodeLicense.objects.get(name='CC-By Attribution 4.0 International')
        license_details = {
            'id': license.license_id,
            'year': '2017',
            'copyrightHolders': ['Jeff Hardy', 'Matt Hardy']
        }
        preprint = PreprintFactory(provider=provider, project=self.node, is_published=True, license_details=license_details)
        metadata_xml = metadata.datacite_metadata_for_preprint(preprint, doi=preprint.get_identifier('doi').value, pretty_print=True)

        root = lxml.etree.fromstring(metadata_xml)
        xsi_location = '{http://www.w3.org/2001/XMLSchema-instance}schemaLocation'
        expected_location = 'http://datacite.org/schema/kernel-4 http://schema.datacite.org/meta/kernel-4/metadata.xsd'
        assert root.attrib[xsi_location] == expected_location

        identifier = root.find('{%s}identifier' % metadata.NAMESPACE)
        assert identifier.attrib['identifierType'] == 'DOI'
        assert identifier.text == preprint.get_identifier('doi').value

        creators = root.find('{%s}creators' % metadata.NAMESPACE)
        assert len(creators.getchildren()) == len(self.node.visible_contributors)

        subjects = root.find('{%s}subjects' % metadata.NAMESPACE)
        assert subjects.getchildren()

        publisher = root.find('{%s}publisher' % metadata.NAMESPACE)
        assert publisher.text == provider.name

        pub_year = root.find('{%s}publicationYear' % metadata.NAMESPACE)
        assert pub_year.text == str(preprint.date_published.year)

        dates = root.find('{%s}dates' % metadata.NAMESPACE).getchildren()[0]
        assert dates.text == preprint.modified.isoformat()
        assert dates.attrib['dateType'] == 'Updated'

        alternate_identifier = root.find('{%s}alternateIdentifiers' % metadata.NAMESPACE).getchildren()[0]
        assert alternate_identifier.text == settings.DOMAIN + preprint._id
        assert alternate_identifier.attrib['alternateIdentifierType'] == 'URL'

        descriptions = root.find('{%s}descriptions' % metadata.NAMESPACE).getchildren()[0]
        assert descriptions.text == preprint.node.description

        rights = root.find('{%s}rightsList' % metadata.NAMESPACE).getchildren()[0]
        assert rights.text == preprint.license.name

    # This test is not used as datacite is currently used for nodes, leaving here for future reference
    def test_datacite_format_creators_for_preprint(self):
        preprint = PreprintFactory(project=self.node, is_published=True)

        verified_user = AuthUserFactory(external_identity={'ORCID': {'1234-1234-1234-1234': 'VERIFIED'}})
        linked_user = AuthUserFactory(external_identity={'ORCID': {'1234-nope-1234-nope': 'LINK'}})
        self.node.add_contributor(verified_user, visible=True)
        self.node.add_contributor(linked_user, visible=True)
        self.node.save()

        formatted_creators = metadata.format_creators(preprint)

        contributors_with_orcids = 0
        guid_identifiers = []
        for creator_xml in formatted_creators:
            assert creator_xml.find('creatorName').text != u'{}, {}'.format(self.invisible_contrib.family_name, self.invisible_contrib.given_name)

            name_identifiers = creator_xml.findall('nameIdentifier')

            for name_identifier in name_identifiers:
                if name_identifier.attrib['nameIdentifierScheme'] == 'ORCID':
                    assert name_identifier.attrib['schemeURI'] == 'http://orcid.org/'
                    contributors_with_orcids += 1
                else:
                    guid_identifiers.append(name_identifier.text)
                    assert name_identifier.attrib['nameIdentifierScheme'] == 'OSF'
                    assert name_identifier.attrib['schemeURI'] == settings.DOMAIN

        assert contributors_with_orcids >= 1
        assert len(formatted_creators) == len(self.node.visible_contributors)
        assert sorted(guid_identifiers) == sorted([contrib.absolute_url for contrib in self.node.visible_contributors])

    # This test is not used as datacite is currently used for nodes, leaving here for future reference
    def test_datacite_format_subjects_for_preprint(self):
        subject = SubjectFactory()
        subject_1 = SubjectFactory(parent=subject)
        subject_2 = SubjectFactory(parent=subject)

        subjects = [[subject._id, subject_1._id], [subject._id, subject_2._id]]
        preprint = PreprintFactory(subjects=subjects, project=self.node, is_published=True)

        formatted_subjects = metadata.format_subjects(preprint)
        assert len(formatted_subjects) == Subject.objects.all().count()
Пример #12
0
class RegistrationRetractionViewsTestCase(OsfTestCase):
    def setUp(self):
        super(RegistrationRetractionViewsTestCase, self).setUp()

        self.user = AuthUserFactory()
        self.registered_from = ProjectFactory(creator=self.user,
                                              is_public=True)
        self.registration = RegistrationFactory(project=self.registered_from,
                                                is_public=True)

        self.retraction_post_url = self.registration.api_url_for(
            'node_registration_retraction_post')
        self.retraction_get_url = self.registration.web_url_for(
            'node_registration_retraction_get')
        self.justification = fake.sentence()

    def test_GET_retraction_page_when_pending_retraction_returns_HTTPError_BAD_REQUEST(
            self):
        self.registration.retract_registration(self.user)
        self.registration.save()

        res = self.app.get(
            self.retraction_get_url,
            auth=self.user.auth,
            expect_errors=True,
        )
        assert_equal(res.status_code, http.BAD_REQUEST)

    def test_POST_retraction_to_private_registration_returns_HTTPError_FORBIDDEN(
            self):
        self.registration.is_public = False
        self.registration.save()

        res = self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
            expect_errors=True,
        )
        assert_equal(res.status_code, http.FORBIDDEN)
        self.registration.reload()
        assert_is_none(self.registration.retraction)

    @mock.patch('website.mails.send_mail')
    def test_POST_retraction_does_not_send_email_to_unregistered_admins(
            self, mock_send_mail):
        unreg = UnregUserFactory()
        self.registration.add_contributor(
            unreg,
            auth=Auth(self.user),
            permissions=['read', 'write', 'admin'])
        self.registration.save()
        self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        # Only the creator gets an email; the unreg user does not get emailed
        assert_equal(mock_send_mail.call_count, 1)

    def test_POST_pending_embargo_returns_HTTPError_HTTPOK(self):
        self.registration.embargo_registration(
            self.user, (timezone.now() + datetime.timedelta(days=10)),
            for_existing_registration=True)
        self.registration.save()
        assert_true(self.registration.is_pending_embargo)

        res = self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
            expect_errors=True,
        )
        assert_equal(res.status_code, http.OK)
        self.registration.reload()
        assert_true(self.registration.is_pending_retraction)

    def test_POST_active_embargo_returns_HTTPOK(self):
        self.registration.embargo_registration(
            self.user, (timezone.now() + datetime.timedelta(days=10)),
            for_existing_registration=True)
        self.registration.save()
        assert_true(self.registration.is_pending_embargo)

        approval_token = self.registration.embargo.approval_state[
            self.user._id]['approval_token']
        self.registration.embargo.approve(self.user, approval_token)
        assert_true(self.registration.embargo_end_date)

        res = self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
            expect_errors=True,
        )
        assert_equal(res.status_code, http.OK)
        self.registration.reload()
        assert_true(self.registration.is_pending_retraction)

    def test_POST_retraction_by_non_admin_retract_HTTPError_UNAUTHORIZED(self):
        res = self.app.post_json(self.retraction_post_url, expect_errors=True)
        assert_equals(res.status_code, http.UNAUTHORIZED)
        self.registration.reload()
        assert_is_none(self.registration.retraction)

    @mock.patch('website.mails.send_mail')
    def test_POST_retraction_without_justification_returns_HTTPOK(
            self, mock_send):
        res = self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        assert_equal(res.status_code, http.OK)
        self.registration.reload()
        assert_false(self.registration.is_retracted)
        assert_true(self.registration.is_pending_retraction)
        assert_is_none(self.registration.retraction.justification)

    @mock.patch('website.mails.send_mail')
    def test_valid_POST_retraction_adds_to_parent_projects_log(
            self, mock_send):
        initial_project_logs = self.registration.registered_from.logs.count()
        self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        self.registration.registered_from.reload()
        # Logs: Created, registered, retraction initiated
        assert_equal(self.registration.registered_from.logs.count(),
                     initial_project_logs + 1)

    @mock.patch('website.mails.send_mail')
    def test_valid_POST_retraction_when_pending_retraction_raises_400(
            self, mock_send):
        self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        res = self.app.post_json(self.retraction_post_url,
                                 {'justification': ''},
                                 auth=self.user.auth,
                                 expect_errors=True)
        assert_equal(res.status_code, 400)

    @mock.patch('website.mails.send_mail')
    def test_valid_POST_calls_send_mail_with_username(self, mock_send):
        self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        assert_true(mock_send.called)
        args, kwargs = mock_send.call_args
        assert_true(self.user.username in args)

    def test_non_contributor_GET_approval_returns_HTTPError_UNAUTHORIZED(self):
        non_contributor = AuthUserFactory()
        self.registration.retract_registration(self.user)
        approval_token = self.registration.retraction.approval_state[
            self.user._id]['approval_token']

        approval_url = self.registration.web_url_for('view_project',
                                                     token=approval_token)
        res = self.app.get(approval_url,
                           auth=non_contributor.auth,
                           expect_errors=True)
        assert_equal(res.status_code, http.UNAUTHORIZED)
        assert_true(self.registration.is_pending_retraction)
        assert_false(self.registration.is_retracted)

    def test_non_contributor_GET_disapproval_returns_HTTPError_UNAUTHORIZED(
            self):
        non_contributor = AuthUserFactory()
        self.registration.retract_registration(self.user)
        rejection_token = self.registration.retraction.approval_state[
            self.user._id]['rejection_token']

        disapproval_url = self.registration.web_url_for('view_project',
                                                        token=rejection_token)
        res = self.app.get(disapproval_url,
                           auth=non_contributor.auth,
                           expect_errors=True)
        assert_equal(res.status_code, http.UNAUTHORIZED)
        assert_true(self.registration.is_pending_retraction)
        assert_false(self.registration.is_retracted)
class TestInstitutionRegistrationList(ApiTestCase):
    def setUp(self):
        super(TestInstitutionRegistrationList, self).setUp()
        self.institution = InstitutionFactory()
        self.registration1 = RegistrationFactory(is_public=True)
        self.registration1.affiliated_institutions.add(self.institution)
        self.registration1.save()
        self.user1 = AuthUserFactory()
        self.user2 = AuthUserFactory()
        self.registration2 = RegistrationFactory(
            creator=self.user1, is_public=False)
        self.registration2.affiliated_institutions.add(self.institution)
        self.registration2.add_contributor(self.user2, auth=Auth(self.user1))
        self.registration2.save()
        self.registration3 = RegistrationFactory(
            creator=self.user2, is_public=False)
        self.registration3.affiliated_institutions.add(self.institution)
        self.registration3.save()

        self.institution_node_url = '/{0}institutions/{1}/registrations/'.format(
            API_BASE, self.institution._id)

    def test_return_all_public_nodes(self):
        res = self.app.get(self.institution_node_url)

        assert_equal(res.status_code, 200)
        ids = [each['id'] for each in res.json['data']]

        assert_in(self.registration1._id, ids)
        assert_not_in(self.registration2._id, ids)
        assert_not_in(self.registration3._id, ids)

    def test_does_not_return_private_nodes_with_auth(self):
        res = self.app.get(self.institution_node_url, auth=self.user1.auth)

        assert_equal(res.status_code, 200)
        ids = [each['id'] for each in res.json['data']]

        assert_in(self.registration1._id, ids)
        assert_not_in(self.registration2._id, ids)
        assert_not_in(self.registration3._id, ids)

    def test_doesnt_return_retractions_without_auth(self):
        self.registration2.is_public = True
        self.registration2.save()
        retraction = WithdrawnRegistrationFactory(
            registration=self.registration2, user=self.user1)
        assert_true(self.registration2.is_retracted)

        res = self.app.get(self.institution_node_url)

        assert_equal(res.status_code, 200)
        ids = [each['id'] for each in res.json['data']]

        assert_not_in(self.registration2._id, ids)

    def test_doesnt_return_retractions_with_auth(self):
        retraction = WithdrawnRegistrationFactory(
            registration=self.registration2, user=self.user1)

        assert_true(self.registration2.is_retracted)

        res = self.app.get(self.institution_node_url, auth=self.user1.auth)

        assert_equal(res.status_code, 200)
        ids = [each['id'] for each in res.json['data']]

        assert_not_in(self.registration2._id, ids)

    @pytest.mark.enable_quickfiles_creation
    def test_total_biographic_contributor_in_institution_registration(self):
        user3 = AuthUserFactory()
        registration3 = RegistrationFactory(is_public=True, creator=self.user1)
        registration3.affiliated_institutions.add(self.institution)
        registration3.add_contributor(self.user2, auth=Auth(self.user1))
        registration3.add_contributor(
            user3, auth=Auth(self.user1), visible=False)
        registration3.save()
        registration3_url = '/{0}registrations/{1}/?embed=contributors'.format(
            API_BASE, registration3._id)

        res = self.app.get(registration3_url)
        assert_true(
            res.json['data']['embeds']['contributors']['links']['meta']['total_bibliographic']
        )
        assert_equal(
            res.json['data']['embeds']['contributors']['links']['meta']['total_bibliographic'],
            2
        )
Пример #14
0
class RegistrationEmbargoViewsTestCase(OsfTestCase):
    def setUp(self):
        super(RegistrationEmbargoViewsTestCase, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(creator=self.user)
        self.draft = DraftRegistrationFactory(branched_from=self.project)
        self.registration = RegistrationFactory(project=self.project, creator=self.user)

        current_month = timezone.now().strftime('%B')
        current_year = timezone.now().strftime('%Y')

        self.valid_make_public_payload = json.dumps({
            u'embargoEndDate': u'Fri, 01, {month} {year} 00:00:00 GMT'.format(
                month=current_month,
                year=current_year
            ),
            u'registrationChoice': 'immediate',
            u'summary': unicode(fake.sentence())
        })
        valid_date = timezone.now() + datetime.timedelta(days=180)
        self.valid_embargo_payload = json.dumps({
            u'embargoEndDate': unicode(valid_date.strftime('%a, %d, %B %Y %H:%M:%S')) + u' GMT',
            u'registrationChoice': 'embargo',
            u'summary': unicode(fake.sentence())
        })
        self.invalid_embargo_date_payload = json.dumps({
            u'embargoEndDate': u"Thu, 01 {month} {year} 05:00:00 GMT".format(
                month=current_month,
                year=str(int(current_year) - 1)
            ),
            u'registrationChoice': 'embargo',
            u'summary': unicode(fake.sentence())
        })

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_register_draft_without_embargo_creates_registration_approval(self, mock_enqueue):
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_make_public_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        assert_equal(res.status_code, 202)

        registration = Registration.find().order_by('-registered_date').first()
        assert_not_equal(registration.registration_approval, None)

    # Regression test for https://openscience.atlassian.net/browse/OSF-5039
    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_register_make_public_immediately_creates_private_pending_registration_for_public_project(self, mock_enqueue):
        self.project.is_public = True
        self.project.save()
        NodeFactory(  # component
            creator=self.user,
            parent=self.project,
            title='Component',
            is_public=True
        )
        subproject = ProjectFactory(
            creator=self.user,
            parent=self.project,
            title='Subproject',
            is_public=True
        )
        NodeFactory(  # subproject's component
            creator=self.user,
            parent=subproject,
            title='Subcomponent',
            is_public=True
        )
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_make_public_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        self.project.reload()
        assert_equal(res.status_code, 202)
        assert_equal(res.json['urls']['registrations'], self.project.web_url_for('node_registrations'))

        # Last node directly registered from self.project
        registration = AbstractNode.objects.filter(registered_from=self.project).order_by('-registered_date')[0]

        assert_true(registration.is_registration)
        assert_false(registration.is_public)
        for node in registration.get_descendants_recursive():
            assert_true(node.is_registration)
            assert_false(node.is_public)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_register_make_public_does_not_make_children_public(self, mock_enqueue):
        NodeFactory(  # component
            creator=self.user,
            parent=self.project,
            title='Component'
        )
        subproject = ProjectFactory(
            creator=self.user,
            parent=self.project,
            title='Subproject'
        )
        NodeFactory(  # subproject component
            creator=self.user,
            parent=subproject,
            title='Subcomponent'
        )

        self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_make_public_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        self.project.reload()
        # Last node directly registered from self.project
        registration = self.project.registrations.order_by('-registered_date').first()
        assert_false(registration.is_public)
        for node in registration.get_descendants_recursive():
            assert_true(node.is_registration)
            assert_false(node.is_public)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_register_embargo_is_not_public(self, mock_enqueue):
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_embargo_payload,
            content_type='application/json',
            auth=self.user.auth
        )

        assert_equal(res.status_code, 202)

        registration = Registration.find().order_by('-registered_date').first()

        assert_false(registration.is_public)
        assert_true(registration.is_pending_embargo_for_existing_registration)
        assert_is_not_none(registration.embargo)

    # Regression test for https://openscience.atlassian.net/browse/OSF-5071
    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_register_embargo_does_not_make_project_or_children_public(self, mock_enqueue):
        self.project.is_public = True
        self.project.save()
        NodeFactory(  # component
            creator=self.user,
            parent=self.project,
            title='Component',
            is_public=True
        )
        subproject = ProjectFactory(
            creator=self.user,
            parent=self.project,
            title='Subproject',
            is_public=True
        )
        NodeFactory(  # subproject's component
            creator=self.user,
            parent=subproject,
            title='Subcomponent',
            is_public=True
        )
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_embargo_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        self.project.reload()
        assert_equal(res.status_code, 202)
        assert_equal(res.json['urls']['registrations'], self.project.web_url_for('node_registrations'))

        # Last node directly registered from self.project
        registration = AbstractNode.objects.filter(registered_from=self.project).order_by('-registered_date')[0]

        assert_true(registration.is_registration)
        assert_false(registration.is_public)
        assert_true(registration.is_pending_embargo_for_existing_registration)
        assert_is_not_none(registration.embargo)

        for node in registration.get_descendants_recursive():
            assert_true(node.is_registration)
            assert_false(node.is_public)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_invalid_embargo_end_date_returns_HTTPBad_Request(self, mock_enqueue):
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.invalid_embargo_date_payload,
            content_type='application/json',
            auth=self.user.auth,
            expect_errors=True
        )

        assert_equal(res.status_code, 400)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_valid_POST_embargo_adds_to_parent_projects_log(self, mock_enquque):
        initial_project_logs = self.project.logs.count()
        self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_embargo_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        self.project.reload()
        # Logs: Created, registered, embargo initiated
        assert_equal(self.project.logs.count(), initial_project_logs + 1)

    @mock.patch('osf.models.sanctions.TokenApprovableSanction.ask')
    def test_embargoed_registration_set_privacy_requests_embargo_termination(self, mock_ask):
        # Initiate and approve embargo
        for i in range(3):
            c = AuthUserFactory()
            self.registration.add_contributor(c, [permissions.ADMIN], auth=Auth(self.user))
        self.registration.save()
        self.registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        for user_id, embargo_tokens in self.registration.embargo.approval_state.iteritems():
            approval_token = embargo_tokens['approval_token']
            self.registration.embargo.approve_embargo(OSFUser.load(user_id), approval_token)
        self.registration.save()

        self.registration.set_privacy('public', Auth(self.registration.creator))
        for reg in self.registration.node_and_primary_descendants():
            reg.reload()
            assert_false(reg.is_public)
        assert_true(reg.embargo_termination_approval)
        assert_true(reg.embargo_termination_approval.is_pending_approval)

    def test_cannot_request_termination_on_component_of_embargo(self):
        node = ProjectFactory()
        ProjectFactory(parent=node, creator=node.creator)  # child project

        with utils.mock_archive(node, embargo=True, autocomplete=True, autoapprove=True) as reg:
            with assert_raises(NodeStateError):
                reg._nodes.first().request_embargo_termination(Auth(node.creator))

    @mock.patch('website.mails.send_mail')
    def test_embargoed_registration_set_privacy_sends_mail(self, mock_send_mail):
        """
        Integration test for https://github.com/CenterForOpenScience/osf.io/pull/5294#issuecomment-212613668
        """
        # Initiate and approve embargo
        for i in range(3):
            c = AuthUserFactory()
            self.registration.add_contributor(c, [permissions.ADMIN], auth=Auth(self.user))
        self.registration.save()
        self.registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        for user_id, embargo_tokens in self.registration.embargo.approval_state.iteritems():
            approval_token = embargo_tokens['approval_token']
            self.registration.embargo.approve_embargo(OSFUser.load(user_id), approval_token)
        self.registration.save()

        self.registration.set_privacy('public', Auth(self.registration.creator))
        for admin in self.registration.admin_contributors:
            assert_true(any([each[0][0] == admin.username for each in mock_send_mail.call_args_list]))

    @mock.patch('osf.models.sanctions.TokenApprovableSanction.ask')
    def test_make_child_embargoed_registration_public_asks_all_admins_in_tree(self, mock_ask):
        # Initiate and approve embargo
        node = NodeFactory(creator=self.user)
        c1 = AuthUserFactory()
        child = NodeFactory(parent=node, creator=c1)
        c2 = AuthUserFactory()
        NodeFactory(parent=child, creator=c2)
        registration = RegistrationFactory(project=node)

        registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        for user_id, embargo_tokens in registration.embargo.approval_state.iteritems():
            approval_token = embargo_tokens['approval_token']
            registration.embargo.approve_embargo(OSFUser.load(user_id), approval_token)
        self.registration.save()

        registration.set_privacy('public', Auth(self.registration.creator))
        asked_admins = [(admin._id, n._id) for admin, n in mock_ask.call_args[0][0]]
        for admin, node in registration.get_admin_contributors_recursive():
            assert_in((admin._id, node._id), asked_admins)

    def test_non_contributor_GET_approval_returns_HTTPError(self):
        non_contributor = AuthUserFactory()
        self.registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        self.registration.save()
        assert_true(self.registration.is_pending_embargo)

        approval_token = self.registration.embargo.approval_state[self.user._id]['approval_token']
        approval_url = self.registration.web_url_for('view_project', token=approval_token)

        res = self.app.get(approval_url, auth=non_contributor.auth, expect_errors=True)
        self.registration.reload()
        assert_equal(http.UNAUTHORIZED, res.status_code)
        assert_true(self.registration.is_pending_embargo)
        assert_equal(self.registration.embargo.state, Embargo.UNAPPROVED)

    def test_non_contributor_GET_disapproval_returns_HTTPError(self):
        non_contributor = AuthUserFactory()
        self.registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        self.registration.save()
        assert_true(self.registration.is_pending_embargo)

        rejection_token = self.registration.embargo.approval_state[self.user._id]['rejection_token']
        approval_url = self.registration.web_url_for('view_project', token=rejection_token)

        res = self.app.get(approval_url, auth=non_contributor.auth, expect_errors=True)
        assert_equal(http.UNAUTHORIZED, res.status_code)
        assert_true(self.registration.is_pending_embargo)
        assert_equal(self.registration.embargo.state, Embargo.UNAPPROVED)
Пример #15
0
class TestMetadataGeneration(OsfTestCase):
    def setUp(self):
        OsfTestCase.setUp(self)
        self.visible_contrib = AuthUserFactory()
        visible_contrib2 = AuthUserFactory(given_name=u'ヽ༼ ಠ益ಠ ༽ノ',
                                           family_name=u'ლ(´◉❥◉`ლ)')
        self.invisible_contrib = AuthUserFactory()
        self.node = RegistrationFactory(is_public=True)
        self.identifier = Identifier(referent=self.node,
                                     category='catid',
                                     value='cat:7')
        self.node.add_contributor(self.visible_contrib, visible=True)
        self.node.add_contributor(self.invisible_contrib, visible=False)
        self.node.add_contributor(visible_contrib2, visible=True)
        self.node.save()

    # This test is not used as datacite is currently used for nodes, leaving here for future reference
    def test_datacite_metadata_for_preprint_has_correct_structure(self):
        provider = PreprintProviderFactory()
        license = NodeLicense.objects.get(
            name='CC-By Attribution 4.0 International')
        license_details = {
            'id': license.license_id,
            'year': '2017',
            'copyrightHolders': ['Jeff Hardy', 'Matt Hardy']
        }
        preprint = PreprintFactory(provider=provider,
                                   project=self.node,
                                   is_published=True,
                                   license_details=license_details)
        metadata_xml = metadata.datacite_metadata_for_preprint(
            preprint,
            doi=preprint.get_identifier('doi').value,
            pretty_print=True)

        root = lxml.etree.fromstring(metadata_xml)
        xsi_location = '{http://www.w3.org/2001/XMLSchema-instance}schemaLocation'
        expected_location = 'http://datacite.org/schema/kernel-4 http://schema.datacite.org/meta/kernel-4/metadata.xsd'
        assert root.attrib[xsi_location] == expected_location

        identifier = root.find('{%s}identifier' % metadata.NAMESPACE)
        assert identifier.attrib['identifierType'] == 'DOI'
        assert identifier.text == preprint.get_identifier('doi').value

        creators = root.find('{%s}creators' % metadata.NAMESPACE)
        assert len(creators.getchildren()) == len(
            self.node.visible_contributors)

        subjects = root.find('{%s}subjects' % metadata.NAMESPACE)
        assert subjects.getchildren()

        publisher = root.find('{%s}publisher' % metadata.NAMESPACE)
        assert publisher.text == provider.name

        pub_year = root.find('{%s}publicationYear' % metadata.NAMESPACE)
        assert pub_year.text == str(preprint.date_published.year)

        dates = root.find('{%s}dates' % metadata.NAMESPACE).getchildren()[0]
        assert dates.text == preprint.modified.isoformat()
        assert dates.attrib['dateType'] == 'Updated'

        alternate_identifier = root.find('{%s}alternateIdentifiers' %
                                         metadata.NAMESPACE).getchildren()[0]
        assert alternate_identifier.text == settings.DOMAIN + preprint._id
        assert alternate_identifier.attrib['alternateIdentifierType'] == 'URL'

        descriptions = root.find('{%s}descriptions' %
                                 metadata.NAMESPACE).getchildren()[0]
        assert descriptions.text == preprint.node.description

        rights = root.find('{%s}rightsList' %
                           metadata.NAMESPACE).getchildren()[0]
        assert rights.text == preprint.license.name

    # This test is not used as datacite is currently used for nodes, leaving here for future reference
    def test_datacite_format_creators_for_preprint(self):
        preprint = PreprintFactory(project=self.node, is_published=True)

        verified_user = AuthUserFactory(
            external_identity={'ORCID': {
                '1234-1234-1234-1234': 'VERIFIED'
            }})
        linked_user = AuthUserFactory(
            external_identity={'ORCID': {
                '1234-nope-1234-nope': 'LINK'
            }})
        self.node.add_contributor(verified_user, visible=True)
        self.node.add_contributor(linked_user, visible=True)
        self.node.save()

        formatted_creators = metadata.format_creators(preprint)

        contributors_with_orcids = 0
        guid_identifiers = []
        for creator_xml in formatted_creators:
            assert creator_xml.find('creatorName').text != u'{}, {}'.format(
                self.invisible_contrib.family_name,
                self.invisible_contrib.given_name)

            name_identifiers = creator_xml.findall('nameIdentifier')

            for name_identifier in name_identifiers:
                if name_identifier.attrib['nameIdentifierScheme'] == 'ORCID':
                    assert name_identifier.attrib[
                        'schemeURI'] == 'http://orcid.org/'
                    contributors_with_orcids += 1
                else:
                    guid_identifiers.append(name_identifier.text)
                    assert name_identifier.attrib[
                        'nameIdentifierScheme'] == 'OSF'
                    assert name_identifier.attrib[
                        'schemeURI'] == settings.DOMAIN

        assert contributors_with_orcids >= 1
        assert len(formatted_creators) == len(self.node.visible_contributors)
        assert sorted(guid_identifiers) == sorted([
            contrib.absolute_url for contrib in self.node.visible_contributors
        ])

    # This test is not used as datacite is currently used for nodes, leaving here for future reference
    def test_datacite_format_subjects_for_preprint(self):
        subject = SubjectFactory()
        subject_1 = SubjectFactory(parent=subject)
        subject_2 = SubjectFactory(parent=subject)

        subjects = [[subject._id, subject_1._id], [subject._id, subject_2._id]]
        preprint = PreprintFactory(subjects=subjects,
                                   project=self.node,
                                   is_published=True)

        formatted_subjects = metadata.format_subjects(preprint)
        assert len(formatted_subjects) == Subject.objects.all().count()
 def registration(self, admin, contrib):
     registration = RegistrationFactory(creator=admin)
     registration.add_contributor(admin, 'admin')
     registration.add_contributor(contrib, 'write')
     update_provider_auth_groups()
     return registration
Пример #17
0
class RegistrationEmbargoViewsTestCase(OsfTestCase):
    def setUp(self):
        super(RegistrationEmbargoViewsTestCase, self).setUp()
        self.user = AuthUserFactory()
        self.project = ProjectFactory(creator=self.user)
        self.draft = DraftRegistrationFactory(branched_from=self.project)
        self.registration = RegistrationFactory(project=self.project, creator=self.user)

        current_month = timezone.now().strftime('%B')
        current_year = timezone.now().strftime('%Y')

        self.valid_make_public_payload = json.dumps({
            u'embargoEndDate': u'Fri, 01, {month} {year} 00:00:00 GMT'.format(
                month=current_month,
                year=current_year
            ),
            u'registrationChoice': 'immediate',
            u'summary': unicode(fake.sentence())
        })
        valid_date = timezone.now() + datetime.timedelta(days=180)
        self.valid_embargo_payload = json.dumps({
            u'embargoEndDate': unicode(valid_date.strftime('%a, %d, %B %Y %H:%M:%S')) + u' GMT',
            u'registrationChoice': 'embargo',
            u'summary': unicode(fake.sentence())
        })
        self.invalid_embargo_date_payload = json.dumps({
            u'embargoEndDate': u"Thu, 01 {month} {year} 05:00:00 GMT".format(
                month=current_month,
                year=str(int(current_year) - 1)
            ),
            u'registrationChoice': 'embargo',
            u'summary': unicode(fake.sentence())
        })

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_register_draft_without_embargo_creates_registration_approval(self, mock_enqueue):
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_make_public_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        assert_equal(res.status_code, 202)

        registration = Registration.objects.all().order_by('-registered_date').first()
        assert_not_equal(registration.registration_approval, None)

    # Regression test for https://openscience.atlassian.net/browse/OSF-5039
    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_register_make_public_immediately_creates_private_pending_registration_for_public_project(self, mock_enqueue):
        self.project.is_public = True
        self.project.save()
        NodeFactory(  # component
            creator=self.user,
            parent=self.project,
            title='Component',
            is_public=True
        )
        subproject = ProjectFactory(
            creator=self.user,
            parent=self.project,
            title='Subproject',
            is_public=True
        )
        NodeFactory(  # subproject's component
            creator=self.user,
            parent=subproject,
            title='Subcomponent',
            is_public=True
        )
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_make_public_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        self.project.reload()
        assert_equal(res.status_code, 202)
        assert_equal(res.json['urls']['registrations'], self.project.web_url_for('node_registrations'))

        # Last node directly registered from self.project
        registration = AbstractNode.objects.filter(registered_from=self.project).order_by('-registered_date')[0]

        assert_true(registration.is_registration)
        assert_false(registration.is_public)
        for node in registration.get_descendants_recursive():
            assert_true(node.is_registration)
            assert_false(node.is_public)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_register_make_public_does_not_make_children_public(self, mock_enqueue):
        NodeFactory(  # component
            creator=self.user,
            parent=self.project,
            title='Component'
        )
        subproject = ProjectFactory(
            creator=self.user,
            parent=self.project,
            title='Subproject'
        )
        NodeFactory(  # subproject component
            creator=self.user,
            parent=subproject,
            title='Subcomponent'
        )

        self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_make_public_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        self.project.reload()
        # Last node directly registered from self.project
        registration = self.project.registrations.order_by('-registered_date').first()
        assert_false(registration.is_public)
        for node in registration.get_descendants_recursive():
            assert_true(node.is_registration)
            assert_false(node.is_public)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_register_embargo_is_not_public(self, mock_enqueue):
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_embargo_payload,
            content_type='application/json',
            auth=self.user.auth
        )

        assert_equal(res.status_code, 202)

        registration = Registration.objects.order_by('-registered_date').first()

        assert_false(registration.is_public)
        assert_true(registration.is_pending_embargo_for_existing_registration)
        assert_is_not_none(registration.embargo)

    # Regression test for https://openscience.atlassian.net/browse/OSF-5071
    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_register_embargo_does_not_make_project_or_children_public(self, mock_enqueue):
        self.project.is_public = True
        self.project.save()
        NodeFactory(  # component
            creator=self.user,
            parent=self.project,
            title='Component',
            is_public=True
        )
        subproject = ProjectFactory(
            creator=self.user,
            parent=self.project,
            title='Subproject',
            is_public=True
        )
        NodeFactory(  # subproject's component
            creator=self.user,
            parent=subproject,
            title='Subcomponent',
            is_public=True
        )
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_embargo_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        self.project.reload()
        assert_equal(res.status_code, 202)
        assert_equal(res.json['urls']['registrations'], self.project.web_url_for('node_registrations'))

        # Last node directly registered from self.project
        registration = AbstractNode.objects.filter(registered_from=self.project).order_by('-registered_date')[0]

        assert_true(registration.is_registration)
        assert_false(registration.is_public)
        assert_true(registration.is_pending_embargo_for_existing_registration)
        assert_is_not_none(registration.embargo)

        for node in registration.get_descendants_recursive():
            assert_true(node.is_registration)
            assert_false(node.is_public)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_POST_invalid_embargo_end_date_returns_HTTPBad_Request(self, mock_enqueue):
        res = self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.invalid_embargo_date_payload,
            content_type='application/json',
            auth=self.user.auth,
            expect_errors=True
        )

        assert_equal(res.status_code, 400)

    @mock.patch('framework.celery_tasks.handlers.enqueue_task')
    def test_valid_POST_embargo_adds_to_parent_projects_log(self, mock_enquque):
        initial_project_logs = self.project.logs.count()
        self.app.post(
            self.project.api_url_for('register_draft_registration', draft_id=self.draft._id),
            self.valid_embargo_payload,
            content_type='application/json',
            auth=self.user.auth
        )
        self.project.reload()
        # Logs: Created, registered, embargo initiated
        assert_equal(self.project.logs.count(), initial_project_logs + 1)

    @mock.patch('osf.models.sanctions.TokenApprovableSanction.ask')
    def test_embargoed_registration_set_privacy_requests_embargo_termination(self, mock_ask):
        # Initiate and approve embargo
        for i in range(3):
            c = AuthUserFactory()
            self.registration.add_contributor(c, [permissions.ADMIN], auth=Auth(self.user))
        self.registration.save()
        self.registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        for user_id, embargo_tokens in self.registration.embargo.approval_state.iteritems():
            approval_token = embargo_tokens['approval_token']
            self.registration.embargo.approve_embargo(OSFUser.load(user_id), approval_token)
        self.registration.save()

        self.registration.set_privacy('public', Auth(self.registration.creator))
        for reg in self.registration.node_and_primary_descendants():
            reg.reload()
            assert_false(reg.is_public)
        assert_true(reg.embargo_termination_approval)
        assert_true(reg.embargo_termination_approval.is_pending_approval)

    def test_cannot_request_termination_on_component_of_embargo(self):
        node = ProjectFactory()
        ProjectFactory(parent=node, creator=node.creator)  # child project

        with utils.mock_archive(node, embargo=True, autocomplete=True, autoapprove=True) as reg:
            with assert_raises(NodeStateError):
                reg._nodes.first().request_embargo_termination(Auth(node.creator))

    @mock.patch('website.mails.send_mail')
    def test_embargoed_registration_set_privacy_sends_mail(self, mock_send_mail):
        """
        Integration test for https://github.com/CenterForOpenScience/osf.io/pull/5294#issuecomment-212613668
        """
        # Initiate and approve embargo
        for i in range(3):
            c = AuthUserFactory()
            self.registration.add_contributor(c, [permissions.ADMIN], auth=Auth(self.user))
        self.registration.save()
        self.registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        for user_id, embargo_tokens in self.registration.embargo.approval_state.iteritems():
            approval_token = embargo_tokens['approval_token']
            self.registration.embargo.approve_embargo(OSFUser.load(user_id), approval_token)
        self.registration.save()

        self.registration.set_privacy('public', Auth(self.registration.creator))
        for admin in self.registration.admin_contributors:
            assert_true(any([each[0][0] == admin.username for each in mock_send_mail.call_args_list]))

    @mock.patch('osf.models.sanctions.TokenApprovableSanction.ask')
    def test_make_child_embargoed_registration_public_asks_all_admins_in_tree(self, mock_ask):
        # Initiate and approve embargo
        node = NodeFactory(creator=self.user)
        c1 = AuthUserFactory()
        child = NodeFactory(parent=node, creator=c1)
        c2 = AuthUserFactory()
        NodeFactory(parent=child, creator=c2)
        registration = RegistrationFactory(project=node)

        registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        for user_id, embargo_tokens in registration.embargo.approval_state.iteritems():
            approval_token = embargo_tokens['approval_token']
            registration.embargo.approve_embargo(OSFUser.load(user_id), approval_token)
        self.registration.save()

        registration.set_privacy('public', Auth(self.registration.creator))
        asked_admins = [(admin._id, n._id) for admin, n in mock_ask.call_args[0][0]]
        for admin, node in registration.get_admin_contributors_recursive():
            assert_in((admin._id, node._id), asked_admins)

    def test_non_contributor_GET_approval_returns_HTTPError(self):
        non_contributor = AuthUserFactory()
        self.registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        self.registration.save()
        assert_true(self.registration.is_pending_embargo)

        approval_token = self.registration.embargo.approval_state[self.user._id]['approval_token']
        approval_url = self.registration.web_url_for('view_project', token=approval_token)

        res = self.app.get(approval_url, auth=non_contributor.auth, expect_errors=True)
        self.registration.reload()
        assert_equal(http.UNAUTHORIZED, res.status_code)
        assert_true(self.registration.is_pending_embargo)
        assert_equal(self.registration.embargo.state, Embargo.UNAPPROVED)

    def test_non_contributor_GET_disapproval_returns_HTTPError(self):
        non_contributor = AuthUserFactory()
        self.registration.embargo_registration(
            self.user,
            timezone.now() + datetime.timedelta(days=10)
        )
        self.registration.save()
        assert_true(self.registration.is_pending_embargo)

        rejection_token = self.registration.embargo.approval_state[self.user._id]['rejection_token']
        approval_url = self.registration.web_url_for('view_project', token=rejection_token)

        res = self.app.get(approval_url, auth=non_contributor.auth, expect_errors=True)
        assert_equal(http.UNAUTHORIZED, res.status_code)
        assert_true(self.registration.is_pending_embargo)
        assert_equal(self.registration.embargo.state, Embargo.UNAPPROVED)
Пример #18
0
class RegistrationRetractionViewsTestCase(OsfTestCase):
    def setUp(self):
        super(RegistrationRetractionViewsTestCase, self).setUp()
        self.mock_registration_update = mock.patch('website.project.tasks.on_registration_updated')
        self.mock_registration_update.start()

        self.user = AuthUserFactory()
        self.registered_from = ProjectFactory(creator=self.user, is_public=True)
        self.registration = RegistrationFactory(project=self.registered_from, is_public=True)

        self.retraction_post_url = self.registration.api_url_for('node_registration_retraction_post')
        self.retraction_get_url = self.registration.web_url_for('node_registration_retraction_get')
        self.justification = fake.sentence()

    def tearDown(self):
        self.mock_registration_update.stop()
        super(RegistrationRetractionViewsTestCase, self).tearDown()

    def test_GET_retraction_page_when_pending_retraction_returns_HTTPError_BAD_REQUEST(self):
        self.registration.retract_registration(self.user)
        self.registration.save()

        res = self.app.get(
            self.retraction_get_url,
            auth=self.user.auth,
            expect_errors=True,
        )
        assert_equal(res.status_code, http.BAD_REQUEST)

    def test_POST_retraction_to_private_registration_returns_HTTPError_FORBIDDEN(self):
        self.registration.is_public = False
        self.registration.save()

        res = self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
            expect_errors=True,
        )
        assert_equal(res.status_code, http.FORBIDDEN)
        self.registration.reload()
        assert_is_none(self.registration.retraction)

    @mock.patch('website.mails.send_mail')
    def test_POST_retraction_does_not_send_email_to_unregistered_admins(self, mock_send_mail):
        unreg = UnregUserFactory()
        self.registration.add_contributor(
            unreg,
            auth=Auth(self.user),
            permissions=['read', 'write', 'admin']
        )
        self.registration.save()
        self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        # Only the creator gets an email; the unreg user does not get emailed
        assert_equal(mock_send_mail.call_count, 1)

    def test_POST_pending_embargo_returns_HTTPError_HTTPOK(self):
        self.registration.embargo_registration(
            self.user,
            (timezone.now() + datetime.timedelta(days=10)),
            for_existing_registration=True
        )
        self.registration.save()
        assert_true(self.registration.is_pending_embargo)

        res = self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
            expect_errors=True,
        )
        assert_equal(res.status_code, http.OK)
        self.registration.reload()
        assert_true(self.registration.is_pending_retraction)

    def test_POST_active_embargo_returns_HTTPOK(self):
        self.registration.embargo_registration(
            self.user,
            (timezone.now() + datetime.timedelta(days=10)),
            for_existing_registration=True
        )
        self.registration.save()
        assert_true(self.registration.is_pending_embargo)

        approval_token = self.registration.embargo.approval_state[self.user._id]['approval_token']
        self.registration.embargo.approve(self.user, approval_token)
        assert_true(self.registration.embargo_end_date)

        res = self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
            expect_errors=True,
        )
        assert_equal(res.status_code, http.OK)
        self.registration.reload()
        assert_true(self.registration.is_pending_retraction)

    def test_POST_retraction_by_non_admin_retract_HTTPError_UNAUTHORIZED(self):
        res = self.app.post_json(self.retraction_post_url, expect_errors=True)
        assert_equals(res.status_code, http.UNAUTHORIZED)
        self.registration.reload()
        assert_is_none(self.registration.retraction)

    @mock.patch('website.mails.send_mail')
    def test_POST_retraction_without_justification_returns_HTTPOK(self, mock_send):
        res = self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        assert_equal(res.status_code, http.OK)
        self.registration.reload()
        assert_false(self.registration.is_retracted)
        assert_true(self.registration.is_pending_retraction)
        assert_is_none(self.registration.retraction.justification)

    @mock.patch('website.mails.send_mail')
    def test_valid_POST_retraction_adds_to_parent_projects_log(self, mock_send):
        initial_project_logs = self.registration.registered_from.logs.count()
        self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        self.registration.registered_from.reload()
        # Logs: Created, registered, retraction initiated
        assert_equal(self.registration.registered_from.logs.count(), initial_project_logs + 1)

    @mock.patch('website.mails.send_mail')
    def test_valid_POST_retraction_when_pending_retraction_raises_400(self, mock_send):
        self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        res = self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
            expect_errors=True
        )
        assert_equal(res.status_code, 400)

    @mock.patch('website.mails.send_mail')
    def test_valid_POST_calls_send_mail_with_username(self, mock_send):
        self.app.post_json(
            self.retraction_post_url,
            {'justification': ''},
            auth=self.user.auth,
        )
        assert_true(mock_send.called)
        args, kwargs = mock_send.call_args
        assert_true(self.user.username in args)

    def test_non_contributor_GET_approval_returns_HTTPError_UNAUTHORIZED(self):
        non_contributor = AuthUserFactory()
        self.registration.retract_registration(self.user)
        approval_token = self.registration.retraction.approval_state[self.user._id]['approval_token']

        approval_url = self.registration.web_url_for('view_project', token=approval_token)
        res = self.app.get(approval_url, auth=non_contributor.auth, expect_errors=True)
        assert_equal(res.status_code, http.UNAUTHORIZED)
        assert_true(self.registration.is_pending_retraction)
        assert_false(self.registration.is_retracted)

    def test_non_contributor_GET_disapproval_returns_HTTPError_UNAUTHORIZED(self):
        non_contributor = AuthUserFactory()
        self.registration.retract_registration(self.user)
        rejection_token = self.registration.retraction.approval_state[self.user._id]['rejection_token']

        disapproval_url = self.registration.web_url_for('view_project', token=rejection_token)
        res = self.app.get(disapproval_url, auth=non_contributor.auth, expect_errors=True)
        assert_equal(res.status_code, http.UNAUTHORIZED)
        assert_true(self.registration.is_pending_retraction)
        assert_false(self.registration.is_retracted)
Пример #19
0
class TestMetadataGeneration(OsfTestCase):

    def setUp(self):
        OsfTestCase.setUp(self)
        self.visible_contrib = AuthUserFactory()
        visible_contrib2 = AuthUserFactory(given_name=u'ヽ༼ ಠ益ಠ ༽ノ', family_name=u'ლ(´◉❥◉`ლ)')
        self.invisible_contrib = AuthUserFactory()
        self.node = RegistrationFactory(is_public=True)
        self.identifier = Identifier(referent=self.node, category='catid', value='cat:7')
        self.node.add_contributor(self.visible_contrib, visible=True)
        self.node.add_contributor(self.invisible_contrib, visible=False)
        self.node.add_contributor(visible_contrib2, visible=True)
        self.node.save()

    def test_metadata_for_node_only_includes_visible_contribs(self):
        metadata_xml = metadata.datacite_metadata_for_node(self.node, doi=self.identifier.value)
        # includes visible contrib name
        assert_in(u'{}, {}'.format(
            self.visible_contrib.family_name, self.visible_contrib.given_name),
            metadata_xml)
        # doesn't include invisible contrib name
        assert_not_in(self.invisible_contrib.family_name, metadata_xml)

        assert_in(self.identifier.value, metadata_xml)

    def test_metadata_for_node_has_correct_structure(self):
        metadata_xml = metadata.datacite_metadata_for_node(self.node, doi=self.identifier.value)
        root = lxml.etree.fromstring(metadata_xml)
        xsi_location = '{http://www.w3.org/2001/XMLSchema-instance}schemaLocation'
        expected_location = 'http://datacite.org/schema/kernel-4 http://schema.datacite.org/meta/kernel-4/metadata.xsd'
        assert_equal(root.attrib[xsi_location], expected_location)

        identifier = root.find('{%s}identifier' % metadata.NAMESPACE)
        assert_equal(identifier.attrib['identifierType'], 'DOI')
        assert_equal(identifier.text, self.identifier.value)

        creators = root.find('{%s}creators' % metadata.NAMESPACE)
        assert_equal(len(creators.getchildren()), len(self.node.visible_contributors))

        publisher = root.find('{%s}publisher' % metadata.NAMESPACE)
        assert_equal(publisher.text, 'Open Science Framework')

        pub_year = root.find('{%s}publicationYear' % metadata.NAMESPACE)
        assert_equal(pub_year.text, str(self.node.registered_date.year))

    def test_metadata_for_preprint_has_correct_structure(self):
        provider = PreprintProviderFactory()
        license = NodeLicense.objects.get(name="CC-By Attribution 4.0 International")
        license_details = {
            'id': license.license_id,
            'year': '2017',
            'copyrightHolders': ['Jeff Hardy', 'Matt Hardy']
        }
        preprint = PreprintFactory(provider=provider, project=self.node, is_published=True, license_details=license_details)
        metadata_xml = metadata.datacite_metadata_for_preprint(preprint, doi=preprint.get_identifier('doi').value, pretty_print=True)

        root = lxml.etree.fromstring(metadata_xml)
        xsi_location = '{http://www.w3.org/2001/XMLSchema-instance}schemaLocation'
        expected_location = 'http://datacite.org/schema/kernel-4 http://schema.datacite.org/meta/kernel-4/metadata.xsd'
        assert root.attrib[xsi_location] == expected_location

        identifier = root.find('{%s}identifier' % metadata.NAMESPACE)
        assert identifier.attrib['identifierType'] == 'DOI'
        assert identifier.text == preprint.get_identifier('doi').value

        creators = root.find('{%s}creators' % metadata.NAMESPACE)
        assert len(creators.getchildren()) == len(self.node.visible_contributors)

        subjects = root.find('{%s}subjects' % metadata.NAMESPACE)
        assert subjects.getchildren()

        publisher = root.find('{%s}publisher' % metadata.NAMESPACE)
        assert publisher.text == provider.name

        pub_year = root.find('{%s}publicationYear' % metadata.NAMESPACE)
        assert pub_year.text == str(preprint.date_published.year)

        dates = root.find('{%s}dates' % metadata.NAMESPACE).getchildren()[0]
        assert dates.text == preprint.date_modified.isoformat()
        assert dates.attrib['dateType'] == 'Updated'

        alternate_identifier = root.find('{%s}alternateIdentifiers' % metadata.NAMESPACE).getchildren()[0]
        assert alternate_identifier.text == settings.DOMAIN + preprint._id
        assert alternate_identifier.attrib['alternateIdentifierType'] == 'URL'

        descriptions = root.find('{%s}descriptions' % metadata.NAMESPACE).getchildren()[0]
        assert descriptions.text == preprint.node.description

        rights = root.find('{%s}rightsList' % metadata.NAMESPACE).getchildren()[0]
        assert rights.text == preprint.license.name

    def test_format_creators_for_preprint(self):
        preprint = PreprintFactory(project=self.node, is_published=True)

        verified_user = AuthUserFactory(external_identity={'ORCID': {'1234-1234-1234-1234': 'VERIFIED'}})
        linked_user = AuthUserFactory(external_identity={'ORCID': {'1234-nope-1234-nope': 'LINK'}})
        self.node.add_contributor(verified_user, visible=True)
        self.node.add_contributor(linked_user, visible=True)
        self.node.save()

        formatted_creators = metadata.format_creators(preprint)

        contributors_with_orcids = 0
        for creator_xml in formatted_creators:
            assert creator_xml.find('creatorName').text != u'{}, {}'.format(self.invisible_contrib.family_name, self.invisible_contrib.given_name)
            if creator_xml.find('nameIdentifier') is not None:
                assert creator_xml.find('nameIdentifier').attrib['nameIdentifierScheme'] == 'ORCID'
                assert creator_xml.find('nameIdentifier').attrib['schemeURI'] == 'http://orcid.org/'
                contributors_with_orcids += 1

        assert contributors_with_orcids >= 1
        assert len(formatted_creators) == len(self.node.visible_contributors)

    def test_format_subjects_for_preprint(self):
        subject = SubjectFactory()
        subject_1 = SubjectFactory(parent=subject)
        subject_2 = SubjectFactory(parent=subject)

        subjects = [[subject._id, subject_1._id], [subject._id, subject_2._id]]
        preprint = PreprintFactory(subjects=subjects, project=self.node, is_published=True)

        formatted_subjects = metadata.format_subjects(preprint)
        assert len(formatted_subjects) == Subject.objects.all().count()
Пример #20
0
class TestRegistrationUpdate(ApiTestCase):

    def setUp(self):
        self.maxDiff = None
        super(TestRegistrationUpdate, self).setUp()
        self.user = AuthUserFactory()

        self.user_two = AuthUserFactory()
        self.user_three = AuthUserFactory()

        self.registration_approval = RegistrationApprovalFactory(state='unapproved', approve=False, user=self.user)
        self.unapproved_registration = Registration.find_one(Q('registration_approval', 'eq', self.registration_approval))
        self.unapproved_url = '/{}registrations/{}/'.format(API_BASE, self.unapproved_registration._id)

        self.public_project = ProjectFactory(title="Project One", is_public=True, creator=self.user)
        self.private_project = ProjectFactory(title="Project Two", is_public=False, creator=self.user)
        self.public_registration = RegistrationFactory(project=self.public_project, creator=self.user, is_public=True)
        self.private_registration = RegistrationFactory(project=self.private_project, creator=self.user)
        self.public_url = '/{}registrations/{}/'.format(API_BASE, self.public_registration._id)
        self.private_url = '/{}registrations/{}/'.format(API_BASE, self.private_registration._id)

        self.private_registration.add_contributor(self.user_two, permissions=[permissions.READ])
        self.private_registration.add_contributor(self.user_three, permissions=[permissions.WRITE])
        self.private_registration.save()

        self.payload = {
            "data": {
                "id": self.private_registration._id,
                "type": "registrations",
                "attributes": {
                    "public": True,
                }
            }
        }

    def make_payload(self, registration_id, attributes):
        return {
            "data": {
                "id": registration_id,
                "type": "registrations",
                "attributes": attributes
            }
        }

    def test_update_private_registration_logged_out(self):
        res = self.app.put_json_api(self.private_url, self.payload, expect_errors=True)
        assert_equal(res.status_code, 401)

    def test_update_private_registration_logged_in_admin(self):
        res = self.app.put_json_api(self.private_url, self.payload, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.json['data']['attributes']['public'], True)

    def test_update_private_registration_logged_in_read_only_contributor(self):
        res = self.app.put_json_api(self.private_url, self.payload, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_update_private_registration_logged_in_read_write_contributor(self):
        res = self.app.put_json_api(self.private_url, self.payload, auth=self.user_three.auth, expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_update_public_registration_to_private(self):
        payload = {
            "data": {
                "id": self.public_registration._id,
                "type": "registrations",
                "attributes": {
                    "public": False,
                }
            }
        }
        res = self.app.put_json_api(self.public_url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Registrations can only be turned from private to public.')

    def test_public_field_has_invalid_value(self):
        payload = {
            "data": {
                "id": self.public_registration._id,
                "type": "registrations",
                "attributes": {
                    "public": "Yes"
                }
            }
        }
        res = self.app.put_json_api(self.public_url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], '"Yes" is not a valid boolean.')

    def test_fields_other_than_public_are_ignored(self):
        payload = {
            "data": {
                "id": self.private_registration._id,
                "type": "registrations",
                "attributes": {
                    "public": True,
                    "category": "instrumentation",
                    "title": "New title",
                    "description": "New description"
                }
            }
        }
        res = self.app.put_json_api(self.private_url, payload, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.json['data']['attributes']['public'], True)
        assert_equal(res.json['data']['attributes']['category'], 'project')
        assert_equal(res.json['data']['attributes']['description'], self.private_registration.description)
        assert_equal(res.json['data']['attributes']['title'], self.private_registration.title)

    def test_type_field_must_match(self):
        payload = {
            "data": {
                "id": self.private_registration._id,
                "type": "nodes",
                "attributes": {
                    "public": True,
                    "category": "instrumentation",
                    "title": "New title",
                    "description": "New description"
                }
            }
        }
        res = self.app.put_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_id_field_must_match(self):
        payload = {
            "data": {
                "id": '12345',
                "type": "registrations",
                "attributes": {
                    "public": True,
                    "category": "instrumentation",
                    "title": "New title",
                    "description": "New description"
                }
            }
        }
        res = self.app.put_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_turning_private_registrations_public(self):
        node2 = ProjectFactory(creator=self.user, is_public=False)
        node1 = RegistrationFactory(project=node2, creator=self.user, is_public=False)

        payload = {
            "data": {
                "id": node1._id,
                "type": "registrations",
                "attributes": {
                    "public": True,
                }
            }
        }

        url = '/{}registrations/{}/'.format(API_BASE, node1._id)
        res = self.app.put_json_api(url, payload, auth=self.user.auth)
        assert_equal(res.json['data']['attributes']['public'], True)
        node1.reload()
        assert_true(node1.is_public)

    def test_registration_fields_are_read_only(self):
        writeable_fields = ['type', 'public', 'draft_registration', 'registration_choice', 'lift_embargo' ]
        for field in RegistrationSerializer._declared_fields:
            reg_field = RegistrationSerializer._declared_fields[field]
            if field not in writeable_fields:
                assert_equal(getattr(reg_field, 'read_only', False), True)

    def test_registration_detail_fields_are_read_only(self):
        writeable_fields = ['type', 'public', 'draft_registration', 'registration_choice', 'lift_embargo' ]

        for field in RegistrationDetailSerializer._declared_fields:
            reg_field = RegistrationSerializer._declared_fields[field]
            if field not in writeable_fields:
                assert_equal(getattr(reg_field, 'read_only', False), True)

    def test_user_cannot_delete_registration(self):
        res = self.app.delete_json_api(self.private_url, expect_errors=True, auth=self.user.auth)
        assert_equal(res.status_code, 405)

    def test_make_public_unapproved_registration_raises_error(self):
        payload = self.make_payload(
            self.unapproved_registration._id,
            {
                "public": True,
                "withdrawn": True
            }
        )
        res = self.app.put_json_api(self.unapproved_url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'An unapproved registration cannot be made public.')