'use client' import { useState, useEffect } from 'react' interface PIIRule { id: string name: string rule_type: string pattern: string severity: string is_active: boolean created_at: string updated_at: string } interface PIIMatch { rule_id: string rule_name: string rule_type: string severity: string match: string start_index: number end_index: number } interface PIITestResult { has_pii: boolean matches: PIIMatch[] should_block: boolean block_level: string } interface PIIRulesTabProps { apiBase: string onUpdate?: () => void } const RULE_TYPES = [ { value: 'regex', label: 'Regex (Muster)' }, { value: 'keyword', label: 'Keyword (Stichwort)' }, ] const SEVERITIES = [ { value: 'warn', label: 'Warnung', color: 'bg-amber-100 text-amber-700' }, { value: 'redact', label: 'Schwärzen', color: 'bg-orange-100 text-orange-700' }, { value: 'block', label: 'Blockieren', color: 'bg-red-100 text-red-700' }, ] export function PIIRulesTab({ apiBase, onUpdate }: PIIRulesTabProps) { const [rules, setRules] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) // Test panel const [testText, setTestText] = useState('') const [testResult, setTestResult] = useState(null) const [testing, setTesting] = useState(false) // Edit modal const [editingRule, setEditingRule] = useState(null) const [isNewRule, setIsNewRule] = useState(false) const [saving, setSaving] = useState(false) // New rule form const [newRule, setNewRule] = useState({ name: '', rule_type: 'regex', pattern: '', severity: 'block', is_active: true, }) useEffect(() => { fetchRules() }, []) const fetchRules = async () => { try { setLoading(true) const res = await fetch(`${apiBase}/v1/admin/pii-rules`) if (!res.ok) throw new Error('Fehler beim Laden') const data = await res.json() setRules(data.rules || []) } catch (err) { setError(err instanceof Error ? err.message : 'Unbekannter Fehler') } finally { setLoading(false) } } const createRule = async () => { try { setSaving(true) const res = await fetch(`${apiBase}/v1/admin/pii-rules`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newRule), }) if (!res.ok) throw new Error('Fehler beim Erstellen') setNewRule({ name: '', rule_type: 'regex', pattern: '', severity: 'block', is_active: true, }) setIsNewRule(false) fetchRules() onUpdate?.() } catch (err) { setError(err instanceof Error ? err.message : 'Unbekannter Fehler') } finally { setSaving(false) } } const updateRule = async () => { if (!editingRule) return try { setSaving(true) const res = await fetch(`${apiBase}/v1/admin/pii-rules/${editingRule.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(editingRule), }) if (!res.ok) throw new Error('Fehler beim Aktualisieren') setEditingRule(null) fetchRules() onUpdate?.() } catch (err) { setError(err instanceof Error ? err.message : 'Unbekannter Fehler') } finally { setSaving(false) } } const deleteRule = async (id: string) => { if (!confirm('Regel wirklich loeschen? Diese Aktion wird im Audit-Log protokolliert.')) return try { const res = await fetch(`${apiBase}/v1/admin/pii-rules/${id}`, { method: 'DELETE', }) if (!res.ok) throw new Error('Fehler beim Loeschen') fetchRules() onUpdate?.() } catch (err) { setError(err instanceof Error ? err.message : 'Unbekannter Fehler') } } const toggleRuleStatus = async (rule: PIIRule) => { try { const res = await fetch(`${apiBase}/v1/admin/pii-rules/${rule.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ is_active: !rule.is_active }), }) if (!res.ok) throw new Error('Fehler beim Aendern des Status') fetchRules() onUpdate?.() } catch (err) { setError(err instanceof Error ? err.message : 'Unbekannter Fehler') } } const runTest = async () => { if (!testText) return try { setTesting(true) const res = await fetch(`${apiBase}/v1/admin/pii-rules/test`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: testText }), }) if (!res.ok) throw new Error('Fehler beim Testen') const data = await res.json() setTestResult(data) } catch (err) { setError(err instanceof Error ? err.message : 'Unbekannter Fehler') } finally { setTesting(false) } } const getSeverityBadge = (severity: string) => { const config = SEVERITIES.find((s) => s.value === severity) return ( {config?.label || severity} ) } return (
{/* Error Display */} {error && (
{error}
)} {/* Test Panel */}

PII-Test

Testen Sie, ob ein Text personenbezogene Daten (PII) enthaelt.