from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.trustedhost import TrustedHostMiddleware from fastapi.staticfiles import StaticFiles from pathlib import Path from contextlib import asynccontextmanager from app.core.config import settings from app.db.init_db import init_db from app.workers.scheduler import start_scheduler from app.core.startup import run_startup_sequence import logging # Configure Logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): # Startup: Initialize DB logger.info("Initializing Database...") await init_db() # Startup Sequence (Auth, Checks) await run_startup_sequence() logger.info("Starting Background Scheduler...") start_scheduler() logger.info("Application Startup Complete.") yield # Shutdown logger.info("Application Shutdown.") app = FastAPI( title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json", docs_url=f"{settings.API_V1_STR}/docs", redoc_url=f"{settings.API_V1_STR}/redoc", lifespan=lifespan ) # 1. Security: Trusted Host Middleware app.add_middleware( TrustedHostMiddleware, allowed_hosts=settings.ALLOWED_HOSTS ) # 2. CORS Middleware if settings.BACKEND_CORS_ORIGINS: app.add_middleware( CORSMiddleware, allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 3. Health Check @app.get("/health") def health_check(): return {"status": "ok", "app": settings.PROJECT_NAME} from app.api.api import api_router # 4. API Router app.include_router(api_router, prefix=settings.API_V1_STR) # 5. Static Files (Frontend) BASE_DIR = Path(__file__).resolve().parent.parent STATIC_DIR = BASE_DIR / "static" if STATIC_DIR.exists(): app.mount("/", StaticFiles(directory=str(STATIC_DIR), html=True), name="static") else: logger.warning(f"Static directory not found at {STATIC_DIR}")