secubox-openwrt/package/secubox/luci-app-secubox-crowdsec/htdocs/luci-static/resources/view/secubox-crowdsec/dashboard.js
CyberMind-FR e6835828af feat(local-build): Add sync command and clean local-feed
- Add sync command to synchronize packages from package/secubox to local-feed
- Add local-feed deletion to clean-all command
- Add missing packages to package/secubox:
  - luci-app-secubox-crowdsec
  - secubox-crowdsec-setup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:50:53 +01:00

163 lines
5.5 KiB
JavaScript

'use strict';
'require view';
'require dom';
'require poll';
'require ui';
'require secubox-crowdsec/api as api';
return view.extend({
api: null,
load: function() {
this.api = new api();
return Promise.all([
this.api.getStatus(),
this.api.getStats(),
this.api.getNftablesStats()
]);
},
renderStatusBadge: function(status, running, stopped) {
var color = (status === running) ? 'green' : 'red';
var text = (status === running) ? 'Running' : 'Stopped';
return E('span', {
'class': 'badge',
'style': 'background-color: ' + color + '; color: white; padding: 2px 8px; border-radius: 3px;'
}, text);
},
renderServiceCard: function(name, status) {
return E('div', { 'class': 'cbi-section', 'style': 'display: inline-block; width: 200px; margin: 10px; text-align: center; padding: 15px; border: 1px solid #ddd; border-radius: 5px;' }, [
E('h4', { 'style': 'margin: 0 0 10px 0;' }, name),
this.renderStatusBadge(status, 'running', 'stopped')
]);
},
renderStatCard: function(label, value, icon) {
return E('div', { 'class': 'cbi-section', 'style': 'display: inline-block; width: 150px; margin: 10px; text-align: center; padding: 15px; border: 1px solid #ddd; border-radius: 5px;' }, [
E('div', { 'style': 'font-size: 24px; font-weight: bold; color: #0066cc;' }, String(value || 0)),
E('div', { 'style': 'color: #666; font-size: 12px;' }, label)
]);
},
render: function(data) {
var status = data[0] || {};
var stats = data[1] || {};
var nftStats = data[2] || {};
var self = this;
var view = E('div', { 'class': 'cbi-map' }, [
E('h2', { 'class': 'cbi-map-title' }, 'CrowdSec Dashboard'),
E('div', { 'class': 'cbi-map-descr' }, 'Security engine status and statistics'),
// Services Status
E('div', { 'class': 'cbi-section' }, [
E('h3', { 'class': 'cbi-section-title' }, 'Services Status'),
E('div', { 'id': 'service-status', 'style': 'text-align: center;' }, [
this.renderServiceCard('CrowdSec', status.crowdsec),
this.renderServiceCard('Bouncer', status.bouncer),
this.renderServiceCard('Syslog-ng', status.syslog)
])
]),
// API Status
E('div', { 'class': 'cbi-section' }, [
E('h3', { 'class': 'cbi-section-title' }, 'API Status'),
E('table', { 'class': 'table cbi-section-table' }, [
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, 'CrowdSec Version'),
E('td', { 'class': 'td' }, status.version || 'Unknown')
]),
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, 'Local API (LAPI)'),
E('td', { 'class': 'td' }, this.renderStatusBadge(status.lapi_status, 'available', 'unavailable'))
]),
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, 'Central API (CAPI)'),
E('td', { 'class': 'td' }, this.renderStatusBadge(status.capi_status, 'connected', 'disconnected'))
])
])
]),
// Statistics
E('div', { 'class': 'cbi-section' }, [
E('h3', { 'class': 'cbi-section-title' }, 'Statistics'),
E('div', { 'id': 'stats-cards', 'style': 'text-align: center;' }, [
this.renderStatCard('Active Decisions', stats.total_decisions),
this.renderStatCard('Alerts (24h)', stats.alerts_24h),
this.renderStatCard('Bouncers', stats.bouncers),
this.renderStatCard('Parsers', stats.parsers),
this.renderStatCard('Scenarios', stats.scenarios)
])
]),
// NFTables Status
E('div', { 'class': 'cbi-section' }, [
E('h3', { 'class': 'cbi-section-title' }, 'Firewall (nftables)'),
E('table', { 'class': 'table cbi-section-table' }, [
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, 'IPv4 Table'),
E('td', { 'class': 'td' }, nftStats.ipv4_table ? 'Active' : 'Inactive')
]),
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, 'IPv6 Table'),
E('td', { 'class': 'td' }, nftStats.ipv6_table ? 'Active' : 'Inactive')
]),
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, 'Blocked IPv4'),
E('td', { 'class': 'td' }, String(nftStats.blocked_ipv4 || 0))
]),
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, 'Blocked IPv6'),
E('td', { 'class': 'td' }, String(nftStats.blocked_ipv6 || 0))
])
])
]),
// Service Controls
E('div', { 'class': 'cbi-section' }, [
E('h3', { 'class': 'cbi-section-title' }, 'Service Controls'),
E('div', { 'style': 'text-align: center;' }, [
E('button', {
'class': 'btn cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
return this.api.controlService('crowdsec', 'restart').then(function() {
ui.addNotification(null, E('p', 'CrowdSec restarted'), 'info');
window.location.reload();
});
})
}, 'Restart CrowdSec'),
' ',
E('button', {
'class': 'btn cbi-button cbi-button-apply',
'click': ui.createHandlerFn(this, function() {
return this.api.controlService('crowdsec-firewall-bouncer', 'restart').then(function() {
ui.addNotification(null, E('p', 'Bouncer restarted'), 'info');
window.location.reload();
});
})
}, 'Restart Bouncer'),
' ',
E('button', {
'class': 'btn cbi-button cbi-button-action',
'click': ui.createHandlerFn(this, function() {
return this.api.updateHub().then(function(res) {
if (res.success)
ui.addNotification(null, E('p', res.message), 'info');
else
ui.addNotification(null, E('p', res.error), 'warning');
});
})
}, 'Update Hub')
])
])
]);
return view;
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});