Jarian Cottingham 5c283eceef chore: remove test artifacts, fix hardcoded paths, ruff clean, license
- Remove committed .coverage and test-results/ (196K screenshots); gitignore them
- Fix hardcoded  /home/userpath + venv/bin/python in test_endpoints.py
  (relative backend dir + sys.executable)
- Fix concatenated 'import json' in settings.py; bare excepts -> Exception;
  SQLAlchemy-safe is_active.is_(True); __all__ on models/schemas barrels
- ruff clean (93 fixes), MIT LICENSE, PLAN.md -> docs/, README Tests section
- 300 tests pass, 93.7% coverage
2026-08-20 21:34:15 +00:00

97 lines
2.5 KiB
Python

import os
from fastapi import FastAPI, Request, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from starlette.middleware.base import BaseHTTPMiddleware
from .db.database import init_db
from .routers import (
songs,
playlists,
mood,
radio,
search,
lofi,
shareplay,
import_,
settings,
releases,
events,
account,
)
app = FastAPI(title="Music App API", version="1.0.0")
# CORS
origins = os.getenv("CORS_ORIGINS", "http://localhost:5173").split(",")
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Auth middleware
API_KEY = os.getenv("API_KEY", "")
class APIKeyMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next): # pragma: no cover
if not API_KEY:
return await call_next(request)
path = request.url.path
if path in ("/health", "/static") or path.startswith("/static"):
return await call_next(request)
header_key = request.headers.get("x-api-key", "")
query_key = request.query_params.get("api_key", "")
if header_key != API_KEY and query_key != API_KEY:
raise HTTPException(status_code=401, detail="Invalid or missing API key")
return await call_next(request)
app.add_middleware(APIKeyMiddleware)
def require_api_key(api_key: str = Depends(lambda: None)): # pragma: no cover
if not API_KEY:
return
raise HTTPException(status_code=401, detail="API key required")
# Static files
static_dir = os.getenv("STATIC_DIR", "./static")
os.makedirs(static_dir, exist_ok=True)
app.mount("/static", StaticFiles(directory=static_dir), name="static")
# Routers
app.include_router(songs.router)
app.include_router(playlists.router)
app.include_router(mood.router)
app.include_router(radio.router)
app.include_router(search.router)
app.include_router(lofi.router)
app.include_router(shareplay.router)
app.include_router(import_.router)
app.include_router(settings.router)
app.include_router(releases.router)
app.include_router(events.router)
app.include_router(account.router)
@app.on_event("startup")
def startup():
init_db()
from .db.database import SessionLocal
db = SessionLocal()
try:
from .routers.lofi import _seed_channels
_seed_channels(db)
finally:
db.close()
@app.get("/health")
def health_check():
return {"status": "ok"}