from fastapi import APIRouter, Depends, Header, HTTPException, Query, BackgroundTasks from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.services.license import ( get_super_admins, create_license, list_licenses, get_license_status, revoke_license, restore_license, update_license, delete_license, check_license_by_referer, ) from app.schemas.license import LicenseCreate, LicenseUpdate from app.schemas.visitor import VisitorInfoCreate from app.services.visitor import store_visitor_info router = APIRouter(prefix="/api/license", tags=["License许可"]) # 公开接口,不带 /api/license 前缀,放在 /api/public 下 public_router = APIRouter(prefix="/api/public", tags=["License公开接口"]) @router.get("/super-admins", summary="超级管理员列表(下拉选项)") async def handle_get_super_admins( db: AsyncSession = Depends(get_db), ): return await get_super_admins(db) @router.post("/", summary="创建/更新 License") async def handle_create_license( payload: LicenseCreate, db: AsyncSession = Depends(get_db), ): return await create_license(db, payload) @router.get("/list", summary="License 列表") async def handle_list_licenses( super_admin_id: int | None = Query(None), status: str | None = Query(None), page: int = Query(1, ge=1), size: int = Query(20, ge=1, le=100), db: AsyncSession = Depends(get_db), ): return await list_licenses(db, super_admin_id, status, page, size) @router.get("/{license_id}", summary="License 状态详情") async def handle_get_license( license_id: int, db: AsyncSession = Depends(get_db), ): try: return await get_license_status(db, license_id) except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) @router.put("/{license_id}", summary="更新 License(key 或过期时间)") async def handle_update_license( license_id: int, payload: LicenseUpdate, background_tasks: BackgroundTasks, db: AsyncSession = Depends(get_db), ): try: return await update_license(db, license_id, payload, background_tasks) except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.post("/{license_id}/revoke", summary="吊销 License") async def handle_revoke_license( license_id: int, background_tasks: BackgroundTasks, db: AsyncSession = Depends(get_db), ): try: return await revoke_license(db, license_id, background_tasks) except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) @router.post("/{license_id}/restore", summary="恢复已吊销的 License") async def handle_restore_license( license_id: int, background_tasks: BackgroundTasks, db: AsyncSession = Depends(get_db), ): try: return await restore_license(db, license_id, background_tasks) except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.delete("/{license_id}", summary="删除 License") async def handle_delete_license( license_id: int, db: AsyncSession = Depends(get_db), ): try: return await delete_license(db, license_id) except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) @public_router.post("/visitor", summary="公开接口:存储域名联系人信息") async def handle_store_visitor( payload: VisitorInfoCreate, referer: str | None = Header(None), db: AsyncSession = Depends(get_db), ): """第三方系统通过请求携带的 Referer 头匹配域名,存储联系人信息(名字/手机/邮箱)。""" return await store_visitor_info(db, referer, payload) @public_router.get("/license/check", summary="公开 License 校验接口(通过 Referer 匹配域名)") async def handle_license_check( referer: str | None = Header(None), db: AsyncSession = Depends(get_db), ): """第三方系统通过请求携带的 Referer 头,匹配对应的监控域名,检查 License 状态。""" return await check_license_by_referer(db, referer)