from __future__ import annotations import json from quart import Blueprint, render_template, request, current_app from sqlalchemy import select from steward.auth.middleware import require_role from steward.models.audit import AuditEvent from steward.models.users import UserRole audit_bp = Blueprint("audit", __name__, url_prefix="/audit") @audit_bp.get("/") @require_role(UserRole.admin) async def list_events(): limit = min(int(request.args.get("limit", 200)), 500) action_filter = request.args.get("action", "").strip() async with current_app.db_sessionmaker() as db: stmt = select(AuditEvent).order_by(AuditEvent.timestamp.desc()).limit(limit) if action_filter: stmt = select(AuditEvent).where( AuditEvent.action.like(f"{action_filter}%") ).order_by(AuditEvent.timestamp.desc()).limit(limit) result = await db.execute(stmt) events = result.scalars().all() # Parse detail_json for display parsed = [] for e in events: detail = {} if e.detail_json: try: detail = json.loads(e.detail_json) except (ValueError, TypeError): detail = {"raw": e.detail_json} parsed.append({"event": e, "detail": detail}) return await render_template( "audit/list.html", events=parsed, limit=limit, action_filter=action_filter, )