import os from dataclasses import dataclass from pathlib import Path # The modal shows this many days of run history; retention can never be shorter. HISTORY_DAYS = 30 # Shared by the systemd service (EnvironmentFile=) and manage.py, so both always use the same DB. DEFAULT_ENV_FILE = "/etc/backup-dashboard/backup-dashboard.env" @dataclass(frozen=True) class Settings: db_path: Path retention_days: int = 90 # Dev only: serve ../public from the API so you can run without nginx. serve_static: bool = False # Microsoft 365 sign-in names allowed into the admin pages (lowercase) admins: frozenset[str] = frozenset() def read_env_file(path: Path) -> dict[str, str]: """Parse simple KEY=VALUE lines (the subset systemd's EnvironmentFile accepts).""" values = {} try: lines = path.read_text().splitlines() except FileNotFoundError: return values for line in lines: line = line.strip() if not line or line.startswith("#") or "=" not in line: continue key, _, value = line.partition("=") values[key.strip()] = value.strip().strip("\"'") return values def load_settings() -> Settings: # Real environment variables win over the env file; the env file wins over dev defaults. env = read_env_file(Path(os.environ.get("BACKUP_DASH_ENV_FILE", DEFAULT_ENV_FILE))) | os.environ return Settings( db_path=Path(env.get("BACKUP_DASH_DB", "backup-dashboard.db")), retention_days=max(HISTORY_DAYS, int(env.get("BACKUP_DASH_RETENTION_DAYS", "90"))), serve_static=env.get("BACKUP_DASH_SERVE_STATIC") == "1", admins=parse_admins(env.get("BACKUP_DASH_ADMINS", "")), ) def parse_admins(value: str) -> frozenset[str]: """'kyle@example.com, Pat@Example.com' -> {'kyle@example.com', 'pat@example.com'}""" return frozenset(part.strip().lower() for part in value.replace(";", ",").split(",") if part.strip())