Skip to content

Commit 063413c

Browse files
Simplify project service functions for public project discovery
1 parent 71f537f commit 063413c

1 file changed

Lines changed: 38 additions & 41 deletions

File tree

src/dstack/_internal/server/services/projects.py

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,12 @@ async def list_user_accessible_projects(
8181
if user.global_role == GlobalRole.ADMIN:
8282
projects = await list_project_models(session=session)
8383
else:
84-
projects = await list_user_project_models(
85-
session=session, user=user, include_public_non_member=True
86-
)
84+
# Get member projects
85+
member_projects = await list_user_project_models(session=session, user=user)
86+
# Get public non-member projects
87+
public_projects = await _list_public_non_member_project_models(session=session, user=user)
88+
# Combine both lists
89+
projects = member_projects + public_projects
8790

8891
projects = sorted(projects, key=lambda p: p.created_at)
8992
return [
@@ -262,61 +265,55 @@ async def list_user_project_models(
262265
session: AsyncSession,
263266
user: UserModel,
264267
include_members: bool = False,
265-
include_public_non_member: bool = False,
266268
) -> List[ProjectModel]:
267269
"""
268-
Get projects for a user.
269-
270+
Get projects for a user where they are a member.
271+
270272
Args:
271273
session: Database session
272274
user: User model
273275
include_members: Whether to join and load project members
274-
include_public_non_member: Whether to include public projects where user is not a member
275-
276+
276277
Returns:
277-
List of ProjectModel instances
278+
List of ProjectModel instances where user is a member
278279
"""
279280
options = []
280281
if include_members:
281282
options.append(joinedload(ProjectModel.members))
282283

283-
if include_public_non_member:
284-
# Get both member projects AND public non-member projects
285-
res = await session.execute(
286-
select(ProjectModel)
287-
.where(
288-
ProjectModel.deleted == False,
289-
# Either user is a member, OR project is public and user is not a member
290-
(
291-
# User is a member (regardless of public/private)
292-
ProjectModel.id.in_(
293-
select(MemberModel.project_id).where(MemberModel.user_id == user.id)
294-
)
295-
) | (
296-
# OR project is public and user is not a member
297-
(ProjectModel.is_public == True) &
298-
ProjectModel.id.notin_(
299-
select(MemberModel.project_id).where(MemberModel.user_id == user.id)
300-
)
301-
)
302-
)
303-
.options(*options)
304-
)
305-
else:
306-
# Original logic - only member projects
307-
res = await session.execute(
308-
select(ProjectModel)
309-
.where(
310-
MemberModel.project_id == ProjectModel.id,
311-
MemberModel.user_id == user.id,
312-
ProjectModel.deleted == False,
313-
)
314-
.options(*options)
284+
res = await session.execute(
285+
select(ProjectModel)
286+
.where(
287+
MemberModel.project_id == ProjectModel.id,
288+
MemberModel.user_id == user.id,
289+
ProjectModel.deleted == False,
315290
)
291+
.options(*options)
292+
)
316293

317294
return list(res.scalars().unique().all())
318295

319296

297+
async def _list_public_non_member_project_models(
298+
session: AsyncSession,
299+
user: UserModel,
300+
) -> List[ProjectModel]:
301+
"""
302+
Get public projects where user is NOT a member.
303+
"""
304+
res = await session.execute(
305+
select(ProjectModel)
306+
.where(
307+
ProjectModel.deleted == False,
308+
ProjectModel.is_public == True,
309+
ProjectModel.id.notin_(
310+
select(MemberModel.project_id).where(MemberModel.user_id == user.id)
311+
)
312+
)
313+
)
314+
return list(res.scalars().all())
315+
316+
320317
async def list_user_owned_project_models(
321318
session: AsyncSession, user: UserModel, include_deleted: bool = False
322319
) -> List[ProjectModel]:

0 commit comments

Comments
 (0)