feat: Add help system integration and fix menu structure

- Created help system (help.js, help.css) for all modules
- Integrated help button in network-modes module
- Fixed menu structure: removed empty Network Management category
- Fixed all dashboard and modules page links
- Added website deployment script
- Created comprehensive documentation

New Files:
- DOCS/HELP_INTEGRATION_PLAN.md
- DOCS/WEBSITE_DEPLOYMENT_GUIDE.md
- EXAMPLES/help-button-integration.js
- luci-app-secubox/htdocs/luci-static/resources/secubox/help.js
- luci-app-secubox/htdocs/luci-static/resources/secubox/help.css
- secubox-tools/deploy-website.sh

Modified:
- luci-app-network-modes: Added help button integration
- luci-app-secubox: Fixed menu paths and module links

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2025-12-28 16:29:04 +01:00
parent 41947c5ae0
commit 6314884f00
22 changed files with 2648 additions and 249 deletions

View File

@ -1,164 +1,59 @@
# SecuBox Project Context for Claude AI
# SecuBox Context
## 🎯 Project Identity
## What SecuBox OpenWrt Suite Is
SecuBox is a suite of LuCI applications that ship advanced security, monitoring, and automation dashboards for OpenWrt routers. Each `luci-app-*` package combines LuCI JavaScript views, RPCD backends, UCI integration, ACL policies, and shared CSS built on the SecuBox design system (dark-first palette, Inter + JetBrains Mono). GitHub Actions builds the packages for every supported architecture (`x86`, `ARM`, `MIPS`) and the repo also carries tooling for validation, repair, deployment, and firmware image creation.
**Name**: SecuBox
**Type**: Modular security suite for OpenWrt routers
**Version**: 1.0.0
**Author**: CyberMind.fr (Gandalf)
**License**: Apache-2.0
## Repository Layout
- `.claude/` authoritative assistant guidance, prompts, and settings
- `.github/workflows/` CI definitions (package build matrix, validation, firmware images)
- `luci-app-*/` one directory per LuCI module (Makefile, README, `htdocs/`, `root/`)
- `secubox-tools/` validation/build/deploy helpers (`local-build.sh`, `validate-modules.sh`, etc.)
- `templates/` scaffolding for new LuCI packages
- Root docs: `README.md`, `QUICK-START.md`, `DEVELOPMENT-GUIDELINES.md`, `CLAUDE.md`, `DOCUMENTATION-INDEX.md`, `CODE-TEMPLATES.md`, `FEATURE-REGENERATION-PROMPTS.md`, `MODULE_STATUS.md`, `PERMISSIONS-GUIDE.md`, `VALIDATION-GUIDE.md`, etc.
- Deploy scripts: `deploy-module-template.sh`, `deploy-*.sh` (system hub, secubox, beta releases, etc.)
- Test fixtures: `test-direct.js`, `test-modules-simple.js`
## 🏗️ Architecture Overview
## Module Map (Purpose & Entry Points)
Each module follows the same structure: `Makefile`, module-specific README, JavaScript views under `htdocs/luci-static/resources/view/<module>/`, API helpers under `htdocs/luci-static/resources/<module>/api.js`, CSS in the same folder, RPCD backend in `root/usr/libexec/rpcd/luci.<module>`, menu JSON under `root/usr/share/luci/menu.d/`, and ACL JSON under `root/usr/share/rpcd/acl.d/`.
```
┌─────────────────────────────────────────────────────────────┐
│ LuCI Web Interface │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ View.js │ │ View.js │ │ View.js │ │ View.js │ ... │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ └───────────┴─────┬─────┴───────────┘ │
│ │ JSON-RPC │
├─────────────────────────┼───────────────────────────────────┤
│ RPCD Daemon │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Script │ │ Script │ │ Script │ │ Script │ ... │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
├───────┼───────────┼───────────┼───────────┼─────────────────┤
│ │ UCI │ Shell │ System │ │
│ │ Config │ Commands │ Services │ │
└───────┴───────────┴───────────┴───────────┴─────────────────┘
```
| Module | Purpose | Primary Views (JS) |
|--------|---------|--------------------|
| `luci-app-secubox` | Central SecuBox hub (module launcher, dashboard, dev status) | `secubox/dashboard.js`, `modules.js`, `modules-minimal.js`, `dev-status.js`, `alerts.js`, `monitoring.js`, `settings.js`
| `luci-app-system-hub` | System control center (health, services, diagnostics, remote) | `system-hub/overview.js`, `health.js`, `services.js`, `components.js`, `logs.js`, `backup.js`, `diagnostics.js`, `remote.js`, `settings.js`, `dev-status.js`
| `luci-app-crowdsec-dashboard` | CrowdSec decision, alerts, bouncer management | `crowdsec-dashboard/overview.js`, `alerts.js`, `decisions.js`, `bouncers.js`, `metrics.js`, `settings.js`
| `luci-app-netdata-dashboard` | Netdata monitoring integration | `netdata-dashboard/dashboard.js`, `system.js`, `network.js`, `processes.js`, `realtime.js`, `settings.js`
| `luci-app-netifyd-dashboard` | DPI / application intelligence | `netifyd-dashboard/overview.js`, `applications.js`, `devices.js`, `flows.js`, `risks.js`, `talkers.js`, `settings.js`
| `luci-app-network-modes` | Switch router/AP/bridge/sniffer modes | `network-modes/overview.js`, `wizard.js`, `sniffer.js`, `accesspoint.js`, `relay.js`, `router.js`, `settings.js`
| `luci-app-wireguard-dashboard` | WireGuard VPN monitoring/config | `wireguard-dashboard/overview.js`, `peers.js`, `traffic.js`, `config.js`, `settings.js`, `qrcodes.js`
| `luci-app-client-guardian` | NAC + captive portal + parental controls | `client-guardian/overview.js`, `clients.js`, `zones.js`, `portal.js`, `captive.js`, `alerts.js`, `parental.js`, `settings.js`, `logs.js`
| `luci-app-auth-guardian` | Authentication/voucher/OAuth portal | `auth-guardian/overview.js`, `sessions.js`, `vouchers.js`, `oauth.js`, `splash.js`, `bypass.js`
| `luci-app-bandwidth-manager` | QoS, quotas, priority classes | `bandwidth-manager/overview.js`, `classes.js`, `rules.js`, `schedules.js`, `media.js`, `clients.js`, `usage.js`, `quotas.js`, `settings.js`
| `luci-app-media-flow` | Streaming/media traffic analytics | `media-flow/dashboard.js`, `services.js`, `clients.js`, `history.js`, `alerts.js`
| `luci-app-cdn-cache` | Local CDN cache policies & stats | `cdn-cache/overview.js`, `policies.js`, `cache.js`, `statistics.js`, `maintenance.js`, `settings.js`
| `luci-app-vhost-manager` | Virtual hosts & SSL orchestration | `vhost-manager/overview.js`, `vhosts.js`, `internal.js`, `redirects.js`, `ssl.js`, `certificates.js`, `logs.js`
| `luci-app-traffic-shaper` | Advanced traffic shaping presets | `traffic-shaper/overview.js`, `classes.js`, `rules.js`, `stats.js`, `presets.js`
| `luci-app-ksm-manager` | Secure key/certificate management | `ksm-manager/overview.js`, `keys.js`, `secrets.js`, `certificates.js`, `ssh.js`, `hsm.js`, `audit.js`, `settings.js`
## 📁 Module Structure Template
(Modules not listed explicitly above share the same structure; inspect each `luci-app-*/htdocs/luci-static/resources/view/<module>/` directory for the definitive entrypoints.)
```
luci-app-{module-name}/
├── Makefile # OpenWrt package definition
├── README.md # Module documentation
├── htdocs/
│ └── luci-static/
│ └── resources/
│ └── view/
│ └── {module_name}/ # Underscore version
│ ├── main.js # Main view
│ └── {subview}.js # Optional subviews
└── root/
├── etc/
│ ├── config/
│ │ └── {module_name} # UCI configuration
│ ├── init.d/
│ │ └── {module_name} # Service init script (optional)
│ └── uci-defaults/
│ └── 99-{module_name} # First-run setup
└── usr/
├── libexec/
│ └── rpcd/
│ └── {module-name} # Hyphen version - RPCD backend
└── share/
├── luci/
│ └── menu.d/
│ └── luci-app-{module-name}.json
└── rpcd/
└── acl.d/
└── luci-app-{module-name}.json
```
## Stack & Integration Points
- **Frontend**: LuCI JavaScript views (`view.extend`) + SecuBox design system CSS. Every view imports the per-module `api.js` module for ubus calls and includes shared styles like `system-hub/common.css`.
- **Backend**: RPCD shell scripts under `root/usr/libexec/rpcd/luci.<module>` expose ubus methods (`status`, `get_*`, `set_*`, etc.). Modules often also ship helper scripts under `/usr/libexec/secubox/` and UCI defaults under `root/etc/uci-defaults/`.
- **UBus / RPC**: JavaScript uses `rpc.declare` with `object: 'luci.<module>'`. RPCD `list` and `call` cases must mirror these names.
- **Menu/ACL**: JSON files in `root/usr/share/luci/menu.d/` and `root/usr/share/rpcd/acl.d/` keep navigation and permissions consistent with the views and RPCD backend.
- **Packaging**: OpenWrt LuCI package Makefiles include `luci.mk`, define `PKG_FILE_MODES` for executable scripts (typically RPCD 755), and mark packages as `LUCI_PKGARCH:=all` because they are script-only.
## 📋 Naming Conventions
| Context | Format | Example |
|---------|--------|---------|
| Package name | luci-app-{module-name} | luci-app-vhost-manager |
| RPCD script | {module-name} | vhost-manager |
| UCI config | {module_name} | vhost_manager |
| View path | {module_name}/ | vhost_manager/ |
| ubus object | luci.{module-name} | luci.vhost-manager |
| Menu path | admin/services/{module_name} | admin/services/vhost_manager |
## 🔧 Code Standards
### Makefile Template
```makefile
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-{module-name}
PKG_VERSION:=1.0.0
PKG_RELEASE:=1
PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=CyberMind <contact@cybermind.fr>
LUCI_TITLE:=LuCI - {Module Title}
LUCI_DESCRIPTION:={Description}
LUCI_DEPENDS:=+luci-base +rpcd {+other-deps}
LUCI_PKGARCH:=all
include $(TOPDIR)/feeds/luci/luci.mk
```
### RPCD Script Template
```sh
#!/bin/sh
# RPCD backend for {module-name}
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
json_init
case "$1" in
list)
# MUST list all available methods
json_add_object "status"
json_close_object
json_add_object "get_config"
json_close_object
json_add_object "set_config"
json_add_string "config" "object"
json_close_object
# Add more methods here
json_dump
;;
call)
case "$2" in
status)
# MUST implement status method
json_add_string "module" "{module-name}"
json_add_string "version" "2.0.0"
json_add_boolean "enabled" 1
json_add_string "status" "running"
json_dump
;;
get_config)
# Read from UCI
json_add_object "config"
# config_load "{module_name}"
json_close_object
json_dump
;;
set_config)
read -r input
json_load "$input"
# Apply to UCI
json_init
json_add_boolean "success" 1
json_dump
;;
*)
json_add_int "error" -32601
json_add_string "message" "Method not found"
json_dump
;;
esac
;;
esac
```
## Glossary
- **LuCI** OpenWrt web interface framework (Lua backend + JS frontend)
- **RPCD** Daemon providing ubus RPC endpoints; modules drop scripts in `/usr/libexec/rpcd/`
- **ubus** OpenWrt message bus used for remote procedure calls
- **UCI** Unified Configuration Interface (files in `/etc/config/`)
- **ACL** RPCD permission JSON files in `/usr/share/rpcd/acl.d/`
- **PKG_FILE_MODES** Makefile variable forcing specific permissions for installed files
- **SecuBox Design System** Shared CSS variables (`--sh-*`) and components defined in `system-hub/common.css`
- **Validation suite** `./secubox-tools/validate-modules.sh`, `validate-module-generation.sh`, `pre-push-validation.sh`
- **Deploy script** `deploy-module-template.sh` (backup, copy JS/CSS/RPCD/menu/ACL, fix perms, restart services)
- **Fix permissions** Toujours lancer `./secubox-tools/fix-permissions.sh --local` avant commit et `--remote <routeur>` après déploiement pour garantir `644` sur CSS/JS et `755` sur scripts exécutables
### ACL File Template

