Merge Global tab into Server tab and remove Global tab
Global tab provided the same four editable fields as Server tab: log_level, log_target, db_purge_age, db_max_matches. Server tab already has these fields plus additional read-only info (db_path, syslog_socket) and a Flush Logs button. - Add hint text to DB Purge Age and DB Max Matches fields in ServerTab - Remove GlobalTab component import from ConfigPage - Remove 'global' from TabValue type - Remove Global tab element from TabList - Remove conditional render for GlobalTab - Remove GlobalTab from barrel export (index.ts) - Delete GlobalTab.tsx file - Update ConfigPage test to remove Global tab test case All 123 frontend tests pass.
This commit is contained in:
@@ -1,142 +0,0 @@
|
||||
/**
|
||||
* GlobalTab — global fail2ban settings editor.
|
||||
*
|
||||
* Provides form fields for log level, log target, database purge age,
|
||||
* and database max matches.
|
||||
*/
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
Field,
|
||||
Input,
|
||||
MessageBar,
|
||||
MessageBarBody,
|
||||
Select,
|
||||
Spinner,
|
||||
} from "@fluentui/react-components";
|
||||
import type { GlobalConfigUpdate } from "../../types/config";
|
||||
import { useGlobalConfig } from "../../hooks/useConfig";
|
||||
import { useAutoSave } from "../../hooks/useAutoSave";
|
||||
import { AutoSaveIndicator } from "./AutoSaveIndicator";
|
||||
import { useConfigStyles } from "./configStyles";
|
||||
|
||||
/** Available fail2ban log levels in descending severity order. */
|
||||
const LOG_LEVELS = ["CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"];
|
||||
|
||||
/**
|
||||
* Tab component for editing global fail2ban configuration.
|
||||
*
|
||||
* @returns JSX element.
|
||||
*/
|
||||
export function GlobalTab(): React.JSX.Element {
|
||||
const styles = useConfigStyles();
|
||||
const { config, loading, error, updateConfig } = useGlobalConfig();
|
||||
const [logLevel, setLogLevel] = useState("");
|
||||
const [logTarget, setLogTarget] = useState("");
|
||||
const [dbPurgeAge, setDbPurgeAge] = useState("");
|
||||
const [dbMaxMatches, setDbMaxMatches] = useState("");
|
||||
|
||||
// Sync local state when config loads for the first time.
|
||||
useEffect(() => {
|
||||
if (config && logLevel === "") {
|
||||
setLogLevel(config.log_level);
|
||||
setLogTarget(config.log_target);
|
||||
setDbPurgeAge(String(config.db_purge_age));
|
||||
setDbMaxMatches(String(config.db_max_matches));
|
||||
}
|
||||
// Only run on first config load.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [config]);
|
||||
|
||||
const effectiveLogLevel = logLevel || config?.log_level || "";
|
||||
const effectiveLogTarget = logTarget || config?.log_target || "";
|
||||
const effectiveDbPurgeAge =
|
||||
dbPurgeAge || (config ? String(config.db_purge_age) : "");
|
||||
const effectiveDbMaxMatches =
|
||||
dbMaxMatches || (config ? String(config.db_max_matches) : "");
|
||||
|
||||
const updatePayload = useMemo<GlobalConfigUpdate>(() => {
|
||||
const update: GlobalConfigUpdate = {};
|
||||
if (effectiveLogLevel) update.log_level = effectiveLogLevel;
|
||||
if (effectiveLogTarget) update.log_target = effectiveLogTarget;
|
||||
if (effectiveDbPurgeAge)
|
||||
update.db_purge_age = Number(effectiveDbPurgeAge);
|
||||
if (effectiveDbMaxMatches)
|
||||
update.db_max_matches = Number(effectiveDbMaxMatches);
|
||||
return update;
|
||||
}, [effectiveLogLevel, effectiveLogTarget, effectiveDbPurgeAge, effectiveDbMaxMatches]);
|
||||
|
||||
const { status: saveStatus, errorText: saveErrorText, retry: retrySave } =
|
||||
useAutoSave(updatePayload, updateConfig);
|
||||
|
||||
if (loading) return <Spinner label="Loading global config…" />;
|
||||
if (error)
|
||||
return (
|
||||
<MessageBar intent="error">
|
||||
<MessageBarBody>{error}</MessageBarBody>
|
||||
</MessageBar>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.sectionCard}>
|
||||
<AutoSaveIndicator
|
||||
status={saveStatus}
|
||||
errorText={saveErrorText}
|
||||
onRetry={retrySave}
|
||||
/>
|
||||
<div className={styles.fieldRow}>
|
||||
<Field label="Log Level">
|
||||
<Select
|
||||
value={effectiveLogLevel}
|
||||
onChange={(_e, d) => {
|
||||
setLogLevel(d.value);
|
||||
}}
|
||||
>
|
||||
{LOG_LEVELS.map((l) => (
|
||||
<option key={l} value={l}>
|
||||
{l}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</Field>
|
||||
<Field label="Log Target">
|
||||
<Input
|
||||
value={effectiveLogTarget}
|
||||
placeholder="STDOUT / /var/log/fail2ban.log"
|
||||
onChange={(_e, d) => {
|
||||
setLogTarget(d.value);
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
<div className={styles.fieldRow}>
|
||||
<Field
|
||||
label="DB Purge Age (s)"
|
||||
hint="Ban records older than this are removed from the fail2ban database."
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
value={effectiveDbPurgeAge}
|
||||
onChange={(_e, d) => {
|
||||
setDbPurgeAge(d.value);
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
<Field
|
||||
label="DB Max Matches"
|
||||
hint="Maximum number of log-line matches stored per ban record."
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
value={effectiveDbMaxMatches}
|
||||
onChange={(_e, d) => {
|
||||
setDbMaxMatches(d.value);
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -154,7 +154,10 @@ export function ServerTab(): React.JSX.Element {
|
||||
</Field>
|
||||
</div>
|
||||
<div className={styles.fieldRow}>
|
||||
<Field label="DB Purge Age (s)">
|
||||
<Field
|
||||
label="DB Purge Age (s)"
|
||||
hint="Ban records older than this are removed from the fail2ban database."
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
value={effectiveDbPurgeAge}
|
||||
@@ -163,7 +166,10 @@ export function ServerTab(): React.JSX.Element {
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
<Field label="DB Max Matches">
|
||||
<Field
|
||||
label="DB Max Matches"
|
||||
hint="Maximum number of log-line matches stored per ban record."
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
value={effectiveDbMaxMatches}
|
||||
|
||||
@@ -30,7 +30,6 @@ export { ExportTab } from "./ExportTab";
|
||||
export { FilterForm } from "./FilterForm";
|
||||
export type { FilterFormProps } from "./FilterForm";
|
||||
export { FiltersTab } from "./FiltersTab";
|
||||
export { GlobalTab } from "./GlobalTab";
|
||||
export { JailFilesTab } from "./JailFilesTab";
|
||||
export { JailFileForm } from "./JailFileForm";
|
||||
export { JailsTab } from "./JailsTab";
|
||||
|
||||
Reference in New Issue
Block a user