Skip to content

Commit f2d28d3

Browse files
committed
error handling
1 parent 12fc813 commit f2d28d3

File tree

3 files changed

+46
-50
lines changed

3 files changed

+46
-50
lines changed

services/web/server/src/simcore_service_webserver/users/_common/constants.py

Lines changed: 0 additions & 7 deletions
This file was deleted.

services/web/server/src/simcore_service_webserver/users/_users_rest.py

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import functools
21
import logging
32

43
from aiohttp import web
@@ -12,16 +11,19 @@
1211
parse_request_body_as,
1312
parse_request_query_parameters_as,
1413
)
15-
from servicelib.aiohttp.typing_extension import Handler
16-
from servicelib.logging_errors import create_troubleshotting_log_kwargs
1714
from servicelib.rest_constants import RESPONSE_MODEL_POLICY
1815

1916
from .._meta import API_VTAG
17+
from ..exception_handling import (
18+
ExceptionToHttpErrorMap,
19+
HttpErrorInfo,
20+
exception_handling_decorator,
21+
to_exceptions_handlers_map,
22+
)
2023
from ..login.decorators import login_required
2124
from ..security.decorators import permission_required
2225
from ..utils_aiohttp import envelope_json_response
2326
from . import _users_service, api
24-
from ._common.constants import FMSG_MISSING_CONFIG_WITH_OEC
2527
from ._common.schemas import PreRegisteredUserGet, UsersRequestContext
2628
from .exceptions import (
2729
AlreadyPreRegisteredError,
@@ -33,35 +35,38 @@
3335
_logger = logging.getLogger(__name__)
3436

3537

36-
routes = web.RouteTableDef()
37-
38-
39-
def _handle_users_exceptions(handler: Handler):
40-
@functools.wraps(handler)
41-
async def wrapper(request: web.Request) -> web.StreamResponse:
42-
try:
43-
return await handler(request)
44-
45-
except UserNotFoundError as exc:
46-
raise web.HTTPNotFound(reason=f"{exc}") from exc
38+
_TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = {
39+
UserNotFoundError: HttpErrorInfo(
40+
status.HTTP_404_NOT_FOUND,
41+
"This user cannot be found. Either it is not registered or has enabled privacy settings.",
42+
),
43+
UserNameDuplicateError: HttpErrorInfo(
44+
status.HTTP_409_CONFLICT,
45+
"Username '{user_name}' is already taken. "
46+
"Consider '{alternative_user_name}' instead.",
47+
),
48+
AlreadyPreRegisteredError: HttpErrorInfo(
49+
status.HTTP_409_CONFLICT,
50+
"Found {num_found} matches for '{email}'. Cannot pre-register existing user",
51+
),
52+
MissingGroupExtraPropertiesForProductError: HttpErrorInfo(
53+
status.HTTP_503_SERVICE_UNAVAILABLE,
54+
"The product is not ready for use until the configuration is fully completed. "
55+
"Please wait and try again. "
56+
"If this issue persists, contact support indicating this support code: {error_code}.",
57+
),
58+
}
59+
60+
_handle_users_exceptions = exception_handling_decorator(
61+
to_exceptions_handlers_map(_TO_HTTP_ERROR_MAP)
62+
)
4763

48-
except UserNameDuplicateError as exc:
49-
raise web.HTTPConflict(reason=f"{exc}") from exc
5064

51-
except MissingGroupExtraPropertiesForProductError as exc:
52-
error_code = exc.error_code()
53-
user_error_msg = FMSG_MISSING_CONFIG_WITH_OEC.format(error_code=error_code)
54-
_logger.exception(
55-
**create_troubleshotting_log_kwargs(
56-
user_error_msg,
57-
error=exc,
58-
error_code=error_code,
59-
tip="Row in `groups_extra_properties` for this product is missing.",
60-
)
61-
)
62-
raise web.HTTPServiceUnavailable(reason=user_error_msg) from exc
65+
routes = web.RouteTableDef()
6366

64-
return wrapper
67+
#
68+
# MY PROFILE: /me
69+
#
6570

6671

6772
@routes.get(f"/{API_VTAG}/me", name="get_my_profile")
@@ -94,6 +99,10 @@ async def update_my_profile(request: web.Request) -> web.Response:
9499
return web.json_response(status=status.HTTP_204_NO_CONTENT)
95100

96101

102+
#
103+
# USERS (only POs)
104+
#
105+
97106
_RESPONSE_MODEL_MINIMAL_POLICY = RESPONSE_MODEL_POLICY.copy()
98107
_RESPONSE_MODEL_MINIMAL_POLICY["exclude_none"] = True
99108

@@ -127,12 +136,9 @@ async def pre_register_user(request: web.Request) -> web.Response:
127136
req_ctx = UsersRequestContext.model_validate(request)
128137
pre_user_profile = await parse_request_body_as(PreRegisteredUserGet, request)
129138

130-
try:
131-
user_profile = await _users_service.pre_register_user(
132-
request.app, profile=pre_user_profile, creator_user_id=req_ctx.user_id
133-
)
134-
return envelope_json_response(
135-
user_profile.model_dump(**_RESPONSE_MODEL_MINIMAL_POLICY)
136-
)
137-
except AlreadyPreRegisteredError as err:
138-
raise web.HTTPConflict(reason=f"{err}") from err
139+
user_profile = await _users_service.pre_register_user(
140+
request.app, profile=pre_user_profile, creator_user_id=req_ctx.user_id
141+
)
142+
return envelope_json_response(
143+
user_profile.model_dump(**_RESPONSE_MODEL_MINIMAL_POLICY)
144+
)

services/web/server/src/simcore_service_webserver/users/exceptions.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ def __init__(self, *, uid: int | None = None, email: str | None = None, **ctx: A
2222

2323

2424
class UserNameDuplicateError(UsersBaseError):
25-
msg_template = (
26-
"The username '{user_name}' is already taken. "
27-
"Consider using '{alternative_user_name}' instead."
28-
)
25+
msg_template = "username is a unique ID and cannot create a new as '{user_name}' since it already exists "
2926

3027

3128
class TokenNotFoundError(UsersBaseError):

0 commit comments

Comments
 (0)