Skip to content

Commit 6cd326d

Browse files
committed
domain models in folders
1 parent f70f1dc commit 6cd326d

File tree

6 files changed

+51
-48
lines changed

6 files changed

+51
-48
lines changed

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from datetime import datetime
2-
from typing import Annotated, NamedTuple, Self
2+
from typing import Annotated, Self
33

4-
from pydantic import ConfigDict, Field, PositiveInt, field_validator
4+
from pydantic import ConfigDict, Field, field_validator
55

66
from ..access_rights import AccessRights
77
from ..basic_types import IDStr
@@ -31,7 +31,7 @@ class FolderGet(OutputSchema):
3131
def from_domain_model(
3232
cls, folder_db: FolderDB, user_folder_access_rights: AccessRights
3333
) -> Self:
34-
return cls(
34+
return cls.model_construct(
3535
folder_id=folder_db.folder_id,
3636
parent_folder_id=folder_db.parent_folder_id,
3737
name=folder_db.name,
@@ -45,11 +45,6 @@ def from_domain_model(
4545
)
4646

4747

48-
class FolderGetPage(NamedTuple):
49-
items: list[FolderGet]
50-
total: PositiveInt
51-
52-
5348
class FolderCreateBodyParams(InputSchema):
5449
name: IDStr
5550
parent_folder_id: FolderID | None = None

packages/models-library/src/models_library/folders.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from datetime import datetime
22
from enum import auto
3-
from typing import TypeAlias
3+
from typing import NamedTuple, TypeAlias
44

55
from pydantic import BaseModel, ConfigDict, PositiveInt, ValidationInfo, field_validator
66

@@ -52,7 +52,7 @@ class FolderDB(BaseModel):
5252

5353
trashed: datetime | None
5454
trashed_by: UserID | None
55-
trashed_by_primary_gid: GroupID | None
55+
trashed_by_primary_gid: GroupID | None = None
5656
trashed_explicitly: bool
5757

5858
user_id: UserID | None # owner?
@@ -64,3 +64,8 @@ class UserFolderAccessRightsDB(FolderDB):
6464
my_access_rights: AccessRights
6565

6666
model_config = ConfigDict(from_attributes=True)
67+
68+
69+
class Folder(NamedTuple):
70+
folder_db: FolderDB
71+
my_access_rights: AccessRights

services/web/server/src/simcore_service_webserver/folders/_folders_rest.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
from models_library.api_schemas_webserver.folders_v2 import (
55
FolderCreateBodyParams,
66
FolderGet,
7-
FolderGetPage,
87
FolderReplaceBodyParams,
98
)
9+
from models_library.folders import Folder
1010
from models_library.rest_ordering import OrderBy
1111
from models_library.rest_pagination import ItemT, Page
1212
from models_library.rest_pagination_utils import paginate_data
@@ -54,7 +54,7 @@ async def create_folder(request: web.Request):
5454
req_ctx = FoldersRequestContext.model_validate(request)
5555
body_params = await parse_request_body_as(FolderCreateBodyParams, request)
5656

57-
folder = await _folders_service.create_folder(
57+
folder: Folder = await _folders_service.create_folder(
5858
request.app,
5959
user_id=req_ctx.user_id,
6060
name=body_params.name,
@@ -63,7 +63,10 @@ async def create_folder(request: web.Request):
6363
workspace_id=body_params.workspace_id,
6464
)
6565

66-
return envelope_json_response(folder, web.HTTPCreated)
66+
return envelope_json_response(
67+
FolderGet.from_domain_model(folder.folder_db, folder.my_access_rights),
68+
web.HTTPCreated,
69+
)
6770

6871

6972
@routes.get(f"/{VTAG}/folders", name="list_folders")
@@ -79,7 +82,7 @@ async def list_folders(request: web.Request):
7982
if not query_params.filters:
8083
query_params.filters = FolderFilters()
8184

82-
folders: FolderGetPage = await _folders_service.list_folders(
85+
folders, total_count = await _folders_service.list_folders(
8386
app=request.app,
8487
user_id=req_ctx.user_id,
8588
product_name=req_ctx.product_name,
@@ -93,9 +96,9 @@ async def list_folders(request: web.Request):
9396

9497
page = Page[FolderGet].model_validate(
9598
paginate_data(
96-
chunk=folders.items,
99+
chunk=[FolderGet.from_domain_model(*f) for f in folders],
97100
request_url=request.url,
98-
total=folders.total,
101+
total=total_count,
99102
limit=query_params.limit,
100103
offset=query_params.offset,
101104
)
@@ -116,7 +119,7 @@ async def list_folders_full_search(request: web.Request):
116119
if not query_params.filters:
117120
query_params.filters = FolderFilters()
118121

119-
folders: FolderGetPage = await _folders_service.list_folders_full_depth(
122+
folders, total_count = await _folders_service.list_folders_full_depth(
120123
app=request.app,
121124
user_id=req_ctx.user_id,
122125
product_name=req_ctx.product_name,
@@ -129,9 +132,9 @@ async def list_folders_full_search(request: web.Request):
129132

130133
page = Page[FolderGet].model_validate(
131134
paginate_data(
132-
chunk=folders.items,
135+
chunk=[FolderGet.from_domain_model(*f) for f in folders],
133136
request_url=request.url,
134-
total=folders.total,
137+
total=total_count,
135138
limit=query_params.limit,
136139
offset=query_params.offset,
137140
)
@@ -147,14 +150,15 @@ async def get_folder(request: web.Request):
147150
req_ctx = FoldersRequestContext.model_validate(request)
148151
path_params = parse_request_path_parameters_as(FoldersPathParams, request)
149152

150-
folder: FolderGet = await _folders_service.get_folder(
153+
folder: Folder = await _folders_service.get_folder(
151154
app=request.app,
152155
folder_id=path_params.folder_id,
153156
user_id=req_ctx.user_id,
154157
product_name=req_ctx.product_name,
155158
)
156-
157-
return envelope_json_response(folder)
159+
return envelope_json_response(
160+
FolderGet.from_domain_model(folder.folder_db, folder.my_access_rights)
161+
)
158162

159163

160164
@routes.put(
@@ -169,7 +173,7 @@ async def replace_folder(request: web.Request):
169173
path_params = parse_request_path_parameters_as(FoldersPathParams, request)
170174
body_params = await parse_request_body_as(FolderReplaceBodyParams, request)
171175

172-
folder = await _folders_service.update_folder(
176+
folder: Folder = await _folders_service.update_folder(
173177
app=request.app,
174178
user_id=req_ctx.user_id,
175179
folder_id=path_params.folder_id,

services/web/server/src/simcore_service_webserver/folders/_folders_service.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
from aiohttp import web
66
from models_library.access_rights import AccessRights
7-
from models_library.api_schemas_webserver.folders_v2 import FolderGet, FolderGetPage
8-
from models_library.folders import FolderID, FolderQuery, FolderScope
7+
from models_library.folders import Folder, FolderID, FolderQuery, FolderScope
98
from models_library.products import ProductName
109
from models_library.projects import ProjectID
1110
from models_library.rest_ordering import OrderBy
@@ -36,7 +35,7 @@ async def create_folder(
3635
parent_folder_id: FolderID | None,
3736
product_name: ProductName,
3837
workspace_id: WorkspaceID | None,
39-
) -> FolderGet:
38+
) -> Folder:
4039
user = await get_user(app, user_id=user_id)
4140

4241
workspace_is_private = True
@@ -86,15 +85,15 @@ async def create_folder(
8685
user_id=user_id if workspace_is_private else None,
8786
workspace_id=workspace_id,
8887
)
89-
return FolderGet.from_domain_model(folder_db, user_folder_access_rights)
88+
return Folder(folder_db=folder_db, my_access_rights=user_folder_access_rights)
9089

9190

9291
async def get_folder(
9392
app: web.Application,
9493
user_id: UserID,
9594
folder_id: FolderID,
9695
product_name: ProductName,
97-
) -> FolderGet:
96+
) -> Folder:
9897
folder_db = await folders_db.get(
9998
app, folder_id=folder_id, product_name=product_name
10099
)
@@ -119,7 +118,7 @@ async def get_folder(
119118
user_id=user_id if workspace_is_private else None,
120119
workspace_id=folder_db.workspace_id,
121120
)
122-
return FolderGet.from_domain_model(folder_db, user_folder_access_rights)
121+
return Folder(folder_db=folder_db, my_access_rights=user_folder_access_rights)
123122

124123

125124
async def list_folders(
@@ -132,7 +131,7 @@ async def list_folders(
132131
offset: NonNegativeInt,
133132
limit: int,
134133
order_by: OrderBy,
135-
) -> FolderGetPage:
134+
) -> tuple[list[Folder], int]:
136135
# NOTE: Folder access rights for listing are checked within the listing DB function.
137136

138137
total_count, folders = await folders_db.list_(
@@ -157,15 +156,15 @@ async def list_folders(
157156
limit=limit,
158157
order_by=order_by,
159158
)
160-
return FolderGetPage(
161-
items=[
162-
FolderGet.from_domain_model(
163-
folder,
164-
folder.my_access_rights,
159+
return (
160+
[
161+
Folder(
162+
folder_db=folder,
163+
my_access_rights=folder.my_access_rights,
165164
)
166165
for folder in folders
167166
],
168-
total=total_count,
167+
total_count,
169168
)
170169

171170

@@ -179,7 +178,7 @@ async def list_folders_full_depth(
179178
offset: NonNegativeInt,
180179
limit: int,
181180
order_by: OrderBy,
182-
) -> FolderGetPage:
181+
) -> tuple[list[Folder], int]:
183182
# NOTE: Folder access rights for listing are checked within the listing DB function.
184183

185184
total_count, folders = await folders_db.list_(
@@ -194,15 +193,15 @@ async def list_folders_full_depth(
194193
limit=limit,
195194
order_by=order_by,
196195
)
197-
return FolderGetPage(
198-
items=[
199-
FolderGet.from_domain_model(
200-
folder,
201-
folder.my_access_rights,
196+
return (
197+
[
198+
Folder(
199+
folder_db=folder,
200+
my_access_rights=folder.my_access_rights,
202201
)
203202
for folder in folders
204203
],
205-
total=total_count,
204+
total_count,
206205
)
207206

208207

@@ -214,7 +213,7 @@ async def update_folder(
214213
name: str,
215214
parent_folder_id: FolderID | None,
216215
product_name: ProductName,
217-
) -> FolderGet:
216+
) -> Folder:
218217
folder_db = await folders_db.get(
219218
app, folder_id=folder_id, product_name=product_name
220219
)
@@ -266,7 +265,7 @@ async def update_folder(
266265
parent_folder_id=parent_folder_id,
267266
product_name=product_name,
268267
)
269-
return FolderGet.from_domain_model(folder_db, user_folder_access_rights)
268+
return Folder(folder_db, user_folder_access_rights)
270269

271270

272271
async def delete_folder(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ async def create_workspace_and_folder(
4141
product_name="osparc",
4242
)
4343

44-
folder = await create_folder(
44+
folder, _ = await create_folder(
4545
client.app,
4646
user_id=logged_user["id"],
4747
name="a",

services/web/server/tests/unit/with_dbs/03/test_trash.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ async def test_trash_single_folder(client: TestClient, logged_user: UserInfoDict
331331
assert got.trashed_at
332332
assert trashing_at < got.trashed_at
333333
assert got.trashed_at < arrow.utcnow().datetime
334-
assert got.trashed_by == logged_user["id"]
334+
assert got.trashed_by == logged_user["primary_gid"]
335335
assert got.owner == logged_user["primary_gid"]
336336

337337
# LIST trashed
@@ -460,7 +460,7 @@ async def test_trash_folder_with_content(
460460
data, _ = await assert_status(resp, status.HTTP_200_OK)
461461
got = ProjectGet.model_validate(data)
462462
assert got.trashed_at is not None
463-
assert got.trashed_by == logged_user["primary_gid"]
463+
assert got.trashed_by == logged_user["id"]
464464

465465
# UNTRASH folder
466466
resp = await client.post(f"/v0/folders/{folder.folder_id}:untrash")

0 commit comments

Comments
 (0)