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

1.5 KiB

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.