示例#1
0
 def provider_two(self):
     provider = PreprintProviderFactory(name='Spotarxiv')
     provider.allow_submissions = False
     provider.domain = 'https://www.spotarxiv.com'
     provider.description = 'spots not dots'
     provider.domain_redirect_enabled = True
     provider._id = 'spot'
     provider.share_publish_type = 'Thesis'
     provider.save()
     return provider
def provider_two():
    provider = PreprintProviderFactory(name='Spotarxiv')
    provider.allow_submissions = False
    provider.domain = 'https://www.spotarxiv.com'
    provider.description = 'spots not dots'
    provider.domain_redirect_enabled = True
    provider._id = 'spot'
    provider.share_publish_type = 'Thesis'
    provider.save()
    return provider
def preprint():
    node_license = NodeLicense.objects.get(name='CC-By Attribution 4.0 International')
    user = AuthUserFactory()
    provider = PreprintProviderFactory()
    provider.doi_prefix = '10.31219'
    provider.save()
    license_details = {
        'id': node_license.license_id,
        'year': '2017',
        'copyrightHolders': ['Jeff Hardy', 'Matt Hardy']
    }
    preprint = PreprintFactory(provider=provider, article_doi='10.31219/FK2osf.io/test!', is_published=True, license_details=license_details)
    preprint.license.node_license.url = 'https://creativecommons.org/licenses/by/4.0/legalcode'
    return preprint
def preprint():
    node_license = NodeLicense.objects.get(name='CC-By Attribution 4.0 International')
    user = AuthUserFactory()
    provider = PreprintProviderFactory()
    provider.doi_prefix = '10.31219'
    provider.save()
    license_details = {
        'id': node_license.license_id,
        'year': '2017',
        'copyrightHolders': ['Jeff Hardy', 'Matt Hardy']
    }
    preprint = PreprintFactory(provider=provider, article_doi='10.31219/FK2osf.io/test!', is_published=True, license_details=license_details)
    preprint.license.node_license.url = 'https://creativecommons.org/licenses/by/4.0/legalcode'
    return preprint
示例#5
0
class TestDeletePreprintProvider(AdminTestCase):
    def setUp(self):
        super(TestDeletePreprintProvider, self).setUp()

        self.user = AuthUserFactory()
        self.preprint_provider = PreprintProviderFactory()

        self.request = RequestFactory().get('/fake_path')
        self.view = views.DeletePreprintProvider()
        self.view = setup_user_view(self.view, self.request, user=self.user)

        self.view.kwargs = {'preprint_provider_id': self.preprint_provider.id}

    def test_cannot_delete_if_preprints_present(self):
        preprint = PreprintFactory()
        self.preprint_provider.preprint_services.add(preprint)
        self.preprint_provider.save()

        redirect = self.view.delete(self.request)
        nt.assert_equal(
            redirect.url, '/preprint_providers/{}/cannot_delete/'.format(
                self.preprint_provider.id))
        nt.assert_equal(redirect.status_code, 302)

    def test_delete_provider_with_no_preprints(self):
        redirect = self.view.delete(self.request)
        nt.assert_equal(redirect.url, '/preprint_providers/')
        nt.assert_equal(redirect.status_code, 302)

    def test_get_with_no_preprints(self):
        res = self.view.get(self.request)
        nt.assert_equal(res.status_code, 200)

    def test_cannot_get_if_preprints_present(self):
        preprint = PreprintFactory()
        self.preprint_provider.preprint_services.add(preprint)
        self.preprint_provider.save()

        redirect = self.view.get(self.request)
        nt.assert_equal(
            redirect.url, '/preprint_providers/{}/cannot_delete/'.format(
                self.preprint_provider.id))
        nt.assert_equal(redirect.status_code, 302)
示例#6
0
class TestDeletePreprintProvider(AdminTestCase):
    def setUp(self):
        super(TestDeletePreprintProvider, self).setUp()

        self.user = AuthUserFactory()
        self.preprint_provider = PreprintProviderFactory()

        self.request = RequestFactory().get('/fake_path')
        self.view = views.DeletePreprintProvider()
        self.view = setup_user_view(self.view, self.request, user=self.user)

        self.view.kwargs = {'preprint_provider_id': self.preprint_provider.id}

    def test_cannot_delete_if_preprints_present(self):
        preprint = PreprintFactory()
        self.preprint_provider.preprint_services.add(preprint)
        self.preprint_provider.save()

        redirect = self.view.delete(self.request)
        nt.assert_equal(redirect.url, '/preprint_providers/{}/cannot_delete/'.format(self.preprint_provider.id))
        nt.assert_equal(redirect.status_code, 302)

    def test_delete_provider_with_no_preprints(self):
        redirect = self.view.delete(self.request)
        nt.assert_equal(redirect.url, '/preprint_providers/')
        nt.assert_equal(redirect.status_code, 302)

    def test_get_with_no_preprints(self):
        res = self.view.get(self.request)
        nt.assert_equal(res.status_code, 200)

    def test_cannot_get_if_preprints_present(self):
        preprint = PreprintFactory()
        self.preprint_provider.preprint_services.add(preprint)
        self.preprint_provider.save()

        redirect = self.view.get(self.request)
        nt.assert_equal(redirect.url, '/preprint_providers/{}/cannot_delete/'.format(self.preprint_provider.id))
        nt.assert_equal(redirect.status_code, 302)
