Make default permissions use only : as separator.
This commit is contained in:
parent
326a7664d3
commit
d045e1c520
@ -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/",
|
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user