Initial commit: moon-household-budget
This commit is contained in:
52
settings.py
Normal file
52
settings.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""App settings + secret storage (Gmail credentials, reminder prefs, etc.).
|
||||
|
||||
Stored as JSON on the data volume (DATA_DIR/settings.json) via the atomic
|
||||
storage layer — so it is NEVER committed to source control. Secrets resolve
|
||||
with an environment-variable fallback, so a value can come from the settings
|
||||
page OR from the container's .env.
|
||||
|
||||
This is what lets us pull the hardcoded Gmail app password out of reminders.py
|
||||
(issue #2): the password lives in settings.json on the volume instead.
|
||||
"""
|
||||
import os
|
||||
from storage import load_json, save_json, DATA_DIR
|
||||
|
||||
SETTINGS_FILE = os.path.join(DATA_DIR, "settings.json")
|
||||
|
||||
# Keys holding secrets — their values are never rendered back to the browser.
|
||||
SECRET_KEYS = {"gmail_app_password"}
|
||||
|
||||
DEFAULTS = {
|
||||
"gmail_address": "",
|
||||
"gmail_app_password": "",
|
||||
"reminder_recipient": "", # blank => send to gmail_address
|
||||
"reminders_enabled": True,
|
||||
}
|
||||
|
||||
|
||||
def load_settings():
|
||||
data = load_json(SETTINGS_FILE, {}) or {}
|
||||
merged = dict(DEFAULTS)
|
||||
merged.update(data)
|
||||
return merged
|
||||
|
||||
|
||||
def save_settings(data):
|
||||
save_json(SETTINGS_FILE, data)
|
||||
|
||||
|
||||
def get_setting(key, env=None, default=""):
|
||||
"""Resolve a setting: stored value first, then env var, then default."""
|
||||
val = load_settings().get(key)
|
||||
if val not in (None, ""):
|
||||
return val
|
||||
if env:
|
||||
env_val = os.environ.get(env)
|
||||
if env_val not in (None, ""):
|
||||
return env_val
|
||||
return default
|
||||
|
||||
|
||||
def is_set(key):
|
||||
"""True if a (typically secret) value is present, without revealing it."""
|
||||
return bool(load_settings().get(key))
|
||||
Reference in New Issue
Block a user