Skip to content

Commit 97bc7cd

Browse files
committed
NRL-703 add perm check to upsert
1 parent 034b6c7 commit 97bc7cd

File tree

2 files changed

+96
-22
lines changed

2 files changed

+96
-22
lines changed

api/producer/upsertDocumentReference/tests/test_upsert_document_reference.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
_set_upsert_time_fields,
99
handler,
1010
)
11+
from nrlf.core.constants import PERMISSION_SUPERSEDE_IGNORE_DELETE_FAIL
1112
from nrlf.core.dynamodb.repository import DocumentPointer, DocumentPointerRepository
1213
from nrlf.producer.fhir.r4.model import (
1314
DocumentReferenceRelatesTo,
@@ -603,6 +604,63 @@ def test_create_document_reference_invalid_relatesto_not_exists(repository):
603604
}
604605

605606

607+
@mock_aws
608+
@mock_repository
609+
def test_create_document_reference_invalid_relatesto_not_exists_still_creates_with_ignore_perm(
610+
repository,
611+
):
612+
doc_ref = load_document_reference("Y05868-736253002-Valid")
613+
doc_ref.relatesTo = [
614+
DocumentReferenceRelatesTo(
615+
code="transforms",
616+
target=Reference(
617+
reference=None,
618+
identifier=Identifier(value="Y05868-99999-99999-999999"),
619+
),
620+
)
621+
]
622+
623+
event = create_test_api_gateway_event(
624+
headers=create_headers(
625+
nrl_permissions=[PERMISSION_SUPERSEDE_IGNORE_DELETE_FAIL]
626+
),
627+
body=doc_ref.json(exclude_none=True),
628+
)
629+
630+
result = handler(event, create_mock_context())
631+
body = result.pop("body")
632+
633+
assert result == {
634+
"statusCode": "201",
635+
"headers": {
636+
"Location": "/nrl-producer-api/FHIR/R4/DocumentReference/Y05868-99999-99999-999999"
637+
},
638+
"isBase64Encoded": False,
639+
}
640+
641+
parsed_body = json.loads(body)
642+
643+
assert parsed_body == {
644+
"resourceType": "OperationOutcome",
645+
"issue": [
646+
{
647+
"severity": "information",
648+
"code": "informational",
649+
"details": {
650+
"coding": [
651+
{
652+
"code": "RESOURCE_CREATED",
653+
"display": "Resource created",
654+
"system": "https://fhir.nhs.uk/ValueSet/NRL-ResponseCode",
655+
}
656+
]
657+
},
658+
"diagnostics": "The document has been created",
659+
}
660+
],
661+
}
662+
663+
606664
@mock_aws
607665
@mock_repository
608666
def test_create_document_reference_invalid_relatesto_nhs_number(

api/producer/upsertDocumentReference/upsert_document_reference.py

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
from nrlf.core.constants import PERMISSION_AUDIT_DATES_FROM_PAYLOAD
1+
from nrlf.core.constants import (
2+
PERMISSION_AUDIT_DATES_FROM_PAYLOAD,
3+
PERMISSION_SUPERSEDE_IGNORE_DELETE_FAIL,
4+
)
25
from nrlf.core.decorators import request_handler
36
from nrlf.core.dynamodb.repository import DocumentPointer, DocumentPointerRepository
47
from nrlf.core.logger import LogReference, logger
@@ -105,6 +108,7 @@ def handler(
105108

106109
if result.resource.relatesTo:
107110
logger.log(LogReference.PROUPSERT006, relatesTo=result.resource.relatesTo)
111+
has_delete_target = True
108112

109113
for idx, relates_to in enumerate(result.resource.relatesTo):
110114
if not (identifier := getattr(relates_to.target.identifier, "value", None)):
@@ -127,27 +131,39 @@ def handler(
127131
)
128132

129133
if not (existing_pointer := repository.get_by_id(identifier)):
130-
logger.log(LogReference.PROUPSERT007c, related_identifier=identifier)
131-
return SpineErrorResponse.BAD_REQUEST(
132-
diagnostics="The relatesTo target document does not exist",
133-
expression=f"relatesTo[{idx}].target.identifier.value",
134-
)
135-
136-
if existing_pointer.nhs_number != core_model.nhs_number:
137-
logger.log(LogReference.PROUPSERT007d, related_identifier=identifier)
138-
return SpineErrorResponse.BAD_REQUEST(
139-
diagnostics="The relatesTo target document NHS number does not match the NHS number in the request",
140-
expression=f"relatesTo[{idx}].target.identifier.value",
141-
)
142-
143-
if existing_pointer.type != core_model.type:
144-
logger.log(LogReference.PROUPSERT007e, related_identifier=identifier)
145-
return SpineErrorResponse.BAD_REQUEST(
146-
diagnostics="The relatesTo target document type does not match the type in the request",
147-
expression=f"relatesTo[{idx}].target.identifier.value",
148-
)
149-
150-
if relates_to.code == "replaces":
134+
if (
135+
PERMISSION_SUPERSEDE_IGNORE_DELETE_FAIL
136+
not in metadata.nrl_permissions
137+
):
138+
logger.log(
139+
LogReference.PROCREATE007c, related_identifier=identifier
140+
)
141+
return SpineErrorResponse.BAD_REQUEST(
142+
diagnostics="The relatesTo target document does not exist",
143+
expression=f"relatesTo[{idx}].target.identifier.value",
144+
)
145+
has_delete_target = False
146+
147+
if has_delete_target:
148+
if existing_pointer.nhs_number != core_model.nhs_number:
149+
logger.log(
150+
LogReference.PROUPSERT007d, related_identifier=identifier
151+
)
152+
return SpineErrorResponse.BAD_REQUEST(
153+
diagnostics="The relatesTo target document NHS number does not match the NHS number in the request",
154+
expression=f"relatesTo[{idx}].target.identifier.value",
155+
)
156+
157+
if existing_pointer.type != core_model.type:
158+
logger.log(
159+
LogReference.PROUPSERT007e, related_identifier=identifier
160+
)
161+
return SpineErrorResponse.BAD_REQUEST(
162+
diagnostics="The relatesTo target document type does not match the type in the request",
163+
expression=f"relatesTo[{idx}].target.identifier.value",
164+
)
165+
166+
if relates_to.code == "replaces" and has_delete_target:
151167
logger.log(
152168
LogReference.PROUPSERT008,
153169
relates_to_code=relates_to.code,

0 commit comments

Comments
 (0)