"""Anmeldung ueber ein einzelnes Passwort, Sitzung als signiertes Cookie.""" import hashlib import hmac import time from fastapi import HTTPException, Request from . import config COOKIE = "bcs_session" def enabled() -> bool: return bool(config.APP_PASSWORD) def _sign(payload: str) -> str: return hmac.new( config.SECRET_KEY.encode(), payload.encode(), hashlib.sha256 ).hexdigest() def issue_token() -> str: expires = str(int(time.time()) + config.SESSION_DAYS * 86400) return f"{expires}.{_sign(expires)}" def valid_token(token: str | None) -> bool: if not token or "." not in token: return False expires, signature = token.split(".", 1) if not hmac.compare_digest(signature, _sign(expires)): return False try: return int(expires) > time.time() except ValueError: return False def check_password(candidate: str) -> bool: return hmac.compare_digest(candidate, config.APP_PASSWORD) def require_auth(request: Request) -> None: """FastAPI-Abhaengigkeit fuer alle geschuetzten Endpunkte.""" if not enabled(): return if not valid_token(request.cookies.get(COOKIE)): raise HTTPException(status_code=401, detail="Nicht angemeldet")