30 lines
972 B
Python
30 lines
972 B
Python
import secrets
|
|
|
|
from fastapi import HTTPException, Request, status
|
|
|
|
|
|
def configured_token(app) -> str:
|
|
runtime = getattr(app.state, "runtime", None)
|
|
return runtime.settings.chart_auth_token if runtime else ""
|
|
|
|
|
|
def token_matches(app, presented: str) -> bool:
|
|
"""True when the caller may proceed.
|
|
|
|
An empty CHART_AUTH_TOKEN leaves everything open, which is what local
|
|
development wants — the check only engages once a token is configured.
|
|
"""
|
|
want = configured_token(app)
|
|
if not want:
|
|
return True
|
|
return secrets.compare_digest(presented or "", want)
|
|
|
|
|
|
def require_token(request: Request) -> None:
|
|
presented = request.headers.get("x-chart-token") or request.query_params.get("token", "")
|
|
if not token_matches(request.app, presented):
|
|
raise HTTPException(
|
|
status.HTTP_401_UNAUTHORIZED,
|
|
"Missing or invalid chart token",
|
|
headers={"WWW-Authenticate": "X-Chart-Token"},
|
|
)
|