| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- """
- app/config.py
- ─────────────
- Central settings object built from environment variables via pydantic-settings.
- All sensitive values must be supplied via the .env file or container env vars —
- never hard-coded here.
- """
- from __future__ import annotations
- from typing import Optional
- from pydantic_settings import BaseSettings, SettingsConfigDict
- class Settings(BaseSettings):
- model_config = SettingsConfigDict(
- env_file=".env",
- env_file_encoding="utf-8",
- extra="allow", # allow arbitrary env vars (forwarded to /api/config)
- case_sensitive=True,
- )
- # ── Database ──────────────────────────────────────────────────────────────
- DATABASE_URL: str
- # ── JWT / Authentication ──────────────────────────────────────────────────
- SECRET_KEY: str
- ALGORITHM: str = "HS256"
- ACCESS_TOKEN_EXPIRE_MINUTES: int = 120
- # ── CORS ──────────────────────────────────────────────────────────────────
- # Comma-separated list of allowed origins, e.g. "http://localhost:3000,https://pmdi.example.com"
- ALLOWED_ORIGINS: str = "http://localhost:3000"
- # ── Cron endpoint guard ───────────────────────────────────────────────────
- CRON_SECRET_TOKEN: str
- # ── Seed admin (first-boot only) ──────────────────────────────────────────
- ADMIN_USERNAME: str = "admin"
- ADMIN_PASSWORD: str = "changeme"
- # ── Mail sender identity ──────────────────────────────────────────────────
- MAIL_FROM: str = "noreply@example.com"
- MAIL_FROM_NAME: str = "PMDI Invoice System"
- # ── Mail Mode A – Authenticated TLS relay ─────────────────────────────────
- # All three must be set to activate Mode A.
- MAIL_RELAYHOST: Optional[str] = None # "smtp.example.com:587"
- MAIL_RELAYHOST_USERNAME: Optional[str] = None
- MAIL_RELAYHOST_PASSWORD: Optional[str] = None
- # ── Mail Mode B – Simple container/host proxy relay ───────────────────────
- # Set to the hostname of the relay container (e.g. "postfix").
- MAIL_RELAY_HOST: Optional[str] = None
- # Module-level singleton — import this everywhere instead of re-instantiating.
- settings = Settings()
|