Files
geutebruck-api/src/api/config.py
Geutebruck API Developer 12c4e1ca9c Phase 3 (Part 1): API Infrastructure - FastAPI, Database, Redis, gRPC Client
Completed Tasks (T027-T032):
-  FastAPI application with structured logging, CORS, global error handlers
-  Pydantic Settings for environment configuration
-  SQLAlchemy async engine with session management
-  Alembic migration environment setup
-  Redis async client with connection pooling
-  gRPC SDK Bridge client (placeholder - awaiting protobuf generation)

Next: JWT utilities, middleware, database models

🤖 Generated with Claude Code
2025-12-09 08:49:08 +01:00

96 lines
3.0 KiB
Python

"""
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!")