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

@@ -7,6 +7,7 @@ import { ENDPOINTS } from "./endpoints";
import type {
ActionConfig,
ActionConfigUpdate,
ActivateJailRequest,
AddLogPathRequest,
ConfFileContent,
ConfFileCreateRequest,
@@ -16,6 +17,8 @@ import type {
FilterConfigUpdate,
GlobalConfig,
GlobalConfigUpdate,
InactiveJailListResponse,
JailActivationResponse,
JailConfigFileContent,
JailConfigFileEnabledUpdate,
JailConfigFilesResponse,
@@ -290,3 +293,38 @@ export async function updateParsedJailFile(
): Promise<void> {
await put<undefined>(ENDPOINTS.configJailFileParsed(filename), update);
}
// ---------------------------------------------------------------------------
// Inactive jails (Stage 1)
// ---------------------------------------------------------------------------
/** Fetch all inactive jails from config files. */
export async function fetchInactiveJails(): Promise<InactiveJailListResponse> {
return get<InactiveJailListResponse>(ENDPOINTS.configJailsInactive);
}
/**
* Activate an inactive jail, optionally providing override values.
*
* @param name - The jail name.
* @param overrides - Optional parameter overrides (bantime, findtime, etc.).
*/
export async function activateJail(
name: string,
overrides?: ActivateJailRequest
): Promise<JailActivationResponse> {
return post<JailActivationResponse>(
ENDPOINTS.configJailActivate(name),
overrides ?? {}
);
}
/** Deactivate an active jail. */
export async function deactivateJail(
name: string
): Promise<JailActivationResponse> {
return post<JailActivationResponse>(
ENDPOINTS.configJailDeactivate(name),
undefined
);
}