View File

@ -53,3 +53,4 @@ Each module follows the same structure: `Makefile`, module-specific README, Java
- **SecuBox Design System** Shared CSS variables (`--sh-*`) and components defined in `system-hub/common.css`
- **Validation suite** `./secubox-tools/validate-modules.sh`, `validate-module-generation.sh`, `pre-push-validation.sh`
- **Deploy script** `deploy-module-template.sh` (backup, copy JS/CSS/RPCD/menu/ACL, fix perms, restart services)
- **Fix permissions** Always run `./secubox-tools/fix-permissions.sh --local` before committing and `--remote <router>` after deploying to enforce `644` web assets / `755` executables

View File

@ -0,0 +1,441 @@
# SecuBox Website Help/Info Button Integration Plan
**Version:** 1.0
**Date:** 2025-12-28
**Status:** Planning Phase
## Overview
This document outlines the strategy for integrating the SecuBox marketing/documentation website with the OpenWrt LuCI modules, providing seamless access to help documentation via help/info buttons in each module.
## Current Architecture
### Website Location
- **Remote URL:** `https://secubox.cybermood.eu/`
- **Local Router Path:** `/www/luci-static/secubox/`
- **Access URL:** `http://[router-ip]/luci-static/secubox/`
### Module Structure
All SecuBox modules follow a consistent pattern:
```
luci-app-{module-name}/
├── htdocs/luci-static/resources/
│ ├── view/{module-name}/
│ │ ├── overview.js (main dashboard)
│ │ └── *.js (other views)
│ └── {module-name}/
│ ├── api.js
│ ├── theme.js (optional)
│ └── *.css
```
### Key Modules
1. **luci-app-secubox** - Central control hub
2. **luci-app-system-hub** - System monitoring
3. **luci-app-network-modes** - Network configuration
4. **luci-app-client-guardian** - Client management
5. **luci-app-bandwidth-manager** - Traffic shaping
6. **luci-app-cdn-cache** - CDN caching
7. **luci-app-traffic-shaper** - QoS management
8. **luci-app-wireguard-dashboard** - VPN management
9. **luci-app-crowdsec-dashboard** - Security monitoring
10. **luci-app-netdata-dashboard** - Performance metrics
## Integration Strategy
### Phase 1: Shared Help Utilities (RECOMMENDED)
Create a centralized help button library that all modules can use.
#### Implementation Steps
1. **Create Shared Help Module**
```javascript
// Location: luci-app-secubox/htdocs/luci-static/resources/secubox/help.js
'use strict';
'require baseclass';
return baseclass.extend({
/**
* Create a help button element
* @param {string} moduleName - Module identifier (e.g., 'network-modes')
* @param {string} position - Button position: 'header', 'footer', 'floating'
* @param {object} options - Custom options
*/
createHelpButton: function(moduleName, position, options) {
var opts = options || {};
var helpUrl = this.getHelpUrl(moduleName);
var buttonClass = 'sb-help-btn sb-help-' + position;
return E('a', {
'class': buttonClass,
'href': helpUrl,
'target': opts.target || '_blank',
'title': opts.title || _('View Help & Documentation')
}, [
E('span', { 'class': 'sb-help-icon' }, opts.icon || '❓'),
opts.showLabel !== false ? E('span', { 'class': 'sb-help-label' }, opts.label || _('Help')) : null
]);
},
/**
* Get help URL for a module
* @param {string} moduleName - Module identifier
*/
getHelpUrl: function(moduleName) {
var baseUrl = '/luci-static/secubox/';
var moduleMap = {
'secubox': 'index.html#modules',
'system-hub': 'demo-secubox-hub.html',
'network-modes': 'demo-network-modes.html',
'client-guardian': 'demo-client-guardian.html',
'bandwidth-manager': 'demo-bandwidth.html',
'cdn-cache': 'demo-cdn-cache.html',
'traffic-shaper': 'demo-traffic-shaper.html',
'wireguard-dashboard': 'demo-wireguard.html',
'crowdsec-dashboard': 'demo-crowdsec.html',
'netdata-dashboard': 'demo-netdata.html',
'netifyd-dashboard': 'demo-netifyd.html',
'auth-guardian': 'demo-auth.html',
'vhost-manager': 'demo-vhost.html',
'ksm-manager': 'demo-ksm-manager.html',
'media-flow': 'demo-media.html'
};
return baseUrl + (moduleMap[moduleName] || 'index.html');
},
/**
* Open help in modal (for inline help)
* @param {string} moduleName - Module identifier
*/
openHelpModal: function(moduleName) {
var helpUrl = this.getHelpUrl(moduleName);
var iframe = E('iframe', {
'src': helpUrl,
'style': 'width: 100%; height: 70vh; border: none; border-radius: 8px;'
});
ui.showModal(_('Help & Documentation'), [
E('div', { 'style': 'min-height: 70vh;' }, [iframe]),
E('div', { 'class': 'right', 'style': 'margin-top: 1rem;' }, [
E('button', {
'class': 'btn',
'click': ui.hideModal
}, _('Close'))
])
]);
}
});
```
2. **Create Common CSS Styles**
```css
/* Location: luci-app-secubox/htdocs/luci-static/resources/secubox/help.css */
/* Base Help Button Styles */
.sb-help-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
transition: all 0.3s ease;
border: 2px solid transparent;
cursor: pointer;
}
.sb-help-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
border-color: rgba(255, 255, 255, 0.3);
}
.sb-help-icon {
font-size: 1.2em;
}
/* Header Position */
.sb-help-header {
margin-left: auto;
padding: 0.4rem 0.8rem;
font-size: 0.9em;
}
/* Footer Position */
.sb-help-footer {
margin-top: 2rem;
}
/* Floating Button (bottom-right) */
.sb-help-floating {
position: fixed;
bottom: 2rem;
right: 2rem;
z-index: 1000;
border-radius: 50%;
width: 60px;
height: 60px;
padding: 0;
justify-content: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.sb-help-floating .sb-help-label {
display: none;
}
.sb-help-floating .sb-help-icon {
font-size: 1.8em;
}
/* Dark theme adjustments */
[data-theme="dark"] .sb-help-btn {
background: linear-gradient(135deg, #4c51bf 0%, #553c9a 100%);
}
```
3. **Update Each Module**
**Example: luci-app-network-modes/htdocs/luci-static/resources/view/network-modes/overview.js**
```javascript
'use strict';
'require view';
'require dom';
'require ui';
'require network-modes.api as api';
'require secubox/help as Help'; // ADD THIS
return view.extend({
title: _('Network Modes'),
load: function() {
return api.getAllData();
},
render: function(data) {
var self = this;
// ... existing code ...
var view = E('div', { 'class': 'network-modes-dashboard' }, [
// Load help CSS
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox/help.css') }),
// Header with help button
E('div', { 'class': 'nm-header' }, [
E('div', { 'class': 'nm-logo' }, [
E('div', { 'class': 'nm-logo-icon' }, '🌐'),
E('div', { 'class': 'nm-logo-text' }, ['Network ', E('span', {}, 'Configuration')])
]),
E('div', { 'class': 'nm-mode-badge ' + currentMode }, [
E('span', { 'class': 'nm-mode-dot' }),
currentModeInfo ? currentModeInfo.name : currentMode
]),
// ADD HELP BUTTON
Help.createHelpButton('network-modes', 'header', {
icon: '📖',
label: _('Help')
})
]),
// ... rest of the UI ...
]);
return view;
}
});
```
### Phase 2: Alternative Approaches
#### Approach A: Floating Help Button
Add a global floating help button that appears on all SecuBox module pages.
**Pros:**
- Non-intrusive
- Consistent UX across all modules
- Easy to implement globally
**Cons:**
- May overlap with other floating elements
- Less discoverable
#### Approach B: Header Integration
Add help buttons to the header of each module dashboard.
**Pros:**
- Highly visible
- Natural placement
- Follows common UI patterns
**Cons:**
- Requires modifications to each module
- May clutter header on small screens
#### Approach C: Quick Actions Integration
Add help as a quick action in modules that have action panels (like SecuBox dashboard).
**Pros:**
- Fits existing UI pattern
- Grouped with other utilities
- Consistent with current design
**Cons:**
- Only works for modules with action panels
- Less prominent
## Recommended Implementation Plan
### Step 1: Create Foundation (Week 1)
1. Create `secubox/help.js` utility module
2. Create `secubox/help.css` stylesheet
3. Deploy to test router
4. Verify accessibility
### Step 2: Integrate Core Modules (Week 2)
Update these critical modules first:
1. `luci-app-secubox` (main dashboard)
2. `luci-app-system-hub`
3. `luci-app-network-modes`
Test on production router.
### Step 3: Roll Out to All Modules (Week 3)
Update remaining modules:
1. `luci-app-client-guardian`
2. `luci-app-bandwidth-manager`
3. `luci-app-cdn-cache`
4. `luci-app-traffic-shaper`
5. `luci-app-wireguard-dashboard`
6. `luci-app-crowdsec-dashboard`
7. `luci-app-netdata-dashboard`
8. Other modules
### Step 4: User Testing & Refinement (Week 4)
1. Gather user feedback
2. Adjust positioning/styling
3. Add localization if needed
4. Document for end users
## Module-to-Help Page Mapping
| Module | Help Page | Status |
|--------|-----------|--------|
| secubox | index.html#modules | Available |
| system-hub | demo-secubox-hub.html | Available |
| network-modes | demo-network-modes.html | Available |
| client-guardian | demo-client-guardian.html | Available |
| bandwidth-manager | demo-bandwidth.html | Available |
| cdn-cache | demo-cdn-cache.html | Available |
| traffic-shaper | demo-traffic-shaper.html | Available |
| wireguard-dashboard | demo-wireguard.html | Available |
| crowdsec-dashboard | demo-crowdsec.html | Available |
| netdata-dashboard | demo-netdata.html | Available |
| netifyd-dashboard | demo-netifyd.html | Available |
| auth-guardian | demo-auth.html | Available |
| vhost-manager | demo-vhost.html | Available |
| ksm-manager | demo-ksm-manager.html | Available |
| media-flow | demo-media.html | Available |
## Deployment Workflow
### Website Updates
```bash
# From secubox-openwrt directory
./secubox-tools/deploy-website.sh root@192.168.8.191 ../secubox-website
```
### Module Updates with Help Integration
```bash
# Build and deploy individual module
./secubox-tools/deploy-network-modes.sh root@192.168.8.191
# Or build all modules
./secubox-tools/local-build.sh build-all
```
## Testing Checklist
- [ ] Help button appears in module header
- [ ] Help button links to correct documentation page
- [ ] Help page opens in new tab (or modal if configured)
- [ ] Styling is consistent across all modules
- [ ] Button is responsive on mobile devices
- [ ] Dark/light theme support
- [ ] Localization support (if applicable)
- [ ] No JavaScript errors in console
- [ ] Works on both local router and remote deployment
## Future Enhancements
### Enhanced Features
1. **Context-Sensitive Help**
- Different help URLs based on current page/section
- Deep linking to specific documentation sections
2. **Inline Help Tooltips**
- Hover tooltips for specific UI elements
- Quick tips without leaving page
3. **Help Search**
- Search box in help modal
- Full-text search across documentation
4. **Interactive Tutorials**
- Step-by-step walkthroughs
- Guided tours for new users
5. **Changelog Integration**
- Show "What's New" on version updates
- Link to release notes
## Technical Considerations
### Performance
- Help resources are static files (no API calls)
- Minimal JavaScript overhead (~2KB)
- CSS loaded only when needed
- No impact on module core functionality
### Compatibility
- Works with LuCI 18.06+
- Compatible with all modern browsers
- Graceful degradation for older browsers
### Security
- All help content served from same origin
- No external dependencies
- No XSS risks (static HTML/CSS/JS)
### Maintenance
- Centralized help utility (single point of update)
- Module changes are minimal (1-3 lines per module)
- Website updates independent of module updates
## References
- **Deployment Script:** `secubox-tools/deploy-website.sh`
- **Module Template:** `secubox-tools/deploy-module-template.sh`
- **Website Repository:** `/home/reepost/CyberMindStudio/_files/secubox-website/`
- **Current Deployment:** `http://192.168.8.191/luci-static/secubox/`
## Questions & Decisions Needed
1. **Button Position:** Header, Floating, or both?
2. **Modal vs New Tab:** Should help open in modal or new tab?
3. **Mobile UX:** How should help button behave on small screens?
4. **Localization:** Support multiple languages for help content?
5. **Analytics:** Track help usage (privacy-respecting)?
## Approval Status
- [ ] Technical approach approved
- [ ] UI/UX design approved
- [ ] Implementation timeline approved
- [ ] Testing plan approved
- [ ] Deployment strategy approved

