94 lines
2.6 KiB
Python
94 lines
2.6 KiB
Python
"""SmartUp FastAPI application entry point."""
|
|
import logging
|
|
from contextlib import asynccontextmanager
|
|
from pathlib import Path
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.staticfiles import StaticFiles
|
|
from fastapi.responses import FileResponse
|
|
|
|
from app.config import get_settings
|
|
from app.database import init_db
|
|
from app.models.admin_user import AdminUser
|
|
from app.database import SessionLocal
|
|
from app.utils.auth import hash_password
|
|
from app.services.scheduler import start_scheduler, stop_scheduler
|
|
from app.routers import auth, upstreams, webhooks, logs, custom_pages
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s %(message)s")
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _init_admin() -> None:
|
|
settings = get_settings()
|
|
if not settings.admin_password:
|
|
logger.warning("ADMIN_PASSWORD not set, skip admin init")
|
|
return
|
|
db = SessionLocal()
|
|
try:
|
|
exists = db.query(AdminUser).filter(AdminUser.email == settings.admin_email).first()
|
|
if not exists:
|
|
user = AdminUser(
|
|
email=settings.admin_email,
|
|
password_hash=hash_password(settings.admin_password),
|
|
)
|
|
db.add(user)
|
|
db.commit()
|
|
logger.info("admin user created: %s", settings.admin_email)
|
|
else:
|
|
logger.info("admin user already exists: %s", settings.admin_email)
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
init_db()
|
|
_init_admin()
|
|
start_scheduler()
|
|
yield
|
|
stop_scheduler()
|
|
|
|
|
|
app = FastAPI(
|
|
title="SmartUp",
|
|
description="API 上游管理与 Webhook 通知系统",
|
|
version="1.0.0",
|
|
lifespan=lifespan,
|
|
docs_url="/api/docs",
|
|
redoc_url="/api/redoc",
|
|
openapi_url="/api/openapi.json",
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# API routers
|
|
app.include_router(auth.router)
|
|
app.include_router(upstreams.router)
|
|
app.include_router(webhooks.router)
|
|
app.include_router(logs.router)
|
|
app.include_router(custom_pages.router)
|
|
|
|
|
|
@app.get("/healthz")
|
|
def health():
|
|
return {"status": "ok"}
|
|
|
|
|
|
# Serve frontend static files
|
|
STATIC_DIR = Path(__file__).parent.parent / "static"
|
|
if STATIC_DIR.exists():
|
|
app.mount("/assets", StaticFiles(directory=str(STATIC_DIR / "assets")), name="assets")
|
|
|
|
@app.get("/{full_path:path}")
|
|
def serve_spa(full_path: str):
|
|
index = STATIC_DIR / "index.html"
|
|
return FileResponse(str(index))
|