5
5
from sqlmodel import Session , select
6
6
from utils .db import get_session
7
7
from utils .auth import get_authenticated_user
8
- from utils .models import Organization , User , Role , UserOrganizationLink , ValidPermissions , RolePermissionLink , Permission
8
+ from utils .models import Organization , User , Role , UserOrganizationLink , ValidPermissions , RolePermissionLink , Permission , utc_time
9
9
from datetime import datetime
10
10
from sqlalchemy import and_
11
+ from typing import List
11
12
12
13
logger = getLogger ("uvicorn.error" )
13
14
@@ -101,22 +102,99 @@ async def as_form(cls, id: int = Form(...), name: str = Form(...)):
101
102
return cls (id = id , name = name )
102
103
103
104
104
- # -- Routes --
105
+ # -- Helper Functions --
105
106
106
- def check_user_permission (
107
+ def get_user_organizations (
108
+ user_id : int ,
107
109
session : Session ,
108
- user : User ,
110
+ include_deleted : bool = False
111
+ ) -> List [Organization ]:
112
+ """
113
+ Retrieve all organizations a user is a member of.
114
+
115
+ Args:
116
+ user_id: ID of the user
117
+ session: Database session
118
+ include_deleted: Whether to include soft-deleted organizations
119
+
120
+ Returns:
121
+ List of Organization objects the user belongs to
122
+ """
123
+ query = (
124
+ select (Organization )
125
+ .join (UserOrganizationLink )
126
+ .where (UserOrganizationLink .user_id == user_id )
127
+ )
128
+
129
+ if not include_deleted :
130
+ query = query .where (Organization .deleted == False )
131
+
132
+ return list (session .exec (query ))
133
+
134
+
135
+ def get_organization (
109
136
org_id : int ,
110
- permission : ValidPermissions
137
+ user_id : int ,
138
+ session : Session ,
139
+ ) -> Organization :
140
+ """
141
+ Retrieve a specific organization if the user is a member.
142
+
143
+ Args:
144
+ org_id: ID of the organization
145
+ user_id: ID of the user
146
+ session: Database session
147
+
148
+ Returns:
149
+ Organization object
150
+
151
+ Raises:
152
+ OrganizationNotFoundError: If organization doesn't exist
153
+ InsufficientPermissionsError: If user is not a member
154
+ """
155
+ # Check if user is a member of the organization
156
+ user_org = session .exec (
157
+ select (UserOrganizationLink ).where (
158
+ and_ (
159
+ UserOrganizationLink .user_id == user_id ,
160
+ UserOrganizationLink .organization_id == org_id
161
+ )
162
+ )
163
+ ).first ()
164
+
165
+ if not user_org :
166
+ raise InsufficientPermissionsError ()
167
+
168
+ db_org = session .get (Organization , org_id )
169
+ if not db_org or db_org .deleted :
170
+ raise OrganizationNotFoundError ()
171
+
172
+ return db_org
173
+
174
+
175
+ def check_user_permission (
176
+ user_id : int ,
177
+ org_id : int ,
178
+ permission : ValidPermissions ,
179
+ session : Session ,
111
180
) -> bool :
112
181
"""
113
- Check if user has the specified permission for the organization
182
+ Check if user has the specified permission for the organization.
183
+
184
+ Args:
185
+ user_id: ID of the user
186
+ org_id: ID of the organization
187
+ permission: Permission to check
188
+ session: Database session
189
+
190
+ Returns:
191
+ True if user has permission, False otherwise
114
192
"""
115
193
# Get user's role in the organization
116
194
user_org = session .exec (
117
195
select (UserOrganizationLink ).where (
118
196
and_ (
119
- UserOrganizationLink .user_id == user . id ,
197
+ UserOrganizationLink .user_id == user_id ,
120
198
UserOrganizationLink .organization_id == org_id
121
199
)
122
200
)
@@ -146,6 +224,8 @@ def check_user_permission(
146
224
return bool (role_permission )
147
225
148
226
227
+ # -- Routes --
228
+
149
229
@router .post ("/" , response_class = RedirectResponse )
150
230
def create_organization (
151
231
org : OrganizationCreate = Depends (OrganizationCreate .as_form ),
@@ -191,43 +271,17 @@ def create_organization(
191
271
return RedirectResponse (url = f"/organizations/{ db_org .id } " , status_code = 303 )
192
272
193
273
194
- @router .get ("/{org_id}" , response_model = OrganizationRead )
195
- def read_organization (
196
- org_id : int ,
197
- user : User = Depends (get_authenticated_user ),
198
- session : Session = Depends (get_session )
199
- ):
200
- # First check if user is a member of the organization
201
- user_org = session .exec (
202
- select (UserOrganizationLink ).where (
203
- and_ (
204
- UserOrganizationLink .user_id == user .id ,
205
- UserOrganizationLink .organization_id == org_id
206
- )
207
- )
208
- ).first ()
209
-
210
- if not user_org :
211
- raise InsufficientPermissionsError ()
212
-
213
- db_org = session .get (Organization , org_id )
214
- if not db_org :
215
- raise OrganizationNotFoundError ()
216
- return db_org
217
-
218
-
219
274
@router .put ("/{org_id}" , response_class = RedirectResponse )
220
275
def update_organization (
221
276
org : OrganizationUpdate = Depends (OrganizationUpdate .as_form ),
222
277
user : User = Depends (get_authenticated_user ),
223
278
session : Session = Depends (get_session )
224
279
) -> RedirectResponse :
225
- if not check_user_permission ( session , user , org . id , ValidPermissions . EDIT_ORGANIZATION ):
226
- raise InsufficientPermissionsError ( )
280
+ # This will raise appropriate exceptions if org doesn't exist or user lacks access
281
+ organization = get_organization ( org . id , user . id , session )
227
282
228
- db_org = session .get (Organization , org .id )
229
- if not db_org :
230
- raise OrganizationNotFoundError ()
283
+ if not check_user_permission (user .id , org .id , ValidPermissions .EDIT_ORGANIZATION , session ):
284
+ raise InsufficientPermissionsError ()
231
285
232
286
# Check if new name already exists for another organization
233
287
existing_org = session .exec (
@@ -238,11 +292,11 @@ def update_organization(
238
292
if existing_org :
239
293
raise OrganizationNameTakenError ()
240
294
241
- db_org .name = org .name
242
- db_org .updated_at = datetime . utcnow ()
243
- session .add (db_org )
295
+ organization .name = org .name
296
+ organization .updated_at = utc_time ()
297
+ session .add (organization )
244
298
session .commit ()
245
- session .refresh (db_org )
299
+ session .refresh (organization )
246
300
247
301
return RedirectResponse (url = f"/organizations/{ org .id } " , status_code = 303 )
248
302
@@ -253,16 +307,15 @@ def delete_organization(
253
307
user : User = Depends (get_authenticated_user ),
254
308
session : Session = Depends (get_session )
255
309
) -> RedirectResponse :
256
- if not check_user_permission ( session , user , org_id , ValidPermissions . DELETE_ORGANIZATION ):
257
- raise InsufficientPermissionsError ( )
310
+ # This will raise appropriate exceptions if org doesn't exist or user lacks access
311
+ organization = get_organization ( org_id , user . id , session )
258
312
259
- db_org = session .get (Organization , org_id )
260
- if not db_org :
261
- raise OrganizationNotFoundError ()
313
+ if not check_user_permission (user .id , org_id , ValidPermissions .DELETE_ORGANIZATION , session ):
314
+ raise InsufficientPermissionsError ()
262
315
263
- db_org .deleted = True
264
- db_org .updated_at = datetime . utcnow ()
265
- session .add (db_org )
316
+ organization .deleted = True
317
+ organization .updated_at = utc_time ()
318
+ session .add (organization )
266
319
session .commit ()
267
320
268
321
return RedirectResponse (url = "/organizations" , status_code = 303 )
0 commit comments