From 801fa26da7b3736da6e1384152912cc9e5c08c2b Mon Sep 17 00:00:00 2001 From: Debian Date: Wed, 3 Jun 2026 11:20:52 +0200 Subject: [PATCH] =?UTF-8?q?feat(waf):=20Regel=20direkt=20aus=20Alert=20als?= =?UTF-8?q?=20Ausnahme=20hinzuf=C3=BCgen=20=E2=80=94=20v1.2.78?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Jede Alert-Zeile hat jetzt einen "Als Ausnahme"-Button. Klick: 1. Lädt aktuelle WAF-Config der betroffenen Domain 2. Fügt die Rule-ID zu rule_exclusions hinzu (dedupliziert) 3. Speichert via PUT /waf/configs/:domain_id → triggert HAProxy-Reload 4. Erfolgsmeldung + WAF-Config-Query invalidiert Button disabled wenn domain_id fehlt (Domain nicht aufgelöst) oder Viewer-Rolle. Co-Authored-By: Claude Sonnet 4.6 --- VERSION | 2 +- management-ui/src/i18n/locales/de/common.json | 6 ++- management-ui/src/i18n/locales/en/common.json | 6 ++- management-ui/src/pages/WAF/index.tsx | 45 +++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 3f7543c..1152f77 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.77 +1.2.78 diff --git a/management-ui/src/i18n/locales/de/common.json b/management-ui/src/i18n/locales/de/common.json index 1576cee..54275b7 100644 --- a/management-ui/src/i18n/locales/de/common.json +++ b/management-ui/src/i18n/locales/de/common.json @@ -1823,7 +1823,11 @@ "ruleId": "Regel-ID", "severity": "Schwere", "msg": "Meldung" - } + }, + "addException": "Als Ausnahme", + "exceptionAdded": "Regel als Ausnahme für diese Domain hinzugefügt.", + "exceptionFailed": "Ausnahme konnte nicht gespeichert werden.", + "noDomain": "Domain nicht gefunden — Ausnahme manuell konfigurieren." } } } \ No newline at end of file diff --git a/management-ui/src/i18n/locales/en/common.json b/management-ui/src/i18n/locales/en/common.json index 533e44f..ad80897 100644 --- a/management-ui/src/i18n/locales/en/common.json +++ b/management-ui/src/i18n/locales/en/common.json @@ -1823,7 +1823,11 @@ "ruleId": "Rule ID", "severity": "Severity", "msg": "Message" - } + }, + "addException": "Add exception", + "exceptionAdded": "Rule added as exception for this domain.", + "exceptionFailed": "Failed to add exception.", + "noDomain": "Domain not found — configure exception manually." } } } \ No newline at end of file diff --git a/management-ui/src/pages/WAF/index.tsx b/management-ui/src/pages/WAF/index.tsx index 90f0c78..8820ae6 100644 --- a/management-ui/src/pages/WAF/index.tsx +++ b/management-ui/src/pages/WAF/index.tsx @@ -272,6 +272,25 @@ function AlertsTab({ domainId }: { domainId?: number }) { }, }) + const addException = useMutation({ + mutationFn: async ({ domainId, ruleId }: { domainId: number; ruleId: number }) => { + // Fetch current config (returns default if none exists yet) + const r = await apiClient.get(`/waf/configs/${domainId}`) + const cfg: WafConfig = isEnvelope(r.data) + ? (r.data.data as { config: WafConfig }).config + : defaultConfig(domainId) + const exclusions = [...(cfg.rule_exclusions ?? [])] + const ruleStr = String(ruleId) + if (!exclusions.includes(ruleStr)) exclusions.push(ruleStr) + return apiClient.put(`/waf/configs/${domainId}`, { ...cfg, rule_exclusions: exclusions }) + }, + onSuccess: () => { + message.success(t('waf.alerts.exceptionAdded')) + void qc.invalidateQueries({ queryKey: ['waf'] }) + }, + onError: () => message.error(t('waf.alerts.exceptionFailed')), + }) + const severityColor = (s: string) => { switch (s?.toLowerCase()) { case 'critical': return 'red' @@ -316,6 +335,32 @@ function AlertsTab({ domainId }: { domainId?: number }) { render: (v: string) => {v || '—'} }, { title: t('waf.alerts.col.msg'), dataIndex: 'rule_msg', key: 'rule_msg', ellipsis: true, render: (v: string) => {v || '—'} }, + { + title: '', + key: 'exception', + width: 130, + render: (_: unknown, row: WafAlert) => { + const canExclude = !!row.domain_id && row.rule_id > 0 && !isViewer + const isPending = addException.isPending && + addException.variables?.domainId === row.domain_id && + addException.variables?.ruleId === row.rule_id + return ( + + + + ) + }, + }, ] return (