espilon-source/tools/C3PO/hp_dashboard/static/hp/js/api.js
Eun0us 79c2a4d4bf c3po: full server rewrite with modular routes and honeypot dashboard
Replace monolithic CLI and web server with route-based Flask API.
New routes: api_commands, api_build, api_can, api_monitor, api_ota,
api_tunnel. Add honeypot security dashboard with real-time SSE,
MITRE ATT&CK mapping, kill chain analysis.

New TUI with commander/help modules. Add session management,
tunnel proxy core, CAN bus data store. Docker support.
2026-02-28 20:12:27 +01:00

88 lines
2.9 KiB
JavaScript

/* 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();
}