View File

@ -150,8 +150,8 @@
- **Use Cases**: Traffic analysis, bandwidth optimization, security monitoring
#### luci-app-network-modes
- **Version**: 0.3.1-1
- **Status**: ✅ In Heavily Development Stage
- **Version**: 0.3.5-1
- **Status**: ✅ Production Ready
- **Description**: Dynamic network mode switching and configuration
- **Views**: 7 (overview, wizard, router, relay, accesspoint, sniffer, settings)
- **JavaScript Lines**: 2,104
@ -171,8 +171,8 @@
- DHCP server/client mode switching
- Interface bridging automation
- **Recent Updates**:
- v0.3.1: Enhanced mode switching logic
- Improved configuration persistence
- v0.3.5: Auto-deploy proxies (Squid/TinyProxy/Privoxy), DoH, nginx vhosts, and Lets Encrypt certificates
- Auto-apply advanced WiFi (802.11r/k/v, band steering) and tcpdump packet capture per mode
- **Integration**: network, firewall, DHCP, hostapd/wpa_supplicant
---

View File

@ -0,0 +1,361 @@
# SecuBox Website Deployment Guide
**Version:** 1.0
**Date:** 2025-12-28
## Overview
This guide explains how to deploy the SecuBox marketing/documentation website to an OpenWrt router, making it accessible locally for help and documentation purposes.
## Prerequisites
- OpenWrt router with SSH access
- SecuBox website files (from `secubox-website` repository)
- Network connectivity to router
- Sufficient storage space on router (approx. 1-2 MB)
## Deployment Script
### Location
```
secubox-openwrt/secubox-tools/deploy-website.sh
```
### Usage
#### Basic Deployment
```bash
# Deploy to default router (192.168.1.1)
./secubox-tools/deploy-website.sh
# Deploy to specific router
./secubox-tools/deploy-website.sh root@192.168.8.191
# Deploy from specific website directory
./secubox-tools/deploy-website.sh root@192.168.8.191 /path/to/secubox-website
```
#### Full Example
```bash
cd /home/reepost/CyberMindStudio/_files/secubox-openwrt
# Deploy website to router at 192.168.8.191
./secubox-tools/deploy-website.sh root@192.168.8.191 ../secubox-website
```
### What the Script Does
1. **Prepares Files** - Creates compressed archive excluding:
- `.git` directory
- `.claude` directory
- Markdown files (*.md)
- README and LICENSE files
2. **Creates Backup** - Backs up existing website if present
3. **Deploys Files** - Uploads and extracts to `/www/luci-static/secubox/`
4. **Sets Permissions** - Ensures proper file permissions:
- Directories: 755
- HTML files: 644
- JavaScript files: 644
- CSS files: 644
5. **Cleanup** - Removes temporary files
## Website Structure on Router
### Directory Layout
```
/www/luci-static/secubox/
├── index.html (main landing page)
├── campaign.html
├── demo-*.html (module demos)
├── dev-status-widget.js
├── i18n.js
├── i18n/
│ └── *.json (language files)
└── blog/
└── *.html (blog posts)
```
### Access URLs
After deployment, the website is accessible at:
- **Local Router:** `http://[router-ip]/luci-static/secubox/`
- **Example:** `http://192.168.8.191/luci-static/secubox/`
#### Individual Pages
- Main: `http://192.168.8.191/luci-static/secubox/index.html`
- System Hub: `http://192.168.8.191/luci-static/secubox/demo-secubox-hub.html`
- Network Modes: `http://192.168.8.191/luci-static/secubox/demo-network-modes.html`
- Client Guardian: `http://192.168.8.191/luci-static/secubox/demo-client-guardian.html`
- etc.
## Deployment Workflow
### 1. Update Website Content
```bash
# Navigate to website directory
cd /home/reepost/CyberMindStudio/_files/secubox-website
# Edit files as needed
# Test locally if possible
```
### 2. Deploy to Router
```bash
# Navigate to OpenWrt directory
cd /home/reepost/CyberMindStudio/_files/secubox-openwrt
# Deploy
./secubox-tools/deploy-website.sh root@192.168.8.191
```
### 3. Verify Deployment
```bash
# Check files on router
ssh root@192.168.8.191 "ls -la /www/luci-static/secubox/"
# Test access via browser
curl http://192.168.8.191/luci-static/secubox/index.html
```
## Manual Deployment (Alternative)
If the script doesn't work, you can deploy manually:
```bash
# 1. Create tarball
cd /path/to/secubox-website
tar czf /tmp/secubox-website.tar.gz \
--exclude='.git' \
--exclude='.claude' \
--exclude='*.md' \
.
# 2. Upload to router
scp /tmp/secubox-website.tar.gz root@192.168.8.191:/tmp/
# 3. Extract on router
ssh root@192.168.8.191 << 'EOF'
mkdir -p /www/luci-static/secubox
cd /www/luci-static/secubox
tar xzf /tmp/secubox-website.tar.gz
chmod 755 .
find . -type d -exec chmod 755 {} \;
find . -type f -name "*.html" -exec chmod 644 {} \;
find . -type f -name "*.js" -exec chmod 644 {} \;
rm /tmp/secubox-website.tar.gz
EOF
# 4. Cleanup
rm /tmp/secubox-website.tar.gz
```
## Troubleshooting
### Issue: "No route to host"
**Solution:** Verify router IP address is correct
```bash
ping 192.168.8.191
```
### Issue: "Permission denied"
**Solution:** Ensure SSH access is configured
```bash
# Test SSH connection
ssh root@192.168.8.191 "echo 'Connected'"
```
### Issue: "Not enough space"
**Solution:** Check available storage
```bash
ssh root@192.168.8.191 "df -h /www"
# If needed, clear cache
ssh root@192.168.8.191 "rm -rf /tmp/luci-*"
```
### Issue: "Files not accessible via HTTP"
**Solution:** Check web server status
```bash
ssh root@192.168.8.191 "/etc/init.d/uhttpd status"
ssh root@192.168.8.191 "/etc/init.d/uhttpd restart"
```
### Issue: "404 Not Found"
**Solution:** Verify files exist and check permissions
```bash
ssh root@192.168.8.191 "ls -la /www/luci-static/secubox/ | head -20"
```
## Integration with Modules
Once deployed, modules can link to the help pages:
```javascript
// Example: Link to help in a module
var helpUrl = '/luci-static/secubox/demo-network-modes.html';
var helpButton = E('a', {
'href': helpUrl,
'target': '_blank',
'class': 'btn'
}, 'Help');
```
See `HELP_INTEGRATION_PLAN.md` for detailed integration guide.
## Maintenance
### Updating Website
To update the website after making changes:
```bash
# 1. Edit files in secubox-website/
cd /home/reepost/CyberMindStudio/_files/secubox-website
# ... make changes ...
# 2. Redeploy
cd ../secubox-openwrt
./secubox-tools/deploy-website.sh root@192.168.8.191
```
### Rollback
If deployment fails, restore from backup:
```bash
ssh root@192.168.8.191 << 'EOF'
# Find latest backup
BACKUP=$(ls -t /tmp/secubox-website-backup-* | head -1)
if [ -n "$BACKUP" ]; then
rm -rf /www/luci-static/secubox/*
cp -a $BACKUP/* /www/luci-static/secubox/
echo "Restored from $BACKUP"
fi
EOF
```
### Remove Website
To completely remove the website:
```bash
ssh root@192.168.8.191 "rm -rf /www/luci-static/secubox"
```
## Performance Optimization
### Enable Compression (Optional)
Configure uhttpd to serve compressed content:
```bash
ssh root@192.168.8.191 << 'EOF'
# Add gzip compression to uhttpd config
uci set uhttpd.main.compression='1'
uci commit uhttpd
/etc/init.d/uhttpd restart
EOF
```
### Cache Headers (Optional)
Add cache headers for static assets:
```bash
ssh root@192.168.8.191 << 'EOF'
# Create .htaccess-like configuration for caching
# (requires additional uhttpd configuration)
EOF
```
## Security Considerations
### Access Control
The website is publicly accessible on the router's LAN. To restrict access:
```bash
# Option 1: Firewall rules (restrict to specific IPs)
ssh root@192.168.8.191 << 'EOF'
# Add firewall rules as needed
EOF
# Option 2: HTTP authentication (requires uhttpd configuration)
```
### Content Security
- Website contains only static HTML/CSS/JavaScript
- No server-side execution
- No database connections
- No sensitive data exposure
## Automated Deployment
### Cron Job (Optional)
To auto-deploy on schedule:
```bash
# Add to router crontab
ssh root@192.168.8.191 "crontab -e"
# Add line (example: deploy daily at 3 AM):
# 0 3 * * * cd /tmp && wget http://server/secubox-website.tar.gz && tar xzf secubox-website.tar.gz -C /www/luci-static/secubox/
```
### Git Hook (Advanced)
Deploy automatically on git push:
```bash
# In secubox-website/.git/hooks/post-commit
#!/bin/bash
cd /home/reepost/CyberMindStudio/_files/secubox-openwrt
./secubox-tools/deploy-website.sh root@192.168.8.191
```
## Monitoring
### Check Deployment Status
```bash
# Verify files
ssh root@192.168.8.191 "find /www/luci-static/secubox -type f | wc -l"
# Check disk usage
ssh root@192.168.8.191 "du -sh /www/luci-static/secubox"
# View access logs (if logging enabled)
ssh root@192.168.8.191 "logread | grep uhttpd"
```
## Related Documentation
- **Help Integration:** `HELP_INTEGRATION_PLAN.md`
- **Module Development:** `LUCI_DEVELOPMENT_REFERENCE.md`
- **Deployment Scripts:** `secubox-tools/deploy-*.sh`
## Support
For issues or questions:
1. Check troubleshooting section above
2. Review router logs: `ssh root@router "logread"`
3. Test network connectivity
4. Verify file permissions
## Changelog
### v1.0 (2025-12-28)
- Initial deployment script
- Documentation created
- Tested on router 192.168.8.191
- Supports automatic website directory detection

140
EXAMPLES/README.md Normal file
View File

