from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from . import models # noqa: F401 (registers tables) from .routers import activity, admin, auth, mail, reports, years app = FastAPI(title="Budget & Capex", docs_url="/api/docs", openapi_url="/api/openapi.json") @app.middleware("http") async def csrf_guard(request: Request, call_next): # Cookies are SameSite=Lax; requiring a custom header on writes also blocks cross-site form posts. if request.method not in ("GET", "HEAD", "OPTIONS") and request.url.path.startswith("/api/"): if request.headers.get("x-requested-with") != "budget-app": return JSONResponse({"detail": "missing_header"}, status_code=403) return await call_next(request) @app.get("/api/health") def health(): return {"ok": True} for r in (auth.router, admin.router, years.router, reports.router, mail.router, activity.router): app.include_router(r)