Spotix-API / backend /main.py
Anish-530
Fix login (audit_logs table + fault-tolerant audit), feedback graceful errors, remove raw AI explanation fallback, localStorage feedback persistence, Betterstack cloud logging
fe56754
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"}