Skip to content

Commit 25b9e9f

Browse files
authored
VED-821 Refactor get by ID journey in line with cleaner design standards (#868)
1 parent 83a9491 commit 25b9e9f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+563
-418
lines changed

backend/src/controller/__init__.py

Whitespace-only changes.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""Utility module for interacting with the AWS API Gateway event provided to controllers"""
2+
from typing import Optional
3+
4+
from aws_lambda_typing.events import APIGatewayProxyEventV1
5+
6+
from controller.constants import SUPPLIER_SYSTEM_HEADER_NAME
7+
from models.errors import UnauthorizedError
8+
from utils import dict_utils
9+
10+
11+
def get_path_parameter(event: APIGatewayProxyEventV1, param_name: str) -> str:
12+
return dict_utils.get_field(
13+
event["pathParameters"],
14+
param_name,
15+
default=""
16+
)
17+
18+
19+
def get_supplier_system_header(event: APIGatewayProxyEventV1) -> str:
20+
"""Retrieves the supplier system header from the API Gateway event"""
21+
supplier_system: Optional[str] = dict_utils.get_field(dict(event), "headers", SUPPLIER_SYSTEM_HEADER_NAME)
22+
23+
if supplier_system is None:
24+
# SupplierSystem header must be provided for looking up permissions
25+
raise UnauthorizedError()
26+
27+
return supplier_system
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Utility module providing helper functions for dealing with response formats for AWS API Gateway"""
2+
import json
3+
from typing import Optional
4+
5+
6+
def create_response(
7+
status_code: int,
8+
body: Optional[dict | str] = None,
9+
headers: Optional[dict] = None
10+
):
11+
"""Creates response body as per Lambda -> API Gateway proxy integration"""
12+
if body is not None:
13+
if isinstance(body, dict):
14+
body = json.dumps(body)
15+
if headers:
16+
headers["Content-Type"] = "application/fhir+json"
17+
else:
18+
headers = {"Content-Type": "application/fhir+json"}
19+
20+
return {
21+
"statusCode": status_code,
22+
"headers": headers if headers else {},
23+
**({"body": body} if body else {}),
24+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""FHIR Controller constants"""
2+
3+
4+
SUPPLIER_SYSTEM_HEADER_NAME = "SupplierSystem"
5+
E_TAG_HEADER_NAME = "E-Tag"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""Module for the global FHIR API exception handler"""
2+
import functools
3+
import uuid
4+
from typing import Callable, Type
5+
6+
from clients import logger
7+
from constants import GENERIC_SERVER_ERROR_DIAGNOSTICS_MESSAGE
8+
from controller.aws_apig_response_utils import create_response
9+
from models.errors import UnauthorizedVaxError, UnauthorizedError, ResourceNotFoundError, create_operation_outcome, \
10+
Severity, Code
11+
12+
13+
_CUSTOM_EXCEPTION_TO_STATUS_MAP: dict[Type[Exception], int] = {
14+
UnauthorizedError: 403,
15+
UnauthorizedVaxError: 403,
16+
ResourceNotFoundError: 404
17+
}
18+
19+
20+
def fhir_api_exception_handler(function: Callable) -> Callable:
21+
"""Decorator to handle any expected FHIR API exceptions or unexpected exception and provide a valid response to
22+
the client"""
23+
24+
@functools.wraps(function)
25+
def wrapper(*args, **kwargs):
26+
try:
27+
return function(*args, **kwargs)
28+
except tuple(_CUSTOM_EXCEPTION_TO_STATUS_MAP) as exc:
29+
status_code = _CUSTOM_EXCEPTION_TO_STATUS_MAP[type(exc)]
30+
return create_response(status_code=status_code, body=exc.to_operation_outcome())
31+
except Exception: # pylint: disable = broad-exception-caught
32+
logger.exception("Unhandled exception")
33+
server_error = create_operation_outcome(
34+
resource_id=str(uuid.uuid4()),
35+
severity=Severity.error,
36+
code=Code.server_error,
37+
diagnostics=GENERIC_SERVER_ERROR_DIAGNOSTICS_MESSAGE,
38+
)
39+
return create_response(500, server_error)
40+
41+
return wrapper
42+

backend/src/fhir_batch_controller.py renamed to backend/src/controller/fhir_batch_controller.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Function to send the request directly to lambda (or return appropriate diagnostics if this is not possible)"""
22

3-
from fhir_batch_service import ImmunizationBatchService
4-
from fhir_batch_repository import ImmunizationBatchRepository
3+
from service.fhir_batch_service import ImmunizationBatchService
4+
from repository.fhir_batch_repository import ImmunizationBatchRepository
55

66

77
def make_batch_controller():

0 commit comments

Comments
 (0)