控制台改为选项卡,并支持封禁节点与下发计算任务。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-11 01:33:44 +08:00
parent 80d46dcd5d
commit f0b35e6b34
18 changed files with 933 additions and 300 deletions
+42 -3
View File
@@ -44,10 +44,13 @@ from app.schemas import (
NodeView,
IPWhitelistCreate,
IPWhitelistOut,
BanToggle,
WhitelistToggle,
RegisterIn,
SettleOut,
SummaryOut,
AdminTaskOut,
TaskCreate,
TaskOut,
TaskReportIn,
TokenOut,
@@ -69,7 +72,7 @@ from app.services.common import get_node_by_sn, get_user_by_wallet
from app.services.datacenter import approve_application, list_applications, reject_application, submit_application
from app.services.hardware import HardwareReport
from app.services.hardware import display_node_id, displayed_population
from app.services.heartbeat import assert_node_token, record_heartbeat
from app.services.heartbeat import assert_node_token, record_heartbeat, set_node_banned
from app.services.ip_guard import add_whitelist_ip, client_ip, list_whitelist, remove_whitelist_ip
from app.services.orders import approve_order, list_orders, place_order, reject_order, render_client
from app.services.portal import (
@@ -81,7 +84,7 @@ from app.services.portal import (
user_rows,
)
from app.services.registry import register_node, register_user
from app.services.tasks import list_pending_tasks, report_task
from app.services.tasks import create_admin_tasks, list_admin_tasks, list_pending_tasks, report_task, result_preview
from app.services.withdrawals import available_balance, confirm_withdrawal, reject_withdrawal, request_withdrawal
from app.services.yield_engine import compute_node_yield, list_node_yields, network_yields, settle_yield_date
@@ -210,6 +213,14 @@ def admin_toggle_node_whitelist(sn: str, body: WhitelistToggle, _: AdminUser, db
return NodeView.model_validate(snapshot)
@router.post("/admin/nodes/{sn}/ban", response_model=NodeView)
def admin_ban_node(sn: str, body: BanToggle, _: AdminUser, db: Db) -> NodeView:
node = get_node_by_sn(db, sn)
set_node_banned(db, node, body.is_banned)
snapshot = next(item for item in live_nodes(db) if item["sn"] == node.sn)
return NodeView.model_validate(snapshot)
@router.get("/admin/ip-whitelist", response_model=list[IPWhitelistOut])
def admin_ip_whitelist(_: AdminUser, db: Db) -> list[IPWhitelist]:
return list_whitelist(db)
@@ -341,7 +352,18 @@ def pending_tasks(sn: str, db: Db, token: str | None = None) -> list[TaskOut]:
@router.post("/node/task/report", response_model=TaskOut)
def report(body: TaskReportIn, db: Db) -> TaskOut:
assert_node_token(get_node_by_sn(db, body.sn), body.token)
return _task_out(report_task(db, body.sn, body.task_id, body.success, body.nonce))
return _task_out(report_task(db, body.sn, body.task_id, body.success, body.nonce, result=body.result))
@router.post("/admin/tasks/create", response_model=list[AdminTaskOut])
def admin_create_tasks(body: TaskCreate, _: AdminUser, db: Db) -> list[AdminTaskOut]:
tasks = create_admin_tasks(db, body.task_type, body.payload, body.target_node_sn)
return [_admin_task_out(task) for task in tasks]
@router.get("/admin/tasks/list", response_model=list[AdminTaskOut])
def admin_list_tasks(_: AdminUser, db: Db) -> list[AdminTaskOut]:
return [_admin_task_out(task) for task in list_admin_tasks(db)]
@router.get("/nodes/{sn}/contribution", response_model=ContributionOut)
@@ -487,6 +509,23 @@ def _withdrawal_view(row: WithdrawalLog) -> WithdrawalView:
)
def _admin_task_out(task: ComputeTask) -> AdminTaskOut:
node = task.node
return AdminTaskOut(
task_id=task.id,
task_type=task.task_type,
target_node_sn=node.sn,
display_node_id=node.display_node_id,
status=task.status,
payload=task.payload or {},
result=task.result,
result_preview=result_preview(task.result),
dispatched_at=task.dispatched_at,
deadline_at=task.deadline_at,
responded_at=task.responded_at,
)
def _task_out(task: ComputeTask) -> TaskOut:
return TaskOut(
task_id=task.id,