From 8bdad3529fb81b86563ff69392a88487f33454d9 Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 13 Mar 2026 13:47:45 +0100 Subject: [PATCH] feat(frontend): add config types and API client for file-config endpoints - types/config.ts: TypeScript interfaces for ActionConfig, FilterConfig, JailFileConfig, ConfFileContent, and related request/response shapes - api/config.ts: typed API functions for reading and writing conf files - api/endpoints.ts: add /config/file/* endpoint constants --- frontend/src/api/config.ts | 57 ++++++++++++++ frontend/src/api/endpoints.ts | 6 ++ frontend/src/types/config.ts | 138 ++++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+) diff --git a/frontend/src/api/config.ts b/frontend/src/api/config.ts index c92c259..fabb850 100644 --- a/frontend/src/api/config.ts +++ b/frontend/src/api/config.ts @@ -5,11 +5,15 @@ import { del, get, post, put } from "./client"; import { ENDPOINTS } from "./endpoints"; import type { + ActionConfig, + ActionConfigUpdate, AddLogPathRequest, ConfFileContent, ConfFileCreateRequest, ConfFilesResponse, ConfFileUpdateRequest, + FilterConfig, + FilterConfigUpdate, GlobalConfig, GlobalConfigUpdate, JailConfigFileContent, @@ -26,6 +30,8 @@ import type { RegexTestResponse, ServerSettingsResponse, ServerSettingsUpdate, + JailFileConfig, + JailFileConfigUpdate, } from "../types/config"; // --------------------------------------------------------------------------- @@ -164,6 +170,12 @@ export async function fetchJailConfigFiles(): Promise { return get(ENDPOINTS.configJailFiles); } +export async function createJailConfigFile( + req: ConfFileCreateRequest +): Promise { + return post(ENDPOINTS.configJailFiles, req); +} + export async function fetchJailConfigFileContent( filename: string ): Promise { @@ -226,3 +238,48 @@ export async function createActionFile( ): Promise { return post(ENDPOINTS.configActions, req); } + +// --------------------------------------------------------------------------- +// Parsed filter config (Task 2.2) +// --------------------------------------------------------------------------- + +export async function fetchParsedFilter(name: string): Promise { + return get(ENDPOINTS.configFilterParsed(name)); +} + +export async function updateParsedFilter( + name: string, + update: FilterConfigUpdate +): Promise { + await put(ENDPOINTS.configFilterParsed(name), update); +} + +// --------------------------------------------------------------------------- +// Parsed action config (Task 3.2) +// --------------------------------------------------------------------------- + +export async function fetchParsedAction(name: string): Promise { + return get(ENDPOINTS.configActionParsed(name)); +} + +export async function updateParsedAction( + name: string, + update: ActionConfigUpdate +): Promise { + await put(ENDPOINTS.configActionParsed(name), update); +} + +// --------------------------------------------------------------------------- +// Parsed jail file config (Task 6.1 / 6.2) +// --------------------------------------------------------------------------- + +export async function fetchParsedJailFile(filename: string): Promise { + return get(ENDPOINTS.configJailFileParsed(filename)); +} + +export async function updateParsedJailFile( + filename: string, + update: JailFileConfigUpdate +): Promise { + await put(ENDPOINTS.configJailFileParsed(filename), update); +} diff --git a/frontend/src/api/endpoints.ts b/frontend/src/api/endpoints.ts index 4695e4d..eb4940c 100644 --- a/frontend/src/api/endpoints.ts +++ b/frontend/src/api/endpoints.ts @@ -76,10 +76,16 @@ export const ENDPOINTS = { `/config/jail-files/${encodeURIComponent(filename)}`, configJailFileEnabled: (filename: string): string => `/config/jail-files/${encodeURIComponent(filename)}/enabled`, + configJailFileParsed: (filename: string): string => + `/config/jail-files/${encodeURIComponent(filename)}/parsed`, configFilters: "/config/filters", configFilter: (name: string): string => `/config/filters/${encodeURIComponent(name)}`, + configFilterParsed: (name: string): string => + `/config/filters/${encodeURIComponent(name)}/parsed`, configActions: "/config/actions", configAction: (name: string): string => `/config/actions/${encodeURIComponent(name)}`, + configActionParsed: (name: string): string => + `/config/actions/${encodeURIComponent(name)}/parsed`, // ------------------------------------------------------------------------- // Server settings diff --git a/frontend/src/types/config.ts b/frontend/src/types/config.ts index 5404328..5630529 100644 --- a/frontend/src/types/config.ts +++ b/frontend/src/types/config.ts @@ -242,3 +242,141 @@ export interface ConfFileCreateRequest { name: string; content: string; } + +// --------------------------------------------------------------------------- +// Parsed filter config (Task 2.1 / 2.2) +// --------------------------------------------------------------------------- + +/** + * Structured representation of a ``filter.d/*.conf`` file. + * Maps 1-to-1 with the backend ``FilterConfig`` Pydantic model. + */ +export interface FilterConfig { + /** Base name without extension, e.g. "sshd". */ + name: string; + /** Actual filename, e.g. "sshd.conf". */ + filename: string; + /** [INCLUDES] before directive, or null. */ + before: string | null; + /** [INCLUDES] after directive, or null. */ + after: string | null; + /** [DEFAULT] section key-value pairs (e.g. _daemon, __prefix). */ + variables: Record; + /** prefregex line, or null. */ + prefregex: string | null; + /** failregex patterns (one per entry). */ + failregex: string[]; + /** ignoreregex patterns (one per entry). */ + ignoreregex: string[]; + /** maxlines, or null. */ + maxlines: number | null; + /** datepattern, or null. */ + datepattern: string | null; + /** journalmatch, or null. */ + journalmatch: string | null; +} + +/** + * Partial update payload for a filter config. + * All fields are optional; ``null`` means leave unchanged. + */ +export interface FilterConfigUpdate { + before?: string | null; + after?: string | null; + variables?: Record | null; + prefregex?: string | null; + failregex?: string[] | null; + ignoreregex?: string[] | null; + maxlines?: number | null; + datepattern?: string | null; + journalmatch?: string | null; +} + +// --------------------------------------------------------------------------- +// Parsed action config (Task 3.1 / 3.2) +// --------------------------------------------------------------------------- + +/** + * Structured representation of an ``action.d/*.conf`` file. + * Maps 1-to-1 with the backend ``ActionConfig`` Pydantic model. + */ +export interface ActionConfig { + /** Base name without extension, e.g. "iptables". */ + name: string; + /** Actual filename, e.g. "iptables.conf". */ + filename: string; + /** [INCLUDES] before directive, or null. */ + before: string | null; + /** [INCLUDES] after directive, or null. */ + after: string | null; + /** actionstart command, or null. */ + actionstart: string | null; + /** actionstop command, or null. */ + actionstop: string | null; + /** actioncheck command, or null. */ + actioncheck: string | null; + /** actionban command, or null. */ + actionban: string | null; + /** actionunban command, or null. */ + actionunban: string | null; + /** actionflush command, or null. */ + actionflush: string | null; + /** [Definition] key-value pairs that are not lifecycle commands. */ + definition_vars: Record; + /** [Init] section key-value pairs. */ + init_vars: Record; +} + +/** + * Partial update payload for an action config. + * All fields are optional; ``null`` means leave unchanged. + */ +export interface ActionConfigUpdate { + before?: string | null; + after?: string | null; + actionstart?: string | null; + actionstop?: string | null; + actioncheck?: string | null; + actionban?: string | null; + actionunban?: string | null; + actionflush?: string | null; + definition_vars?: Record | null; + init_vars?: Record | null; +} + +// --------------------------------------------------------------------------- +// Parsed jail file config (Task 6.1 / 6.2) +// --------------------------------------------------------------------------- + +/** + * Settings within a single [jailname] section of a jail.d/*.conf file. + * Maps 1-to-1 with the backend ``JailSectionConfig`` Pydantic model. + */ +export interface JailSectionConfig { + enabled: boolean | null; + port: string | null; + filter: string | null; + logpath: string[]; + maxretry: number | null; + findtime: number | null; + bantime: number | null; + action: string[]; + backend: string | null; + extra: Record; +} + +/** + * Structured representation of a ``jail.d/*.conf`` file. + * Maps 1-to-1 with the backend ``JailFileConfig`` Pydantic model. + */ +export interface JailFileConfig { + filename: string; + jails: Record; +} + +/** + * Partial update payload for a jail file config. + */ +export interface JailFileConfigUpdate { + jails?: Record | null; +}