Skip to content

Commit 74670b8

Browse files
committed
improves exception handling
1 parent ef5f023 commit 74670b8

File tree

4 files changed

+54
-21
lines changed

4 files changed

+54
-21
lines changed

services/invitations/src/simcore_service_invitations/api/_invitations.py

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
from typing import Annotated
33

4-
from fastapi import APIRouter, Depends, HTTPException, status
4+
from fastapi import APIRouter, Depends
55
from fastapi.security import HTTPBasicCredentials
66
from models_library.api_schemas_invitations.invitations import (
77
ApiEncryptedInvitation,
@@ -12,7 +12,7 @@
1212

1313
from ..core.settings import ApplicationSettings
1414
from ..services.invitations import (
15-
InvalidInvitationCodeError,
15+
InvitationContent,
1616
create_invitation_link_and_content,
1717
extract_invitation_code_from_query,
1818
extract_invitation_content,
@@ -71,18 +71,10 @@ async def extracts_invitation_from_code(
7171
):
7272
"""Decrypts the invitation code and returns its content"""
7373

74-
try:
75-
invitation = extract_invitation_content(
76-
invitation_code=extract_invitation_code_from_query(
77-
encrypted.invitation_url
78-
),
79-
secret_key=settings.INVITATIONS_SECRET_KEY.get_secret_value().encode(),
80-
default_product=settings.INVITATIONS_DEFAULT_PRODUCT,
81-
)
82-
except InvalidInvitationCodeError as err:
83-
raise HTTPException(
84-
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
85-
detail=INVALID_INVITATION_URL_MSG,
86-
) from err
74+
invitation: InvitationContent = extract_invitation_content(
75+
invitation_code=extract_invitation_code_from_query(encrypted.invitation_url),
76+
secret_key=settings.INVITATIONS_SECRET_KEY.get_secret_value().encode(),
77+
default_product=settings.INVITATIONS_DEFAULT_PRODUCT,
78+
)
8779

8880
return invitation

services/invitations/src/simcore_service_invitations/core/application.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
SUMMARY,
1616
)
1717
from ..api.routes import setup_api_routes
18+
from . import exceptions_handlers
1819
from .settings import ApplicationSettings
1920

2021

@@ -43,7 +44,7 @@ def create_app(settings: ApplicationSettings | None = None) -> FastAPI:
4344
setup_tracing(app, app.state.settings.INVITATIONS_TRACING, APP_NAME)
4445

4546
# ERROR HANDLERS
46-
# ... add here ...
47+
exceptions_handlers.setup(app)
4748

4849
# EVENTS
4950
async def _on_startup() -> None:
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import logging
2+
3+
from fastapi import FastAPI, Request, status
4+
from fastapi.responses import JSONResponse
5+
from servicelib.logging_errors import create_troubleshotting_log_kwargs
6+
7+
from ..services.invitations import InvalidInvitationCodeError
8+
9+
_logger = logging.getLogger(__name__)
10+
11+
INVALID_INVITATION_URL_MSG = "Invalid invitation link"
12+
13+
14+
def handle_invalid_invitation_code_error(request: Request, exception: Exception):
15+
assert isinstance(exception, InvalidInvitationCodeError) # nosec
16+
user_msg = INVALID_INVITATION_URL_MSG
17+
_logger.warning(
18+
**create_troubleshotting_log_kwargs(
19+
user_msg,
20+
error=exception,
21+
error_context={
22+
"request": f"{request}",
23+
"request.method": f"{request.method}",
24+
"request.path": f"{request.url.path}",
25+
},
26+
tip="Some invitation link is invalid. Note that the encryption key for generation/check must be the same!",
27+
)
28+
)
29+
30+
return JSONResponse(
31+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
32+
content={"detail": INVALID_INVITATION_URL_MSG},
33+
)
34+
35+
36+
def setup(app: FastAPI):
37+
app.add_exception_handler(
38+
InvalidInvitationCodeError, handle_invalid_invitation_code_error
39+
)

services/invitations/src/simcore_service_invitations/services/invitations.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,16 @@ def create_invitation_link_and_content(
118118
def extract_invitation_code_from_query(invitation_url: HttpUrl) -> str:
119119
"""Parses url and extracts invitation code from url's query"""
120120
if not invitation_url.fragment:
121-
raise InvalidInvitationCodeError
121+
msg = "Invalid link format: fragment missing"
122+
raise InvalidInvitationCodeError(msg)
122123

123124
try:
124125
query_params = dict(parse.parse_qsl(URL(invitation_url.fragment).query))
125126
invitation_code: str = query_params["invitation"]
126127
return invitation_code
127128
except KeyError as err:
128-
_logger.debug("Invalid invitation: %s", err)
129-
raise InvalidInvitationCodeError from err
129+
msg = "Invalid link format: fragment misses `invitation` link"
130+
raise InvalidInvitationCodeError(msg) from err
130131

131132

132133
def decrypt_invitation(
@@ -167,5 +168,5 @@ def extract_invitation_content(
167168
return content
168169

169170
except (InvalidToken, ValidationError, binascii.Error) as err:
170-
_logger.debug("Invalid code: %s", err)
171-
raise InvalidInvitationCodeError from err
171+
msg = "Failed while decripting"
172+
raise InvalidInvitationCodeError(msg) from err

0 commit comments

Comments
 (0)