Cleaned up login/logout flows.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import logging
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
from fastapi import Body, Cookie, FastAPI, HTTPException
|
||||
from fastapi.responses import FileResponse, JSONResponse
|
||||
from fastapi import Body, Cookie, FastAPI, HTTPException, Request
|
||||
from fastapi.responses import FileResponse, JSONResponse, RedirectResponse
|
||||
|
||||
from ..authsession import expires
|
||||
from ..globals import db
|
||||
@@ -24,8 +24,14 @@ async def general_exception_handler(_request, exc: Exception):
|
||||
return JSONResponse(status_code=500, content={"detail": "Internal server error"})
|
||||
|
||||
|
||||
@app.get("")
|
||||
def adminapp_slashmissing(request: Request):
|
||||
print("HERE")
|
||||
return RedirectResponse(url=request.url_for("adminapp"))
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def admin_frontend(auth=Cookie(None)):
|
||||
async def adminapp(auth=Cookie(None)):
|
||||
try:
|
||||
await authz.verify(auth, ["auth:admin", "auth:org:*"], match=permutil.has_any)
|
||||
return FileResponse(frontend.file("admin/index.html"))
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import logging
|
||||
|
||||
from fastapi import HTTPException
|
||||
|
||||
from ..util import permutil
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def verify(auth: str | None, perm: list[str], match=permutil.has_all):
|
||||
"""Validate session token and optional list of required permissions.
|
||||
@@ -20,6 +24,16 @@ async def verify(auth: str | None, perm: list[str], match=permutil.has_all):
|
||||
raise HTTPException(status_code=401, detail="Session not found")
|
||||
|
||||
if not match(ctx, perm):
|
||||
# Determine which permissions are missing for clearer diagnostics
|
||||
missing = sorted(set(perm) - set(ctx.role.permissions))
|
||||
logger.warning(
|
||||
"Permission denied: user=%s role=%s missing=%s required=%s granted=%s", # noqa: E501
|
||||
getattr(ctx.user, "uuid", "?"),
|
||||
getattr(ctx.role, "display_name", "?"),
|
||||
missing,
|
||||
perm,
|
||||
ctx.role.permissions,
|
||||
)
|
||||
raise HTTPException(status_code=403, detail="Permission required")
|
||||
|
||||
return ctx
|
||||
|
||||
@@ -46,10 +46,12 @@ async def lifespan(app: FastAPI): # pragma: no cover - startup path
|
||||
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
app.mount("/auth/admin", admin.app)
|
||||
app.mount("/auth/api", api.app)
|
||||
app.mount("/auth/ws", ws.app)
|
||||
app.mount("/auth/assets", StaticFiles(directory=frontend.file("assets")), name="assets")
|
||||
app.mount("/auth/admin/", admin.app)
|
||||
app.mount("/auth/api/", api.app)
|
||||
app.mount("/auth/ws/", ws.app)
|
||||
app.mount(
|
||||
"/auth/assets/", StaticFiles(directory=frontend.file("assets")), name="assets"
|
||||
)
|
||||
|
||||
|
||||
@app.get("/auth/")
|
||||
@@ -61,6 +63,9 @@ async def frontapp():
|
||||
@app.get("/auth/{reset}")
|
||||
async def reset_link(request: Request, reset: str):
|
||||
"""Pretty URL for reset links."""
|
||||
if reset == "admin":
|
||||
# Admin app missing trailing slash lands here, be friendly to user
|
||||
return RedirectResponse(request.url_for("adminapp"), status_code=303)
|
||||
if not passphrase.is_well_formed(reset):
|
||||
raise HTTPException(status_code=404)
|
||||
url = request.url_for("frontapp").include_query_params(reset=reset)
|
||||
|
||||
Reference in New Issue
Block a user