Update admin theme/layout and refresh README details.
Align the project baseline with the latest admin interface styling and layout structure while documenting setup and usage updates in README.
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
SETTINGS_ENV_KEYS: dict[str, str] = {
|
||||
"enable_rate_limit": "ENABLE_RATE_LIMIT",
|
||||
"enable_docs": "ENABLE_DOCS",
|
||||
"cookie_secure": "COOKIE_SECURE",
|
||||
"jwt_access_ttl_min": "JWT_ACCESS_TTL_MIN",
|
||||
"auth_lockout_attempts": "AUTH_LOCKOUT_ATTEMPTS",
|
||||
"auth_lockout_minutes": "AUTH_LOCKOUT_MINUTES",
|
||||
"cors_origins": "CORS_ORIGINS",
|
||||
"frontend_url": "FRONTEND_URL",
|
||||
"public_base_url": "PUBLIC_BASE_URL",
|
||||
"smtp_host": "SMTP_HOST",
|
||||
"smtp_port": "SMTP_PORT",
|
||||
"smtp_from": "SMTP_FROM",
|
||||
"avatar_max_bytes": "AVATAR_MAX_BYTES",
|
||||
"media_url_ttl_seconds": "MEDIA_URL_TTL_SECONDS",
|
||||
"log_level": "LOG_LEVEL",
|
||||
"audit_retention_days": "AUDIT_RETENTION_DAYS",
|
||||
"jwt_refresh_ttl_days": "JWT_REFRESH_TTL_DAYS",
|
||||
}
|
||||
|
||||
MANAGED_KEYS = tuple(SETTINGS_ENV_KEYS.keys())
|
||||
|
||||
|
||||
def _settings_file() -> Path:
|
||||
return Path(settings.compton_settings_path)
|
||||
|
||||
|
||||
def get_settings_values() -> dict[str, Any]:
|
||||
return {key: getattr(settings, key) for key in MANAGED_KEYS}
|
||||
|
||||
|
||||
def _coerce_value(key: str, value: Any) -> Any:
|
||||
current = getattr(settings, key)
|
||||
if isinstance(current, bool):
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
return value.lower() in {"1", "true", "yes", "on"}
|
||||
return bool(value)
|
||||
if isinstance(current, int):
|
||||
return int(value)
|
||||
if isinstance(current, list):
|
||||
if isinstance(value, list):
|
||||
return [str(item) for item in value]
|
||||
if isinstance(value, str):
|
||||
return [item.strip() for item in value.split(",") if item.strip()]
|
||||
raise ValueError(f"INVALID_LIST_{key}")
|
||||
return value
|
||||
|
||||
|
||||
def env_locks() -> dict[str, bool]:
|
||||
return {key: os.getenv(env_key) is not None for key, env_key in SETTINGS_ENV_KEYS.items()}
|
||||
|
||||
|
||||
def apply_settings_to_app(values: dict[str, Any]) -> None:
|
||||
for key, value in values.items():
|
||||
if key not in MANAGED_KEYS:
|
||||
continue
|
||||
setattr(settings, key, _coerce_value(key, value))
|
||||
|
||||
|
||||
def read_settings() -> dict[str, Any]:
|
||||
path = _settings_file()
|
||||
if not path.exists():
|
||||
return {}
|
||||
with path.open("r", encoding="utf-8") as file:
|
||||
payload = json.load(file)
|
||||
if not isinstance(payload, dict):
|
||||
return {}
|
||||
return {key: payload[key] for key in MANAGED_KEYS if key in payload}
|
||||
|
||||
|
||||
def write_settings(partial: dict[str, Any]) -> dict[str, Any]:
|
||||
locks = env_locks()
|
||||
current = get_settings_values()
|
||||
for key, value in partial.items():
|
||||
if key not in MANAGED_KEYS:
|
||||
continue
|
||||
if locks[key]:
|
||||
continue
|
||||
current[key] = _coerce_value(key, value)
|
||||
|
||||
path = _settings_file()
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with path.open("w", encoding="utf-8") as file:
|
||||
json.dump(current, file, ensure_ascii=False, indent=2)
|
||||
return current
|
||||
|
||||
|
||||
def bootstrap_settings() -> None:
|
||||
apply_settings_to_app(read_settings())
|
||||
|
||||
|
||||
def get_settings_payload() -> dict[str, Any]:
|
||||
locks = env_locks()
|
||||
values = get_settings_values()
|
||||
secrets = {
|
||||
"jwt_access_secret_configured": bool(settings.jwt_access_secret),
|
||||
"jwt_refresh_pepper_configured": bool(settings.jwt_refresh_pepper),
|
||||
"smtp_password_configured": bool(settings.smtp_password),
|
||||
"s3_secret_key_configured": bool(settings.s3_secret_key),
|
||||
}
|
||||
return {
|
||||
"values": values,
|
||||
"locks": locks,
|
||||
"settings_path": str(_settings_file()),
|
||||
"secrets": secrets,
|
||||
}
|
||||
Reference in New Issue
Block a user