class TestPreprintProviderSubjects(ApiTestCase):
    def create_subject_rules(self):
        '''
        Subject Hierarchy
        +-----------------------------+
        |                             |
        |      +-------->B+----->F    |
        |      |                      |
        |  A+----------->C            |
        |      |                      |
        |      +-------->D+----->G    |
        |                             |
        |  H+------>I+----->J         |
        |            |                |
        |            +----->K         |
        |                             |
        |  L+------>M+----->N         |
        |            |                |
        |            +------->E       |
        |                             |
        |  O                          |
        +-----------------------------+
        '''
        self.subA = SubjectFactory(text='A')
        self.subB = SubjectFactory(text='B', parent=self.subA)
        self.subC = SubjectFactory(text='C', parent=self.subA)
        self.subD = SubjectFactory(text='D', parent=self.subA)
        self.subF = SubjectFactory(text='F', parent=self.subB)
        self.subG = SubjectFactory(text='G', parent=self.subD)
        self.subH = SubjectFactory(text='H')
        self.subI = SubjectFactory(text='I', parent=self.subH)
        self.subJ = SubjectFactory(text='J', parent=self.subI)
        self.subK = SubjectFactory(text='K', parent=self.subI)
        self.subL = SubjectFactory(text='L')
        self.subM = SubjectFactory(text='M', parent=self.subL)
        self.subE = SubjectFactory(text='E', parent=self.subM)
        self.subN = SubjectFactory(text='N', parent=self.subM)
        self.subO = SubjectFactory(text='O')
        rules = [([self.subA._id, self.subB._id], False),
                 ([self.subA._id, self.subD._id], True),
                 ([self.subH._id, self.subI._id, self.subJ._id], True),
                 ([self.subL._id], True)]
        #  This should allow: A, B, D, G, H, I, J, L, M, N and E
        #  This should not allow: C, F, K, O
        return rules

    def setUp(self):
        super(TestPreprintProviderSubjects, self).setUp()
        self.lawless_preprint_provider = PreprintProviderFactory()
        self.ruled_preprint_provider = PreprintProviderFactory()
        self.ruled_preprint_provider.subjects_acceptable = self.create_subject_rules(
        )
        self.ruled_preprint_provider.save()
        self.lawless_url = '/{}preprint_providers/{}/taxonomies/?page[size]=15&'.format(
            API_BASE, self.lawless_preprint_provider._id)
        self.ruled_url = '/{}preprint_providers/{}/taxonomies/?page[size]=15&'.format(
            API_BASE, self.ruled_preprint_provider._id)

    def test_no_rules_grabs_all(self):
        res = self.app.get(self.lawless_url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 15)

    def test_rules_only_grab_acceptable_subjects(self):
        res = self.app.get(self.ruled_url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 11)

    def test_no_rules_with_null_parent_filter(self):
        res = self.app.get(self.lawless_url + 'filter[parents]=null')

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 4)

    def test_rules_enforced_with_null_parent_filter(self):
        res = self.app.get(self.ruled_url + 'filter[parents]=null')

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 3)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('A', texts)
        assert_in('H', texts)
        assert_in('L', texts)
        assert_not_in('O', texts)

    def test_no_rules_with_parents_filter(self):
        res = self.app.get(self.lawless_url +
                           'filter[parents]={}'.format(self.subB._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 1)
        assert_equal(res.json['data'][0]['attributes']['text'], 'F')

        res = self.app.get(self.lawless_url +
                           'filter[parents]={}'.format(self.subI._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

        res = self.app.get(self.lawless_url +
                           'filter[parents]={}'.format(self.subM._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

    def test_rules_enforced_with_parents_filter(self):
        res = self.app.get(self.ruled_url +
                           'filter[parents]={}'.format(self.subB._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 0)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_not_in('F', texts)

        res = self.app.get(self.ruled_url +
                           'filter[parents]={}'.format(self.subI._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 1)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('J', texts)
        assert_not_in('K', texts)

        res = self.app.get(self.ruled_url +
                           'filter[parents]={}'.format(self.subM._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('N', texts)
        assert_in('E', texts)

    def test_no_rules_with_parent_filter(self):
        res = self.app.get(self.lawless_url +
                           'filter[parent]={}'.format(self.subB._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 1)
        assert_equal(res.json['data'][0]['attributes']['text'], 'F')

        res = self.app.get(self.lawless_url +
                           'filter[parent]={}'.format(self.subI._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

        res = self.app.get(self.lawless_url +
                           'filter[parent]={}'.format(self.subM._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

    def test_rules_enforced_with_parent_filter(self):
        res = self.app.get(self.ruled_url +
                           'filter[parent]={}'.format(self.subB._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 0)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_not_in('F', texts)

        res = self.app.get(self.ruled_url +
                           'filter[parent]={}'.format(self.subI._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 1)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('J', texts)
        assert_not_in('K', texts)

        res = self.app.get(self.ruled_url +
                           'filter[parent]={}'.format(self.subM._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('N', texts)
        assert_in('E', texts)

    def test_no_rules_with_grandparent_filter(self):
        res = self.app.get(self.lawless_url +
                           'filter[parents]={}'.format(self.subA._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 3)

    def test_rules_enforced_with_grandparent_filter(self):
        res = self.app.get(self.ruled_url +
                           'filter[parents]={}'.format(self.subA._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('B', texts)
        assert_in('D', texts)
        assert_not_in('C', texts)
 def preprint_provider(self, cc0_license, no_license):
     preprint_provider = PreprintProviderFactory()
     preprint_provider.licenses_acceptable = [cc0_license, no_license]
     preprint_provider.save()
     return preprint_provider
示例#9
0
class TestPreprintCreate(ApiTestCase):
    def setUp(self):
        super(TestPreprintCreate, self).setUp()

        self.user = AuthUserFactory()
        self.other_user = AuthUserFactory()
        self.private_project = ProjectFactory(creator=self.user)
        self.public_project = ProjectFactory(creator=self.user, is_public=True)
        self.public_project.add_contributor(
            self.other_user,
            permissions=permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS,
            save=True)
        self.subject = SubjectFactory()
        self.provider = PreprintProviderFactory()

        self.user_two = AuthUserFactory()

        self.file_one_public_project = test_utils.create_test_file(
            self.public_project, self.user, 'millionsofdollars.pdf')
        self.file_one_private_project = test_utils.create_test_file(
            self.private_project, self.user, 'woowoowoo.pdf')

        self.url = '/{}preprints/'.format(API_BASE)

    def test_create_preprint_from_public_project(self):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id,
            self.file_one_public_project._id)
        res = self.app.post_json_api(self.url,
                                     public_project_payload,
                                     auth=self.user.auth)

        assert_equal(res.status_code, 201)

    @mock.patch('website.preprints.tasks.get_and_set_preprint_identifiers.si')
    def test_create_preprint_from_private_project(self,
                                                  mock_create_identifiers):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id,
            self.file_one_private_project._id,
            attrs={
                'subjects': [[SubjectFactory()._id]],
                'is_published': True
            })
        res = self.app.post_json_api(self.url,
                                     private_project_payload,
                                     auth=self.user.auth)

        self.private_project.reload()
        assert_equal(res.status_code, 201)
        assert_true(self.private_project.is_public)

    def test_non_authorized_user(self):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id,
            self.file_one_public_project._id)
        res = self.app.post_json_api(self.url,
                                     public_project_payload,
                                     auth=self.user_two.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 403)

    def test_read_write_user_not_admin(self):
        assert_in(self.other_user, self.public_project.contributors)
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id,
            self.file_one_public_project._id)
        res = self.app.post_json_api(self.url,
                                     public_project_payload,
                                     auth=self.other_user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 403)

    def test_file_is_not_in_node(self):
        wrong_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id,
            self.file_one_private_project._id)
        res = self.app.post_json_api(self.url,
                                     wrong_project_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_already_a_preprint_with_conflicting_provider(self):
        preprint = PreprintFactory(creator=self.user)
        file_one_preprint = test_utils.create_test_file(
            preprint.node, self.user, 'openupthatwindow.pdf')

        already_preprint_payload = build_preprint_create_payload(
            preprint.node._id, preprint.provider._id, file_one_preprint._id)
        res = self.app.post_json_api(self.url,
                                     already_preprint_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 409)
        assert_in(
            'Only one preprint per provider can be submitted for a node.',
            res.json['errors'][0]['detail'])

    def test_read_write_user_already_a_preprint_with_conflicting_provider(
            self):
        assert_in(self.other_user, self.public_project.contributors)

        preprint = PreprintFactory(creator=self.user)
        preprint.node.add_contributor(
            self.other_user,
            permissions=permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS,
            save=True)
        file_one_preprint = test_utils.create_test_file(
            preprint.node, self.user, 'openupthatwindow.pdf')

        already_preprint_payload = build_preprint_create_payload(
            preprint.node._id, self.provider._id, file_one_preprint._id)
        res = self.app.post_json_api(self.url,
                                     already_preprint_payload,
                                     auth=self.other_user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 403)

    @mock.patch('website.preprints.tasks.get_and_set_preprint_identifiers.si')
    def test_publish_preprint_fails_with_no_primary_file(
            self, mock_get_identifiers):
        no_file_payload = build_preprint_create_payload(
            node_id=self.public_project._id,
            provider_id=self.provider._id,
            file_id=None,
            attrs={
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            })
        res = self.app.post_json_api(self.url,
                                     no_file_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'A valid primary_file must be set before publishing a preprint.')

    @mock.patch('website.preprints.tasks.get_and_set_preprint_identifiers.si')
    def test_publish_preprint_fails_with_invalid_primary_file(
            self, mock_get_identifiers):
        no_file_payload = build_preprint_create_payload(
            node_id=self.public_project._id,
            provider_id=self.provider._id,
            file_id='totallynotanid',
            attrs={
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            })
        res = self.app.post_json_api(self.url,
                                     no_file_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'A valid primary_file must be set before publishing a preprint.')

    def test_no_provider_given(self):
        no_providers_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id,
            self.file_one_public_project._id)
        del no_providers_payload['data']['relationships']['provider']
        res = self.app.post_json_api(self.url,
                                     no_providers_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'You must specify a valid provider to create a preprint.')

    def test_invalid_provider_given(self):
        wrong_provider_payload = build_preprint_create_payload(
            self.public_project._id, 'jobbers',
            self.file_one_public_project._id)

        res = self.app.post_json_api(self.url,
                                     wrong_provider_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'You must specify a valid provider to create a preprint.')

    def test_request_id_does_not_match_request_url_id(self):
        public_project_payload = build_preprint_create_payload(
            self.private_project._id, self.provider._id,
            self.file_one_public_project._id)
        res = self.app.post_json_api(self.url,
                                     public_project_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_file_not_osfstorage(self):
        github_file = self.file_one_public_project
        github_file.recast(GithubFile._typedmodels_type)
        github_file.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, github_file._id)
        res = self.app.post_json_api(self.url,
                                     public_project_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_preprint_contributor_signal_not_sent_on_creation(self):
        with capture_signals() as mock_signals:
            public_project_payload = build_preprint_create_payload(
                self.public_project._id, self.provider._id,
                self.file_one_public_project._id)
            res = self.app.post_json_api(self.url,
                                         public_project_payload,
                                         auth=self.user.auth)

            assert_equal(res.status_code, 201)
            assert_not_in(project_signals.contributor_added,
                          mock_signals.signals_sent())

    def test_create_preprint_with_deleted_node_should_fail(self):
        self.public_project.is_deleted = True
        self.public_project.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id,
            self.file_one_public_project._id)
        res = self.app.post_json_api(self.url,
                                     public_project_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     'Cannot create a preprint from a deleted node.')

    @mock.patch('website.preprints.tasks.get_and_set_preprint_identifiers.si')
    def test_create_preprint_adds_log_if_published(self, mock_get_identifiers):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id,
            self.file_one_public_project._id, {
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            })
        res = self.app.post_json_api(self.url,
                                     public_project_payload,
                                     auth=self.user.auth)
        assert_equal(res.status_code, 201)
        preprint_id = res.json['data']['id']
        preprint = PreprintService.load(preprint_id)
        log = preprint.node.logs.latest()
        assert_equal(log.action, 'preprint_initiated')
        assert_equal(log.params.get('preprint'), preprint_id)

    @mock.patch('website.preprints.tasks.get_and_set_preprint_identifiers.si')
    @mock.patch('website.preprints.tasks.on_preprint_updated.si')
    def test_create_preprint_from_project_published_hits_update(
            self, mock_on_preprint_updated, mock_get_identifiers):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id,
            self.file_one_private_project._id,
            attrs={
                'subjects': [[SubjectFactory()._id]],
                'is_published': True
            })
        res = self.app.post_json_api(self.url,
                                     private_project_payload,
                                     auth=self.user.auth)
        assert mock_on_preprint_updated.called

    @mock.patch('website.preprints.tasks.on_preprint_updated.si')
    def test_create_preprint_from_project_unpublished_does_not_hit_update(
            self, mock_on_preprint_updated):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id,
            self.file_one_private_project._id,
            attrs={
                'subjects': [[SubjectFactory()._id]],
                'is_published': False
            })
        res = self.app.post_json_api(self.url,
                                     private_project_payload,
                                     auth=self.user.auth)
        assert not mock_on_preprint_updated.called

    @mock.patch('website.preprints.tasks.get_and_set_preprint_identifiers.si')
    @mock.patch('website.preprints.tasks.on_preprint_updated.si')
    def test_setting_is_published_with_moderated_provider_fails(
            self, mock_get_identifiers, mock_on_preprint_updated):
        self.provider.reviews_workflow = 'pre-moderation'
        self.provider.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id,
            self.file_one_public_project._id, {
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            })
        res = self.app.post_json_api(self.url,
                                     public_project_payload,
                                     auth=self.user.auth,
                                     expect_errors=True)
        assert res.status_code == 409
        assert not mock_get_identifiers.called
        assert not mock_on_preprint_updated.called
示例#10
0
class TestPreprintUpdateLicense(ApiTestCase):
    def setUp(self):
        super(TestPreprintUpdateLicense, self).setUp()

        ensure_licenses()

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

        self.preprint_provider = PreprintProviderFactory()
        self.preprint = PreprintFactory(creator=self.admin_contributor,
                                        provider=self.preprint_provider)

        self.preprint.node.add_contributor(self.rw_contributor,
                                           auth=Auth(self.admin_contributor))
        self.preprint.node.add_contributor(self.read_contributor,
                                           auth=Auth(self.admin_contributor),
                                           permissions=['read'])
        self.preprint.node.save()

        self.cc0_license = NodeLicense.find_one(
            Q('name', 'eq', 'CC0 1.0 Universal'))
        self.mit_license = NodeLicense.find_one(Q('name', 'eq', 'MIT License'))
        self.no_license = NodeLicense.find_one(Q('name', 'eq', 'No license'))

        self.preprint_provider.licenses_acceptable = [
            self.cc0_license, self.no_license
        ]
        self.preprint_provider.save()

        self.url = '/{}preprints/{}/'.format(API_BASE, self.preprint._id)

    def make_payload(self,
                     node_id,
                     license_id=None,
                     license_year=None,
                     copyright_holders=None):
        attributes = {}

        if license_year and copyright_holders:
            attributes = {
                'license_record': {
                    'year': license_year,
                    'copyright_holders': copyright_holders
                }
            }
        elif license_year:
            attributes = {'license_record': {'year': license_year}}
        elif copyright_holders:
            attributes = {
                'license_record': {
                    'copyright_holders': copyright_holders
                }
            }

        return {
            'data': {
                'id': node_id,
                'attributes': attributes,
                'relationships': {
                    'license': {
                        'data': {
                            'type': 'licenses',
                            'id': license_id
                        }
                    }
                }
            }
        } if license_id else {
            'data': {
                'id': node_id,
                'attributes': attributes
            }
        }

    def make_request(self, url, data, auth=None, expect_errors=False):
        return self.app.patch_json_api(url,
                                       data,
                                       auth=auth,
                                       expect_errors=expect_errors)

    def test_admin_update_license_with_invalid_id(self):
        data = self.make_payload(node_id=self.preprint._id,
                                 license_id='thisisafakelicenseid')

        assert_equal(self.preprint.license, None)

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth,
                                expect_errors=True)
        assert_equal(res.status_code, 404)
        assert_equal(res.json['errors'][0]['detail'],
                     'Unable to find specified license.')

        self.preprint.reload()
        assert_equal(self.preprint.license, None)

    def test_admin_can_update_license(self):
        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.cc0_license._id)

        assert_equal(self.preprint.license, None)

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth)
        assert_equal(res.status_code, 200)
        self.preprint.reload()

        assert_equal(self.preprint.license.node_license, self.cc0_license)
        assert_equal(self.preprint.license.year, None)
        assert_equal(self.preprint.license.copyright_holders, [])

        # check logs
        log = self.preprint.node.logs.latest()
        assert_equal(log.action, 'preprint_license_updated')
        assert_equal(log.params.get('preprint'), self.preprint._id)

    def test_admin_can_update_license_record(self):
        data = self.make_payload(
            node_id=self.preprint._id,
            license_id=self.no_license._id,
            license_year='2015',
            copyright_holders=['Bojack Horseman, Princess Carolyn'])

        assert_equal(self.preprint.license, None)

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth)
        assert_equal(res.status_code, 200)
        self.preprint.reload()

        assert_equal(self.preprint.license.node_license, self.no_license)
        assert_equal(self.preprint.license.year, '2015')
        assert_equal(self.preprint.license.copyright_holders,
                     ['Bojack Horseman, Princess Carolyn'])

    def test_rw_contributor_cannot_update_license(self):
        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.cc0_license._id)

        res = self.make_request(self.url,
                                data,
                                auth=self.rw_contributor.auth,
                                expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'],
                     'User must be an admin to update a preprint.')

    def test_read_contributor_cannot_update_license(self):
        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.cc0_license._id)

        res = self.make_request(self.url,
                                data,
                                auth=self.read_contributor.auth,
                                expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'],
                     'You do not have permission to perform this action.')

    def test_non_contributor_cannot_update_license(self):
        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.cc0_license._id)

        res = self.make_request(self.url,
                                data,
                                auth=self.non_contributor.auth,
                                expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(res.json['errors'][0]['detail'],
                     'You do not have permission to perform this action.')

    def test_unauthenticated_user_cannot_update_license(self):
        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.cc0_license._id)

        res = self.make_request(self.url, data, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_equal(res.json['errors'][0]['detail'],
                     'Authentication credentials were not provided.')

    def test_update_preprint_with_invalid_license_for_provider(self):
        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.mit_license._id)

        assert_equal(self.preprint.license, None)

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth,
                                expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_equal(
            res.json['errors'][0]['detail'],
            'Invalid license chosen for {}'.format(
                self.preprint_provider.name))

    def test_update_preprint_with_existing_license_year_attribute_only(self):
        self.preprint.set_preprint_license(
            {
                'id': self.no_license.license_id,
                'year': '2014',
                'copyrightHolders': ['Diane', 'Mr. Peanut Butter']
            },
            Auth(self.admin_contributor),
        )
        self.preprint.save()

        assert_equal(self.preprint.license.node_license, self.no_license)
        assert_equal(self.preprint.license.year, '2014')
        assert_equal(self.preprint.license.copyright_holders,
                     ['Diane', 'Mr. Peanut Butter'])

        data = self.make_payload(node_id=self.preprint._id,
                                 license_year='2015')

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth)
        assert_equal(res.status_code, 200)
        self.preprint.license.reload()

        assert_equal(self.preprint.license.node_license, self.no_license)
        assert_equal(self.preprint.license.year, '2015')
        assert_equal(self.preprint.license.copyright_holders,
                     ['Diane', 'Mr. Peanut Butter'])

    def test_update_preprint_with_existing_license_copyright_holders_attribute_only(
            self):
        self.preprint.set_preprint_license(
            {
                'id': self.no_license.license_id,
                'year': '2014',
                'copyrightHolders': ['Diane', 'Mr. Peanut Butter']
            },
            Auth(self.admin_contributor),
        )
        self.preprint.save()

        assert_equal(self.preprint.license.node_license, self.no_license)
        assert_equal(self.preprint.license.year, '2014')
        assert_equal(self.preprint.license.copyright_holders,
                     ['Diane', 'Mr. Peanut Butter'])

        data = self.make_payload(
            node_id=self.preprint._id,
            copyright_holders=['Bojack Horseman', 'Princess Carolyn'])

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth)
        assert_equal(res.status_code, 200)
        self.preprint.license.reload()

        assert_equal(self.preprint.license.node_license, self.no_license)
        assert_equal(self.preprint.license.year, '2014')
        assert_equal(self.preprint.license.copyright_holders,
                     ['Bojack Horseman', 'Princess Carolyn'])

    def test_update_preprint_with_existing_license_relationship_only(self):
        self.preprint.set_preprint_license(
            {
                'id': self.no_license.license_id,
                'year': '2014',
                'copyrightHolders': ['Diane', 'Mr. Peanut Butter']
            },
            Auth(self.admin_contributor),
        )
        self.preprint.save()

        assert_equal(self.preprint.license.node_license, self.no_license)
        assert_equal(self.preprint.license.year, '2014')
        assert_equal(self.preprint.license.copyright_holders,
                     ['Diane', 'Mr. Peanut Butter'])

        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.cc0_license._id)

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth)
        assert_equal(res.status_code, 200)
        self.preprint.license.reload()

        assert_equal(self.preprint.license.node_license, self.cc0_license)
        assert_equal(self.preprint.license.year, '2014')
        assert_equal(self.preprint.license.copyright_holders,
                     ['Diane', 'Mr. Peanut Butter'])

    def test_update_preprint_with_existing_license_relationship_and_attributes(
            self):
        self.preprint.set_preprint_license(
            {
                'id': self.no_license.license_id,
                'year': '2014',
                'copyrightHolders': ['Diane', 'Mr. Peanut Butter']
            },
            Auth(self.admin_contributor),
            save=True)

        assert_equal(self.preprint.license.node_license, self.no_license)
        assert_equal(self.preprint.license.year, '2014')
        assert_equal(self.preprint.license.copyright_holders,
                     ['Diane', 'Mr. Peanut Butter'])

        data = self.make_payload(
            node_id=self.preprint._id,
            license_id=self.cc0_license._id,
            license_year='2015',
            copyright_holders=['Bojack Horseman', 'Princess Carolyn'])

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth)
        assert_equal(res.status_code, 200)
        self.preprint.license.reload()

        assert_equal(self.preprint.license.node_license, self.cc0_license)
        assert_equal(self.preprint.license.year, '2015')
        assert_equal(self.preprint.license.copyright_holders,
                     ['Bojack Horseman', 'Princess Carolyn'])

    def test_update_preprint_license_without_required_year_in_payload(self):
        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.no_license._id,
                                 copyright_holders=['Rick', 'Morty'])

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth,
                                expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     'year must be specified for this license')

    def test_update_preprint_license_without_required_copyright_holders_in_payload_(
            self):
        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.no_license._id,
                                 license_year='1994')

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth,
                                expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     'copyrightHolders must be specified for this license')

    def test_update_preprint_license_does_not_change_project_license(self):
        self.preprint.node.set_node_license(
            {
                'id': self.no_license.license_id,
                'year': '2015',
                'copyrightHolders': ['Simba', 'Mufasa']
            },
            auth=Auth(self.admin_contributor))
        self.preprint.node.save()
        assert_equal(self.preprint.node.node_license.node_license,
                     self.no_license)

        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.cc0_license._id)

        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth)
        assert_equal(res.status_code, 200)
        self.preprint.reload()

        assert_equal(self.preprint.license.node_license, self.cc0_license)
        assert_equal(self.preprint.node.node_license.node_license,
                     self.no_license)

    def test_update_preprint_license_without_change_does_not_add_log(self):
        self.preprint.set_preprint_license(
            {
                'id': self.no_license.license_id,
                'year': '2015',
                'copyrightHolders': ['Kim', 'Kanye']
            },
            auth=Auth(self.admin_contributor),
            save=True)

        before_num_logs = self.preprint.node.logs.count()
        before_update_log = self.preprint.node.logs.latest()

        data = self.make_payload(node_id=self.preprint._id,
                                 license_id=self.no_license._id,
                                 license_year='2015',
                                 copyright_holders=['Kanye', 'Kim'])
        res = self.make_request(self.url,
                                data,
                                auth=self.admin_contributor.auth)
        self.preprint.node.reload()

        after_num_logs = self.preprint.node.logs.count()
        after_update_log = self.preprint.node.logs.latest()

        assert_equal(res.status_code, 200)
        assert_equal(before_num_logs, after_num_logs)
        assert_equal(before_update_log._id, after_update_log._id)
