Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ default: help
help: ## This is a help message
@grep -E --no-filename '^[a-zA-Z-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-42s\033[0m %s\n", $$1, $$2}'

aws-login: ## Login to AWS. Usage: make aws-login AWS_PROFILE=<AWS_PROFILE>
aws sso login --profile $(PROFILE) && export AWS_PROFILE=$(PROFILE)

clean: clean-build clean-py clean-test

clean-build:
Expand Down Expand Up @@ -96,14 +99,19 @@ test-unit-collect:
cd ./lambdas && ./venv/bin/python3 -m pytest tests/unit --collect-only

env:
rm -rf lambdas/venv || true
python3 -m venv ./lambdas/venv
./lambdas/venv/bin/pip3 install --upgrade pip
./lambdas/venv/bin/pip3 install -r $(TEST_REQUIREMENTS) --no-cache-dir
./lambdas/venv/bin/pip3 install -r $(CORE_REQUIREMENTS) --no-cache-dir
./lambdas/venv/bin/pip3 install -r $(DATA_REQUIREMENTS) --no-cache-dir
./lambdas/venv/bin/pip3 install -r $(REPORTS_REQUIREMENTS) --no-cache-dir
./lambdas/venv/bin/pip3 install -r $(ALERTING_REQUIREMENTS) --no-cache-dir
@echo "Removing old venv."
@rm -rf lambdas/venv || true
@echo "Building new venv and installing requirements."
@python3 -m venv ./lambdas/venv
@./lambdas/venv/bin/pip3 install --upgrade pip
@./lambdas/venv/bin/pip3 install -r $(TEST_REQUIREMENTS) --no-cache-dir
@./lambdas/venv/bin/pip3 install -r $(CORE_REQUIREMENTS) --no-cache-dir
@./lambdas/venv/bin/pip3 install -r $(DATA_REQUIREMENTS) --no-cache-dir
@./lambdas/venv/bin/pip3 install -r $(REPORTS_REQUIREMENTS) --no-cache-dir
@./lambdas/venv/bin/pip3 install -r $(ALERTING_REQUIREMENTS) --no-cache-dir
@echo " "
@echo " "
@echo "Now activate your venv."

github_env:
rm -rf lambdas/venv || true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,6 @@
"requestContext": {},
}

MOCK_MTLS_VALID_EVENT = {
"httpMethod": "GET",
"headers": {},
"pathParameters": {"id": f"{SNOMED_CODE}~{TEST_UUID}"},
"body": None,
"requestContext": {
"accountId": "123456789012",
"apiId": "abc123",
"domainName": "api.example.com",
"identity": {
"sourceIp": "1.2.3.4",
"userAgent": "curl/7.64.1",
"clientCert": {
"clientCertPem": "-----BEGIN CERTIFICATE-----...",
"subjectDN": "CN=ndrclient.main.int.pdm.national.nhs.uk,O=NHS,C=UK",
"issuerDN": "CN=NHS Root CA,O=NHS,C=UK",
"serialNumber": "12:34:56",
"validity": {
"notBefore": "May 10 00:00:00 2024 GMT",
"notAfter": "May 10 00:00:00 2025 GMT",
},
},
},
},
}

MOCK_INVALID_EVENT_ID_MALFORMED = deepcopy(MOCK_CIS2_VALID_EVENT)
MOCK_INVALID_EVENT_ID_MALFORMED["pathParameters"]["id"] = f"~{TEST_UUID}"

Expand Down Expand Up @@ -171,40 +145,12 @@ def test_lambda_handler_happy_path_with_application_login(
)


def test_lambda_handler_happy_path_with_mtls_pdm_login(
set_env,
mock_document_service,
mock_search_patient_service,
context,
):
mock_document_service.create_document_reference_fhir_response.return_value = (
"test_document_reference"
)

response = lambda_handler(MOCK_MTLS_VALID_EVENT, context)

assert response["statusCode"] == 200
assert response["body"] == "test_document_reference"
# Verify correct method calls
mock_document_service.handle_get_document_reference_request.assert_called_once_with(
SNOMED_CODE, TEST_UUID
)
mock_document_service.create_document_reference_fhir_response.assert_called_once_with(
MOCK_DOCUMENT_REFERENCE
)


