Files
Magent/backend/app/main.py
T
2026-05-16 10:44:20 +00:00

90 lines
3.0 KiB
Python

import asyncio
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from .config import settings
from .db import init_db
from .routers.requests import (
router as requests_router,
startup_warmup_requests_cache,
run_requests_delta_loop,
run_daily_requests_full_sync,
run_daily_db_cleanup,
)
from .routers.auth import router as auth_router
from .routers.admin import router as admin_router
from .routers.images import router as images_router
from .routers.branding import router as branding_router
from .routers.status import router as status_router
from .routers.feedback import router as feedback_router
from .services.jellyfin_sync import run_daily_jellyfin_sync
from .logging_config import configure_logging
from .runtime import get_runtime_settings
def validate_security_settings() -> None:
issues = []
jwt_secret = (settings.jwt_secret or "").strip()
admin_username = (settings.admin_username or "").strip()
admin_password = (settings.admin_password or "").strip()
if not jwt_secret:
issues.append("JWT_SECRET is required")
if not admin_username:
issues.append("ADMIN_USERNAME is required")
if not admin_password:
issues.append("ADMIN_PASSWORD is required")
if jwt_secret == "change-me":
issues.append("JWT_SECRET must not use the default placeholder")
if admin_password == "adminadmin":
issues.append("ADMIN_PASSWORD must not use the default placeholder")
if issues:
raise RuntimeError("Unsafe Magent security configuration: " + "; ".join(issues))
@asynccontextmanager
async def lifespan(_: FastAPI):
validate_security_settings()
init_db()
runtime = get_runtime_settings()
configure_logging(runtime.log_level, runtime.log_file)
background_tasks = [
asyncio.create_task(run_daily_jellyfin_sync(), name="daily-jellyfin-sync"),
asyncio.create_task(startup_warmup_requests_cache(), name="startup-warmup-requests-cache"),
asyncio.create_task(run_requests_delta_loop(), name="requests-delta-loop"),
asyncio.create_task(run_daily_requests_full_sync(), name="daily-requests-full-sync"),
asyncio.create_task(run_daily_db_cleanup(), name="daily-db-cleanup"),
]
try:
yield
finally:
for task in background_tasks:
task.cancel()
await asyncio.gather(*background_tasks, return_exceptions=True)
app = FastAPI(title=settings.app_name, lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=[settings.cors_allow_origin],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/health")
async def health() -> dict:
return {"status": "ok"}
app.include_router(requests_router)
app.include_router(auth_router)
app.include_router(admin_router)
app.include_router(images_router)
app.include_router(branding_router)
app.include_router(status_router)
app.include_router(feedback_router)