""" Configurazione applicazione – legge variabili d'ambiente tramite pydantic-settings. """ from functools import lru_cache from typing import Literal from pydantic import field_validator from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore", ) # ── Applicazione ────────────────────────────────────────────────────────── app_env: Literal["development", "staging", "production"] = "development" app_debug: bool = True app_host: str = "0.0.0.0" app_port: int = 8000 app_base_url: str = "http://localhost:8000" # ── Sicurezza / JWT ─────────────────────────────────────────────────────── secret_key: str = "change-me-in-production" algorithm: str = "HS256" access_token_expire_minutes: int = 15 refresh_token_expire_days: int = 30 # Chiave AES-256-GCM per cifratura credenziali IMAP/SMTP (hex 64 chars = 32 bytes) encryption_key: str = "0" * 64 # ── Database ────────────────────────────────────────────────────────────── database_url: str = "postgresql+asyncpg://pechub:pechub_dev_password@db:5432/pechub" database_url_sync: str = "postgresql://pechub:pechub_dev_password@db:5432/pechub" # ── Redis ───────────────────────────────────────────────────────────────── redis_url: str = "redis://redis:6379/0" # ── MinIO ───────────────────────────────────────────────────────────────── minio_endpoint: str = "minio:9000" minio_access_key: str = "minioadmin" minio_secret_key: str = "minioadmin" minio_bucket: str = "pechub" minio_use_ssl: bool = False # ── Admin sicurezza ─────────────────────────────────────────────────────── # Header X-Admin-Key richiesto sugli endpoint /api/v1/tenants # Se vuoto → protezione disabilitata (solo sviluppo) admin_secret_key: str = "" # ── CORS ────────────────────────────────────────────────────────────────── cors_origins: str = "http://localhost:3000,http://localhost:5173" # ── Rate Limiting ───────────────────────────────────────────────────────── rate_limit_auth: str = "10/minute" rate_limit_default: str = "100/minute" # ── Logging ─────────────────────────────────────────────────────────────── log_level: str = "INFO" log_json: bool = False @field_validator("encryption_key") @classmethod def validate_encryption_key(cls, v: str) -> str: if len(v) != 64: raise ValueError( "ENCRYPTION_KEY deve essere una stringa hex di 64 caratteri (32 bytes)" ) try: bytes.fromhex(v) except ValueError: raise ValueError("ENCRYPTION_KEY deve essere una stringa esadecimale valida") return v @property def cors_origins_list(self) -> list[str]: return [origin.strip() for origin in self.cors_origins.split(",")] @property def is_production(self) -> bool: return self.app_env == "production" @property def encryption_key_bytes(self) -> bytes: return bytes.fromhex(self.encryption_key) @lru_cache def get_settings() -> Settings: """Restituisce istanza singleton delle impostazioni (cachata).""" return Settings()