31 lines
1.2 KiB
Python
31 lines
1.2 KiB
Python
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"},
|
|
)
|