mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 08:08:48 +02:00
46 lines
1.7 KiB
Python
46 lines
1.7 KiB
Python
from pydantic import model_validator
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
DATABASE_URL: str = "postgresql://wealthy_user:wealthy_pass@db:5432/wealthysmart"
|
|
# No defaults: the app must refuse to boot without real values (see _reject_weak_secrets).
|
|
SECRET_KEY: str
|
|
ADMIN_USERNAME: str
|
|
ADMIN_PASSWORD: str
|
|
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 7 # 7 days
|
|
COOKIE_SECURE: bool = True # dev compose sets "false"; prod serves over TLS
|
|
CORS_ORIGINS: str = (
|
|
"https://wealth.cescalante.dev,"
|
|
"http://localhost:3000,http://localhost:3001,http://localhost:5175"
|
|
)
|
|
BCCR_API_EMAIL: str = ""
|
|
BCCR_API_TOKEN: str = ""
|
|
VAPID_PRIVATE_KEY: str = ""
|
|
VAPID_PUBLIC_KEY: str = ""
|
|
VAPID_CLAIM_EMAIL: str = "mailto:admin@wealth.cescalante.dev"
|
|
OPENAI_API_KEY: str = ""
|
|
AGENT_MODEL: str = "gpt-5.6-luna"
|
|
|
|
@property
|
|
def cors_origins_list(self) -> list[str]:
|
|
return [o.strip() for o in self.CORS_ORIGINS.split(",") if o.strip()]
|
|
|
|
@model_validator(mode="after")
|
|
def _reject_weak_secrets(self) -> "Settings":
|
|
if len(self.SECRET_KEY) < 32 or self.SECRET_KEY == "change-me-in-production":
|
|
raise ValueError(
|
|
"SECRET_KEY must be a random value of at least 32 characters "
|
|
"(generate one with: openssl rand -hex 32)"
|
|
)
|
|
if not self.ADMIN_USERNAME:
|
|
raise ValueError("ADMIN_USERNAME must be set")
|
|
if not self.ADMIN_PASSWORD or self.ADMIN_PASSWORD == "admin":
|
|
raise ValueError("ADMIN_PASSWORD must be set and must not be 'admin'")
|
|
return self
|
|
|
|
model_config = SettingsConfigDict(env_file=".env")
|
|
|
|
|
|
settings = Settings()
|