diff --git a/api/nodes/permissions.py b/api/nodes/permissions.py index 45636819f72b..00aaee13ca53 100644 --- a/api/nodes/permissions.py +++ b/api/nodes/permissions.py @@ -161,6 +161,21 @@ def has_object_permission(self, request, view, obj): return obj.is_admin_contributor(auth.user) +class NodeDraftRegistrationsListPermission(permissions.BasePermission): + acceptable_models = (AbstractNode, DraftRegistration,) + + def has_object_permission(self, request, view, obj): + """ + To make changes, user must be an admin contributor. Admin group membership is not sufficient. + """ + assert_resource_type(obj, self.acceptable_models) + auth = get_user_auth(request) + if request.method in permissions.SAFE_METHODS: + return obj.has_permission(auth.user, osf_permissions.READ) + else: + return obj.is_admin_contributor(auth.user) + + class ExcludeWithdrawals(permissions.BasePermission): def has_object_permission(self, request, view, obj): diff --git a/api/nodes/views.py b/api/nodes/views.py index 000d6bbbad97..b0cdc00bc5c0 100644 --- a/api/nodes/views.py +++ b/api/nodes/views.py @@ -89,6 +89,7 @@ ExcludeWithdrawals, NodeLinksShowIfVersion, ReadOnlyIfWithdrawn, + NodeDraftRegistrationsListPermission ) from api.nodes.serializers import ( NodeSerializer, @@ -622,7 +623,7 @@ class NodeDraftRegistrationsList(JSONAPIBaseView, generics.ListCreateAPIView, No Use DraftRegistrationsList endpoint instead. """ permission_classes = ( - IsAdminContributor, + NodeDraftRegistrationsListPermission, drf_permissions.IsAuthenticatedOrReadOnly, base_permissions.TokenHasScope, ) 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 a37a81ad53ee..d36e986a8bcd 100644 --- a/api_tests/nodes/views/test_node_draft_registration_list.py +++ b/api_tests/nodes/views/test_node_draft_registration_list.py @@ -138,37 +138,34 @@ def test_osf_group_with_admin_permissions_can_view( assert len(data) == 1 assert schema._id in data[0]['relationships']['registration_schema']['links']['related']['href'] - def test_cannot_view_draft_list( - self, app, user_write_contrib, project_public, - user_read_contrib, user_non_contrib, - url_draft_registrations, group, group_mem): + def test_read_only_contributor_can_view_draft_list( + self, app, project_public, user_read_contrib, user_non_contrib, url_draft_registrations): - # test_read_only_contributor_cannot_view_draft_list - res = app.get( - url_draft_registrations, - auth=user_read_contrib.auth, - expect_errors=True) - assert res.status_code == 403 + res = app.get(url_draft_registrations, auth=user_read_contrib.auth, expect_errors=True) + assert res.status_code == 200 - # test_read_write_contributor_cannot_view_draft_list - res = app.get( - url_draft_registrations, - auth=user_write_contrib.auth, - expect_errors=True) - assert res.status_code == 403 + 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): - # test_logged_in_non_contributor_cannot_view_draft_list - res = app.get( - url_draft_registrations, - auth=user_non_contrib.auth, - expect_errors=True) + res = app.get(url_draft_registrations, auth=user_write_contrib.auth, expect_errors=True) + 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): + + res = app.get(url_draft_registrations, auth=user_non_contrib.auth, expect_errors=True) assert res.status_code == 403 - # test_unauthenticated_user_cannot_view_draft_list + def test_unauthenticated_user_cannot_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, expect_errors=True) assert res.status_code == 401 - # test_osf_group_with_read_permissions + def test_osf_group_with_read_permissions( + self, app, user_write_contrib, project_public, + user_read_contrib, user_non_contrib, url_draft_registrations, group, group_mem): + project_public.remove_osf_group(group) project_public.add_osf_group(group, permissions.READ) res = app.get(url_draft_registrations, auth=group_mem.auth, expect_errors=True)