/* ESPILON Honeypot Dashboard — API Client */ import { S } from './state.js'; // showToast will be set by ui.js to break circular dependency let _showToast = (title, msg, detail, type) => console.warn('[HP]', title, msg); export function setToastHandler(fn) { _showToast = fn; } // Default render callback — set by app.js so fetchAll() always re-renders let _defaultRender = null; export function setDefaultRender(fn) { _defaultRender = fn; } export async function api(url) { try { const r = await fetch(url); if (!r.ok) throw new Error(r.status + ' ' + r.statusText); return await r.json(); } catch (e) { console.warn('[HP API]', url, e.message); _showToast('API Error', url + ': ' + e.message, '', 'error'); return null; } } let _csrfToken = null; async function _getCsrf() { if (_csrfToken) return _csrfToken; try { const r = await fetch('/api/honeypot/csrf-token'); if (r.ok) { const j = await r.json(); _csrfToken = j.token; } } catch (_) { /* ignore */ } return _csrfToken || ''; } export async function postApi(url, body) { try { const csrf = await _getCsrf(); const r = await fetch(url, { method: 'POST', headers: {'Content-Type': 'application/json', 'X-CSRF-Token': csrf}, body: JSON.stringify(body || {}) }); if (r.status === 403) { _csrfToken = null; } // token expired, refresh next time if (!r.ok) throw new Error(r.status + ' ' + r.statusText); return await r.json(); } catch (e) { console.warn('[HP API]', url, e.message); _showToast('API Error', url + ': ' + e.message, '', 'error'); return null; } } export async function fetchAll(renderAll) { const devParam = S.selectedDevice ? '?device_id=' + S.selectedDevice : ''; const [stats, events, attackers, timeline, devices, services, history, alerts] = await Promise.all([ api('/api/honeypot/stats'), api('/api/honeypot/events?limit=200'), api('/api/honeypot/attackers?limit=50'), api('/api/honeypot/timeline?hours=24&bucket=5'), api('/api/honeypot/devices'), api('/api/honeypot/services' + devParam), api('/api/honeypot/history?limit=50'), api('/api/honeypot/alerts/active') ]); if (stats) S.stats = stats; if (events) S.events = events.events || []; if (attackers) S.attackers = attackers.attackers || []; if (timeline) S.timeline = timeline.timeline || []; if (devices) S.devices = devices.devices || []; if (services) { S.services = services.services || {}; S.definitions = services.definitions || {}; } if (history) S.history = history.history || []; if (alerts) S.alerts = alerts.alerts || []; S.lastId = S.stats.last_id || 0; // Reset cached tabs S.sessions = null; S.credentials = null; S.killchain = null; const cb = renderAll || _defaultRender; if (cb) cb(); }