Skip to content

Commit 8bbb523

Browse files
kamenbachvarov-nhssteph-torres-nhsDuncanSangsterNHS
authored
[PRMP-1082] Add file type check for review docs (#965)
Co-authored-by: steph-torres-nhs <[email protected]> Co-authored-by: DuncanSangsterNHS <[email protected]>
1 parent 52819f8 commit 8bbb523

File tree

8 files changed

+51
-10
lines changed

8 files changed

+51
-10
lines changed

lambdas/enums/lambda_error.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,10 @@ def create_error_body(self, params: Optional[dict] = None, **kwargs) -> str:
517517
"err_code": "DRV_4005",
518518
"message": "The NHS number provided is invalid",
519519
}
520+
DocumentReviewUnsupportedFileType = {
521+
"err_code": "DRV_4006",
522+
"message": "The file type provided is not supported",
523+
}
520524

521525
"""
522526
Errors for get ods report lambda
@@ -690,10 +694,7 @@ def create_error_body(self, params: Optional[dict] = None, **kwargs) -> str:
690694
"message": "Invalid request",
691695
}
692696

693-
DocumentReviewUploadForbidden = {
694-
"err_code": "UDR_4031",
695-
"message": "Forbidden"
696-
}
697+
DocumentReviewUploadForbidden = {"err_code": "UDR_4031", "message": "Forbidden"}
697698

698699
DocumentReviewPresignedFailure = {
699700
"err_code": "UDR_5003",

lambdas/handlers/post_document_review_handler.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from utils.decorators.ensure_env_var import ensure_environment_variables
1111
from utils.decorators.handle_lambda_exceptions import handle_lambda_exceptions
1212
from utils.decorators.set_audit_arg import set_request_context_for_logging
13-
from utils.exceptions import InvalidNhsNumberException
13+
from utils.exceptions import InvalidNhsNumberException, InvalidFileTypeException
1414
from utils.lambda_exceptions import DocumentReviewLambdaException
1515
from utils.lambda_response import ApiGatewayResponse
1616

@@ -60,3 +60,8 @@ def validate_event_body(body):
6060
raise DocumentReviewLambdaException(
6161
400, LambdaError.DocumentReviewUploadInvalidRequest
6262
)
63+
except InvalidFileTypeException as e:
64+
logger.error(e)
65+
raise DocumentReviewLambdaException(
66+
400, LambdaError.DocumentReviewUnsupportedFileType
67+
)

lambdas/models/document_review.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import uuid
22
from datetime import datetime, timezone
3+
from typing import Self
34

45
from enums.document_review_reason import DocumentReviewReason
56
from enums.document_review_status import DocumentReviewStatus
67
from enums.metadata_field_names import DocumentReferenceMetadataFields
8+
from enums.upload_forbidden_file_extensions import is_file_type_allowed
79
from enums.snomed_codes import SnomedCodes
8-
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
10+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator, ValidationError
911
from pydantic.alias_generators import to_camel, to_pascal
10-
from utils.exceptions import InvalidNhsNumberException
12+
from utils.exceptions import InvalidNhsNumberException, ConfigNotFoundException, InvalidFileTypeException
13+
from utils import upload_file_configs
1114
from utils.utilities import validate_nhs_number
1215

1316

@@ -158,3 +161,16 @@ def check_snomed_code(cls, value) -> SnomedCodes | None:
158161
def verify_nhs_number(cls, value) -> str | None:
159162
if validate_nhs_number(value):
160163
return value
164+
165+
@model_validator(mode="after")
166+
def validate_file_extension(self) -> Self:
167+
try:
168+
accepted_file_types = upload_file_configs.get_config_by_snomed_code(self.snomed_code.code).accepted_file_types
169+
170+
for file in self.documents:
171+
if not is_file_type_allowed(file, accepted_file_types):
172+
raise InvalidFileTypeException("Invalid file extension.")
173+
return self
174+
except ConfigNotFoundException:
175+
raise InvalidFileTypeException("Unable to find file configuration.")
176+

lambdas/services/post_document_review_service.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def process_event(self, event: DocumentReviewUploadEvent) -> dict:
8686
except ClientError:
8787
raise DocumentReviewLambdaException(500, LambdaError.DocumentReviewDB)
8888

89+
8990
def create_response(
9091
self, document_review_reference: DocumentUploadReviewReference
9192
) -> dict:

lambdas/tests/unit/handlers/test_post_document_review_handler.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@
3838
"documents": [],
3939
}
4040

41+
INVALID_EVENT_INVALID_FILE_EXTENSION = {
42+
"nhsNumber": TEST_NHS_NUMBER,
43+
"snomedCode": SnomedCodes.LLOYD_GEORGE.value.code,
44+
"documents": ["testFile.job"],
45+
}
46+
4147
TEST_PRESIGNED_URL_1 = "https://s3.amazonaws.com/presigned1?signature=abc123"
4248

4349

@@ -215,13 +221,21 @@ def test_validate_event_body_valid_event_returns_document_review_upload_event_mo
215221

216222

217223
def test_validate_event_body_throws_error_unsupported_snomed_code(invalid_event):
218-
invalid_event["body"] = INVALID_EVENT_UNSUPPORTED_SNOMED_CODE
224+
invalid_event["body"] = json.dumps(INVALID_EVENT_UNSUPPORTED_SNOMED_CODE)
219225
with pytest.raises(DocumentReviewLambdaException) as e:
220226
validate_event_body(invalid_event["body"])
221227
assert e.value.status_code == 400
222228
assert e.value.err_code == "UDR_4003"
223229

224230

231+
def test_validate_event_body_throws_error_unsupported_file_type(invalid_event):
232+
invalid_event["body"] = json.dumps(INVALID_EVENT_INVALID_FILE_EXTENSION)
233+
with pytest.raises(DocumentReviewLambdaException) as e:
234+
validate_event_body(invalid_event["body"])
235+
assert e.value.status_code == 400
236+
assert e.value.err_code == "DRV_4006"
237+
238+
225239
def test_lambda_handler_calls_service_with_validated_event(
226240
mock_service, context, mock_upload_document_iteration_3_enabled, valid_event
227241
):

lambdas/tests/unit/services/test_post_document_review_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,4 +293,4 @@ def test_create_response(mock_service):
293293
nhs_number=TEST_NHS_NUMBER,
294294
)
295295
)
296-
assert actual == expected
296+
assert actual == expected

lambdas/tests/unit/services/test_post_fhir_document_reference_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ def test_extract_author_from_fhir(
549549
],
550550
)
551551
def test_extract_author_from_fhir_raises_error(
552-
mock_post_fhir_doc_ref_service, mocker, fhir_author
552+
mock_fhir_doc_ref_base_service, mock_post_fhir_doc_ref_service, mocker, fhir_author
553553
):
554554
"""Test _extract_author_from_fhir method with malformed json returns Validation errors."""
555555
fhir_doc = mocker.MagicMock(spec=FhirDocumentReference)

lambdas/utils/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,7 @@ class ReviewProcessCreateRecordException(Exception):
218218

219219
class CorruptedFileException(Exception):
220220
pass
221+
222+
223+
class InvalidFileTypeException(Exception):
224+
pass

0 commit comments

Comments
 (0)