import secrets from fastapi import Header, HTTPException, status from app.core.config import settings def require_admin(authorization: str | None = Header(default=None)) -> None: """Gate admin endpoints on a Bearer token equal to ADMIN_PASSWORD. The token is issued by POST /admin/login after the username + password match the values from .env. We keep things deliberately simple — no JWT, no expiry — because there is exactly one admin account. """ if not settings.ADMIN_PASSWORD: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Admin account is not configured", ) if not authorization or not authorization.lower().startswith("bearer "): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Missing bearer token", headers={"WWW-Authenticate": "Bearer"}, ) token = authorization.split(" ", 1)[1].strip() if not secrets.compare_digest(token, settings.ADMIN_PASSWORD): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token", headers={"WWW-Authenticate": "Bearer"}, )