from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from contextlib import asynccontextmanager import os from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware from slowapi import _rate_limit_exceeded_handler from slowapi.errors import RateLimitExceeded from app.api.user_routes import router as user_router from app.api.auth_routes import router as auth_router from app.api.profile_routes import router as profile_router from app.api.file_routes import router as file_router from app.api.feedback_routes import router as feedback_router from app.api.admin_routes import router as admin_router from app.api.metric_routes import router as metrics_router from app.api.user_issue_routes import router as user_issue_router from app.core.logging_middleware import APILoggingMiddleware from app.core.limiter import limiter from app.middleware.security_headers import SecurityHeadersMiddleware from starlette.middleware.sessions import SessionMiddleware @asynccontextmanager async def lifespan(app: FastAPI): # Auto-create any missing tables (e.g. audit_logs) without dropping existing data from app.db.database import Base, engine import app.models.audit_model # noqa: ensure AuditLog is registered with Base import app.models.user_model # noqa import app.models.file_model # noqa Base.metadata.create_all(bind=engine, checkfirst=True) yield is_production = os.environ.get("ENVIRONMENT", "development") == "production" app = FastAPI( title="Spotix", lifespan=lifespan, docs_url=None if is_production else "/docs", redoc_url=None if is_production else "/redoc", openapi_url=None if is_production else "/openapi.json" ) app.add_middleware(ProxyHeadersMiddleware, trusted_hosts=["*"]) app.add_middleware( SessionMiddleware, secret_key=os.environ.get("SESSION_SECRET_KEY", "neural-vault-oauth-session-secret-9912"), https_only=is_production ) frontend_url = os.environ.get("FRONTEND_URL", "http://localhost:3000") origins = [frontend_url] if frontend_url != "http://localhost:3000": origins.append("http://localhost:3000") app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Trigger reload app.mount("/static", StaticFiles(directory="."), name="static") app.state.limiter = limiter app.include_router(profile_router) app.include_router(user_router) app.include_router(auth_router) app.include_router(file_router) app.include_router(feedback_router) app.include_router(admin_router) app.include_router(metrics_router) app.include_router(user_issue_router) app.add_middleware(APILoggingMiddleware) app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) app.add_middleware(SecurityHeadersMiddleware) @app.get("/") def home(): return {"message": "Backend running successfully"}