95 lines
4.4 KiB
Python
95 lines
4.4 KiB
Python
from fastapi import APIRouter, Cookie, HTTPException, Request
|
|
from fastapi.responses import HTMLResponse
|
|
|
|
from app.db import auth_db
|
|
from app.db.scheduler_db import (
|
|
enqueue_manual_trigger,
|
|
get_job_config,
|
|
get_scheduler_overview,
|
|
list_manual_triggers,
|
|
set_job_enabled,
|
|
set_job_interval,
|
|
)
|
|
from app.web.shared import (
|
|
SchedulerIntervalRequest,
|
|
SchedulerToggleRequest,
|
|
SchedulerTriggerRequest,
|
|
login_redirect,
|
|
require_admin,
|
|
)
|
|
|
|
def build_router(templates):
|
|
router = APIRouter()
|
|
|
|
@router.get("/admin.html", response_class=HTMLResponse)
|
|
async def admin_page(request: Request, altcoin_session: str = Cookie(default="")):
|
|
if not auth_db.get_user_by_session_token(altcoin_session):
|
|
return login_redirect()
|
|
try:
|
|
require_admin(altcoin_session)
|
|
except HTTPException as e:
|
|
return HTMLResponse(content=f"<meta charset=utf-8><h2>需要管理员权限</h2><p>{e.detail}</p><a href=/app>返回看板</a>", status_code=e.status_code)
|
|
return templates.TemplateResponse(request=request, name="admin.html", context={"show_nav": True})
|
|
|
|
@router.get("/api/admin/check")
|
|
async def api_admin_check(altcoin_session: str = Cookie(default="")):
|
|
try:
|
|
user = require_admin(altcoin_session)
|
|
return {"is_admin": True, "email": user.get("email", "")}
|
|
except HTTPException:
|
|
return {"is_admin": False}
|
|
|
|
@router.get("/api/admin/stats")
|
|
async def api_admin_stats(altcoin_session: str = Cookie(default="")):
|
|
require_admin(altcoin_session)
|
|
return auth_db.get_admin_stats()
|
|
|
|
@router.get("/api/admin/users")
|
|
async def api_admin_users(search: str = "", offset: int = 0, limit: int = 50, tab: str = "all", altcoin_session: str = Cookie(default="")):
|
|
require_admin(altcoin_session)
|
|
return auth_db.get_admin_users(search=search, offset=offset, limit=limit, tab=tab)
|
|
|
|
@router.get("/api/admin/orders")
|
|
async def api_admin_orders(search: str = "", offset: int = 0, limit: int = 50, status: str = "all", altcoin_session: str = Cookie(default="")):
|
|
require_admin(altcoin_session)
|
|
return auth_db.get_admin_orders(search=search, offset=offset, limit=limit, status=status)
|
|
|
|
@router.get("/api/scheduler/jobs")
|
|
async def api_scheduler_jobs(altcoin_session: str = Cookie(default="")):
|
|
require_admin(altcoin_session)
|
|
return get_scheduler_overview()
|
|
|
|
@router.post("/api/scheduler/jobs/{job_name}/toggle")
|
|
async def api_scheduler_toggle(job_name: str, payload: SchedulerToggleRequest, altcoin_session: str = Cookie(default="")):
|
|
require_admin(altcoin_session)
|
|
if not set_job_enabled(job_name, payload.enabled):
|
|
raise HTTPException(status_code=404, detail="任务不存在")
|
|
return {"ok": True, "job_name": job_name, "enabled": payload.enabled}
|
|
|
|
@router.post("/api/scheduler/jobs/{job_name}/interval")
|
|
async def api_scheduler_interval(job_name: str, payload: SchedulerIntervalRequest, altcoin_session: str = Cookie(default="")):
|
|
require_admin(altcoin_session)
|
|
if payload.every_seconds < 30:
|
|
raise HTTPException(status_code=400, detail="周期不能低于 30 秒")
|
|
if not set_job_interval(job_name, payload.every_seconds):
|
|
raise HTTPException(status_code=404, detail="任务不存在")
|
|
return {"ok": True, "job_name": job_name, "every_seconds": payload.every_seconds}
|
|
|
|
@router.post("/api/scheduler/jobs/{job_name}/trigger")
|
|
async def api_scheduler_trigger(job_name: str, payload: SchedulerTriggerRequest, altcoin_session: str = Cookie(default="")):
|
|
user = require_admin(altcoin_session)
|
|
job = get_job_config(job_name)
|
|
if not job:
|
|
raise HTTPException(status_code=404, detail="任务不存在")
|
|
if not job.get("enabled") and not payload.force:
|
|
raise HTTPException(status_code=409, detail="任务已关闭,需要确认后 force=true 才能单次运行")
|
|
trigger_id = enqueue_manual_trigger(job_name, force=payload.force, requested_by=user.get("email", ""))
|
|
return {"ok": True, "job_name": job_name, "trigger_id": trigger_id, "force": payload.force}
|
|
|
|
@router.get("/api/scheduler/triggers")
|
|
async def api_scheduler_triggers(limit: int = 30, altcoin_session: str = Cookie(default="")):
|
|
require_admin(altcoin_session)
|
|
return {"items": list_manual_triggers(limit=limit)}
|
|
|
|
return router
|