from pydantic_settings import BaseSettings, SettingsConfigDict from typing import List, Optional from enum import Enum class Environment(str, Enum): DEVELOPMENT = "development" STAGING = "staging" PRODUCTION = "production" class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore" ) # === Environment === environment: Environment = Environment.DEVELOPMENT # === JWT & Auth === jwt_secret: str jwt_algorithm: str = "HS256" access_token_expire_minutes: int = 15 refresh_token_expire_days: int = 7 csrf_token_expire_minutes: int = 60 # === Cookie Settings === cookie_domain: Optional[str] = None cookie_secure: bool = True cookie_samesite: str = "strict" cookie_httponly: bool = True cookie_access_token_name: str = "access_token" cookie_refresh_token_name: str = "refresh_token" cookie_csrf_token_name: str = "csrf_token" # === Redis (Token Blacklist & Rate Limiting) === redis_url: str = "redis://localhost:6379/0" redis_password: Optional[str] = None redis_ssl: bool = False token_blacklist_prefix: str = "blacklist:" rate_limit_prefix: str = "ratelimit:" # === Rate Limiting === rate_limit_login_attempts: int = 5 rate_limit_login_window_minutes: int = 15 rate_limit_api_requests: int = 100 rate_limit_api_window_seconds: int = 60 # === Security === password_min_length: int = 8 password_require_uppercase: bool = True password_require_lowercase: bool = True password_require_digit: bool = True password_require_special: bool = True account_lockout_threshold: int = 5 account_lockout_duration_minutes: int = 30 # === Fingerprint === fingerprint_secret: str = "" fingerprint_components: List[str] = [ "user_agent", "accept_language", "accept_encoding", ] # === Refresh Token Rotation === refresh_token_rotation_enabled: bool = True refresh_token_reuse_window_seconds: int = 10 # === Sage Types === SAGE_TYPE_DEVIS: int = 0 SAGE_TYPE_BON_COMMANDE: int = 10 SAGE_TYPE_PREPARATION: int = 20 SAGE_TYPE_BON_LIVRAISON: int = 30 SAGE_TYPE_BON_RETOUR: int = 40 SAGE_TYPE_BON_AVOIR: int = 50 SAGE_TYPE_FACTURE: int = 60 # === Sage Gateway === sage_gateway_url: str sage_gateway_token: str frontend_url: str # === Database === database_url: str = "sqlite+aiosqlite:///./data/sage_dataven.db" # === SMTP === smtp_host: str smtp_port: int = 587 smtp_user: str smtp_password: str smtp_from: str smtp_use_tls: bool = True # === Universign === universign_api_key: str universign_api_url: str # === API === api_host: str = "0.0.0.0" api_port: int = 8000 api_reload: bool = True # === Email Queue === max_email_workers: int = 3 max_retry_attempts: int = 3 retry_delay_seconds: int = 3 # === CORS === cors_origins: List[str] = ["*"] @property def is_production(self) -> bool: return self.environment == Environment.PRODUCTION @property def is_development(self) -> bool: return self.environment == Environment.DEVELOPMENT settings = Settings()