Files
BanGUI/Docs/Tasks.md
Lukas 0225f32901 Fix country not shown in ban list due to geo rate limiting
list_bans() was calling geo_service.lookup() once per IP on the
page (e.g. 100 sequential HTTP requests), hitting the ip-api.com
free-tier single-IP limit of 45 req/min.  IPs beyond the ~45th
were added to the in-process negative cache (5 min TTL) and showed
as no country until the TTL expired.  The map endpoint never had
this problem because it used lookup_batch (100 IPs per POST).

Add http_session and app_db params to list_bans().  When
http_session is provided (production path), the entire page is
resolved in one lookup_batch() call instead of N individual ones.
The legacy geo_enricher callback is kept for test compatibility.
Update the dashboard router to use the batch path directly.

Adds 3 tests covering the batch geo path, failure resilience, and
http_session priority over geo_enricher.
2026-03-10 17:20:13 +01:00

28 lines
1.5 KiB
Markdown

# BanGUI — Task List
This document breaks the entire BanGUI project into development stages, ordered so that each stage builds on the previous one. Every task is described in prose with enough detail for a developer to begin work. References point to the relevant documentation.
---
## Completed
### [DONE] Fix: Country column shows "—" for blocklist-import IPs in ban list
**Root cause:** `ban_service.list_bans()` resolved geo data one IP at a time via
`geo_service.lookup()`, which uses the ip-api.com single-IP endpoint (45 req/min
free tier limit). A page of 100 bans triggered 100 sequential HTTP requests;
after the ~45th request ip-api.com applied rate limiting, all remaining IPs were
added to the in-process negative cache (5 min TTL), and they showed "—" in the
country column permanently until the TTL expired. Because the map endpoint
(`bans_by_country`) used `lookup_batch` (100 IPs per POST), it never hit the
rate limit, which is why the map showed colours while the list did not.
**Fix:** Added `http_session` and `app_db` parameters to `list_bans()`. When
`http_session` is provided (production path via the dashboard router), the entire
page of IPs is resolved in a single `geo_service.lookup_batch()` call instead of
100 individual ones. The legacy `geo_enricher` callback is kept for backwards
compatibility in tests. Updated `dashboard.py` to pass `http_session` and `db`
instead of constructing a per-IP enricher closure. Added 3 new tests covering
the batch path, failure resilience, and priority over `geo_enricher`.