diff --git a/backend/main.py b/backend/main.py index bda78a7..de5d4dc 100644 --- a/backend/main.py +++ b/backend/main.py @@ -20,6 +20,7 @@ from auth import ( from permissions import ( has_role, whoami, + get_member_role, ) from rooms import ( @@ -372,23 +373,40 @@ def api_leave_room( } @app.delete("/rooms/{room_id}/members/{user_id}") -def remove_user_as_admin( +def api_remove_member( room_id: int, user_id: int, current_user: int = Depends(get_current_user), ): - if not has_role(room_id, current_user, "admin"): + current_role = get_member_role(room_id, current_user) + target_role = get_member_role(room_id, user_id) + + if current_role is None: + raise HTTPException( + status_code=403, + detail="not a room member", + ) + + if target_role is None: + raise HTTPException( + status_code=404, + detail="user is not a member of this room", + ) + + if current_role < 2: raise HTTPException( status_code=403, detail="admin permission required", ) - if not remove_room_member(room_id, user_id): + if target_role >= current_role: raise HTTPException( - status_code=404, - detail="user is not a member of this room", + status_code=403, + detail="cannot remove a member with equal or higher role", ) + remove_room_member(room_id, user_id) + return { "status": "removed", "user_id": user_id, diff --git a/backend/permissions.py b/backend/permissions.py index 53e71c0..aae6dc7 100644 --- a/backend/permissions.py +++ b/backend/permissions.py @@ -9,13 +9,6 @@ ROLE_LEVELS = { def get_role(room_id: int, user_id: int) -> str | None: - """ - Return the user's role in a room. - - Returns: - "member", "admin", "owner" - None if the user is not a member. - """ member = fetch_one( """ SELECT role @@ -78,6 +71,29 @@ def whoami(room_id: int, user_id: int) -> dict: "is_owner": role == "owner", } +def get_member_role(room_id, user_id): + member = fetch_one( + """ + SELECT role + FROM room_members + WHERE room_id = ? + AND user_id = ? + """, + (room_id, user_id), + ) + + if member is None: + return None + + roles = { + "member": 1, + "admin": 2, + "owner": 3, + } + + return roles.get(member["role"]) + + # PUBLIC # ├── POST /create-user # ├── POST /login