def test_extract_bearer_token(context):
context.function_name = "GetDocumentReference"
token = extract_bearer_token(MOCK_CIS2_VALID_EVENT, context)
assert token == f"Bearer {TEST_UUID}"


def test_extract_bearer_token_when_pdm(context):
token = extract_bearer_token(MOCK_MTLS_VALID_EVENT, context)
assert token is None


def test_extract_missing_bearer_token(context):
context.function_name = "GetDocumentReference"
event_without_auth = {"headers": {}}
Expand All @@ -220,12 +166,6 @@ def test_extract_document_parameters_valid():
assert snomed_code == SNOMED_CODE


def test_extract_document_parameters_valid_pdm():
document_id, snomed_code = extract_document_parameters(MOCK_MTLS_VALID_EVENT)
assert document_id == TEST_UUID
assert snomed_code == SNOMED_CODE


def test_extract_document_parameters_invalid():
with pytest.raises(GetFhirDocumentReferenceException) as e:
extract_document_parameters(MOCK_INVALID_EVENT_ID_MALFORMED)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import pytest
from enums.snomed_codes import SnomedCodes
from handlers.get_fhir_document_reference_handler import (
extract_document_parameters,
lambda_handler,
)
from models.document_reference import DocumentReference
from tests.unit.conftest import TEST_UUID
from tests.unit.helpers.data.dynamo.dynamo_responses import MOCK_SEARCH_RESPONSE
from utils.lambda_handler_utils import extract_bearer_token

SNOMED_CODE = SnomedCodes.PATIENT_DATA.value.code

MOCK_MTLS_VALID_EVENT = {
"httpMethod": "GET",
"headers": {},
"pathParameters": {"id": f"{SNOMED_CODE}~{TEST_UUID}"},
"body": None,
"requestContext": {
"accountId": "123456789012",
"apiId": "abc123",
"domainName": "api.example.com",
"identity": {
"sourceIp": "1.2.3.4",
"userAgent": "curl/7.64.1",
"clientCert": {
"clientCertPem": "-----BEGIN CERTIFICATE-----...",
"subjectDN": "CN=ndrclient.main.int.pdm.national.nhs.uk,O=NHS,C=UK",
"issuerDN": "CN=NHS Root CA,O=NHS,C=UK",
"serialNumber": "12:34:56",
"validity": {
"notBefore": "May 10 00:00:00 2024 GMT",
"notAfter": "May 10 00:00:00 2025 GMT",
},
},
},
},
}

MOCK_DOCUMENT_REFERENCE = DocumentReference.model_validate(
MOCK_SEARCH_RESPONSE["Items"][0]
)


@pytest.fixture
def mock_config_service(mocker):
mock_config = mocker.patch(
"handlers.get_fhir_document_reference_handler.DynamicConfigurationService"
)
mock_config_instance = mock_config.return_value
return mock_config_instance


@pytest.fixture
def mock_document_service(mocker):
mock_service = mocker.patch(
"handlers.get_fhir_document_reference_handler.GetFhirDocumentReferenceService"
)
mock_service_instance = mock_service.return_value
mock_service_instance.handle_get_document_reference_request.return_value = (
MOCK_DOCUMENT_REFERENCE
)
return mock_service_instance


def test_lambda_handler_happy_path_with_mtls_pdm_login(
set_env,
mock_document_service,
context,
):
mock_document_service.create_document_reference_fhir_response.return_value = (
"test_document_reference"
)

response = lambda_handler(MOCK_MTLS_VALID_EVENT, context)

assert response["statusCode"] == 200
assert response["body"] == "test_document_reference"
# Verify correct method calls
mock_document_service.handle_get_document_reference_request.assert_called_once_with(
SNOMED_CODE, TEST_UUID
)
mock_document_service.create_document_reference_fhir_response.assert_called_once_with(
MOCK_DOCUMENT_REFERENCE
)


def test_extract_bearer_token_when_pdm(context):
token = extract_bearer_token(MOCK_MTLS_VALID_EVENT, context)
assert token is None


def test_extract_document_parameters_valid_pdm():
document_id, snomed_code = extract_document_parameters(MOCK_MTLS_VALID_EVENT)
assert document_id == TEST_UUID
assert snomed_code == SNOMED_CODE
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import json

import pytest
from handlers.post_fhir_document_reference_handler import lambda_handler


