feat: Task 3 — invalid jail config recovery (pre-validation, crash detection, rollback)
- Backend: extend activate_jail() with pre-validation and 4-attempt post-reload
health probe; add validate_jail_config() and rollback_jail() service functions
- Backend: new endpoints POST /api/config/jails/{name}/validate,
GET /api/config/pending-recovery, POST /api/config/jails/{name}/rollback
- Backend: extend JailActivationResponse with fail2ban_running + validation_warnings;
add JailValidationIssue, JailValidationResult, PendingRecovery, RollbackResponse models
- Backend: health_check task tracks last_activation and creates PendingRecovery
record when fail2ban goes offline within 60 s of an activation
- Backend: add fail2ban_start_command setting (configurable start cmd for rollback)
- Frontend: ActivateJailDialog — pre-validation on open, crash-detected callback,
extended spinner text during activation+verify
- Frontend: JailsTab — Validate Config button for inactive jails, validation
result panels (blocking errors + advisory warnings)
- Frontend: RecoveryBanner component — polls pending-recovery, shows full-width
alert with Disable & Restart / View Logs buttons
- Frontend: MainLayout — mount RecoveryBanner at layout level
- Tests: 19 new backend service tests (validate, rollback, filter/action parsing)
+ 6 health_check crash-detection tests + 11 router tests; 5 RecoveryBanner
frontend tests; fix mock setup in existing activate_jail tests
This commit is contained in:
@@ -549,6 +549,52 @@ export interface JailActivationResponse {
|
||||
active: boolean;
|
||||
/** Human-readable result message. */
|
||||
message: string;
|
||||
/** Whether fail2ban was still running after the reload. Defaults to true. */
|
||||
fail2ban_running: boolean;
|
||||
/** Non-fatal pre-activation validation warnings (e.g. missing log path). */
|
||||
validation_warnings: string[];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Jail config recovery models (Task 3)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** A single validation issue found in a jail's config. */
|
||||
export interface JailValidationIssue {
|
||||
/** Config field that has the issue, e.g. "filter", "failregex". */
|
||||
field: string;
|
||||
/** Human-readable description of the issue. */
|
||||
message: string;
|
||||
}
|
||||
|
||||
/** Full result of pre-activation validation for a single jail. */
|
||||
export interface JailValidationResult {
|
||||
jail_name: string;
|
||||
valid: boolean;
|
||||
issues: JailValidationIssue[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Recorded when fail2ban stops responding shortly after a jail activation.
|
||||
* Surfaced by `GET /api/config/pending-recovery`.
|
||||
*/
|
||||
export interface PendingRecovery {
|
||||
jail_name: string;
|
||||
/** ISO-8601 datetime string. */
|
||||
activated_at: string;
|
||||
/** ISO-8601 datetime string. */
|
||||
detected_at: string;
|
||||
/** True once fail2ban comes back online after the crash. */
|
||||
recovered: boolean;
|
||||
}
|
||||
|
||||
/** Response from `POST /api/config/jails/{name}/rollback`. */
|
||||
export interface RollbackResponse {
|
||||
jail_name: string;
|
||||
disabled: boolean;
|
||||
fail2ban_running: boolean;
|
||||
active_jails: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user