fec3953009
- Three category scopes: personal / group / system (watch) - PascalCase-with-dashes naming convention enforced at backend + frontend - is_group_admin flag on GroupMembership; PATCH endpoint for admins to toggle it - Categories router: scope-based list/create/rename/delete with _check_can_manage_cat - Documents router: delete uses is_admin + can_delete share flag + group-admin check; remove_category requires doc ownership; assign_category accepts group/system categories - Proxy layers inject x-user-is-admin and x-user-admin-groups headers - Frontend: ManageCategoriesDialog grouped by scope with lock icons; SourcePanel scope picker + client-side name validation; AdminGroupsPage group-admin checkbox Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
43 lines
1.5 KiB
Python
43 lines
1.5 KiB
Python
from fastapi import Header, HTTPException
|
|
|
|
|
|
async def get_user_id(x_user_id: str = Header(...)) -> str:
|
|
"""
|
|
Extract the user identity injected by the main backend proxy.
|
|
The main backend validates the JWT and forwards the user ID via this header.
|
|
Doc-service trusts it because it is only reachable from backend on backend-net.
|
|
"""
|
|
if not x_user_id:
|
|
raise HTTPException(status_code=400, detail="Missing X-User-Id header")
|
|
return x_user_id
|
|
|
|
|
|
async def get_user_groups(x_user_groups: str = Header(default="")) -> list[str]:
|
|
"""
|
|
Extract the group IDs injected by the main backend proxy.
|
|
Comma-separated list of group UUIDs the current user belongs to.
|
|
Returns an empty list if the header is absent or empty.
|
|
"""
|
|
if not x_user_groups:
|
|
return []
|
|
return [g.strip() for g in x_user_groups.split(",") if g.strip()]
|
|
|
|
|
|
async def get_user_is_admin(x_user_is_admin: str = Header(default="false")) -> bool:
|
|
"""
|
|
Extract the superuser flag injected by the main backend proxy.
|
|
Returns True only when the header value is exactly "true".
|
|
"""
|
|
return x_user_is_admin.lower() == "true"
|
|
|
|
|
|
async def get_user_admin_groups(x_user_admin_groups: str = Header(default="")) -> list[str]:
|
|
"""
|
|
Extract the group IDs for which the current user is a group admin.
|
|
Injected by the main backend proxy from GroupMembership.is_group_admin.
|
|
Returns an empty list if absent or empty.
|
|
"""
|
|
if not x_user_admin_groups:
|
|
return []
|
|
return [g.strip() for g in x_user_admin_groups.split(",") if g.strip()]
|