feat: implement IP ban management with override functionality and UI updates

This commit is contained in:
Lorenzo Venerandi
2026-03-08 12:26:57 +01:00
parent a9aeb00279
commit 2539713a1d
10 changed files with 603 additions and 12 deletions

View File

@@ -137,6 +137,41 @@ async def auth_check(request: Request):
return JSONResponse(content={"authenticated": False}, status_code=401)
# ── Protected Ban Management API ─────────────────────────────────────
class BanOverrideRequest(BaseModel):
ip: str
action: str # "ban", "unban", or "reset"
@router.post("/api/ban-override")
async def ban_override(request: Request, body: BanOverrideRequest):
if not verify_auth(request):
return JSONResponse(content={"error": "Unauthorized"}, status_code=401)
db = get_db()
action_map = {"ban": True, "unban": False, "reset": None}
override_value = action_map.get(body.action)
if body.action not in action_map:
return JSONResponse(
content={"error": "Invalid action. Use: ban, unban, reset"},
status_code=400,
)
if body.action == "ban":
success = db.force_ban_ip(body.ip)
else:
success = db.set_ban_override(body.ip, override_value)
if success:
get_app_logger().info(f"Ban override: {body.action} on IP {body.ip}")
return JSONResponse(
content={"success": True, "ip": body.ip, "action": body.action}
)
return JSONResponse(content={"error": "IP not found"}, status_code=404)
@router.get("/api/all-ip-stats")
async def all_ip_stats(request: Request):
db = get_db()

View File

@@ -434,3 +434,56 @@ async def htmx_admin(request: Request):
"dashboard_path": _dashboard_path(request),
},
)
# ── Ban Management HTMX Endpoints ───────────────────────────────────
@router.get("/htmx/ban/attackers")
async def htmx_ban_attackers(
request: Request,
page: int = Query(1),
page_size: int = Query(25),
):
if not verify_auth(request):
return HTMLResponse(
"<p style='color:#f85149;'>Unauthorized</p>", status_code=200
)
db = get_db()
result = db.get_attackers_paginated(page=max(1, page), page_size=page_size)
templates = get_templates()
return templates.TemplateResponse(
"dashboard/partials/ban_attackers_table.html",
{
"request": request,
"dashboard_path": _dashboard_path(request),
"items": result["attackers"],
"pagination": result["pagination"],
},
)
@router.get("/htmx/ban/overrides")
async def htmx_ban_overrides(
request: Request,
page: int = Query(1),
page_size: int = Query(25),
):
if not verify_auth(request):
return HTMLResponse(
"<p style='color:#f85149;'>Unauthorized</p>", status_code=200
)
db = get_db()
result = db.get_ban_overrides_paginated(page=max(1, page), page_size=page_size)
templates = get_templates()
return templates.TemplateResponse(
"dashboard/partials/ban_overrides_table.html",
{
"request": request,
"dashboard_path": _dashboard_path(request),
"items": result["overrides"],
"pagination": result["pagination"],
},
)