crowdswc full
This commit is contained in:
parent
ff20666817
commit
eb72e12a72
@ -4,7 +4,9 @@
|
|||||||
"Bash(done)",
|
"Bash(done)",
|
||||||
"Bash(ls:*)",
|
"Bash(ls:*)",
|
||||||
"Bash(find:*)",
|
"Bash(find:*)",
|
||||||
"Bash(xargs:*)"
|
"Bash(xargs:*)",
|
||||||
|
"Bash(mkdir:*)",
|
||||||
|
"Bash(shellcheck:*)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"anthropic.claude-code"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,22 +1,75 @@
|
|||||||
# SecuBox - Security Suite for OpenWrt
|
# SecuBox Central Hub
|
||||||
|
|
||||||
Unified security dashboard providing central management for:
|
Central management dashboard for the SecuBox security and network management suite for OpenWrt.
|
||||||
|
|
||||||
- **CrowdSec** - Collaborative intrusion prevention
|
## Features
|
||||||
|
|
||||||
|
### Dashboard Overview
|
||||||
|
- Real-time system health monitoring (CPU, Memory, Disk, Network)
|
||||||
|
- Visual gauges with color-coded status indicators
|
||||||
|
- Module status grid with quick access links
|
||||||
|
- Aggregated alerts from all modules
|
||||||
|
- Quick action buttons for common tasks
|
||||||
|
|
||||||
|
### System Health Monitoring
|
||||||
|
- **CPU**: Load average and percentage with multi-core support
|
||||||
|
- **Memory**: RAM usage with total/used/available metrics
|
||||||
|
- **Disk**: Root filesystem usage and available space
|
||||||
|
- **Network**: Real-time RX/TX bandwidth statistics
|
||||||
|
|
||||||
|
### Quick Actions
|
||||||
|
- Restart RPCD service
|
||||||
|
- Restart uHTTPd web server
|
||||||
|
- Clear system cache
|
||||||
|
- Create configuration backup
|
||||||
|
- Restart network services
|
||||||
|
- Restart firewall
|
||||||
|
|
||||||
|
### Module Management
|
||||||
|
Auto-detection and status monitoring for all SecuBox modules:
|
||||||
|
|
||||||
|
**Security & Monitoring**
|
||||||
|
- **CrowdSec** - Collaborative threat intelligence
|
||||||
- **Netdata** - Real-time system monitoring
|
- **Netdata** - Real-time system monitoring
|
||||||
- **Netifyd** - Deep packet inspection and traffic analysis
|
- **Netifyd** - Deep packet inspection
|
||||||
- **WireGuard** - Modern VPN
|
- **Client Guardian** - Network access control and captive portal
|
||||||
- **Network Modes** - Simplified network configuration
|
- **Auth Guardian** - Advanced authentication system
|
||||||
- **Client Guardian** - Access control and captive portal
|
|
||||||
- **System Hub** - System control center
|
**Network Management**
|
||||||
- **CDN Cache** - Bandwidth optimization proxy
|
- **WireGuard** - Modern VPN with QR codes
|
||||||
- **Traffic Shaper** - QoS, priorities, and quotas
|
- **Network Modes** - Network topology configuration
|
||||||
|
- **Bandwidth Manager** - QoS and bandwidth quotas
|
||||||
|
- **Media Flow** - Media traffic detection and optimization
|
||||||
|
- **Traffic Shaper** - Advanced traffic shaping
|
||||||
|
|
||||||
|
**System & Performance**
|
||||||
|
- **System Hub** - Unified control center
|
||||||
|
- **CDN Cache** - Local caching proxy
|
||||||
|
- **Virtual Host Manager** - Virtual host configuration
|
||||||
|
|
||||||
|
## RPCD API Methods
|
||||||
|
|
||||||
|
The hub provides a comprehensive RPC API via ubus:
|
||||||
|
|
||||||
|
- `status` - Get hub status and basic system info
|
||||||
|
- `modules` - List all SecuBox modules with status
|
||||||
|
- `modules_by_category` - Filter modules by category
|
||||||
|
- `module_info` - Get detailed info for a specific module
|
||||||
|
- `get_system_health` - Detailed system health metrics
|
||||||
|
- `get_alerts` - Aggregated alerts from all modules
|
||||||
|
- `get_dashboard_data` - All dashboard data in one call
|
||||||
|
- `quick_action` - Execute quick actions
|
||||||
|
- `start_module` / `stop_module` / `restart_module` - Module control
|
||||||
|
- `health` - System health checks
|
||||||
|
- `diagnostics` - Generate diagnostics bundle
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
opkg update
|
opkg update
|
||||||
opkg install luci-app-secubox
|
opkg install luci-app-secubox
|
||||||
|
/etc/init.d/rpcd restart
|
||||||
|
/etc/init.d/uhttpd restart
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
@ -27,6 +80,33 @@ git clone https://github.com/youruser/luci-app-secubox.git package/luci-app-secu
|
|||||||
make package/luci-app-secubox/compile V=s
|
make package/luci-app-secubox/compile V=s
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Edit `/etc/config/secubox` to customize module definitions and settings.
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
luci-app-secubox/
|
||||||
|
├── Makefile
|
||||||
|
├── README.md
|
||||||
|
├── htdocs/luci-static/resources/
|
||||||
|
│ ├── view/secubox/
|
||||||
|
│ │ ├── dashboard.js # Main dashboard view
|
||||||
|
│ │ ├── modules.js # Modules management view
|
||||||
|
│ │ └── settings.js # Settings view
|
||||||
|
│ └── secubox/
|
||||||
|
│ ├── api.js # RPC API client
|
||||||
|
│ └── secubox.css # Dashboard styles
|
||||||
|
└── root/
|
||||||
|
├── etc/config/secubox # UCI configuration
|
||||||
|
└── usr/
|
||||||
|
├── libexec/rpcd/secubox # RPCD backend
|
||||||
|
└── share/
|
||||||
|
├── luci/menu.d/luci-app-secubox.json
|
||||||
|
└── rpcd/acl.d/luci-app-secubox.json
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT License - CyberMind Security
|
Apache-2.0 - Copyright (C) 2025 CyberMind.fr
|
||||||
|
|||||||
@ -64,6 +64,31 @@ var callDiagnostics = rpc.declare({
|
|||||||
expect: { }
|
expect: { }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var callSystemHealth = rpc.declare({
|
||||||
|
object: 'luci.secubox',
|
||||||
|
method: 'get_system_health',
|
||||||
|
expect: { }
|
||||||
|
});
|
||||||
|
|
||||||
|
var callAlerts = rpc.declare({
|
||||||
|
object: 'luci.secubox',
|
||||||
|
method: 'get_alerts',
|
||||||
|
expect: { alerts: [] }
|
||||||
|
});
|
||||||
|
|
||||||
|
var callQuickAction = rpc.declare({
|
||||||
|
object: 'luci.secubox',
|
||||||
|
method: 'quick_action',
|
||||||
|
params: ['action'],
|
||||||
|
expect: { }
|
||||||
|
});
|
||||||
|
|
||||||
|
var callDashboardData = rpc.declare({
|
||||||
|
object: 'luci.secubox',
|
||||||
|
method: 'get_dashboard_data',
|
||||||
|
expect: { }
|
||||||
|
});
|
||||||
|
|
||||||
function formatUptime(seconds) {
|
function formatUptime(seconds) {
|
||||||
if (!seconds) return '0s';
|
if (!seconds) return '0s';
|
||||||
var d = Math.floor(seconds / 86400);
|
var d = Math.floor(seconds / 86400);
|
||||||
@ -74,6 +99,14 @@ function formatUptime(seconds) {
|
|||||||
return m + 'm';
|
return m + 'm';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatBytes(bytes) {
|
||||||
|
if (!bytes) return '0 B';
|
||||||
|
var k = 1024;
|
||||||
|
var sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||||
|
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
return baseclass.extend({
|
return baseclass.extend({
|
||||||
getStatus: callStatus,
|
getStatus: callStatus,
|
||||||
getModules: callModules,
|
getModules: callModules,
|
||||||
@ -84,5 +117,10 @@ return baseclass.extend({
|
|||||||
restartModule: callRestartModule,
|
restartModule: callRestartModule,
|
||||||
getHealth: callHealth,
|
getHealth: callHealth,
|
||||||
getDiagnostics: callDiagnostics,
|
getDiagnostics: callDiagnostics,
|
||||||
formatUptime: formatUptime
|
getSystemHealth: callSystemHealth,
|
||||||
|
getAlerts: callAlerts,
|
||||||
|
quickAction: callQuickAction,
|
||||||
|
getDashboardData: callDashboardData,
|
||||||
|
formatUptime: formatUptime,
|
||||||
|
formatBytes: formatBytes
|
||||||
});
|
});
|
||||||
|
|||||||
@ -30,3 +30,262 @@
|
|||||||
.sb-color-client-guardian { --module-color: #ef4444; }
|
.sb-color-client-guardian { --module-color: #ef4444; }
|
||||||
.sb-color-system-hub { --module-color: #6366f1; }
|
.sb-color-system-hub { --module-color: #6366f1; }
|
||||||
.sb-color-cdn-cache { --module-color: #06b6d4; }
|
.sb-color-cdn-cache { --module-color: #06b6d4; }
|
||||||
|
|
||||||
|
/* System Health Section */
|
||||||
|
.secubox-health-section {
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: var(--sb-bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--sb-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-health-section h3 {
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
color: var(--sb-text);
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-health-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-gauge {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 16px;
|
||||||
|
background: rgba(15, 23, 42, 0.5);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-gauge-label {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--sb-text);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-gauge-chart {
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-gauge-details {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--sb-text-muted);
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Quick Actions Section */
|
||||||
|
.secubox-quick-actions {
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: var(--sb-bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--sb-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-quick-actions h3 {
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
color: var(--sb-text);
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-actions-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-quick-actions .cbi-button-action {
|
||||||
|
padding: 12px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alerts Section */
|
||||||
|
.secubox-alerts-section {
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: var(--sb-bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--sb-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-alerts-section h3 {
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
color: var(--sb-text);
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-alerts-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-alert {
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border-left: 4px solid;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-alert-warning {
|
||||||
|
background: rgba(245, 158, 11, 0.1);
|
||||||
|
border-left-color: var(--sb-warning);
|
||||||
|
color: #fbbf24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-alert-error {
|
||||||
|
background: rgba(239, 68, 68, 0.1);
|
||||||
|
border-left-color: var(--sb-danger);
|
||||||
|
color: #fca5a5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-alert-info {
|
||||||
|
background: rgba(59, 130, 246, 0.1);
|
||||||
|
border-left-color: var(--sb-primary);
|
||||||
|
color: #93c5fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modules Section */
|
||||||
|
.secubox-modules-section {
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-modules-section h3 {
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
color: var(--sb-text);
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-modules-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-card {
|
||||||
|
background: var(--sb-bg-card);
|
||||||
|
border: 1px solid var(--sb-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
border-color: var(--sb-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-card[data-status="running"] {
|
||||||
|
border-left: 4px solid var(--sb-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-card[data-status="stopped"] {
|
||||||
|
border-left: 4px solid var(--sb-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-card[data-status="not-installed"] {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-status {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-body {
|
||||||
|
flex: 1;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--sb-text);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-description {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--sb-text-muted);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-category {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: rgba(59, 130, 246, 0.2);
|
||||||
|
color: var(--sb-primary);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-footer {
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid var(--sb-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-module-footer .cbi-button-link {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-not-installed {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--sb-text-muted);
|
||||||
|
font-size: 13px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.secubox-health-grid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-actions-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secubox-modules-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,38 +1,216 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
'require view';
|
'require view';
|
||||||
'require rpc';
|
'require ui';
|
||||||
|
'require secubox/api as API';
|
||||||
|
'require dom';
|
||||||
|
|
||||||
var callStatus = rpc.declare({object:'luci.secubox',method:'status',expect:{}});
|
// Load CSS
|
||||||
var callModules = rpc.declare({object:'luci.secubox',method:'modules',expect:{modules:[]}});
|
document.head.appendChild(E('link', {
|
||||||
|
'rel': 'stylesheet',
|
||||||
|
'type': 'text/css',
|
||||||
|
'href': L.resource('secubox/secubox.css')
|
||||||
|
}));
|
||||||
|
|
||||||
return view.extend({
|
return view.extend({
|
||||||
load: function() { return Promise.all([callStatus(), callModules()]); },
|
load: function() {
|
||||||
render: function(data) {
|
return Promise.all([
|
||||||
var status = data[0] || {}, modules = data[1].modules || [];
|
API.getDashboardData(),
|
||||||
var cats = {security:[], monitoring:[], network:[], system:[]};
|
API.getSystemHealth(),
|
||||||
modules.forEach(function(m) { if(cats[m.category]) cats[m.category].push(m); });
|
API.getAlerts()
|
||||||
|
]);
|
||||||
return E('div', {class:'cbi-map'}, [
|
},
|
||||||
E('h2', {}, '🛡️ SecuBox Dashboard'),
|
|
||||||
E('div', {style:'display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin:20px 0'}, [
|
render: function(data) {
|
||||||
E('div', {style:'background:#1e293b;padding:16px;border-radius:8px;text-align:center'}, [
|
var dashboard = data[0] || {};
|
||||||
E('div', {style:'font-size:24px;font-weight:bold;color:#22d3ee'}, status.modules_total || 0),
|
var health = data[1] || {};
|
||||||
E('div', {style:'color:#94a3b8'}, 'Total Modules')
|
var alertsData = data[2] || {};
|
||||||
]),
|
|
||||||
E('div', {style:'background:#1e293b;padding:16px;border-radius:8px;text-align:center'}, [
|
var status = dashboard.status || {};
|
||||||
E('div', {style:'font-size:24px;font-weight:bold;color:#3b82f6'}, status.modules_installed || 0),
|
var modules = dashboard.modules || [];
|
||||||
E('div', {style:'color:#94a3b8'}, 'Installed')
|
var counts = dashboard.counts || {};
|
||||||
]),
|
var alerts = alertsData.alerts || [];
|
||||||
E('div', {style:'background:#1e293b;padding:16px;border-radius:8px;text-align:center'}, [
|
|
||||||
E('div', {style:'font-size:24px;font-weight:bold;color:#22c55e'}, status.modules_running || 0),
|
var container = E('div', { 'class': 'cbi-map' });
|
||||||
E('div', {style:'color:#94a3b8'}, 'Running')
|
|
||||||
]),
|
// Header
|
||||||
E('div', {style:'background:#1e293b;padding:16px;border-radius:8px;text-align:center'}, [
|
container.appendChild(E('h2', {}, 'SecuBox Central Hub'));
|
||||||
E('div', {style:'font-size:24px;font-weight:bold;color:#f59e0b'}, (status.memory_percent || 0) + '%'),
|
container.appendChild(E('p', {},
|
||||||
E('div', {style:'color:#94a3b8'}, 'Memory')
|
'Hostname: ' + (status.hostname || 'Unknown') + ' | ' +
|
||||||
])
|
'Uptime: ' + API.formatUptime(status.uptime) + ' | ' +
|
||||||
]),
|
'Load: ' + (status.load || '0.00')
|
||||||
E('p', {}, 'Hostname: ' + (status.hostname || 'unknown') + ' | Load: ' + (status.load || '0'))
|
));
|
||||||
]);
|
|
||||||
}
|
// System Health Section
|
||||||
|
container.appendChild(this.renderSystemHealth(health));
|
||||||
|
|
||||||
|
// Quick Actions Section
|
||||||
|
container.appendChild(this.renderQuickActions());
|
||||||
|
|
||||||
|
// Alerts Section
|
||||||
|
if (alerts.length > 0) {
|
||||||
|
container.appendChild(this.renderAlerts(alerts));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modules Grid
|
||||||
|
container.appendChild(this.renderModulesGrid(modules));
|
||||||
|
|
||||||
|
return container;
|
||||||
|
},
|
||||||
|
|
||||||
|
renderSystemHealth: function(health) {
|
||||||
|
var cpu = health.cpu || {};
|
||||||
|
var memory = health.memory || {};
|
||||||
|
var disk = health.disk || {};
|
||||||
|
var network = health.network || {};
|
||||||
|
|
||||||
|
var section = E('div', { 'class': 'secubox-health-section' }, [
|
||||||
|
E('h3', {}, 'System Health'),
|
||||||
|
E('div', { 'class': 'secubox-health-grid' }, [
|
||||||
|
this.renderGauge('CPU', cpu.percent || 0, '%', cpu.load_1min),
|
||||||
|
this.renderGauge('Memory', memory.percent || 0, '%',
|
||||||
|
API.formatBytes(memory.used_kb * 1024) + ' / ' + API.formatBytes(memory.total_kb * 1024)),
|
||||||
|
this.renderGauge('Disk', disk.percent || 0, '%',
|
||||||
|
API.formatBytes(disk.used_kb * 1024) + ' / ' + API.formatBytes(disk.total_kb * 1024)),
|
||||||
|
this.renderGauge('Network', 0, '',
|
||||||
|
'RX: ' + API.formatBytes(network.rx_bytes) + ' | TX: ' + API.formatBytes(network.tx_bytes))
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
return section;
|
||||||
|
},
|
||||||
|
|
||||||
|
renderGauge: function(label, percent, unit, details) {
|
||||||
|
var color = percent < 70 ? '#22c55e' : percent < 85 ? '#f59e0b' : '#ef4444';
|
||||||
|
|
||||||
|
return E('div', { 'class': 'secubox-gauge' }, [
|
||||||
|
E('div', { 'class': 'secubox-gauge-label' }, label),
|
||||||
|
E('div', { 'class': 'secubox-gauge-chart' }, [
|
||||||
|
E('svg', { 'width': '120', 'height': '120', 'viewBox': '0 0 120 120' }, [
|
||||||
|
E('circle', {
|
||||||
|
'cx': '60', 'cy': '60', 'r': '54',
|
||||||
|
'fill': 'none', 'stroke': '#1e293b', 'stroke-width': '12'
|
||||||
|
}),
|
||||||
|
E('circle', {
|
||||||
|
'cx': '60', 'cy': '60', 'r': '54',
|
||||||
|
'fill': 'none', 'stroke': color, 'stroke-width': '12',
|
||||||
|
'stroke-dasharray': (339.292 * percent / 100) + ' 339.292',
|
||||||
|
'stroke-linecap': 'round',
|
||||||
|
'transform': 'rotate(-90 60 60)'
|
||||||
|
}),
|
||||||
|
E('text', {
|
||||||
|
'x': '60', 'y': '65', 'text-anchor': 'middle',
|
||||||
|
'font-size': '24', 'font-weight': 'bold', 'fill': color
|
||||||
|
}, percent + unit)
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
E('div', { 'class': 'secubox-gauge-details' }, details || '')
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
renderQuickActions: function() {
|
||||||
|
var self = this;
|
||||||
|
var actions = [
|
||||||
|
{ name: 'restart_rpcd', label: 'Restart RPCD', icon: '🔄' },
|
||||||
|
{ name: 'restart_uhttpd', label: 'Restart uHTTPd', icon: '🌐' },
|
||||||
|
{ name: 'clear_cache', label: 'Clear Cache', icon: '🧹' },
|
||||||
|
{ name: 'backup_config', label: 'Backup Config', icon: '💾' },
|
||||||
|
{ name: 'restart_network', label: 'Restart Network', icon: '📡' },
|
||||||
|
{ name: 'restart_firewall', label: 'Restart Firewall', icon: '🛡️' }
|
||||||
|
];
|
||||||
|
|
||||||
|
var buttons = actions.map(function(action) {
|
||||||
|
return E('button', {
|
||||||
|
'class': 'cbi-button cbi-button-action',
|
||||||
|
'click': function() {
|
||||||
|
self.executeQuickAction(action.name, action.label);
|
||||||
|
}
|
||||||
|
}, action.icon + ' ' + action.label);
|
||||||
|
});
|
||||||
|
|
||||||
|
return E('div', { 'class': 'secubox-quick-actions' }, [
|
||||||
|
E('h3', {}, 'Quick Actions'),
|
||||||
|
E('div', { 'class': 'secubox-actions-grid' }, buttons)
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
executeQuickAction: function(action, label) {
|
||||||
|
ui.showModal(_('Quick Action'), [
|
||||||
|
E('p', { 'class': 'spinning' }, _('Executing: ') + label + '...')
|
||||||
|
]);
|
||||||
|
|
||||||
|
API.quickAction(action).then(function(result) {
|
||||||
|
ui.hideModal();
|
||||||
|
if (result && result.success) {
|
||||||
|
ui.addNotification(null, E('p', result.message || 'Action completed'), 'info');
|
||||||
|
} else {
|
||||||
|
ui.addNotification(null, E('p', result.message || 'Action failed'), 'error');
|
||||||
|
}
|
||||||
|
}).catch(function(err) {
|
||||||
|
ui.hideModal();
|
||||||
|
ui.addNotification(null, E('p', 'Error: ' + err.message), 'error');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
renderAlerts: function(alerts) {
|
||||||
|
var alertItems = alerts.map(function(alert) {
|
||||||
|
var severityClass = 'secubox-alert-' + (alert.severity || 'info');
|
||||||
|
return E('div', { 'class': 'secubox-alert ' + severityClass }, [
|
||||||
|
E('strong', {}, alert.module + ': '),
|
||||||
|
E('span', {}, alert.message)
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return E('div', { 'class': 'secubox-alerts-section' }, [
|
||||||
|
E('h3', {}, 'Recent Alerts (' + alerts.length + ')'),
|
||||||
|
E('div', { 'class': 'secubox-alerts-list' }, alertItems)
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
renderModulesGrid: function(modules) {
|
||||||
|
var moduleCards = modules.map(function(module) {
|
||||||
|
var statusClass = module.installed ? (module.running ? 'running' : 'stopped') : 'not-installed';
|
||||||
|
var statusIcon = module.installed ? (module.running ? '✓' : '✗') : '○';
|
||||||
|
var statusColor = module.installed ? (module.running ? '#22c55e' : '#ef4444') : '#64748b';
|
||||||
|
|
||||||
|
return E('div', {
|
||||||
|
'class': 'secubox-module-card',
|
||||||
|
'data-status': statusClass
|
||||||
|
}, [
|
||||||
|
E('div', { 'class': 'secubox-module-header' }, [
|
||||||
|
E('div', {
|
||||||
|
'class': 'secubox-module-icon',
|
||||||
|
'style': 'background-color: ' + (module.color || '#64748b')
|
||||||
|
}, module.icon || '📦'),
|
||||||
|
E('div', {
|
||||||
|
'class': 'secubox-module-status',
|
||||||
|
'style': 'color: ' + statusColor
|
||||||
|
}, statusIcon)
|
||||||
|
]),
|
||||||
|
E('div', { 'class': 'secubox-module-body' }, [
|
||||||
|
E('div', { 'class': 'secubox-module-name' }, module.name || module.id),
|
||||||
|
E('div', { 'class': 'secubox-module-description' }, module.description || ''),
|
||||||
|
E('div', { 'class': 'secubox-module-category' }, module.category || 'other')
|
||||||
|
]),
|
||||||
|
E('div', { 'class': 'secubox-module-footer' }, [
|
||||||
|
module.installed ? E('a', {
|
||||||
|
'href': '#',
|
||||||
|
'class': 'cbi-button cbi-button-link',
|
||||||
|
'click': function(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
window.location.hash = '#admin/secubox/' + module.id;
|
||||||
|
}
|
||||||
|
}, 'Open Dashboard') : E('span', { 'class': 'secubox-not-installed' }, 'Not Installed')
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return E('div', { 'class': 'secubox-modules-section' }, [
|
||||||
|
E('h3', {}, 'Installed Modules'),
|
||||||
|
E('div', { 'class': 'secubox-modules-grid' }, moduleCards)
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSaveApply: null,
|
||||||
|
handleSave: null,
|
||||||
|
handleReset: null
|
||||||
});
|
});
|
||||||
|
|||||||
@ -95,3 +95,58 @@ config module 'cdn_cache'
|
|||||||
option config 'cdn-cache'
|
option config 'cdn-cache'
|
||||||
option installed '0'
|
option installed '0'
|
||||||
option enabled '0'
|
option enabled '0'
|
||||||
|
|
||||||
|
config module 'bandwidth_manager'
|
||||||
|
option name 'Bandwidth Manager'
|
||||||
|
option description 'QoS and bandwidth quotas'
|
||||||
|
option category 'network'
|
||||||
|
option icon 'activity'
|
||||||
|
option color '#3b82f6'
|
||||||
|
option package 'luci-app-bandwidth-manager'
|
||||||
|
option config 'bandwidth_manager'
|
||||||
|
option installed '0'
|
||||||
|
option enabled '0'
|
||||||
|
|
||||||
|
config module 'auth_guardian'
|
||||||
|
option name 'Auth Guardian'
|
||||||
|
option description 'Advanced authentication system'
|
||||||
|
option category 'security'
|
||||||
|
option icon 'key'
|
||||||
|
option color '#f59e0b'
|
||||||
|
option package 'luci-app-auth-guardian'
|
||||||
|
option config 'auth_guardian'
|
||||||
|
option installed '0'
|
||||||
|
option enabled '0'
|
||||||
|
|
||||||
|
config module 'media_flow'
|
||||||
|
option name 'Media Flow'
|
||||||
|
option description 'Media traffic detection and optimization'
|
||||||
|
option category 'network'
|
||||||
|
option icon 'play-circle'
|
||||||
|
option color '#ec4899'
|
||||||
|
option package 'luci-app-media-flow'
|
||||||
|
option config 'media_flow'
|
||||||
|
option installed '0'
|
||||||
|
option enabled '0'
|
||||||
|
|
||||||
|
config module 'vhost_manager'
|
||||||
|
option name 'Virtual Host Manager'
|
||||||
|
option description 'Virtual host configuration'
|
||||||
|
option category 'system'
|
||||||
|
option icon 'server'
|
||||||
|
option color '#8b5cf6'
|
||||||
|
option package 'luci-app-vhost-manager'
|
||||||
|
option config 'vhost_manager'
|
||||||
|
option installed '0'
|
||||||
|
option enabled '0'
|
||||||
|
|
||||||
|
config module 'traffic_shaper'
|
||||||
|
option name 'Traffic Shaper'
|
||||||
|
option description 'Advanced traffic shaping'
|
||||||
|
option category 'network'
|
||||||
|
option icon 'trending-up'
|
||||||
|
option color '#10b981'
|
||||||
|
option package 'luci-app-traffic-shaper'
|
||||||
|
option config 'traffic_shaper'
|
||||||
|
option installed '0'
|
||||||
|
option enabled '0'
|
||||||
|
|||||||
@ -7,8 +7,23 @@
|
|||||||
. /lib/functions.sh
|
. /lib/functions.sh
|
||||||
. /usr/share/libubox/jshn.sh
|
. /usr/share/libubox/jshn.sh
|
||||||
|
|
||||||
# Module registry
|
# Module registry - auto-detected from /usr/libexec/rpcd/
|
||||||
MODULES="crowdsec netdata netifyd wireguard network_modes client_guardian system_hub cdn_cache"
|
detect_modules() {
|
||||||
|
local modules=""
|
||||||
|
local scripts="crowdsec-dashboard netdata-dashboard netifyd-dashboard wireguard-dashboard network-modes client-guardian system-hub bandwidth-manager auth-guardian media-flow vhost-manager cdn-cache traffic-shaper"
|
||||||
|
|
||||||
|
for script in $scripts; do
|
||||||
|
if [ -x "/usr/libexec/rpcd/$script" ]; then
|
||||||
|
# Convert script name to module ID (remove -dashboard suffix)
|
||||||
|
local module_id=$(echo "$script" | sed 's/-dashboard$//')
|
||||||
|
modules="$modules $module_id"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$modules"
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULES=$(detect_modules)
|
||||||
|
|
||||||
# Check if a module is installed
|
# Check if a module is installed
|
||||||
check_module_installed() {
|
check_module_installed() {
|
||||||
@ -338,7 +353,7 @@ get_health() {
|
|||||||
# Generate diagnostics bundle
|
# Generate diagnostics bundle
|
||||||
get_diagnostics() {
|
get_diagnostics() {
|
||||||
json_init
|
json_init
|
||||||
|
|
||||||
# System info
|
# System info
|
||||||
json_add_object "system"
|
json_add_object "system"
|
||||||
json_add_string "hostname" "$(uci -q get system.@system[0].hostname)"
|
json_add_string "hostname" "$(uci -q get system.@system[0].hostname)"
|
||||||
@ -347,13 +362,13 @@ get_diagnostics() {
|
|||||||
json_add_string "kernel" "$(uname -r)"
|
json_add_string "kernel" "$(uname -r)"
|
||||||
json_add_int "uptime" "$(cat /proc/uptime | cut -d. -f1)"
|
json_add_int "uptime" "$(cat /proc/uptime | cut -d. -f1)"
|
||||||
json_close_object
|
json_close_object
|
||||||
|
|
||||||
# Modules status
|
# Modules status
|
||||||
json_add_array "modules"
|
json_add_array "modules"
|
||||||
for module in $MODULES; do
|
for module in $MODULES; do
|
||||||
local is_installed=$(check_module_installed "$module")
|
local is_installed=$(check_module_installed "$module")
|
||||||
local is_running=$(check_module_running "$module")
|
local is_running=$(check_module_running "$module")
|
||||||
|
|
||||||
json_add_object ""
|
json_add_object ""
|
||||||
json_add_string "id" "$module"
|
json_add_string "id" "$module"
|
||||||
json_add_boolean "installed" "$is_installed"
|
json_add_boolean "installed" "$is_installed"
|
||||||
@ -361,13 +376,13 @@ get_diagnostics() {
|
|||||||
json_close_object
|
json_close_object
|
||||||
done
|
done
|
||||||
json_close_array
|
json_close_array
|
||||||
|
|
||||||
# Network interfaces
|
# Network interfaces
|
||||||
json_add_array "interfaces"
|
json_add_array "interfaces"
|
||||||
for iface in $(ls /sys/class/net/); do
|
for iface in $(ls /sys/class/net/); do
|
||||||
local mac=$(cat /sys/class/net/$iface/address 2>/dev/null)
|
local mac=$(cat /sys/class/net/$iface/address 2>/dev/null)
|
||||||
local state=$(cat /sys/class/net/$iface/operstate 2>/dev/null)
|
local state=$(cat /sys/class/net/$iface/operstate 2>/dev/null)
|
||||||
|
|
||||||
json_add_object ""
|
json_add_object ""
|
||||||
json_add_string "name" "$iface"
|
json_add_string "name" "$iface"
|
||||||
json_add_string "mac" "$mac"
|
json_add_string "mac" "$mac"
|
||||||
@ -375,9 +390,287 @@ get_diagnostics() {
|
|||||||
json_close_object
|
json_close_object
|
||||||
done
|
done
|
||||||
json_close_array
|
json_close_array
|
||||||
|
|
||||||
json_add_int "generated" "$(date +%s)"
|
json_add_int "generated" "$(date +%s)"
|
||||||
|
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get system health metrics
|
||||||
|
get_system_health() {
|
||||||
|
json_init
|
||||||
|
|
||||||
|
# CPU usage (based on load average)
|
||||||
|
local load=$(cat /proc/loadavg | cut -d' ' -f1)
|
||||||
|
local cpu_cores=$(grep -c processor /proc/cpuinfo)
|
||||||
|
local cpu_pct=$(awk "BEGIN {printf \"%.0f\", ($load / $cpu_cores) * 100}")
|
||||||
|
|
||||||
|
# Memory
|
||||||
|
local mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
|
||||||
|
local mem_avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
|
||||||
|
local mem_used=$((mem_total - mem_avail))
|
||||||
|
local mem_pct=$((mem_used * 100 / mem_total))
|
||||||
|
|
||||||
|
# Disk usage (root filesystem)
|
||||||
|
local disk_info=$(df / | tail -1)
|
||||||
|
local disk_total=$(echo "$disk_info" | awk '{print $2}')
|
||||||
|
local disk_used=$(echo "$disk_info" | awk '{print $3}')
|
||||||
|
local disk_pct=$(echo "$disk_info" | awk '{print $5}' | tr -d '%')
|
||||||
|
|
||||||
|
# Network stats (sum all interfaces)
|
||||||
|
local net_rx=0
|
||||||
|
local net_tx=0
|
||||||
|
for iface in $(ls /sys/class/net/ | grep -v lo); do
|
||||||
|
if [ -f "/sys/class/net/$iface/statistics/rx_bytes" ]; then
|
||||||
|
local rx=$(cat /sys/class/net/$iface/statistics/rx_bytes 2>/dev/null || echo 0)
|
||||||
|
local tx=$(cat /sys/class/net/$iface/statistics/tx_bytes 2>/dev/null || echo 0)
|
||||||
|
net_rx=$((net_rx + rx))
|
||||||
|
net_tx=$((net_tx + tx))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Uptime
|
||||||
|
local uptime=$(cat /proc/uptime | cut -d. -f1)
|
||||||
|
|
||||||
|
# Load averages
|
||||||
|
local load_1min=$(cat /proc/loadavg | cut -d' ' -f1)
|
||||||
|
local load_5min=$(cat /proc/loadavg | cut -d' ' -f2)
|
||||||
|
local load_15min=$(cat /proc/loadavg | cut -d' ' -f3)
|
||||||
|
|
||||||
|
json_add_object "cpu"
|
||||||
|
json_add_int "percent" "$cpu_pct"
|
||||||
|
json_add_int "cores" "$cpu_cores"
|
||||||
|
json_add_string "load_1min" "$load_1min"
|
||||||
|
json_add_string "load_5min" "$load_5min"
|
||||||
|
json_add_string "load_15min" "$load_15min"
|
||||||
|
json_close_object
|
||||||
|
|
||||||
|
json_add_object "memory"
|
||||||
|
json_add_int "percent" "$mem_pct"
|
||||||
|
json_add_int "total_kb" "$mem_total"
|
||||||
|
json_add_int "used_kb" "$mem_used"
|
||||||
|
json_add_int "available_kb" "$mem_avail"
|
||||||
|
json_close_object
|
||||||
|
|
||||||
|
json_add_object "disk"
|
||||||
|
json_add_int "percent" "$disk_pct"
|
||||||
|
json_add_int "total_kb" "$disk_total"
|
||||||
|
json_add_int "used_kb" "$disk_used"
|
||||||
|
json_close_object
|
||||||
|
|
||||||
|
json_add_object "network"
|
||||||
|
json_add_int "rx_bytes" "$net_rx"
|
||||||
|
json_add_int "tx_bytes" "$net_tx"
|
||||||
|
json_close_object
|
||||||
|
|
||||||
|
json_add_int "uptime" "$uptime"
|
||||||
|
json_add_int "timestamp" "$(date +%s)"
|
||||||
|
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get aggregated alerts from all modules
|
||||||
|
get_alerts() {
|
||||||
|
json_init
|
||||||
|
json_add_array "alerts"
|
||||||
|
|
||||||
|
# Check each installed module for alerts via ubus
|
||||||
|
for module in $MODULES; do
|
||||||
|
local is_installed=$(check_module_installed "$module")
|
||||||
|
|
||||||
|
if [ "$is_installed" = "1" ]; then
|
||||||
|
# Try to call module's status method to get alerts
|
||||||
|
local module_script=$(echo "$module" | sed 's/_/-/g')
|
||||||
|
if [ -x "/usr/libexec/rpcd/${module_script}" ] || [ -x "/usr/libexec/rpcd/${module_script}-dashboard" ]; then
|
||||||
|
# Call via ubus if available
|
||||||
|
local alerts=$(ubus call "luci.${module_script//-/_}" status 2>/dev/null | jsonfilter -e '@.alerts[@]' 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -n "$alerts" ]; then
|
||||||
|
# Module has alerts, add them
|
||||||
|
json_add_object ""
|
||||||
|
json_add_string "module" "$module"
|
||||||
|
json_add_string "message" "$alerts"
|
||||||
|
json_add_string "severity" "warning"
|
||||||
|
json_add_int "timestamp" "$(date +%s)"
|
||||||
|
json_close_object
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if module service is not running
|
||||||
|
local is_running=$(check_module_running "$module")
|
||||||
|
if [ "$is_running" != "1" ]; then
|
||||||
|
config_load secubox
|
||||||
|
local name
|
||||||
|
config_get name "$module" name "$module"
|
||||||
|
|
||||||
|
json_add_object ""
|
||||||
|
json_add_string "module" "$module"
|
||||||
|
json_add_string "message" "$name service is not running"
|
||||||
|
json_add_string "severity" "warning"
|
||||||
|
json_add_int "timestamp" "$(date +%s)"
|
||||||
|
json_close_object
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
json_close_array
|
||||||
|
json_add_int "count" "$(ubus call luci.secubox get_alerts 2>/dev/null | jsonfilter -e '@.alerts[*]' | wc -l || echo 0)"
|
||||||
|
json_add_int "timestamp" "$(date +%s)"
|
||||||
|
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execute quick actions
|
||||||
|
quick_action() {
|
||||||
|
local action="$1"
|
||||||
|
|
||||||
|
json_init
|
||||||
|
|
||||||
|
case "$action" in
|
||||||
|
restart_rpcd)
|
||||||
|
/etc/init.d/rpcd restart >/dev/null 2>&1
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "RPCD service restarted"
|
||||||
|
;;
|
||||||
|
restart_uhttpd)
|
||||||
|
/etc/init.d/uhttpd restart >/dev/null 2>&1
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "uHTTPd service restarted"
|
||||||
|
;;
|
||||||
|
clear_cache)
|
||||||
|
sync
|
||||||
|
echo 3 > /proc/sys/vm/drop_caches 2>/dev/null
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "System cache cleared"
|
||||||
|
;;
|
||||||
|
backup_config)
|
||||||
|
local backup_file="/tmp/backup-$(date +%Y%m%d-%H%M%S).tar.gz"
|
||||||
|
sysupgrade -b "$backup_file" >/dev/null 2>&1
|
||||||
|
if [ -f "$backup_file" ]; then
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "Configuration backup created"
|
||||||
|
json_add_string "file" "$backup_file"
|
||||||
|
else
|
||||||
|
json_add_boolean "success" 0
|
||||||
|
json_add_string "message" "Backup failed"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
restart_network)
|
||||||
|
/etc/init.d/network restart >/dev/null 2>&1
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "Network services restarted"
|
||||||
|
;;
|
||||||
|
restart_firewall)
|
||||||
|
/etc/init.d/firewall restart >/dev/null 2>&1
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "Firewall restarted"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
json_add_boolean "success" 0
|
||||||
|
json_add_string "message" "Unknown action: $action"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
json_add_int "timestamp" "$(date +%s)"
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get all dashboard data in one call
|
||||||
|
get_dashboard_data() {
|
||||||
|
json_init
|
||||||
|
|
||||||
|
# Get status info
|
||||||
|
local uptime=$(cat /proc/uptime | cut -d. -f1)
|
||||||
|
local load=$(cat /proc/loadavg | cut -d' ' -f1-3)
|
||||||
|
local mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
|
||||||
|
local mem_free=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
|
||||||
|
local mem_used=$((mem_total - mem_free))
|
||||||
|
local mem_pct=$((mem_used * 100 / mem_total))
|
||||||
|
|
||||||
|
json_add_object "status"
|
||||||
|
json_add_string "version" "1.0.0"
|
||||||
|
json_add_string "hostname" "$(uci -q get system.@system[0].hostname || echo 'SecuBox')"
|
||||||
|
json_add_int "uptime" "$uptime"
|
||||||
|
json_add_string "load" "$load"
|
||||||
|
json_add_int "memory_total" "$mem_total"
|
||||||
|
json_add_int "memory_used" "$mem_used"
|
||||||
|
json_add_int "memory_percent" "$mem_pct"
|
||||||
|
json_close_object
|
||||||
|
|
||||||
|
# Get modules list
|
||||||
|
json_add_array "modules"
|
||||||
|
config_load secubox
|
||||||
|
for module in $MODULES; do
|
||||||
|
local name desc category icon color
|
||||||
|
config_get name "$module" name "$module"
|
||||||
|
config_get desc "$module" description ""
|
||||||
|
config_get category "$module" category "other"
|
||||||
|
config_get icon "$module" icon "box"
|
||||||
|
config_get color "$module" color "#64748b"
|
||||||
|
|
||||||
|
local is_installed=$(check_module_installed "$module")
|
||||||
|
local is_running=$(check_module_running "$module")
|
||||||
|
|
||||||
|
json_add_object ""
|
||||||
|
json_add_string "id" "$module"
|
||||||
|
json_add_string "name" "$name"
|
||||||
|
json_add_string "description" "$desc"
|
||||||
|
json_add_string "category" "$category"
|
||||||
|
json_add_string "icon" "$icon"
|
||||||
|
json_add_string "color" "$color"
|
||||||
|
json_add_boolean "installed" "$is_installed"
|
||||||
|
json_add_boolean "running" "$is_running"
|
||||||
|
json_close_object
|
||||||
|
done
|
||||||
|
json_close_array
|
||||||
|
|
||||||
|
# Count installed and running modules
|
||||||
|
local total=0 installed=0 running=0
|
||||||
|
for module in $MODULES; do
|
||||||
|
total=$((total + 1))
|
||||||
|
[ "$(check_module_installed "$module")" = "1" ] && installed=$((installed + 1))
|
||||||
|
[ "$(check_module_running "$module")" = "1" ] && running=$((running + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
json_add_object "counts"
|
||||||
|
json_add_int "total" "$total"
|
||||||
|
json_add_int "installed" "$installed"
|
||||||
|
json_add_int "running" "$running"
|
||||||
|
json_close_object
|
||||||
|
|
||||||
|
# Get system health
|
||||||
|
local cpu_cores=$(grep -c processor /proc/cpuinfo)
|
||||||
|
local load_val=$(cat /proc/loadavg | cut -d' ' -f1)
|
||||||
|
local cpu_pct=$(awk "BEGIN {printf \"%.0f\", ($load_val / $cpu_cores) * 100}")
|
||||||
|
local disk_pct=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
|
||||||
|
|
||||||
|
json_add_object "health"
|
||||||
|
json_add_int "cpu_percent" "$cpu_pct"
|
||||||
|
json_add_int "memory_percent" "$mem_pct"
|
||||||
|
json_add_int "disk_percent" "$disk_pct"
|
||||||
|
json_close_object
|
||||||
|
|
||||||
|
# Get recent alerts (simplified)
|
||||||
|
json_add_array "alerts"
|
||||||
|
for module in $MODULES; do
|
||||||
|
local is_installed=$(check_module_installed "$module")
|
||||||
|
local is_running=$(check_module_running "$module")
|
||||||
|
|
||||||
|
if [ "$is_installed" = "1" ] && [ "$is_running" != "1" ]; then
|
||||||
|
config_load secubox
|
||||||
|
local name
|
||||||
|
config_get name "$module" name "$module"
|
||||||
|
|
||||||
|
json_add_object ""
|
||||||
|
json_add_string "module" "$module"
|
||||||
|
json_add_string "message" "$name is not running"
|
||||||
|
json_add_string "severity" "warning"
|
||||||
|
json_close_object
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
json_close_array
|
||||||
|
|
||||||
|
json_add_int "timestamp" "$(date +%s)"
|
||||||
json_dump
|
json_dump
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,6 +701,15 @@ case "$1" in
|
|||||||
json_close_object
|
json_close_object
|
||||||
json_add_object "diagnostics"
|
json_add_object "diagnostics"
|
||||||
json_close_object
|
json_close_object
|
||||||
|
json_add_object "get_system_health"
|
||||||
|
json_close_object
|
||||||
|
json_add_object "get_alerts"
|
||||||
|
json_close_object
|
||||||
|
json_add_object "quick_action"
|
||||||
|
json_add_string "action" "string"
|
||||||
|
json_close_object
|
||||||
|
json_add_object "get_dashboard_data"
|
||||||
|
json_close_object
|
||||||
json_dump
|
json_dump
|
||||||
;;
|
;;
|
||||||
call)
|
call)
|
||||||
@ -454,6 +756,21 @@ case "$1" in
|
|||||||
diagnostics)
|
diagnostics)
|
||||||
get_diagnostics
|
get_diagnostics
|
||||||
;;
|
;;
|
||||||
|
get_system_health)
|
||||||
|
get_system_health
|
||||||
|
;;
|
||||||
|
get_alerts)
|
||||||
|
get_alerts
|
||||||
|
;;
|
||||||
|
quick_action)
|
||||||
|
read -r input
|
||||||
|
json_load "$input"
|
||||||
|
json_get_var action action ""
|
||||||
|
quick_action "$action"
|
||||||
|
;;
|
||||||
|
get_dashboard_data)
|
||||||
|
get_dashboard_data
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo '{"error":"Unknown method"}'
|
echo '{"error":"Unknown method"}'
|
||||||
;;
|
;;
|
||||||
|
|||||||
@ -1,7 +1,30 @@
|
|||||||
{
|
{
|
||||||
"luci-app-secubox": {
|
"luci-app-secubox": {
|
||||||
"description": "SecuBox Dashboard",
|
"description": "SecuBox Dashboard",
|
||||||
"read": {"ubus": {"luci.secubox": ["status", "modules"]}},
|
"read": {
|
||||||
"write": {}
|
"ubus": {
|
||||||
|
"luci.secubox": [
|
||||||
|
"status",
|
||||||
|
"modules",
|
||||||
|
"modules_by_category",
|
||||||
|
"module_info",
|
||||||
|
"health",
|
||||||
|
"diagnostics",
|
||||||
|
"get_system_health",
|
||||||
|
"get_alerts",
|
||||||
|
"get_dashboard_data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"write": {
|
||||||
|
"ubus": {
|
||||||
|
"luci.secubox": [
|
||||||
|
"start_module",
|
||||||
|
"stop_module",
|
||||||
|
"restart_module",
|
||||||
|
"quick_action"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user