Split frontend config API into file_config, server, and health modules

This commit is contained in:
2026-04-18 20:32:38 +02:00
parent 01f2e07921
commit d9550ae4aa
14 changed files with 179 additions and 37 deletions

View File

@@ -1,5 +1,5 @@
/**
* API functions for the configuration and server settings endpoints.
* API functions for the configuration endpoints.
*/
import { del, get, post, put } from "./client";
@@ -41,8 +41,6 @@ import type {
MapColorThresholdsUpdate,
RegexTestRequest,
RegexTestResponse,
ServerSettingsResponse,
ServerSettingsUpdate,
JailFileConfig,
JailFileConfigUpdate,
ServiceStatusResponse,
@@ -139,30 +137,6 @@ export async function previewLog(
return post<LogPreviewResponse>(ENDPOINTS.configPreviewLog, req);
}
// ---------------------------------------------------------------------------
// Server settings
// ---------------------------------------------------------------------------
export async function fetchServerSettings(
): Promise<ServerSettingsResponse> {
return get<ServerSettingsResponse>(ENDPOINTS.serverSettings);
}
export async function updateServerSettings(
update: ServerSettingsUpdate
): Promise<void> {
await put<undefined>(ENDPOINTS.serverSettings, update);
}
export async function flushLogs(
): Promise<string> {
const resp = await post<{ message: string }>(
ENDPOINTS.serverFlushLogs,
undefined,
);
return resp.message;
}
// ---------------------------------------------------------------------------
// Map color thresholds
// ---------------------------------------------------------------------------

View File

@@ -0,0 +1,102 @@
import { get, post, put } from "./client";
import { ENDPOINTS } from "./endpoints";
import type {
ActionListResponse,
ConfFileContent,
ConfFileCreateRequest,
ConfFileUpdateRequest,
ConfFilesResponse,
FilterListResponse,
JailConfigFileContent,
JailConfigFilesResponse,
} from "../types/config";
export async function fetchJailConfigFiles(): Promise<JailConfigFilesResponse> {
return get<JailConfigFilesResponse>(ENDPOINTS.configJailFiles);
}
export async function createJailConfigFile(
req: ConfFileCreateRequest,
): Promise<ConfFileContent> {
return post<ConfFileContent>(ENDPOINTS.configJailFiles, req);
}
export async function fetchJailConfigFileContent(
filename: string,
): Promise<JailConfigFileContent> {
return get<JailConfigFileContent>(ENDPOINTS.configJailFile(filename));
}
export async function updateJailConfigFile(
filename: string,
req: ConfFileUpdateRequest,
): Promise<void> {
await put<undefined>(ENDPOINTS.configJailFile(filename), req);
}
export async function setJailConfigFileEnabled(
filename: string,
update: { enabled: boolean },
): Promise<void> {
await put<undefined>(ENDPOINTS.configJailFileEnabled(filename), update);
}
export async function fetchFilterFiles(): Promise<ConfFilesResponse> {
const result = await get<FilterListResponse>(ENDPOINTS.configFilters);
return {
files: result.filters.map((filter) => ({
name: filter.name,
filename: filter.filename,
})),
total: result.total,
};
}
export async function fetchFilterFile(
name: string,
): Promise<ConfFileContent> {
return get<ConfFileContent>(ENDPOINTS.configFilterRaw(name));
}
export async function updateFilterFile(
name: string,
req: ConfFileUpdateRequest,
): Promise<void> {
await put<undefined>(ENDPOINTS.configFilterRaw(name), req);
}
export async function createFilterFile(
req: ConfFileCreateRequest,
): Promise<ConfFileContent> {
return post<ConfFileContent>(ENDPOINTS.configFiltersRaw, req);
}
export async function fetchActionFiles(): Promise<ConfFilesResponse> {
const result = await get<ActionListResponse>(ENDPOINTS.configActions);
return {
files: result.actions.map((action) => ({
name: action.name,
filename: action.filename,
})),
total: result.total,
};
}
export async function fetchActionFile(
name: string,
): Promise<ConfFileContent> {
return get<ConfFileContent>(ENDPOINTS.configActionRaw(name));
}
export async function updateActionFile(
name: string,
req: ConfFileUpdateRequest,
): Promise<void> {
await put<undefined>(ENDPOINTS.configActionRaw(name), req);
}
export async function createActionFile(
req: ConfFileCreateRequest,
): Promise<ConfFileContent> {
return post<ConfFileContent>(ENDPOINTS.configActions, req);
}

View File

@@ -0,0 +1,7 @@
import { get } from "./client";
import { ENDPOINTS } from "./endpoints";
import type { HealthResponse } from "../types/server";
export async function fetchHealth(): Promise<HealthResponse> {
return get<HealthResponse>(ENDPOINTS.health);
}

View File

@@ -0,0 +1,24 @@
import { get, post, put } from "./client";
import { ENDPOINTS } from "./endpoints";
import type {
ServerSettingsResponse,
ServerSettingsUpdate,
} from "../types/config";
export async function fetchServerSettings(): Promise<ServerSettingsResponse> {
return get<ServerSettingsResponse>(ENDPOINTS.serverSettings);
}
export async function updateServerSettings(
update: ServerSettingsUpdate,
): Promise<void> {
await put<undefined>(ENDPOINTS.serverSettings, update);
}
export async function flushLogs(): Promise<string> {
const resp = await post<{ message: string }>(
ENDPOINTS.serverFlushLogs,
undefined,
);
return resp.message;
}

View File

@@ -118,6 +118,26 @@ vi.mock("../../api/config", () => ({
updateParsedJailFile: vi.fn(),
}));
vi.mock("../../api/file_config", () => ({
fetchJailConfigFiles: mockFetchJailConfigFiles,
createJailConfigFile: vi.fn().mockResolvedValue({
name: "new-jail",
filename: "new-jail.conf",
content: "# new-jail\n",
}),
fetchJailConfigFileContent: vi.fn(),
updateJailConfigFile: mockUpdateJailConfigFile,
setJailConfigFileEnabled: mockSetJailConfigFileEnabled,
fetchFilterFiles: mockFetchFilterFiles,
fetchFilterFile: vi.fn(),
updateFilterFile: vi.fn(),
createFilterFile: vi.fn(),
fetchActionFiles: mockFetchActionFiles,
fetchActionFile: vi.fn(),
updateActionFile: vi.fn(),
createActionFile: vi.fn(),
}));
vi.mock("../../api/jails", () => ({
fetchJails: vi.fn().mockResolvedValue({ jails: [], total: 0 }),
}));

View File

@@ -24,10 +24,9 @@ import {
import { Add24Regular, Delete24Regular, LinkEdit24Regular } from "@fluentui/react-icons";
import {
fetchActionFile,
fetchActions,
removeActionFromJail,
updateActionFile,
} from "../../api/config";
} from "../../api/file_config";
import { fetchActions, removeActionFromJail } from "../../api/config";
import type { ActionConfig, ConfFileUpdateRequest } from "../../types/config";
import { ActionForm } from "./ActionForm";
import { AssignActionDialog } from "./AssignActionDialog";

View File

@@ -22,7 +22,7 @@ import {
Text,
tokens,
} from "@fluentui/react-components";
import { createJailConfigFile } from "../../api/config";
import { createJailConfigFile } from "../../api/file_config";
import type { ConfFileCreateRequest } from "../../types/config";
import { ApiError } from "../../api/client";

View File

@@ -20,7 +20,7 @@ import {
createFilterFile,
updateActionFile,
updateFilterFile,
} from "../../api/config";
} from "../../api/file_config";
import { JailFilesTab } from "./JailFilesTab";
import { ConfFilesTab } from "./ConfFilesTab";

