129 lines
3.8 KiB
Python
129 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Any
|
|
|
|
from pydantic import field_validator
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""Application configuration loaded from environment variables."""
|
|
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env",
|
|
env_file_encoding="utf-8",
|
|
case_sensitive=False,
|
|
extra="ignore",
|
|
)
|
|
|
|
# Application
|
|
app_name: str = "DocEngine"
|
|
app_version: str = "1.0.0"
|
|
app_env: str = "development"
|
|
app_debug: bool = True
|
|
app_host: str = "0.0.0.0"
|
|
app_port: int = 7989
|
|
app_workers: int = 4
|
|
|
|
# Database
|
|
db_host: str = "192.168.0.111"
|
|
db_port: int = 5432
|
|
db_name: str = "ocr"
|
|
db_user: str = "postgres"
|
|
db_password: str = "M@triXPostgr3s@6202"
|
|
db_schema: str = "admin"
|
|
db_pool_size: int = 20
|
|
db_max_overflow: int = 10
|
|
db_echo: bool = False
|
|
|
|
# Redis
|
|
redis_host: str = "192.168.0.111"
|
|
redis_port: int = 7901
|
|
redis_db: int = 0
|
|
redis_password: str = "M@triXR3d1s@6202"
|
|
|
|
# Celery
|
|
celery_broker_url: str = "redis://:M@triXR3d1s@6202@192.168.0.111:7901/0"
|
|
celery_result_backend: str = "redis://:M@triXR3d1s@6202@192.168.0.111:7901/1"
|
|
|
|
# JWT
|
|
jwt_secret_key: str = "a7f3c9e1d4b8f2a6c0e5d7b3a9f1c4e8d2b6a0f5c3e7d1b9a4f8c2e6d0b5a3"
|
|
jwt_algorithm: str = "HS256"
|
|
jwt_access_token_expire_minutes: int = 30
|
|
jwt_refresh_token_expire_days: int = 7
|
|
session_encryption_secret: str = ""
|
|
session_encryption_secret_internal: str = ""
|
|
|
|
# Storage
|
|
storage_provider: str = "local"
|
|
storage_local_path: str = "./storage"
|
|
storage_max_file_size_mb: int = 100
|
|
|
|
# OCR
|
|
ocr_language: str = "en"
|
|
ocr_use_gpu: bool = False
|
|
|
|
# Logging
|
|
log_level: str = "INFO"
|
|
log_format: str = "json"
|
|
|
|
# CORS
|
|
cors_origins: list[str] = ["http://localhost:3000", "http://localhost:8080", "http://localhost:4200"]
|
|
cors_allow_credentials: bool = True
|
|
|
|
# Rate Limiting
|
|
rate_limit_requests: int = 100
|
|
rate_limit_window_seconds: int = 60
|
|
|
|
# Prometheus
|
|
prometheus_enabled: bool = True
|
|
|
|
@field_validator("cors_origins", mode="before")
|
|
@classmethod
|
|
def parse_cors_origins(cls, v: Any) -> list[str]:
|
|
if isinstance(v, str):
|
|
if not v.strip():
|
|
return []
|
|
try:
|
|
parsed = json.loads(v)
|
|
if isinstance(parsed, list):
|
|
return [str(item).strip() for item in parsed]
|
|
elif isinstance(parsed, str):
|
|
return [parsed.strip()]
|
|
except (json.JSONDecodeError, TypeError):
|
|
pass
|
|
return [origin.strip() for origin in v.split(",") if origin.strip()]
|
|
if isinstance(v, list):
|
|
return [str(item).strip() for item in v]
|
|
return []
|
|
|
|
@property
|
|
def database_url(self) -> str:
|
|
from urllib.parse import quote_plus
|
|
password = quote_plus(self.db_password)
|
|
return f"postgresql+psycopg2://{self.db_user}:{password}@{self.db_host}:{self.db_port}/{self.db_name}"
|
|
|
|
@property
|
|
def async_database_url(self) -> str:
|
|
from urllib.parse import quote_plus
|
|
password = quote_plus(self.db_password)
|
|
return f"postgresql+asyncpg://{self.db_user}:{password}@{self.db_host}:{self.db_port}/{self.db_name}"
|
|
|
|
@property
|
|
def redis_url(self) -> str:
|
|
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}"
|
|
|
|
@property
|
|
def is_production(self) -> bool:
|
|
return self.app_env == "production"
|
|
|
|
@property
|
|
def storage_max_file_size_bytes(self) -> int:
|
|
return self.storage_max_file_size_mb * 1024 * 1024
|
|
|
|
|
|
settings = Settings()
|