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

@@ -33,8 +33,8 @@ from starlette.middleware.base import BaseHTTPMiddleware
from app.config import Settings, get_settings
from app.db import init_db
from app.routers import auth, bans, config, dashboard, geo, health, history, jails, server, setup
from app.tasks import health_check
from app.routers import auth, bans, blocklist, config, dashboard, geo, health, history, jails, server, setup
from app.tasks import blocklist_import, health_check
# ---------------------------------------------------------------------------
# Ensure the bundled fail2ban package is importable from fail2ban-master/
@@ -118,6 +118,9 @@ async def _lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
# --- Health-check background probe ---
health_check.register(app)
# --- Blocklist import scheduled task ---
blocklist_import.register(app)
log.info("bangui_started")
try:
@@ -279,5 +282,6 @@ def create_app(settings: Settings | None = None) -> FastAPI:
app.include_router(config.router)
app.include_router(server.router)
app.include_router(history.router)
app.include_router(blocklist.router)
return app