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(User.load(user_id), approval_token) self.registration.save() res = self.app.post(registration.api_url_for('project_set_privacy', permissions='public'), auth=self.user.auth) assert_equal(res.status_code, 200) 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_register_draft_registration_already_registered(self): reg = RegistrationFactory(user=self.user) res = self.app.post_json(reg.api_url_for('register_draft_registration', draft_id=self.draft._id), self.invalid_payload, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, http.BAD_REQUEST)
def test_register_draft_registration_already_registered(self): reg = RegistrationFactory(user=self.user) res = self.app.post_json( reg.api_url_for('register_draft_registration', draft_id=self.draft._id), self.invalid_payload, auth=self.user.auth, expect_errors=True ) assert_equal(res.status_code, http.BAD_REQUEST)
class TestIdentifierViews(OsfTestCase): def setUp(self): super(TestIdentifierViews, self).setUp() self.user = AuthUserFactory() self.node = RegistrationFactory(creator=self.user, is_public=True) @httpretty.activate def test_create_identifiers_not_exists(self): identifier = self.node._id url = furl.furl('https://ezid.cdlib.org/id') doi = settings.EZID_FORMAT.format(namespace=settings.DOI_NAMESPACE, guid=identifier) url.path.segments.append(doi) httpretty.register_uri( httpretty.PUT, url.url, body=to_anvl({ 'success': '{doi}osf.io/{ident} | {ark}osf.io/{ident}'.format( doi=settings.DOI_NAMESPACE, ark=settings.ARK_NAMESPACE, ident=identifier, ), }), status=201, priority=1, ) res = self.app.post( self.node.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.node.reload() assert_equal(res.json['doi'], self.node.get_identifier_value('doi')) assert_equal(res.json['ark'], self.node.get_identifier_value('ark')) assert_equal(res.status_code, 201) @httpretty.activate def test_create_identifiers_exists(self): identifier = self.node._id doi = settings.EZID_FORMAT.format(namespace=settings.DOI_NAMESPACE, guid=identifier) url = furl.furl('https://ezid.cdlib.org/id') url.path.segments.append(doi) httpretty.register_uri( httpretty.PUT, url.url, body='identifier already exists', status=400, ) httpretty.register_uri( httpretty.GET, url.url, body=to_anvl({ 'success': doi, }), status=200, ) res = self.app.post( self.node.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.node.reload() assert_equal(res.json['doi'], self.node.get_identifier_value('doi')) assert_equal(res.json['ark'], self.node.get_identifier_value('ark')) assert_equal(res.status_code, 201) def test_get_by_identifier(self): self.node.set_identifier_value('doi', 'FK424601') self.node.set_identifier_value('ark', 'fk224601') res_doi = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='doi', value=self.node.get_identifier_value('doi'), ), ) assert_equal(res_doi.status_code, 302) assert_urls_equal(res_doi.headers['Location'], self.node.absolute_url) res_ark = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='ark', value=self.node.get_identifier_value('ark'), ), ) assert_equal(res_ark.status_code, 302) assert_urls_equal(res_ark.headers['Location'], self.node.absolute_url) def test_get_by_identifier_not_found(self): self.node.set_identifier_value('doi', 'FK424601') res = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='doi', value='fakedoi', ), expect_errors=True, ) assert_equal(res.status_code, 404)
class TestIdentifierViews(OsfTestCase): def setUp(self): super(TestIdentifierViews, self).setUp() self.user = AuthUserFactory() self.node = RegistrationFactory(creator=self.user, is_public=True) @httpretty.activate def test_create_identifiers_not_exists(self): identifier = self.node._id url = furl.furl('https://ezid.cdlib.org/id') doi = settings.EZID_FORMAT.format(namespace=settings.DOI_NAMESPACE, guid=identifier) url.path.segments.append(doi) httpretty.register_uri( httpretty.PUT, url.url, body=to_anvl({ 'success': '{doi}osf.io/{ident} | {ark}osf.io/{ident}'.format( doi=settings.DOI_NAMESPACE, ark=settings.ARK_NAMESPACE, ident=identifier, ), }), status=201, priority=1, ) res = self.app.post( self.node.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.node.reload() assert_equal( res.json['doi'], self.node.get_identifier_value('doi') ) assert_equal( res.json['ark'], self.node.get_identifier_value('ark') ) assert_equal(res.status_code, 201) @httpretty.activate def test_create_identifiers_exists(self): identifier = self.node._id doi = settings.EZID_FORMAT.format(namespace=settings.DOI_NAMESPACE, guid=identifier) url = furl.furl('https://ezid.cdlib.org/id') url.path.segments.append(doi) httpretty.register_uri( httpretty.PUT, url.url, body='identifier already exists', status=400, ) httpretty.register_uri( httpretty.GET, url.url, body=to_anvl({ 'success': doi, }), status=200, ) res = self.app.post( self.node.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.node.reload() assert_equal( res.json['doi'], self.node.get_identifier_value('doi') ) assert_equal( res.json['ark'], self.node.get_identifier_value('ark') ) assert_equal(res.status_code, 201) def test_get_by_identifier(self): self.node.set_identifier_value('doi', 'FK424601') self.node.set_identifier_value('ark', 'fk224601') res_doi = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='doi', value=self.node.get_identifier_value('doi'), ), ) assert_equal(res_doi.status_code, 302) assert_urls_equal(res_doi.headers['Location'], self.node.absolute_url) res_ark = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='ark', value=self.node.get_identifier_value('ark'), ), ) assert_equal(res_ark.status_code, 302) assert_urls_equal(res_ark.headers['Location'], self.node.absolute_url) def test_get_by_identifier_not_found(self): self.node.set_identifier_value('doi', 'FK424601') res = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='doi', value='fakedoi', ), expect_errors=True, ) assert_equal(res.status_code, 404)
class TestDataCiteViews(OsfTestCase): """ This tests the v1 views for Project/Registration DOI creation.""" def setUp(self): super(TestDataCiteViews, self).setUp() self.user = AuthUserFactory() self.node = RegistrationFactory(creator=self.user, is_public=True) self.client = DataCiteClient(base_url='https://mds.fake.datacite.org', prefix=settings.DATACITE_PREFIX) @responses.activate def test_datacite_create_identifiers_not_exists(self): responses.add( responses.Response( responses.POST, self.client.base_url + '/metadata', body='OK (10.70102/FK2osf.io/cq695)', status=201, )) responses.add( responses.Response( responses.POST, self.client.base_url + '/doi', body='OK (10.70102/FK2osf.io/cq695)', status=201, )) with mock.patch( 'osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res = self.app.post( self.node.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.node.reload() assert res.json['doi'] == self.node.get_identifier_value('doi') assert res.status_code == 201 @responses.activate def test_datacite_get_by_identifier(self): self.node.set_identifier_value('doi', 'FK424601') self.node.set_identifier_value('ark', 'fk224601') with mock.patch( 'osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res_doi = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='doi', value=self.node.get_identifier_value('doi'), ), ) assert res_doi.status_code == 302 assert_urls_equal(res_doi.headers['Location'], self.node.absolute_url) @responses.activate def test_datacite_get_by_identifier_not_found(self): self.node.set_identifier_value('doi', 'FK424601') with mock.patch( 'osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='doi', value='fakedoi', ), expect_errors=True, ) assert res.status_code == 404 def test_qatest_doesnt_make_dois(self): self.node.add_tag('qatest', auth=Auth(self.user)) assert not request_identifiers(self.node)
class TestDataCiteViews(OsfTestCase): """ This tests the v1 views for Project/Registration DOI creation.""" def setUp(self): super(TestDataCiteViews, self).setUp() self.user = AuthUserFactory() self.node = RegistrationFactory(creator=self.user, is_public=True) self.client = DataCiteClient(base_url = 'https://mds.fake.datacite.org', prefix=settings.DATACITE_PREFIX) @responses.activate def test_datacite_create_identifiers_not_exists(self): responses.add( responses.Response( responses.POST, self.client.base_url + '/metadata', body='OK (10.5072/FK2osf.io/cq695)', status=201, ) ) responses.add( responses.Response( responses.POST, self.client.base_url + '/doi', body='OK (10.5072/FK2osf.io/cq695)', status=201, ) ) with mock.patch('osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res = self.app.post( self.node.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.node.reload() assert res.json['doi'] == self.node.get_identifier_value('doi') assert res.status_code == 201 @responses.activate def test_datacite_get_by_identifier(self): self.node.set_identifier_value('doi', 'FK424601') self.node.set_identifier_value('ark', 'fk224601') with mock.patch('osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res_doi = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='doi', value=self.node.get_identifier_value('doi'), ), ) assert res_doi.status_code == 302 assert_urls_equal(res_doi.headers['Location'], self.node.absolute_url) @responses.activate def test_datacite_get_by_identifier_not_found(self): self.node.set_identifier_value('doi', 'FK424601') with mock.patch('osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res = self.app.get( self.node.web_url_for( 'get_referent_by_identifier', category='doi', value='fakedoi', ), expect_errors=True, ) assert res.status_code == 404
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_unregistered_contributor( unreg.fullname, unreg.email, auth=Auth(self.user), permissions=['read', 'write', 'admin'], existing_user=unreg) 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 TestEZIDClient(OsfTestCase): def setUp(self): super(TestEZIDClient, self).setUp() self.user = AuthUserFactory() self.registration = RegistrationFactory(creator=self.user, is_public=True) self.client = EzidClient(base_url='https://test.ezid.osf.io', prefix=settings.EZID_DOI_NAMESPACE.replace('doi:', '')) @override_switch('ezid', active=True) @responses.activate def test_create_identifiers_not_exists_ezid(self): guid = self.registration._id url = furl.furl(self.client.base_url) doi = settings.DOI_FORMAT.format(prefix=settings.EZID_DOI_NAMESPACE, guid=guid).replace('doi:', '') url.path.segments += ['id', doi] responses.add( responses.Response( responses.PUT, url.url, body=to_anvl({ 'success': '{doi}osf.io/{ident} | {ark}osf.io/{ident}'.format( doi=settings.EZID_DOI_NAMESPACE, ark=settings.EZID_ARK_NAMESPACE, ident=guid, ), }), status=201, ) ) with mock.patch('osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res = self.app.post( self.registration.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.registration.reload() assert_equal( res.json['doi'], self.registration.get_identifier_value('doi') ) assert_equal(res.status_code, 201) @override_switch('ezid', active=True) @responses.activate def test_create_identifiers_exists_ezid(self): guid = self.registration._id doi = settings.DOI_FORMAT.format(prefix=settings.EZID_DOI_NAMESPACE, guid=guid).replace('doi:', '') url = furl.furl(self.client.base_url) url.path.segments += ['id', doi] responses.add( responses.Response( responses.PUT, url.url, body='identifier already exists', status=400, ) ) responses.add( responses.Response( responses.GET, url.url, body=to_anvl({ 'success': doi, }), status=200, ) ) with mock.patch('osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res = self.app.post( self.registration.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.registration.reload() assert_equal( res.json['doi'], self.registration.get_identifier_value('doi') ) assert_equal(res.status_code, 201) @responses.activate def test_get_by_identifier(self): self.registration.set_identifier_value('doi', 'FK424601') self.registration.set_identifier_value('ark', 'fk224601') res_doi = self.app.get( self.registration.web_url_for( 'get_referent_by_identifier', category='doi', value=self.registration.get_identifier_value('doi'), ), ) assert_equal(res_doi.status_code, 302) assert_urls_equal(res_doi.headers['Location'], self.registration.absolute_url) res_ark = self.app.get( self.registration.web_url_for( 'get_referent_by_identifier', category='ark', value=self.registration.get_identifier_value('ark'), ), ) assert_equal(res_ark.status_code, 302) assert_urls_equal(res_ark.headers['Location'], self.registration.absolute_url) @responses.activate def test_get_by_identifier_not_found(self): self.registration.set_identifier_value('doi', 'FK424601') res = self.app.get( self.registration.web_url_for( 'get_referent_by_identifier', category='doi', value='fakedoi', ), expect_errors=True, ) assert_equal(res.status_code, 404)
class RegistrationEmbargoViewsTestCase(OsfTestCase): def setUp(self): super(RegistrationEmbargoViewsTestCase, self).setUp() ensure_schemas() 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().sort('-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 = Node.find(Q('registered_from', 'eq', self.project)).sort('-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().sort('-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 = Node.find(Q('registered_from', 'eq', self.project)).sort('-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(User.load(user_id), approval_token) self.registration.save() res = self.app.post( self.registration.api_url_for('project_set_privacy', permissions='public'), auth=self.user.auth, ) assert_equal(res.status_code, 200) 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(User.load(user_id), approval_token) self.registration.save() res = self.app.post( self.registration.api_url_for('project_set_privacy', permissions='public'), auth=self.user.auth, ) assert_equal(res.status_code, 200) 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(User.load(user_id), approval_token) self.registration.save() res = self.app.post(registration.api_url_for('project_set_privacy', permissions='public'), auth=self.user.auth) assert_equal(res.status_code, 200) 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.FORBIDDEN, 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.FORBIDDEN, res.status_code) assert_true(self.registration.is_pending_embargo) assert_equal(self.registration.embargo.state, Embargo.UNAPPROVED)
class TestEZIDClient(OsfTestCase): def setUp(self): super(TestEZIDClient, self).setUp() self.user = AuthUserFactory() self.registration = RegistrationFactory(creator=self.user, is_public=True) self.client = EzidClient(base_url='https://test.ezid.osf.io', prefix=settings.EZID_DOI_NAMESPACE.replace( 'doi:', '')) @override_switch('ezid', active=True) @responses.activate def test_create_identifiers_not_exists_ezid(self): guid = self.registration._id url = furl.furl(self.client.base_url) doi = settings.DOI_FORMAT.format(prefix=settings.EZID_DOI_NAMESPACE, guid=guid).replace('doi:', '') url.path.segments += ['id', doi] responses.add( responses.Response( responses.PUT, url.url, body=to_anvl({ 'success': '{doi}osf.io/{ident} | {ark}osf.io/{ident}'.format( doi=settings.EZID_DOI_NAMESPACE, ark=settings.EZID_ARK_NAMESPACE, ident=guid, ), }), status=201, )) with mock.patch( 'osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res = self.app.post( self.registration.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.registration.reload() assert_equal(res.json['doi'], self.registration.get_identifier_value('doi')) assert_equal(res.status_code, 201) @override_switch('ezid', active=True) @responses.activate def test_create_identifiers_exists_ezid(self): guid = self.registration._id doi = settings.DOI_FORMAT.format(prefix=settings.EZID_DOI_NAMESPACE, guid=guid).replace('doi:', '') url = furl.furl(self.client.base_url) url.path.segments += ['id', doi] responses.add( responses.Response( responses.PUT, url.url, body='identifier already exists', status=400, )) responses.add( responses.Response( responses.GET, url.url, body=to_anvl({ 'success': doi, }), status=200, )) with mock.patch( 'osf.models.Registration.get_doi_client') as mock_get_doi: mock_get_doi.return_value = self.client res = self.app.post( self.registration.api_url_for('node_identifiers_post'), auth=self.user.auth, ) self.registration.reload() assert_equal(res.json['doi'], self.registration.get_identifier_value('doi')) assert_equal(res.status_code, 201) @responses.activate def test_get_by_identifier(self): self.registration.set_identifier_value('doi', 'FK424601') self.registration.set_identifier_value('ark', 'fk224601') res_doi = self.app.get( self.registration.web_url_for( 'get_referent_by_identifier', category='doi', value=self.registration.get_identifier_value('doi'), ), ) assert_equal(res_doi.status_code, 302) assert_urls_equal(res_doi.headers['Location'], self.registration.absolute_url) res_ark = self.app.get( self.registration.web_url_for( 'get_referent_by_identifier', category='ark', value=self.registration.get_identifier_value('ark'), ), ) assert_equal(res_ark.status_code, 302) assert_urls_equal(res_ark.headers['Location'], self.registration.absolute_url) @responses.activate def test_get_by_identifier_not_found(self): self.registration.set_identifier_value('doi', 'FK424601') res = self.app.get( self.registration.web_url_for( 'get_referent_by_identifier', category='doi', value='fakedoi', ), expect_errors=True, ) assert_equal(res.status_code, 404)
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)