60 lines
2.6 KiB
Python
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()
|