Skip to content

Commit 5225799

Browse files
Perform org operations only if the user has permissions
1 parent 476f69c commit 5225799

File tree

1 file changed

+103
-2
lines changed

1 file changed

+103
-2
lines changed

routers/organization.py

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
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
8+
from utils.models import Organization, User, Role, UserOrganizationLink, ValidPermissions, RolePermissionLink, Permission
99
from datetime import datetime
10+
from sqlalchemy import and_
1011

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

@@ -45,6 +46,14 @@ def __init__(self):
4546
)
4647

4748

49+
class InsufficientPermissionsError(HTTPException):
50+
def __init__(self):
51+
super().__init__(
52+
status_code=403,
53+
detail="You don't have permission to perform this action"
54+
)
55+
56+
4857
router = APIRouter(prefix="/organizations", tags=["organizations"])
4958

5059

@@ -94,6 +103,49 @@ async def as_form(cls, id: int = Form(...), name: str = Form(...)):
94103

95104
# -- Routes --
96105

106+
def check_user_permission(
107+
session: Session,
108+
user: User,
109+
org_id: int,
110+
permission: ValidPermissions
111+
) -> bool:
112+
"""
113+
Check if user has the specified permission for the organization
114+
"""
115+
# Get user's role in the organization
116+
user_org = session.exec(
117+
select(UserOrganizationLink).where(
118+
and_(
119+
UserOrganizationLink.user_id == user.id,
120+
UserOrganizationLink.organization_id == org_id
121+
)
122+
)
123+
).first()
124+
125+
if not user_org:
126+
return False
127+
128+
# Get permission ID
129+
permission_record = session.exec(
130+
select(Permission).where(Permission.name == permission)
131+
).first()
132+
133+
if not permission_record:
134+
return False
135+
136+
# Check if role has the permission
137+
role_permission = session.exec(
138+
select(RolePermissionLink).where(
139+
and_(
140+
RolePermissionLink.role_id == user_org.role_id,
141+
RolePermissionLink.permission_id == permission_record.id
142+
)
143+
)
144+
).first()
145+
146+
return bool(role_permission)
147+
148+
97149
@router.post("/", response_class=RedirectResponse)
98150
def create_organization(
99151
org: OrganizationCreate = Depends(OrganizationCreate.as_form),
@@ -110,11 +162,54 @@ def create_organization(
110162
session.commit()
111163
session.refresh(db_org)
112164

165+
owner_role = session.exec(
166+
select(Role).where(
167+
and_(
168+
Role.organization_id == db_org.id,
169+
Role.name == "Owner"
170+
)
171+
)
172+
).first()
173+
174+
if not owner_role:
175+
owner_role = Role(
176+
name="Owner",
177+
organization_id=db_org.id
178+
)
179+
session.add(owner_role)
180+
session.commit()
181+
session.refresh(owner_role)
182+
183+
user_org_link = UserOrganizationLink(
184+
user_id=user.id,
185+
organization_id=db_org.id,
186+
role_id=owner_role.id
187+
)
188+
session.add(user_org_link)
189+
session.commit()
190+
113191
return RedirectResponse(url=f"/organizations/{db_org.id}", status_code=303)
114192

115193

116194
@router.get("/{org_id}", response_model=OrganizationRead)
117-
def read_organization(org_id: int, user: User = Depends(get_authenticated_user), session: Session = Depends(get_session)):
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+
118213
db_org = session.get(Organization, org_id)
119214
if not db_org:
120215
raise OrganizationNotFoundError()
@@ -127,6 +222,9 @@ def update_organization(
127222
user: User = Depends(get_authenticated_user),
128223
session: Session = Depends(get_session)
129224
) -> RedirectResponse:
225+
if not check_user_permission(session, user, org.id, ValidPermissions.EDIT_ORGANIZATION):
226+
raise InsufficientPermissionsError()
227+
130228
db_org = session.get(Organization, org.id)
131229
if not db_org:
132230
raise OrganizationNotFoundError()
@@ -155,6 +253,9 @@ def delete_organization(
155253
user: User = Depends(get_authenticated_user),
156254
session: Session = Depends(get_session)
157255
) -> RedirectResponse:
256+
if not check_user_permission(session, user, org_id, ValidPermissions.DELETE_ORGANIZATION):
257+
raise InsufficientPermissionsError()
258+
158259
db_org = session.get(Organization, org_id)
159260
if not db_org:
160261
raise OrganizationNotFoundError()

0 commit comments

Comments
 (0)