/** * ============================================================================= * GHAYMAH SIEM DASHBOARD — Frontend Application * ============================================================================= * Connects to the Python SIEM engine API, fetches alerts and malicious IPs, * and renders them in real-time on the dashboard. * ============================================================================= */ (function () { 'use strict'; // ── Configuration ── const CONFIG = { API_BASE: window.location.origin, REFRESH_INTERVAL: 5000, // ms MAX_VISIBLE_ALERTS: 200, }; // ── State ── let allAlerts = []; let allIPs = []; let stats = {}; let currentFilters = { severity: 'all', source: 'all' }; // ── DOM References ── const DOM = { // Stats countCritical: document.getElementById('count-critical'), countHigh: document.getElementById('count-high'), countMedium: document.getElementById('count-medium'), countLow: document.getElementById('count-low'), countTotal: document.getElementById('count-total'), countIPs: document.getElementById('count-ips'), // Lists alertsList: document.getElementById('alerts-list'), ipsList: document.getElementById('ips-list'), ipCountBadge: document.getElementById('ip-count-badge'), // Filters filterSeverity: document.getElementById('filter-severity'), filterSource: document.getElementById('filter-source'), // Modal modalOverlay: document.getElementById('modal-overlay'), modalTitle: document.getElementById('modal-title'), modalBody: document.getElementById('modal-body'), modalClose: document.getElementById('modal-close'), // Status lastUpdate: document.getElementById('last-update'), }; // ── API Fetchers ── async function fetchAlerts() { try { const res = await fetch(`${CONFIG.API_BASE}/api/alerts`); if (res.ok) { allAlerts = await res.json(); renderAlerts(); } } catch (err) { console.warn('[SIEM] Failed to fetch alerts:', err.message); } } async function fetchIPs() { try { const res = await fetch(`${CONFIG.API_BASE}/api/ips`); if (res.ok) { allIPs = await res.json(); renderIPs(); } } catch (err) { console.warn('[SIEM] Failed to fetch IPs:', err.message); } } async function fetchStats() { try { const res = await fetch(`${CONFIG.API_BASE}/api/stats`); if (res.ok) { stats = await res.json(); renderStats(); } } catch (err) { console.warn('[SIEM] Failed to fetch stats:', err.message); } } // ── Renderers ── function renderStats() { const sev = stats.by_severity || {}; animateCounter(DOM.countCritical, sev.CRITICAL || 0); animateCounter(DOM.countHigh, sev.HIGH || 0); animateCounter(DOM.countMedium, sev.MEDIUM || 0); animateCounter(DOM.countLow, (sev.LOW || 0) + (sev.INFO || 0)); animateCounter(DOM.countTotal, stats.total_alerts || 0); animateCounter(DOM.countIPs, (stats.malicious_ips || 0) + (stats.suspicious_ips || 0)); DOM.lastUpdate.textContent = `Updated: ${new Date().toLocaleTimeString()}`; } function animateCounter(el, target) { const current = parseInt(el.textContent) || 0; if (current === target) return; const diff = target - current; const steps = Math.min(Math.abs(diff), 20); const increment = diff / steps; let step = 0; const timer = setInterval(() => { step++; if (step >= steps) { el.textContent = target; clearInterval(timer); } else { el.textContent = Math.round(current + increment * step); } }, 30); } function renderAlerts() { const filtered = allAlerts.filter(alert => { if (currentFilters.severity !== 'all' && alert.severity !== currentFilters.severity) return false; if (currentFilters.source !== 'all' && alert.source !== currentFilters.source) return false; return true; }).slice(0, CONFIG.MAX_VISIBLE_ALERTS); if (filtered.length === 0) { DOM.alertsList.innerHTML = `
🛡️ No alerts matching current filters.
✅ No malicious IPs detected.