hku-class-hub/backend/app/main.py
2026-04-11 12:52:23 +08:00

95 lines
2.7 KiB
Python

import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config import settings
from app.db.database import create_tables
from app.api import auth, users, classes, directory, timeline, schedule, upload
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)
async def ensure_sample_class():
"""Seed a sample class if none exists."""
from sqlalchemy import select, func
from app.db.database import async_session
from app.db.models import Class_
async with async_session() as db:
result = await db.execute(select(func.count(Class_.id)))
count = result.scalar()
if count == 0:
sample = Class_(
name="HKU ICB Sample Class",
cohort_year=2025,
description="Sample class for testing",
)
db.add(sample)
await db.commit()
logger.info("Sample class seeded")
@asynccontextmanager
async def lifespan(app: FastAPI):
await create_tables()
await ensure_super_admin()
await ensure_sample_class()
yield
app = FastAPI(
title="ClassHub",
description="HKU ICB Graduate Class Resource Platform",
version="1.0.0",
lifespan=lifespan,
)
app.add_middleware(
CORSMiddleware,
allow_origins=[settings.frontend_url, "http://localhost:3000"],
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.get("/api/health")
async def health():
return {"status": "ok", "service": "classhub"}