From 2e0531f1e2c302b7e4cc5fa2083596187643376a Mon Sep 17 00:00:00 2001 From: Longze Chen Date: Fri, 6 Sep 2024 16:13:33 -0400 Subject: [PATCH] [ENG-5966] 2.0.1 BE: Update permission to support edit as a WRITE contributor (#10741) * reorganize tests to ensure contributor permissions visible * allow read permissions for non-public contributors * fix testing issues and clean-up permissions changes * fix up author assertion permissions to be admin only * change test file name * improve tests institution relationship add affiliation addition/removal * Sync diff between #10739 and #10687 * Fix flake8 * Fix WriteOrPublicForRelationshipInstitutions for nodes * Fix incorrect `.can_edit()` call for preprints --------- Co-authored-by: John Tordoff --- api/base/permissions.py | 4 +- api/preprints/serializers.py | 124 +++--- .../preprints/views/test_preprint_detail.py | 356 ---------------- .../test_preprint_detail_author_assertions.py | 300 ++++++++++++++ ...test_preprint_institutions_relationship.py | 392 +++++++++--------- 5 files changed, 568 insertions(+), 608 deletions(-) create mode 100644 api_tests/preprints/views/test_preprint_detail_author_assertions.py diff --git a/api/base/permissions.py b/api/base/permissions.py index 60f69512ebc..50f467a8512 100644 --- a/api/base/permissions.py +++ b/api/base/permissions.py @@ -8,7 +8,7 @@ from framework.auth import oauth_scopes from framework.auth.cas import CasResponse -from osf.models import ApiOAuth2Application, ApiOAuth2PersonalToken +from osf.models import ApiOAuth2Application, ApiOAuth2PersonalToken, Preprint from osf.utils import permissions as osf_permissions from website.util.sanitize import is_iterable_but_not_string from api.base.utils import get_user_auth @@ -173,4 +173,6 @@ def has_object_permission(self, request, view, obj): if request.method in permissions.SAFE_METHODS: return resource.is_public or resource.can_view(auth) else: + if isinstance(resource, Preprint): + return resource.can_edit(auth=auth) return resource.has_permission(auth.user, osf_permissions.WRITE) diff --git a/api/preprints/serializers.py b/api/preprints/serializers.py index 3531184a33e..bdf8e0ad5e5 100644 --- a/api/preprints/serializers.py +++ b/api/preprints/serializers.py @@ -369,59 +369,7 @@ def update(self, preprint, validated_data): preprint.custom_publication_citation = validated_data['custom_publication_citation'] or None save_preprint = True - if 'has_coi' in validated_data: - try: - preprint.update_has_coi(auth, validated_data['has_coi']) - except PreprintStateError as e: - raise exceptions.ValidationError(detail=str(e)) - - if 'conflict_of_interest_statement' in validated_data: - try: - preprint.update_conflict_of_interest_statement(auth, validated_data['conflict_of_interest_statement']) - except PreprintStateError as e: - raise exceptions.ValidationError(detail=str(e)) - - if 'has_data_links' in validated_data: - try: - preprint.update_has_data_links(auth, validated_data['has_data_links']) - except PreprintStateError as e: - raise exceptions.ValidationError(detail=str(e)) - - if 'why_no_data' in validated_data: - try: - preprint.update_why_no_data(auth, validated_data['why_no_data']) - except PreprintStateError as e: - raise exceptions.ValidationError(detail=str(e)) - - if 'data_links' in validated_data: - try: - preprint.update_data_links(auth, validated_data['data_links']) - except PreprintStateError as e: - raise exceptions.ValidationError(detail=str(e)) - - if 'has_prereg_links' in validated_data: - try: - preprint.update_has_prereg_links(auth, validated_data['has_prereg_links']) - except PreprintStateError as e: - raise exceptions.ValidationError(detail=str(e)) - - if 'why_no_prereg' in validated_data: - try: - preprint.update_why_no_prereg(auth, validated_data['why_no_prereg']) - except PreprintStateError as e: - raise exceptions.ValidationError(detail=str(e)) - - if 'prereg_links' in validated_data: - try: - preprint.update_prereg_links(auth, validated_data['prereg_links']) - except PreprintStateError as e: - raise exceptions.ValidationError(detail=str(e)) - - if 'prereg_link_info' in validated_data: - try: - preprint.update_prereg_link_info(auth, validated_data['prereg_link_info']) - except PreprintStateError as e: - raise exceptions.ValidationError(detail=str(e)) + self.handle_author_assertions(preprint, validated_data, auth) if published is not None: if not preprint.primary_file: @@ -448,6 +396,76 @@ def update(self, preprint, validated_data): return preprint + def handle_author_assertions(self, preprint, validated_data, auth): + author_assertions = { + 'has_coi', + 'conflict_of_interest_statement', + 'has_data_links', + 'why_no_data', + 'data_links', + 'why_no_prereg', + 'prereg_links', + 'has_prereg_links', + 'prereg_link_info', + } + if author_assertions & validated_data.keys(): + if not preprint.is_admin_contributor(auth.user): + raise exceptions.PermissionDenied('User must be admin to add author assertions') + + if 'has_coi' in validated_data: + try: + preprint.update_has_coi(auth, validated_data['has_coi']) + except PreprintStateError as e: + raise exceptions.ValidationError(detail=str(e)) + + if 'conflict_of_interest_statement' in validated_data: + try: + preprint.update_conflict_of_interest_statement(auth, validated_data['conflict_of_interest_statement']) + except PreprintStateError as e: + raise exceptions.ValidationError(detail=str(e)) + + if 'has_data_links' in validated_data: + try: + preprint.update_has_data_links(auth, validated_data['has_data_links']) + except PreprintStateError as e: + raise exceptions.ValidationError(detail=str(e)) + + if 'why_no_data' in validated_data: + try: + preprint.update_why_no_data(auth, validated_data['why_no_data']) + except PreprintStateError as e: + raise exceptions.ValidationError(detail=str(e)) + + if 'data_links' in validated_data: + try: + preprint.update_data_links(auth, validated_data['data_links']) + except PreprintStateError as e: + raise exceptions.ValidationError(detail=str(e)) + + if 'has_prereg_links' in validated_data: + try: + preprint.update_has_prereg_links(auth, validated_data['has_prereg_links']) + except PreprintStateError as e: + raise exceptions.ValidationError(detail=str(e)) + + if 'why_no_prereg' in validated_data: + try: + preprint.update_why_no_prereg(auth, validated_data['why_no_prereg']) + except PreprintStateError as e: + raise exceptions.ValidationError(detail=str(e)) + + if 'prereg_links' in validated_data: + try: + preprint.update_prereg_links(auth, validated_data['prereg_links']) + except PreprintStateError as e: + raise exceptions.ValidationError(detail=str(e)) + + if 'prereg_link_info' in validated_data: + try: + preprint.update_prereg_link_info(auth, validated_data['prereg_link_info']) + except PreprintStateError as e: + raise exceptions.ValidationError(detail=str(e)) + def set_field(self, func, val, auth, save=False): try: func(val, auth) diff --git a/api_tests/preprints/views/test_preprint_detail.py b/api_tests/preprints/views/test_preprint_detail.py index 916274d88f7..7e3b279c406 100644 --- a/api_tests/preprints/views/test_preprint_detail.py +++ b/api_tests/preprints/views/test_preprint_detail.py @@ -18,7 +18,6 @@ from osf.models import ( NodeLicense, PreprintContributor, - PreprintLog ) from osf.utils.permissions import WRITE from osf.utils.workflows import DefaultStates @@ -836,361 +835,6 @@ def test_update_preprint_task_called_on_api_update( assert mock_on_preprint_updated.called - def test_update_has_coi(self, app, user, preprint, url): - update_payload = build_preprint_update_payload( - preprint._id, - attributes={'has_coi': True} - ) - - contrib = AuthUserFactory() - preprint.add_contributor(contrib, READ) - res = app.patch_json_api(url, update_payload, auth=contrib.auth, expect_errors=True) - assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['has_coi'] - - preprint.reload() - assert preprint.has_coi - log = preprint.logs.first() - assert log.action == PreprintLog.UPDATE_HAS_COI - assert log.params == {'preprint': preprint._id, 'user': user._id, 'value': True} - - def test_update_conflict_of_interest_statement(self, app, user, preprint, url): - update_payload = build_preprint_update_payload( - preprint._id, - attributes={'conflict_of_interest_statement': 'Owns shares in Closed Science Corporation.'} - ) - contrib = AuthUserFactory() - preprint.add_contributor(contrib, READ) - res = app.patch_json_api(url, update_payload, auth=contrib.auth, expect_errors=True) - assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - - preprint.has_coi = False - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'You do not have the ability to edit a conflict of interest while the ' \ - 'has_coi field is set to false or unanswered' - - preprint.has_coi = True - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['conflict_of_interest_statement'] ==\ - 'Owns shares in Closed Science Corporation.' - - preprint.reload() - assert preprint.conflict_of_interest_statement == 'Owns shares in Closed Science Corporation.' - log = preprint.logs.first() - assert log.action == PreprintLog.UPDATE_COI_STATEMENT - assert log.params == {'preprint': preprint._id, 'user': user._id} - - def test_update_has_data_links(self, app, user, preprint, url): - update_payload = build_preprint_update_payload(preprint._id, attributes={'has_data_links': 'available'}) - - contrib = AuthUserFactory() - preprint.add_contributor(contrib, READ) - res = app.patch_json_api(url, update_payload, auth=contrib.auth, expect_errors=True) - assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['has_data_links'] == 'available' - - preprint.reload() - assert preprint.has_data_links - log = preprint.logs.first() - assert log.action == PreprintLog.UPDATE_HAS_DATA_LINKS - assert log.params == {'value': 'available', 'user': user._id, 'preprint': preprint._id} - - def test_update_why_no_data(self, app, user, preprint, url): - update_payload = build_preprint_update_payload(preprint._id, attributes={'why_no_data': 'My dog ate it.'}) - - contrib = AuthUserFactory() - preprint.add_contributor(contrib, READ) - res = app.patch_json_api(url, update_payload, auth=contrib.auth, expect_errors=True) - assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'You cannot edit this statement while your data links availability' \ - ' is set to true or is unanswered.' - - preprint.has_data_links = 'no' - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['why_no_data'] == 'My dog ate it.' - - preprint.reload() - assert preprint.why_no_data - log = preprint.logs.first() - assert log.action == PreprintLog.UPDATE_WHY_NO_DATA - assert log.params == {'user': user._id, 'preprint': preprint._id} - - def test_update_data_links(self, app, user, preprint, url): - data_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] - update_payload = build_preprint_update_payload(preprint._id, attributes={'data_links': data_links}) - - contrib = AuthUserFactory() - preprint.add_contributor(contrib, READ) - res = app.patch_json_api(url, update_payload, auth=contrib.auth, expect_errors=True) - assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - - preprint.has_data_links = 'no' - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'You cannot edit this statement while your data links availability' \ - ' is set to false or is unanswered.' - - preprint.has_data_links = 'available' - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['data_links'] == data_links - - preprint.reload() - assert preprint.data_links == data_links - log = preprint.logs.first() - assert log.action == PreprintLog.UPDATE_DATA_LINKS - assert log.params == {'user': user._id, 'preprint': preprint._id} - - update_payload = build_preprint_update_payload(preprint._id, attributes={'data_links': 'maformed payload'}) - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'Expected a list of items but got type "str".' - - def test_invalid_data_links(self, app, user, preprint, url): - preprint.has_data_links = 'available' - preprint.save() - - update_payload = build_preprint_update_payload(preprint._id, attributes={'data_links': ['thisaintright']}) - - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'Enter a valid URL.' - - def test_update_has_prereg_links(self, app, user, preprint, url): - update_payload = build_preprint_update_payload(preprint._id, attributes={'has_prereg_links': 'available'}) - - contrib = AuthUserFactory() - preprint.add_contributor(contrib, READ) - res = app.patch_json_api(url, update_payload, auth=contrib.auth, expect_errors=True) - assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['has_prereg_links'] == 'available' - - preprint.reload() - assert preprint.has_prereg_links - log = preprint.logs.first() - assert log.action == PreprintLog.UPDATE_HAS_PREREG_LINKS - assert log.params == {'value': 'available', 'user': user._id, 'preprint': preprint._id} - - def test_invalid_prereg_links(self, app, user, preprint, url): - preprint.has_prereg_links = 'available' - preprint.save() - - update_payload = build_preprint_update_payload(preprint._id, attributes={'prereg_links': ['thisaintright']}) - - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'Enter a valid URL.' - - def test_no_data_links_clears_links(self, app, user, preprint, url): - preprint.has_data_links = 'available' - preprint.data_links = ['http://www.apple.com'] - preprint.save() - - update_payload = build_preprint_update_payload(preprint._id, attributes={'has_data_links': 'no'}) - - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['has_data_links'] == 'no' - assert res.json['data']['attributes']['data_links'] == [] - - def test_no_prereg_links_clears_links(self, app, user, preprint, url): - preprint.has_prereg_links = 'available' - preprint.prereg_links = ['http://example.com'] - preprint.prereg_link_info = 'prereg_analysis' - preprint.save() - - update_payload = build_preprint_update_payload(preprint._id, attributes={'has_prereg_links': 'no'}) - - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['has_prereg_links'] == 'no' - assert res.json['data']['attributes']['prereg_links'] == [] - assert not res.json['data']['attributes']['prereg_link_info'] - - def test_update_why_no_prereg(self, app, user, preprint, url): - update_payload = build_preprint_update_payload(preprint._id, attributes={'why_no_prereg': 'My dog ate it.'}) - - contrib = AuthUserFactory() - preprint.add_contributor(contrib, READ) - res = app.patch_json_api(url, update_payload, auth=contrib.auth, expect_errors=True) - assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'You cannot edit this statement while your prereg links availability' \ - ' is set to true or is unanswered.' - - preprint.has_prereg_links = False - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['why_no_prereg'] == 'My dog ate it.' - - preprint.reload() - assert preprint.why_no_prereg - log = preprint.logs.first() - assert log.action == PreprintLog.UPDATE_WHY_NO_PREREG - assert log.params == {'user': user._id, 'preprint': preprint._id} - - def test_update_prereg_links(self, app, user, preprint, url): - - prereg_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] - update_payload = build_preprint_update_payload(preprint._id, attributes={'prereg_links': prereg_links}) - - contrib = AuthUserFactory() - preprint.add_contributor(contrib, READ) - res = app.patch_json_api(url, update_payload, auth=contrib.auth, expect_errors=True) - assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - - preprint.has_prereg_links = 'no' - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'You cannot edit this field while your prereg links availability' \ - ' is set to false or is unanswered.' - - preprint.has_prereg_links = 'available' - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['prereg_links'] == prereg_links - - preprint.reload() - assert preprint.prereg_links == prereg_links - log = preprint.logs.first() - assert log.action == PreprintLog.UPDATE_PREREG_LINKS - assert log.params == {'user': user._id, 'preprint': preprint._id} - - update_payload = build_preprint_update_payload(preprint._id, attributes={'prereg_links': 'maformed payload'}) - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'Expected a list of items but got type "str".' - - def test_update_prereg_link_info(self, app, user, preprint, url): - update_payload = build_preprint_update_payload( - preprint._id, - attributes={'prereg_link_info': 'prereg_designs'} - ) - - preprint.has_prereg_links = 'no' - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == 'You cannot edit this field while your prereg links availability' \ - ' is set to false or is unanswered.' - - preprint.has_prereg_links = 'available' - preprint.save() - res = app.patch_json_api(url, update_payload, auth=user.auth) - - assert res.status_code == 200 - assert res.json['data']['attributes']['prereg_link_info'] == 'prereg_designs' - - preprint.reload() - assert preprint.prereg_link_info == 'prereg_designs' - log = preprint.logs.first() - assert log.action == PreprintLog.UPDATE_PREREG_LINKS_INFO - assert log.params == {'user': user._id, 'preprint': preprint._id} - - update_payload = build_preprint_update_payload( - preprint._id, - attributes={'prereg_link_info': 'maformed payload'} - ) - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == '"maformed payload" is not a valid choice.' - - def test_sloan_updates(self, app, user, preprint, url): - """ - - Tests to ensure updating a preprint with unchanged data does not create superfluous log statements. - - Tests to ensure various dependent fields can be updated in a single request. - """ - preprint.has_prereg_links = 'available' - preprint.prereg_links = ['http://no-sf.io'] - preprint.prereg_link_info = 'prereg_designs' - preprint.save() - - update_payload = build_preprint_update_payload( - preprint._id, - attributes={ - 'has_prereg_links': 'available', - 'prereg_link_info': 'prereg_designs', - 'prereg_links': ['http://osf.io'], # changing here should be only non-factory created log. - } - ) - app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - # Any superfluous log statements? - logs = preprint.logs.all().values_list('action', 'params') - assert logs.count() == 3 # actions should be: 'subjects_updated', 'published', 'prereg_links_updated' - assert logs.latest() == ('prereg_links_updated', {'user': user._id, 'preprint': preprint._id}) - - # Can we set `has_prereg_links` to false and update `why_no_prereg` in a single request? - update_payload = build_preprint_update_payload( - preprint._id, - attributes={ - 'has_prereg_links': 'no', - 'why_no_prereg': 'My dog ate it.' - } - ) - res = app.patch_json_api(url, update_payload, auth=user.auth, expect_errors=True) - - assert res.status_code == 200 - assert res.json['data']['attributes']['has_prereg_links'] == 'no' - assert res.json['data']['attributes']['why_no_prereg'] == 'My dog ate it.' - - preprint.refresh_from_db() - assert preprint.has_prereg_links == 'no' - assert preprint.why_no_prereg == 'My dog ate it.' - @pytest.mark.django_db class TestPreprintUpdateSubjects(UpdateSubjectsMixin): diff --git a/api_tests/preprints/views/test_preprint_detail_author_assertions.py b/api_tests/preprints/views/test_preprint_detail_author_assertions.py new file mode 100644 index 00000000000..63dc8696d41 --- /dev/null +++ b/api_tests/preprints/views/test_preprint_detail_author_assertions.py @@ -0,0 +1,300 @@ +import pytest + +from osf.utils.permissions import READ, WRITE, ADMIN +from api.base.settings.defaults import API_BASE +from osf.models import PreprintLog +from osf_tests.factories import PreprintFactory, AuthUserFactory + + +def build_preprint_update_payload( + node_id, attributes=None, relationships=None, + jsonapi_type='preprints'): + payload = { + 'data': { + 'id': node_id, + 'type': jsonapi_type, + 'attributes': attributes, + 'relationships': relationships + } + } + return payload + + +@pytest.mark.django_db +@pytest.mark.enable_enqueue_task +class TestPreprintUpdateWithAuthorAssertion: + + @pytest.fixture() + def user(self): + return AuthUserFactory() + + @pytest.fixture() + def preprint(self, user): + """ + Creator is not admin permission + """ + preprint = PreprintFactory(creator=user) + admin = AuthUserFactory() + preprint.add_contributor(admin, ADMIN) + preprint.add_contributor(user, READ) + return preprint + + @pytest.fixture() + def url(self, preprint): + return f'/{API_BASE}preprints/{preprint._id}/' + + @pytest.fixture() + def read_contrib(self, preprint): + contrib = AuthUserFactory() + preprint.add_contributor(contrib, READ) + return contrib + + @pytest.fixture() + def write_contrib(self, preprint): + contrib = AuthUserFactory() + preprint.add_contributor(contrib, WRITE) + return contrib + + @pytest.fixture() + def admin_contrib(self, preprint): + contrib = AuthUserFactory() + preprint.add_contributor(contrib, ADMIN) + return contrib + + def assert_permission(self, app, url, contrib, attributes, expected_status): + update_payload = build_preprint_update_payload(node_id=contrib._id, attributes=attributes) + res = app.patch_json_api(url, update_payload, auth=contrib.auth, expect_errors=True) + assert res.status_code == expected_status + + # Testing permissions for updating has_coi + def test_update_has_coi_permission_denied(self, app, read_contrib, url): + self.assert_permission(app, url, read_contrib, {'has_coi': True}, 403) + + def test_update_has_coi_permission_granted_write(self, app, write_contrib, url): + self.assert_permission(app, url, write_contrib, {'has_coi': True}, 403) + + def test_update_has_coi_permission_granted_admin(self, app, admin_contrib, url): + self.assert_permission(app, url, admin_contrib, {'has_coi': True}, 200) + + def test_update_has_coi_permission_granted_creator(self, app, user, url): + self.assert_permission(app, url, user, {'has_coi': True}, 403) + + # Testing permissions for updating conflict_of_interest_statement + def test_update_conflict_of_interest_statement_permission_denied(self, app, read_contrib, url): + self.assert_permission(app, url, read_contrib, {'conflict_of_interest_statement': 'Test'}, 403) + + def test_update_conflict_of_interest_statement_permission_granted_write(self, app, write_contrib, preprint, url): + preprint.has_coi = True + preprint.save() + self.assert_permission(app, url, write_contrib, {'conflict_of_interest_statement': 'Test'}, 403) + + def test_update_conflict_of_interest_statement_permission_granted_admin(self, app, admin_contrib, preprint, url): + preprint.has_coi = True + preprint.save() + self.assert_permission(app, url, admin_contrib, {'conflict_of_interest_statement': 'Test'}, 200) + + def test_update_conflict_of_interest_statement_permission_granted_creator(self, app, user, preprint, url): + preprint.has_coi = True + preprint.save() + self.assert_permission(app, url, user, {'conflict_of_interest_statement': 'Test'}, 403) + + # Testing permissions for updating has_data_links + def test_update_has_data_links_permission_denied(self, app, read_contrib, url): + self.assert_permission(app, url, read_contrib, {'has_data_links': 'available'}, 403) + + def test_update_has_data_links_permission_granted_write(self, app, write_contrib, url): + self.assert_permission(app, url, write_contrib, {'has_data_links': 'available'}, 403) + + def test_update_has_data_links_permission_granted_admin(self, app, admin_contrib, url): + self.assert_permission(app, url, admin_contrib, {'has_data_links': 'available'}, 200) + + def test_update_has_data_links_permission_granted_creator(self, app, user, url): + self.assert_permission(app, url, user, {'has_data_links': 'available'}, 403) + + # Testing permissions for updating why_no_data + def test_update_why_no_data_permission_denied(self, app, read_contrib, url): + self.assert_permission(app, url, read_contrib, {'why_no_data': 'My dog ate it.'}, 403) + + def test_update_why_no_data_permission_granted_write(self, app, write_contrib, preprint, url): + preprint.has_data_links = 'no' + preprint.save() + self.assert_permission(app, url, write_contrib, {'why_no_data': 'My dog ate it.'}, 403) + + def test_update_why_no_data_permission_granted_admin(self, app, admin_contrib, preprint, url): + preprint.has_data_links = 'no' + preprint.save() + self.assert_permission(app, url, admin_contrib, {'why_no_data': 'My dog ate it.'}, 200) + + def test_update_why_no_data_permission_granted_creator(self, app, user, preprint, url): + preprint.has_data_links = 'no' + preprint.save() + self.assert_permission(app, url, user, {'why_no_data': 'My dog ate it.'}, 403) + + # Testing permissions for updating data_links + def test_update_data_links_permission_denied(self, app, read_contrib, url): + data_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] + self.assert_permission(app, url, read_contrib, {'data_links': data_links}, 403) + + def test_update_data_links_permission_granted_write(self, app, write_contrib, preprint, url): + data_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] + preprint.has_data_links = 'available' + preprint.save() + self.assert_permission(app, url, write_contrib, {'data_links': data_links}, 403) + + def test_update_data_links_permission_granted_admin(self, app, admin_contrib, preprint, url): + data_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] + preprint.has_data_links = 'available' + preprint.save() + self.assert_permission(app, url, admin_contrib, {'data_links': data_links}, 200) + + def test_update_data_links_permission_granted_creator(self, app, user, preprint, url): + data_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] + preprint.has_data_links = 'available' + preprint.save() + self.assert_permission(app, url, user, {'data_links': data_links}, 403) + + def test_update_data_links_invalid_payload(self, app, admin_contrib, url): + update_payload = build_preprint_update_payload(node_id=admin_contrib._id, attributes={'data_links': 'maformed payload'}) + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Expected a list of items but got type "str".' + + def test_update_data_links_invalid_url(self, app, admin_contrib, preprint, url): + preprint.has_data_links = 'available' + preprint.save() + update_payload = build_preprint_update_payload(node_id=admin_contrib._id, attributes={'data_links': ['thisaintright']}) + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Enter a valid URL.' + + # Testing permissions for updating has_prereg_links + def test_update_has_prereg_links_permission_denied(self, app, read_contrib, url): + self.assert_permission(app, url, read_contrib, {'has_prereg_links': 'available'}, 403) + + def test_update_has_prereg_links_permission_granted_write(self, app, write_contrib, url): + self.assert_permission(app, url, write_contrib, {'has_prereg_links': 'available'}, 403) + + def test_update_has_prereg_links_permission_granted_admin(self, app, admin_contrib, url): + self.assert_permission(app, url, admin_contrib, {'has_prereg_links': 'available'}, 200) + + def test_update_has_prereg_links_permission_granted_creator(self, app, user, url): + self.assert_permission(app, url, user, {'has_prereg_links': 'available'}, 403) + + # Testing permissions for updating prereg_links + def test_update_prereg_links_permission_denied(self, app, read_contrib, url): + prereg_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] + self.assert_permission(app, url, read_contrib, {'prereg_links': prereg_links}, 403) + + def test_update_prereg_links_permission_granted_write(self, app, write_contrib, preprint, url): + prereg_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] + preprint.has_prereg_links = 'available' + preprint.save() + self.assert_permission(app, url, write_contrib, {'prereg_links': prereg_links}, 403) + + def test_update_prereg_links_permission_granted_admin(self, app, admin_contrib, preprint, url): + prereg_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] + preprint.has_prereg_links = 'available' + preprint.save() + self.assert_permission(app, url, admin_contrib, {'prereg_links': prereg_links}, 200) + + def test_update_prereg_links_permission_granted_creator(self, app, user, preprint, url): + prereg_links = ['http://www.JasonKelce.com', 'http://www.ItsTheWholeTeam.com/'] + preprint.has_prereg_links = 'available' + preprint.save() + self.assert_permission(app, url, user, {'prereg_links': prereg_links}, 403) + + def test_update_prereg_links_invalid_payload(self, app, admin_contrib, url): + update_payload = build_preprint_update_payload(node_id=admin_contrib._id, attributes={'prereg_links': 'maformed payload'}) + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Expected a list of items but got type "str".' + + def test_update_prereg_links_invalid_url(self, app, admin_contrib, preprint, url): + preprint.has_prereg_links = 'available' + preprint.save() + update_payload = build_preprint_update_payload(node_id=admin_contrib._id, attributes={'prereg_links': ['thisaintright']}) + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Enter a valid URL.' + + def test_update_prereg_link_info_fail_prereg_links(self, app, admin_contrib, preprint, url): + update_payload = build_preprint_update_payload(node_id=admin_contrib._id, attributes={'prereg_link_info': 'prereg_designs'}) + preprint.has_prereg_links = 'no' + preprint.save() + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'You cannot edit this field while your prereg links availability is set to false or is unanswered.' + + def test_update_prereg_link_info_success(self, app, admin_contrib, preprint, url): + update_payload = build_preprint_update_payload(node_id=admin_contrib._id, attributes={'prereg_link_info': 'prereg_designs'}) + preprint.has_prereg_links = 'available' + preprint.save() + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['prereg_link_info'] == 'prereg_designs' + preprint.reload() + assert preprint.prereg_link_info == 'prereg_designs' + log = preprint.logs.first() + assert log.action == PreprintLog.UPDATE_PREREG_LINKS_INFO + assert log.params == {'user': admin_contrib._id, 'preprint': preprint._id} + + def test_update_prereg_link_info_invalid_payload(self, app, admin_contrib, url): + update_payload = build_preprint_update_payload(node_id=admin_contrib._id, attributes={'prereg_link_info': 'maformed payload'}) + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == '"maformed payload" is not a valid choice.' + + def test_no_prereg_links_clears_links(self, app, admin_contrib, preprint, url): + preprint.has_prereg_links = 'available' + preprint.prereg_links = ['http://example.com'] + preprint.prereg_link_info = 'prereg_analysis' + preprint.save() + update_payload = build_preprint_update_payload(node_id=admin_contrib._id, attributes={'has_prereg_links': 'no'}) + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['has_prereg_links'] == 'no' + assert res.json['data']['attributes']['prereg_links'] == [] + assert not res.json['data']['attributes']['prereg_link_info'] + + def test_no_data_links_clears_links(self, app, admin_contrib, preprint, url): + preprint.has_data_links = 'available' + preprint.data_links = ['http://www.apple.com'] + preprint.save() + update_payload = build_preprint_update_payload(node_id=admin_contrib._id, attributes={'has_data_links': 'no'}) + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['has_data_links'] == 'no' + assert res.json['data']['attributes']['data_links'] == [] + + def test_sloan_updates(self, app, admin_contrib, preprint, url): + preprint.has_prereg_links = 'available' + preprint.prereg_links = ['http://no-sf.io'] + preprint.prereg_link_info = 'prereg_designs' + preprint.save() + update_payload = build_preprint_update_payload( + node_id=preprint._id, + attributes={ + 'has_prereg_links': 'available', + 'prereg_link_info': 'prereg_designs', + 'prereg_links': ['http://osf.io'], + } + ) + app.patch_json_api(url, update_payload, auth=admin_contrib.auth, expect_errors=True) + logs = preprint.logs.all().values_list('action', 'params') + assert logs.count() == 5 + assert logs.latest() == ('prereg_links_updated', {'user': admin_contrib._id, 'preprint': preprint._id}) + + update_payload = build_preprint_update_payload( + node_id=preprint._id, + attributes={ + 'has_prereg_links': 'no', + 'why_no_prereg': 'My dog ate it.' + } + ) + res = app.patch_json_api(url, update_payload, auth=admin_contrib.auth, expect_errors=True) + assert res.status_code == 200 + assert res.json['data']['attributes']['has_prereg_links'] == 'no' + assert res.json['data']['attributes']['why_no_prereg'] == 'My dog ate it.' + preprint.refresh_from_db() + assert preprint.has_prereg_links == 'no' + assert preprint.why_no_prereg == 'My dog ate it.' diff --git a/api_tests/preprints/views/test_preprint_institutions_relationship.py b/api_tests/preprints/views/test_preprint_institutions_relationship.py index d8ef0d7e1b3..cd00750c0eb 100644 --- a/api_tests/preprints/views/test_preprint_institutions_relationship.py +++ b/api_tests/preprints/views/test_preprint_institutions_relationship.py @@ -1,11 +1,7 @@ import pytest - from api.base.settings.defaults import API_BASE -from osf_tests.factories import ( - PreprintFactory, - AuthUserFactory, - InstitutionFactory, -) +from osf_tests.factories import PreprintFactory, AuthUserFactory, InstitutionFactory +from osf.utils.permissions import READ, WRITE, ADMIN @pytest.mark.django_db @@ -17,33 +13,73 @@ def user(self): return AuthUserFactory() @pytest.fixture() - def admin_with_institutional_affilation(self, institution, preprint): + def institution_A(self): + return InstitutionFactory() + + @pytest.fixture() + def institution_B(self): + return InstitutionFactory() + + @pytest.fixture() + def institution_C(self): + return InstitutionFactory() + + @pytest.fixture() + def institution_D(self): + return InstitutionFactory() + + @pytest.fixture() + def institution_E(self): + return InstitutionFactory() + + @pytest.fixture() + def institution_F(self): + return InstitutionFactory() + + @pytest.fixture() + def admin_with_institutional_affiliation(self, institution_A, institution_B, institution_C, preprint): user = AuthUserFactory() - preprint.add_permission(user, 'admin') - user.add_or_update_affiliated_institution(institution) + preprint.add_contributor(user, permissions=ADMIN) + user.add_or_update_affiliated_institution(institution_A) + user.add_or_update_affiliated_institution(institution_B) + user.add_or_update_affiliated_institution(institution_C) + return user + + @pytest.fixture() + def write_user_with_institutional_affiliation(self, institution_B, institution_C, institution_D, preprint): + user = AuthUserFactory() + preprint.add_contributor(user, permissions=WRITE) + user.add_or_update_affiliated_institution(institution_B) + user.add_or_update_affiliated_institution(institution_C) + user.add_or_update_affiliated_institution(institution_D) + return user + + @pytest.fixture() + def read_user_with_institutional_affiliation(self, institution_C, institution_D, institution_F, preprint): + user = AuthUserFactory() + preprint.add_contributor(user, permissions=READ) + user.add_or_update_affiliated_institution(institution_C) + user.add_or_update_affiliated_institution(institution_D) + user.add_or_update_affiliated_institution(institution_F) return user @pytest.fixture() - def no_auth_with_institutional_affilation(self, institution): + def no_auth_with_institutional_affiliation(self, institution): user = AuthUserFactory() user.add_or_update_affiliated_institution(institution) user.save() return user @pytest.fixture() - def admin_without_institutional_affilation(self, institution, preprint): + def admin_without_institutional_affiliation(self, preprint): user = AuthUserFactory() - preprint.add_permission(user, 'admin') + preprint.add_contributor(user, permissions=ADMIN) return user @pytest.fixture() def institutions(self): return [InstitutionFactory() for _ in range(3)] - @pytest.fixture() - def institution(self): - return InstitutionFactory() - @pytest.fixture() def preprint(self): return PreprintFactory() @@ -53,256 +89,216 @@ def url(self, preprint): """Fixture that returns the URL for the preprint-institutions relationship endpoint.""" return f'/{API_BASE}preprints/{preprint._id}/relationships/institutions/' - def test_update_affiliated_institutions_add(self, app, user, admin_with_institutional_affilation, admin_without_institutional_affilation, preprint, url, - institution): + def test_update_affiliated_institutions_add_unauthorized_user(self, app, user, url, institution_A): """ - Test adding affiliated institutions to a preprint. - - Verifies: - - Unauthorized users cannot add institutions. - - Admins without affiliation cannot add institutions. - - Admins with affiliation can add institutions. + Test that unauthorized users cannot add institutions. """ - update_institutions_payload = { - 'data': [{'type': 'institutions', 'id': institution._id}] - } + update_institutions_payload = {'data': [{'type': 'institutions', 'id': institution_A._id}]} + res = app.put_json_api(url, update_institutions_payload, auth=user.auth, expect_errors=True) + assert res.status_code == 403 - res = app.put_json_api( - url, - update_institutions_payload, - auth=user.auth, - expect_errors=True - ) + def test_update_affiliated_institutions_add_read_user(self, app, read_user_with_institutional_affiliation, url, institution_A): + """ + Test that read users cannot add institutions. + """ + update_institutions_payload = {'data': [{'type': 'institutions', 'id': institution_A._id}]} + res = app.put_json_api(url, update_institutions_payload, auth=read_user_with_institutional_affiliation.auth, expect_errors=True) assert res.status_code == 403 - res = app.put_json_api( - url, - update_institutions_payload, - auth=admin_without_institutional_affilation.auth, - expect_errors=True - ) + def test_update_affiliated_institutions_add_write_user(self, app, write_user_with_institutional_affiliation, url, institution_A, institution_B): + """ + Test that write users cannot add institutions. + """ + update_institutions_payload = {'data': [{'type': 'institutions', 'id': institution_A._id}]} + res = app.put_json_api(url, update_institutions_payload, auth=write_user_with_institutional_affiliation.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == f'User needs to be affiliated with {institution.name}' - res = app.put_json_api( - url, - update_institutions_payload, - auth=admin_with_institutional_affilation.auth - ) + update_institutions_payload = {'data': [{'type': 'institutions', 'id': institution_B._id}]} + res = app.put_json_api(url, update_institutions_payload, auth=write_user_with_institutional_affiliation.auth) assert res.status_code == 200 + def test_update_affiliated_institutions_add_admin_without_affiliation(self, app, admin_without_institutional_affiliation, url, institution_A): + """ + Test that admins without affiliation cannot add institutions. + """ + update_institutions_payload = {'data': [{'type': 'institutions', 'id': institution_A._id}]} + res = app.put_json_api(url, update_institutions_payload, auth=admin_without_institutional_affiliation.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == f'User needs to be affiliated with {institution_A.name}' + + def test_update_affiliated_institutions_add_admin_with_affiliation(self, app, admin_with_institutional_affiliation, preprint, url, institution_A): + """ + Test that admins with affiliation can add institutions. + """ + update_institutions_payload = {'data': [{'type': 'institutions', 'id': institution_A._id}]} + res = app.put_json_api(url, update_institutions_payload, auth=admin_with_institutional_affiliation.auth) + assert res.status_code == 200 preprint.reload() - assert institution in preprint.affiliated_institutions.all() + assert institution_A in preprint.affiliated_institutions.all() log = preprint.logs.latest() assert log.action == 'affiliated_institution_added' - assert log.params['institution'] == { - 'id': institution._id, - 'name': institution.name - } + assert log.params['institution'] == {'id': institution_A._id, 'name': institution_A.name} - def test_update_affiliated_institutions_remove(self, app, user, admin_with_institutional_affilation, no_auth_with_institutional_affilation, admin_without_institutional_affilation, preprint, url, - institution): + def test_update_affiliated_institutions_remove_unauthorized_user(self, app, user, preprint, url, institution_A): """ - Test removing affiliated institutions from a preprint. - - Verifies: - - Unauthorized users cannot remove institutions. - - Non-admin users cannot remove institutions. - - Admins without affiliation can remove institutions. - - Admins with affiliation can remove institutions. + Test that unauthorized users cannot remove institutions. """ - preprint.affiliated_institutions.add(institution) + preprint.affiliated_institutions.add(institution_A) preprint.save() - - update_institutions_payload = { - 'data': [] - } - - res = app.put_json_api( - url, - update_institutions_payload, - auth=user.auth, - expect_errors=True - ) + update_institutions_payload = {'data': []} + res = app.put_json_api(url, update_institutions_payload, auth=user.auth, expect_errors=True) assert res.status_code == 403 - res = app.put_json_api( - url, - update_institutions_payload, - auth=no_auth_with_institutional_affilation.auth, - expect_errors=True - ) + def test_update_affiliated_institutions_remove_read_user(self, app, read_user_with_institutional_affiliation, preprint, url, institution_A): + """ + Test that read users cannot remove institutions. + """ + preprint.affiliated_institutions.add(institution_A) + preprint.save() + update_institutions_payload = {'data': []} + res = app.put_json_api(url, update_institutions_payload, auth=read_user_with_institutional_affiliation.auth, expect_errors=True) assert res.status_code == 403 - res = app.put_json_api( - url, - update_institutions_payload, - auth=admin_without_institutional_affilation.auth, - expect_errors=True - ) - assert res.status_code == 200 # you can always remove it you are an admin - - res = app.put_json_api( - url, - update_institutions_payload, - auth=admin_with_institutional_affilation.auth - ) + def test_update_affiliated_institutions_remove_write_user(self, app, write_user_with_institutional_affiliation, preprint, url, institution_A): + """ + Test that write users cannot remove institutions. + """ + preprint.affiliated_institutions.add(institution_A) + preprint.save() + update_institutions_payload = {'data': []} + res = app.put_json_api(url, update_institutions_payload, auth=write_user_with_institutional_affiliation.auth, expect_errors=True) assert res.status_code == 200 + def test_update_affiliated_institutions_remove_admin_without_affiliation(self, app, admin_without_institutional_affiliation, preprint, url, institution_A): + """ + Test that admins without affiliation can remove institutions. + """ + preprint.affiliated_institutions.add(institution_A) + preprint.save() + update_institutions_payload = {'data': []} + res = app.put_json_api(url, update_institutions_payload, auth=admin_without_institutional_affiliation.auth) + assert res.status_code == 200 + + def test_update_affiliated_institutions_remove_admin_with_affiliation(self, app, admin_with_institutional_affiliation, preprint, url, institution_A): + """ + Test that admins with affiliation can remove institutions. + """ + preprint.affiliated_institutions.add(institution_A) + preprint.save() + update_institutions_payload = {'data': []} + res = app.put_json_api(url, update_institutions_payload, auth=admin_with_institutional_affiliation.auth) + assert res.status_code == 200 preprint.reload() - assert institution not in preprint.affiliated_institutions.all() + assert institution_A not in preprint.affiliated_institutions.all() log = preprint.logs.latest() assert log.action == 'affiliated_institution_removed' - assert log.params['institution'] == { - 'id': institution._id, - 'name': institution.name - } + assert log.params['institution'] == {'id': institution_A._id, 'name': institution_A.name} - def test_preprint_institutions_list_get(self, app, user, admin_with_institutional_affilation, admin_without_institutional_affilation, preprint, url, - institution): + def test_preprint_institutions_list_get_unauthenticated(self, app, url): """ - Test retrieving the list of affiliated institutions for a preprint. - - Verifies: - - Unauthenticated users cannot retrieve the list. - - Users without permissions cannot retrieve the list. - - Admins without affiliation can retrieve the list. - - Admins with affiliation can retrieve the list. + Test that unauthenticated users cannot retrieve the list of affiliated institutions for a preprint. """ - preprint.is_public = False - preprint.save() - res = app.get(url, expect_errors=True) - assert res.status_code == 401 + assert res.status_code == 200 + def test_preprint_institutions_list_get_no_permissions(self, app, user, url): + """ + Test that users without permissions cannot retrieve the list of affiliated institutions for a preprint. + """ res = app.get(url, auth=user.auth, expect_errors=True) - assert res.status_code == 403 + assert res.status_code == 200 - res = app.get(url, auth=admin_without_institutional_affilation.auth, expect_errors=True) + def test_preprint_institutions_list_get_read_user(self, app, read_user_with_institutional_affiliation, preprint, url): + """ + Test that read users can retrieve the list of affiliated institutions for a preprint. + """ + preprint.is_public = False + preprint.save() + res = app.get(url, auth=read_user_with_institutional_affiliation.auth) assert res.status_code == 200 + assert not res.json['data'] + def test_preprint_institutions_list_get_write_user(self, app, write_user_with_institutional_affiliation, preprint, url): + """ + Test that write users can retrieve the list of affiliated institutions for a preprint. + """ + preprint.is_public = False + preprint.save() + res = app.get(url, auth=write_user_with_institutional_affiliation.auth) assert res.status_code == 200 assert not res.json['data'] - preprint.add_affiliated_institution(institution, admin_with_institutional_affilation) - res = app.get(url, auth=admin_with_institutional_affilation.auth) + def test_preprint_institutions_list_get_admin_without_affiliation(self, app, admin_without_institutional_affiliation, preprint, url): + """ + Test that admins without affiliation can retrieve the list of affiliated institutions for a preprint. + """ + preprint.is_public = False + preprint.save() + res = app.get(url, auth=admin_without_institutional_affiliation.auth) assert res.status_code == 200 + assert not res.json['data'] - assert res.json['data'][0]['id'] == institution._id + def test_preprint_institutions_list_get_admin_with_affiliation(self, app, admin_with_institutional_affiliation, preprint, url, institution_A): + """ + Test that admins with affiliation can retrieve the list of affiliated institutions for a preprint. + """ + preprint.add_affiliated_institution(institution_A, admin_with_institutional_affiliation) + res = app.get(url, auth=admin_with_institutional_affiliation.auth) + assert res.status_code == 200 + assert res.json['data'][0]['id'] == institution_A._id assert res.json['data'][0]['type'] == 'institutions' - def test_post_affiliated_institutions(self, app, user, admin_with_institutional_affilation, preprint, url, - institutions, institution): + def test_post_affiliated_institutions(self, app, admin_with_institutional_affiliation, url, institutions): """ Test that POST method is not allowed for affiliated institutions. - - Verifies: - - POST requests return a 405 Method Not Allowed status. """ - add_institutions_payload = { - 'data': [{'type': 'institutions', 'id': institution._id} for institution in institutions] - } - - res = app.post_json_api( - url, - add_institutions_payload, - auth=admin_with_institutional_affilation.auth, - expect_errors=True - ) + add_institutions_payload = {'data': [{'type': 'institutions', 'id': institution._id} for institution in institutions]} + res = app.post_json_api(url, add_institutions_payload, auth=admin_with_institutional_affiliation.auth, expect_errors=True) assert res.status_code == 405 - def test_patch_affiliated_institutions(self, app, user, admin_with_institutional_affilation, preprint, url, - institutions, institution): + def test_patch_affiliated_institutions(self, app, admin_with_institutional_affiliation, url, institutions): """ Test that PATCH method is not allowed for affiliated institutions. - - Verifies: - - PATCH requests return a 405 Method Not Allowed status. """ - add_institutions_payload = { - 'data': [{'type': 'institutions', 'id': institution._id} for institution in institutions] - } - - res = app.patch_json_api( - url, - add_institutions_payload, - auth=admin_with_institutional_affilation.auth, - expect_errors=True - ) + add_institutions_payload = {'data': [{'type': 'institutions', 'id': institution._id} for institution in institutions]} + res = app.patch_json_api(url, add_institutions_payload, auth=admin_with_institutional_affiliation.auth, expect_errors=True) assert res.status_code == 405 - def test_delete_affiliated_institution(self, app, user, admin_with_institutional_affilation, admin_without_institutional_affilation, preprint, url, - institution): + def test_delete_affiliated_institution(self, app, admin_with_institutional_affiliation, preprint, url, institution_A): """ Test that DELETE method is not allowed for affiliated institutions. - - Verifies: - - DELETE requests return a 405 Method Not Allowed status. """ - preprint.affiliated_institutions.add(institution) + preprint.affiliated_institutions.add(institution_A) preprint.save() - - res = app.delete_json_api( - url, - {'data': [{'type': 'institutions', 'id': institution._id}]}, - auth=admin_with_institutional_affilation.auth, - expect_errors=True - ) + res = app.delete_json_api(url, {'data': [{'type': 'institutions', 'id': institution_A._id}]}, auth=admin_with_institutional_affiliation.auth, expect_errors=True) assert res.status_code == 405 - def test_add_multiple_institutions_affiliations(self, app, admin_with_institutional_affilation, admin_without_institutional_affilation, preprint, url, - institutions): + def test_add_multiple_institutions_affiliations(self, app, admin_with_institutional_affiliation, preprint, url, institutions): """ - Test adding multiple institution affiliations to a preprint. - - Verifies: - - Admins with multiple affiliations can add them to a preprint. + Test that admins with multiple affiliations can add them to a preprint. """ - admin_with_institutional_affilation.add_or_update_affiliated_institution(institutions[0]) - admin_with_institutional_affilation.add_or_update_affiliated_institution(institutions[1]) - admin_with_institutional_affilation.add_or_update_affiliated_institution(institutions[2]) - admin_with_institutional_affilation.save() - add_institutions_payload = { - 'data': [{'type': 'institutions', 'id': institution._id} for institution in institutions] - } - - assert preprint.affiliated_institutions.all().count() == 0 - res = app.put_json_api( - url, - add_institutions_payload, - auth=admin_with_institutional_affilation.auth, - ) + for institution in institutions: + admin_with_institutional_affiliation.add_or_update_affiliated_institution(institution) + admin_with_institutional_affiliation.save() + add_institutions_payload = {'data': [{'type': 'institutions', 'id': institution._id} for institution in institutions]} + res = app.put_json_api(url, add_institutions_payload, auth=admin_with_institutional_affiliation.auth) assert res.status_code == 200 - assert preprint.affiliated_institutions.all().count() == 3 - preprint.reload() + assert preprint.affiliated_institutions.all().count() == 3 - def test_remove_only_institutions_affiliations_that_user_has(self, app, user, admin_with_institutional_affilation, preprint, url, - institutions, institution): + def test_remove_only_institutions_affiliations_that_user_has(self, app, admin_with_institutional_affiliation, preprint, url, institutions, institution_A): """ - Test removing only institutions that the user is affiliated with from a preprint. - - Verifies: - - Admins with multiple affiliations only remove their own affiliations, leaving others unchanged. + Test that admins with multiple affiliations only remove their own affiliations, leaving others unchanged. """ preprint.affiliated_institutions.add(*institutions) assert preprint.affiliated_institutions.all().count() == 3 - - admin_with_institutional_affilation.add_or_update_affiliated_institution(institutions[0]) - admin_with_institutional_affilation.add_or_update_affiliated_institution(institutions[1]) - - update_institution_payload = { - 'data': [{'type': 'institutions', 'id': institution._id}] - } - - res = app.put_json_api( - url, - update_institution_payload, - auth=admin_with_institutional_affilation.auth - ) + admin_with_institutional_affiliation.add_or_update_affiliated_institution(institutions[0]) + admin_with_institutional_affiliation.add_or_update_affiliated_institution(institutions[1]) + update_institution_payload = {'data': [{'type': 'institutions', 'id': institution_A._id}]} + res = app.put_json_api(url, update_institution_payload, auth=admin_with_institutional_affiliation.auth) assert res.status_code == 200 assert preprint.affiliated_institutions.all().count() == 2 - assert institution in preprint.affiliated_institutions.all() + assert institution_A in preprint.affiliated_institutions.all() assert institutions[2] in preprint.affiliated_institutions.all()