44from sqlalchemy import delete , select , update
55from sqlalchemy import func as safunc
66from sqlalchemy .ext .asyncio import AsyncSession
7- from sqlalchemy .orm import joinedload
7+ from sqlalchemy .orm import QueryableAttribute , joinedload , load_only
88
99from dstack ._internal .core .backends .configurators import get_configurator
1010from dstack ._internal .core .backends .dstack .models import (
@@ -53,13 +53,12 @@ async def list_user_projects(
5353 user : UserModel ,
5454) -> List [Project ]:
5555 """
56- Returns projects where the user is a member.
56+ Returns projects where the user is a member or all projects for global admins .
5757 """
58- if user .global_role == GlobalRole .ADMIN :
59- projects = await list_project_models (session = session )
60- else :
61- projects = await list_user_project_models (session = session , user = user )
62-
58+ projects = await list_user_project_models (
59+ session = session ,
60+ user = user ,
61+ )
6362 projects = sorted (projects , key = lambda p : p .created_at )
6463 return [
6564 project_model_to_project (p , include_backends = False , include_members = False )
@@ -79,7 +78,7 @@ async def list_user_accessible_projects(
7978 if user .global_role == GlobalRole .ADMIN :
8079 projects = await list_project_models (session = session )
8180 else :
82- member_projects = await list_user_project_models (session = session , user = user )
81+ member_projects = await list_member_project_models (session = session , user = user )
8382 public_projects = await list_public_non_member_project_models (session = session , user = user )
8483 projects = member_projects + public_projects
8584
@@ -166,7 +165,7 @@ async def delete_projects(
166165 projects_names : List [str ],
167166):
168167 if user .global_role != GlobalRole .ADMIN :
169- user_projects = await list_user_project_models (
168+ user_projects = await list_member_project_models (
170169 session = session , user = user , include_members = True
171170 )
172171 user_project_names = [p .name for p in user_projects ]
@@ -338,16 +337,34 @@ async def clear_project_members(
338337
339338
340339async def list_user_project_models (
340+ session : AsyncSession ,
341+ user : UserModel ,
342+ only_names : bool = False ,
343+ ) -> List [ProjectModel ]:
344+ load_only_attrs = []
345+ if only_names :
346+ load_only_attrs += [ProjectModel .id , ProjectModel .name ]
347+ if user .global_role == GlobalRole .ADMIN :
348+ return await list_project_models (session = session , load_only_attrs = load_only_attrs )
349+ return await list_member_project_models (
350+ session = session , user = user , load_only_attrs = load_only_attrs
351+ )
352+
353+
354+ async def list_member_project_models (
341355 session : AsyncSession ,
342356 user : UserModel ,
343357 include_members : bool = False ,
358+ load_only_attrs : Optional [List [QueryableAttribute ]] = None ,
344359) -> List [ProjectModel ]:
345360 """
346361 List project models for a user where they are a member.
347362 """
348363 options = []
349364 if include_members :
350365 options .append (joinedload (ProjectModel .members ))
366+ if load_only_attrs :
367+ options .append (load_only (* load_only_attrs ))
351368 res = await session .execute (
352369 select (ProjectModel )
353370 .where (
@@ -394,9 +411,13 @@ async def list_user_owned_project_models(
394411
395412async def list_project_models (
396413 session : AsyncSession ,
414+ load_only_attrs : Optional [List [QueryableAttribute ]] = None ,
397415) -> List [ProjectModel ]:
416+ options = []
417+ if load_only_attrs :
418+ options .append (load_only (* load_only_attrs ))
398419 res = await session .execute (
399- select (ProjectModel ).where (ProjectModel .deleted == False ),
420+ select (ProjectModel ).where (ProjectModel .deleted == False ). options ( * options )
400421 )
401422 return list (res .scalars ().all ())
402423
0 commit comments