Stage 10: external blocklist importer — backend + frontend

- blocklist_repo.py: CRUD for blocklist_sources table
- import_log_repo.py: add/list/get-last log entries
- blocklist_service.py: source CRUD, preview, import (download/validate/ban),
  import_all, schedule get/set/info
- blocklist_import.py: APScheduler task (hourly/daily/weekly schedule triggers)
- blocklist.py router: 9 endpoints (list/create/update/delete/preview/import/
  schedule-get+put/log)
- blocklist.py models: ScheduleFrequency (StrEnum), ScheduleConfig, ScheduleInfo,
  ImportSourceResult, ImportRunResult, PreviewResponse
- 59 new tests (18 repo + 19 service + 22 router); 374 total pass
- ruff clean, mypy clean for Stage 10 files
- types/blocklist.ts, api/blocklist.ts, hooks/useBlocklist.ts
- BlocklistsPage.tsx: source management, schedule picker, import log table
- Frontend tsc + ESLint clean
This commit is contained in:
2026-03-01 15:33:24 +01:00
parent b8f3a1c562
commit 1efa0e973b
15 changed files with 3771 additions and 53 deletions

View File

@@ -0,0 +1,104 @@
/**
* TypeScript types for the blocklist management feature.
*/
// ---------------------------------------------------------------------------
// Sources
// ---------------------------------------------------------------------------
export interface BlocklistSource {
id: number;
name: string;
url: string;
enabled: boolean;
created_at: string;
updated_at: string;
}
export interface BlocklistSourceCreate {
name: string;
url: string;
enabled: boolean;
}
export interface BlocklistSourceUpdate {
name?: string;
url?: string;
enabled?: boolean;
}
export interface BlocklistListResponse {
sources: BlocklistSource[];
}
// ---------------------------------------------------------------------------
// Import log
// ---------------------------------------------------------------------------
export interface ImportLogEntry {
id: number;
source_id: number | null;
source_url: string;
timestamp: string;
ips_imported: number;
ips_skipped: number;
errors: string | null;
}
export interface ImportLogListResponse {
items: ImportLogEntry[];
total: number;
page: number;
page_size: number;
total_pages: number;
}
// ---------------------------------------------------------------------------
// Schedule
// ---------------------------------------------------------------------------
export type ScheduleFrequency = "hourly" | "daily" | "weekly";
export interface ScheduleConfig {
frequency: ScheduleFrequency;
interval_hours: number;
hour: number;
minute: number;
day_of_week: number;
}
export interface ScheduleInfo {
config: ScheduleConfig;
next_run_at: string | null;
last_run_at: string | null;
}
// ---------------------------------------------------------------------------
// Import results
// ---------------------------------------------------------------------------
export interface ImportSourceResult {
source_id: number | null;
source_url: string;
ips_imported: number;
ips_skipped: number;
error: string | null;
}
export interface ImportRunResult {
results: ImportSourceResult[];
total_imported: number;
total_skipped: number;
errors_count: number;
}
// ---------------------------------------------------------------------------
// Preview
// ---------------------------------------------------------------------------
export interface PreviewResponse {
entries: string[];
total_lines: number;
valid_count: number;
skipped_count: number;
}