Skip to content

Commit c88e650

Browse files
committed
updates workspaces to return groupid
1 parent 8078962 commit c88e650

File tree

2 files changed

+59
-64
lines changed

2 files changed

+59
-64
lines changed

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Workspace(BaseModel):
4747
workspace_id: WorkspaceID
4848
name: str
4949
description: str | None
50-
owner_primary_gid: PositiveInt = Field(
50+
owner_primary_gid: GroupID = Field(
5151
...,
5252
description="GID of the group that owns this wallet",
5353
)
@@ -62,6 +62,14 @@ class Workspace(BaseModel):
6262
)
6363
trashed: datetime | None
6464
trashed_by: UserID | None
65+
trashed_by_primary_gid: GroupID | None = None
66+
67+
model_config = ConfigDict(from_attributes=True)
68+
69+
70+
class UserWorkspaceWithAccessRights(Workspace):
71+
my_access_rights: AccessRights
72+
access_rights: dict[GroupID, AccessRights]
6573

6674
model_config = ConfigDict(from_attributes=True)
6775

@@ -72,10 +80,3 @@ class WorkspaceUpdates(BaseModel):
7280
thumbnail: str | None = None
7381
trashed: datetime | None = None
7482
trashed_by: UserID | None = None
75-
76-
77-
class UserWorkspaceWithAccessRights(Workspace):
78-
my_access_rights: AccessRights
79-
access_rights: dict[GroupID, AccessRights]
80-
81-
model_config = ConfigDict(from_attributes=True)

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

