import logging import os import secrets from pathlib import Path from sqladmin.authentication import AuthenticationBackend from starlette.requests import Request BASE_DIR = Path(__file__).resolve().parent.parent SECRET_FILE = BASE_DIR / ".session_secret" logger = logging.getLogger("idrs.auth") def get_admin_credentials(): user = os.environ.get("ADMIN_USERNAME", "") password = os.environ.get("ADMIN_PASSWORD", "") return user, password def get_session_secret(): secret = os.environ.get("IDRS_SESSION_SECRET", "") if not secret: if SECRET_FILE.exists(): secret = SECRET_FILE.read_text(encoding="utf-8").strip() else: secret = secrets.token_urlsafe(48) SECRET_FILE.write_text(secret, encoding="utf-8") os.chmod(SECRET_FILE, 0o600) return secret def credentials_configured() -> bool: user, password = get_admin_credentials() return bool(user and password) class AdminAuthBackend(AuthenticationBackend): async def authenticate(self, request: Request) -> bool: return bool(request.session.get("auth")) async def login(self, request: Request) -> bool: user, password = get_admin_credentials() if not (user and password): logger.warning("ADMIN_USERNAME/ADMIN_PASSWORD not set — login refused (fail closed)") return False form = await request.form() if secrets.compare_digest(form.get("username", ""), user) and secrets.compare_digest( form.get("password", ""), password ): request.session["auth"] = True return True return False async def logout(self, request: Request) -> bool: request.session.clear() return True