Initial commit

This commit is contained in:
liumangmang
2026-05-12 17:51:53 +08:00
commit b564ca4797
55 changed files with 6407 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
"""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))