class TestPreprintCreate(ApiTestCase):
    def setUp(self):
        super(TestPreprintCreate, self).setUp()

        self.user = AuthUserFactory()
        self.other_user = AuthUserFactory()
        self.private_project = ProjectFactory(creator=self.user)
        self.public_project = ProjectFactory(creator=self.user, is_public=True)
        self.public_project.add_contributor(
            self.other_user,
            permissions=permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS,
            save=True)
        self.subject = SubjectFactory()
        self.provider = PreprintProviderFactory()

        self.user_two = AuthUserFactory()
        self.url = '/{}preprints/'.format(API_BASE)

    def publish_preprint(self, preprint, user, expect_errors=False):
        preprint_file = test_utils.create_test_preprint_file(
            preprint, user, 'coffee_manuscript.pdf')

        update_payload = build_preprint_update_payload(preprint._id, preprint_file._id)

        res = self.app.patch_json_api(
            self.url + '{}/'.format(preprint._id),
            update_payload,
            auth=user.auth,
            expect_errors=expect_errors
        )
        return res

    def test_create_preprint_with_supplemental_public_project(self):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)

        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth)

        data = res.json['data']
        preprint = Preprint.load(data['id'])
        assert_equal(res.status_code, 201)
        assert_equal(data['attributes']['is_published'], False)
        assert preprint.node == self.public_project

    def test_create_preprint_with_supplemental_private_project(self):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id,
            attrs={
                'subjects': [
                    [
                        SubjectFactory()._id]],
            })
        res = self.app.post_json_api(
            self.url,
            private_project_payload,
            auth=self.user.auth)

        assert_equal(res.status_code, 201)
        self.private_project.reload()
        assert_false(self.private_project.is_public)

        preprint = Preprint.load(res.json['data']['id'])
        res = self.publish_preprint(preprint, self.user)
        preprint.reload()
        assert_equal(res.status_code, 200)
        self.private_project.reload()
        assert_false(self.private_project.is_public)
        assert_true(preprint.is_public)
        assert_true(preprint.is_published)

    def test_non_authorized_user_on_supplemental_node(self):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user_two.auth,
            expect_errors=True)

        assert_equal(res.status_code, 403)

    def test_write_user_on_supplemental_node(self):
        assert_in(self.other_user, self.public_project.contributors)
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.other_user.auth,
            expect_errors=True)
        # Users can create a preprint with a supplemental node that they have write perms to
        assert_equal(res.status_code, 201)

    def test_read_user_on_supplemental_node(self):
        self.public_project.set_permissions(self.other_user, ['read'], save=True)
        assert_in(self.other_user, self.public_project.contributors)
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.other_user.auth,
            expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_file_is_not_in_node(self):
        file_one_project = test_utils.create_test_file(
            self.public_project, self.user, 'openupthatwindow.pdf')
        assert_equal(file_one_project.target, self.public_project)
        wrong_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, file_one_project._id)
        res = self.app.post_json_api(
            self.url,
            wrong_project_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        # File which is targeted towards the project instead of the preprint is invalid
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_already_has_supplemental_node_on_another_preprint(self):
        preprint = PreprintFactory(creator=self.user, project=self.public_project)
        already_preprint_payload = build_preprint_create_payload(
            preprint.node._id, preprint.provider._id)
        res = self.app.post_json_api(
            self.url,
            already_preprint_payload,
            auth=self.user.auth,
            expect_errors=True)
        # One preprint per provider per node constraint has been lifted
        assert_equal(res.status_code, 201)

    def test_read_write_user_already_a_preprint_with_same_provider(
            self):
        assert_in(self.other_user, self.public_project.contributors)

        preprint = PreprintFactory(creator=self.user, project=self.public_project)
        already_preprint_payload = build_preprint_create_payload(
            preprint.node._id, preprint.provider._id)
        res = self.app.post_json_api(
            self.url,
            already_preprint_payload,
            auth=self.other_user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 201)

    def test_publish_preprint_fails_with_no_primary_file(self):
        no_file_payload = build_preprint_create_payload(
            node_id=self.public_project._id,
            provider_id=self.provider._id,
            file_id=None,
            attrs={
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            }
        )
        res = self.app.post_json_api(
            self.url,
            no_file_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'A valid primary_file must be set before publishing a preprint.')

    def test_publish_preprint_fails_with_invalid_primary_file(self):
        no_file_payload = build_preprint_create_payload(
            node_id=self.public_project._id,
            provider_id=self.provider._id,
            attrs={
                'subjects': [[SubjectFactory()._id]],
            }
        )
        res = self.app.post_json_api(
            self.url,
            no_file_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 201)
        preprint = Preprint.load(res.json['data']['id'])
        update_payload = build_preprint_update_payload(preprint._id, 'fakefileid')

        res = self.app.patch_json_api(
            self.url + '{}/'.format(preprint._id),
            update_payload,
            auth=self.user.auth,
            expect_errors=True
        )

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'A valid primary_file must be set before publishing a preprint.')

    def test_no_provider_given(self):
        no_providers_payload = build_preprint_create_payload()
        res = self.app.post_json_api(
            self.url,
            no_providers_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'You must specify a valid provider to create a preprint.')

    def test_invalid_provider_given(self):
        wrong_provider_payload = build_preprint_create_payload(
            provider_id='jobbers')

        res = self.app.post_json_api(
            self.url,
            wrong_provider_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'You must specify a valid provider to create a preprint.')

    def test_file_not_osfstorage(self):
        public_project_payload = build_preprint_create_payload(
            provider_id=self.provider._id)

        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)

        preprint = Preprint.load(res.json['data']['id'])
        assert_equal(res.status_code, 201)

        github_file = test_utils.create_test_preprint_file(
            preprint, self.user, 'coffee_manuscript.pdf')
        github_file.recast(GithubFile._typedmodels_type)
        github_file.save()

        update_payload = build_preprint_update_payload(preprint._id, github_file._id)

        res = self.app.patch_json_api(
            self.url + '{}/'.format(preprint._id),
            update_payload,
            auth=self.user.auth,
            expect_errors=True
        )

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_preprint_contributor_signal_sent_on_creation(self):
        # Signal sent but bails out early without sending email
        with capture_signals() as mock_signals:
            payload = build_preprint_create_payload(
                provider_id=self.provider._id)
            res = self.app.post_json_api(
                self.url, payload, auth=self.user.auth)

            assert_equal(res.status_code, 201)
            assert_true(len(mock_signals.signals_sent()) == 1)
            assert_in(
                project_signals.contributor_added,
                mock_signals.signals_sent())

    def test_create_preprint_with_deleted_node_should_fail(self):
        self.public_project.is_deleted = True
        self.public_project.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     'Cannot attach a deleted project to a preprint.')

    def test_create_preprint_with_no_permissions_to_node(self):
        project = ProjectFactory()
        public_project_payload = build_preprint_create_payload(
            project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_create_preprint_adds_log_if_published(self):
        public_project_payload = build_preprint_create_payload(
            provider_id=self.provider._id,
        )
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth)
        assert_equal(res.status_code, 201)

        preprint = Preprint.load(res.json['data']['id'])
        res = self.publish_preprint(preprint, self.user)

        log = preprint.logs.latest()
        assert_equal(log.action, 'published')
        assert_equal(log.params.get('preprint'), preprint._id)

    @mock.patch('osf.models.preprint.update_or_enqueue_on_preprint_updated')
    def test_create_preprint_from_project_published_hits_update(
            self, mock_on_preprint_updated):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id)
        res = self.app.post_json_api(
            self.url,
            private_project_payload,
            auth=self.user.auth)

        assert_false(mock_on_preprint_updated.called)
        preprint = Preprint.load(res.json['data']['id'])
        self.publish_preprint(preprint, self.user)

        assert_true(mock_on_preprint_updated.called)

    @mock.patch('osf.models.preprint.update_or_enqueue_on_preprint_updated')
    def test_create_preprint_from_project_unpublished_does_not_hit_update(
            self, mock_on_preprint_updated):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id)
        self.app.post_json_api(
            self.url,
            private_project_payload,
            auth=self.user.auth)
        assert not mock_on_preprint_updated.called

    @mock.patch('osf.models.preprint.update_or_enqueue_on_preprint_updated')
    def test_setting_is_published_with_moderated_provider_fails(
            self, mock_on_preprint_updated):
        self.provider.reviews_workflow = 'pre-moderation'
        self.provider.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id,
            self.provider._id,
        )
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)
        assert res.status_code == 201
        preprint = Preprint.load(res.json['data']['id'])
        res = self.publish_preprint(preprint, self.user, expect_errors=True)
        assert res.status_code == 409
        assert not mock_on_preprint_updated.called
