Skip to content

Commit 88cc7cb

Browse files
committed
rest model knows about domain model but not the opposite
1 parent 48093f1 commit 88cc7cb

File tree

4 files changed

+39
-52
lines changed

4 files changed

+39
-52
lines changed

packages/models-library/src/models_library/api_schemas_webserver/workspaces.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from datetime import datetime
2-
from typing import NamedTuple
2+
from typing import Self
33

44
from models_library.basic_types import IDStr
55
from models_library.groups import GroupID
66
from models_library.workspaces import WorkspaceID
7-
from pydantic import ConfigDict, PositiveInt
7+
from pydantic import ConfigDict
88

99
from ..access_rights import AccessRights
1010
from ..users import UserID
11+
from ..workspaces import UserWorkspaceAccessRightsDB, WorkspaceID
1112
from ._base import InputSchema, OutputSchema
1213

1314

@@ -23,10 +24,20 @@ class WorkspaceGet(OutputSchema):
2324
my_access_rights: AccessRights
2425
access_rights: dict[GroupID, AccessRights]
2526

26-
27-
class WorkspaceGetPage(NamedTuple):
28-
items: list[WorkspaceGet]
29-
total: PositiveInt
27+
@classmethod
28+
def from_model(cls, workspace_db: UserWorkspaceAccessRightsDB) -> Self:
29+
return cls(
30+
workspace_id=workspace_db.workspace_id,
31+
name=workspace_db.name,
32+
description=workspace_db.description,
33+
thumbnail=workspace_db.thumbnail,
34+
created_at=workspace_db.created,
35+
modified_at=workspace_db.modified,
36+
trashed_at=workspace_db.trashed,
37+
trashed_by=workspace_db.trashed_by if workspace_db.trashed else None,
38+
my_access_rights=workspace_db.my_access_rights,
39+
access_rights=workspace_db.access_rights,
40+
)
3041

3142

3243
class WorkspaceCreateBodyParams(InputSchema):

