Skip to content

Commit

Permalink
prmdr-242 refactor validtion service and add unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
NogaNHS committed Oct 10, 2023
1 parent b3bd130 commit 5ad95d7
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 32 deletions.
10 changes: 10 additions & 0 deletions lambdas/handlers/create_document_reference_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from utils.lambda_response import ApiGatewayResponse
from utils.utilities import validate_id

from services.lloyd_george_validator import validate_lg_files, LGInvalidFilesException, LGFileTypeException, LGFileNameException

sys.path.append(os.path.join(os.path.dirname(__file__)))

logger = logging.getLogger()
Expand Down Expand Up @@ -119,6 +121,7 @@ def lambda_handler(event, context):
return response

try:

s3_response = s3_service.create_document_presigned_url_handler(
document_reference.s3_bucket_name,
document_reference.nhs_number + "/" + document_reference.id,
Expand All @@ -135,6 +138,7 @@ def lambda_handler(event, context):
return response

try:
validate_lg_files(lg_documents)
dynamo_service = DynamoDBService()
if arf_documents:
logger.info("Writing ARF document references")
Expand All @@ -152,6 +156,12 @@ def lambda_handler(event, context):
500, "An error occurred when creating document reference", "POST"
).create_api_gateway_response()
return response
except (LGInvalidFilesException, LGFileTypeException, LGFileNameException) as e:
logger.error(e)
response = ApiGatewayResponse(
400, "One or more if the files is not valid", "POST"
).create_api_gateway_response()
return response

return ApiGatewayResponse(
200, json.dumps(url_responses), "POST"
Expand Down
18 changes: 1 addition & 17 deletions lambdas/models/nhs_document_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,15 @@
from typing import Any

from enums.metadata_field_names import DocumentReferenceMetadataFields
from pydantic import BaseModel, model_validator
from pydantic import BaseModel

from services.lloyd_george_validator import validate_lg_file_type, validate_file_name


class UploadRequestDocument(BaseModel):
fileName: str
contentType: str
docType: str

@model_validator(mode='before')
@classmethod
def validation_for_lg(cls, data: Any) -> Any:
if isinstance(data, dict):
file_name = data.get('fileName')
doc_type = data.get('docType')
content_type = data.get('contentType')
elif isinstance(data, UploadRequestDocument):
doc_type = data.docType
content_type = data.contentType
if doc_type == 'LG':
validate_lg_file_type(content_type)
validate_file_name(file_name)
return data


class NHSDocumentReference:
def __init__(
Expand Down
16 changes: 13 additions & 3 deletions lambdas/services/lloyd_george_validator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import re

from lambdas.models.nhs_document_reference import NHSDocumentReference


class LGFileTypeException(ValueError):
"""One or more of the files do not match the required file type"""
Expand All @@ -18,17 +20,25 @@ def validate_lg_file_type(file_type: str):
raise LGFileTypeException

def validate_file_name(name: str):
lg_regex = '[0-9]+of[0-9]+_Lloyd_George_Record_\\[[A-Za-z]+\\s[A-Za-z]+]_\\[[0-9]{10}]_\\[\\d\\d-\\d\\d-\\d\\d\\d\\d].pdf'
lg_regex = r'[0-9]+of[0-9]+_Lloyd_George_Record_\[[A-Za-z]+\s[A-Za-z]+]_\[[0-9]{10}]_\[\d\d-\d\d-\d\d\d\d].pdf'
if not re.fullmatch(lg_regex, name):
raise LGFileNameException

def check_for_duplicate_files(file_list: list[str]):
if len(file_list) > len(set(file_list)):
raise LGInvalidFilesException

def check_for_number_of_files_match_expected(file_name: str, total_files_number: str):
def check_for_number_of_files_match_expected(file_name: str, total_files_number: int):
lg_number_regex = 'of[0-9]+'
expected_number_of_files = re.search(lg_number_regex, file_name)
if expected_number_of_files and not expected_number_of_files.group()[2:] == total_files_number:
if expected_number_of_files and not expected_number_of_files.group()[2:] == str(total_files_number):
raise LGInvalidFilesException

def validate_lg_files(file_list: list[NHSDocumentReference]):
files_name_list = []
for doc in file_list:
check_for_number_of_files_match_expected(doc.file_name, len(file_list))
validate_lg_file_type(doc.content_type)
validate_file_name(doc.file_name)
files_name_list.append(doc.file_name)
check_for_duplicate_files(files_name_list)
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
TEST_NHS_NUMBER, TEST_OBJECT_KEY)
from tests.unit.helpers.data.create_document_reference import (
ARF_MOCK_EVENT_BODY, ARF_MOCK_RESPONSE, LG_AND_ARF_MOCK_RESPONSE,
LG_MOCK_EVENT_BODY, LG_MOCK_RESPONSE, MOCK_EVENT_BODY, LG_MOCK_BAD_EVENT_BODY)
LG_MOCK_EVENT_BODY, LG_MOCK_RESPONSE, MOCK_EVENT_BODY, LG_MOCK_BAD_FILE_TYPE_EVENT_BODY,
LG_MOCK_MISSING_FILES_EVENT_BODY, LG_MOCK_BAD_FILE_NAME_EVENT_BODY, LG_MOCK_DUPLICATE_FILES_EVENT_BODY)
from tests.unit.services.test_s3_service import MOCK_PRESIGNED_POST_RESPONSE
from utils.lambda_response import ApiGatewayResponse

