""" Configuration management using Pydantic Settings Loads configuration from environment variables """ from pydantic_settings import BaseSettings from typing import List import os class Settings(BaseSettings): """Application settings loaded from environment variables""" # API Configuration API_HOST: str = "0.0.0.0" API_PORT: int = 8000 API_TITLE: str = "Geutebruck Cross-Switching API" API_VERSION: str = "1.0.0" ENVIRONMENT: str = "development" # development, production # GeViScope SDK Bridge (gRPC) SDK_BRIDGE_HOST: str = "localhost" SDK_BRIDGE_PORT: int = 50051 # GeViServer Connection (used by SDK Bridge) GEVISERVER_HOST: str = "localhost" GEVISERVER_USERNAME: str = "sysadmin" GEVISERVER_PASSWORD: str = "masterkey" # Database (PostgreSQL) DATABASE_URL: str = "postgresql+asyncpg://geutebruck:geutebruck@localhost:5432/geutebruck_api" DATABASE_POOL_SIZE: int = 20 DATABASE_MAX_OVERFLOW: int = 10 # Redis REDIS_HOST: str = "localhost" REDIS_PORT: int = 6379 REDIS_DB: int = 0 REDIS_PASSWORD: str = "" REDIS_MAX_CONNECTIONS: int = 50 # JWT Authentication JWT_SECRET_KEY: str = "change-this-to-a-secure-random-key-in-production" JWT_ALGORITHM: str = "HS256" JWT_ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 JWT_REFRESH_TOKEN_EXPIRE_DAYS: int = 7 # Logging LOG_LEVEL: str = "INFO" LOG_FORMAT: str = "json" # json or console # Security ALLOWED_HOSTS: str = "*" CORS_ORIGINS: List[str] = ["http://localhost:3000", "http://localhost:8080"] # Cache Settings CACHE_CAMERA_LIST_TTL: int = 60 # seconds CACHE_MONITOR_LIST_TTL: int = 60 # seconds # Rate Limiting RATE_LIMIT_ENABLED: bool = True RATE_LIMIT_PER_MINUTE: int = 60 class Config: env_file = ".env" env_file_encoding = "utf-8" case_sensitive = True @property def sdk_bridge_url(self) -> str: """Get SDK Bridge gRPC URL""" return f"{self.SDK_BRIDGE_HOST}:{self.SDK_BRIDGE_PORT}" @property def redis_url(self) -> str: """Get Redis connection URL""" if self.REDIS_PASSWORD: return f"redis://:{self.REDIS_PASSWORD}@{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}" return f"redis://{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}" def get_cors_origins(self) -> List[str]: """Parse CORS origins (handles both list and comma-separated string)""" if isinstance(self.CORS_ORIGINS, list): return self.CORS_ORIGINS return [origin.strip() for origin in self.CORS_ORIGINS.split(",")] # Create global settings instance settings = Settings() # Validate critical settings on import if settings.ENVIRONMENT == "production": if settings.JWT_SECRET_KEY == "change-this-to-a-secure-random-key-in-production": raise ValueError("JWT_SECRET_KEY must be changed in production!") if settings.GEVISERVER_PASSWORD == "masterkey": import warnings warnings.warn("Using default GeViServer password in production!")