From bf6aa50b8cc8d52ea3097d0a4bee40a4ce9e2550 Mon Sep 17 00:00:00 2001 From: johnwilliams57-nhs <108133809+johnwilliams57-nhs@users.noreply.github.com> Date: Wed, 14 Feb 2024 17:13:31 +0000 Subject: [PATCH] spinecore-3594: moving mailbox info to a separate router/handler and removing old routes --- .vscode/settings.json | 2 +- src/mesh_sandbox/api.py | 8 +++++ src/mesh_sandbox/handlers/admin.py | 10 +----- src/mesh_sandbox/handlers/mailbox_info.py | 20 +++++++++++ src/mesh_sandbox/routers/admin.py | 30 ++-------------- src/mesh_sandbox/routers/mailbox_info.py | 38 ++++++++++++++++++++ src/mesh_sandbox/tests/admin.py | 25 ------------- src/mesh_sandbox/tests/mailbox_info_tests.py | 29 +++++++++++++++ src/mesh_sandbox/views/lookup.py | 38 +++++++++++++++++++- 9 files changed, 136 insertions(+), 64 deletions(-) create mode 100644 src/mesh_sandbox/handlers/mailbox_info.py create mode 100644 src/mesh_sandbox/routers/mailbox_info.py create mode 100644 src/mesh_sandbox/tests/mailbox_info_tests.py diff --git a/.vscode/settings.json b/.vscode/settings.json index d742caf..1780e78 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,7 +2,7 @@ "editor.formatOnSave": true, "[python]": { "editor.codeActionsOnSave": { - "source.organizeImports": true + "source.organizeImports": "explicit" } }, "isort.args": [ diff --git a/src/mesh_sandbox/api.py b/src/mesh_sandbox/api.py index a643f6e..c00a6ca 100644 --- a/src/mesh_sandbox/api.py +++ b/src/mesh_sandbox/api.py @@ -12,6 +12,7 @@ inbox, inbox_count, lookup, + mailbox_info, outbox, tracking, update, @@ -125,3 +126,10 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE tags=["update"], responses={status.HTTP_403_FORBIDDEN: {"description": "Forbidden"}}, ) + +app.include_router( + mailbox_info.router, + prefix="/messageexchange/mailbox", + tags=["Mailbox"], + responses={status.HTTP_403_FORBIDDEN: {"description": "Forbidden"}}, +) diff --git a/src/mesh_sandbox/handlers/admin.py b/src/mesh_sandbox/handlers/admin.py index 72fbd4a..9aeea8f 100644 --- a/src/mesh_sandbox/handlers/admin.py +++ b/src/mesh_sandbox/handlers/admin.py @@ -5,7 +5,6 @@ from ..common.messaging import Messaging from ..dependencies import get_messaging -from ..models.mailbox import Mailbox from ..models.message import ( Message, MessageEvent, @@ -14,7 +13,7 @@ MessageStatus, MessageType, ) -from ..views.admin import AddMessageEventRequest, CreateReportRequest, MailboxDetails +from ..views.admin import AddMessageEventRequest, CreateReportRequest class AdminHandler: @@ -105,10 +104,3 @@ async def add_message_event( message = await self.messaging.add_message_event(message, event, background_tasks) return message - - async def get_mailbox_details(self, mailbox_id: str) -> MailboxDetails: - mailbox: Optional[Mailbox] = await self.messaging.get_mailbox(mailbox_id) - if not mailbox: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) - - return MailboxDetails.from_mailbox(mailbox) diff --git a/src/mesh_sandbox/handlers/mailbox_info.py b/src/mesh_sandbox/handlers/mailbox_info.py new file mode 100644 index 0000000..bf0cc5f --- /dev/null +++ b/src/mesh_sandbox/handlers/mailbox_info.py @@ -0,0 +1,20 @@ +from typing import Optional + +from fastapi import Depends, HTTPException, status + +from ..common.messaging import Messaging +from ..dependencies import get_messaging +from ..models.mailbox import Mailbox +from ..views.admin import MailboxDetails + + +class MailboxInfoHandler: + def __init__(self, messaging: Messaging = Depends(get_messaging)): + self.messaging = messaging + + async def get_mailbox_details(self, mailbox_id: str) -> MailboxDetails: + mailbox: Optional[Mailbox] = await self.messaging.get_mailbox(mailbox_id) + if not mailbox: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) + + return MailboxDetails.from_mailbox(mailbox) diff --git a/src/mesh_sandbox/routers/admin.py b/src/mesh_sandbox/routers/admin.py index bb7535d..5d06ed8 100644 --- a/src/mesh_sandbox/routers/admin.py +++ b/src/mesh_sandbox/routers/admin.py @@ -1,4 +1,4 @@ -from fastapi import APIRouter, BackgroundTasks, Depends, Path, Response, status +from fastapi import APIRouter, BackgroundTasks, Depends, Response, status from ..dependencies import ( EnvConfig, @@ -7,7 +7,7 @@ normalise_message_id_path, ) from ..handlers.admin import AdminHandler -from ..views.admin import AddMessageEventRequest, CreateReportRequest, MailboxDetails +from ..views.admin import AddMessageEventRequest, CreateReportRequest from .request_logging import RequestLoggingRoute router = APIRouter( @@ -109,29 +109,3 @@ async def add_message_event( ): await handler.add_message_event(message_id, new_event, background_tasks) return Response() - - -@router.get( - "/admin/mailbox/{mailbox_id}", - summary=f"Get mailbox details. {TESTING_ONLY}", - status_code=status.HTTP_200_OK, - response_model_exclude_none=True, -) -@router.get( - "/messageexchange/admin/mailbox/{mailbox_id}", - summary=f"Get mailbox details. {TESTING_ONLY}", - status_code=status.HTTP_200_OK, - response_model_exclude_none=True, -) -@router.get( - "/messageexchange/mailbox/{mailbox_id}", - summary="Get mailbox details.", - status_code=status.HTTP_200_OK, - response_model_exclude_none=True, -) -async def get_mailbox_details( - mailbox_id: str = Path(..., title="mailbox_id", description="The Mailbox ID of the mailbox to retrieve"), - handler: AdminHandler = Depends(AdminHandler), -) -> MailboxDetails: - mailbox = await handler.get_mailbox_details(mailbox_id) - return mailbox diff --git a/src/mesh_sandbox/routers/mailbox_info.py b/src/mesh_sandbox/routers/mailbox_info.py new file mode 100644 index 0000000..8186a35 --- /dev/null +++ b/src/mesh_sandbox/routers/mailbox_info.py @@ -0,0 +1,38 @@ +from fastapi import APIRouter, Depends, Path, status + +from ..common import MESH_MEDIA_TYPES +from ..handlers.mailbox_info import MailboxInfoHandler +from ..views.admin import MailboxDetails +from ..views.lookup import MailboxInfoView +from .request_logging import RequestLoggingRoute + +router = APIRouter( + route_class=RequestLoggingRoute, +) + + +@router.get( + "/{mailbox_id}", + summary="Get mailbox details.", + status_code=status.HTTP_200_OK, + response_model_exclude_none=True, + responses={ + status.HTTP_200_OK: { + "content": { + MESH_MEDIA_TYPES[2]: { + "schema": MailboxInfoView.schema(), + }, + MESH_MEDIA_TYPES[1]: { + "schema": MailboxInfoView.schema(), + }, + } + } + }, + openapi_extra={"spec_order": 610}, +) +async def get_mailbox_details( + mailbox_id: str = Path(..., title="mailbox_id", description="The Mailbox ID of the mailbox to retrieve"), + handler: MailboxInfoHandler = Depends(MailboxInfoHandler), +) -> MailboxDetails: + mailbox = await handler.get_mailbox_details(mailbox_id) + return mailbox diff --git a/src/mesh_sandbox/tests/admin.py b/src/mesh_sandbox/tests/admin.py index 60b2fed..1663c5b 100644 --- a/src/mesh_sandbox/tests/admin.py +++ b/src/mesh_sandbox/tests/admin.py @@ -337,28 +337,3 @@ def test_add_message_event(app: TestClient, tmp_path: str): ) messages = res.json().get("messages", []) assert messages == [message_id] - - -@pytest.mark.parametrize("root_path", ["/admin/mailbox", "/messageexchange/admin/mailbox", "/messageexchange/mailbox"]) -def test_get_mailbox_invalid_mailbox_returns_404(app: TestClient, root_path: str): - with temp_env_vars(STORE_MODE="canned"): - res = app.get(f"{root_path}/NotAMailboxId") - assert res.status_code == status.HTTP_404_NOT_FOUND - - -@pytest.mark.parametrize("root_path", ["/admin/mailbox", "/messageexchange/admin/mailbox", "/messageexchange/mailbox"]) -def test_get_mailbox_happy_path(app: TestClient, root_path: str): - with temp_env_vars(STORE_MODE="canned"): - res = app.get(f"{root_path}/{_CANNED_MAILBOX1}") - assert res.status_code == status.HTTP_200_OK - - get_mailbox = res.json() - assert len(get_mailbox) == 7 - - assert get_mailbox["mailbox_id"] == _CANNED_MAILBOX1 - assert get_mailbox["mailbox_name"] == "TESTMB1" - assert get_mailbox["billing_entity"] == "England" - assert get_mailbox["ods_code"] == "X26" - assert get_mailbox["org_code"] == "X26" - assert get_mailbox["org_name"] == "" - assert get_mailbox["active"] is True diff --git a/src/mesh_sandbox/tests/mailbox_info_tests.py b/src/mesh_sandbox/tests/mailbox_info_tests.py new file mode 100644 index 0000000..b74217b --- /dev/null +++ b/src/mesh_sandbox/tests/mailbox_info_tests.py @@ -0,0 +1,29 @@ +from fastapi import status +from fastapi.testclient import TestClient + +from mesh_sandbox.tests import _CANNED_MAILBOX1 + +from .helpers import temp_env_vars + + +def test_get_mailbox_invalid_mailbox_returns_404(app: TestClient): + with temp_env_vars(STORE_MODE="canned"): + res = app.get("/messageexchange/mailbox/NotAMailboxId") + assert res.status_code == status.HTTP_404_NOT_FOUND + + +def test_get_mailbox_happy_path(app: TestClient): + with temp_env_vars(STORE_MODE="canned"): + res = app.get(f"/messageexchange/mailbox/{_CANNED_MAILBOX1}") + assert res.status_code == status.HTTP_200_OK + + get_mailbox = res.json() + assert len(get_mailbox) == 7 + + assert get_mailbox["mailbox_id"] == _CANNED_MAILBOX1 + assert get_mailbox["mailbox_name"] == "TESTMB1" + assert get_mailbox["billing_entity"] == "England" + assert get_mailbox["ods_code"] == "X26" + assert get_mailbox["org_code"] == "X26" + assert get_mailbox["org_name"] == "" + assert get_mailbox["active"] is True diff --git a/src/mesh_sandbox/views/lookup.py b/src/mesh_sandbox/views/lookup.py index 255058f..ae2439d 100644 --- a/src/mesh_sandbox/views/lookup.py +++ b/src/mesh_sandbox/views/lookup.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Optional, Union from uuid import uuid4 from pydantic import BaseModel, Field # pylint: disable=no-name-in-module @@ -85,3 +85,39 @@ def workflow_search_response(mailboxes: list[Mailbox], model_version: int = 1) - for mailbox in mailboxes ] ) + + +class MailboxInfoView(BaseModel): + mailbox_id: str + mailbox_name: str + active: bool + billing_entity: Optional[str] = None + ods_code: Optional[str] = "" + org_code: Optional[str] = "" + org_name: Optional[str] = "" + + class Config: + title = "mailbox-info" + json_schema_extra = { + "example": { + "mailbox_id": "X26OT0ABC1", + "mailbox_name": "This is a mailbox for messages", + "active": True, + "billing_entity": "England", + "ods_code": "X26", + "org_code": "X36001", + "org_name": "SuperOrg", + } + } + + +def mailbox_info_response(mailbox: Mailbox, _accepts_api_version: int = 2) -> MailboxInfoView: + return MailboxInfoView( + mailbox_id=mailbox.mailbox_id, + mailbox_name=mailbox.mailbox_name, + active=mailbox.active, + billing_entity=mailbox.billing_entity, + ods_code=mailbox.ods_code, + org_code=mailbox.org_code, + org_name=mailbox.org_name, + )