Files
stundenfuchs/app/config.py
T
maddin 6fbd1bb3c2
CI / checks (push) Has been cancelled
chore: initialize public repository
2026-03-22 12:57:09 +00:00

60 lines
2.6 KiB
Python

from functools import lru_cache
from pathlib import Path
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
ROOT_DIR = Path(__file__).resolve().parents[1]
VERSION_FILE = ROOT_DIR / "VERSION"
def load_default_app_version() -> str:
try:
value = VERSION_FILE.read_text(encoding="utf-8").strip()
except FileNotFoundError:
return "1.0.0"
return value or "1.0.0"
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
app_env: str = Field(default="development", alias="APP_ENV")
port: int = Field(default=8000, alias="PORT")
db_url: str = Field(default="sqlite:///./data/stundentracker.db", alias="DB_URL")
session_secret: str = Field(default="change-this-in-production", alias="SESSION_SECRET")
cookie_secure: bool = Field(default=False, alias="COOKIE_SECURE")
cookie_samesite: str = Field(default="lax", alias="COOKIE_SAMESITE")
login_rate_limit_attempts: int = Field(default=5, alias="LOGIN_RATE_LIMIT_ATTEMPTS")
login_rate_limit_window_minutes: int = Field(default=15, alias="LOGIN_RATE_LIMIT_WINDOW_MINUTES")
data_encryption_key: str | None = Field(default=None, alias="DATA_ENCRYPTION_KEY")
password_reset_token_ttl_minutes: int = Field(default=60, alias="PASSWORD_RESET_TOKEN_TTL_MINUTES")
mfa_code_ttl_minutes: int = Field(default=10, alias="MFA_CODE_TTL_MINUTES")
mfa_pending_ttl_minutes: int = Field(default=10, alias="MFA_PENDING_TTL_MINUTES")
smtp_timeout_seconds: int = Field(default=15, alias="SMTP_TIMEOUT_SECONDS")
registration_notify_email: str = Field(default="admin@example.com", alias="REGISTRATION_NOTIFY_EMAIL")
app_name: str = Field(default="Stundenfuchs", alias="APP_NAME")
app_title: str | None = Field(default=None, alias="APP_TITLE")
app_version: str = Field(default=load_default_app_version(), alias="APP_VERSION")
email_verification_required: bool = Field(default=True, alias="EMAIL_VERIFICATION_REQUIRED")
email_verification_token_ttl_minutes: int = Field(default=60 * 24, alias="EMAIL_VERIFICATION_TOKEN_TTL_MINUTES")
bootstrap_admin_email: str | None = Field(default=None, alias="BOOTSTRAP_ADMIN_EMAIL")
forwarded_allow_ips: str = Field(default="127.0.0.1,::1", alias="FORWARDED_ALLOW_IPS")
@property
def is_production(self) -> bool:
return self.app_env.lower() == "production"
@property
def resolved_app_title(self) -> str:
value = (self.app_title or "").strip()
if value:
return value
return self.app_name
@lru_cache(maxsize=1)
def get_settings() -> Settings:
return Settings()