Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions api/draft_registrations/permissions.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from rest_framework import permissions

from api.base.exceptions import Conflict
from api.base.utils import get_user_auth, assert_resource_type
from osf.models import (
DraftRegistration,
AbstractNode,
DraftRegistrationContributor,
OSFUser,
RegistrationProvider,
)
from api.nodes.permissions import ContributorDetailPermissions
from osf.utils.permissions import WRITE, ADMIN
Expand Down Expand Up @@ -90,3 +92,32 @@ def has_object_permission(self, request, view, obj):
elif isinstance(obj, AbstractNode):
return obj.has_permission(auth.user, WRITE)
return False


class CanSubmitDraftRegistrationToProvider(permissions.BasePermission):
"""
Prevent creating draft registrations for providers that are closed to submissions.
"""

def has_permission(self, request, view):
if request.method != 'POST':
return True

provider_id = request.data.get('provider')

if not provider_id:
try:
provider = RegistrationProvider.get_default()
except RegistrationProvider.DoesNotExist:
return True
else:
try:
provider = RegistrationProvider.objects.get(_id=provider_id)
except RegistrationProvider.DoesNotExist:
# Let existing validation handle bad provider ids.
return True

if not provider.allow_submissions:
raise Conflict(f"Registry {provider.name} is closed for new submissions. Please start a new registration with a different registry.")

return True
2 changes: 2 additions & 0 deletions api/draft_registrations/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
DraftContributorDetailPermissions,
DraftRegistrationPermission,
IsAdminContributor,
CanSubmitDraftRegistrationToProvider,
)
from api.draft_registrations.serializers import (
DraftRegistrationSerializer,
Expand Down Expand Up @@ -53,6 +54,7 @@ class DraftRegistrationList(NodeDraftRegistrationsList):
drf_permissions.IsAuthenticatedOrReadOnly,
base_permissions.TokenHasScope,
DraftRegistrationPermission,
CanSubmitDraftRegistrationToProvider,
)

view_category = 'draft_registrations'
Expand Down
6 changes: 5 additions & 1 deletion api/nodes/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@
NodeCommentSerializer,
)
from api.draft_registrations.serializers import DraftRegistrationSerializer, DraftRegistrationDetailSerializer
from api.draft_registrations.permissions import DraftRegistrationPermission
from api.draft_registrations.permissions import (
DraftRegistrationPermission,
CanSubmitDraftRegistrationToProvider,
)
from api.files.serializers import FileSerializer, OsfStorageFileSerializer
from api.files import annotations as file_annotations
from api.identifiers.serializers import NodeIdentifierSerializer
Expand Down Expand Up @@ -671,6 +674,7 @@ class NodeDraftRegistrationsList(JSONAPIBaseView, generics.ListCreateAPIView, No
DraftRegistrationPermission,
drf_permissions.IsAuthenticatedOrReadOnly,
base_permissions.TokenHasScope,
CanSubmitDraftRegistrationToProvider,
)

parser_classes = (JSONAPIMultipleRelationshipsParser, JSONAPIMultipleRelationshipsParserForRegularJSON)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,19 @@ def test_affiliated_institutions_are_copied_from_user(self, app, user, url_draft
draft_registration = DraftRegistration.load(res.json['data']['id'])
assert list(draft_registration.affiliated_institutions.all()) == list(user.get_affiliated_institutions())

def test_cannot_create_draft_when_provider_disallows_submissions(
self, app, user, provider, payload, url_draft_registrations):
provider.allow_submissions = False
provider.save()

res = app.post_json_api(
url_draft_registrations,
payload,
auth=user.auth,
expect_errors=True,
)
assert res.status_code == 409


class TestDraftRegistrationCreateWithoutNode(AbstractDraftRegistrationTestCase):
@pytest.fixture()
Expand Down Expand Up @@ -451,6 +464,19 @@ def test_create_draft_with_provider(
draft = DraftRegistration.load(data['id'])
assert draft.provider == non_default_provider

def test_cannot_create_draft_when_provider_disallows_submissions(
self, app, user, url_draft_registrations, non_default_provider, payload_with_non_default_provider):
non_default_provider.allow_submissions = False
non_default_provider.save()

res = app.post_json_api(
url_draft_registrations,
payload_with_non_default_provider,
auth=user.auth,
expect_errors=True,
)
assert res.status_code == 409

def test_write_contrib(self, app, user, project_public, payload, url_draft_registrations, user_write_contrib):
"""(no node supplied, so any logged in user can create)
"""
Expand Down
Loading