diff --git a/VERSION b/VERSION index bee17c9..22122db 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.13 \ No newline at end of file +1.3.14 \ No newline at end of file diff --git a/management-ui/src/i18n/locales/de/common.json b/management-ui/src/i18n/locales/de/common.json index e2317a1..3f25d77 100644 --- a/management-ui/src/i18n/locales/de/common.json +++ b/management-ui/src/i18n/locales/de/common.json @@ -1947,7 +1947,11 @@ "saveFailed": "WAF-Konfiguration konnte nicht gespeichert werden.", "noExclusions": "Noch keine Regelausnahmen.", "noNote": "Keine Notiz", - "exclusionsAddHint": "Ausnahmen über den Alarme-Tab hinzufügen — \"Als Ausnahme\" auf einem Alarm klicken." + "exclusionsAddHint": "Regel oben suchen und hinzufügen — oder im Alarme-Tab per \"Als Ausnahme\" auf einem Alarm.", + "exclusionAddPlaceholder": "Regel suchen (ID oder Beschreibung)…", + "exclusionAddNote": "Notiz (optional)", + "exclusionAddNotFound": "Keine Regel gefunden", + "exclusionAddBtn": "Hinzufügen" }, "tabs": { "domains": "Domains", diff --git a/management-ui/src/i18n/locales/en/common.json b/management-ui/src/i18n/locales/en/common.json index b89f025..03f18df 100644 --- a/management-ui/src/i18n/locales/en/common.json +++ b/management-ui/src/i18n/locales/en/common.json @@ -1947,7 +1947,11 @@ "saveFailed": "Failed to save WAF configuration.", "noExclusions": "No rule exclusions yet.", "noNote": "No note", - "exclusionsAddHint": "Add exceptions via the Alerts tab — click \"Add exception\" on an alert." + "exclusionsAddHint": "Search for a rule above and add it — or via the Alerts tab with \"Add exception\" on an alert.", + "exclusionAddPlaceholder": "Search rule (ID or description)…", + "exclusionAddNote": "Note (optional)", + "exclusionAddNotFound": "No rule found", + "exclusionAddBtn": "Add" }, "tabs": { "domains": "Domains", diff --git a/management-ui/src/pages/WAF/index.tsx b/management-ui/src/pages/WAF/index.tsx index 5689aa7..5d33db3 100644 --- a/management-ui/src/pages/WAF/index.tsx +++ b/management-ui/src/pages/WAF/index.tsx @@ -1,10 +1,10 @@ -import { useState } from 'react' +import { useMemo, useState } from 'react' import { Alert, Button, Card, Col, Drawer, Form, Input, Modal, Popconfirm, Row, Select, Space, Switch, Tabs, Tag, Tooltip, Typography, message, } from 'antd' import { - CheckCircleOutlined, CloseCircleOutlined, DeleteOutlined, + CheckCircleOutlined, CloseCircleOutlined, DeleteOutlined, PlusOutlined, SafetyCertificateOutlined, SettingOutlined, WarningOutlined, } from '@ant-design/icons' import { useTranslation } from 'react-i18next' @@ -14,7 +14,7 @@ import apiClient, { isEnvelope } from '../../api/client' import PageHeader from '../../components/PageHeader' import DataTable from '../../components/DataTable' import { useAuthStore } from '../../stores/auth' -import { getRuleDescription } from './crsRules' +import { CRS_RULES, getRuleDescription } from './crsRules' const { Text } = Typography @@ -102,6 +102,14 @@ function ConfigDrawer({ domainName, domainId, onClose }: ConfigDrawerProps) { const qc = useQueryClient() const isViewer = useAuthStore((s) => s.user?.role) === 'viewer' const [form] = Form.useForm() + const [addRuleId, setAddRuleId] = useState('') + const [addNote, setAddNote] = useState('') + // Durchsuchbare Optionen aus der CRS-Regel-Liste (ID — Beschreibung). + // filterOption unten matcht sowohl ID als auch Beschreibung. + const ruleOptions = useMemo( + () => Object.entries(CRS_RULES).map(([id, desc]) => ({ value: id, label: `${id} — ${desc}` })), + [], + ) const { data: cfg, isLoading } = useQuery({ queryKey: ['waf', 'config', domainId], @@ -261,9 +269,58 @@ function ConfigDrawer({ domainName, domainId, onClose }: ConfigDrawerProps) { ))} )} -
- {t('waf.config.exclusionsAddHint')} -
+ {!isViewer && ( +
+
+ setAddNote(e.target.value)} + style={{ width: 150 }} + /> + +
+ + {t('waf.config.exclusionsAddHint')} + +
+ )}