Expand Down Expand Up @@ -265,14 +266,14 @@ def test_create_document_reference_arf_type_s3_ClientError_returns_500(
actual = lambda_handler(arf_type_event, context)
assert actual == expected


def test_invalid_file_type_for_lg_return_400(set_env, context):
@pytest.mark.parametrize("event_body", [LG_MOCK_BAD_FILE_TYPE_EVENT_BODY, LG_MOCK_MISSING_FILES_EVENT_BODY, LG_MOCK_BAD_FILE_NAME_EVENT_BODY, LG_MOCK_DUPLICATE_FILES_EVENT_BODY])
def test_invalid_file_type_for_lg_return_400(set_env, context, event_body):
expected = ApiGatewayResponse(
400,
"Failed to parse document upload request data",
"GET",
"One or more if the files is not valid",
"POST",
).create_api_gateway_response()
actual = lambda_handler({"body": json.dumps(LG_MOCK_BAD_EVENT_BODY)}, context)
actual = lambda_handler({"body": json.dumps(event_body)}, context)
assert actual == expected

def test_create_document_reference_unknown_document_type_returns_400(
Expand Down
59 changes: 53 additions & 6 deletions lambdas/tests/unit/helpers/data/create_document_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,33 +69,80 @@
"created": "2023-10-02T15:55:30.650Z",
}

LG_MOCK_BAD_EVENT_BODY = {
LG_MOCK_BAD_FILE_TYPE_EVENT_BODY = {
"resourceType": "DocumentReference",
"subject": {"identifier": {"value": TEST_NHS_NUMBER}},
"content": [
{
"attachment": [
{
"fileName": f"1of3_Lloyd_George_Record_[Joe Bloggs]_[{TEST_NHS_NUMBER}]_[25-12-2019].pdf",
"fileName": f"1of1_Lloyd_George_Record_[Joe Bloggs]_[{TEST_NHS_NUMBER}]_[25-12-2019].pdf",
"contentType": "text/plain",
"docType": "LG",
},
}
]
}
],
"created": "2023-10-02T15:55:30.650Z",
}

LG_MOCK_BAD_FILE_NAME_EVENT_BODY = {
"resourceType": "DocumentReference",
"subject": {"identifier": {"value": TEST_NHS_NUMBER}},
"content": [
{
"attachment": [
{
"fileName": f"2of3_Lloyd_George_Record_[Joe Bloggs]_[{TEST_NHS_NUMBER}]_[25-12-2019].pdf",
"fileName": f"1of1_BAD_NAME_[Joe Bloggs]_[{TEST_NHS_NUMBER}]_[25-12-2019].pdf",
"contentType": "application/pdf",
"docType": "LG",
},
}
]
}
],
"created": "2023-10-02T15:55:30.650Z",
}

LG_MOCK_MISSING_FILES_EVENT_BODY = {
"resourceType": "DocumentReference",
"subject": {"identifier": {"value": TEST_NHS_NUMBER}},
"content": [
{
"attachment": [
{
"fileName": f"3of3_Lloyd_George_Record_[Joe Bloggs]_[{TEST_NHS_NUMBER}]_[25-12-2019].pdf",
"fileName": f"1of3_Lloyd_George_Record_[Joe Bloggs]_[{TEST_NHS_NUMBER}]_[25-12-2019].pdf",
"contentType": "application/pdf",
"docType": "LG",
}
]
}
],
"created": "2023-10-02T15:55:30.650Z",
}

LG_MOCK_DUPLICATE_FILES_EVENT_BODY = {
"resourceType": "DocumentReference",
"subject": {"identifier": {"value": TEST_NHS_NUMBER}},
"content": [
{
"attachment": [
{
"fileName": f"1of2_Lloyd_George_Record_[Joe Bloggs]_[{TEST_NHS_NUMBER}]_[25-12-2019].pdf",
"contentType": "application/pdf",
"docType": "LG",
},
{
"fileName": f"1of2_Lloyd_George_Record_[Joe Bloggs]_[{TEST_NHS_NUMBER}]_[25-12-2019].pdf",
"contentType": "application/pdf",
"docType": "LG",
}
]
}
],
"created": "2023-10-02T15:55:30.650Z",
}


ARF_MOCK_EVENT_BODY = {
"resourceType": "DocumentReference",
"subject": {"identifier": {"value": TEST_NHS_NUMBER}},
Expand Down

0 comments on commit 5ad95d7

Please sign in to comment.