Skip to content
9 changes: 5 additions & 4 deletions lambdas/enums/lambda_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,10 @@ def create_error_body(self, params: Optional[dict] = None, **kwargs) -> str:
"err_code": "DRV_4005",
"message": "The NHS number provided is invalid",
}
DocumentReviewUnsupportedFileType = {
"err_code": "DRV_4006",
"message": "The file type provided is not supported",
}

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

DocumentReviewUploadForbidden = {
"err_code": "UDR_4031",
"message": "Forbidden"
}
DocumentReviewUploadForbidden = {"err_code": "UDR_4031", "message": "Forbidden"}

DocumentReviewPresignedFailure = {
"err_code": "UDR_5003",
Expand Down
7 changes: 6 additions & 1 deletion lambdas/handlers/post_document_review_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from utils.decorators.ensure_env_var import ensure_environment_variables
from utils.decorators.handle_lambda_exceptions import handle_lambda_exceptions
from utils.decorators.set_audit_arg import set_request_context_for_logging
from utils.exceptions import InvalidNhsNumberException
from utils.exceptions import InvalidNhsNumberException, InvalidFileTypeException
from utils.lambda_exceptions import DocumentReviewLambdaException
from utils.lambda_response import ApiGatewayResponse

Expand Down Expand Up @@ -60,3 +60,8 @@ def validate_event_body(body):
raise DocumentReviewLambdaException(
400, LambdaError.DocumentReviewUploadInvalidRequest
)
except InvalidFileTypeException as e:
logger.error(e)
raise DocumentReviewLambdaException(
400, LambdaError.DocumentReviewUnsupportedFileType
)
20 changes: 18 additions & 2 deletions lambdas/models/document_review.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import uuid
from datetime import datetime, timezone
from typing import Self

from enums.document_review_reason import DocumentReviewReason
from enums.document_review_status import DocumentReviewStatus
from enums.metadata_field_names import DocumentReferenceMetadataFields
from enums.upload_forbidden_file_extensions import is_file_type_allowed
from enums.snomed_codes import SnomedCodes
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator, ValidationError
from pydantic.alias_generators import to_camel, to_pascal
from utils.exceptions import InvalidNhsNumberException
from utils.exceptions import InvalidNhsNumberException, ConfigNotFoundException, InvalidFileTypeException
from utils import upload_file_configs
from utils.utilities import validate_nhs_number


Expand Down Expand Up @@ -158,3 +161,16 @@ def check_snomed_code(cls, value) -> SnomedCodes | None:
def verify_nhs_number(cls, value) -> str | None:
if validate_nhs_number(value):
return value

@model_validator(mode="after")
def validate_file_extension(self) -> Self:
try:
accepted_file_types = upload_file_configs.get_config_by_snomed_code(self.snomed_code.code).accepted_file_types

for file in self.documents:
if not is_file_type_allowed(file, accepted_file_types):
raise InvalidFileTypeException("Invalid file extension.")
return self
except ConfigNotFoundException:
raise InvalidFileTypeException("Unable to find file configuration.")

1 change: 1 addition & 0 deletions lambdas/services/post_document_review_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def process_event(self, event: DocumentReviewUploadEvent) -> dict:
except ClientError:
raise DocumentReviewLambdaException(500, LambdaError.DocumentReviewDB)


def create_response(
self, document_review_reference: DocumentUploadReviewReference
) -> dict:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
"documents": [],
}

INVALID_EVENT_INVALID_FILE_EXTENSION = {
"nhsNumber": TEST_NHS_NUMBER,
"snomedCode": SnomedCodes.LLOYD_GEORGE.value.code,
"documents": ["testFile.job"],
}

TEST_PRESIGNED_URL_1 = "https://s3.amazonaws.com/presigned1?signature=abc123"


Expand Down Expand Up @@ -215,13 +221,21 @@ def test_validate_event_body_valid_event_returns_document_review_upload_event_mo


def test_validate_event_body_throws_error_unsupported_snomed_code(invalid_event):
invalid_event["body"] = INVALID_EVENT_UNSUPPORTED_SNOMED_CODE
invalid_event["body"] = json.dumps(INVALID_EVENT_UNSUPPORTED_SNOMED_CODE)
with pytest.raises(DocumentReviewLambdaException) as e:
validate_event_body(invalid_event["body"])
assert e.value.status_code == 400
assert e.value.err_code == "UDR_4003"


def test_validate_event_body_throws_error_unsupported_file_type(invalid_event):
invalid_event["body"] = json.dumps(INVALID_EVENT_INVALID_FILE_EXTENSION)
with pytest.raises(DocumentReviewLambdaException) as e:
validate_event_body(invalid_event["body"])
assert e.value.status_code == 400
assert e.value.err_code == "DRV_4006"


def test_lambda_handler_calls_service_with_validated_event(
mock_service, context, mock_upload_document_iteration_3_enabled, valid_event
):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,4 +293,4 @@ def test_create_response(mock_service):
nhs_number=TEST_NHS_NUMBER,
)
)
assert actual == expected
assert actual == expected
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ def test_extract_author_from_fhir(
],
)
def test_extract_author_from_fhir_raises_error(
mock_post_fhir_doc_ref_service, mocker, fhir_author
mock_fhir_doc_ref_base_service, mock_post_fhir_doc_ref_service, mocker, fhir_author
):
"""Test _extract_author_from_fhir method with malformed json returns Validation errors."""
fhir_doc = mocker.MagicMock(spec=FhirDocumentReference)
Expand Down
4 changes: 4 additions & 0 deletions lambdas/utils/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,7 @@ class ReviewProcessCreateRecordException(Exception):

class CorruptedFileException(Exception):
pass


class InvalidFileTypeException(Exception):
pass
Loading