Allow specifying multiple permissions.

This commit is contained in:
Leo Vasanko 2025-08-30 16:47:38 -06:00
parent cb17a332a3
commit 16de7b5f1f
3 changed files with 12 additions and 11 deletions

View File

@ -44,12 +44,12 @@ def register_api_routes(app: FastAPI):
@app.post("/auth/validate") @app.post("/auth/validate")
async def validate_token( async def validate_token(
response: Response, perm: str | None = None, auth=Cookie(None) response: Response, perm: list[str] | None = None, auth=Cookie(None)
): ):
"""Lightweight token validation endpoint. """Lightweight token validation endpoint.
Query Params: Query Params:
- perm: optional permission ID the caller must possess - perm: repeated permission IDs the caller must possess (ALL required)
""" """
s = await authz.verify(auth, perm) s = await authz.verify(auth, perm)

View File

@ -12,23 +12,24 @@ from ..globals import db
from ..util.tokens import session_key from ..util.tokens import session_key
async def verify(auth: str | None, perm: str | None): async def verify(auth: str | None, perms: list[str] | None):
"""Validate session token and optional permission. """Validate session token and optional list of required permissions.
Returns the Session object on success. Raises HTTPException on failure. Returns the Session object on success. Raises HTTPException on failure.
401: unauthenticated / invalid session 401: unauthenticated / invalid session
403: missing required permission 403: one or more required permissions missing
""" """
if not auth: if not auth:
raise HTTPException(status_code=401, detail="Authentication required") raise HTTPException(status_code=401, detail="Authentication required")
session = await get_session(auth) session = await get_session(auth)
if perm: if perms:
ctx = await db.instance.get_session_context(session_key(auth)) ctx = await db.instance.get_session_context(session_key(auth))
if not ctx: if not ctx:
raise HTTPException(status_code=401, detail="Session not found") raise HTTPException(status_code=401, detail="Session not found")
role_perms = set(ctx.role.permissions or []) available = set(ctx.role.permissions or []) | (
org_perms = set(ctx.org.permissions or []) if ctx.org else set() set(ctx.org.permissions or []) if ctx.org else set()
if perm not in role_perms and perm not in org_perms: )
if any(p not in available for p in perms):
raise HTTPException(status_code=403, detail="Permission required") raise HTTPException(status_code=403, detail="Permission required")
return session return session

View File

@ -73,12 +73,12 @@ app.mount("/auth/ws", ws.app)
@app.get("/auth/forward-auth") @app.get("/auth/forward-auth")
async def forward_authentication( async def forward_authentication(
request: Request, perm: str | None = None, auth=Cookie(None) request: Request, perm: list[str] | None = None, auth=Cookie(None)
): ):
"""A validation endpoint to use with Caddy forward_auth or Nginx auth_request. """A validation endpoint to use with Caddy forward_auth or Nginx auth_request.
Query Params: Query Params:
- perm: optional permission ID the authenticated user must possess (role or org). - perm: repeated permission IDs the authenticated user must possess (ALL required).
Success: 204 No Content with x-auth-user-uuid header. Success: 204 No Content with x-auth-user-uuid header.
Failure (unauthenticated / unauthorized): 4xx with index.html body so the Failure (unauthenticated / unauthorized): 4xx with index.html body so the