View File

@@ -22,7 +22,8 @@ import {
tokens,
} from "@fluentui/react-components";
import { Add24Regular, LinkEdit24Regular } from "@fluentui/react-icons";
import { fetchFilterFile, fetchFilters, updateFilterFile } from "../../api/config";
import { fetchFilterFile, updateFilterFile } from "../../api/file_config";
import { fetchFilters } from "../../api/config";
import type { ConfFileUpdateRequest, FilterConfig } from "../../types/config";
import { AssignFilterDialog } from "./AssignFilterDialog";
import { ConfigListDetail } from "./ConfigListDetail";

View File

@@ -31,7 +31,7 @@ import {
createJailConfigFile,
fetchJailConfigFiles,
setJailConfigFileEnabled,
} from "../../api/config";
} from "../../api/file_config";
import type { JailConfigFile } from "../../types/config";
import { JailFileForm } from "./JailFileForm";
import { useConfigStyles } from "./configStyles";

View File

@@ -14,6 +14,9 @@ import type { FilterConfig, FilterListResponse } from "../../../types/config";
vi.mock("../../../api/config", () => ({
fetchFilters: vi.fn(),
}));
vi.mock("../../../api/file_config", () => ({
fetchFilterFile: vi.fn(),
updateFilterFile: vi.fn(),
}));

View File

@@ -8,16 +8,18 @@ import {
fetchGlobalConfig,
fetchJailConfig,
fetchJailConfigs,
fetchServerSettings,
flushLogs,
previewLog,
reloadConfig,
restartFail2Ban,
testRegex,
updateGlobalConfig,
updateJailConfig,
updateServerSettings,
} from "../api/config";
import {
fetchServerSettings,
flushLogs,
updateServerSettings,
} from "../api/server";
import { handleFetchError } from "../utils/fetchError";
import type {
AddLogPathRequest,

View File

@@ -22,3 +22,9 @@ export interface ServerStatus {
export interface ServerStatusResponse {
status: ServerStatus;
}
/** Response shape for ``GET /api/health``. */
export interface HealthResponse {
status: "ok";
fail2ban: "online" | "offline";
}