import os from contextlib import asynccontextmanager from dotenv import load_dotenv from fastapi import FastAPI, Request from fastapi.responses import RedirectResponse from fastapi.staticfiles import StaticFiles from starlette.middleware.sessions import SessionMiddleware from starlette.middleware.base import BaseHTTPMiddleware from database import init_db from routers import about, auth, films, imports as imports_router, profile, stats, tmdb load_dotenv() class AuthMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): public_paths = {"/about", "/login", "/logout", "/tyler", "/films/partial", "/tyler/films/partial", "/tyler/api/recent"} path = request.url.path if path.startswith("/static") or path in public_paths: return await call_next(request) if not request.session.get("authenticated"): return RedirectResponse("/login", status_code=303) return await call_next(request) @asynccontextmanager async def lifespan(app: FastAPI): init_db() yield app = FastAPI(title="Lumière", lifespan=lifespan) # Middleware order: SessionMiddleware first, then AuthMiddleware session_secret = os.getenv("SESSION_SECRET", "change-me-in-production") app.add_middleware(AuthMiddleware) app.add_middleware(SessionMiddleware, secret_key=session_secret) app.mount("/static", StaticFiles(directory="static"), name="static") app.include_router(about.router) app.include_router(auth.router) app.include_router(profile.router) app.include_router(tmdb.router) app.include_router(imports_router.router) app.include_router(stats.router) app.include_router(films.router)