Skip to content

Commit a8bee02

Browse files
Replaced role and organization endpoints with helper functions to return them as context
1 parent 636bd45 commit a8bee02

File tree

2 files changed

+131
-76
lines changed

2 files changed

+131
-76
lines changed

routers/organization.py

Lines changed: 102 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
from sqlmodel import Session, select
66
from utils.db import get_session
77
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
99
from datetime import datetime
1010
from sqlalchemy import and_
11+
from typing import List
1112

1213
logger = getLogger("uvicorn.error")
1314

@@ -101,22 +102,99 @@ async def as_form(cls, id: int = Form(...), name: str = Form(...)):
101102
return cls(id=id, name=name)
102103

103104

104-
# -- Routes --
105+
# -- Helper Functions --
105106

106-
def check_user_permission(
107+
def get_user_organizations(
108+
user_id: int,
107109
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(
109136
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,
111180
) -> bool:
112181
"""
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
114192
"""
115193
# Get user's role in the organization
116194
user_org = session.exec(
117195
select(UserOrganizationLink).where(
118196
and_(
119-
UserOrganizationLink.user_id == user.id,
197+
UserOrganizationLink.user_id == user_id,
120198
UserOrganizationLink.organization_id == org_id
121199
)
122200
)
@@ -146,6 +224,8 @@ def check_user_permission(
146224
return bool(role_permission)
147225

148226

227+
# -- Routes --
228+
149229
@router.post("/", response_class=RedirectResponse)
150230
def create_organization(
151231
org: OrganizationCreate = Depends(OrganizationCreate.as_form),
@@ -191,43 +271,17 @@ def create_organization(
191271
return RedirectResponse(url=f"/organizations/{db_org.id}", status_code=303)
192272

193273

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-
219274
@router.put("/{org_id}", response_class=RedirectResponse)
220275
def update_organization(
221276
org: OrganizationUpdate = Depends(OrganizationUpdate.as_form),
222277
user: User = Depends(get_authenticated_user),
223278
session: Session = Depends(get_session)
224279
) -> 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)
227282

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()
231285

232286
# Check if new name already exists for another organization
233287
existing_org = session.exec(
@@ -238,11 +292,11 @@ def update_organization(
238292
if existing_org:
239293
raise OrganizationNameTakenError()
240294

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)
244298
session.commit()
245-
session.refresh(db_org)
299+
session.refresh(organization)
246300

247301
return RedirectResponse(url=f"/organizations/{org.id}", status_code=303)
248302

@@ -253,16 +307,15 @@ def delete_organization(
253307
user: User = Depends(get_authenticated_user),
254308
session: Session = Depends(get_session)
255309
) -> 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)
258312

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()
262315

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)
266319
session.commit()
267320

268321
return RedirectResponse(url="/organizations", status_code=303)

routers/role.py

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,31 @@ async def as_form(
107107
)
108108

109109

110+
# -- Helper Functions --
111+
112+
def get_organization_roles(
113+
organization_id: int,
114+
session: Session,
115+
include_deleted: bool = False
116+
) -> List[Role]:
117+
"""
118+
Retrieve all roles for an organization.
119+
120+
Args:
121+
organization_id: ID of the organization
122+
session: Database session
123+
include_deleted: Whether to include soft-deleted roles
124+
125+
Returns:
126+
List of Role objects with their associated permissions
127+
"""
128+
query = select(Role).where(Role.organization_id == organization_id)
129+
if not include_deleted:
130+
query = query.where(Role.deleted == False)
131+
132+
return list(session.exec(query))
133+
134+
110135
# -- Routes --
111136

112137

@@ -117,7 +142,10 @@ def create_role(
117142
session: Session = Depends(get_session)
118143
) -> RedirectResponse:
119144
# Create role and permissions in a single transaction
120-
db_role = Role(name=role.name)
145+
db_role = Role(
146+
name=role.name,
147+
organization_id=user.organization_id # Add organization ID to role
148+
)
121149

122150
# Create RolePermissionLink objects and associate them with the role
123151
db_role.permissions = [
@@ -131,32 +159,6 @@ def create_role(
131159
return RedirectResponse(url="/roles", status_code=303)
132160

133161

134-
@router.get("/{role_id}", response_model=RoleRead)
135-
def read_role(
136-
role_id: int,
137-
user: User = Depends(get_authenticated_user),
138-
session: Session = Depends(get_session)
139-
):
140-
db_role: Role | None = session.get(Role, role_id)
141-
if not db_role or not db_role.id or db_role.deleted:
142-
raise RoleNotFoundError()
143-
144-
permissions = [
145-
ValidPermissions(link.permission.name)
146-
for link in db_role.role_permission_links
147-
if link.permission is not None
148-
]
149-
150-
return RoleRead(
151-
id=db_role.id,
152-
name=db_role.name,
153-
created_at=db_role.created_at,
154-
updated_at=db_role.updated_at,
155-
deleted=db_role.deleted,
156-
permissions=permissions
157-
)
158-
159-
160162
@router.put("/{role_id}", response_class=RedirectResponse)
161163
def update_role(
162164
role: RoleUpdate = Depends(RoleUpdate.as_form),

0 commit comments

Comments
 (0)