Make default permissions use only : as separator.
This commit is contained in:
		| @@ -66,7 +66,7 @@ async def bootstrap_system( | |||||||
|         dict: Contains information about created entities and reset link |         dict: Contains information about created entities and reset link | ||||||
|     """ |     """ | ||||||
|     # Create permission first - will fail if already exists |     # Create permission first - will fail if already exists | ||||||
|     perm0 = Permission(id="auth/admin", display_name="Master Admin") |     perm0 = Permission(id="auth:admin", display_name="Master Admin") | ||||||
|     await globals.db.instance.create_permission(perm0) |     await globals.db.instance.create_permission(perm0) | ||||||
|  |  | ||||||
|     org = Org(uuid7.create(), org_name or "Organization") |     org = Org(uuid7.create(), org_name or "Organization") | ||||||
| @@ -122,7 +122,7 @@ async def check_admin_credentials() -> bool: | |||||||
|     try: |     try: | ||||||
|         # Get permission organizations to find admin users |         # Get permission organizations to find admin users | ||||||
|         permission_orgs = await globals.db.instance.get_permission_organizations( |         permission_orgs = await globals.db.instance.get_permission_organizations( | ||||||
|             "auth/admin" |             "auth:admin" | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         if not permission_orgs: |         if not permission_orgs: | ||||||
| @@ -173,7 +173,7 @@ async def bootstrap_if_needed( | |||||||
|     """ |     """ | ||||||
|     try: |     try: | ||||||
|         # Check if the admin permission exists - if it does, system is already bootstrapped |         # Check if the admin permission exists - if it does, system is already bootstrapped | ||||||
|         await globals.db.instance.get_permission("auth/admin") |         await globals.db.instance.get_permission("auth:admin") | ||||||
|         # Permission exists, system is already bootstrapped |         # Permission exists, system is already bootstrapped | ||||||
|         # Check if admin needs credentials (only for already-bootstrapped systems) |         # Check if admin needs credentials (only for already-bootstrapped systems) | ||||||
|         await check_admin_credentials() |         await check_admin_credentials() | ||||||
|   | |||||||
| @@ -462,8 +462,7 @@ class DB(DatabaseInterface): | |||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|             # Automatically create an organization admin permission if not present. |             # Automatically create an organization admin permission if not present. | ||||||
|             # Pattern: auth/org:<org-uuid> |             auto_perm_id = f"auth:org:{org.uuid}" | ||||||
|             auto_perm_id = f"auth/org:{org.uuid}" |  | ||||||
|             # Only create if it does not already exist (in case caller passed it) |             # Only create if it does not already exist (in case caller passed it) | ||||||
|             existing_perm = await session.execute( |             existing_perm = await session.execute( | ||||||
|                 select(PermissionModel).where(PermissionModel.id == auto_perm_id) |                 select(PermissionModel).where(PermissionModel.id == auto_perm_id) | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ This module contains all the HTTP API endpoints for: | |||||||
|  |  | ||||||
| from uuid import UUID, uuid4 | from uuid import UUID, uuid4 | ||||||
|  |  | ||||||
| from fastapi import Body, Cookie, Depends, FastAPI, HTTPException, Response | from fastapi import Body, Cookie, Depends, FastAPI, HTTPException, Query, Response | ||||||
| from fastapi.security import HTTPBearer | from fastapi.security import HTTPBearer | ||||||
|  |  | ||||||
| from passkey.util import passphrase | from passkey.util import passphrase | ||||||
| @@ -38,14 +38,12 @@ def register_api_routes(app: FastAPI): | |||||||
|             raise ValueError("Not authenticated") |             raise ValueError("Not authenticated") | ||||||
|         role_perm_ids = set(ctx.role.permissions or []) |         role_perm_ids = set(ctx.role.permissions or []) | ||||||
|         org_uuid_str = str(ctx.org.uuid) |         org_uuid_str = str(ctx.org.uuid) | ||||||
|         is_global_admin = "auth/admin" in role_perm_ids |         is_global_admin = "auth:admin" in role_perm_ids | ||||||
|         is_org_admin = f"auth/org:{org_uuid_str}" in role_perm_ids |         is_org_admin = f"auth:org:{org_uuid_str}" in role_perm_ids | ||||||
|         return ctx, is_global_admin, is_org_admin |         return ctx, is_global_admin, is_org_admin | ||||||
|  |  | ||||||
|     @app.post("/auth/validate") |     @app.post("/auth/validate") | ||||||
|     async def validate_token( |     async def validate_token(perm=Query(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: | ||||||
| @@ -137,9 +135,9 @@ def register_api_routes(app: FastAPI): | |||||||
|                 "permissions": ctx.org.permissions, |                 "permissions": ctx.org.permissions, | ||||||
|             } |             } | ||||||
|             effective_permissions = [p.id for p in (ctx.permissions or [])] |             effective_permissions = [p.id for p in (ctx.permissions or [])] | ||||||
|             is_global_admin = "auth/admin" in role_info["permissions"] |             is_global_admin = "auth:admin" in role_info["permissions"] | ||||||
|             is_org_admin = ( |             is_org_admin = ( | ||||||
|                 f"auth/org:{org_info['uuid']}" in role_info["permissions"] |                 f"auth:org:{org_info['uuid']}" in role_info["permissions"] | ||||||
|                 if org_info |                 if org_info | ||||||
|                 else False |                 else False | ||||||
|             ) |             ) | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ from ..globals import db | |||||||
| from ..util.tokens import session_key | from ..util.tokens import session_key | ||||||
|  |  | ||||||
|  |  | ||||||
| async def verify(auth: str | None, perms: list[str] | None): | async def verify(auth: str | None, perm: list[str] | str | None): | ||||||
|     """Validate session token and optional list of required permissions. |     """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. | ||||||
| @@ -22,14 +22,16 @@ async def verify(auth: str | None, perms: list[str] | None): | |||||||
|     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 perms: |     if perm is not None: | ||||||
|  |         if isinstance(perm, str): | ||||||
|  |             perm = [perm] | ||||||
|         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") | ||||||
|         available = set(ctx.role.permissions or []) | ( |         available = set(ctx.role.permissions or []) | ( | ||||||
|             set(ctx.org.permissions or []) if ctx.org else set() |             set(ctx.org.permissions or []) if ctx.org else set() | ||||||
|         ) |         ) | ||||||
|         if any(p not in available for p in perms): |         if any(p not in available for p in perm): | ||||||
|             raise HTTPException(status_code=403, detail="Permission required") |             raise HTTPException(status_code=403, detail="Permission required") | ||||||
|     return session |     return session | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import os | |||||||
| from contextlib import asynccontextmanager | from contextlib import asynccontextmanager | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  |  | ||||||
| from fastapi import Cookie, FastAPI, HTTPException, Request, Response | from fastapi import Cookie, FastAPI, HTTPException, Query, Request, Response | ||||||
| from fastapi.responses import FileResponse, JSONResponse | from fastapi.responses import FileResponse, JSONResponse | ||||||
| from fastapi.staticfiles import StaticFiles | from fastapi.staticfiles import StaticFiles | ||||||
|  |  | ||||||
| @@ -72,9 +72,7 @@ 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=Query(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: | ||||||
|   | |||||||
| @@ -30,5 +30,4 @@ def set_session_cookie(response: Response, token: str) -> None: | |||||||
|         max_age=int(EXPIRES.total_seconds()), |         max_age=int(EXPIRES.total_seconds()), | ||||||
|         httponly=True, |         httponly=True, | ||||||
|         secure=True, |         secure=True, | ||||||
|         path="/auth/", |  | ||||||
|     ) |     ) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Leo Vasanko
					Leo Vasanko