5050)
5151from simcore_postgres_database .storage_models import file_meta_data , user_to_groups
5252from simcore_postgres_database .utils_repos import pass_or_acquire_connection
53- from simcore_postgres_database .utils_sql import assemble_array_groups
5453from sqlalchemy .ext .asyncio import AsyncConnection
5554
5655from ...exceptions .errors import InvalidFileIdentifierError
@@ -89,112 +88,104 @@ def _aggregate_access_rights(
8988 return AccessRights .none ()
9089
9190
92- access_rights_subquery = (
93- sa .select (
94- project_to_groups .c .project_uuid ,
95- sa .func .jsonb_object_agg (
96- project_to_groups .c .gid ,
97- sa .func .jsonb_build_object (
98- "read" ,
99- project_to_groups .c .read ,
100- "write" ,
101- project_to_groups .c .write ,
102- "delete" ,
103- project_to_groups .c .delete ,
104- ),
91+ def my_private_workspace_access_rights_subquery (user_group_ids : list [GroupID ]):
92+ return (
93+ sa .select (
94+ project_to_groups .c .project_uuid ,
95+ sa .func .jsonb_object_agg (
96+ project_to_groups .c .gid ,
97+ sa .func .jsonb_build_object (
98+ "read" ,
99+ project_to_groups .c .read ,
100+ "write" ,
101+ project_to_groups .c .write ,
102+ "delete" ,
103+ project_to_groups .c .delete ,
104+ ),
105+ ).label ("access_rights" ),
106+ )
107+ .where (
108+ (project_to_groups .c .read ) # Filters out entries where "read" is False
109+ & (
110+ project_to_groups .c .gid .in_ (user_group_ids )
111+ ) # Filters gid to be in user_groups
105112 )
106- .filter (project_to_groups .c .read ) # Filters out entries where "read" is False
107- .label ("access_rights" ),
108- ).group_by (project_to_groups .c .project_uuid )
109- ).subquery ("access_rights_subquery" )
110-
111-
112- workspace_access_rights_subquery = (
113- sa .select (
114- workspaces_access_rights .c .workspace_id ,
115- sa .func .jsonb_object_agg (
116- workspaces_access_rights .c .gid ,
117- sa .func .jsonb_build_object (
118- "read" ,
119- workspaces_access_rights .c .read ,
120- "write" ,
121- workspaces_access_rights .c .write ,
122- "delete" ,
123- workspaces_access_rights .c .delete ,
124- ),
113+ .group_by (project_to_groups .c .project_uuid )
114+ ).subquery ("my_access_rights_subquery" )
115+
116+
117+ def my_shared_workspace_access_rights_subquery (user_group_ids : list [GroupID ]):
118+ return (
119+ sa .select (
120+ workspaces_access_rights .c .workspace_id ,
121+ sa .func .jsonb_object_agg (
122+ workspaces_access_rights .c .gid ,
123+ sa .func .jsonb_build_object (
124+ "read" ,
125+ workspaces_access_rights .c .read ,
126+ "write" ,
127+ workspaces_access_rights .c .write ,
128+ "delete" ,
129+ workspaces_access_rights .c .delete ,
130+ ),
131+ ).label ("access_rights" ),
132+ )
133+ .where (
134+ (
135+ workspaces_access_rights .c .read
136+ ) # Filters out entries where "read" is False
137+ & (
138+ workspaces_access_rights .c .gid .in_ (user_group_ids )
139+ ) # Filters gid to be in user_groups
125140 )
126- .filter (workspaces_access_rights .c .read )
127- .label ("access_rights" ),
128- ).group_by (workspaces_access_rights .c .workspace_id )
129- ).subquery ("workspace_access_rights_subquery" )
141+ .group_by (workspaces_access_rights .c .workspace_id )
142+ ).subquery ("my_workspace_access_rights_subquery" )
130143
131144
132- async def _list_projects_access_rights (
145+ async def _list_user_projects_access_rights_with_read_access (
133146 connection : AsyncConnection , user_id : UserID
134- ) -> dict [ProjectID , AccessRights ]:
147+ ) -> list [ProjectID ]:
135148 """
136149 Returns access-rights of user (user_id) over all OWNED or SHARED projects
137150 """
138151
139152 user_group_ids : list [GroupID ] = await _get_user_groups_ids (connection , user_id )
153+ _my_access_rights_subquery = my_private_workspace_access_rights_subquery (
154+ user_group_ids
155+ )
140156
141157 private_workspace_query = (
142158 sa .select (
143159 projects .c .uuid ,
144- access_rights_subquery .c .access_rights ,
145- )
146- .select_from (projects .join (access_rights_subquery , isouter = True ))
147- .where (
148- (
149- (projects .c .prj_owner == user_id )
150- | sa .text (
151- f"jsonb_exists_any(access_rights_subquery.access_rights, { assemble_array_groups (user_group_ids )} )"
152- )
153- )
154- & (projects .c .workspace_id .is_ (None ))
155160 )
161+ .select_from (projects .join (_my_access_rights_subquery ))
162+ .where (projects .c .workspace_id .is_ (None ))
163+ )
164+
165+ _my_workspace_access_rights_subquery = my_shared_workspace_access_rights_subquery (
166+ user_group_ids
156167 )
157168
158169 shared_workspace_query = (
159- sa .select (
160- projects .c .uuid ,
161- workspace_access_rights_subquery .c .access_rights ,
162- )
170+ sa .select (projects .c .uuid )
163171 .select_from (
164172 projects .join (
165- workspace_access_rights_subquery ,
173+ _my_workspace_access_rights_subquery ,
166174 projects .c .workspace_id
167- == workspace_access_rights_subquery .c .workspace_id ,
175+ == _my_workspace_access_rights_subquery .c .workspace_id ,
168176 )
169177 )
170- .where (
171- (
172- sa .text (
173- f"jsonb_exists_any(workspace_access_rights_subquery.access_rights, { assemble_array_groups (user_group_ids )} )"
174- )
175- )
176- & (projects .c .workspace_id .is_not (None ))
177- )
178+ .where (projects .c .workspace_id .is_not (None ))
178179 )
179180
180181 combined_query = sa .union_all (private_workspace_query , shared_workspace_query )
181182
182- projects_access_rights = {}
183+ projects_access_rights = []
183184
184185 async for row in await connection .stream (combined_query ):
185- assert isinstance (row .access_rights , dict ) # nosec
186186 assert isinstance (row .uuid , str ) # nosec
187187
188- if row .access_rights :
189- # NOTE: access_rights should be direclty filtered from result in stm instead calling again user_group_ids
190- projects_access_rights [ProjectID (row .uuid )] = _aggregate_access_rights (
191- row .access_rights , user_group_ids
192- )
193-
194- else :
195- # backwards compatibility
196- # - no access_rights defined BUT project is owned
197- projects_access_rights [ProjectID (row .uuid )] = AccessRights .all ()
188+ projects_access_rights .append (ProjectID (row .uuid ))
198189
199190 return projects_access_rights
200191
@@ -213,44 +204,40 @@ async def get_project_access_rights(
213204
214205 async with pass_or_acquire_connection (self .db_engine , connection ) as conn :
215206 user_group_ids = await _get_user_groups_ids (conn , user_id )
207+ _my_access_rights_subquery = my_private_workspace_access_rights_subquery (
208+ user_group_ids
209+ )
216210
217211 private_workspace_query = (
218212 sa .select (
219213 projects .c .prj_owner ,
220- access_rights_subquery .c .access_rights ,
214+ _my_access_rights_subquery .c .access_rights ,
221215 )
222- .select_from (projects .join (access_rights_subquery , isouter = True ))
216+ .select_from (projects .join (_my_access_rights_subquery ))
223217 .where (
224218 (projects .c .uuid == f"{ project_id } " )
225- & (
226- (projects .c .prj_owner == user_id )
227- | sa .text (
228- f"jsonb_exists_any(access_rights_subquery.access_rights, { assemble_array_groups (user_group_ids )} )"
229- )
230- )
231219 & (projects .c .workspace_id .is_ (None ))
232220 )
233221 )
234222
223+ _my_workspace_access_rights_subquery = (
224+ my_shared_workspace_access_rights_subquery (user_group_ids )
225+ )
226+
235227 shared_workspace_query = (
236228 sa .select (
237229 projects .c .prj_owner ,
238- workspace_access_rights_subquery .c .access_rights ,
230+ _my_workspace_access_rights_subquery .c .access_rights ,
239231 )
240232 .select_from (
241233 projects .join (
242- workspace_access_rights_subquery ,
234+ _my_workspace_access_rights_subquery ,
243235 projects .c .workspace_id
244- == workspace_access_rights_subquery .c .workspace_id ,
236+ == _my_workspace_access_rights_subquery .c .workspace_id ,
245237 )
246238 )
247239 .where (
248240 (projects .c .uuid == f"{ project_id } " )
249- & (
250- sa .text (
251- f"jsonb_exists_any(workspace_access_rights_subquery.access_rights, { assemble_array_groups (user_group_ids )} )"
252- )
253- )
254241 & (projects .c .workspace_id .is_not (None ))
255242 )
256243 )
@@ -358,5 +345,6 @@ async def get_readable_project_ids(
358345 ) -> list [ProjectID ]:
359346 """Returns a list of projects where user has granted read-access"""
360347 async with pass_or_acquire_connection (self .db_engine , connection ) as conn :
361- projects_access_rights = await _list_projects_access_rights (conn , user_id )
362- return [pid for pid , access in projects_access_rights .items () if access .read ]
348+ return await _list_user_projects_access_rights_with_read_access (
349+ conn , user_id
350+ )
0 commit comments