feat(stage-1): inactive jail discovery and activation

- Backend: config_file_service.py parses jail.conf/jail.local/jail.d/*
  following fail2ban merge order; discovers jails not running in fail2ban
- Backend: 3 new API endpoints (GET /jails/inactive, POST /jails/{name}/activate,
  POST /jails/{name}/deactivate); moved /jails/inactive before /jails/{name}
  to fix route-ordering conflict
- Frontend: ActivateJailDialog component with optional parameter overrides
- Frontend: JailsTab extended with inactive jail list and InactiveJailDetail pane
- Frontend: JailsPage JailOverviewSection shows inactive jails with toggle
- Tests: 57 service tests + 16 router tests for all new endpoints (all pass)
- Docs: Features.md, Architekture.md, Tasks.md updated; Tasks 1.1-1.5 marked done
This commit is contained in:
2026-03-13 15:44:36 +01:00
parent a344f1035b
commit 8d9d63b866
15 changed files with 2711 additions and 182 deletions

View File

@@ -380,3 +380,60 @@ export interface JailFileConfig {
export interface JailFileConfigUpdate {
jails?: Record<string, JailSectionConfig> | null;
}
// ---------------------------------------------------------------------------
// Inactive jail models (Stage 1)
// ---------------------------------------------------------------------------
/**
* A jail discovered in fail2ban config files that is not currently active.
*
* Maps 1-to-1 with the backend ``InactiveJail`` Pydantic model.
*/
export interface InactiveJail {
/** Jail name from the config section header. */
name: string;
/** Filter name (may include mode suffix, e.g. ``sshd[mode=normal]``). */
filter: string;
/** Action references listed in the config (raw strings). */
actions: string[];
/** Port(s) to monitor, or null. */
port: string | null;
/** Log file paths to monitor. */
logpath: string[];
/** Ban duration as a raw config string (e.g. ``"10m"``), or null. */
bantime: string | null;
/** Failure-counting window as a raw config string, or null. */
findtime: string | null;
/** Number of failures before a ban is issued, or null. */
maxretry: number | null;
/** Absolute path to the config file where this jail is defined. */
source_file: string;
/** Effective ``enabled`` value — always ``false`` for inactive jails. */
enabled: boolean;
}
export interface InactiveJailListResponse {
jails: InactiveJail[];
total: number;
}
/**
* Optional override values when activating an inactive jail.
*/
export interface ActivateJailRequest {
bantime?: string | null;
findtime?: string | null;
maxretry?: number | null;
port?: string | null;
logpath?: string[] | null;
}
export interface JailActivationResponse {
/** Name of the affected jail. */
name: string;
/** New activation state: true after activate, false after deactivate. */
active: boolean;
/** Human-readable result message. */
message: string;
}