diff --git a/api/requests/serializers.py b/api/requests/serializers.py index 3723d8984e8e..3fa4ffebba8c 100644 --- a/api/requests/serializers.py +++ b/api/requests/serializers.py @@ -1,4 +1,4 @@ -from django.db import IntegrityError +from django.db import IntegrityError, transaction from rest_framework import exceptions from rest_framework import serializers as ser @@ -209,17 +209,32 @@ def _create_node_request(self, node, validated_data) -> NodeRequest: comment = validated_data.get('comment', '') requested_permissions = validated_data.get('requested_permissions') try: - node_request = NodeRequest.objects.create( - target=node, - creator=creator, - comment=comment, - machine_state=DefaultStates.INITIAL.value, - request_type=request_type, - requested_permissions=requested_permissions, - ) - node_request.save() + with transaction.atomic(): + node_request = NodeRequest.objects.create( + target=node, + creator=creator, + comment=comment, + machine_state=DefaultStates.INITIAL.value, + request_type=request_type, + requested_permissions=requested_permissions, + ) + node_request.save() except IntegrityError: - raise Conflict(f"Users may not have more than one {request_type} request per node.") + # if INSTITUTIONAL_REQUEST updates and restarts the request + with transaction.atomic(): + if request_type == NodeRequestTypes.INSTITUTIONAL_REQUEST.value: + node_request = NodeRequest.objects.filter( + target=node, + creator=creator, + request_type=NodeRequestTypes.INSTITUTIONAL_REQUEST.value, + ).first() + else: + raise Conflict(f"Users may not have more than one {request_type} request per node.") + if node_request: + node_request.comment = comment + node_request.machine_state = DefaultStates.INITIAL.value + node_request.requested_permissions = requested_permissions + node_request.save() node_request.run_submit(creator) return node_request diff --git a/api_tests/requests/views/test_node_request_institutional_access.py b/api_tests/requests/views/test_node_request_institutional_access.py index c3fdc4e111b5..2560d49fb9b3 100644 --- a/api_tests/requests/views/test_node_request_institutional_access.py +++ b/api_tests/requests/views/test_node_request_institutional_access.py @@ -395,3 +395,20 @@ def test_access_requests_disabled_raises_permission_denied( ) assert res.status_code == 403 assert f"{node_with_disabled_access_requests._id} does not have Access Requests enabled" in res.json['errors'][0]['detail'] + + def test_requester_can_resubmit(self, app, project, institutional_admin, url, create_payload): + """ + Test that a requester cannot submit another access request for the same node. + """ + # Create the first request + app.post_json_api(url, create_payload, auth=institutional_admin.auth) + node_request = project.requests.get() + node_request.run_reject(project.creator, 'test comment2') + node_request.refresh_from_db() + assert node_request.machine_state == 'rejected' + + # Attempt to create a second request + res = app.post_json_api(url, create_payload, auth=institutional_admin.auth) + assert res.status_code == 201 + node_request.refresh_from_db() + assert node_request.machine_state == 'pending'