Switch dashboard/map/history views to archive source for long-term data

Update fail2ban dbpurgeage to 648000 and history sync backfill/pagination for archive-based 7.5 day history.
This commit is contained in:
2026-04-05 20:21:54 +02:00
parent 7d09b78437
commit ffaa14f864
21 changed files with 149 additions and 37 deletions

View File

@@ -42,6 +42,7 @@ export interface UseBanTrendResult {
export function useBanTrend(
timeRange: TimeRange,
origin: BanOriginFilter,
source: "fail2ban" | "archive" = "fail2ban",
): UseBanTrendResult {
const [buckets, setBuckets] = useState<BanTrendBucket[]>([]);
const [bucketSize, setBucketSize] = useState<string>("1h");
@@ -58,7 +59,7 @@ export function useBanTrend(
setIsLoading(true);
setError(null);
fetchBanTrend(timeRange, origin)
fetchBanTrend(timeRange, origin, source)
.then((data) => {
if (controller.signal.aborted) return;
setBuckets(data.buckets);
@@ -73,7 +74,7 @@ export function useBanTrend(
setIsLoading(false);
}
});
}, [timeRange, origin]);
}, [timeRange, origin, source]);
useEffect(() => {
load();

View File

@@ -44,6 +44,7 @@ export interface UseBansResult {
export function useBans(
timeRange: TimeRange,
origin: BanOriginFilter = "all",
source: "fail2ban" | "archive" = "fail2ban",
): UseBansResult {
const [banItems, setBanItems] = useState<DashboardBanItem[]>([]);
const [total, setTotal] = useState<number>(0);
@@ -51,16 +52,16 @@ export function useBans(
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
// Reset page when time range or origin filter changes.
// Reset page when time range, origin filter, or source changes.
useEffect(() => {
setPage(1);
}, [timeRange, origin]);
}, [timeRange, origin, source]);
const doFetch = useCallback(async (): Promise<void> => {
setLoading(true);
setError(null);
try {
const data = await fetchBans(timeRange, page, PAGE_SIZE, origin);
const data = await fetchBans(timeRange, page, PAGE_SIZE, origin, source);
setBanItems(data.items);
setTotal(data.total);
} catch (err: unknown) {
@@ -68,7 +69,7 @@ export function useBans(
} finally {
setLoading(false);
}
}, [timeRange, page, origin]);
}, [timeRange, page, origin, source]);
// Stable ref to the latest doFetch so the refresh callback is always current.
const doFetchRef = useRef(doFetch);

View File

@@ -48,6 +48,7 @@ export interface UseDashboardCountryDataResult {
export function useDashboardCountryData(
timeRange: TimeRange,
origin: BanOriginFilter,
source: "fail2ban" | "archive" = "fail2ban",
): UseDashboardCountryDataResult {
const [countries, setCountries] = useState<Record<string, number>>({});
const [countryNames, setCountryNames] = useState<Record<string, string>>({});
@@ -67,7 +68,7 @@ export function useDashboardCountryData(
setIsLoading(true);
setError(null);
fetchBansByCountry(timeRange, origin)
fetchBansByCountry(timeRange, origin, source)
.then((data) => {
if (controller.signal.aborted) return;
setCountries(data.countries);
@@ -85,7 +86,7 @@ export function useDashboardCountryData(
setIsLoading(false);
}
});
}, [timeRange, origin]);
}, [timeRange, origin, source]);
useEffect(() => {
load();

View File

@@ -43,6 +43,7 @@ export interface UseMapDataResult {
export function useMapData(
range: TimeRange = "24h",
origin: BanOriginFilter = "all",
source: "fail2ban" | "archive" = "fail2ban",
): UseMapDataResult {
const [data, setData] = useState<BansByCountryResponse | null>(null);
const [loading, setLoading] = useState(true);
@@ -64,7 +65,7 @@ export function useMapData(
abortRef.current?.abort();
abortRef.current = new AbortController();
fetchBansByCountry(range, origin)
fetchBansByCountry(range, origin, source)
.then((resp) => {
setData(resp);
})
@@ -75,7 +76,7 @@ export function useMapData(
setLoading(false);
});
}, DEBOUNCE_MS);
}, [range, origin]);
}, [range, origin, source]);
useEffect((): (() => void) => {
load();