Add ban management features and update documentation

- Implement ban model, service, and router endpoints in backend
- Add ban table component and dashboard integration in frontend
- Update ban-related types and API endpoints
- Add comprehensive tests for ban service and dashboard router
- Update documentation (Features, Tasks, Architecture, Web-Design)
- Clean up old fail2ban configuration files
- Update Makefile with new commands
This commit is contained in:
2026-03-06 20:33:42 +01:00
parent 06738dbfa5
commit cbad4ea706
20 changed files with 58 additions and 760 deletions

View File

@@ -1,27 +1,21 @@
/**
* `useBans` hook.
*
* Fetches and manages paginated ban-list or access-list data from the
* dashboard endpoints. Re-fetches automatically when `timeRange` or `page`
* changes.
* Fetches and manages paginated ban-list data from the dashboard endpoint.
* Re-fetches automatically when `timeRange` or `page` changes.
*/
import { useCallback, useEffect, useRef, useState } from "react";
import { fetchAccesses, fetchBans } from "../api/dashboard";
import type { AccessListItem, DashboardBanItem, TimeRange } from "../types/ban";
import { fetchBans } from "../api/dashboard";
import type { DashboardBanItem, TimeRange } from "../types/ban";
/** The dashboard view mode: aggregate bans or individual access events. */
export type BanTableMode = "bans" | "accesses";
/** Items per page for the ban/access tables. */
/** Items per page for the ban table. */
const PAGE_SIZE = 100;
/** Return value shape for {@link useBans}. */
export interface UseBansResult {
/** Ban items — populated when `mode === "bans"`, otherwise empty. */
/** Ban items for the current page. */
banItems: DashboardBanItem[];
/** Access items — populated when `mode === "accesses"`, otherwise empty. */
accessItems: AccessListItem[];
/** Total records in the selected time window (for pagination). */
total: number;
/** Current 1-based page number. */
@@ -37,50 +31,39 @@ export interface UseBansResult {
}
/**
* Fetch and manage dashboard ban-list or access-list data.
* Fetch and manage dashboard ban-list data.
*
* Automatically re-fetches when `mode`, `timeRange`, or `page` changes.
* Automatically re-fetches when `timeRange` or `page` changes.
*
* @param mode - `"bans"` for the ban-list view; `"accesses"` for the
* access-list view.
* @param timeRange - Time-range preset that controls how far back to look.
* @returns Current data, pagination state, loading flag, and a `refresh`
* callback.
*/
export function useBans(mode: BanTableMode, timeRange: TimeRange): UseBansResult {
export function useBans(timeRange: TimeRange): UseBansResult {
const [banItems, setBanItems] = useState<DashboardBanItem[]>([]);
const [accessItems, setAccessItems] = useState<AccessListItem[]>([]);
const [total, setTotal] = useState<number>(0);
const [page, setPage] = useState<number>(1);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
// Reset page when mode or time range changes.
// Reset page when time range changes.
useEffect(() => {
setPage(1);
}, [mode, timeRange]);
}, [timeRange]);
const doFetch = useCallback(async (): Promise<void> => {
setLoading(true);
setError(null);
try {
if (mode === "bans") {
const data = await fetchBans(timeRange, page, PAGE_SIZE);
setBanItems(data.items);
setAccessItems([]);
setTotal(data.total);
} else {
const data = await fetchAccesses(timeRange, page, PAGE_SIZE);
setAccessItems(data.items);
setBanItems([]);
setTotal(data.total);
}
const data = await fetchBans(timeRange, page, PAGE_SIZE);
setBanItems(data.items);
setTotal(data.total);
} catch (err: unknown) {
setError(err instanceof Error ? err.message : "Failed to fetch data");
} finally {
setLoading(false);
}
}, [mode, timeRange, page]);
}, [timeRange, page]);
// Stable ref to the latest doFetch so the refresh callback is always current.
const doFetchRef = useRef(doFetch);
@@ -96,7 +79,6 @@ export function useBans(mode: BanTableMode, timeRange: TimeRange): UseBansResult
return {
banItems,
accessItems,
total,
page,
setPage,