@@ -81,7 +81,9 @@ 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_accessible_project_models (session = session , user = user )
84+ projects = await list_user_project_models (
85+ session = session , user = user , include_public_non_member = True
86+ )
8587
8688 projects = sorted (projects , key = lambda p : p .created_at )
8789 return [
@@ -90,37 +92,6 @@ async def list_user_accessible_projects(
9092 ]
9193
9294
93- async def _list_user_accessible_project_models (
94- session : AsyncSession ,
95- user : UserModel ,
96- ) -> List [ProjectModel ]:
97- """
98- Get projects that a user can access:
99- 1. Projects where user is a member (regardless of public/private)
100- 2. Public projects where user is not a member
101- """
102- res = await session .execute (
103- select (ProjectModel )
104- .where (
105- ProjectModel .deleted == False ,
106- # Either user is a member, OR project is public and user is not a member
107- (
108- # User is a member (regardless of public/private)
109- ProjectModel .id .in_ (
110- select (MemberModel .project_id ).where (MemberModel .user_id == user .id )
111- )
112- ) | (
113- # OR project is public and user is not a member
114- (ProjectModel .is_public == True ) &
115- ProjectModel .id .notin_ (
116- select (MemberModel .project_id ).where (MemberModel .user_id == user .id )
117- )
118- )
119- )
120- )
121- return list (res .scalars ().all ())
122-
123-
12495async def list_projects (session : AsyncSession ) -> List [Project ]:
12596 projects = await list_project_models (session = session )
12697 return [
@@ -291,19 +262,58 @@ async def list_user_project_models(
291262 session : AsyncSession ,
292263 user : UserModel ,
293264 include_members : bool = False ,
265+ include_public_non_member : bool = False ,
294266) -> List [ProjectModel ]:
267+ """
268+ Get projects for a user.
269+
270+ Args:
271+ session: Database session
272+ user: User model
273+ 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+ Returns:
277+ List of ProjectModel instances
278+ """
295279 options = []
296280 if include_members :
297281 options .append (joinedload (ProjectModel .members ))
298- res = await session .execute (
299- select (ProjectModel )
300- .where (
301- MemberModel .project_id == ProjectModel .id ,
302- MemberModel .user_id == user .id ,
303- ProjectModel .deleted == False ,
282+
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 )
304304 )
305- .options (* options )
306- )
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 )
315+ )
316+
307317 return list (res .scalars ().unique ().all ())
308318
309319
0 commit comments