91 lines
2.9 KiB
Python
91 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import secrets
|
|
from pathlib import Path
|
|
|
|
|
|
def _default_data_dir() -> Path:
|
|
return Path(os.getenv("SALDO_DATA_DIR", Path.cwd() / "instance")).resolve()
|
|
|
|
|
|
def _secret_key(data_dir: Path) -> str:
|
|
configured = os.getenv("SECRET_KEY")
|
|
if configured:
|
|
return configured
|
|
|
|
secret_file = data_dir / ".secret_key"
|
|
if secret_file.exists():
|
|
return secret_file.read_text(encoding="utf-8").strip()
|
|
|
|
data_dir.mkdir(parents=True, exist_ok=True)
|
|
generated = secrets.token_hex(32)
|
|
secret_file.write_text(generated, encoding="utf-8")
|
|
return generated
|
|
|
|
|
|
class Config:
|
|
APP_NAME = "Saldo"
|
|
DATA_DIR = _default_data_dir()
|
|
SECRET_KEY = _secret_key(DATA_DIR)
|
|
AVATAR_UPLOAD_DIR = DATA_DIR / "avatars"
|
|
SQLALCHEMY_DATABASE_URI = os.getenv(
|
|
"DATABASE_URL",
|
|
f"sqlite:///{(DATA_DIR / 'saldo.db').as_posix()}",
|
|
)
|
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
REMEMBER_COOKIE_DURATION = 60 * 60 * 24 * 30
|
|
MAX_CONTENT_LENGTH = int(os.getenv("SALDO_MAX_CONTENT_LENGTH", str(5 * 1024 * 1024)))
|
|
SESSION_COOKIE_HTTPONLY = True
|
|
SESSION_COOKIE_SAMESITE = "Lax"
|
|
REMEMBER_COOKIE_HTTPONLY = True
|
|
REMEMBER_COOKIE_SAMESITE = "Lax"
|
|
SESSION_COOKIE_SECURE = os.getenv("SALDO_SESSION_COOKIE_SECURE", "0") != "0"
|
|
REMEMBER_COOKIE_SECURE = SESSION_COOKIE_SECURE
|
|
CSRF_ENABLED = os.getenv("SALDO_CSRF_ENABLED", "1") != "0"
|
|
|
|
VAPID_PUBLIC_KEY = os.getenv("VAPID_PUBLIC_KEY", "")
|
|
VAPID_PRIVATE_KEY = os.getenv("VAPID_PRIVATE_KEY", "")
|
|
VAPID_CLAIMS = {
|
|
"sub": os.getenv("VAPID_SUBJECT", "mailto:admin@example.invalid"),
|
|
}
|
|
|
|
ADMIN_BOOTSTRAP_USERNAME = os.getenv("SALDO_ADMIN_USERNAME", "admin")
|
|
ADMIN_BOOTSTRAP_PASSWORD = os.getenv("SALDO_ADMIN_PASSWORD", "")
|
|
ADMIN_BOOTSTRAP_EMAIL = os.getenv("SALDO_ADMIN_EMAIL", "admin@example.invalid")
|
|
|
|
ALLOCATION_TARGET_RULES = json.loads(
|
|
os.getenv(
|
|
"SALDO_ALLOCATION_TARGET_RULES",
|
|
json.dumps(
|
|
{
|
|
"sparen": {
|
|
"recommended_pct": 0.18,
|
|
"min_pct": 0.15,
|
|
"max_pct": 0.20,
|
|
"label": "Sparen",
|
|
},
|
|
"urlaub": {
|
|
"recommended_pct": 0.06,
|
|
"min_pct": 0.05,
|
|
"max_pct": 0.08,
|
|
"label": "Urlaub",
|
|
},
|
|
"freizeit": {
|
|
"recommended_pct": 0.07,
|
|
"min_pct": 0.05,
|
|
"max_pct": 0.10,
|
|
"label": "Freizeit",
|
|
},
|
|
}
|
|
),
|
|
)
|
|
)
|
|
DEFAULT_PERSONAL_SPLIT_DESI_PCT = float(
|
|
os.getenv("SALDO_DEFAULT_PERSONAL_SPLIT_DESI_PCT", "50")
|
|
)
|
|
STRONG_INCOME_CHANGE_THRESHOLD = float(
|
|
os.getenv("SALDO_STRONG_INCOME_CHANGE_THRESHOLD", "150")
|
|
)
|