mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 06:40:45 +08:00
Collect interface bit/s via CLI on a schedule, store samples in Postgres, and chart trends with uPlot. Co-authored-by: Cursor <cursoragent@cursor.com>
211 lines
5.7 KiB
Python
211 lines
5.7 KiB
Python
"""HTTP API for port traffic monitoring."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from fastapi import APIRouter, Depends, Query, Request
|
|
from sqlalchemy.orm import Session
|
|
|
|
from .auth_service import write_audit
|
|
from .db import get_db
|
|
from .port_traffic_schemas import (
|
|
DiscoverPortsRequest,
|
|
PortTrafficTaskCreate,
|
|
PortTrafficTaskUpdate,
|
|
PortTrafficTargetsPut,
|
|
)
|
|
from .port_traffic_service import (
|
|
create_task,
|
|
dashboard,
|
|
delete_task,
|
|
discover_ports,
|
|
get_samples,
|
|
get_task,
|
|
list_targets,
|
|
list_tasks,
|
|
put_targets,
|
|
set_task_status,
|
|
update_task,
|
|
)
|
|
|
|
router = APIRouter(prefix="/v1/port-traffic", tags=["port-traffic"])
|
|
|
|
|
|
def _actor(request: Request) -> tuple[str, str]:
|
|
user = getattr(request.state, "auth_user", None)
|
|
if not user:
|
|
return "", ""
|
|
return str(getattr(user, "id", "") or ""), str(getattr(user, "username", "") or "")
|
|
|
|
|
|
@router.get("/dashboard")
|
|
def api_dashboard(db: Session = Depends(get_db)):
|
|
return dashboard(db).model_dump()
|
|
|
|
|
|
@router.get("/tasks")
|
|
def api_list_tasks(
|
|
page: int = Query(default=1, ge=1),
|
|
page_size: int = Query(default=20, ge=1, le=100),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
return list_tasks(db, page=page, page_size=page_size)
|
|
|
|
|
|
@router.post("/tasks")
|
|
def api_create_task(
|
|
body: PortTrafficTaskCreate,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
out = create_task(db, body)
|
|
uid, uname = _actor(request)
|
|
write_audit(
|
|
db,
|
|
action="port_traffic.task.create",
|
|
actor_user_id=uid,
|
|
actor_username=uname,
|
|
method="POST",
|
|
path="/v1/port-traffic/tasks",
|
|
status_code=200,
|
|
detail={"id": out.id, "title": out.title, "start_now": body.start_now},
|
|
)
|
|
return out.model_dump()
|
|
|
|
|
|
@router.get("/tasks/{task_id}")
|
|
def api_get_task(task_id: str, db: Session = Depends(get_db)):
|
|
return get_task(db, task_id).model_dump()
|
|
|
|
|
|
@router.patch("/tasks/{task_id}")
|
|
def api_patch_task(
|
|
task_id: str,
|
|
body: PortTrafficTaskUpdate,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
out = update_task(db, task_id, body)
|
|
uid, uname = _actor(request)
|
|
write_audit(
|
|
db,
|
|
action="port_traffic.task.update",
|
|
actor_user_id=uid,
|
|
actor_username=uname,
|
|
method="PATCH",
|
|
path=f"/v1/port-traffic/tasks/{task_id}",
|
|
status_code=200,
|
|
detail=body.model_dump(exclude_unset=True),
|
|
)
|
|
return out.model_dump()
|
|
|
|
|
|
@router.delete("/tasks/{task_id}")
|
|
def api_delete_task(task_id: str, request: Request, db: Session = Depends(get_db)):
|
|
out = delete_task(db, task_id)
|
|
uid, uname = _actor(request)
|
|
write_audit(
|
|
db,
|
|
action="port_traffic.task.delete",
|
|
actor_user_id=uid,
|
|
actor_username=uname,
|
|
method="DELETE",
|
|
path=f"/v1/port-traffic/tasks/{task_id}",
|
|
status_code=200,
|
|
detail={"id": task_id},
|
|
)
|
|
return out
|
|
|
|
|
|
@router.post("/tasks/{task_id}/start")
|
|
def api_start_task(task_id: str, request: Request, db: Session = Depends(get_db)):
|
|
out = set_task_status(db, task_id, "running")
|
|
uid, uname = _actor(request)
|
|
write_audit(
|
|
db,
|
|
action="port_traffic.task.start",
|
|
actor_user_id=uid,
|
|
actor_username=uname,
|
|
method="POST",
|
|
path=f"/v1/port-traffic/tasks/{task_id}/start",
|
|
status_code=200,
|
|
detail={"id": task_id},
|
|
)
|
|
return out.model_dump()
|
|
|
|
|
|
@router.post("/tasks/{task_id}/pause")
|
|
def api_pause_task(task_id: str, request: Request, db: Session = Depends(get_db)):
|
|
out = set_task_status(db, task_id, "paused")
|
|
uid, uname = _actor(request)
|
|
write_audit(
|
|
db,
|
|
action="port_traffic.task.pause",
|
|
actor_user_id=uid,
|
|
actor_username=uname,
|
|
method="POST",
|
|
path=f"/v1/port-traffic/tasks/{task_id}/pause",
|
|
status_code=200,
|
|
detail={"id": task_id},
|
|
)
|
|
return out.model_dump()
|
|
|
|
|
|
@router.post("/tasks/{task_id}/stop")
|
|
def api_stop_task(task_id: str, request: Request, db: Session = Depends(get_db)):
|
|
out = set_task_status(db, task_id, "stopped")
|
|
uid, uname = _actor(request)
|
|
write_audit(
|
|
db,
|
|
action="port_traffic.task.stop",
|
|
actor_user_id=uid,
|
|
actor_username=uname,
|
|
method="POST",
|
|
path=f"/v1/port-traffic/tasks/{task_id}/stop",
|
|
status_code=200,
|
|
detail={"id": task_id},
|
|
)
|
|
return out.model_dump()
|
|
|
|
|
|
@router.get("/tasks/{task_id}/targets")
|
|
def api_list_targets(task_id: str, db: Session = Depends(get_db)):
|
|
return {"items": [t.model_dump() for t in list_targets(db, task_id)]}
|
|
|
|
|
|
@router.put("/tasks/{task_id}/targets")
|
|
def api_put_targets(
|
|
task_id: str,
|
|
body: PortTrafficTargetsPut,
|
|
request: Request,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
items = put_targets(db, task_id, body)
|
|
uid, uname = _actor(request)
|
|
write_audit(
|
|
db,
|
|
action="port_traffic.targets.put",
|
|
actor_user_id=uid,
|
|
actor_username=uname,
|
|
method="PUT",
|
|
path=f"/v1/port-traffic/tasks/{task_id}/targets",
|
|
status_code=200,
|
|
detail={"id": task_id, "count": len(items)},
|
|
)
|
|
return {"items": [t.model_dump() for t in items]}
|
|
|
|
|
|
@router.post("/discover/ports")
|
|
def api_discover_ports(body: DiscoverPortsRequest, db: Session = Depends(get_db)):
|
|
return discover_ports(db, body).model_dump()
|
|
|
|
|
|
@router.get("/samples")
|
|
def api_samples(
|
|
target_id: str = Query(..., description="port_traffic_target row id"),
|
|
from_ts: datetime | None = Query(default=None, alias="from"),
|
|
to_ts: datetime | None = Query(default=None, alias="to"),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
return get_samples(db, target_row_id=target_id, from_ts=from_ts, to_ts=to_ts).model_dump()
|