Skip to content

Commit 0f9aa5c

Browse files
batch get project access rights sql query
1 parent 097a18d commit 0f9aa5c

File tree

1 file changed

+40
-27
lines changed

1 file changed

+40
-27
lines changed

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

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
from aiohttp import web
44
from aiopg.sa.engine import Engine
55
from models_library.groups import GroupID
6-
from models_library.projects import ProjectID
6+
from models_library.projects import ProjectID, ProjectIDStr
77
from models_library.users import UserID
88
from models_library.workspaces import WorkspaceID
99
from simcore_postgres_database.models.project_to_groups import project_to_groups
1010
from simcore_postgres_database.models.projects import projects
11-
from simcore_postgres_database.models.workspace_access_rights import (
12-
workspace_access_rights,
11+
from simcore_postgres_database.models.workspaces_access_rights import (
12+
workspaces_access_rights,
1313
)
1414
from simcore_postgres_database.utils_repos import (
1515
pass_or_acquire_connection,
@@ -33,22 +33,30 @@ async def get_project_owner(engine: Engine, project_uuid: ProjectID) -> UserID:
3333
return owner_id
3434

3535

36+
def _split_private_and_shared_projects(
37+
projects_uuids_with_workspace_id: list[tuple[ProjectID, WorkspaceID | None]],
38+
) -> tuple[list[ProjectID], dict[WorkspaceID, list[ProjectID]]]:
39+
"""Splits project tuples into private project IDs and a mapping of workspace_id to project IDs."""
40+
private_project_ids = []
41+
workspace_to_project_ids: dict[WorkspaceID, list[ProjectID]] = {}
42+
for pid, wid in projects_uuids_with_workspace_id:
43+
if wid is None:
44+
private_project_ids.append(pid)
45+
else:
46+
workspace_to_project_ids.setdefault(wid, []).append(pid)
47+
return private_project_ids, workspace_to_project_ids
48+
49+
3650
async def batch_get_project_access_rights(
3751
app: web.Application,
3852
connection: AsyncConnection | None = None,
3953
*,
40-
projects_uuids_with_workspace_id: list[
41-
tuple[ProjectID, WorkspaceID | None]
42-
], # list of tuples (project_uuid, workspace_id)
43-
) -> dict[ProjectID, dict[GroupID, dict[str, bool]]]:
44-
# Split into private and shared workspace project IDs
45-
private_project_ids = [
46-
pid for pid, wid in projects_uuids_with_workspace_id if wid is None
47-
]
48-
shared_project_ids = [
49-
pid for pid, wid in projects_uuids_with_workspace_id if wid is not None
50-
]
51-
54+
projects_uuids_with_workspace_id: list[tuple[ProjectID, WorkspaceID | None]],
55+
) -> dict[ProjectIDStr, dict[GroupID, dict[str, bool]]]:
56+
private_project_ids, workspace_to_project_ids = _split_private_and_shared_projects(
57+
projects_uuids_with_workspace_id
58+
)
59+
shared_workspace_ids = set(workspace_to_project_ids.keys())
5260
results = {}
5361

5462
async with pass_or_acquire_connection(get_asyncpg_engine(app), connection) as conn:
@@ -80,32 +88,37 @@ async def batch_get_project_access_rights(
8088
async for row in private_result:
8189
results[row.project_uuid] = row.access_rights
8290

83-
# Query shared workspace projects
84-
if shared_project_ids:
91+
# Query shared workspace projects by workspace_id
92+
if shared_workspace_ids:
8593
shared_query = (
8694
sa.select(
87-
workspace_access_rights.c.project_uuid,
95+
workspaces_access_rights.c.workspace_id,
8896
sa.func.jsonb_object_agg(
89-
workspace_access_rights.c.gid,
97+
workspaces_access_rights.c.gid,
9098
sa.func.jsonb_build_object(
9199
"read",
92-
workspace_access_rights.c.read,
100+
workspaces_access_rights.c.read,
93101
"write",
94-
workspace_access_rights.c.write,
102+
workspaces_access_rights.c.write,
95103
"delete",
96-
workspace_access_rights.c.delete,
104+
workspaces_access_rights.c.delete,
97105
),
98106
).label("access_rights"),
99107
)
100108
.where(
101-
workspace_access_rights.c.project_uuid.in_(
102-
[f"{uuid}" for uuid in shared_project_ids]
103-
)
109+
workspaces_access_rights.c.workspace_id.in_(shared_workspace_ids)
104110
)
105-
.group_by(workspace_access_rights.c.project_uuid)
111+
.group_by(workspaces_access_rights.c.workspace_id)
106112
)
107113
shared_result = await conn.stream(shared_query)
114+
workspace_access_rights_map = {}
108115
async for row in shared_result:
109-
results[row.project_uuid] = row.access_rights
116+
workspace_access_rights_map[row.workspace_id] = row.access_rights
117+
# Assign access rights to each project in the workspace
118+
for wid, project_ids in workspace_to_project_ids.items():
119+
access_rights = workspace_access_rights_map.get(wid)
120+
if access_rights is not None:
121+
for pid in project_ids:
122+
results[f"{pid}"] = access_rights
110123

111124
return results

0 commit comments

Comments
 (0)