import logging from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.config import settings from app.api import auth, users, classes, directory, timeline, schedule, upload, announcements, resources, notifications, votes, assignments, reading, fund logging.basicConfig( level=logging.DEBUG if settings.debug else logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", ) logger = logging.getLogger(__name__) async def ensure_super_admin(): """Seed super admin on first run.""" from sqlalchemy import select from app.db.database import async_session from app.db.models import User from app.core.auth import hash_password async with async_session() as db: result = await db.execute(select(User).where(User.role == "super_admin")) if result.scalar_one_or_none() is None: admin = User( email=settings.super_admin_email, password_hash=hash_password(settings.super_admin_password), name="Super Admin", role="super_admin", status="approved", ) db.add(admin) await db.commit() logger.info("Super admin seeded: %s", settings.super_admin_email) @asynccontextmanager async def lifespan(app: FastAPI): await ensure_super_admin() yield app = FastAPI( title="HKU ICB", description="HKU ICB Graduate Class Resource Platform", version="1.0.0", lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=[settings.frontend_url, "http://localhost:3001", "http://192.168.31.172:3001"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(auth.router) app.include_router(users.router) app.include_router(classes.router) app.include_router(directory.router) app.include_router(timeline.router) app.include_router(schedule.router) app.include_router(upload.router) app.include_router(announcements.router) app.include_router(resources.router) app.include_router(notifications.router) app.include_router(votes.router) app.include_router(assignments.router) app.include_router(reading.router) app.include_router(fund.router) @app.get("/api/health") async def health(): return {"status": "ok", "service": "classhub"}