from pydantic_settings import BaseSettings from typing import Optional, List from pydantic import field_validator, ConfigDict import json class Settings(BaseSettings): # Database database_url: str = "sqlite+aiosqlite:///./mockapi.db" # Application debug: bool = False title: str = "Mock API Server" version: str = "1.0.0" log_level: str = "INFO" host: str = "0.0.0.0" port: int = 8000 # Admin authentication admin_username: str = "admin" admin_password: str = "admin123" secret_key: str = "your-secret-key-here-change-me" # Security session_cookie_name: str = "mockapi_session" session_max_age: int = 24 * 60 * 60 # 24 hours # OAuth2 Settings oauth2_issuer: str = "http://localhost:8000" # Used for discovery oauth2_access_token_expire_minutes: int = 30 oauth2_refresh_token_expire_days: int = 7 oauth2_authorization_code_expire_minutes: int = 10 oauth2_supported_grant_types: List[str] = ["authorization_code", "client_credentials", "refresh_token"] oauth2_supported_scopes: List[str] = ["openid", "profile", "email", "api:read", "api:write"] oauth2_pkce_required: bool = False # Future enhancement @field_validator('admin_password') def validate_admin_password(cls, v, info): if not info.data.get('debug', True) and v == "admin123": raise ValueError( 'admin_password must be set via environment variable in production (debug=False)' ) return v @field_validator('secret_key') def validate_secret_key(cls, v, info): if not info.data.get('debug', True) and v == "your-secret-key-here-change-me": raise ValueError( 'secret_key must be set via environment variable in production (debug=False)' ) return v @field_validator('oauth2_supported_scopes', 'oauth2_supported_grant_types', mode='before') @classmethod def parse_list_from_string(cls, v): """Parse list from either JSON string or space/comma-separated string.""" if isinstance(v, list): return v if isinstance(v, str): # Try to parse as JSON first try: return json.loads(v) except json.JSONDecodeError: # If not JSON, try comma-separated or space-separated # Remove quotes and split by commas or spaces v = v.strip() if ',' in v: # Comma-separated items = [item.strip().strip('"\'') for item in v.split(',')] else: # Space-separated items = [item.strip().strip('"\'') for item in v.split()] # Filter out empty strings return [item for item in items if item] # Return as-is for other types (should be list) return v model_config = ConfigDict(env_file=".env", extra="allow") settings = Settings()