From 80f7f2978de0595f7f4a3ff6135cb9284745233d Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 17 Aug 2026 16:29:11 +0200 Subject: [PATCH] restructured --- backend/main.py | 9 ++--- backend/permissions.py | 78 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/backend/main.py b/backend/main.py index 0ae9ba1..24e29a8 100644 --- a/backend/main.py +++ b/backend/main.py @@ -315,12 +315,9 @@ def api_room_whoami( room_id: int, user_id: int = Depends(get_current_user), ): - role = whoami( - room_id, - user_id, - ) + permissions = whoami(room_id, user_id) - if role is None: + if not permissions["member"]: raise HTTPException( status_code=403, detail="not a room member", @@ -329,7 +326,7 @@ def api_room_whoami( return { "room_id": room_id, "user_id": user_id, - "role": role, + **permissions, } diff --git a/backend/permissions.py b/backend/permissions.py index 6f61002..53e71c0 100644 --- a/backend/permissions.py +++ b/backend/permissions.py @@ -8,7 +8,14 @@ ROLE_LEVELS = { } -def get_role(room_id: int, user_id: int): +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 @@ -16,7 +23,7 @@ def get_role(room_id: int, user_id: int): WHERE room_id = ? AND user_id = ? """, - (room_id, user_id) + (room_id, user_id), ) if member is None: @@ -28,28 +35,81 @@ def get_role(room_id: int, user_id: int): def has_role( room_id: int, user_id: int, - required_role: str + required_role: str, ) -> bool: - role = get_role(room_id, user_id) + """ + Check whether a user has at least the required role. - if role is None: + Role hierarchy: + owner > admin > member + """ + user_role = get_role(room_id, user_id) + + if user_role is None: return False - return ROLE_LEVELS.get(role, 0) >= ROLE_LEVELS[required_role] + user_level = ROLE_LEVELS.get(user_role, 0) + required_level = ROLE_LEVELS.get(required_role, 0) + + if required_level == 0: + return False + + return user_level >= required_level -def whoami(room_id: int, user_id: int): +def whoami(room_id: int, user_id: int) -> dict: + """ + Return the user's permissions within a room. + """ role = get_role(room_id, user_id) if role is None: return { "member": False, "role": None, + "is_admin": False, + "is_owner": False, } return { "member": True, "role": role, - "is_admin": ROLE_LEVELS[role] >= ROLE_LEVELS["admin"], + "is_admin": ROLE_LEVELS.get(role, 0) >= ROLE_LEVELS["admin"], "is_owner": role == "owner", - } \ No newline at end of file + } + +# PUBLIC +# ├── POST /create-user +# ├── POST /login +# ├── GET / +# └── GET /ascii-art + +# AUTHENTICATED +# ├── GET /me +# ├── GET /users/{id} +# ├── GET /database +# ├── POST /create-room +# ├── POST /search-room +# ├── POST /join-room +# └── GET /rooms + +# MEMBER +# ├── GET /rooms/{id} +# ├── GET /rooms/{id}/whoami +# ├── GET /rooms/{id}/members +# ├── GET /rooms/{id}/events +# ├── DELETE /rooms/{id}/members/me +# ├── POST /events +# ├── GET /events +# ├── GET /events/{id} +# ├── POST /events/{id}/respond +# └── GET /events/{id}/responses + +# ADMIN +# ├── PATCH /rooms/{id} +# ├── POST /rooms/{id}/invite-code +# ├── PATCH /events/{id} +# └── DELETE /events/{id} + +# OWNER +# └── DELETE /rooms/{id} \ No newline at end of file