@ -0,0 +1,140 @@
# SecuBox Code Examples
This directory contains practical code examples for SecuBox module development and integration.
## Available Examples
### help-button-integration.js
Comprehensive examples for integrating help/documentation buttons into SecuBox modules.
**What's Included:**
- Shared help utility module
- Module integration examples
- Multiple UI patterns (header, floating, quick actions)
- Context-sensitive help
- CSS styling examples
**Use Cases:**
- Adding help buttons to module dashboards
- Linking to website documentation
- Creating consistent help UX across modules
## Related Documentation
- **Integration Plan:** `../DOCS/HELP_INTEGRATION_PLAN.md`
- **Deployment Guide:** `../DOCS/WEBSITE_DEPLOYMENT_GUIDE.md`
- **LuCI Development:** `../DOCS/LUCI_DEVELOPMENT_REFERENCE.md`
## How to Use Examples
1. **Review the example code** to understand the pattern
2. **Copy relevant sections** to your module
3. **Customize** module names, URLs, and styling
4. **Test** on development router
5. **Deploy** using deployment scripts
## Integration Workflow
```bash
# 1. Deploy website to router
./secubox-tools/deploy-website.sh root@192.168.8.191
# 2. Add help button code to your module
# (see help-button-integration.js)
# 3. Build and deploy module
./secubox-tools/local-build.sh build luci-app-your-module
./secubox-tools/deploy-network-modes.sh root@192.168.8.191
# 4. Test in browser
open http://192.168.8.191/cgi-bin/luci/admin/secubox/your-module
```
## Common Patterns
### Pattern 1: Header Help Button
```javascript
'require secubox/help as Help';
E('div', { 'class': 'header' }, [
E('h2', {}, 'Module Title'),
Help.createHelpButton('module-name', 'header')
])
```
### Pattern 2: Floating Help Button
```javascript
E('a', {
'class': 'sb-help-floating',
'href': '/luci-static/secubox/demo-module.html',
'target': '_blank'
}, [E('span', {}, '❓')])
```
### Pattern 3: Quick Action
```javascript
buttons.push(
E('button', {
'class': 'action-btn',
'click': function() {
window.open('/luci-static/secubox/demo-module.html', '_blank');
}
}, ['📖 Help'])
)
```
## Module-Specific Examples
Each module can have different help button placements:
| Module | Recommended Position | Example File |
|--------|---------------------|--------------|
| SecuBox Dashboard | Quick Actions | help-button-integration.js (Ex 3) |
| System Hub | Header Badge | help-button-integration.js (Ex 4) |
| Network Modes | Header Button | help-button-integration.js (Ex 2) |
| Other Modules | Floating Button | help-button-integration.js (Ex 5) |
## Testing Checklist
- [ ] Help button is visible
- [ ] Clicking opens correct documentation page
- [ ] Styling matches module theme
- [ ] Works in dark/light mode
- [ ] Responsive on mobile
- [ ] No console errors
- [ ] Accessible via keyboard
## Contributing Examples
To add new examples:
1. Create descriptive JavaScript file
2. Include clear comments
3. Show complete, working code
4. Update this README
5. Test on actual router
## Support
For questions about examples:
- Review related documentation in `DOCS/`
- Check module source code in `luci-app-*/`
- Test on development router first
## Quick Reference
**Website Base URL:** `/luci-static/secubox/`
**Module Help Pages:**
- secubox → `index.html#modules`
- system-hub → `demo-secubox-hub.html`
- network-modes → `demo-network-modes.html`
- client-guardian → `demo-client-guardian.html`
- bandwidth-manager → `demo-bandwidth.html`
- traffic-shaper → `demo-traffic-shaper.html`
- (See help-button-integration.js for complete list)
**Help Utility Methods:**
- `Help.createHelpButton(module, position, options)`
- `Help.getHelpUrl(module)`
- `Help.openHelpModal(module)`

View File

@ -0,0 +1,356 @@
/**
* SecuBox Help Button Integration Example
*
* This file demonstrates how to integrate help buttons into SecuBox modules
* to link with the deployed website documentation.
*
* Version: 1.0
* Date: 2025-12-28
*/
// ============================================================================
// EXAMPLE 1: Shared Help Utility (Recommended)
// ============================================================================
// File: luci-app-secubox/htdocs/luci-static/resources/secubox/help.js
'use strict';
'require baseclass';
return baseclass.extend({
/**
* Create a help button element
* @param {string} moduleName - Module identifier (e.g., 'network-modes')
* @param {string} position - Button position: 'header', 'footer', 'floating'
* @param {object} options - Custom options
*/
createHelpButton: function(moduleName, position, options) {
var opts = options || {};
var helpUrl = this.getHelpUrl(moduleName);
var buttonClass = 'sb-help-btn sb-help-' + position;
return E('a', {
'class': buttonClass,
'href': helpUrl,
'target': opts.target || '_blank',
'title': opts.title || _('View Help & Documentation'),
'style': opts.style || ''
}, [
E('span', { 'class': 'sb-help-icon' }, opts.icon || '❓'),
opts.showLabel !== false ? E('span', { 'class': 'sb-help-label' }, opts.label || _('Help')) : null
]);
},
/**
* Get help URL for a module
* @param {string} moduleName - Module identifier
*/
getHelpUrl: function(moduleName) {
var baseUrl = '/luci-static/secubox/';
var moduleMap = {
'secubox': 'index.html#modules',
'system-hub': 'demo-secubox-hub.html',
'network-modes': 'demo-network-modes.html',
'client-guardian': 'demo-client-guardian.html',
'bandwidth-manager': 'demo-bandwidth.html',
'cdn-cache': 'demo-cdn-cache.html',
'traffic-shaper': 'demo-traffic-shaper.html',
'wireguard-dashboard': 'demo-wireguard.html',
'crowdsec-dashboard': 'demo-crowdsec.html',
'netdata-dashboard': 'demo-netdata.html',
'netifyd-dashboard': 'demo-netifyd.html',
'auth-guardian': 'demo-auth.html',
'vhost-manager': 'demo-vhost.html',
'ksm-manager': 'demo-ksm-manager.html',
'media-flow': 'demo-media.html'
};
return baseUrl + (moduleMap[moduleName] || 'index.html');
},
/**
* Open help in modal (for inline help)
* @param {string} moduleName - Module identifier
*/
openHelpModal: function(moduleName) {
var helpUrl = this.getHelpUrl(moduleName);
var iframe = E('iframe', {
'src': helpUrl,
'style': 'width: 100%; height: 70vh; border: none; border-radius: 8px;'
});
ui.showModal(_('Help & Documentation'), [
E('div', { 'style': 'min-height: 70vh;' }, [iframe]),
E('div', { 'class': 'right', 'style': 'margin-top: 1rem;' }, [
E('button', {
'class': 'btn',
'click': ui.hideModal
}, _('Close'))
])
]);
}
});
// ============================================================================
// EXAMPLE 2: Module Integration (Network Modes)
// ============================================================================
// File: luci-app-network-modes/htdocs/luci-static/resources/view/network-modes/overview.js
'use strict';
'require view';
'require dom';
'require ui';
'require network-modes.api as api';
'require secubox/help as Help'; // ← ADD THIS LINE
return view.extend({
title: _('Network Modes'),
load: function() {
return api.getAllData();
},
render: function(data) {
var self = this;
var status = data.status || {};
var currentMode = status.current_mode || 'router';
var view = E('div', { 'class': 'network-modes-dashboard' }, [
// Load help CSS
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox/help.css') }),
// Header with help button
E('div', { 'class': 'nm-header' }, [
E('div', { 'class': 'nm-logo' }, [
E('div', { 'class': 'nm-logo-icon' }, '🌐'),
E('div', { 'class': 'nm-logo-text' }, ['Network ', E('span', {}, 'Configuration')])
]),
E('div', { 'class': 'nm-mode-badge ' + currentMode }, [
E('span', { 'class': 'nm-mode-dot' }),
currentMode
]),
// ← ADD HELP BUTTON HERE
Help.createHelpButton('network-modes', 'header', {
icon: '📖',
label: _('Help')
})
]),
// Rest of the dashboard...
]);
return view;
}
});
// ============================================================================
// EXAMPLE 3: SecuBox Dashboard Integration (Quick Actions)
// ============================================================================
// File: luci-app-secubox/htdocs/luci-static/resources/view/secubox/dashboard.js
// Add to renderQuickActions method
renderQuickActions: function() {
var self = this;
var actions = [
{ name: 'restart_rpcd', label: 'RPCD', icon: '🔄', color: '#6366f1' },
{ name: 'restart_uhttpd', label: 'Web Server', icon: '🌐', color: '#00ab44' },
{ name: 'restart_network', label: 'Network', icon: '📡', color: '#06b6d4' },
{ name: 'restart_firewall', label: 'Firewall', icon: '🛡️', color: '#ef4444' },
{ name: 'clear_cache', label: 'Clear Cache', icon: '🧹', color: '#f59e0b' },
{ name: 'backup_config', label: 'Backup', icon: '💾', color: '#8b5cf6' }
];
var buttons = actions.map(function(action) {
return E('button', {
'class': 'secubox-action-btn',
'style': 'border-color: ' + action.color,
'click': function() {
self.executeQuickAction(action.name, action.label);
}
}, [
E('span', { 'class': 'secubox-action-icon' }, action.icon),
E('span', { 'class': 'secubox-action-label' }, action.label)
]);
});
// ← ADD HELP BUTTON TO QUICK ACTIONS
buttons.push(
E('button', {
'class': 'secubox-action-btn',
'style': 'border-color: #667eea',
'click': function() {
window.open('/luci-static/secubox/index.html#modules', '_blank');
}
}, [
E('span', { 'class': 'secubox-action-icon' }, '📖'),
E('span', { 'class': 'secubox-action-label' }, _('Help'))
])
);
return E('div', { 'class': 'secubox-card' }, [
E('h3', { 'class': 'secubox-card-title' }, '⚡ Quick Actions'),
E('div', { 'class': 'secubox-actions-grid' }, buttons)
]);
},
// ============================================================================
// EXAMPLE 4: System Hub Integration (Header Badge Style)
// ============================================================================
// File: luci-app-system-hub/htdocs/luci-static/resources/view/system-hub/overview.js
// Modify renderHeader method
renderHeader: function() {
var score = this.healthData.score || 0;
var scoreClass = score >= 80 ? 'excellent' : (score >= 60 ? 'good' : 'warning');
var scoreLabel = score >= 80 ? 'Excellent' : (score >= 60 ? 'Good' : 'Warning');
return E('div', { 'class': 'sh-dashboard-header' }, [
E('div', { 'class': 'sh-dashboard-header-content' }, [
E('div', {}, [
E('h2', {}, '⚙️ System Control Center'),
E('p', { 'class': 'sh-dashboard-subtitle' }, 'System Monitoring & Management Center')
]),
E('div', { 'class': 'sh-dashboard-header-info' }, [
E('div', { 'class': 'sh-header-badge-group' }, [
E('span', { 'class': 'sh-dashboard-badge sh-dashboard-badge-version' },
'v0.3.6'),
E('span', { 'class': 'sh-dashboard-badge' },
'⏱️ ' + (this.sysInfo.uptime_formatted || '0d 0h 0m')),
E('span', { 'class': 'sh-dashboard-badge' },
'🖥️ ' + (this.sysInfo.hostname || 'OpenWrt')),
// ← ADD HELP BADGE
E('a', {
'class': 'sh-dashboard-badge sh-help-badge',
'href': '/luci-static/secubox/demo-secubox-hub.html',
'target': '_blank',
'title': _('View Help')
}, '📖 Help')
]),
this.renderHealthGauge(score, scoreClass, scoreLabel)
])
])
]);
},
// ============================================================================
// EXAMPLE 5: Floating Help Button (Global)
// ============================================================================
// Add to any module's render method for a floating help button
render: function(data) {
var container = E('div', { 'class': 'module-dashboard' }, [
// ... module content ...
// ← ADD FLOATING HELP BUTTON
E('a', {
'class': 'sb-help-floating',
'href': '/luci-static/secubox/demo-module.html',
'target': '_blank',
'title': _('Help & Documentation')
}, [
E('span', { 'class': 'sb-help-icon' }, '❓')
])
]);
return container;
}
// ============================================================================
// EXAMPLE 6: Inline Modal Help
// ============================================================================
// Use Help.openHelpModal() for inline help
E('button', {
'class': 'btn cbi-button-action',
'click': function() {
Help.openHelpModal('network-modes');
}
}, [
E('span', {}, '❓ '),
_('Help')
])
// ============================================================================
// EXAMPLE 7: Context-Sensitive Help
// ============================================================================
// Different help URLs based on context
getContextualHelpUrl: function(context) {
var baseUrl = '/luci-static/secubox/demo-network-modes.html';
var anchors = {
'sniffer': '#sniffer-mode',
'accesspoint': '#access-point-mode',
'relay': '#relay-mode',
'router': '#router-mode'
};
return baseUrl + (anchors[context] || '');
}
// Then use it:
E('a', {
'href': this.getContextualHelpUrl('sniffer'),
'target': '_blank'
}, _('Learn about Sniffer Mode'))
// ============================================================================
// CSS INTEGRATION EXAMPLE
// ============================================================================
/*
File: luci-app-secubox/htdocs/luci-static/resources/secubox/help.css
Add to existing module CSS for consistent styling:
*/
/* Help Button Base */
.sb-help-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
transition: all 0.3s ease;
border: 2px solid transparent;
cursor: pointer;
}
.sb-help-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}
/* Floating position */
.sb-help-floating {
position: fixed;
bottom: 2rem;
right: 2rem;
z-index: 1000;
width: 60px;
height: 60px;
border-radius: 50%;
padding: 0;
justify-content: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
/* System Hub badge style */
.sh-help-badge {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
transition: all 0.3s ease;
}
.sh-help-badge:hover {
transform: scale(1.05);
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.4);
}

