from __future__ import annotations from typing import Any from config import CONFIGURABLE_FIELDS, reload_settings from paths import get_dates_file_path from services.pts_client import normalize_pts_base_url from services.secret_box import encrypt_secret from services.settings_store import ( PASSWORD_FIELDS, is_masked_or_empty, load_overrides, public_view, save_overrides, SECRET_FIELDS, ) from config import get_settings_dict class SettingsService: def get_public_settings(self) -> dict[str, Any]: return public_view(get_settings_dict()) def save_settings(self, payload: dict[str, Any]) -> dict[str, Any]: overrides = load_overrides() updates = {k: payload[k] for k in CONFIGURABLE_FIELDS if k in payload} for field in SECRET_FIELDS: if field in updates and is_masked_or_empty(updates[field]): updates.pop(field) elif field in updates and updates[field] is not None: # strip whitespace / accidental quotes from pasted tokens updates[field] = str(updates[field]).strip().strip("\"'") for field in PASSWORD_FIELDS: if field in updates and updates[field]: updates[field] = encrypt_secret(str(updates[field])) if "pts_url" in updates and updates["pts_url"]: updates["pts_url"] = normalize_pts_base_url(str(updates["pts_url"])) overrides.update(updates) save_overrides(overrides) from services.scheduler import reschedule_scheduler reload_settings() reschedule_scheduler() return self.get_public_settings() def get_dates_file(self) -> str: path = get_dates_file_path() if not path.exists(): return "" return path.read_text(encoding="utf-8") def save_dates_file(self, content: str) -> None: path = get_dates_file_path() path.parent.mkdir(parents=True, exist_ok=True) path.write_text(content, encoding="utf-8")