63 lines
2.2 KiB
Python
63 lines
2.2 KiB
Python
import logging
|
|
import os
|
|
from pathlib import Path
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _resolve_db_url(url: str) -> str:
|
|
"""Convert relative sqlite path to absolute path for Docker or local dev."""
|
|
if url.startswith("sqlite+aiosqlite:///./"):
|
|
# Convert relative path to absolute (works in both local and Docker)
|
|
rel_path = url.replace("sqlite+aiosqlite:///./", "")
|
|
# Use working directory as base
|
|
base_dir = Path.cwd()
|
|
abs_path = base_dir / rel_path
|
|
return f"sqlite+aiosqlite:///{abs_path.resolve()}"
|
|
return url
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
|
|
|
|
DATABASE_URL: str = "sqlite+aiosqlite:///./data/claudia_docs.db"
|
|
JWT_SECRET_KEY: str
|
|
JWT_ALGORITHM: str = "HS256"
|
|
JWT_ACCESS_TOKEN_EXPIRE_MINUTES: int = 15
|
|
JWT_REFRESH_TOKEN_EXPIRE_DAYS: int = 7
|
|
CORS_ORIGINS: str = "http://localhost:5173,http://localhost:80"
|
|
HOST: str = "0.0.0.0"
|
|
PORT: int = 8000
|
|
LOG_LEVEL: str = "INFO"
|
|
INITIAL_ADMIN_USERNAME: str # Required: admin user to auto-create
|
|
INITIAL_ADMIN_PASSWORD: str # Required: password for auto-created admin
|
|
|
|
@property
|
|
def resolved_database_url(self) -> str:
|
|
return _resolve_db_url(self.DATABASE_URL)
|
|
|
|
@property
|
|
def cors_origins_list(self) -> list[str]:
|
|
return [o.strip() for o in self.CORS_ORIGINS.split(",") if o.strip()]
|
|
|
|
|
|
settings = Settings()
|
|
|
|
# Validate required secrets at startup
|
|
_missing = []
|
|
if not settings.JWT_SECRET_KEY or settings.JWT_SECRET_KEY == "change-me-super-secret-key-min32chars!!":
|
|
_missing.append("JWT_SECRET_KEY")
|
|
if not settings.INITIAL_ADMIN_USERNAME:
|
|
_missing.append("INITIAL_ADMIN_USERNAME")
|
|
if not settings.INITIAL_ADMIN_PASSWORD:
|
|
_missing.append("INITIAL_ADMIN_PASSWORD")
|
|
|
|
if _missing:
|
|
raise ValueError(f"Required environment variables not set: {', '.join(_missing)}")
|
|
|
|
# Log initial admin credentials (password masked)
|
|
logger.info(f"Initial admin username: {settings.INITIAL_ADMIN_USERNAME}")
|
|
logger.info(f"Initial admin password: {'*' * len(settings.INITIAL_ADMIN_PASSWORD)}")
|