secubox-openwrt/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/waf.js
CyberMind-FR ed52af6ab9 feat(theming): Add custom navigation tabs to Client Guardian and CrowdSec dashboards
- Create nav.js for Client Guardian with SecuBox themed tabs
- Create nav.js for CrowdSec dashboard with themed navigation
- Update all Client Guardian views to use CgNav.renderTabs()
- Update all CrowdSec views to use CsNav.renderTabs()
- Update Client Guardian menu.json paths from /client-guardian/ to /guardian/
- Hide default LuCI tabs via CSS injection for both dashboards

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 13:44:11 +01:00

177 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
'require view';
'require secubox-theme/theme as Theme';
'require dom';
'require poll';
'require ui';
'require crowdsec-dashboard/api as api';
'require crowdsec-dashboard/nav as CsNav';
/**
* CrowdSec Dashboard - WAF/AppSec View
* Web Application Firewall status and configuration
* Copyright (C) 2024 CyberMind.fr - Gandalf
*/
return view.extend({
title: _('WAF/AppSec'),
csApi: null,
wafStatus: {},
load: function() {
var cssLink = document.createElement('link');
cssLink.rel = 'stylesheet';
cssLink.href = L.resource('crowdsec-dashboard/dashboard.css');
document.head.appendChild(cssLink);
this.csApi = api;
return this.csApi.getWAFStatus().then(function(result) {
return {
wafStatus: result || {}
};
});
},
renderWAFStatus: function() {
var self = this;
var enabled = this.wafStatus.waf_enabled === true || this.wafStatus.waf_enabled === 1;
var message = this.wafStatus.message || '';
if (!enabled) {
return E('div', { 'class': 'cs-card' }, [
E('div', { 'class': 'cs-card-header' }, [
E('div', { 'class': 'cs-card-icon' }, '🛡️'),
E('h3', {}, _('WAF Status'))
]),
E('div', { 'class': 'cs-card-body' }, [
E('div', { 'class': 'cs-empty' }, [
E('div', { 'class': 'cs-empty-icon' }, '⚠️'),
E('p', { 'style': 'margin: 16px 0; color: var(--cs-text-secondary);' }, message || _('WAF/AppSec not configured')),
E('p', { 'style': 'font-size: 13px; color: var(--cs-text-muted);' },
_('The Web Application Firewall (WAF) feature requires CrowdSec 1.7.0 or higher. Configure AppSec rules to enable request filtering and blocking.'))
])
])
]);
}
return E('div', { 'class': 'cs-card' }, [
E('div', { 'class': 'cs-card-header' }, [
E('div', { 'class': 'cs-card-icon' }, '🛡'),
E('h3', {}, _('WAF Status')),
E('span', {
'class': 'cs-action ban',
'style': 'margin-left: auto; background: rgba(0,212,170,0.15); color: var(--cs-accent-green); padding: 6px 12px; border-radius: 6px; font-weight: 600;'
}, _('Enabled'))
]),
E('div', { 'class': 'cs-card-body' }, [
this.renderWAFInfo()
])
]);
},
renderWAFInfo: function() {
var info = [];
if (this.wafStatus.rules_count !== undefined) {
info.push(
E('div', { 'class': 'cs-metric-item' }, [
E('span', { 'class': 'cs-metric-name' }, _('Active Rules')),
E('span', { 'class': 'cs-metric-value' }, String(this.wafStatus.rules_count))
])
);
}
if (this.wafStatus.blocked_requests !== undefined) {
info.push(
E('div', { 'class': 'cs-metric-item' }, [
E('span', { 'class': 'cs-metric-name' }, _('Blocked Requests')),
E('span', { 'class': 'cs-metric-value' }, String(this.wafStatus.blocked_requests))
])
);
}
if (this.wafStatus.engine_version) {
info.push(
E('div', { 'class': 'cs-metric-item' }, [
E('span', { 'class': 'cs-metric-name' }, _('Engine Version')),
E('span', { 'class': 'cs-metric-value' }, String(this.wafStatus.engine_version))
])
);
}
if (info.length === 0) {
return E('p', { 'style': 'color: var(--cs-text-secondary); margin: 8px 0;' },
_('WAF is enabled but no detailed metrics available.'));
}
return E('div', { 'class': 'cs-metric-list' }, info);
},
renderConfigHelp: function() {
return E('div', { 'class': 'cs-card' }, [
E('div', { 'class': 'cs-card-header' }, [
E('div', { 'class': 'cs-card-icon' }, '📖'),
E('h3', {}, _('Configuration Guide'))
]),
E('div', { 'class': 'cs-card-body' }, [
E('div', { 'class': 'cs-info-box' }, [
E('h4', { 'style': 'margin: 0 0 8px 0; color: var(--cs-text-primary);' }, _('Enabling WAF/AppSec')),
E('p', { 'style': 'margin: 0 0 12px 0; color: var(--cs-text-secondary); font-size: 14px;' },
_('To enable the Web Application Firewall, you need to:')),
E('ol', { 'style': 'margin: 0; padding-left: 20px; color: var(--cs-text-secondary); font-size: 14px;' }, [
E('li', {}, [
_('Install AppSec collections: '),
E('code', {}, 'cscli collections install crowdsecurity/appsec-*')
]),
E('li', {}, _('Configure AppSec in your acquis.yaml')),
E('li', {}, [
_('Restart CrowdSec service: '),
E('code', {}, '/etc/init.d/crowdsec restart')
]),
E('li', {}, [
_('Verify status: '),
E('code', {}, 'cscli appsec status')
])
])
]),
E('div', { 'class': 'cs-info-box', 'style': 'margin-top: 16px;' }, [
E('h4', { 'style': 'margin: 0 0 8px 0; color: var(--cs-text-primary);' }, _('Documentation')),
E('p', { 'style': 'margin: 0; color: var(--cs-text-secondary); font-size: 14px;' }, [
_('For detailed configuration, see: '),
E('a', {
'href': 'https://docs.crowdsec.net/docs/appsec/intro',
'target': '_blank',
'style': 'color: var(--cs-accent-cyan);'
}, 'CrowdSec AppSec Documentation')
])
])
])
]);
},
render: function(data) {
this.wafStatus = data.wafStatus || {};
var lang = (typeof L !== 'undefined' && L.env && L.env.lang) ||
(document.documentElement && document.documentElement.getAttribute('lang')) ||
(navigator.language ? navigator.language.split('-')[0] : 'en');
Theme.init({ language: lang });
return E('div', { 'class': 'crowdsec-dashboard' }, [
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox-theme/secubox-theme.css') }),
CsNav.renderTabs('waf'),
E('h2', { 'class': 'cs-page-title' }, _('CrowdSec WAF/AppSec')),
E('div', { 'class': 'cs-grid' }, [
this.renderWAFStatus(),
this.renderConfigHelp()
])
]);
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});