From cb5c5bde84950c2c4f2c82b58ba7f85a0989cd80 Mon Sep 17 00:00:00 2001 From: John Tordoff <> Date: Wed, 18 Oct 2023 22:36:03 +0800 Subject: [PATCH] split-up and clean-up tests for differing draftregstration permissions --- api/nodes/permissions.py | 2 +- .../views/test_draft_registration_list.py | 153 ++++++++++++++---- .../test_node_draft_registration_list.py | 26 +-- 3 files changed, 131 insertions(+), 50 deletions(-) diff --git a/api/nodes/permissions.py b/api/nodes/permissions.py index 00aaee13ca53..94195d05b8a4 100644 --- a/api/nodes/permissions.py +++ b/api/nodes/permissions.py @@ -166,7 +166,7 @@ class NodeDraftRegistrationsListPermission(permissions.BasePermission): def has_object_permission(self, request, view, obj): """ - To make changes, user must be an admin contributor. Admin group membership is not sufficient. + To make changes, user must be an admin contributor. Viewing information is acceptable for any READ contributor. """ assert_resource_type(obj, self.acceptable_models) auth = get_user_auth(request) diff --git a/api_tests/draft_registrations/views/test_draft_registration_list.py b/api_tests/draft_registrations/views/test_draft_registration_list.py index 509e8daacc2a..d2be1d6f1354 100644 --- a/api_tests/draft_registrations/views/test_draft_registration_list.py +++ b/api_tests/draft_registrations/views/test_draft_registration_list.py @@ -2,20 +2,26 @@ import pytest from framework.auth.core import Auth -from api_tests.nodes.views.test_node_draft_registration_list import ( - TestDraftRegistrationList, - TestDraftRegistrationCreate -) +from django.utils import timezone +from api_tests.nodes.views.test_node_draft_registration_list import TestDraftRegistrationCreate from api.base.settings.defaults import API_BASE from osf.migrations import ensure_invisible_and_inactive_schema -from osf.models import DraftRegistration, NodeLicense, RegistrationProvider, Institution +from osf.models import ( + DraftRegistration, + NodeLicense, + RegistrationProvider, + Institution, + RegistrationSchema +) + from osf_tests.factories import ( RegistrationFactory, CollectionFactory, ProjectFactory, AuthUserFactory, - InstitutionFactory + InstitutionFactory, + DraftRegistrationFactory, ) from osf.utils.permissions import READ, WRITE, ADMIN @@ -28,48 +34,135 @@ def invisible_and_inactive_schema(): @pytest.mark.django_db -class TestDraftRegistrationListNewWorkflow(TestDraftRegistrationList): +class TestDraftRegistrationListNewWorkflow: + @pytest.fixture() - def url_draft_registrations(self, project_public): - return '/{}draft_registrations/?'.format(API_BASE) + def user(self): + return AuthUserFactory() - # Overrides TestDraftRegistrationList - def test_osf_group_with_admin_permissions_can_view(self): - # DraftRegistration endpoints permissions are not calculated from the node - return + @pytest.fixture() + def user_admin_contrib(self): + return AuthUserFactory() - # Overrides TestDraftRegistrationList - def test_cannot_view_draft_list( - self, app, user_write_contrib, project_public, - user_read_contrib, user_non_contrib, draft_registration, - url_draft_registrations, group, group_mem): + @pytest.fixture() + def user_write_contrib(self): + return AuthUserFactory() + + @pytest.fixture() + def user_read_contrib(self): + return AuthUserFactory() + + @pytest.fixture() + def user_non_contrib(self): + return AuthUserFactory() + + @pytest.fixture() + def group_mem(self): + return AuthUserFactory() + + @pytest.fixture() + def project(self, user): + return ProjectFactory(creator=user) + + @pytest.fixture() + def schema(self): + return RegistrationSchema.objects.get(name='Open-Ended Registration', schema_version=3) + + @pytest.fixture() + def draft_registration(self, user, project, schema, user_write_contrib, user_read_contrib, user_admin_contrib): + draft = DraftRegistrationFactory( + initiator=user, + registration_schema=schema, + branched_from=project + ) + draft.add_contributor(user_read_contrib, permissions=READ) + draft.add_contributor(user_write_contrib, permissions=WRITE) + draft.add_contributor(user_admin_contrib, permissions=ADMIN) + return draft + + @pytest.fixture() + def url_draft_registrations(self, project): + return f'/{API_BASE}draft_registrations/' - # test_read_only_contributor_can_view_draft_list + def test_read_only_contributor_can_view_draft_list( + self, app, user_read_contrib, draft_registration, url_draft_registrations + ): res = app.get( url_draft_registrations, - auth=user_read_contrib.auth) + auth=user_read_contrib.auth + ) assert res.status_code == 200 assert len(res.json['data']) == 1 - # test_read_write_contributor_can_view_draft_list - res = app.get( - url_draft_registrations, - auth=user_write_contrib.auth) + def test_read_write_contributor_can_view_draft_list( + self, app, user_write_contrib, draft_registration, url_draft_registrations + ): + res = app.get(url_draft_registrations, auth=user_write_contrib.auth) assert res.status_code == 200 assert len(res.json['data']) == 1 - # test_logged_in_non_contributor_can_view_draft_list - res = app.get( - url_draft_registrations, - auth=user_non_contrib.auth, - expect_errors=True) + def test_logged_in_non_contributor_has_empty_list( + self, app, user_non_contrib, url_draft_registrations + ): + res = app.get(url_draft_registrations, auth=user_non_contrib.auth) assert res.status_code == 200 assert len(res.json['data']) == 0 - # test_unauthenticated_user_cannot_view_draft_list + def test_unauthenticated_user_cannot_view_draft_list(self, app, url_draft_registrations): res = app.get(url_draft_registrations, expect_errors=True) assert res.status_code == 401 + def test_admin_can_view_draft_list(self, app, user_admin_contrib, draft_registration, schema, url_draft_registrations): + res = app.get(url_draft_registrations, auth=user_admin_contrib.auth) + + assert res.status_code == 200 + data = res.json['data'] + assert len(data) == 1 + + assert schema._id in data[0]['relationships']['registration_schema']['links']['related']['href'] + assert data[0]['id'] == draft_registration._id + assert data[0]['attributes']['registration_metadata'] == {} + + def test_logged_in_non_contributor_cannot_view_draft_list(self, app, user_non_contrib, url_draft_registrations): + res = app.get(url_draft_registrations, auth=user_non_contrib.auth) + assert res.status_code == 200 + + def test_deleted_draft_registration_does_not_show_up_in_draft_list(self, app, user, draft_registration, url_draft_registrations): + draft_registration.deleted = timezone.now() + draft_registration.save() + res = app.get(url_draft_registrations, auth=user.auth) + assert res.status_code == 200 + assert not res.json['data'] + + def test_draft_with_registered_node_does_not_show_up_in_draft_list( + self, app, user, project, draft_registration, url_draft_registrations + ): + registration = RegistrationFactory( + project=project, + draft_registration=draft_registration + ) + draft_registration.registered_node = registration + draft_registration.save() + res = app.get(url_draft_registrations, auth=user.auth) + assert res.status_code == 200 + assert not res.json['data'] + + def test_draft_with_deleted_registered_node_shows_up_in_draft_list( + self, app, user, project, draft_registration, schema, url_draft_registrations + ): + registration = RegistrationFactory(project=project, draft_registration=draft_registration) + draft_registration.registered_node = registration + draft_registration.save() + registration.deleted = timezone.now() + registration.save() + res = app.get(url_draft_registrations, auth=user.auth) + assert res.status_code == 200 + data = res.json['data'] + assert len(data) == 1 + assert schema._id in data[0]['relationships']['registration_schema']['links']['related']['href'] + assert data[0]['id'] == draft_registration._id + assert data[0]['attributes']['registration_metadata'] == {} + class TestDraftRegistrationCreateWithNode(TestDraftRegistrationCreate): diff --git a/api_tests/nodes/views/test_node_draft_registration_list.py b/api_tests/nodes/views/test_node_draft_registration_list.py index 4f6e7d03a657..d033d66c8eab 100644 --- a/api_tests/nodes/views/test_node_draft_registration_list.py +++ b/api_tests/nodes/views/test_node_draft_registration_list.py @@ -132,37 +132,25 @@ def test_osf_group_with_admin_permissions_can_view( group_mem = AuthUserFactory() group = OSFGroupFactory(creator=group_mem) project_public.add_osf_group(group, permissions.ADMIN) - res = app.get(url_draft_registrations, auth=group_mem.auth, expect_errors=True) + res = app.get(url_draft_registrations, auth=group_mem.auth) assert res.status_code == 200 data = res.json['data'] assert len(data) == 1 assert schema._id in data[0]['relationships']['registration_schema']['links']['related']['href'] - def test_read_only_contributor_can_view_draft_list( - self, app, project_public, user_read_contrib, user_non_contrib, url_draft_registrations - ): - - res = app.get(url_draft_registrations, auth=user_read_contrib.auth, expect_errors=True) + def test_read_only_contributor_can_view_draft_list(self, app, user_read_contrib, url_draft_registrations): + res = app.get(url_draft_registrations, auth=user_read_contrib.auth) assert res.status_code == 200 - def test_read_write_contributor_can_view_draft_list( - self, app, user_write_contrib, project_public, user_read_contrib, user_non_contrib, url_draft_registrations - ): - - res = app.get(url_draft_registrations, auth=user_write_contrib.auth, expect_errors=True) + def test_read_write_contributor_can_view_draft_list(self, app, user_write_contrib, url_draft_registrations): + res = app.get(url_draft_registrations, auth=user_write_contrib.auth) assert res.status_code == 200 - def test_logged_in_non_contributor_cannot_view_draft_list( - self, app, user_write_contrib, project_public, user_read_contrib, user_non_contrib, url_draft_registrations - ): - + def test_logged_in_non_contributor_cannot_view_draft_list(self, app, user_non_contrib, url_draft_registrations): res = app.get(url_draft_registrations, auth=user_non_contrib.auth, expect_errors=True) assert res.status_code == 403 - def test_unauthenticated_user_cannot_view_draft_list( - self, app, user_write_contrib, project_public, user_read_contrib, user_non_contrib, url_draft_registrations - ): - + def test_unauthenticated_user_cannot_view_draft_list(self, app, url_draft_registrations): res = app.get(url_draft_registrations, expect_errors=True) assert res.status_code == 401