Lines changed: 50 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
WorkspaceUpdates,
2020
)
2121
from pydantic import NonNegativeInt
22+
from simcore_postgres_database.models.users import users
2223
from simcore_postgres_database.models.workspaces import workspaces
2324
from simcore_postgres_database.models.workspaces_access_rights import (
2425
workspaces_access_rights,
@@ -40,7 +41,7 @@
4041
_logger = logging.getLogger(__name__)
4142

4243

43-
_SELECTION_ARGS = (
44+
_WORKSPACE_SELECTION_COLS = (
4445
workspaces.c.workspace_id,
4546
workspaces.c.name,
4647
workspaces.c.description,
@@ -52,10 +53,12 @@
5253
workspaces.c.trashed_by,
5354
)
5455

55-
assert set(Workspace.model_fields) == {c.name for c in _SELECTION_ARGS} # nosec
56+
assert set(Workspace.model_fields).issubset(
57+
{c.name for c in _WORKSPACE_SELECTION_COLS} # nosec
58+
), "part of the data-model is one-to-one to the domain model"
5659
assert set(WorkspaceUpdates.model_fields).issubset( # nosec
5760
c.name for c in workspaces.columns
58-
)
61+
), "part of the data-model is one-to-one to the domain model"
5962

6063

6164
async def create_workspace(
@@ -80,32 +83,54 @@ async def create_workspace(
8083
modified=func.now(),
8184
product_name=product_name,
8285
)
83-
.returning(*_SELECTION_ARGS)
86+
.returning(*_WORKSPACE_SELECTION_COLS)
8487
)
8588
row = await result.first()
8689
return Workspace.model_validate(row)
8790

8891

89-
_access_rights_subquery = (
90-
select(
91-
workspaces_access_rights.c.workspace_id,
92-
func.jsonb_object_agg(
93-
workspaces_access_rights.c.gid,
94-
func.jsonb_build_object(
95-
"read",
96-
workspaces_access_rights.c.read,
97-
"write",
98-
workspaces_access_rights.c.write,
99-
"delete",
100-
workspaces_access_rights.c.delete,
101-
),
92+
def _create_base_query(caller_user_id: UserID, product_name: ProductName):
93+
# any other access
94+
access_rights_subquery = (
95+
select(
96+
workspaces_access_rights.c.workspace_id,
97+
func.jsonb_object_agg(
98+
workspaces_access_rights.c.gid,
99+
func.jsonb_build_object(
100+
"read",
101+
workspaces_access_rights.c.read,
102+
"write",
103+
workspaces_access_rights.c.write,
104+
"delete",
105+
workspaces_access_rights.c.delete,
106+
),
107+
)
108+
.filter(
109+
workspaces_access_rights.c.read # Filters out entries where "read" is False
110+
)
111+
.label("access_rights"),
112+
).group_by(workspaces_access_rights.c.workspace_id)
113+
).subquery("access_rights_subquery")
114+
115+
# caller's access rights
116+
my_access_rights_subquery = create_my_workspace_access_rights_subquery(
117+
user_id=caller_user_id
118+
)
119+
120+
return (
121+
select(
122+
*_WORKSPACE_SELECTION_COLS,
123+
access_rights_subquery.c.access_rights,
124+
my_access_rights_subquery.c.my_access_rights,
125+
users.c.primary_gid.label("trashed_by_primary_gid"),
102126
)
103-
.filter(
104-
workspaces_access_rights.c.read # Filters out entries where "read" is False
127+
.select_from(
128+
workspaces.join(access_rights_subquery)
129+
.join(my_access_rights_subquery)
130+
.outerjoin(users, workspaces.c.trashed_by == users.c.id)
105131
)
106-
.label("access_rights"),
107-
).group_by(workspaces_access_rights.c.workspace_id)
108-
).subquery("access_rights_subquery")
132+
.where(workspaces.c.product_name == product_name)
133+
)
109134

110135

111136
async def list_workspaces_for_user(
@@ -120,21 +145,7 @@ async def list_workspaces_for_user(
120145
limit: NonNegativeInt,
121146
order_by: OrderBy,
122147
) -> tuple[int, list[UserWorkspaceWithAccessRights]]:
123-
my_access_rights_subquery = create_my_workspace_access_rights_subquery(
124-
user_id=user_id
125-
)
126-
127-
base_query = (
128-
select(
129-
*_SELECTION_ARGS,
130-
_access_rights_subquery.c.access_rights,
131-
my_access_rights_subquery.c.my_access_rights,
132-
)
133-
.select_from(
134-
workspaces.join(_access_rights_subquery).join(my_access_rights_subquery)
135-
)
136-
.where(workspaces.c.product_name == product_name)
137-
)
148+
base_query = _create_base_query(caller_user_id=user_id, product_name=product_name)
138149

139150
if filter_trashed is not None:
140151
base_query = base_query.where(
@@ -178,24 +189,7 @@ async def get_workspace_for_user(
178189
workspace_id: WorkspaceID,
179190
product_name: ProductName,
180191
) -> UserWorkspaceWithAccessRights:
181-
my_access_rights_subquery = create_my_workspace_access_rights_subquery(
182-
user_id=user_id
183-
)
184-
185-
base_query = (
186-
select(
187-
*_SELECTION_ARGS,
188-
_access_rights_subquery.c.access_rights,
189-
my_access_rights_subquery.c.my_access_rights,
190-
)
191-
.select_from(
192-
workspaces.join(_access_rights_subquery).join(my_access_rights_subquery)
193-
)
194-
.where(
195-
(workspaces.c.workspace_id == workspace_id)
196-
& (workspaces.c.product_name == product_name)
197-
)
198-
)
192+
base_query = _create_base_query(caller_user_id=user_id, product_name=product_name)
199193

200194
async with pass_or_acquire_connection(get_asyncpg_engine(app), connection) as conn:
201195
result = await conn.stream(base_query)
@@ -229,7 +223,7 @@ async def update_workspace(
229223
(workspaces.c.workspace_id == workspace_id)
230224
& (workspaces.c.product_name == product_name)
231225
)
232-
.returning(*_SELECTION_ARGS)
226+
.returning(*_WORKSPACE_SELECTION_COLS)
233227
)
234228
row = await result.first()
235229
if row is None:

0 commit comments

Comments
 (0)