88from app .models import (
99 Message ,
1010 ProjectAccessCreate ,
11- ProjectAccessesPublic ,
11+ ProjectAccessInviteByEmail ,
1212 ProjectAccessPublic ,
1313 ProjectAccessUpdate ,
14+ ProjectAccessWithUser ,
1415 User ,
1516)
1617
1718router = APIRouter ()
1819
1920
21+ # AN - New endpoint to get all projects the current user has access to
22+ @router .get ("/my-projects" )
23+ def read_my_projects (
24+ session : SessionDep ,
25+ current_user : CurrentUser ,
26+ ) -> Any :
27+ """
28+ Get all projects the current user has access to.
29+ For clients: returns projects they've been invited to.
30+ For team members: returns all projects in their organization.
31+ """
32+ if getattr (current_user , "user_type" , None ) == "client" :
33+ # Use the existing function - perfect!
34+ projects = crud .get_user_accessible_projects (
35+ session = session , user_id = current_user .id , skip = 0 , limit = 1000
36+ )
37+ return {"data" : projects , "count" : len (projects )}
38+ elif getattr (current_user , "user_type" , None ) == "team_member" :
39+ if not current_user .organization_id :
40+ return {"data" : [], "count" : 0 }
41+ projects = crud .get_projects_by_organization (
42+ session = session ,
43+ organization_id = current_user .organization_id ,
44+ skip = 0 ,
45+ limit = 1000
46+ )
47+ return {"data" : projects , "count" : len (projects )}
48+ else :
49+ return {"data" : [], "count" : 0 }
50+
51+ @router .post ("/{project_id}/access/invite-by-email" )
52+ def invite_client_by_email (
53+ * ,
54+ session : SessionDep ,
55+ current_user : CurrentUser ,
56+ project_id : uuid .UUID ,
57+ invite_data : ProjectAccessInviteByEmail ,
58+ ) -> Any :
59+ """
60+ Invite a client to a project by email.
61+ If user exists: grants immediate access
62+ If user doesn't exist: creates a pending invitation
63+ Only team members can invite clients.
64+ """
65+ # Check if current user is a team member
66+ if getattr (current_user , "user_type" , None ) != "team_member" :
67+ raise HTTPException (
68+ status_code = 403 ,
69+ detail = "Only team members can invite clients to projects" ,
70+ )
71+
72+ # Check if project exists and user has access to it
73+ project = crud .get_project (session = session , project_id = project_id )
74+ if not project :
75+ raise HTTPException (status_code = 404 , detail = "Project not found" )
76+
77+ # Check if current user's organization owns the project
78+ if (
79+ not current_user .organization_id
80+ or current_user .organization_id != project .organization_id
81+ ):
82+ raise HTTPException (
83+ status_code = 403 ,
84+ detail = "You don't have permission to manage this project" ,
85+ )
86+
87+ # Invite client by email
88+ try :
89+ access , is_pending = crud .invite_client_by_email (
90+ session = session ,
91+ project_id = project_id ,
92+ email = invite_data .email ,
93+ role = invite_data .role ,
94+ can_comment = invite_data .can_comment ,
95+ can_download = invite_data .can_download ,
96+ )
97+
98+ if is_pending :
99+ return {
100+ "message" : "Invitation sent. Client will get access when they sign up with this email." ,
101+ "is_pending" : True ,
102+ "email" : invite_data .email ,
103+ }
104+ else :
105+ return {
106+ "message" : "Client invited successfully" ,
107+ "is_pending" : False ,
108+ "access" : ProjectAccessPublic .model_validate (access ),
109+ }
110+ except ValueError as e :
111+ raise HTTPException (status_code = 400 , detail = str (e ))
112+
113+
20114@router .post ("/{project_id}/access" , response_model = ProjectAccessPublic )
21115def grant_project_access (
22116 * ,
@@ -31,6 +125,7 @@ def grant_project_access(
31125 """
32126 Grant a user access to a project (invite a client).
33127 Only team members can invite clients.
128+ DEPRECATED: Use /invite-by-email endpoint instead.
34129 """
35130 # Check if current user is a team member
36131 if getattr (current_user , "user_type" , None ) != "team_member" :
@@ -71,7 +166,7 @@ def grant_project_access(
71166 return access
72167
73168
74- @router .get ("/{project_id}/access" , response_model = ProjectAccessesPublic )
169+ @router .get ("/{project_id}/access" , response_model = list [ ProjectAccessWithUser ] )
75170def read_project_access_list (
76171 * ,
77172 session : SessionDep ,
@@ -99,7 +194,26 @@ def read_project_access_list(
99194 raise HTTPException (status_code = 403 , detail = "Access denied" )
100195
101196 access_list = crud .get_project_access_list (session = session , project_id = project_id )
102- return ProjectAccessesPublic (data = access_list , count = len (access_list ))
197+ # Convert to ProjectAccessWithUser
198+ result = []
199+ for access in access_list :
200+ user = session .get (User , access .user_id )
201+ if user :
202+ from app .models import UserPublic
203+
204+ result .append (
205+ ProjectAccessWithUser (
206+ id = access .id ,
207+ created_at = access .created_at ,
208+ project_id = access .project_id ,
209+ user_id = access .user_id ,
210+ role = access .role ,
211+ can_comment = access .can_comment ,
212+ can_download = access .can_download ,
213+ user = UserPublic .model_validate (user ),
214+ )
215+ )
216+ return result
103217
104218
105219@router .delete ("/{project_id}/access/{user_id}" , response_model = Message )
@@ -176,3 +290,5 @@ def update_project_access_permissions(
176290 session = session , db_access = db_access , access_in = access_in
177291 )
178292 return access
293+
294+
0 commit comments