57 lines
1.7 KiB
Python
57 lines
1.7 KiB
Python
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 |