'use client' import { useEffect, useState, useCallback } from 'react' import type { ToolStatus, Finding, SeveritySummary, MonitoringMetric, ActiveAlert, ScanType, TabId, } from './types' import { SCAN_TYPE_LABELS } from './types' const DEFAULT_METRICS: MonitoringMetric[] = [ { name: 'API Latency', value: 45, unit: 'ms', status: 'ok', trend: 'stable' }, { name: 'Auth Failures', value: 3, unit: '/h', status: 'ok', trend: 'down' }, { name: 'Rate Limit Hits', value: 12, unit: '/h', status: 'warning', trend: 'up' }, { name: 'Failed Logins', value: 0, unit: '/24h', status: 'ok', trend: 'stable' }, { name: 'SSL Expiry', value: 45, unit: 'days', status: 'ok', trend: 'down' }, { name: 'Open Ports', value: 8, unit: '', status: 'ok', trend: 'stable' }, ] export function useSecurityDashboard() { const [tools, setTools] = useState([]) const [findings, setFindings] = useState([]) const [summary, setSummary] = useState({ critical: 0, high: 0, medium: 0, low: 0, info: 0, total: 0 }) const [history, setHistory] = useState([]) const [loading, setLoading] = useState(true) const [scanning, setScanning] = useState(null) const [error, setError] = useState(null) const [activeTab, setActiveTab] = useState('overview') const [monitoringMetrics, setMonitoringMetrics] = useState([]) const [activeAlerts, setActiveAlerts] = useState([]) const [severityFilter, setSeverityFilter] = useState(null) const [toolFilter, setToolFilter] = useState(null) const [showFullDocs, setShowFullDocs] = useState(false) const [scanMessage, setScanMessage] = useState(null) const [lastScanTime, setLastScanTime] = useState(null) const fetchData = useCallback(async (showLoadingSpinner = false) => { if (showLoadingSpinner) { setLoading(true) } setError(null) try { const [toolsRes, findingsRes, summaryRes, historyRes] = await Promise.all([ fetch('/api/v1/security/tools'), fetch('/api/v1/security/findings'), fetch('/api/v1/security/summary'), fetch('/api/v1/security/history'), ]) if (toolsRes.ok) setTools(await toolsRes.json()) if (findingsRes.ok) setFindings(await findingsRes.json()) if (summaryRes.ok) setSummary(await summaryRes.json()) if (historyRes.ok) setHistory(await historyRes.json()) const [metricsRes, alertsRes] = await Promise.all([ fetch('/api/v1/security/monitoring/metrics'), fetch('/api/v1/security/monitoring/alerts'), ]) if (metricsRes.ok) { setMonitoringMetrics(await metricsRes.json()) } else { setMonitoringMetrics(DEFAULT_METRICS) } if (alertsRes.ok) { setActiveAlerts(await alertsRes.json()) } else { setActiveAlerts([]) } } catch (err) { setError(err instanceof Error ? err.message : 'Verbindung zum Backend fehlgeschlagen') } finally { setLoading(false) } }, []) // Initial load useEffect(() => { fetchData(true) // eslint-disable-next-line react-hooks/exhaustive-deps }, []) // Auto-refresh every 60 seconds useEffect(() => { const interval = setInterval(() => fetchData(false), 60000) return () => clearInterval(interval) // eslint-disable-next-line react-hooks/exhaustive-deps }, []) const runScan = async (scanType: ScanType) => { console.log(`Starting scan: ${scanType}`) setScanning(scanType) setError(null) setScanMessage(`${SCAN_TYPE_LABELS[scanType]} wird gestartet...`) try { const response = await fetch(`/api/v1/security/scan/${scanType}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, }) console.log(`Scan response status: ${response.status}`) if (!response.ok) { const errorText = await response.text() console.error(`Scan error: ${errorText}`) throw new Error(`Scan fehlgeschlagen: ${response.status} - ${errorText}`) } const result = await response.json() console.log('Scan result:', result) setScanMessage(`${SCAN_TYPE_LABELS[scanType]} laeuft im Hintergrund. Ergebnisse werden in wenigen Sekunden aktualisiert.`) setLastScanTime(new Date().toLocaleTimeString('de-DE')) setTimeout(() => { fetchData(false); setScanMessage(null) }, 5000) setTimeout(() => fetchData(false), 15000) setTimeout(() => fetchData(false), 30000) } catch (err) { console.error('Scan error:', err) setError(err instanceof Error ? err.message : 'Scan fehlgeschlagen - Pruefe Browser-Konsole') setScanMessage(null) } finally { setScanning(null) } } const filteredFindings = findings.filter(f => { if (severityFilter && f.severity.toUpperCase() !== severityFilter.toUpperCase()) return false if (toolFilter && f.tool.toLowerCase() !== toolFilter.toLowerCase()) return false return true }) const overallStatus = getOverallStatus(summary) return { tools, findings, filteredFindings, summary, history, loading, scanning, error, activeTab, setActiveTab, monitoringMetrics, activeAlerts, severityFilter, setSeverityFilter, toolFilter, setToolFilter, showFullDocs, setShowFullDocs, scanMessage, lastScanTime, overallStatus, runScan, } } // --- Helper functions --- function getOverallStatus(summary: SeveritySummary) { if (summary.critical > 0) return { label: 'Critical Issues', color: 'bg-red-100 text-red-800' } if (summary.high > 0) return { label: 'High Issues', color: 'bg-orange-100 text-orange-800' } if (summary.medium > 0) return { label: 'Warnings', color: 'bg-yellow-100 text-yellow-800' } return { label: 'Secure', color: 'bg-green-100 text-green-800' } } export function getSeverityBadge(severity: string) { const base = 'px-3 py-1 rounded-full text-xs font-semibold uppercase' switch (severity.toUpperCase()) { case 'CRITICAL': return `${base} bg-red-100 text-red-800` case 'HIGH': return `${base} bg-orange-100 text-orange-800` case 'MEDIUM': return `${base} bg-yellow-100 text-yellow-800` case 'LOW': return `${base} bg-green-100 text-green-800` default: return `${base} bg-blue-100 text-blue-800` } } export function getStatusBadge(installed: boolean) { return installed ? 'px-2 py-1 rounded text-xs font-semibold bg-green-100 text-green-800' : 'px-2 py-1 rounded text-xs font-semibold bg-red-100 text-red-800' } export function getHistoryStatusColor(status: string) { switch (status) { case 'success': return 'bg-green-500' case 'warning': return 'bg-yellow-500' case 'error': return 'bg-red-500' default: return 'bg-slate-400' } }