Files
BanGUI/Docs/Tasks.md

7.4 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.


Open Issues

Architectural Review — 2026-03-16 The findings below were identified by auditing every backend and frontend module against the rules in Refactoring.md and Architekture.md. Tasks are grouped by layer and ordered so that lower-level fixes (repositories, services) are done before the layers that depend on them.


Task 1 — Blocklist-import jail ban time must be 24 hours

Status: Done

Context

When the blocklist importer bans an IP it calls jail_service.ban_ip(socket_path, BLOCKLIST_JAIL, ip) (see backend/app/services/blocklist_service.py, constant BLOCKLIST_JAIL = "blocklist-import"). That call sends set blocklist-import banip <ip> to fail2ban, which applies the jail's configured bantime. There is currently no guarantee that the blocklist-import jail's bantime is 86 400 s (24 h), so imported IPs may be released too early or held indefinitely depending on the jail template.

What to do

  1. Locate every place the blocklist-import jail is defined or provisioned — check Docker/fail2ban-dev-config/, Docker/Dockerfile.backend, any jail template files, and the setup_service.py / SetupPage.tsx flow.
  2. Ensure the blocklist-import jail is created with bantime = 86400 (24 h). If the jail is created at runtime by the setup service, add or update the bantime parameter there. If it is defined in a static config file, set bantime = 86400 in that file.
  3. Verify that the existing jail_service.ban_ip call in blocklist_service.import_source does not need a per-call duration override; the jail-level default of 86 400 s is sufficient.
  4. Add or update the relevant unit/integration test in backend/tests/ to assert that the blocklist-import jail is set up with a 24-hour bantime.

Task 2 — Clicking a jail in Jail Overview navigates to Configuration → Jails

Status: Done

Context

JailsPage.tsx renders a "Jail Overview" data grid with one row per jail (see frontend/src/pages/JailsPage.tsx). Clicking a row currently does nothing. ConfigPage.tsx hosts a tab bar with a "Jails" tab that renders JailsTab, which already uses a list/detail layout where a jail can be selected from the left pane.

What to do

  1. In JailsPage.tsx, make each jail name cell (or the entire row) a clickable element that navigates to /config with state { tab: "jails", jail: "<jailName>" }. Use useNavigate from react-router-dom; the existing Link import can be used or replaced with a programmatic navigate.
  2. In ConfigPage.tsx, read the location state on mount. If state.tab is "jails", set the active tab to "jails". Pass state.jail down to <JailsTab initialJail={state.jail} />.
  3. In JailsTab.tsx, accept an optional initialJail?: string prop. When it is provided, pre-select that jail in the left-pane list on first render (i.e. set the selected jail state to the jail whose name matches initialJail). This should scroll the item into view if the list is long.
  4. Add a frontend unit test in frontend/src/pages/__tests__/ that mounts JailsPage with a mocked jail list, clicks a jail row, and asserts that useNavigate was called with the correct path and state.

Task 3 — Setting bantime / findtime throws 400 error due to unsupported backend set command

Status: Done

Context

Editing ban time or find time in Configuration → Jails triggers an auto-save that sends the full JailConfigUpdate payload including the backend field. config_service.update_jail_config then calls set <jail> backend <value> on the fail2ban socket, which returns error code 1 with the message Invalid command 'backend' (no set action or not yet implemented). Fail2ban does not support changing a jail's backend at runtime; it must be set before the jail starts.

What to do

Backend (backend/app/services/config_service.py):

  1. Remove the if update.backend is not None: await _set("backend", update.backend) block from update_jail_config. Setting backend via the socket is not supported by fail2ban and will always fail.
  2. log_encoding has the same constraint — verify whether set <jail> logencoding is supported at runtime. If it is not, remove it too. If it is supported, leave it.
  3. Ensure the function still accepts and stores the backend value in the Pydantic model for read purposes; do not remove it from JailConfigUpdate or the response model.

Frontend (frontend/src/components/config/JailsTab.tsx):

  1. Remove backend (and log_encoding if step 2 confirms it is unsupported) from the autoSavePayload memo so the field is never sent in the PATCH/PUT body. The displayed value should remain read-only — show them as plain text or a disabled select so the user can see the current value without being able to trigger the broken set command.

Tests:

  1. Add or update the backend test for update_jail_config to assert that no set … backend command is issued, and that a payload containing a backend field does not cause an error.

Task 4 — Unify filter bar: use DashboardFilterBar in World Map and History pages

Status: Done

Context

DashboardPage.tsx uses the shared <DashboardFilterBar> component for its time-range and origin-filter controls. MapPage.tsx and HistoryPage.tsx each implement their own ad-hoc filter UI: MapPage uses a Fluent UI <Select> for time range plus an inline Toolbar for origin filter; HistoryPage uses a <Select> for time range with no origin filter toggle. The DashboardFilterBar already supports both TimeRange and BanOriginFilter with the exact toggle-button style shown in the design reference. All three pages should share the same filter appearance and interaction patterns.

What to do

  1. MapPage.tsx: Replace the custom time-range <Select> and the inline origin-filter Toolbar with <DashboardFilterBar timeRange={range} onTimeRangeChange={setRange} originFilter={originFilter} onOriginFilterChange={setOriginFilter} />. Remove the now-unused TIME_RANGE_OPTIONS constant and the BAN_ORIGIN_FILTER_LABELS inline usage. Pass originFilter to useMapData if it does not already receive it (check the hook signature).
  2. HistoryPage.tsx: Replace the custom time-range <Select> with <DashboardFilterBar>. Add an originFilter state (BanOriginFilter, default "all") and wire it through <DashboardFilterBar onOriginFilterChange={setOriginFilter} />. Pass the origin filter into the useHistory query so the backend receives it. If useHistory / HistoryQuery does not yet accept origin_filter, add the parameter to the type and the hook's fetch call.
  3. Remove any local filterBar style definitions from MapPage.tsx and HistoryPage.tsx that duplicate what DashboardFilterBar already provides.
  4. Ensure the DashboardFilterBar component's props interface (DashboardFilterBarProps in frontend/src/components/DashboardFilterBar.tsx) is not changed in a breaking way; only the call sites change.
  5. Update or add component tests for MapPage and HistoryPage to assert that DashboardFilterBar is rendered and that changing the time range or origin filter updates the displayed data.