@pytest.fixture
def valid_mtls_event():
return {
"body": json.dumps(
{
"resourceType": "DocumentReference",
"subject": {
"identifier": {
"system": "https://fhir.nhs.uk/Id/nhs-number",
"value": "9000000009",
}
},
}
),
"headers": json.dumps(
{
"Accept": "text/json",
"Host": "example.com",
}
),
"requestContext": json.dumps(
{
"accountId": "123456789012",
"apiId": "abc123",
"domainName": "api.example.com",
"identity": {
"sourceIp": "1.2.3.4",
"userAgent": "curl/7.64.1",
"clientCert": {
"clientCertPem": "-----BEGIN CERTIFICATE-----...",
"subjectDN": "CN=ndrclient.main.int.pdm.national.nhs.uk,O=NHS,C=UK",
"issuerDN": "CN=NHS Root CA,O=NHS,C=UK",
"serialNumber": "12:34:56",
"validity": {
"notBefore": "May 10 00:00:00 2024 GMT",
"notAfter": "May 10 00:00:00 2025 GMT",
},
},
},
}
),
}


@pytest.fixture
def mock_service(mocker):
mock_service = mocker.patch(
"handlers.post_fhir_document_reference_handler.PostFhirDocumentReferenceService"
)
mock_service_instance = mock_service.return_value
return mock_service_instance


def test_mtls_lambda_handler_success(valid_mtls_event, context, mock_service):
"""Test successful lambda execution."""
mock_response = {"resourceType": "DocumentReference", "id": "test-id"}

mock_service.process_fhir_document_reference.return_value = json.dumps(
mock_response
)

result = lambda_handler(valid_mtls_event, context)

assert result["statusCode"] == 200
assert json.loads(result["body"]) == mock_response

mock_service.process_fhir_document_reference.assert_called_once_with(
valid_mtls_event["body"], valid_mtls_event["requestContext"]
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,9 @@
from handlers.post_fhir_document_reference_handler import lambda_handler
from utils.lambda_exceptions import DocumentRefException

@pytest.fixture
def valid_event():
return {
"body": json.dumps(
{
"resourceType": "DocumentReference",
"subject": {
"identifier": {
"system": "https://fhir.nhs.uk/Id/nhs-number",
"value": "9000000009",
}
},
}
),
"headers": json.dumps(
{
"Accept": "text/json",
"Host": "example.com",
}
),
"requestContext": json.dumps(
{
"accountId": "123456789012",
"apiId": "abc123",
"domainName": "api.example.com",
"identity": {
"sourceIp": "1.2.3.4",
"userAgent": "curl/7.64.1",
},
}
),
}


@pytest.fixture
def valid_mtls_event():
def valid_event():
return {
"body": json.dumps(
{
Expand All @@ -67,16 +34,6 @@ def valid_mtls_event():
"identity": {
"sourceIp": "1.2.3.4",
"userAgent": "curl/7.64.1",
"clientCert": {
"clientCertPem": "-----BEGIN CERTIFICATE-----...",
"subjectDN": "CN=ndrclient.main.int.pdm.national.nhs.uk,O=NHS,C=UK",
"issuerDN": "CN=NHS Root CA,O=NHS,C=UK",
"serialNumber": "12:34:56",
"validity": {
"notBefore": "May 10 00:00:00 2024 GMT",
"notAfter": "May 10 00:00:00 2025 GMT",
},
},
},
}
),
Expand Down Expand Up @@ -124,21 +81,3 @@ def test_lambda_handler_exception_handling(valid_event, context, mock_service):
mock_service.process_fhir_document_reference.assert_called_once_with(
valid_event["body"], valid_event["requestContext"]
)


def test_mtls_lambda_handler_success(valid_mtls_event, context, mock_service):
"""Test successful lambda execution."""
mock_response = {"resourceType": "DocumentReference", "id": "test-id"}

mock_service.process_fhir_document_reference.return_value = json.dumps(
mock_response
)

result = lambda_handler(valid_mtls_event, context)

assert result["statusCode"] == 200
assert json.loads(result["body"]) == mock_response

mock_service.process_fhir_document_reference.assert_called_once_with(
valid_mtls_event["body"], valid_mtls_event["requestContext"]
)
Loading
Loading