feat(secubox): Add P2P Hub API and wizard-first menu

- Make Setup Wizard the first menu item in SecuBox (order 5)
- Add P2P Hub collaborative catalog API methods:
  - Peer discovery and management
  - Catalog sharing between SecuBox instances
  - Settings for P2P sharing preferences
- Fix crowdsec-dashboard theme.js to return class instead of instance
- Update views to properly instantiate theme class

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-01-30 09:27:56 +01:00
parent 19e8a67acd
commit 2d15c641f1
5 changed files with 96 additions and 24 deletions

View File

@ -12,9 +12,12 @@
* - cyberpunk: Neon glow effects with orange/cyan accents
*
* Profiles can extend themes with custom configurations
*
* Usage: var theme = new (require('crowdsec-dashboard.theme'))();
* theme.init().then(function() { ... });
*/
var ThemeManager = baseclass.extend({
return baseclass.extend({
// Available themes
themes: {
'classic': {
@ -241,5 +244,3 @@ var ThemeManager = baseclass.extend({
return 'cs-dashboard theme-' + (this.currentTheme || 'classic');
}
});
return new ThemeManager();

View File

@ -5,7 +5,7 @@
'require ui';
'require uci';
'require crowdsec-dashboard.api as api';
'require crowdsec-dashboard.theme as theme';
'require crowdsec-dashboard.theme as ThemeClass';
/**
* CrowdSec SOC Dashboard - Overview
@ -13,12 +13,16 @@
* Version 1.1.0
*/
var themeInstance = new ThemeClass();
return view.extend({
title: _('CrowdSec SOC'),
theme: themeInstance,
load: function() {
var self = this;
return Promise.all([
theme.init(),
self.theme.init(),
api.getOverview().catch(function() { return {}; })
]);
},
@ -30,7 +34,7 @@ return view.extend({
// Apply theme class
document.body.classList.add('cs-fullwidth');
var view = E('div', { 'class': theme.getDashboardClass() }, [
var view = E('div', { 'class': self.theme.getDashboardClass() }, [
this.renderHeader(status),
this.renderNav('overview'),
E('div', { 'id': 'cs-stats' }, this.renderStats(status)),

View File

@ -4,7 +4,7 @@
'require ui';
'require uci';
'require crowdsec-dashboard.api as api';
'require crowdsec-dashboard.theme as theme';
'require crowdsec-dashboard.theme as ThemeClass';
/**
* CrowdSec SOC - Settings View
@ -12,15 +12,19 @@
* With theme/appearance settings
*/
var themeInstance = new ThemeClass();
return view.extend({
title: _('Settings'),
status: {},
machines: [],
collections: [],
theme: themeInstance,
load: function() {
var self = this;
return Promise.all([
theme.init(),
self.theme.init(),
api.getStatus(),
api.getMachines(),
api.getCollections(),
@ -42,7 +46,7 @@ return view.extend({
document.body.classList.add('cs-fullwidth');
return E('div', { 'class': theme.getDashboardClass() }, [
return E('div', { 'class': self.theme.getDashboardClass() }, [
this.renderHeader(),
this.renderNav('settings'),
E('div', { 'class': 'cs-stats' }, this.renderServiceStats()),
@ -89,8 +93,8 @@ return view.extend({
var currentTheme = uci.get('crowdsec-dashboard', 'main', 'theme') || 'classic';
var currentProfile = uci.get('crowdsec-dashboard', 'main', 'profile') || 'default';
var themes = theme.getThemes();
var profiles = theme.getProfiles();
var themes = this.theme.getThemes();
var profiles = this.theme.getProfiles();
return E('div', {}, [
E('div', { 'style': 'margin-bottom: 16px;' }, [
@ -127,11 +131,11 @@ return view.extend({
},
previewTheme: function(themeName) {
theme.switchTheme(themeName);
this.theme.switchTheme(themeName);
},
previewProfile: function(profileName) {
theme.switchProfile(profileName);
this.theme.switchProfile(profileName);
},
saveAppearance: function() {

View File

@ -227,6 +227,60 @@ var callRemoveAppstoreApp = rpc.declare({
expect: { success: false }
});
// P2P Hub methods - Collaborative peer-to-peer app catalog sharing
var callGetP2PPeers = rpc.declare({
object: 'luci.secubox',
method: 'p2p_get_peers',
expect: { peers: [] }
});
var callP2PDiscover = rpc.declare({
object: 'luci.secubox',
method: 'p2p_discover',
expect: { peers: [], discovered: 0 }
});
var callP2PAddPeer = rpc.declare({
object: 'luci.secubox',
method: 'p2p_add_peer',
params: ['address', 'name'],
expect: { success: false }
});
var callP2PRemovePeer = rpc.declare({
object: 'luci.secubox',
method: 'p2p_remove_peer',
params: ['peer_id'],
expect: { success: false }
});
var callP2PGetPeerCatalog = rpc.declare({
object: 'luci.secubox',
method: 'p2p_get_peer_catalog',
params: ['peer_id'],
expect: { apps: [] }
});
var callP2PShareCatalog = rpc.declare({
object: 'luci.secubox',
method: 'p2p_share_catalog',
params: ['enabled'],
expect: { success: false }
});
var callP2PGetSettings = rpc.declare({
object: 'luci.secubox',
method: 'p2p_get_settings',
expect: { }
});
var callP2PSetSettings = rpc.declare({
object: 'luci.secubox',
method: 'p2p_set_settings',
params: ['settings'],
expect: { success: false }
});
function formatUptime(seconds) {
if (!seconds) return '0s';
var d = Math.floor(seconds / 86400);
@ -284,6 +338,15 @@ return baseclass.extend({
getAppstoreApp: callGetAppstoreApp,
installAppstoreApp: callInstallAppstoreApp,
removeAppstoreApp: callRemoveAppstoreApp,
// P2P Hub - Collaborative catalog sharing
getP2PPeers: callGetP2PPeers,
p2pDiscover: callP2PDiscover,
p2pAddPeer: callP2PAddPeer,
p2pRemovePeer: callP2PRemovePeer,
p2pGetPeerCatalog: callP2PGetPeerCatalog,
p2pShareCatalog: callP2PShareCatalog,
p2pGetSettings: callP2PGetSettings,
p2pSetSettings: callP2PSetSettings,
// Utilities
formatUptime: formatUptime,
formatBytes: formatBytes

View File

@ -9,6 +9,17 @@
"acl": ["luci-app-secubox"]
}
},
"admin/secubox/wizard": {
"title": "Setup Wizard",
"order": 5,
"action": {
"type": "view",
"path": "secubox/wizard"
},
"depends": {
"acl": ["luci-app-secubox"]
}
},
"admin/secubox/dashboard": {
"title": "Dashboard",
"order": 10,
@ -20,17 +31,6 @@
"acl": ["luci-app-secubox"]
}
},
"admin/secubox/wizard": {
"title": "First-Run Wizard",
"order": 15,
"action": {
"type": "view",
"path": "secubox/wizard"
},
"depends": {
"acl": ["luci-app-secubox"]
}
},
"admin/secubox/apps": {
"title": "App Store",
"order": 18,