class TestPreprintCreate(ApiTestCase):
    def setUp(self):
        super(TestPreprintCreate, self).setUp()

        self.user = AuthUserFactory()
        self.other_user = AuthUserFactory()
        self.private_project = ProjectFactory(creator=self.user)
        self.public_project = ProjectFactory(creator=self.user, is_public=True)
        self.public_project.add_contributor(
            self.other_user,
            permissions=permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS,
            save=True)
        self.subject = SubjectFactory()
        self.provider = PreprintProviderFactory()

        self.user_two = AuthUserFactory()
        self.url = '/{}preprints/'.format(API_BASE)

    def publish_preprint(self, preprint, user, expect_errors=False):
        preprint_file = test_utils.create_test_preprint_file(
            preprint, user, 'coffee_manuscript.pdf')

        update_payload = build_preprint_update_payload(preprint._id, preprint_file._id)

        res = self.app.patch_json_api(
            self.url + '{}/'.format(preprint._id),
            update_payload,
            auth=user.auth,
            expect_errors=expect_errors
        )
        return res

    def test_create_preprint_with_supplemental_public_project(self):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)

        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth)

        data = res.json['data']
        preprint = Preprint.load(data['id'])
        assert_equal(res.status_code, 201)
        assert_equal(data['attributes']['is_published'], False)
        assert preprint.node == self.public_project

    def test_create_preprint_with_supplemental_private_project(self):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id,
            attrs={
                'subjects': [
                    [
                        SubjectFactory()._id]],
            })
        res = self.app.post_json_api(
            self.url,
            private_project_payload,
            auth=self.user.auth)

        assert_equal(res.status_code, 201)
        self.private_project.reload()
        assert_false(self.private_project.is_public)

        preprint = Preprint.load(res.json['data']['id'])
        res = self.publish_preprint(preprint, self.user)
        preprint.reload()
        assert_equal(res.status_code, 200)
        self.private_project.reload()
        assert_false(self.private_project.is_public)
        assert_true(preprint.is_public)
        assert_true(preprint.is_published)

    def test_non_authorized_user_on_supplemental_node(self):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user_two.auth,
            expect_errors=True)

        assert_equal(res.status_code, 403)

    def test_write_user_on_supplemental_node(self):
        assert_in(self.other_user, self.public_project.contributors)
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.other_user.auth,
            expect_errors=True)
        # Users can create a preprint with a supplemental node that they have write perms to
        assert_equal(res.status_code, 201)

    def test_read_user_on_supplemental_node(self):
        self.public_project.set_permissions(self.other_user, permissions.READ, save=True)
        assert_in(self.other_user, self.public_project.contributors)
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.other_user.auth,
            expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_file_is_not_in_node(self):
        file_one_project = test_utils.create_test_file(
            self.public_project, self.user, 'openupthatwindow.pdf')
        assert_equal(file_one_project.target, self.public_project)
        wrong_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, file_one_project._id)
        res = self.app.post_json_api(
            self.url,
            wrong_project_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        # File which is targeted towards the project instead of the preprint is invalid
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_already_has_supplemental_node_on_another_preprint(self):
        preprint = PreprintFactory(creator=self.user, project=self.public_project)
        already_preprint_payload = build_preprint_create_payload(
            preprint.node._id, preprint.provider._id)
        res = self.app.post_json_api(
            self.url,
            already_preprint_payload,
            auth=self.user.auth,
            expect_errors=True)
        # One preprint per provider per node constraint has been lifted
        assert_equal(res.status_code, 201)

    def test_read_write_user_already_a_preprint_with_same_provider(
            self):
        assert_in(self.other_user, self.public_project.contributors)

        preprint = PreprintFactory(creator=self.user, project=self.public_project)
        already_preprint_payload = build_preprint_create_payload(
            preprint.node._id, preprint.provider._id)
        res = self.app.post_json_api(
            self.url,
            already_preprint_payload,
            auth=self.other_user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 201)

    def test_publish_preprint_fails_with_no_primary_file(self):
        no_file_payload = build_preprint_create_payload(
            node_id=self.public_project._id,
            provider_id=self.provider._id,
            file_id=None,
            attrs={
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            }
        )
        res = self.app.post_json_api(
            self.url,
            no_file_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'A valid primary_file must be set before publishing a preprint.')

    def test_publish_preprint_fails_with_invalid_primary_file(self):
        no_file_payload = build_preprint_create_payload(
            node_id=self.public_project._id,
            provider_id=self.provider._id,
            attrs={
                'subjects': [[SubjectFactory()._id]],
            }
        )
        res = self.app.post_json_api(
            self.url,
            no_file_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 201)
        preprint = Preprint.load(res.json['data']['id'])
        update_payload = build_preprint_update_payload(preprint._id, 'fakefileid')

        res = self.app.patch_json_api(
            self.url + '{}/'.format(preprint._id),
            update_payload,
            auth=self.user.auth,
            expect_errors=True
        )

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'A valid primary_file must be set before publishing a preprint.')

    def test_no_provider_given(self):
        no_providers_payload = build_preprint_create_payload()
        res = self.app.post_json_api(
            self.url,
            no_providers_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'You must specify a valid provider to create a preprint.')

    def test_invalid_provider_given(self):
        wrong_provider_payload = build_preprint_create_payload(
            provider_id='jobbers')

        res = self.app.post_json_api(
            self.url,
            wrong_provider_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'You must specify a valid provider to create a preprint.')

    def test_file_not_osfstorage(self):
        public_project_payload = build_preprint_create_payload(
            provider_id=self.provider._id)

        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)

        preprint = Preprint.load(res.json['data']['id'])
        assert_equal(res.status_code, 201)

        github_file = test_utils.create_test_preprint_file(
            preprint, self.user, 'coffee_manuscript.pdf')
        github_file.recast(GithubFile._typedmodels_type)
        github_file.save()

        update_payload = build_preprint_update_payload(preprint._id, github_file._id)

        res = self.app.patch_json_api(
            self.url + '{}/'.format(preprint._id),
            update_payload,
            auth=self.user.auth,
            expect_errors=True
        )

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_preprint_contributor_signal_sent_on_creation(self):
        # Signal sent but bails out early without sending email
        with capture_signals() as mock_signals:
            payload = build_preprint_create_payload(
                provider_id=self.provider._id)
            res = self.app.post_json_api(
                self.url, payload, auth=self.user.auth)

            assert_equal(res.status_code, 201)
            assert_true(len(mock_signals.signals_sent()) == 1)
            assert_in(
                project_signals.contributor_added,
                mock_signals.signals_sent())

    def test_create_preprint_with_deleted_node_should_fail(self):
        self.public_project.is_deleted = True
        self.public_project.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     'Cannot attach a deleted project to a preprint.')

    def test_create_preprint_with_no_permissions_to_node(self):
        project = ProjectFactory()
        public_project_payload = build_preprint_create_payload(
            project._id, self.provider._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)
        assert_equal(res.status_code, 403)

    def test_create_preprint_adds_log_if_published(self):
        public_project_payload = build_preprint_create_payload(
            provider_id=self.provider._id,
        )
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth)
        assert_equal(res.status_code, 201)

        preprint = Preprint.load(res.json['data']['id'])
        res = self.publish_preprint(preprint, self.user)

        log = preprint.logs.latest()
        assert_equal(log.action, 'published')
        assert_equal(log.params.get('preprint'), preprint._id)

    @mock.patch('osf.models.preprint.update_or_enqueue_on_preprint_updated')
    def test_create_preprint_from_project_published_hits_update(
            self, mock_on_preprint_updated):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id)
        res = self.app.post_json_api(
            self.url,
            private_project_payload,
            auth=self.user.auth)

        assert_false(mock_on_preprint_updated.called)
        preprint = Preprint.load(res.json['data']['id'])
        self.publish_preprint(preprint, self.user)

        assert_true(mock_on_preprint_updated.called)

    @mock.patch('osf.models.preprint.update_or_enqueue_on_preprint_updated')
    def test_create_preprint_from_project_unpublished_does_not_hit_update(
            self, mock_on_preprint_updated):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id)
        self.app.post_json_api(
            self.url,
            private_project_payload,
            auth=self.user.auth)
        assert not mock_on_preprint_updated.called

    @mock.patch('osf.models.preprint.update_or_enqueue_on_preprint_updated')
    def test_setting_is_published_with_moderated_provider_fails(
            self, mock_on_preprint_updated):
        self.provider.reviews_workflow = 'pre-moderation'
        self.provider.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id,
            self.provider._id,
        )
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)
        assert res.status_code == 201
        preprint = Preprint.load(res.json['data']['id'])
        res = self.publish_preprint(preprint, self.user, expect_errors=True)
        assert res.status_code == 409
        assert not mock_on_preprint_updated.called