View File

@ -3,6 +3,7 @@
'require dom';
'require ui';
'require network-modes.api as api';
'require secubox/help as Help';
return view.extend({
title: _('Network Modes'),
@ -62,6 +63,9 @@ return view.extend({
var currentModeInfo = modeInfos[currentMode];
var view = E('div', { 'class': 'network-modes-dashboard' }, [
// Load help CSS
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox/help.css') }),
// Header
E('div', { 'class': 'nm-header' }, [
E('div', { 'class': 'nm-logo' }, [
@ -71,7 +75,11 @@ return view.extend({
E('div', { 'class': 'nm-mode-badge ' + currentMode }, [
E('span', { 'class': 'nm-mode-dot' }),
currentModeInfo ? currentModeInfo.name : currentMode
])
]),
Help.createHelpButton('network-modes', 'header', {
icon: '📖',
label: _('Help')
})
]),
// Current Mode Display Card

View File

@ -448,8 +448,8 @@ apply_mode() {
apply_accesspoint_features
;;
relay)
# Repeater mode: STA + AP relay
relay)
# Repeater mode: STA + AP relay
# Client interface (sta)
uci set network.wwan=interface
uci set network.wwan.proto='dhcp'
@ -465,12 +465,41 @@ apply_mode() {
uci set network.stabridge.proto='relay'
uci set network.stabridge.network='lan wwan'
apply_wireguard_config
apply_mtu_clamping
enable_tcp_bbr
;;
apply_wireguard_config
apply_mtu_clamping
enable_tcp_bbr
;;
bridge)
sniffer)
local ports=$(uci -q get network-modes.sniffer.bridge_ports || echo "eth0 eth1")
local bridge_iface=$(uci -q get network-modes.sniffer.bridge_interface || echo "br-lan")
local promisc=$(uci -q get network-modes.sniffer.promiscuous || echo 1)
uci delete network.wan 2>/dev/null
uci set network.lan=interface
uci set network.lan.proto='none'
uci set network.lan.type='bridge'
uci set network.lan.ifname="$ports"
uci set network.lan.delegate='0'
uci set network.lan.device="$bridge_iface"
uci set dhcp.lan=dhcp
uci set dhcp.lan.interface='lan'
uci set dhcp.lan.ignore='1'
uci set firewall.@zone[0].input='ACCEPT'
uci set firewall.@zone[0].output='ACCEPT'
uci set firewall.@zone[0].forward='ACCEPT'
uci delete firewall.@zone[1] 2>/dev/null
if [ "$promisc" = "1" ]; then
for port in $ports; do
ip link set "$port" promisc on 2>/dev/null || true
done
fi
;;
bridge)
# Pure L2 bridge: all interfaces bridged, DHCP client
uci delete network.wan 2>/dev/null

View File

@ -1,5 +1,5 @@
{
"admin/secubox/network/network-modes": {
"admin/secubox/network-modes": {
"title": "Network Modes",
"order": 20,
"action": {
@ -9,7 +9,7 @@
"acl": ["luci-app-network-modes"]
}
},
"admin/secubox/network/network-modes/overview": {
"admin/secubox/network-modes/overview": {
"title": "Overview",
"order": 10,
"action": {
@ -17,7 +17,7 @@
"path": "network-modes/overview"
}
},
"admin/secubox/network/network-modes/wizard": {
"admin/secubox/network-modes/wizard": {
"title": "Mode Wizard",
"order": 20,
"action": {
@ -25,7 +25,7 @@
"path": "network-modes/wizard"
}
},
"admin/secubox/network/network-modes/router": {
"admin/secubox/network-modes/router": {
"title": "Router Mode",
"order": 30,
"action": {
@ -33,7 +33,7 @@
"path": "network-modes/router"
}
},
"admin/secubox/network/network-modes/accesspoint": {
"admin/secubox/network-modes/accesspoint": {
"title": "Access Point Mode",
"order": 40,
"action": {
@ -41,7 +41,7 @@
"path": "network-modes/accesspoint"
}
},
"admin/secubox/network/network-modes/relay": {
"admin/secubox/network-modes/relay": {
"title": "Relay Mode",
"order": 50,
"action": {
@ -49,7 +49,7 @@
"path": "network-modes/relay"
}
},
"admin/secubox/network/network-modes/sniffer": {
"admin/secubox/network-modes/sniffer": {
"title": "Sniffer Mode",
"order": 60,
"action": {
@ -57,7 +57,7 @@
"path": "network-modes/sniffer"
}
},
"admin/secubox/network/network-modes/settings": {
"admin/secubox/network-modes/settings": {
"title": "Settings",
"order": 90,
"action": {

View File

@ -244,6 +244,18 @@
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
}
.secubox-tab-bonus {
background: linear-gradient(135deg, #f97316 0%, #ec4899 100%);
border: none;
color: white;
box-shadow: 0 10px 24px rgba(236, 72, 153, 0.35);
}
.secubox-tab-bonus:hover {
background: linear-gradient(135deg, #fb923c 0%, #f472b6 100%);
box-shadow: 0 12px 28px rgba(236, 72, 153, 0.4);
}
.secubox-tab-icon {
font-size: 16px;
line-height: 1;

View File

@ -0,0 +1,322 @@
/**
* SecuBox Help System Styles
* Version: 1.0.0
*/
/* ============================================================================
Base Help Button Styles
============================================================================ */
.sb-help-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white !important;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
font-size: 0.9rem;
transition: all 0.3s ease;
border: 2px solid transparent;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.sb-help-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
border-color: rgba(255, 255, 255, 0.3);
color: white !important;
text-decoration: none;
}
.sb-help-btn:active {
transform: translateY(0);
box-shadow: 0 2px 6px rgba(102, 126, 234, 0.3);
}
.sb-help-icon {
font-size: 1.2em;
line-height: 1;
display: inline-flex;
align-items: center;
}
.sb-help-label {
white-space: nowrap;
}
/* ============================================================================
Position Variants
============================================================================ */
/* Header Position - Compact style for headers */
.sb-help-header {
margin-left: auto;
padding: 0.4rem 0.8rem;
font-size: 0.85em;
align-self: center;
}
/* Footer Position - Full width on mobile */
.sb-help-footer {
margin-top: 2rem;
width: 100%;
justify-content: center;
}
@media (min-width: 768px) {
.sb-help-footer {
width: auto;
}
}
/* Badge Style - Minimal, badge-like appearance */
.sb-help-badge {
padding: 0.3rem 0.6rem;
font-size: 0.8rem;
border-radius: 4px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white !important;
text-decoration: none;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
gap: 0.3rem;
}
.sb-help-badge:hover {
transform: scale(1.05);
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.4);
color: white !important;
}
/* Floating Button - Fixed position, circular */
.sb-help-floating {
position: fixed;
bottom: 2rem;
right: 2rem;
z-index: 1000;
border-radius: 50%;
width: 60px;
height: 60px;
padding: 0;
justify-content: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.sb-help-floating .sb-help-label {
display: none;
}
.sb-help-floating .sb-help-icon {
font-size: 1.8em;
}
.sb-help-floating:hover {
transform: scale(1.1);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5);
}
/* Hide floating button on small screens to avoid overlap */
@media (max-width: 768px) {
.sb-help-floating {
bottom: 1rem;
right: 1rem;
width: 50px;
height: 50px;
}
.sb-help-floating .sb-help-icon {
font-size: 1.5em;
}
}
/* ============================================================================
Tooltip Styles
============================================================================ */
.sb-help-tooltip {
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
border-radius: 50%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-size: 12px;
cursor: help;
margin-left: 0.3rem;
transition: all 0.2s ease;
}
.sb-help-tooltip:hover {
transform: scale(1.2);
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.4);
}
/* ============================================================================
Dark Theme Support
============================================================================ */
[data-theme="dark"] .sb-help-btn {
background: linear-gradient(135deg, #4c51bf 0%, #553c9a 100%);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}
[data-theme="dark"] .sb-help-btn:hover {
box-shadow: 0 4px 12px rgba(76, 81, 191, 0.5);
border-color: rgba(255, 255, 255, 0.2);
}
[data-theme="dark"] .sb-help-badge {
background: linear-gradient(135deg, #4c51bf 0%, #553c9a 100%);
}
[data-theme="dark"] .sb-help-tooltip {
background: linear-gradient(135deg, #4c51bf 0%, #553c9a 100%);
}
/* ============================================================================
Button States
============================================================================ */
.sb-help-btn:disabled,
.sb-help-btn.disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
}
.sb-help-btn:focus {
outline: 2px solid #667eea;
outline-offset: 2px;
}
/* ============================================================================
Loading State
============================================================================ */
.sb-help-btn.loading {
position: relative;
color: transparent !important;
}
.sb-help-btn.loading::after {
content: '';
position: absolute;
width: 16px;
height: 16px;
top: 50%;
left: 50%;
margin-left: -8px;
margin-top: -8px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top-color: white;
animation: sb-help-spin 0.6s linear infinite;
}
@keyframes sb-help-spin {
to { transform: rotate(360deg); }
}
/* ============================================================================
Integration with Existing Modules
============================================================================ */
/* SecuBox Dashboard */
.secubox-actions-grid .sb-help-btn {
width: 100%;
justify-content: center;
}
/* System Hub */
.sh-dashboard-header .sb-help-badge {
margin-left: 0.5rem;
}
/* Network Modes */
.nm-header .sb-help-btn {
margin-left: auto;
}
/* ============================================================================
Accessibility
============================================================================ */
/* High contrast mode support */
@media (prefers-contrast: high) {
.sb-help-btn {
border: 2px solid currentColor;
}
}
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
.sb-help-btn,
.sb-help-tooltip,
.sb-help-floating {
transition: none;
}
.sb-help-btn:hover,
.sb-help-floating:hover {
transform: none;
}
.sb-help-btn.loading::after {
animation: none;
border-top-color: transparent;
}
}
/* Focus visible for keyboard navigation */
.sb-help-btn:focus-visible {
outline: 3px solid #667eea;
outline-offset: 3px;
}
/* ============================================================================
Print Styles
============================================================================ */
@media print {
.sb-help-btn,
.sb-help-floating,
.sb-help-tooltip {
display: none !important;
}
}
/* ============================================================================
Responsive Adjustments
============================================================================ */
@media (max-width: 480px) {
.sb-help-btn {
font-size: 0.85rem;
padding: 0.4rem 0.7rem;
}
.sb-help-header {
padding: 0.3rem 0.6rem;
}
/* Stack label vertically on very small screens if needed */
.sb-help-btn.sb-help-stacked {
flex-direction: column;
gap: 0.2rem;
}
.sb-help-btn.sb-help-stacked .sb-help-icon {
font-size: 1.4em;
}
.sb-help-btn.sb-help-stacked .sb-help-label {
font-size: 0.75rem;
}
}

View File

@ -0,0 +1,183 @@
'use strict';
'require baseclass';
'require ui';
/**
* SecuBox Help System
* Provides centralized help/documentation access for all SecuBox modules
* Version: 1.0.0
*/
console.log('📖 SecuBox Help System v1.0.0 loaded');
return baseclass.extend({
/**
* Create a help button element
* @param {string} moduleName - Module identifier (e.g., 'network-modes')
* @param {string} position - Button position: 'header', 'footer', 'floating', 'badge'
* @param {object} options - Custom options
* @returns {Element} Help button element
*/
createHelpButton: function(moduleName, position, options) {
var opts = options || {};
var helpUrl = this.getHelpUrl(moduleName);
var buttonClass = 'sb-help-btn sb-help-' + position;
var target = opts.target || '_blank';
// Handle modal vs new tab
if (opts.modal) {
var self = this;
return E('button', {
'class': buttonClass,
'title': opts.title || _('View Help & Documentation'),
'style': opts.style || '',
'click': function(ev) {
ev.preventDefault();
self.openHelpModal(moduleName);
}
}, [
E('span', { 'class': 'sb-help-icon' }, opts.icon || '❓'),
opts.showLabel !== false ? E('span', { 'class': 'sb-help-label' }, opts.label || _('Help')) : null
]);
}
// Regular link button
return E('a', {
'class': buttonClass,
'href': helpUrl,
'target': target,
'title': opts.title || _('View Help & Documentation'),
'style': opts.style || ''
}, [
E('span', { 'class': 'sb-help-icon' }, opts.icon || '❓'),
opts.showLabel !== false ? E('span', { 'class': 'sb-help-label' }, opts.label || _('Help')) : null
]);
},
/**
* Get help URL for a module
* @param {string} moduleName - Module identifier
* @param {string} anchor - Optional anchor/section (e.g., '#features')
* @returns {string} Help page URL
*/
getHelpUrl: function(moduleName, anchor) {
var baseUrl = '/luci-static/secubox/';
var moduleMap = {
'secubox': 'index.html#modules',
'system-hub': 'demo-secubox-hub.html',
'network-modes': 'demo-network-modes.html',
'client-guardian': 'demo-client-guardian.html',
'bandwidth-manager': 'demo-bandwidth.html',
'cdn-cache': 'demo-cdn-cache.html',
'traffic-shaper': 'demo-traffic-shaper.html',
'wireguard-dashboard': 'demo-wireguard.html',
'crowdsec-dashboard': 'demo-crowdsec.html',
'netdata-dashboard': 'demo-netdata.html',
'netifyd-dashboard': 'demo-netifyd.html',
'auth-guardian': 'demo-auth.html',
'vhost-manager': 'demo-vhost.html',
'ksm-manager': 'demo-ksm-manager.html',
'media-flow': 'demo-media.html'
};
var url = baseUrl + (moduleMap[moduleName] || 'index.html');
return anchor ? url + anchor : url;
},
/**
* Open help in modal dialog with iframe
* @param {string} moduleName - Module identifier
* @param {object} options - Modal options
*/
openHelpModal: function(moduleName, options) {
var opts = options || {};
var helpUrl = this.getHelpUrl(moduleName);
var modalTitle = opts.title || _('Help & Documentation');
var iframe = E('iframe', {
'src': helpUrl,
'style': 'width: 100%; height: 70vh; border: none; border-radius: 8px; background: white;',
'frameborder': '0'
});
var modal = E('div', { 'style': 'min-height: 70vh;' }, [
iframe,
E('div', {
'class': 'right',
'style': 'margin-top: 1rem; display: flex; gap: 0.5rem; justify-content: flex-end;'
}, [
opts.showOpenButton !== false ? E('a', {
'class': 'btn cbi-button-neutral',
'href': helpUrl,
'target': '_blank'
}, [
'🔗 ',
_('Open in New Tab')
]) : null,
E('button', {
'class': 'btn cbi-button-action',
'click': ui.hideModal
}, _('Close'))
])
]);
ui.showModal(modalTitle, [modal]);
},
/**
* Create a quick help tooltip
* @param {string} text - Tooltip text
* @param {string} moduleName - Optional module for "Learn More" link
* @returns {Element} Tooltip element
*/
createTooltip: function(text, moduleName) {
var tooltip = E('span', {
'class': 'sb-help-tooltip',
'title': text
}, '❓');
if (moduleName) {
var self = this;
tooltip.addEventListener('click', function(ev) {
ev.preventDefault();
window.open(self.getHelpUrl(moduleName), '_blank');
});
}
return tooltip;
},
/**
* Check if help page exists (basic check)
* @param {string} moduleName - Module identifier
* @returns {boolean} True if help page is configured
*/
hasHelpPage: function(moduleName) {
var url = this.getHelpUrl(moduleName);
return url.indexOf('demo-') !== -1 || moduleName === 'secubox';
},
/**
* Get all available help pages
* @returns {object} Map of module names to help URLs
*/
getAllHelpPages: function() {
return {
'secubox': this.getHelpUrl('secubox'),
'system-hub': this.getHelpUrl('system-hub'),
'network-modes': this.getHelpUrl('network-modes'),
'client-guardian': this.getHelpUrl('client-guardian'),
'bandwidth-manager': this.getHelpUrl('bandwidth-manager'),
'cdn-cache': this.getHelpUrl('cdn-cache'),
'traffic-shaper': this.getHelpUrl('traffic-shaper'),
'wireguard-dashboard': this.getHelpUrl('wireguard-dashboard'),
'crowdsec-dashboard': this.getHelpUrl('crowdsec-dashboard'),
'netdata-dashboard': this.getHelpUrl('netdata-dashboard'),
'netifyd-dashboard': this.getHelpUrl('netifyd-dashboard'),
'auth-guardian': this.getHelpUrl('auth-guardian'),
'vhost-manager': this.getHelpUrl('vhost-manager'),
'ksm-manager': this.getHelpUrl('ksm-manager'),
'media-flow': this.getHelpUrl('media-flow')
};
}
});

View File

@ -92,6 +92,18 @@
color: white;
}
.secubox-filter-tab-bonus {
background: linear-gradient(135deg, #f97316 0%, #ec4899 100%);
border-color: transparent;
color: white;
box-shadow: 0 8px 20px rgba(249, 115, 22, 0.35);
}
.secubox-filter-tab-bonus:hover {
transform: translateY(-2px);
box-shadow: 0 10px 24px rgba(236, 72, 153, 0.35);
}
/* Modules Grid */
.secubox-modules-grid {
display: grid;

View File

@ -345,6 +345,228 @@
font-style: italic;
}
/* SecuBox Help Bonus Page */
.secubox-help-page {
display: flex;
flex-direction: column;
gap: 20px;
}
.secubox-help-hero {
display: flex;
gap: 32px;
align-items: center;
background: linear-gradient(135deg, #312e81 0%, #0f172a 60%, #1e293b 100%);
border: 1px solid rgba(255, 255, 255, 0.08);
box-shadow: 0 20px 60px rgba(15, 23, 42, 0.45);
color: #eef2ff;
}
.secubox-help-hero-text {
flex: 1;
}
.secubox-help-eyebrow {
display: inline-flex;
align-items: center;
gap: 6px;
text-transform: uppercase;
letter-spacing: 0.2em;
font-size: 11px;
font-weight: 600;
color: rgba(255, 255, 255, 0.6);
}
.secubox-help-subtitle {
color: rgba(255, 255, 255, 0.9);
font-size: 15px;
margin: 12px 0 0 0;
}
.secubox-help-hero-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 16px;
margin-top: 20px;
}
.secubox-help-hero-stat {
background: rgba(15, 23, 42, 0.55);
border-radius: 10px;
padding: 14px 16px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.secubox-help-hero-stat-icon {
font-size: 22px;
margin-bottom: 6px;
}
.secubox-help-hero-stat-value {
display: block;
font-size: 20px;
font-weight: 700;
}
.secubox-help-hero-stat-label {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.04em;
color: rgba(255, 255, 255, 0.7);
}
.secubox-help-hero-actions {
display: flex;
flex-direction: column;
gap: 12px;
min-width: 230px;
}
.secubox-help-cta {
background: linear-gradient(135deg, #22c55e 0%, #15803d 100%) !important;
box-shadow: 0 10px 30px rgba(21, 128, 61, 0.45);
}
.secubox-card-title-row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
}
.secubox-card-hint {
font-size: 13px;
color: var(--sb-text-muted);
}
.secubox-help-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
margin-top: 16px;
}
.secubox-help-card {
background: var(--sb-bg-card);
border: 1px solid var(--sb-border);
border-radius: 12px;
padding: 18px;
display: flex;
flex-direction: row;
gap: 16px;
align-items: center;
text-decoration: none;
color: inherit;
transition: all 0.2s ease;
}
.secubox-help-card-body {
flex: 1;
}
.secubox-help-card:hover {
border-color: var(--sb-primary);
transform: translateY(-2px);
box-shadow: 0 12px 24px var(--sb-hover-shadow);
}
.secubox-help-card-icon {
font-size: 28px;
width: 48px;
height: 48px;
border-radius: 10px;
background: rgba(99, 102, 241, 0.12);
display: flex;
align-items: center;
justify-content: center;
}
.secubox-help-card-title {
margin: 0;
font-size: 16px;
font-weight: 600;
color: var(--sb-text);
}
.secubox-help-card-text {
margin: 4px 0 8px 0;
font-size: 13px;
color: var(--sb-text-muted);
}
.secubox-help-card-link {
font-size: 12px;
font-weight: 600;
color: var(--sb-primary);
text-transform: uppercase;
letter-spacing: 0.08em;
}
.secubox-help-support-grid {
margin-top: 16px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
.secubox-help-support-item {
border: 1px dashed var(--sb-border);
border-radius: 10px;
padding: 16px;
background: rgba(99, 102, 241, 0.04);
}
.secubox-help-support-icon {
font-size: 24px;
margin-bottom: 8px;
}
.secubox-help-support-title {
font-weight: 600;
margin-bottom: 6px;
color: var(--sb-text);
}
.secubox-help-support-text {
margin: 0;
font-size: 13px;
color: var(--sb-text-muted);
line-height: 1.5;
}
.secubox-help-support-actions {
margin-top: 20px;
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.secubox-help-footer {
background: var(--sb-bg-card);
border: 1px solid var(--sb-border);
border-radius: 14px;
padding: 20px;
text-align: center;
}
.secubox-help-footer-text {
font-size: 14px;
color: var(--sb-text-muted);
margin-bottom: 10px;
}
.secubox-help-footer-links {
display: inline-flex;
justify-content: center;
gap: 8px;
color: var(--sb-primary);
font-weight: 600;
}
.secubox-help-footer-links .sep {
color: var(--sb-text-muted);
}
/* Responsive Design */
@media (max-width: 768px) {
.secubox-health-grid {
@ -358,4 +580,24 @@
.secubox-modules-grid {
grid-template-columns: 1fr;
}
.secubox-help-hero {
flex-direction: column;
text-align: center;
}
.secubox-help-hero-actions {
width: 100%;
flex-direction: row;
justify-content: center;
}
.secubox-help-card {
flex-direction: column;
text-align: center;
}
.secubox-help-support-actions {
justify-content: center;
}
}

View File

@ -239,20 +239,20 @@ return view.extend({
// Map module IDs to their dashboard paths
var modulePaths = {
'crowdsec': 'admin/secubox/security/crowdsec/overview',
'netdata': 'admin/secubox/monitoring/netdata/dashboard',
'netifyd': 'admin/secubox/security/netifyd/overview',
'wireguard': 'admin/secubox/network/wireguard/overview',
'network_modes': 'admin/secubox/network/network-modes/overview',
'client_guardian': 'admin/secubox/security/client-guardian/overview',
'system_hub': 'admin/secubox/system/system-hub/overview',
'bandwidth_manager': 'admin/secubox/network/bandwidth-manager/overview',
'auth_guardian': 'admin/secubox/security/auth-guardian/overview',
'media_flow': 'admin/secubox/monitoring/mediaflow/dashboard',
'vhost_manager': 'admin/secubox/services/vhosts/overview',
'traffic_shaper': 'admin/secubox/network/traffic-shaper/overview',
'cdn_cache': 'admin/secubox/network/cdn-cache/overview',
'ksm_manager': 'admin/secubox/security/ksm-manager/overview'
'crowdsec': 'admin/secubox/crowdsec/overview',
'netdata': 'admin/secubox/netdata/dashboard',
'netifyd': 'admin/secubox/netifyd/overview',
'wireguard': 'admin/secubox/wireguard/overview',
'network_modes': 'admin/secubox/network-modes/overview',
'client_guardian': 'admin/secubox/client-guardian/overview',
'system_hub': 'admin/secubox/system-hub/overview',
'bandwidth_manager': 'admin/secubox/bandwidth-manager/overview',
'auth_guardian': 'admin/secubox/auth-guardian/overview',
'media_flow': 'admin/secubox/mediaflow/dashboard',
'vhost_manager': 'admin/secubox/vhosts/overview',
'traffic_shaper': 'admin/secubox/traffic-shaper/overview',
'cdn_cache': 'admin/secubox/cdn-cache/overview',
'ksm_manager': 'admin/secubox/ksm-manager/overview'
};
var moduleCards = filteredModules.map(function(module) {
@ -302,22 +302,34 @@ return view.extend({
{ id: 'monitoring', label: 'Monitoring', icon: '📊' }
];
var filterTabs = E('div', { 'class': 'secubox-filter-tabs' },
filters.map(function(filter) {
var isActive = self.activeFilter === filter.id;
return E('div', {
'class': 'secubox-filter-tab' + (isActive ? ' active' : ''),
'click': function() {
self.activeFilter = filter.id;
self.updateModulesGrid();
}
}, [
E('span', { 'class': 'secubox-tab-icon' }, filter.icon),
E('span', { 'class': 'secubox-tab-label' }, filter.label)
]);
})
var filterTabButtons = filters.map(function(filter) {
var isActive = self.activeFilter === filter.id;
return E('div', {
'class': 'secubox-filter-tab' + (isActive ? ' active' : ''),
'click': function() {
self.activeFilter = filter.id;
self.updateModulesGrid();
}
}, [
E('span', { 'class': 'secubox-tab-icon' }, filter.icon),
E('span', { 'class': 'secubox-tab-label' }, filter.label)
]);
});
filterTabButtons.push(
E('div', {
'class': 'secubox-filter-tab secubox-tab-bonus',
'click': function() {
window.location.href = L.url('admin/secubox/help');
}
}, [
E('span', { 'class': 'secubox-tab-icon' }, '✨'),
E('span', { 'class': 'secubox-tab-label' }, _('Bonus · Help à SecuBox'))
])
);
var filterTabs = E('div', { 'class': 'secubox-filter-tabs' }, filterTabButtons);
return E('div', { 'class': 'secubox-card' }, [
E('h3', { 'class': 'secubox-card-title' }, '🎯 Active Modules (' + activeModules.length + ')'),
filterTabs,
@ -359,20 +371,20 @@ return view.extend({
// Map module IDs to their dashboard paths
var modulePaths = {
'crowdsec': 'admin/secubox/security/crowdsec/overview',
'netdata': 'admin/secubox/monitoring/netdata/dashboard',
'netifyd': 'admin/secubox/security/netifyd/overview',
'wireguard': 'admin/secubox/network/wireguard/overview',
'network_modes': 'admin/secubox/network/network-modes/overview',
'client_guardian': 'admin/secubox/security/client-guardian/overview',
'system_hub': 'admin/secubox/system/system-hub/overview',
'bandwidth_manager': 'admin/secubox/network/bandwidth-manager/overview',
'auth_guardian': 'admin/secubox/security/auth-guardian/overview',
'media_flow': 'admin/secubox/monitoring/mediaflow/dashboard',
'vhost_manager': 'admin/secubox/services/vhosts/overview',
'traffic_shaper': 'admin/secubox/network/traffic-shaper/overview',
'cdn_cache': 'admin/secubox/network/cdn-cache/overview',
'ksm_manager': 'admin/secubox/security/ksm-manager/overview'
'crowdsec': 'admin/secubox/crowdsec/overview',
'netdata': 'admin/secubox/netdata/dashboard',
'netifyd': 'admin/secubox/netifyd/overview',
'wireguard': 'admin/secubox/wireguard/overview',
'network_modes': 'admin/secubox/network-modes/overview',
'client_guardian': 'admin/secubox/client-guardian/overview',
'system_hub': 'admin/secubox/system-hub/overview',
'bandwidth_manager': 'admin/secubox/bandwidth-manager/overview',
'auth_guardian': 'admin/secubox/auth-guardian/overview',
'media_flow': 'admin/secubox/mediaflow/dashboard',
'vhost_manager': 'admin/secubox/vhosts/overview',
'traffic_shaper': 'admin/secubox/traffic-shaper/overview',
'cdn_cache': 'admin/secubox/cdn-cache/overview',
'ksm_manager': 'admin/secubox/ksm-manager/overview'
};
var moduleCards = filteredModules.map(function(module) {

View File

@ -0,0 +1,203 @@
'use strict';
'require view';
'require dom';
'require secubox/api as API';
'require secubox/help as Help';
'require secubox/theme as Theme';
// Ensure SecuBox theme variables are loaded for this view
Theme.init();
// Load base SecuBox + help styles
document.head.appendChild(E('link', {
'rel': 'stylesheet',
'type': 'text/css',
'href': L.resource('secubox/secubox.css')
}));
document.head.appendChild(E('link', {
'rel': 'stylesheet',
'type': 'text/css',
'href': L.resource('secubox/help.css')
}));
return view.extend({
load: function() {
return API.getStatus();
},
render: function(status) {
var data = status || {};
var helpPages = Help.getAllHelpPages();
return E('div', { 'class': 'secubox-help-page' }, [
this.renderHero(data),
this.renderHelpCatalog(helpPages),
this.renderSupportSection(),
this.renderFooter()
]);
},
renderHero: function(status) {
return E('div', { 'class': 'secubox-card secubox-help-hero' }, [
E('div', { 'class': 'secubox-help-hero-text' }, [
E('span', { 'class': 'secubox-help-eyebrow' }, _('Bonus Tab')),
E('h2', {}, _('Help à SecuBox')),
E('p', { 'class': 'secubox-help-subtitle' },
_('Retrouvez la documentation, les guides et toutes les façons de soutenir la suite SecuBox.')),
E('div', { 'class': 'secubox-help-hero-stats' }, [
this.renderHeroStat('📦', _('Modules Couvert•e•s'), Object.keys(Help.getAllHelpPages()).length),
this.renderHeroStat('⚙️', _('Version Actuelle'), status.version || 'v1.0.0'),
this.renderHeroStat('🌐', _('Site Officiel'), 'secubox.cybermood.eu')
])
]),
E('div', { 'class': 'secubox-help-hero-actions' }, [
Help.createHelpButton('secubox', 'header', {
icon: '📚',
label: _('Ouvrir la knowledge base'),
modal: true
}),
E('a', {
'class': 'sb-help-btn sb-help-header secubox-help-cta',
'href': 'https://secubox.cybermood.eu/#contact',
'target': '_blank'
}, [
E('span', { 'class': 'sb-help-icon' }, '🤝'),
E('span', { 'class': 'sb-help-label' }, _('Contacter SecuBox'))
])
])
]);
},
renderHeroStat: function(icon, label, value) {
return E('div', { 'class': 'secubox-help-hero-stat' }, [
E('div', { 'class': 'secubox-help-hero-stat-icon' }, icon),
E('div', { 'class': 'secubox-help-hero-stat-value' }, value),
E('div', { 'class': 'secubox-help-hero-stat-label' }, label)
]);
},
renderHelpCatalog: function(pages) {
var self = this;
var entries = Object.keys(pages || {});
return E('div', { 'class': 'secubox-card' }, [
E('div', { 'class': 'secubox-card-title-row' }, [
E('h3', { 'class': 'secubox-card-title' }, '📘 ' + _('Documentation Express')),
E('span', { 'class': 'secubox-card-hint' },
_('Chaque tuile ouvre la doc dédiée dans un nouvel onglet.'))
]),
E('div', { 'class': 'secubox-help-grid' },
entries.map(function(key) {
return self.renderHelpCard(key, pages[key]);
})
)
]);
},
renderHelpCard: function(key, url) {
var info = this.getModuleInfo(key);
return E('a', {
'class': 'secubox-help-card',
'href': url,
'target': '_blank'
}, [
E('div', { 'class': 'secubox-help-card-icon' }, info.icon),
E('div', { 'class': 'secubox-help-card-body' }, [
E('h4', { 'class': 'secubox-help-card-title' }, info.title),
E('p', { 'class': 'secubox-help-card-text' }, info.description || _('Guide officiel et FAQ.'))
]),
E('span', { 'class': 'secubox-help-card-link' }, _('Voir la doc →'))
]);
},
renderSupportSection: function() {
var items = [
{
icon: '💬',
title: _('Feedback & idées'),
text: _('Partagez vos retours via GitHub Issues ou email pour faire évoluer les modules.')
},
{
icon: '🛠️',
title: _('Contribuer au code'),
text: _('Forkez le dépôt SecuBox, proposez des améliorations, corrigez des bugs, créez de nouveaux helpers.')
},
{
icon: '🤗',
title: _('Soutenir le projet'),
text: _('Commandes pro, sponsoring ou partenariats : contactez CyberMind.fr pour renforcer SecuBox.')
}
];
return E('div', { 'class': 'secubox-card secubox-help-support' }, [
E('h3', { 'class': 'secubox-card-title' }, '🤝 ' + _('Comment aider SecuBox ?')),
E('div', { 'class': 'secubox-help-support-grid' },
items.map(function(item) {
return E('div', { 'class': 'secubox-help-support-item' }, [
E('div', { 'class': 'secubox-help-support-icon' }, item.icon),
E('div', { 'class': 'secubox-help-support-title' }, item.title),
E('p', { 'class': 'secubox-help-support-text' }, item.text)
]);
})
),
E('div', { 'class': 'secubox-help-support-actions' }, [
Help.createHelpButton('secubox', 'footer', {
icon: '💡',
label: _('Ouvrir la FAQ')
}),
E('a', {
'class': 'sb-help-btn sb-help-footer',
'href': 'mailto:contact@cybermind.fr?subject=SecuBox%20Feedback'
}, [
E('span', { 'class': 'sb-help-icon' }, '✉️'),
E('span', { 'class': 'sb-help-label' }, _('Écrire à léquipe'))
])
])
]);
},
renderFooter: function() {
return E('div', { 'class': 'secubox-help-footer' }, [
E('div', { 'class': 'secubox-help-footer-text' },
_('Besoin dun accompagnement premium ? SecuBox peut être intégré, maintenu et personnalisé par CyberMind.fr.')),
E('div', { 'class': 'secubox-help-footer-links' }, [
E('a', {
'href': 'https://secubox.cybermood.eu/',
'target': '_blank'
}, _('Découvrir le site vitrine')),
E('span', { 'class': 'sep' }, '•'),
E('a', {
'href': 'https://github.com/CyberMindStudio/secubox-openwrt',
'target': '_blank'
}, _('GitHub SecuBox'))
])
]);
},
getModuleInfo: function(key) {
var titles = {
'secubox': { title: _('SecuBox Hub'), icon: '🚀', description: _('Vue densemble, modules et roadmap.') },
'system-hub': { title: _('System Hub'), icon: '⚙️', description: _('Surveillance système et diagnostics.') },
'network-modes': { title: _('Network Modes'), icon: '🌐', description: _('Guides de bascule et scénarios réseau.') },
'client-guardian': { title: _('Client Guardian'), icon: '🛡️', description: _('Portail captif et NAC avancé.') },
'bandwidth-manager': { title: _('Bandwidth Manager'), icon: '📶', description: _('QoS, classes et quotas réseau.') },
'cdn-cache': { title: _('CDN Cache'), icon: '🗄️', description: _('Cache CDN local et politiques.') },
'traffic-shaper': { title: _('Traffic Shaper'), icon: '🌀', description: _('Profils et préréglages QoS.') },
'wireguard-dashboard': { title: _('WireGuard Dashboard'), icon: '🛜', description: _('Peers, profils et QR codes.') },
'crowdsec-dashboard': { title: _('CrowdSec Dashboard'), icon: '🕵️', description: _('Décisions, bouncers et alertes.') },
'netdata-dashboard': { title: _('Netdata Dashboard'), icon: '📊', description: _('Monitoring temps réel Netdata.') },
'netifyd-dashboard': { title: _('Netifyd Dashboard'), icon: '🔍', description: _('DPI, flux et risques applications.') },
'auth-guardian': { title: _('Auth Guardian'), icon: '🔐', description: _('Auth portail, vouchers et OAuth.') },
'vhost-manager': { title: _('VHost Manager'), icon: '🧩', description: _('Virtual hosts, SSL & redirections.') },
'ksm-manager': { title: _('KSM Manager'), icon: '🔑', description: _('Gestion clés et secrets sécurisés.') },
'media-flow': { title: _('Media Flow'), icon: '🎬', description: _('Analytique streaming & clients.') }
};
var fallbackTitle = key.replace(/-/g, ' ').replace(/\b\w/g, function(c) {
return c.toUpperCase();
});
return titles[key] || { title: fallbackTitle, icon: '📦' };
}
});

View File

@ -106,21 +106,30 @@ return view.extend({
{ id: 'system', label: 'System', icon: '⚙️' }
];
return E('div', { 'class': 'secubox-filter-tabs' },
tabs.map(function(tab) {
return E('button', {
'class': 'secubox-filter-tab' + (tab.id === 'all' ? ' active' : ''),
'data-filter': tab.id,
'click': function(ev) {
document.querySelectorAll('.secubox-filter-tab').forEach(function(el) {
el.classList.remove('active');
});
ev.target.classList.add('active');
self.filterModules(tab.id);
}
}, tab.icon + ' ' + tab.label);
})
var filterButtons = tabs.map(function(tab) {
return E('button', {
'class': 'secubox-filter-tab' + (tab.id === 'all' ? ' active' : ''),
'data-filter': tab.id,
'click': function(ev) {
document.querySelectorAll('.secubox-filter-tab').forEach(function(el) {
el.classList.remove('active');
});
ev.target.classList.add('active');
self.filterModules(tab.id);
}
}, tab.icon + ' ' + tab.label);
});
filterButtons.push(
E('button', {
'class': 'secubox-filter-tab secubox-filter-tab-bonus',
'click': function() {
window.location.href = L.url('admin/secubox/help');
}
}, '✨ ' + _('Bonus · Help à SecuBox'))
);
return E('div', { 'class': 'secubox-filter-tabs' }, filterButtons);
},
renderModuleCards: function(modules, filter) {
@ -256,20 +265,20 @@ return view.extend({
getModuleDashboardPath: function(moduleId) {
var paths = {
'crowdsec': 'admin/secubox/security/crowdsec/overview',
'netdata': 'admin/secubox/monitoring/netdata/dashboard',
'netifyd': 'admin/secubox/security/netifyd/overview',
'wireguard': 'admin/secubox/network/wireguard/overview',
'network_modes': 'admin/secubox/network/network-modes/overview',
'client_guardian': 'admin/secubox/security/client-guardian/overview',
'system_hub': 'admin/secubox/system/system-hub/overview',
'bandwidth_manager': 'admin/secubox/network/bandwidth-manager/overview',
'auth_guardian': 'admin/secubox/security/auth-guardian/overview',
'media_flow': 'admin/secubox/monitoring/mediaflow/dashboard',
'vhost_manager': 'admin/secubox/services/vhosts/overview',
'traffic_shaper': 'admin/secubox/network/traffic-shaper/overview',
'cdn_cache': 'admin/secubox/network/cdn-cache/overview',
'ksm_manager': 'admin/secubox/security/ksm-manager/overview'
'crowdsec': 'admin/secubox/crowdsec/overview',
'netdata': 'admin/secubox/netdata/dashboard',
'netifyd': 'admin/secubox/netifyd/overview',
'wireguard': 'admin/secubox/wireguard/overview',
'network_modes': 'admin/secubox/network-modes/overview',
'client_guardian': 'admin/secubox/client-guardian/overview',
'system_hub': 'admin/secubox/system-hub/overview',
'bandwidth_manager': 'admin/secubox/bandwidth-manager/overview',
'auth_guardian': 'admin/secubox/auth-guardian/overview',
'media_flow': 'admin/secubox/mediaflow/dashboard',
'vhost_manager': 'admin/secubox/vhosts/overview',
'traffic_shaper': 'admin/secubox/traffic-shaper/overview',
'cdn_cache': 'admin/secubox/cdn-cache/overview',
'ksm_manager': 'admin/secubox/ksm-manager/overview'
};
return paths[moduleId] || null;
},

View File

@ -39,11 +39,6 @@
"order": 10,
"action": {"type": "view", "path": "secubox/monitoring"}
},
"admin/secubox/network": {
"title": "Network Management",
"order": 40,
"action": {"type": "firstchild"}
},
"admin/secubox/system": {
"title": "System & Performance",
"order": 50,
@ -53,5 +48,10 @@
"title": "Services & Applications",
"order": 60,
"action": {"type": "firstchild"}
},
"admin/secubox/help": {
"title": "Bonus · Help à SecuBox",
"order": 99,
"action": {"type": "view", "path": "secubox/help"}
}
}

68
scripts/sync_module_versions.py Executable file
View File

@ -0,0 +1,68 @@
#!/usr/bin/env python3
"""Synchronize module versions and website progress bars."""
from __future__ import annotations
import re
import sys
from pathlib import Path
import difflib
import subprocess
RE_WEBSITE = re.compile(
r'(<div class="module-progress-fill" style="width:)([0-9.]+)(%;"></div>\s*</div>\s*<div class="module-progress-label">v)'
r'([0-9]+\.[0-9]+\.[0-9]+)(?:\s*·\s*)([0-9.]+)(\s*/ 1.00</div>)'
)
def version_ratio(ver: str) -> float:
major, minor, patch = map(int, ver.split('.'))
return major + minor / 10 + patch / 100
def update_website(html: Path) -> bool:
text = html.read_text()
def repl(match: re.Match) -> str:
ver = match.group(4)
ratio = version_ratio(ver)
width = f"{ratio * 100:.0f}".rstrip('0').rstrip('.')
label = f"{ratio:.2f}".rstrip('0').rstrip('.')
return f"{match.group(1)}{width}{match.group(3)}{ver} · {label}{match.group(6)}"
new_text, count = RE_WEBSITE.subn(repl, text)
if count:
if new_text == text:
return False
diff = difflib.unified_diff(
text.splitlines(keepends=True),
new_text.splitlines(keepends=True),
fromfile=str(html),
tofile=str(html)
)
diff_text = ''.join(diff)
if not diff_text:
return False
subprocess.run(['patch', str(html)], input=diff_text.encode(), check=True)
return True
return False
def main() -> int:
repo_root = Path(__file__).resolve().parents[1]
site_dir = repo_root.parent / 'secubox-website'
targets = [site_dir / 'index.html', site_dir / 'campaign.html']
overall = False
for html in targets:
if not html.exists():
print(f'Skipping missing file: {html}', file=sys.stderr)
continue
if update_website(html):
print(f'Updated {html.name}')
overall = True
print('Website progress sync', 'done' if overall else 'no changes')
return 0
if __name__ == '__main__':
raise SystemExit(main())

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SCR="$REPO_ROOT/scripts/sync_module_versions.py"
python3 "$SCR"

99
secubox-tools/deploy-website.sh Executable file
View File

@ -0,0 +1,99 @@
#!/usr/bin/env bash
# Deploy SecuBox website to an OpenWrt router.
# Usage: ./secubox-tools/deploy-website.sh [root@192.168.1.1] [/path/to/website]
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
ROUTER_HOST="${1:-root@192.168.8.191}"
WEBSITE_PATH="${2:-}"
TARGET_DIR="/www/luci-static/secubox"
# Determine website source path
if [[ -z "$WEBSITE_PATH" ]]; then
# Check common locations
COMMON_PATHS=(
"$REPO_ROOT/../secubox-website"
"$HOME/CyberMindStudio/_files/secubox-website"
"./secubox-website"
)
for path in "${COMMON_PATHS[@]}"; do
if [[ -d "$path" ]]; then
WEBSITE_PATH="$path"
break
fi
done
if [[ -z "$WEBSITE_PATH" ]]; then
echo "ERROR: Website directory not found. Please specify path as second argument." >&2
echo "Usage: $0 [router_host] [website_path]" >&2
exit 1
fi
fi
if [[ ! -d "$WEBSITE_PATH" ]]; then
echo "ERROR: Website directory not found: $WEBSITE_PATH" >&2
exit 1
fi
echo "[1/4] Preparing website files from $WEBSITE_PATH" >&2
# Create tarball excluding unnecessary files
TARBALL="/tmp/secubox-website-$(date +%s).tar.gz"
(cd "$WEBSITE_PATH" && tar czf "$TARBALL" \
--exclude='.git' \
--exclude='.claude' \
--exclude='*.md' \
--exclude='.gitignore' \
--exclude='README*' \
--exclude='LICENSE' \
.)
echo "[2/4] Uploading website files to $ROUTER_HOST:$TARGET_DIR/" >&2
scp "$TARBALL" "${ROUTER_HOST}:/tmp/secubox-website.tar.gz"
echo "[3/4] Deploying website on router…" >&2
ssh "$ROUTER_HOST" "sh -s" <<EOF
set -e
# Create target directory
mkdir -p "$TARGET_DIR"
# Backup existing website if present
if [ -d "$TARGET_DIR" ] && [ "\$(ls -A $TARGET_DIR)" ]; then
BACKUP_DIR="/tmp/secubox-website-backup-\$(date +%s)"
echo "[router] Creating backup at \$BACKUP_DIR…" >&2
mkdir -p "\$BACKUP_DIR"
cp -a "$TARGET_DIR"/* "\$BACKUP_DIR/" 2>/dev/null || true
fi
# Extract new website
echo "[router] Extracting website files…" >&2
cd "$TARGET_DIR"
tar xzf /tmp/secubox-website.tar.gz
# Set proper permissions
chmod 755 "$TARGET_DIR"
find "$TARGET_DIR" -type d -exec chmod 755 {} \;
find "$TARGET_DIR" -type f -name "*.html" -exec chmod 644 {} \;
find "$TARGET_DIR" -type f -name "*.js" -exec chmod 644 {} \;
find "$TARGET_DIR" -type f -name "*.css" -exec chmod 644 {} \; 2>/dev/null || true
# Clean up
rm -f /tmp/secubox-website.tar.gz
echo "[router] Website deployed to $TARGET_DIR"
echo "[router] Access URL: http://\$(uci get network.lan.ipaddress 2>/dev/null || echo 'router-ip')/luci-static/secubox/"
EOF
echo "[4/4] Cleaning up local tarball…" >&2
rm -f "$TARBALL"
echo ""
echo "✓ Website deployment completed successfully!"
echo " Target: $ROUTER_HOST:$TARGET_DIR"
echo " Files: $(find "$WEBSITE_PATH" -type f \( -name "*.html" -o -name "*.js" \) | wc -l) files deployed"
echo ""