Skip to content

Commit 3cefffe

Browse files
authored
[ENG-10384] return 409 when submit to closed registry (#11628)
1 parent 595ce85 commit 3cefffe

4 files changed

Lines changed: 64 additions & 1 deletion

File tree

api/draft_registrations/permissions.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from rest_framework import permissions
22

3+
from api.base.exceptions import Conflict
34
from api.base.utils import get_user_auth, assert_resource_type
45
from osf.models import (
56
DraftRegistration,
67
AbstractNode,
78
DraftRegistrationContributor,
89
OSFUser,
10+
RegistrationProvider,
911
)
1012
from api.nodes.permissions import ContributorDetailPermissions
1113
from osf.utils.permissions import WRITE, ADMIN
@@ -90,3 +92,32 @@ def has_object_permission(self, request, view, obj):
9092
elif isinstance(obj, AbstractNode):
9193
return obj.has_permission(auth.user, WRITE)
9294
return False
95+
96+
97+
class CanSubmitDraftRegistrationToProvider(permissions.BasePermission):
98+
"""
99+
Prevent creating draft registrations for providers that are closed to submissions.
100+
"""
101+
102+
def has_permission(self, request, view):
103+
if request.method != 'POST':
104+
return True
105+
106+
provider_id = request.data.get('provider')
107+
108+
if not provider_id:
109+
try:
110+
provider = RegistrationProvider.get_default()
111+
except RegistrationProvider.DoesNotExist:
112+
return True
113+
else:
114+
try:
115+
provider = RegistrationProvider.objects.get(_id=provider_id)
116+
except RegistrationProvider.DoesNotExist:
117+
# Let existing validation handle bad provider ids.
118+
return True
119+
120+
if not provider.allow_submissions:
121+
raise Conflict(f"Registry {provider.name} is closed for new submissions. Please start a new registration with a different registry.")
122+
123+
return True

api/draft_registrations/views.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
DraftContributorDetailPermissions,
99
DraftRegistrationPermission,
1010
IsAdminContributor,
11+
CanSubmitDraftRegistrationToProvider,
1112
)
1213
from api.draft_registrations.serializers import (
1314
DraftRegistrationSerializer,
@@ -53,6 +54,7 @@ class DraftRegistrationList(NodeDraftRegistrationsList):
5354
drf_permissions.IsAuthenticatedOrReadOnly,
5455
base_permissions.TokenHasScope,
5556
DraftRegistrationPermission,
57+
CanSubmitDraftRegistrationToProvider,
5658
)
5759

5860
view_category = 'draft_registrations'

api/nodes/views.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@
7474
NodeCommentSerializer,
7575
)
7676
from api.draft_registrations.serializers import DraftRegistrationSerializer, DraftRegistrationDetailSerializer
77-
from api.draft_registrations.permissions import DraftRegistrationPermission
77+
from api.draft_registrations.permissions import (
78+
DraftRegistrationPermission,
79+
CanSubmitDraftRegistrationToProvider,
80+
)
7881
from api.files.serializers import FileSerializer, OsfStorageFileSerializer
7982
from api.files import annotations as file_annotations
8083
from api.identifiers.serializers import NodeIdentifierSerializer
@@ -671,6 +674,7 @@ class NodeDraftRegistrationsList(JSONAPIBaseView, generics.ListCreateAPIView, No
671674
DraftRegistrationPermission,
672675
drf_permissions.IsAuthenticatedOrReadOnly,
673676
base_permissions.TokenHasScope,
677+
CanSubmitDraftRegistrationToProvider,
674678
)
675679

676680
parser_classes = (JSONAPIMultipleRelationshipsParser, JSONAPIMultipleRelationshipsParserForRegularJSON)

api_tests/draft_registrations/views/test_draft_registration_list.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,19 @@ def test_affiliated_institutions_are_copied_from_user(self, app, user, url_draft
399399
draft_registration = DraftRegistration.load(res.json['data']['id'])
400400
assert list(draft_registration.affiliated_institutions.all()) == list(user.get_affiliated_institutions())
401401

402+
def test_cannot_create_draft_when_provider_disallows_submissions(
403+
self, app, user, provider, payload, url_draft_registrations):
404+
provider.allow_submissions = False
405+
provider.save()
406+
407+
res = app.post_json_api(
408+
url_draft_registrations,
409+
payload,
410+
auth=user.auth,
411+
expect_errors=True,
412+
)
413+
assert res.status_code == 409
414+
402415

403416
class TestDraftRegistrationCreateWithoutNode(AbstractDraftRegistrationTestCase):
404417
@pytest.fixture()
@@ -451,6 +464,19 @@ def test_create_draft_with_provider(
451464
draft = DraftRegistration.load(data['id'])
452465
assert draft.provider == non_default_provider
453466

467+
def test_cannot_create_draft_when_provider_disallows_submissions(
468+
self, app, user, url_draft_registrations, non_default_provider, payload_with_non_default_provider):
469+
non_default_provider.allow_submissions = False
470+
non_default_provider.save()
471+
472+
res = app.post_json_api(
473+
url_draft_registrations,
474+
payload_with_non_default_provider,
475+
auth=user.auth,
476+
expect_errors=True,
477+
)
478+
assert res.status_code == 409
479+
454480
def test_write_contrib(self, app, user, project_public, payload, url_draft_registrations, user_write_contrib):
455481
"""(no node supplied, so any logged in user can create)
456482
"""

0 commit comments

Comments
 (0)