Skip to content

Commit 4b8bf12

Browse files
committed
error handling in states rest
1 parent 7513aea commit 4b8bf12

File tree

2 files changed

+15
-48
lines changed

2 files changed

+15
-48
lines changed

services/web/server/src/simcore_service_webserver/projects/_common/exception_handlers.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
ProjectDeleteError,
2323
ProjectGroupNotFoundError,
2424
ProjectInDebtCanNotChangeWalletError,
25+
ProjectInDebtCanNotOpenError,
2526
ProjectInvalidRightsError,
2627
ProjectInvalidUsageError,
2728
ProjectNodeRequiredInputsNotSetError,
2829
ProjectNotFoundError,
2930
ProjectOwnerNotFoundInTheProjectAccessRightsError,
3031
ProjectStartsTooManyDynamicNodesError,
32+
ProjectTooManyProjectOpenedError,
3133
WrongTagIdsInQueryError,
3234
)
3335

@@ -77,6 +79,10 @@
7779
status.HTTP_400_BAD_REQUEST,
7880
"Project owner identifier was not found in the project's access-rights field",
7981
),
82+
ProjectTooManyProjectOpenedError: HttpErrorInfo(
83+
status.HTTP_409_CONFLICT,
84+
"You cannot open more than {max_num_projects} study/ies at once. Please close another study and retry.",
85+
),
8086
WorkspaceAccessForbiddenError: HttpErrorInfo(
8187
status.HTTP_403_FORBIDDEN,
8288
"Access to workspace forbidden: {reason}",
@@ -109,6 +115,10 @@
109115
status.HTTP_402_PAYMENT_REQUIRED,
110116
"Unable to change the credit account linked to the project. The project is embargoed because the last transaction of {debt_amount} resulted in the credit account going negative.",
111117
),
118+
ProjectInDebtCanNotOpenError: HttpErrorInfo(
119+
status.HTTP_402_PAYMENT_REQUIRED,
120+
"Unable to open the project. The project is embargoed because the last transaction of {debt_amount} resulted in the credit account going negative.",
121+
),
112122
ProjectStartsTooManyDynamicNodesError: HttpErrorInfo(
113123
status.HTTP_409_CONFLICT,
114124
"The maximal amount of concurrently running dynamic services was reached. Please manually stop a service and retry.",

services/web/server/src/simcore_service_webserver/projects/_states_handlers.py

Lines changed: 5 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""handlers for project states"""
22

33
import contextlib
4-
import functools
54
import json
65
import logging
76

@@ -14,7 +13,6 @@
1413
parse_request_path_parameters_as,
1514
parse_request_query_parameters_as,
1615
)
17-
from servicelib.aiohttp.typing_extension import Handler
1816
from servicelib.aiohttp.web_exceptions_extension import HTTPLockedError
1917
from servicelib.common_headers import (
2018
UNDEFINED_DEFAULT_SIMCORE_USER_AGENT_VALUE,
@@ -28,63 +26,21 @@
2826
from ..login.decorators import login_required
2927
from ..notifications import project_logs
3028
from ..products.api import Product, get_current_product
31-
from ..resource_usage.errors import DefaultPricingPlanNotFoundError
3229
from ..security.decorators import permission_required
3330
from ..users import api
34-
from ..users.exceptions import UserDefaultWalletNotFoundError
3531
from ..utils_aiohttp import envelope_json_response
36-
from ..wallets.errors import WalletNotEnoughCreditsError
3732
from . import api as projects_api
3833
from . import projects_service
34+
from ._common.exception_handlers import handle_plugin_requests_exceptions
3935
from ._common.models import ProjectPathParams, RequestContext
40-
from .exceptions import (
41-
DefaultPricingUnitNotFoundError,
42-
ProjectInDebtCanNotChangeWalletError,
43-
ProjectInDebtCanNotOpenError,
44-
ProjectInvalidRightsError,
45-
ProjectNotFoundError,
46-
ProjectStartsTooManyDynamicNodesError,
47-
ProjectTooManyProjectOpenedError,
48-
)
36+
from .exceptions import ProjectStartsTooManyDynamicNodesError
4937

5038
_logger = logging.getLogger(__name__)
5139

5240

5341
routes = web.RouteTableDef()
5442

5543

56-
def _handle_project_exceptions(handler: Handler):
57-
"""Transforms common project errors -> http errors"""
58-
59-
@functools.wraps(handler)
60-
async def _wrapper(request: web.Request) -> web.StreamResponse:
61-
try:
62-
return await handler(request)
63-
64-
except (
65-
ProjectNotFoundError,
66-
UserDefaultWalletNotFoundError,
67-
DefaultPricingPlanNotFoundError,
68-
DefaultPricingUnitNotFoundError,
69-
) as exc:
70-
raise web.HTTPNotFound(reason=f"{exc}") from exc
71-
72-
except ProjectInvalidRightsError as exc:
73-
raise web.HTTPForbidden(reason=f"{exc}") from exc
74-
75-
except ProjectTooManyProjectOpenedError as exc:
76-
raise web.HTTPConflict(reason=f"{exc}") from exc
77-
78-
except (
79-
WalletNotEnoughCreditsError,
80-
ProjectInDebtCanNotChangeWalletError,
81-
ProjectInDebtCanNotOpenError,
82-
) as exc:
83-
raise web.HTTPPaymentRequired(reason=f"{exc}") from exc
84-
85-
return _wrapper
86-
87-
8844
#
8945
# open project: custom methods https://google.aip.dev/136
9046
#
@@ -97,7 +53,7 @@ class _OpenProjectQuery(BaseModel):
9753
@routes.post(f"/{VTAG}/projects/{{project_id}}:open", name="open_project")
9854
@login_required
9955
@permission_required("project.open")
100-
@_handle_project_exceptions
56+
@handle_plugin_requests_exceptions
10157
async def open_project(request: web.Request) -> web.Response:
10258
req_ctx = RequestContext.model_validate(request)
10359
path_params = parse_request_path_parameters_as(ProjectPathParams, request)
@@ -208,7 +164,7 @@ async def open_project(request: web.Request) -> web.Response:
208164
@routes.post(f"/{VTAG}/projects/{{project_id}}:close", name="close_project")
209165
@login_required
210166
@permission_required("project.close")
211-
@_handle_project_exceptions
167+
@handle_plugin_requests_exceptions
212168
async def close_project(request: web.Request) -> web.Response:
213169
req_ctx = RequestContext.model_validate(request)
214170
path_params = parse_request_path_parameters_as(ProjectPathParams, request)
@@ -247,6 +203,7 @@ async def close_project(request: web.Request) -> web.Response:
247203
@routes.get(f"/{VTAG}/projects/{{project_id}}/state", name="get_project_state")
248204
@login_required
249205
@permission_required("project.read")
206+
@handle_plugin_requests_exceptions
250207
async def get_project_state(request: web.Request) -> web.Response:
251208
req_ctx = RequestContext.model_validate(request)
252209
path_params = parse_request_path_parameters_as(ProjectPathParams, request)

0 commit comments

Comments
 (0)