示例#13
0
class TestPreprintProviderLicenses(ApiTestCase):
    def setUp(self):
        super(TestPreprintProviderLicenses, self).setUp()
        self.provider = PreprintProviderFactory()
        self.licenses = NodeLicense.objects.all()
        self.license1 = self.licenses[0]
        self.license2 = self.licenses[1]
        self.license3 = self.licenses[2]
        self.url = '/{}preprint_providers/{}/licenses/'.format(
            API_BASE, self.provider._id)

    def test_preprint_provider_has_no_acceptable_licenses_and_no_default(self):
        self.provider.licenses_acceptable = []
        self.provider.default_license = None
        self.provider.save()
        res = self.app.get(self.url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], len(self.licenses))

    def test_preprint_provider_has_a_default_license_but_no_acceptable_licenses(
            self):
        self.provider.licenses_acceptable = []
        self.provider.default_license = self.license2
        self.provider.save()
        res = self.app.get(self.url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], len(self.licenses))

        assert_equal(self.license2._id, res.json['data'][0]['id'])

    def test_prerint_provider_has_acceptable_licenses_but_no_default(self):
        self.provider.licenses_acceptable.add(self.license1, self.license2)
        self.provider.default_license = None
        self.provider.save()
        res = self.app.get(self.url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

        license_ids = [item['id'] for item in res.json['data']]
        assert_in(self.license1._id, license_ids)
        assert_in(self.license2._id, license_ids)
        assert_not_in(self.license3._id, license_ids)

    def test_preprint_provider_has_both_acceptable_and_default_licenses(self):
        self.provider.licenses_acceptable.add(self.license1, self.license3)
        self.provider.default_license = self.license3
        self.provider.save()
        res = self.app.get(self.url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

        license_ids = [item['id'] for item in res.json['data']]
        assert_in(self.license1._id, license_ids)
        assert_in(self.license3._id, license_ids)
        assert_not_in(self.license2._id, license_ids)

        assert_equal(self.license3._id, license_ids[0])
示例#14
0
    def test_resolve_guid_download_file_from_emberapp_preprints_unpublished(self):
        # non-branded domains
        provider = PreprintProviderFactory(_id='sockarxiv', name='Sockarxiv', reviews_workflow='pre-moderation')

        # branded domains
        branded_provider = PreprintProviderFactory(_id='spot', name='Spotarxiv', reviews_workflow='pre-moderation')
        branded_provider.allow_submissions = False
        branded_provider.domain = 'https://www.spotarxiv.com'
        branded_provider.description = 'spots not dots'
        branded_provider.domain_redirect_enabled = True
        branded_provider.share_publish_type = 'Thesis'
        branded_provider.save()

        # test_provider_submitter_can_download_unpublished
        submitter = AuthUserFactory()
        pp = PreprintFactory(finish=True, provider=provider, is_published=False, creator=submitter)
        pp.run_submit(submitter)
        pp_branded = PreprintFactory(finish=True, provider=branded_provider, is_published=False, filename='preprint_file_two.txt', creator=submitter)
        pp_branded.run_submit(submitter)

        res = self.app.get('{}download'.format(pp.url), auth=submitter.auth)
        assert res.status_code == 302
        assert '{}/v1/resources/{}/providers/{}{}?action=download&version=1&direct'.format(WATERBUTLER_URL, pp._id, pp.primary_file.provider, pp.primary_file.path) in res.location

        res = self.app.get('{}download'.format(pp_branded.url), auth=submitter.auth)
        assert res.status_code == 302

        # test_provider_super_user_can_download_unpublished
        super_user = AuthUserFactory()
        super_user.is_superuser = True
        super_user.save()

        res = self.app.get('{}download'.format(pp.url), auth=super_user.auth)
        assert res.status_code == 302
        assert '{}/v1/resources/{}/providers/{}{}?action=download&version=1&direct'.format(WATERBUTLER_URL, pp._id, pp.primary_file.provider, pp.primary_file.path) in res.location

        res = self.app.get('{}download'.format(pp_branded.url), auth=super_user.auth)
        assert res.status_code == 302

        # test_provider_moderator_can_download_unpublished
        moderator = AuthUserFactory()
        provider.add_to_group(moderator, 'moderator')
        provider.save()

        res = self.app.get('{}download'.format(pp.url), auth=moderator.auth)
        assert res.status_code == 302
        assert '{}/v1/resources/{}/providers/{}{}?action=download&version=1&direct'.format(WATERBUTLER_URL, pp._id, pp.primary_file.provider, pp.primary_file.path) in res.location

        branded_provider.add_to_group(moderator, 'moderator')
        branded_provider.save()

        res = self.app.get('{}download'.format(pp_branded.url), auth=moderator.auth)
        assert res.status_code == 302

        # test_provider_admin_can_download_unpublished
        admin = AuthUserFactory()
        provider.add_to_group(admin, ADMIN)
        provider.save()

        res = self.app.get('{}download'.format(pp.url), auth=admin.auth)
        assert res.status_code == 302
        assert '{}/v1/resources/{}/providers/{}{}?action=download&version=1&direct'.format(WATERBUTLER_URL, pp._id, pp.primary_file.provider, pp.primary_file.path) in res.location

        branded_provider.add_to_group(admin, ADMIN)
        branded_provider.save()

        res = self.app.get('{}download'.format(pp_branded.url), auth=admin.auth)
        assert res.status_code == 302
class TestPreprintProviderSubjects(ApiTestCase):
    def create_subject_rules(self):
        '''
        Subject Hierarchy
        +-----------------------------+
        |                             |
        |      +-------->B+----->F    |
        |      |                      |
        |  A+----------->C            |
        |      |                      |
        |      +-------->D+----->G    |
        |                             |
        |  H+------>I+----->J         |
        |            |                |
        |            +----->K         |
        |                             |
        |  L+------>M+----->N         |
        |            |                |
        |            +------->E       |
        |                             |
        |  O                          |
        +-----------------------------+
        '''
        self.subA = SubjectFactory(text='A')
        self.subB = SubjectFactory(text='B', parent=self.subA)
        self.subC = SubjectFactory(text='C', parent=self.subA)
        self.subD = SubjectFactory(text='D', parent=self.subA)
        self.subF = SubjectFactory(text='F', parent=self.subB)
        self.subG = SubjectFactory(text='G', parent=self.subD)
        self.subH = SubjectFactory(text='H')
        self.subI = SubjectFactory(text='I', parent=self.subH)
        self.subJ = SubjectFactory(text='J', parent=self.subI)
        self.subK = SubjectFactory(text='K', parent=self.subI)
        self.subL = SubjectFactory(text='L')
        self.subM = SubjectFactory(text='M', parent=self.subL)
        self.subE = SubjectFactory(text='E', parent=self.subM)
        self.subN = SubjectFactory(text='N', parent=self.subM)
        self.subO = SubjectFactory(text='O')
        rules = [
            ([self.subA._id, self.subB._id], False),
            ([self.subA._id, self.subD._id], True),
            ([self.subH._id, self.subI._id, self.subJ._id], True),
            ([self.subL._id], True)
        ]
        #  This should allow: A, B, D, G, H, I, J, L, M, N and E
        #  This should not allow: C, F, K, O
        return rules

    def setUp(self):
        super(TestPreprintProviderSubjects, self).setUp()
        self.lawless_preprint_provider = PreprintProviderFactory()
        self.ruled_preprint_provider = PreprintProviderFactory()
        self.ruled_preprint_provider.subjects_acceptable = self.create_subject_rules()
        self.ruled_preprint_provider.save()
        self.lawless_url = '/{}preprint_providers/{}/taxonomies/?page[size]=15&'.format(API_BASE, self.lawless_preprint_provider._id)
        self.ruled_url = '/{}preprint_providers/{}/taxonomies/?page[size]=15&'.format(API_BASE, self.ruled_preprint_provider._id)

    def test_no_rules_grabs_all(self):
        res = self.app.get(self.lawless_url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 15)

    def test_rules_only_grab_acceptable_subjects(self):
        res = self.app.get(self.ruled_url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 11)

    def test_no_rules_with_null_parent_filter(self):
        res = self.app.get(self.lawless_url + 'filter[parents]=null')

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 4)

    def test_rules_enforced_with_null_parent_filter(self):
        res = self.app.get(self.ruled_url + 'filter[parents]=null')

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 3)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('A', texts)
        assert_in('H', texts)
        assert_in('L', texts)
        assert_not_in('O', texts)

    def test_no_rules_with_parents_filter(self):
        res = self.app.get(self.lawless_url + 'filter[parents]={}'.format(self.subB._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 1)
        assert_equal(res.json['data'][0]['attributes']['text'], 'F')

        res = self.app.get(self.lawless_url + 'filter[parents]={}'.format(self.subI._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

        res = self.app.get(self.lawless_url + 'filter[parents]={}'.format(self.subM._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

    def test_rules_enforced_with_parents_filter(self):
        res = self.app.get(self.ruled_url + 'filter[parents]={}'.format(self.subB._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 0)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_not_in('F', texts)

        res = self.app.get(self.ruled_url + 'filter[parents]={}'.format(self.subI._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 1)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('J', texts)
        assert_not_in('K', texts)

        res = self.app.get(self.ruled_url + 'filter[parents]={}'.format(self.subM._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('N', texts)
        assert_in('E', texts)

    def test_no_rules_with_parent_filter(self):
        res = self.app.get(self.lawless_url + 'filter[parent]={}'.format(self.subB._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 1)
        assert_equal(res.json['data'][0]['attributes']['text'], 'F')

        res = self.app.get(self.lawless_url + 'filter[parent]={}'.format(self.subI._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

        res = self.app.get(self.lawless_url + 'filter[parent]={}'.format(self.subM._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

    def test_rules_enforced_with_parent_filter(self):
        res = self.app.get(self.ruled_url + 'filter[parent]={}'.format(self.subB._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 0)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_not_in('F', texts)

        res = self.app.get(self.ruled_url + 'filter[parent]={}'.format(self.subI._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 1)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('J', texts)
        assert_not_in('K', texts)

        res = self.app.get(self.ruled_url + 'filter[parent]={}'.format(self.subM._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('N', texts)
        assert_in('E', texts)

    def test_no_rules_with_grandparent_filter(self):
        res = self.app.get(self.lawless_url + 'filter[parents]={}'.format(self.subA._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 3)

    def test_rules_enforced_with_grandparent_filter(self):
        res = self.app.get(self.ruled_url + 'filter[parents]={}'.format(self.subA._id))

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)
        texts = [item['attributes']['text'] for item in res.json['data']]
        assert_in('B', texts)
        assert_in('D', texts)
        assert_not_in('C', texts)
示例#16
0
 def preprint_provider(self, cc0_license, no_license):
     preprint_provider = PreprintProviderFactory()
     preprint_provider.licenses_acceptable = [cc0_license, no_license]
     preprint_provider.save()
     return preprint_provider
示例#17
0
class TestPreprintCreate(ApiTestCase):
    def setUp(self):
        super(TestPreprintCreate, self).setUp()

        self.user = AuthUserFactory()
        self.other_user = AuthUserFactory()
        self.private_project = ProjectFactory(creator=self.user)
        self.public_project = ProjectFactory(creator=self.user, is_public=True)
        self.public_project.add_contributor(
            self.other_user,
            permissions=permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS,
            save=True)
        self.subject = SubjectFactory()
        self.provider = PreprintProviderFactory()

        self.user_two = AuthUserFactory()

        self.file_one_public_project = test_utils.create_test_file(
            self.public_project, self.user, 'millionsofdollars.pdf')
        self.file_one_private_project = test_utils.create_test_file(
            self.private_project, self.user, 'woowoowoo.pdf')

        self.url = '/{}preprints/'.format(API_BASE)

    def test_create_preprint_from_public_project(self):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, self.file_one_public_project._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth)

        assert_equal(res.status_code, 201)

    def test_create_preprint_from_private_project(self):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id,
            self.file_one_private_project._id,
            attrs={
                'subjects': [
                    [
                        SubjectFactory()._id]],
                'is_published': True})
        res = self.app.post_json_api(
            self.url,
            private_project_payload,
            auth=self.user.auth)

        self.private_project.reload()
        assert_equal(res.status_code, 201)
        assert_true(self.private_project.is_public)

    def test_non_authorized_user(self):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, self.file_one_public_project._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user_two.auth,
            expect_errors=True)

        assert_equal(res.status_code, 403)

    def test_read_write_user_not_admin(self):
        assert_in(self.other_user, self.public_project.contributors)
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, self.file_one_public_project._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.other_user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 403)

    def test_file_is_not_in_node(self):
        wrong_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, self.file_one_private_project._id)
        res = self.app.post_json_api(
            self.url,
            wrong_project_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_already_a_preprint_with_conflicting_provider(self):
        preprint = PreprintFactory(creator=self.user)
        file_one_preprint = test_utils.create_test_file(
            preprint.node, self.user, 'openupthatwindow.pdf')

        already_preprint_payload = build_preprint_create_payload(
            preprint.node._id, preprint.provider._id, file_one_preprint._id)
        res = self.app.post_json_api(
            self.url,
            already_preprint_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 409)
        assert_in(
            'Only one preprint per provider can be submitted for a node.',
            res.json['errors'][0]['detail'])

    def test_read_write_user_already_a_preprint_with_conflicting_provider(
            self):
        assert_in(self.other_user, self.public_project.contributors)

        preprint = PreprintFactory(creator=self.user)
        preprint.node.add_contributor(
            self.other_user,
            permissions=permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS,
            save=True)
        file_one_preprint = test_utils.create_test_file(
            preprint.node, self.user, 'openupthatwindow.pdf')

        already_preprint_payload = build_preprint_create_payload(
            preprint.node._id, self.provider._id, file_one_preprint._id)
        res = self.app.post_json_api(
            self.url,
            already_preprint_payload,
            auth=self.other_user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 403)

    def test_publish_preprint_fails_with_no_primary_file(self):
        no_file_payload = build_preprint_create_payload(
            node_id=self.public_project._id,
            provider_id=self.provider._id,
            file_id=None,
            attrs={
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            }
        )
        res = self.app.post_json_api(
            self.url,
            no_file_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'A valid primary_file must be set before publishing a preprint.')

    def test_publish_preprint_fails_with_invalid_primary_file(self):
        no_file_payload = build_preprint_create_payload(
            node_id=self.public_project._id,
            provider_id=self.provider._id,
            file_id='totallynotanid',
            attrs={
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            }
        )
        res = self.app.post_json_api(
            self.url,
            no_file_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'A valid primary_file must be set before publishing a preprint.')

    def test_no_provider_given(self):
        no_providers_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, self.file_one_public_project._id)
        del no_providers_payload['data']['relationships']['provider']
        res = self.app.post_json_api(
            self.url,
            no_providers_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'You must specify a valid provider to create a preprint.')

    def test_invalid_provider_given(self):
        wrong_provider_payload = build_preprint_create_payload(
            self.public_project._id, 'jobbers', self.file_one_public_project._id)

        res = self.app.post_json_api(
            self.url,
            wrong_provider_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'You must specify a valid provider to create a preprint.')

    def test_request_id_does_not_match_request_url_id(self):
        public_project_payload = build_preprint_create_payload(
            self.private_project._id, self.provider._id, self.file_one_public_project._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_file_not_osfstorage(self):
        github_file = self.file_one_public_project
        github_file.recast(GithubFile._typedmodels_type)
        github_file.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, github_file._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)

        assert_equal(res.status_code, 400)
        assert_equal(
            res.json['errors'][0]['detail'],
            'This file is not a valid primary file for this preprint.')

    def test_preprint_contributor_signal_not_sent_on_creation(self):
        with capture_signals() as mock_signals:
            public_project_payload = build_preprint_create_payload(
                self.public_project._id, self.provider._id, self.file_one_public_project._id)
            res = self.app.post_json_api(
                self.url, public_project_payload, auth=self.user.auth)

            assert_equal(res.status_code, 201)
            assert_not_in(
                project_signals.contributor_added,
                mock_signals.signals_sent())

    def test_create_preprint_with_deleted_node_should_fail(self):
        self.public_project.is_deleted = True
        self.public_project.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id, self.provider._id, self.file_one_public_project._id)
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'],
                     'Cannot create a preprint from a deleted node.')

    def test_create_preprint_adds_log_if_published(self):
        public_project_payload = build_preprint_create_payload(
            self.public_project._id,
            self.provider._id,
            self.file_one_public_project._id,
            {
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            }
        )
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth)
        assert_equal(res.status_code, 201)
        preprint_id = res.json['data']['id']
        preprint = PreprintService.load(preprint_id)
        log = preprint.node.logs.latest()
        assert_equal(log.action, 'preprint_initiated')
        assert_equal(log.params.get('preprint'), preprint_id)

    @mock.patch('website.preprints.tasks.on_preprint_updated.si')
    def test_create_preprint_from_project_published_hits_update(
            self, mock_on_preprint_updated):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id,
            self.file_one_private_project._id,
            attrs={
                'subjects': [
                    [
                        SubjectFactory()._id]],
                'is_published': True})
        res = self.app.post_json_api(
            self.url,
            private_project_payload,
            auth=self.user.auth)
        assert mock_on_preprint_updated.called

    @mock.patch('website.preprints.tasks.on_preprint_updated.si')
    def test_create_preprint_from_project_unpublished_does_not_hit_update(
            self, mock_on_preprint_updated):
        private_project_payload = build_preprint_create_payload(
            self.private_project._id,
            self.provider._id,
            self.file_one_private_project._id,
            attrs={
                'subjects': [
                    [
                        SubjectFactory()._id]],
                'is_published': False})
        res = self.app.post_json_api(
            self.url,
            private_project_payload,
            auth=self.user.auth)
        assert not mock_on_preprint_updated.called

    @mock.patch('website.preprints.tasks.on_preprint_updated.si')
    def test_setting_is_published_with_moderated_provider_fails(
            self, mock_on_preprint_updated):
        self.provider.reviews_workflow = 'pre-moderation'
        self.provider.save()
        public_project_payload = build_preprint_create_payload(
            self.public_project._id,
            self.provider._id,
            self.file_one_public_project._id,
            {
                'is_published': True,
                'subjects': [[SubjectFactory()._id]],
            }
        )
        res = self.app.post_json_api(
            self.url,
            public_project_payload,
            auth=self.user.auth,
            expect_errors=True)
        assert res.status_code == 409
        assert not mock_on_preprint_updated.called
示例#18
0
    def test_resolve_guid_download_file_from_emberapp_preprints_unpublished(self):
        # non-branded domains
        provider = PreprintProviderFactory(_id='sockarxiv', name='Sockarxiv', reviews_workflow='pre-moderation')

        # branded domains
        branded_provider = PreprintProviderFactory(_id='spot', name='Spotarxiv', reviews_workflow='pre-moderation')
        branded_provider.allow_submissions = False
        branded_provider.domain = 'https://www.spotarxiv.com'
        branded_provider.description = 'spots not dots'
        branded_provider.domain_redirect_enabled = True
        branded_provider.share_publish_type = 'Thesis'
        branded_provider.save()

        # test_provider_submitter_can_download_unpublished
        submitter = AuthUserFactory()
        pp = PreprintFactory(finish=True, provider=provider, is_published=False, creator=submitter)
        pp.run_submit(submitter)
        pp_branded = PreprintFactory(finish=True, provider=branded_provider, is_published=False, filename='preprint_file_two.txt', creator=submitter)
        pp_branded.run_submit(submitter)

        res = self.app.get('{}download'.format(pp.url), auth=submitter.auth)
        assert res.status_code == 302
        assert '{}/v1/resources/{}/providers/{}{}?action=download&version=1&direct'.format(WATERBUTLER_URL, pp._id, pp.primary_file.provider, pp.primary_file.path) in res.location

        res = self.app.get('{}download'.format(pp_branded.url), auth=submitter.auth)
        assert res.status_code == 302

        # test_provider_super_user_can_download_unpublished
        super_user = AuthUserFactory()
        super_user.is_superuser = True
        super_user.save()

        res = self.app.get('{}download'.format(pp.url), auth=super_user.auth)
        assert res.status_code == 302
        assert '{}/v1/resources/{}/providers/{}{}?action=download&version=1&direct'.format(WATERBUTLER_URL, pp._id, pp.primary_file.provider, pp.primary_file.path) in res.location

        res = self.app.get('{}download'.format(pp_branded.url), auth=super_user.auth)
        assert res.status_code == 302

        # test_provider_moderator_can_download_unpublished
        moderator = AuthUserFactory()
        provider.add_to_group(moderator, 'moderator')
        provider.save()

        res = self.app.get('{}download'.format(pp.url), auth=moderator.auth)
        assert res.status_code == 302
        assert '{}/v1/resources/{}/providers/{}{}?action=download&version=1&direct'.format(WATERBUTLER_URL, pp._id, pp.primary_file.provider, pp.primary_file.path) in res.location

        branded_provider.add_to_group(moderator, 'moderator')
        branded_provider.save()

        res = self.app.get('{}download'.format(pp_branded.url), auth=moderator.auth)
        assert res.status_code == 302

        # test_provider_admin_can_download_unpublished
        admin = AuthUserFactory()
        provider.add_to_group(admin, 'admin')
        provider.save()

        res = self.app.get('{}download'.format(pp.url), auth=admin.auth)
        assert res.status_code == 302
        assert '{}/v1/resources/{}/providers/{}{}?action=download&version=1&direct'.format(WATERBUTLER_URL, pp._id, pp.primary_file.provider, pp.primary_file.path) in res.location

        branded_provider.add_to_group(admin, 'admin')
        branded_provider.save()

        res = self.app.get('{}download'.format(pp_branded.url), auth=admin.auth)
        assert res.status_code == 302
class TestPreprintProviderLicenses(ApiTestCase):
    def setUp(self):
        super(TestPreprintProviderLicenses, self).setUp()
        self.provider = PreprintProviderFactory()
        self.licenses = NodeLicense.objects.all()
        self.license1 = self.licenses[0]
        self.license2 = self.licenses[1]
        self.license3 = self.licenses[2]
        self.url = '/{}preprint_providers/{}/licenses/'.format(API_BASE, self.provider._id)


    def test_preprint_provider_has_no_acceptable_licenses_and_no_default(self):
        self.provider.licenses_acceptable = []
        self.provider.default_license = None
        self.provider.save()
        res = self.app.get(self.url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], len(self.licenses))


    def test_preprint_provider_has_a_default_license_but_no_acceptable_licenses(self):
        self.provider.licenses_acceptable = []
        self.provider.default_license = self.license2
        self.provider.save()
        res = self.app.get(self.url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], len(self.licenses))

        assert_equal(self.license2._id, res.json['data'][0]['id'])

    def test_prerint_provider_has_acceptable_licenses_but_no_default(self):
        self.provider.licenses_acceptable.add(self.license1, self.license2)
        self.provider.default_license = None
        self.provider.save()
        res = self.app.get(self.url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

        license_ids = [item['id'] for item in res.json['data']]
        assert_in(self.license1._id, license_ids)
        assert_in(self.license2._id, license_ids)
        assert_not_in(self.license3._id, license_ids)


    def test_preprint_provider_has_both_acceptable_and_default_licenses(self):
        self.provider.licenses_acceptable.add(self.license1, self.license3)
        self.provider.default_license = self.license3
        self.provider.save()
        res = self.app.get(self.url)

        assert_equal(res.status_code, 200)
        assert_equal(res.json['links']['meta']['total'], 2)

        license_ids = [item['id'] for item in res.json['data']]
        assert_in(self.license1._id, license_ids)
        assert_in(self.license3._id, license_ids)
        assert_not_in(self.license2._id, license_ids)

        assert_equal(self.license3._id, license_ids[0])
class TestShareSourcePreprintProvider(AdminTestCase):
    def setUp(self):
        self.user = AuthUserFactory()
        self.user.is_superuser = True
        self.user.save()

        self.preprint_provider = PreprintProviderFactory()
        asset_file = ProviderAssetFileFactory(name='square_color_no_transparent')
        self.preprint_provider.asset_files.add(asset_file)
        self.preprint_provider.save()

        self.request = RequestFactory().get('/fake_path')
        self.view = views.ShareSourcePreprintProvider()
        self.view = setup_user_view(self.view, self.request, user=self.user, preprint_provider_id=self.preprint_provider.id)

        self.mock_prepend = mock.patch.object(website.settings, 'SHARE_PROVIDER_PREPEND', 'testenv')

    @responses.activate
    @mock.patch('api.share.utils.settings.SHARE_ENABLED', True)
    def test_update_share_token_and_source(self):
        token = 'tokennethbranagh'
        source_name = 'sir'
        responses.add(
            responses.POST, 'https://share.osf.io/api/v2/sources/',
            body=json.dumps({
                'data': {
                    'attributes': {
                        'longTitle': source_name,
                    },
                },
                'included': [{
                    'attributes': {
                        'token': token,
                    },
                    'type': 'ShareUser',
                }]
            })
        )

        self.view.get(self.request)
        self.preprint_provider.refresh_from_db()

        assert self.preprint_provider.access_token == token
        assert self.preprint_provider.share_source == source_name

    @responses.activate
    @mock.patch('api.share.utils.settings.SHARE_ENABLED', True)
    def test_update_share_token_and_source_prefix(self):
        with self.mock_prepend:
            token = 'tokennethbranagh'
            responses.add(
                responses.POST, 'https://share.osf.io/api/v2/sources/',
                body=json.dumps({
                    'data': {
                        'attributes': {
                            'homePage': self.preprint_provider.external_url,
                            'longTitle': f'testenv_{self.preprint_provider.name}',
                            'iconUrl': self.preprint_provider.get_asset_url('square_color_no_transparent')
                        }
                    },
                    'included': [{
                        'attributes': {
                            'token': token,
                        },
                        'type': 'ShareUser',
                    }]
                })
            )

            self.view.get(self.request)
            self.preprint_provider.refresh_from_db()

            request_body = json.loads(responses.calls[-1].request.body)

            assert request_body['data']['attributes']['longTitle'] == f'testenv_{self.preprint_provider.name}'
            assert self.preprint_provider.access_token == token
            assert self.preprint_provider.share_source == f'testenv_{self.preprint_provider.name}'