feat: implement IP ban management with override functionality and UI updates
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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"],
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user