services/web/server/src/simcore_service_webserver/workspaces/_workspaces_rest.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
from models_library.api_schemas_webserver.workspaces import (
55
WorkspaceCreateBodyParams,
66
WorkspaceGet,
7-
WorkspaceGetPage,
87
WorkspaceReplaceBodyParams,
98
)
109
from models_library.rest_ordering import OrderBy
1110
from models_library.rest_pagination import Page
1211
from models_library.rest_pagination_utils import paginate_data
12+
from models_library.workspaces import UserWorkspaceAccessRightsDB
1313
from servicelib.aiohttp import status
1414
from servicelib.aiohttp.requests_validation import (
1515
parse_request_body_as,
@@ -46,7 +46,7 @@ async def create_workspace(request: web.Request):
4646
req_ctx = WorkspacesRequestContext.model_validate(request)
4747
body_params = await parse_request_body_as(WorkspaceCreateBodyParams, request)
4848

49-
workspace: WorkspaceGet = await _workspaces_service.create_workspace(
49+
workspace: UserWorkspaceAccessRightsDB = await _workspaces_service.create_workspace(
5050
request.app,
5151
user_id=req_ctx.user_id,
5252
name=body_params.name,
@@ -55,7 +55,7 @@ async def create_workspace(request: web.Request):
5555
product_name=req_ctx.product_name,
5656
)
5757

58-
return envelope_json_response(workspace, web.HTTPCreated)
58+
return envelope_json_response(WorkspaceGet.from_model(workspace), web.HTTPCreated)
5959

6060

6161
@routes.get(f"/{VTAG}/workspaces", name="list_workspaces")
@@ -72,7 +72,7 @@ async def list_workspaces(request: web.Request):
7272
query_params.filters = WorkspacesFilters()
7373

7474
assert query_params.filters
75-
workspaces: WorkspaceGetPage = await _workspaces_service.list_workspaces(
75+
total_count, workspaces = await _workspaces_service.list_workspaces(
7676
app=request.app,
7777
user_id=req_ctx.user_id,
7878
product_name=req_ctx.product_name,
@@ -85,9 +85,9 @@ async def list_workspaces(request: web.Request):
8585

8686
page = Page[WorkspaceGet].model_validate(
8787
paginate_data(
88-
chunk=workspaces.items,
88+
chunk=[WorkspaceGet.from_model(w) for w in workspaces],
8989
request_url=request.url,
90-
total=workspaces.total,
90+
total=total_count,
9191
limit=query_params.limit,
9292
offset=query_params.offset,
9393
)
@@ -106,14 +106,14 @@ async def get_workspace(request: web.Request):
106106
req_ctx = WorkspacesRequestContext.model_validate(request)
107107
path_params = parse_request_path_parameters_as(WorkspacesPathParams, request)
108108

109-
workspace: WorkspaceGet = await _workspaces_service.get_workspace(
109+
workspace = await _workspaces_service.get_workspace(
110110
app=request.app,
111111
workspace_id=path_params.workspace_id,
112112
user_id=req_ctx.user_id,
113113
product_name=req_ctx.product_name,
114114
)
115115

116-
return envelope_json_response(workspace)
116+
return envelope_json_response(WorkspaceGet.from_model(workspace))
117117

118118

119119
@routes.put(
@@ -128,14 +128,14 @@ async def replace_workspace(request: web.Request):
128128
path_params = parse_request_path_parameters_as(WorkspacesPathParams, request)
129129
body_params = await parse_request_body_as(WorkspaceReplaceBodyParams, request)
130130

131-
workspace: WorkspaceGet = await _workspaces_service.update_workspace(
131+
workspace = await _workspaces_service.update_workspace(
132132
app=request.app,
133133
user_id=req_ctx.user_id,
134134
workspace_id=path_params.workspace_id,
135135
product_name=req_ctx.product_name,
136136
**body_params.model_dump(),
137137
)
138-
return envelope_json_response(workspace)
138+
return envelope_json_response(WorkspaceGet.from_model(workspace))
139139

140140

141141
@routes.delete(

services/web/server/src/simcore_service_webserver/workspaces/_workspaces_service.py

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
import logging
44

55
from aiohttp import web
6-
from models_library.api_schemas_webserver.workspaces import (
7-
WorkspaceGet,
8-
WorkspaceGetPage,
9-
)
106
from models_library.products import ProductName
117
from models_library.rest_ordering import OrderBy
128
from models_library.users import UserID
@@ -25,21 +21,6 @@
2521
_logger = logging.getLogger(__name__)
2622

2723

28-
def _to_api_model(workspace_db: UserWorkspaceAccessRightsDB) -> WorkspaceGet:
29-
return WorkspaceGet(
30-
workspace_id=workspace_db.workspace_id,
31-
name=workspace_db.name,
32-
description=workspace_db.description,
33-
thumbnail=workspace_db.thumbnail,
34-
created_at=workspace_db.created,
35-
modified_at=workspace_db.modified,
36-
trashed_at=workspace_db.trashed,
37-
trashed_by=workspace_db.trashed_by if workspace_db.trashed else None,
38-
my_access_rights=workspace_db.my_access_rights,
39-
access_rights=workspace_db.access_rights,
40-
)
41-
42-
4324
async def create_workspace(
4425
app: web.Application,
4526
*,
@@ -48,7 +29,7 @@ async def create_workspace(
4829
description: str | None,
4930
thumbnail: str | None,
5031
product_name: ProductName,
51-
) -> WorkspaceGet:
32+
) -> UserWorkspaceAccessRightsDB:
5233
user = await get_user(app, user_id=user_id)
5334

5435
created_workspace_db = await db.create_workspace(
@@ -59,13 +40,12 @@ async def create_workspace(
5940
description=description,
6041
thumbnail=thumbnail,
6142
)
62-
workspace_db = await db.get_workspace_for_user(
43+
return await db.get_workspace_for_user(
6344
app,
6445
user_id=user_id,
6546
workspace_id=created_workspace_db.workspace_id,
6647
product_name=product_name,
6748
)
68-
return _to_api_model(workspace_db)
6949

7050

7151
async def get_workspace(
@@ -74,15 +54,14 @@ async def get_workspace(
7454
user_id: UserID,
7555
workspace_id: WorkspaceID,
7656
product_name: ProductName,
77-
) -> WorkspaceGet:
78-
workspace_db = await check_user_workspace_access(
57+
) -> UserWorkspaceAccessRightsDB:
58+
return await check_user_workspace_access(
7959
app=app,
8060
user_id=user_id,
8161
workspace_id=workspace_id,
8262
product_name=product_name,
8363
permission="read",
8464
)
85-
return _to_api_model(workspace_db)
8665

8766

8867
async def list_workspaces(
@@ -95,7 +74,7 @@ async def list_workspaces(
9574
offset: NonNegativeInt,
9675
limit: int,
9776
order_by: OrderBy,
98-
) -> WorkspaceGetPage:
77+
) -> tuple[int, list[UserWorkspaceAccessRightsDB]]:
9978
total_count, workspaces = await db.list_workspaces_for_user(
10079
app,
10180
user_id=user_id,
@@ -107,10 +86,7 @@ async def list_workspaces(
10786
order_by=order_by,
10887
)
10988

110-
return WorkspaceGetPage(
111-
items=[_to_api_model(workspace_db) for workspace_db in workspaces],
112-
total=total_count,
113-
)
89+
return total_count, workspaces
11490

11591

11692
async def update_workspace(
@@ -120,7 +96,7 @@ async def update_workspace(
12096
user_id: UserID,
12197
workspace_id: WorkspaceID,
12298
**updates,
123-
) -> WorkspaceGet:
99+
) -> UserWorkspaceAccessRightsDB:
124100

125101
await check_user_workspace_access(
126102
app=app,
@@ -135,13 +111,12 @@ async def update_workspace(
135111
product_name=product_name,
136112
updates=WorkspaceUpdateDB(**updates),
137113
)
138-
workspace_db = await db.get_workspace_for_user(
114+
return await db.get_workspace_for_user(
139115
app,
140116
user_id=user_id,
141117
workspace_id=workspace_id,
142118
product_name=product_name,
143119
)
144-
return _to_api_model(workspace_db)
145120

146121

147122
async def delete_workspace(

services/web/server/tests/unit/with_dbs/02/test_projects_crud_handlers__clone_in_workspace_and_folder.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
# pylint: disable=unused-argument
44
# pylint: disable=unused-variable
55

6-
from collections.abc import Iterator
76
from copy import deepcopy
8-
from typing import Any
7+
from typing import Any, AsyncIterator
98

109
import pytest
1110
import sqlalchemy as sa
@@ -30,7 +29,9 @@
3029
@pytest.fixture
3130
async def create_workspace_and_folder(
3231
client: TestClient, logged_user: UserInfoDict, postgres_db: sa.engine.Engine
33-
) -> Iterator[tuple[WorkspaceID, FolderID]]:
32+
) -> AsyncIterator[tuple[WorkspaceID, FolderID]]:
33+
assert client.app
34+
3435
workspace = await create_workspace(
3536
client.app,
3637
user_id=logged_user["id"],

0 commit comments

Comments
 (0)