From a53e5f7068f483619c947359a71f6fb0ff47ad77 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Sun, 28 Dec 2025 02:19:30 +0100 Subject: [PATCH] feat: Add comprehensive permission management system (v0.3.1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement three-tier permission management across all SecuBox modules: **1. Package-Level Permissions (PKG_FILE_MODES)** - Add PKG_FILE_MODES to all 15 module Makefiles - RPCD scripts: 755 (executable) - CSS/JS/JSON files: 644 (default, no config needed) - Ensures correct permissions at installation time **2. Runtime Permission Fix** - New script: /usr/libexec/secubox/fix-permissions.sh - RPCD method: luci.secubox fix_permissions - UI control: "🔧 Fix Perms" button in Quick Actions - Fixes all permissions and restarts services **3. Automation & Documentation** - secubox-tools/add-pkg-file-modes.sh: Auto-configure PKG_FILE_MODES - PERMISSIONS-GUIDE.md: Comprehensive permissions guide - MODULE-ENABLE-DISABLE-DESIGN.md: Enable/disable system design doc - Updated Makefile template with PKG_FILE_MODES pattern **Modules Updated:** - luci-app-auth-guardian - luci-app-bandwidth-manager - luci-app-cdn-cache - luci-app-client-guardian - luci-app-crowdsec-dashboard - luci-app-ksm-manager - luci-app-media-flow - luci-app-netdata-dashboard - luci-app-netifyd-dashboard - luci-app-network-modes - luci-app-secubox (+ fix-permissions.sh script) - luci-app-system-hub - luci-app-traffic-shaper - luci-app-vhost-manager - luci-app-wireguard-dashboard **Benefits:** - No more manual permission fixes after installation - Users can fix permissions from UI without SSH access - Proper OpenWrt package management compliance - Automated detection and configuration đŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- MODULE-ENABLE-DISABLE-DESIGN.md | 356 ++++++++++++++++++ PERMISSIONS-GUIDE.md | 229 +++++++++++ luci-app-auth-guardian/Makefile | 4 + luci-app-bandwidth-manager/Makefile | 4 + luci-app-cdn-cache/Makefile | 4 + luci-app-client-guardian/Makefile | 4 + luci-app-crowdsec-dashboard/Makefile | 4 + luci-app-ksm-manager/Makefile | 4 + luci-app-media-flow/Makefile | 4 + luci-app-netdata-dashboard/Makefile | 4 + luci-app-netifyd-dashboard/Makefile | 4 + luci-app-network-modes/Makefile | 3 + .../resources/network-modes/api.js | 98 ++++- luci-app-secubox/Makefile | 4 + .../luci-static/resources/secubox/api.js | 38 +- .../resources/secubox/dashboard.css | 46 ++- .../resources/view/secubox/dashboard.js | 84 ++++- .../resources/view/secubox/modules.js | 113 +++--- .../root/usr/libexec/rpcd/luci.secubox | 184 ++++++++- .../usr/libexec/secubox/fix-permissions.sh | 169 +++++++++ .../share/rpcd/acl.d/luci-app-secubox.json | 6 +- luci-app-system-hub/Makefile | 3 + luci-app-traffic-shaper/Makefile | 4 + luci-app-vhost-manager/Makefile | 4 + luci-app-wireguard-dashboard/Makefile | 4 + secubox-tools/add-pkg-file-modes.sh | 209 ++++++++++ templates/Makefile.template | 7 +- 27 files changed, 1515 insertions(+), 82 deletions(-) create mode 100644 MODULE-ENABLE-DISABLE-DESIGN.md create mode 100644 PERMISSIONS-GUIDE.md create mode 100644 luci-app-secubox/root/usr/libexec/secubox/fix-permissions.sh create mode 100755 secubox-tools/add-pkg-file-modes.sh diff --git a/MODULE-ENABLE-DISABLE-DESIGN.md b/MODULE-ENABLE-DISABLE-DESIGN.md new file mode 100644 index 00000000..9fe681a0 --- /dev/null +++ b/MODULE-ENABLE-DISABLE-DESIGN.md @@ -0,0 +1,356 @@ +# Module Enable/Disable Design Document + +**Version:** 0.3.1 +**Date:** 2025-12-27 +**Author:** Claude Code + CyberMind + +## 🎯 Objectif + +Remplacer la logique **start/stop** des modules SecuBox par une logique **enable/disable** (activĂ©/dĂ©sactivĂ©), car les modules sont des **plugins installĂ©s** qu'on souhaite activer ou dĂ©sactiver, plutĂŽt que des services qu'on dĂ©marre ou arrĂȘte ponctuellement. + +## 📋 Changements Conceptuels + +### Avant (v0.2.x) + +``` +Module installĂ© → peut ĂȘtre "Running" ou "Stopped" +Actions: Start / Stop / Restart +État affichĂ©: "Running" (vert) ou "Stopped" (gris) +``` + +### AprĂšs (v0.3.1+) + +``` +Module installĂ© → peut ĂȘtre "Enabled" ou "Disabled" +Actions: Enable / Disable +État affichĂ©: "ActivĂ©" (vert) ou "DĂ©sactivĂ©" (gris) +Info complĂ©mentaire: "Service running" (si enabled + running) +``` + +## đŸ—ïž Architecture Technique + +### 1. Configuration UCI + +Chaque module dans `/etc/config/secubox` aura un champ `enabled`: + +```uci +config module 'crowdsec' + option name 'CrowdSec Dashboard' + option package 'luci-app-crowdsec-dashboard' + option config 'crowdsec' + option category 'security' + option enabled '1' # NEW: 1 = activĂ©, 0 = dĂ©sactivĂ© + option icon 'đŸ›Ąïž' + option color '#ef4444' +``` + +### 2. MĂ©thodes RPCD (`luci.secubox`) + +#### Anciennes mĂ©thodes (DEPRECATED) +- ❌ `start_module(module_id)` → dĂ©marre le service +- ❌ `stop_module(module_id)` → arrĂȘte le service +- ❌ `restart_module(module_id)` → redĂ©marre le service + +#### Nouvelles mĂ©thodes (v0.3.1+) + +```javascript +// Active un module (config UCI + dĂ©marrage service) +enable_module(module_id) +→ uci set secubox.${module}.enabled='1' +→ uci commit secubox +→ /etc/init.d/${service} enable +→ /etc/init.d/${service} start +→ return { success: true, message: "Module activĂ©" } + +// DĂ©sactive un module (config UCI + arrĂȘt service) +disable_module(module_id) +→ uci set secubox.${module}.enabled='0' +→ uci commit secubox +→ /etc/init.d/${service} disable +→ /etc/init.d/${service} stop +→ return { success: true, message: "Module dĂ©sactivĂ©" } + +// VĂ©rifie si un module est activĂ© +check_module_enabled(module_id) +→ return uci get secubox.${module}.enabled == '1' + +// VĂ©rifie si le service tourne (info complĂ©mentaire) +check_service_running(module_id) +→ return pgrep -f ${service} > /dev/null +``` + +### 3. Structure de donnĂ©es retournĂ©e + +```json +{ + "modules": [ + { + "id": "crowdsec", + "name": "CrowdSec Dashboard", + "category": "security", + "installed": true, + "enabled": true, // État principal (config UCI) + "running": true, // État du service (info) + "status": "active", // enabled + running = "active" + "icon": "đŸ›Ąïž", + "color": "#ef4444" + }, + { + "id": "netdata", + "name": "Netdata Monitoring", + "category": "monitoring", + "installed": true, + "enabled": false, // Module dĂ©sactivĂ© + "running": false, + "status": "disabled", // Status affichĂ© + "icon": "📊", + "color": "#22c55e" + } + ] +} +``` + +### 4. États Possibles + +| enabled | running | status | Badge UI | Description | +|---------|---------|----------|---------------|-------------| +| `true` | `true` | `active` | ✓ ActivĂ© | Module activĂ© et service tourne | +| `true` | `false` | `error` | ⚠ Erreur | Module activĂ© mais service arrĂȘtĂ© (problĂšme) | +| `false` | `false` | `disabled` | ○ DĂ©sactivĂ© | Module dĂ©sactivĂ© (Ă©tat normal) | +| `false` | `true` | `unknown` | ? Inconnu | État incohĂ©rent (rare) | + +## 🎹 Interface Utilisateur + +### Dashboard Principal (SecuBox Hub) + +**Avant:** +``` +[CrowdSec Dashboard] ● Running [Stop] [Restart] +[Netdata Monitor] ○ Stopped [Start] +``` + +**AprĂšs:** +``` +[CrowdSec Dashboard] ✓ ActivĂ© [DĂ©sactiver] +[Netdata Monitor] ○ DĂ©sactivĂ© [Activer] +``` + +### Module Individual Card + +```html +
+
+ đŸ›Ąïž + CrowdSec Dashboard + ✓ ActivĂ© +
+
+ + Service en cours d'exécution +
+
+ +
+
+``` + +### Classes CSS + +```css +/* Module states */ +.module-badge.enabled { + background: linear-gradient(135deg, #22c55e, #16a34a); + color: white; +} + +.module-badge.disabled { + background: var(--sh-bg-secondary); + color: var(--sh-text-muted); +} + +.module-badge.error { + background: linear-gradient(135deg, #f59e0b, #d97706); + color: white; +} + +/* Status indicators */ +.status-dot.running { + background: #22c55e; + animation: pulse 2s infinite; +} + +.status-dot.stopped { + background: #94a3b8; +} +``` + +## 📝 API JavaScript + +### Fichier: `secubox/api.js` + +```javascript +// Anciennes mĂ©thodes (DEPRECATED - Ă  supprimer) +startModule: callStartModule, // DEPRECATED +stopModule: callStopModule, // DEPRECATED +restartModule: callRestartModule, // DEPRECATED + +// Nouvelles mĂ©thodes (v0.3.1+) +enableModule: callEnableModule, // NEW +disableModule: callDisableModule, // NEW + +// DĂ©clarations RPC +var callEnableModule = rpc.declare({ + object: 'luci.secubox', + method: 'enable_module', + params: ['module_id'], + expect: { success: false, message: '' } +}); + +var callDisableModule = rpc.declare({ + object: 'luci.secubox', + method: 'disable_module', + params: ['module_id'], + expect: { success: false, message: '' } +}); +``` + +## 🔄 Migration des DonnĂ©es + +### Script de migration (Ă  exĂ©cuter une fois) + +```bash +#!/bin/sh +# migrate-to-enable-disable.sh + +. /lib/functions.sh + +migrate_module() { + local module="$1" + local running=$(pgrep -f "$module" > /dev/null && echo "1" || echo "0") + + # Si le service tourne actuellement, on l'active + if [ "$running" = "1" ]; then + uci set secubox.${module}.enabled='1' + else + # Sinon, on le dĂ©sactive par dĂ©faut + uci set secubox.${module}.enabled='0' + fi +} + +# Migrer tous les modules +config_load secubox +config_foreach migrate_module module + +uci commit secubox +echo "Migration completed" +``` + +## 📚 Documentation Utilisateur + +### README.md (Ă  ajouter) + +```markdown +## Gestion des Modules + +Les modules SecuBox sont des plugins installĂ©s qui peuvent ĂȘtre **activĂ©s** ou **dĂ©sactivĂ©s**. + +### Activer un module +- Cliquez sur le bouton **"Activer"** sur la carte du module +- Le module sera configurĂ© pour dĂ©marrer automatiquement au boot +- Le service associĂ© dĂ©marrera immĂ©diatement + +### DĂ©sactiver un module +- Cliquez sur le bouton **"DĂ©sactiver"** sur la carte du module +- Le module ne dĂ©marrera plus automatiquement au boot +- Le service associĂ© s'arrĂȘtera immĂ©diatement + +### États des modules + +| Badge | Signification | +|-------|---------------| +| ✓ ActivĂ© | Module activĂ© et service en cours d'exĂ©cution | +| ⚠ Erreur | Module activĂ© mais service arrĂȘtĂ© (vĂ©rifier les logs) | +| ○ DĂ©sactivĂ© | Module dĂ©sactivĂ© (normal) | + +**Note:** Les modules restent installĂ©s mĂȘme lorsqu'ils sont dĂ©sactivĂ©s. Pour les supprimer complĂštement, utilisez le gestionnaire de paquets APK. +``` + +## đŸ§Ș Tests Ă  Effectuer + +### Tests Unitaires RPCD + +```bash +# Test enable_module +ubus call luci.secubox enable_module '{"module_id":"crowdsec"}' +# Expected: {"success":true,"message":"Module activĂ©"} + +# VĂ©rifier config UCI +uci get secubox.crowdsec.enabled +# Expected: 1 + +# VĂ©rifier service +/etc/init.d/crowdsec enabled && echo "OK" || echo "FAIL" +pgrep crowdsec && echo "Running" || echo "Not running" + +# Test disable_module +ubus call luci.secubox disable_module '{"module_id":"crowdsec"}' +# Expected: {"success":true,"message":"Module dĂ©sactivĂ©"} + +# VĂ©rifier +uci get secubox.crowdsec.enabled +# Expected: 0 +``` + +### Tests Interface + +1. ✅ Ouvrir le dashboard SecuBox +2. ✅ VĂ©rifier que les modules affichent "ActivĂ©" ou "DĂ©sactivĂ©" +3. ✅ Cliquer sur "DĂ©sactiver" → badge passe Ă  "○ DĂ©sactivĂ©" +4. ✅ Cliquer sur "Activer" → badge passe Ă  "✓ ActivĂ©" +5. ✅ VĂ©rifier que le service dĂ©marre/s'arrĂȘte rĂ©ellement +6. ✅ RafraĂźchir la page → Ă©tat persiste (UCI) + +## 📩 Modules AffectĂ©s + +### SecuBox Hub (`luci-app-secubox`) + +**Fichiers Ă  modifier:** +- ✅ `root/usr/libexec/rpcd/luci.secubox` - Backend RPCD +- ✅ `htdocs/luci-static/resources/secubox/api.js` - API JS +- ✅ `htdocs/luci-static/resources/view/secubox/dashboard.js` - Dashboard +- ✅ `htdocs/luci-static/resources/view/secubox/modules.js` - Module list +- ✅ `htdocs/luci-static/resources/secubox/dashboard.css` - Styles +- ✅ `root/usr/share/rpcd/acl.d/luci-app-secubox.json` - ACL permissions +- ✅ `README.md` - Documentation + +### System Hub (`luci-app-system-hub`) + +**Fichiers Ă  modifier:** +- ✅ `htdocs/luci-static/resources/view/system-hub/components.js` - Vue composants +- ✅ `htdocs/luci-static/resources/view/system-hub/services.js` - Vue services +- ✅ `README.md` - Documentation + +## 🎯 BĂ©nĂ©fices + +1. **ClartĂ© conceptuelle**: "Activer/DĂ©sactiver" est plus clair que "DĂ©marrer/ArrĂȘter" pour des plugins +2. **Persistance**: L'Ă©tat persiste aprĂšs redĂ©marrage (UCI + init.d enable/disable) +3. **CohĂ©rence**: Tous les modules suivent la mĂȘme logique +4. **Meilleure UX**: L'utilisateur comprend qu'il active/dĂ©sactive des fonctionnalitĂ©s +5. **Alignement OpenWrt**: Utilise les mĂ©canismes natifs (`/etc/init.d/${service} enable/disable`) + +## 🔜 Prochaines Étapes + +- [x] CrĂ©er ce document de design +- [ ] ImplĂ©menter les modifications RPCD +- [ ] Mettre Ă  jour l'API JavaScript +- [ ] Mettre Ă  jour les interfaces UI +- [ ] Mettre Ă  jour les ACL permissions +- [ ] CrĂ©er script de migration UCI +- [ ] Mettre Ă  jour la documentation +- [ ] Tester sur router de test +- [ ] DĂ©ployer en production + +--- + +**Maintainer:** CyberMind +**License:** Apache-2.0 diff --git a/PERMISSIONS-GUIDE.md b/PERMISSIONS-GUIDE.md new file mode 100644 index 00000000..88ed4181 --- /dev/null +++ b/PERMISSIONS-GUIDE.md @@ -0,0 +1,229 @@ +# OpenWrt Package Permissions Guide + +**Version:** 0.3.1 +**Date:** 2025-12-28 +**Author:** CyberMind + +## 🎯 Objectif + +Assurer que tous les fichiers des packages SecuBox ont les **bonnes permissions** dĂšs l'installation, sans nĂ©cessiter de correction manuelle. + +## 📋 Permissions Requises + +### Fichiers ExĂ©cutables (755) + +Ces fichiers **DOIVENT** avoir les permissions d'exĂ©cution: + +``` +-rwxr-xr-x (755) +``` + +**Liste des fichiers:** +- `/usr/libexec/rpcd/luci.*` - Scripts RPCD backend +- `/usr/libexec/secubox/*.sh` - Scripts utilitaires +- `/etc/init.d/*` - Scripts d'initialisation +- `/etc/uci-defaults/*` - Scripts de configuration initiale + +### Fichiers Non-ExĂ©cutables (644) + +Ces fichiers **NE DOIVENT PAS** ĂȘtre exĂ©cutables: + +``` +-rw-r--r-- (644) +``` + +**Liste des fichiers:** +- `/www/luci-static/resources/**/*.js` - Fichiers JavaScript +- `/www/luci-static/resources/**/*.css` - Fichiers CSS +- `/usr/share/rpcd/acl.d/*.json` - Permissions ACL +- `/usr/share/luci/menu.d/*.json` - DĂ©finitions de menu +- `/etc/config/*` - Fichiers de configuration UCI + +## 🔧 Configuration dans le Makefile + +### MĂ©thode RecommandĂ©e: PKG_FILE_MODES + +OpenWrt supporte la variable `PKG_FILE_MODES` pour dĂ©finir les permissions des fichiers lors de l'installation du package. + +**Syntaxe:** +```makefile +PKG_FILE_MODES:=/path/to/file:permissions +``` + +**Exemple complet:** +```makefile +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-example +PKG_VERSION:=0.3.1 +PKG_RELEASE:=1 +PKG_LICENSE:=Apache-2.0 +PKG_MAINTAINER:=CyberMind + +LUCI_TITLE:=LuCI - Example Module +LUCI_DESCRIPTION:=Example SecuBox module +LUCI_DEPENDS:=+luci-base +rpcd +LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.example:755 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature +``` + +### Plusieurs Fichiers ExĂ©cutables + +Si vous avez plusieurs fichiers exĂ©cutables: + +```makefile +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.example:755 \ + /usr/libexec/example/helper.sh:755 \ + /etc/init.d/example:755 +``` + +**Note:** Utilisez `\` pour continuer sur la ligne suivante. + +## 📩 Modules SecuBox avec PKG_FILE_MODES + +### luci-app-secubox +```makefile +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.secubox:755 \ + /usr/libexec/secubox/fix-permissions.sh:755 +``` + +### luci-app-system-hub +```makefile +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.system-hub:755 +``` + +### luci-app-network-modes +```makefile +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.network-modes:755 +``` + +## đŸ§Ș VĂ©rification + +### Lors du DĂ©veloppement + +Avant de dĂ©ployer un package, vĂ©rifiez les permissions: + +```bash +# VĂ©rifier les scripts RPCD +ls -l root/usr/libexec/rpcd/luci.* + +# VĂ©rifier les scripts helper +ls -l root/usr/libexec/*/ + +# VĂ©rifier les fichiers web +find root/www -type f -name "*.js" -o -name "*.css" | xargs ls -l +``` + +### AprĂšs Installation du Package + +VĂ©rifiez que les permissions sont correctes sur le routeur: + +```bash +# RPCD scripts doivent ĂȘtre 755 +ls -l /usr/libexec/rpcd/luci.* + +# Fichiers web doivent ĂȘtre 644 +ls -l /www/luci-static/resources/secubox/*.js +ls -l /www/luci-static/resources/secubox/*.css +``` + +## đŸ› ïž Script de VĂ©rification Automatique + +Un script de vĂ©rification est inclus dans `luci-app-secubox`: + +```bash +# VĂ©rifier et corriger toutes les permissions +/usr/libexec/secubox/fix-permissions.sh + +# Via ubus +ubus call luci.secubox fix_permissions + +# Via l'interface web +Dashboard → Quick Actions → "🔧 Fix Perms" +``` + +## ⚠ Erreurs Communes + +### 1. RPCD Script Non-ExĂ©cutable + +**SymptĂŽme:** +```bash +ubus call luci.example status +# Command failed: Permission denied +``` + +**Cause:** Le script RPCD n'a pas les permissions 755 + +**Solution:** +```makefile +# Ajouter dans le Makefile +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.example:755 +``` + +### 2. Fichiers Web ExĂ©cutables + +**SymptĂŽme:** Fichiers JavaScript/CSS avec permissions 755 + +**Cause:** Mauvaise manipulation ou script mal configurĂ© + +**Solution:** Les fichiers web sont 644 par dĂ©faut avec LuCI, pas besoin de les spĂ©cifier dans PKG_FILE_MODES + +### 3. Script Helper Non-ExĂ©cutable + +**SymptĂŽme:** +```bash +/usr/libexec/example/helper.sh +# -bash: /usr/libexec/example/helper.sh: Permission denied +``` + +**Solution:** +```makefile +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.example:755 \ + /usr/libexec/example/helper.sh:755 +``` + +## 📚 RĂ©fĂ©rences + +- **LuCI Build System:** `$(TOPDIR)/feeds/luci/luci.mk` +- **OpenWrt Package Build:** https://openwrt.org/docs/guide-developer/packages +- **PKG_FILE_MODES:** https://openwrt.org/docs/guide-developer/build-system/use-buildsystem#build_system_variables + +## ✅ Checklist PrĂ©-DĂ©ploiement + +Avant de crĂ©er un package `.ipk` ou `.apk`: + +- [ ] Tous les scripts RPCD ont 755 dans PKG_FILE_MODES +- [ ] Tous les scripts helper ont 755 dans PKG_FILE_MODES +- [ ] Les fichiers web (JS/CSS) ne sont PAS dans PKG_FILE_MODES (ils sont 644 par dĂ©faut) +- [ ] Les fichiers ACL/Menu ne sont PAS dans PKG_FILE_MODES (ils sont 644 par dĂ©faut) +- [ ] Le Makefile utilise `include $(TOPDIR)/feeds/luci/luci.mk` +- [ ] PKG_FILE_MODES est dĂ©fini AVANT le `include $(TOPDIR)/feeds/luci/luci.mk` + +## 🔄 Migration des Modules Existants + +Pour ajouter PKG_FILE_MODES Ă  un module existant: + +```bash +cd luci-app-mymodule + +# Éditer le Makefile +vi Makefile + +# Ajouter avant 'include $(TOPDIR)/feeds/luci/luci.mk' +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.mymodule:755 + +# Reconstruire le package +make package/luci-app-mymodule/clean +make package/luci-app-mymodule/compile +``` + +--- + +**Maintainer:** CyberMind +**License:** Apache-2.0 diff --git a/luci-app-auth-guardian/Makefile b/luci-app-auth-guardian/Makefile index 618a6256..98094083 100644 --- a/luci-app-auth-guardian/Makefile +++ b/luci-app-auth-guardian/Makefile @@ -11,6 +11,10 @@ LUCI_DESCRIPTION:=Comprehensive authentication and session management with capti LUCI_DEPENDS:=+luci-base +rpcd +nodogsplash LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.auth-guardian:755 + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-bandwidth-manager/Makefile b/luci-app-bandwidth-manager/Makefile index 58bf5ca2..8db4456c 100644 --- a/luci-app-bandwidth-manager/Makefile +++ b/luci-app-bandwidth-manager/Makefile @@ -11,6 +11,10 @@ LUCI_DESCRIPTION:=Advanced bandwidth management with QoS rules, client quotas, a LUCI_DEPENDS:=+luci-base +rpcd +tc +kmod-sched-core +kmod-sched-cake +kmod-ifb +sqm-scripts +iptables +iptables-mod-conntrack-extra +ip-full LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.bandwidth-manager:755 + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-cdn-cache/Makefile b/luci-app-cdn-cache/Makefile index 3d8fb475..5c855c35 100644 --- a/luci-app-cdn-cache/Makefile +++ b/luci-app-cdn-cache/Makefile @@ -11,6 +11,10 @@ LUCI_DESCRIPTION:=Dashboard for managing local CDN caching proxy on OpenWrt LUCI_DEPENDS:=+luci-base +rpcd LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.cdn-cache:755 + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-client-guardian/Makefile b/luci-app-client-guardian/Makefile index 9ab4f0f8..1c6202cf 100644 --- a/luci-app-client-guardian/Makefile +++ b/luci-app-client-guardian/Makefile @@ -20,6 +20,10 @@ LUCI_DEPENDS:=+luci-base +luci-app-secubox +luci-lib-jsonc +rpcd +rpcd-mod-luci LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.client-guardian:755 + include $(TOPDIR)/feeds/luci/luci.mk define Package/$(PKG_NAME)/conffiles diff --git a/luci-app-crowdsec-dashboard/Makefile b/luci-app-crowdsec-dashboard/Makefile index 75ae8f68..f4524b4f 100644 --- a/luci-app-crowdsec-dashboard/Makefile +++ b/luci-app-crowdsec-dashboard/Makefile @@ -20,6 +20,10 @@ LUCI_DEPENDS:=+luci-base +luci-app-secubox +crowdsec +luci-lib-jsonc +rpcd +rpcd LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.crowdsec-dashboard:755 + include $(TOPDIR)/feeds/luci/luci.mk define Package/$(PKG_NAME)/conffiles diff --git a/luci-app-ksm-manager/Makefile b/luci-app-ksm-manager/Makefile index 1fed185b..d4e0fa49 100644 --- a/luci-app-ksm-manager/Makefile +++ b/luci-app-ksm-manager/Makefile @@ -16,6 +16,10 @@ LUCI_PKGARCH:=all PKG_MAINTAINER:=CyberMind PKG_LICENSE:=Apache-2.0 + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.ksm-manager:755 + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-media-flow/Makefile b/luci-app-media-flow/Makefile index 4dabd72c..a5274c73 100644 --- a/luci-app-media-flow/Makefile +++ b/luci-app-media-flow/Makefile @@ -14,6 +14,10 @@ LUCI_DESCRIPTION:=Real-time detection and monitoring of streaming services (Netf LUCI_DEPENDS:=+luci-base +rpcd +netifyd +luci-app-netifyd-dashboard LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.media-flow:755 + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-netdata-dashboard/Makefile b/luci-app-netdata-dashboard/Makefile index 3bf7cc3c..b8fb8036 100644 --- a/luci-app-netdata-dashboard/Makefile +++ b/luci-app-netdata-dashboard/Makefile @@ -20,6 +20,10 @@ LUCI_DEPENDS:=+luci-base +luci-app-secubox +luci-lib-jsonc +rpcd +rpcd-mod-luci LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.netdata-dashboard:755 + include $(TOPDIR)/feeds/luci/luci.mk define Package/$(PKG_NAME)/conffiles diff --git a/luci-app-netifyd-dashboard/Makefile b/luci-app-netifyd-dashboard/Makefile index 4dfd35fc..abe946f4 100644 --- a/luci-app-netifyd-dashboard/Makefile +++ b/luci-app-netifyd-dashboard/Makefile @@ -20,6 +20,10 @@ LUCI_DEPENDS:=+luci-base +luci-app-secubox +luci-lib-jsonc +rpcd +rpcd-mod-luci LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.netifyd-dashboard:755 + include $(TOPDIR)/feeds/luci/luci.mk define Package/$(PKG_NAME)/conffiles diff --git a/luci-app-network-modes/Makefile b/luci-app-network-modes/Makefile index a6b018b9..443332af 100644 --- a/luci-app-network-modes/Makefile +++ b/luci-app-network-modes/Makefile @@ -20,6 +20,9 @@ LUCI_DEPENDS:=+luci-base +luci-app-secubox +luci-lib-jsonc +rpcd +rpcd-mod-luci LUCI_PKGARCH:=all +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.network-modes:755 + include $(TOPDIR)/feeds/luci/luci.mk define Package/$(PKG_NAME)/conffiles diff --git a/luci-app-network-modes/htdocs/luci-static/resources/network-modes/api.js b/luci-app-network-modes/htdocs/luci-static/resources/network-modes/api.js index 10eea7b5..048dbc3f 100644 --- a/luci-app-network-modes/htdocs/luci-static/resources/network-modes/api.js +++ b/luci-app-network-modes/htdocs/luci-static/resources/network-modes/api.js @@ -63,12 +63,102 @@ return baseclass.extend({ callGetAvailableModes(), callGetInterfaces() ]).then(function(results) { + var status = results[0] || {}; + var currentMode = results[1] || {}; + + // Merge current_mode into status for compatibility + status.current_mode = currentMode.mode || 'router'; + status.interfaces = (results[3] || {}).interfaces || []; + return { - status: results[0] || {}, - current_mode: results[1] || { mode: '' }, - available_modes: results[2] || { modes: [] }, - interfaces: results[3] || { interfaces: [] } + status: status, + modes: results[2] || { modes: [] } }; }); + }, + + // Get static information about a mode + getModeInfo: function(mode) { + var modeInfo = { + router: { + id: 'router', + name: 'Router Mode', + icon: '🏠', + description: 'Traditional home/office router with NAT, firewall, and DHCP server. Ideal for connecting multiple devices to the internet.', + features: [ + 'NAT and firewall enabled', + 'DHCP server for LAN clients', + 'Port forwarding and DMZ', + 'QoS and traffic shaping' + ] + }, + bridge: { + id: 'bridge', + name: 'Bridge Mode', + icon: '🌉', + description: 'Transparent layer-2 forwarding without NAT. All devices appear on the same network segment.', + features: [ + 'Layer-2 transparent bridging', + 'No NAT or routing', + 'STP/RSTP support', + 'VLAN tagging support' + ] + }, + accesspoint: { + id: 'accesspoint', + name: 'Access Point', + icon: '📡', + description: 'WiFi access point with wired uplink. Extends your existing network wirelessly.', + features: [ + 'WiFi hotspot functionality', + 'Wired uplink to main router', + 'Multiple SSID support', + 'Fast roaming (802.11r/k/v)' + ] + }, + relay: { + id: 'relay', + name: 'Repeater/Extender', + icon: '🔁', + description: 'WiFi to WiFi repeating to extend wireless coverage. Connects wirelessly to upstream network.', + features: [ + 'WiFi range extension', + 'Wireless uplink (WDS/Relay)', + 'Rebroadcast on same or different SSID', + 'Signal amplification' + ] + }, + sniffer: { + id: 'sniffer', + name: 'Sniffer Mode', + icon: '🔍', + description: 'Network monitoring and packet capture mode for security analysis and troubleshooting.', + features: [ + 'Promiscuous mode capture', + 'WiFi monitor mode', + 'pcap/pcapng output', + 'Integration with Wireshark' + ] + } + }; + + return modeInfo[mode] || { + id: mode, + name: mode.charAt(0).toUpperCase() + mode.slice(1), + icon: '⚙', + description: 'Unknown mode', + features: [] + }; + }, + + // Format uptime seconds to human readable + formatUptime: function(seconds) { + if (!seconds || seconds < 0) return '0d 0h 0m'; + + var days = Math.floor(seconds / 86400); + var hours = Math.floor((seconds % 86400) / 3600); + var minutes = Math.floor((seconds % 3600) / 60); + + return days + 'd ' + hours + 'h ' + minutes + 'm'; } }); diff --git a/luci-app-secubox/Makefile b/luci-app-secubox/Makefile index 5045a8cc..d271ba84 100644 --- a/luci-app-secubox/Makefile +++ b/luci-app-secubox/Makefile @@ -11,6 +11,10 @@ LUCI_DESCRIPTION:=Central control hub for all SecuBox modules. Provides unified LUCI_DEPENDS:=+luci-base +rpcd +curl +jq LUCI_PKGARCH:=all +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.secubox:755 \ + /usr/libexec/secubox/fix-permissions.sh:755 + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot diff --git a/luci-app-secubox/htdocs/luci-static/resources/secubox/api.js b/luci-app-secubox/htdocs/luci-static/resources/secubox/api.js index da14341f..44f65999 100644 --- a/luci-app-secubox/htdocs/luci-static/resources/secubox/api.js +++ b/luci-app-secubox/htdocs/luci-static/resources/secubox/api.js @@ -8,7 +8,7 @@ * RPCD object: luci.secubox */ -// Version: 0.2.2 +// Version: 0.3.1 var callStatus = rpc.declare({ object: 'luci.secubox', @@ -54,6 +54,28 @@ var callRestartModule = rpc.declare({ params: ['module'] }); +// NEW v0.3.1: Enable/Disable module methods +var callEnableModule = rpc.declare({ + object: 'luci.secubox', + method: 'enable_module', + params: ['module'], + expect: { success: false, message: '' } +}); + +var callDisableModule = rpc.declare({ + object: 'luci.secubox', + method: 'disable_module', + params: ['module'], + expect: { success: false, message: '' } +}); + +var callCheckModuleEnabled = rpc.declare({ + object: 'luci.secubox', + method: 'check_module_enabled', + params: ['module'], + expect: { enabled: false } +}); + var callHealth = rpc.declare({ object: 'luci.secubox', method: 'health', @@ -110,6 +132,12 @@ var callClearAlerts = rpc.declare({ expect: { } }); +var callFixPermissions = rpc.declare({ + object: 'luci.secubox', + method: 'fix_permissions', + expect: { success: false, message: '', output: '' } +}); + function formatUptime(seconds) { if (!seconds) return '0s'; var d = Math.floor(seconds / 86400); @@ -133,9 +161,15 @@ return baseclass.extend({ getModules: callModules, getModulesByCategory: callModulesByCategory, getModuleInfo: callModuleInfo, + // DEPRECATED: Use enable/disable instead startModule: callStartModule, stopModule: callStopModule, restartModule: callRestartModule, + // NEW v0.3.1: Enable/Disable methods + enableModule: callEnableModule, + disableModule: callDisableModule, + checkModuleEnabled: callCheckModuleEnabled, + // Health & diagnostics getHealth: callHealth, getDiagnostics: callDiagnostics, getSystemHealth: callSystemHealth, @@ -145,6 +179,8 @@ return baseclass.extend({ getTheme: callGetTheme, dismissAlert: callDismissAlert, clearAlerts: callClearAlerts, + fixPermissions: callFixPermissions, + // Utilities formatUptime: formatUptime, formatBytes: formatBytes }); diff --git a/luci-app-secubox/htdocs/luci-static/resources/secubox/dashboard.css b/luci-app-secubox/htdocs/luci-static/resources/secubox/dashboard.css index e77cabcc..9db6bb00 100644 --- a/luci-app-secubox/htdocs/luci-static/resources/secubox/dashboard.css +++ b/luci-app-secubox/htdocs/luci-static/resources/secubox/dashboard.css @@ -1,4 +1,5 @@ -/* SecuBox Dashboard Styles * Version: 0.3.0 +/* SecuBox Dashboard Styles + * Version: 0.3.1 */ .secubox-dashboard { @@ -301,6 +302,28 @@ display: inline-block; } +/* Module Status Indicators (v0.3.1) */ +.secubox-status-dot.secubox-status-active { + background: #22c55e; + box-shadow: 0 0 8px rgba(34, 197, 94, 0.5); + animation: pulse 2s infinite; +} + +.secubox-status-dot.secubox-status-disabled { + background: #94a3b8; +} + +.secubox-status-dot.secubox-status-error { + background: #f59e0b; + box-shadow: 0 0 8px rgba(245, 158, 11, 0.5); +} + +.secubox-status-dot.secubox-status-unknown { + background: #94a3b8; + opacity: 0.5; +} + +/* DEPRECATED: Keeping for backward compatibility */ .secubox-status-dot.secubox-status-running { background: #22c55e; box-shadow: 0 0 8px rgba(34, 197, 94, 0.5); @@ -334,6 +357,27 @@ color: var(--sb-text-muted); } +/* Module Status Colors (v0.3.1) */ +.secubox-module-active .secubox-module-mini-status { + color: #22c55e; + font-weight: 500; +} + +.secubox-module-disabled .secubox-module-mini-status { + color: #94a3b8; +} + +.secubox-module-error .secubox-module-mini-status { + color: #f59e0b; + font-weight: 500; +} + +.secubox-module-unknown .secubox-module-mini-status { + color: #94a3b8; + opacity: 0.7; +} + +/* DEPRECATED: Keeping for backward compatibility */ .secubox-module-running .secubox-module-mini-status { color: #22c55e; } diff --git a/luci-app-secubox/htdocs/luci-static/resources/view/secubox/dashboard.js b/luci-app-secubox/htdocs/luci-static/resources/view/secubox/dashboard.js index d7a7eec3..724eb203 100644 --- a/luci-app-secubox/htdocs/luci-static/resources/view/secubox/dashboard.js +++ b/luci-app-secubox/htdocs/luci-static/resources/view/secubox/dashboard.js @@ -256,10 +256,20 @@ return view.extend({ }; var moduleCards = filteredModules.map(function(module) { - var isRunning = module.running; - var statusClass = isRunning ? 'running' : 'stopped'; + var status = module.status || 'unknown'; + var statusClass = status; var dashboardPath = modulePaths[module.id] || ('admin/secubox/' + module.id); + // Status label mapping (v0.3.1) + var statusLabels = { + 'active': '✓ ActivĂ©', + 'disabled': '○ DĂ©sactivĂ©', + 'error': '⚠ Erreur', + 'unknown': '? Inconnu' + }; + + var statusLabel = statusLabels[status] || '○ DĂ©sactivĂ©'; + return E('a', { 'href': L.url(dashboardPath), 'class': 'secubox-module-link secubox-module-' + statusClass @@ -272,13 +282,12 @@ return view.extend({ E('span', { 'class': 'secubox-module-mini-icon' }, module.icon || '📩'), E('span', { 'class': 'secubox-status-dot secubox-status-' + statusClass, - 'title': isRunning ? 'Running' : 'Stopped' + 'title': statusLabel }) ]), E('div', { 'class': 'secubox-module-mini-body' }, [ E('div', { 'class': 'secubox-module-mini-name' }, module.name || module.id), - E('div', { 'class': 'secubox-module-mini-status' }, - isRunning ? '● Running' : '○ Stopped') + E('div', { 'class': 'secubox-module-mini-status' }, statusLabel) ]) ]) ]); @@ -367,10 +376,20 @@ return view.extend({ }; var moduleCards = filteredModules.map(function(module) { - var isRunning = module.running; - var statusClass = isRunning ? 'running' : 'stopped'; + var status = module.status || 'unknown'; + var statusClass = status; var dashboardPath = modulePaths[module.id] || ('admin/secubox/' + module.id); + // Status label mapping (v0.3.1) + var statusLabels = { + 'active': '✓ ActivĂ©', + 'disabled': '○ DĂ©sactivĂ©', + 'error': '⚠ Erreur', + 'unknown': '? Inconnu' + }; + + var statusLabel = statusLabels[status] || '○ DĂ©sactivĂ©'; + return E('a', { 'href': L.url(dashboardPath), 'class': 'secubox-module-link secubox-module-' + statusClass @@ -383,13 +402,12 @@ return view.extend({ E('span', { 'class': 'secubox-module-mini-icon' }, module.icon || '📩'), E('span', { 'class': 'secubox-status-dot secubox-status-' + statusClass, - 'title': isRunning ? 'Running' : 'Stopped' + 'title': statusLabel }) ]), E('div', { 'class': 'secubox-module-mini-body' }, [ E('div', { 'class': 'secubox-module-mini-name' }, module.name || module.id), - E('div', { 'class': 'secubox-module-mini-status' }, - isRunning ? '● Running' : '○ Stopped') + E('div', { 'class': 'secubox-module-mini-status' }, statusLabel) ]) ]) ]); @@ -443,6 +461,20 @@ return view.extend({ ]); }); + // Add Fix Permissions button (v0.3.1) + buttons.push( + E('button', { + 'class': 'secubox-action-btn', + 'style': 'border-color: #f97316', + 'click': function() { + self.executeFixPermissions(); + } + }, [ + E('span', { 'class': 'secubox-action-icon' }, '🔧'), + E('span', { 'class': 'secubox-action-label' }, 'Fix Perms') + ]) + ); + return E('div', { 'class': 'secubox-card' }, [ E('h3', { 'class': 'secubox-card-title' }, '⚡ Quick Actions'), E('div', { 'class': 'secubox-actions-grid' }, buttons) @@ -474,6 +506,38 @@ return view.extend({ }); }, + executeFixPermissions: function() { + var self = this; + ui.showModal(_('Fixing Permissions'), [ + E('p', { 'class': 'spinning' }, _('Fixing file permissions and restarting services...')) + ]); + + API.fixPermissions().then(function(result) { + ui.hideModal(); + if (result && result.success) { + ui.addNotification(null, E('p', '✓ Permissions fixed successfully'), 'info'); + // Show output in console + if (result.output) { + console.log('Fix Permissions Output:\n' + result.output); + } + // Refresh data after fixing permissions + setTimeout(function() { + self.refreshData().then(function() { + self.updateDynamicElements(); + }); + }, 2000); + } else { + ui.addNotification(null, E('p', '✗ ' + (result.message || 'Failed to fix permissions')), 'error'); + if (result.output) { + console.error('Fix Permissions Error:\n' + result.output); + } + } + }).catch(function(err) { + ui.hideModal(); + ui.addNotification(null, E('p', 'Error: ' + err.message), 'error'); + }); + }, + renderAlerts: function(alerts) { if (!alerts || alerts.length === 0) { return E('div', { 'class': 'secubox-card' }, [ diff --git a/luci-app-secubox/htdocs/luci-static/resources/view/secubox/modules.js b/luci-app-secubox/htdocs/luci-static/resources/view/secubox/modules.js index 85106506..fc408621 100644 --- a/luci-app-secubox/htdocs/luci-static/resources/view/secubox/modules.js +++ b/luci-app-secubox/htdocs/luci-static/resources/view/secubox/modules.js @@ -66,8 +66,8 @@ return view.extend({ renderHeader: function(modules) { var total = modules.length; var installed = modules.filter(function(m) { return m.installed; }).length; - var running = modules.filter(function(m) { return m.running; }).length; - var stopped = installed - running; + var enabled = modules.filter(function(m) { return m.enabled; }).length; + var disabled = installed - enabled; return E('div', { 'class': 'secubox-page-header' }, [ E('div', {}, [ @@ -81,12 +81,12 @@ return view.extend({ E('span', { 'class': 'secubox-stat-label' }, 'Total') ]), E('div', { 'class': 'secubox-stat-badge secubox-stat-success' }, [ - E('span', { 'class': 'secubox-stat-value' }, running), - E('span', { 'class': 'secubox-stat-label' }, 'Running') + E('span', { 'class': 'secubox-stat-value' }, enabled), + E('span', { 'class': 'secubox-stat-label' }, 'ActivĂ©s') ]), E('div', { 'class': 'secubox-stat-badge secubox-stat-warning' }, [ - E('span', { 'class': 'secubox-stat-value' }, stopped), - E('span', { 'class': 'secubox-stat-label' }, 'Stopped') + E('span', { 'class': 'secubox-stat-value' }, disabled), + E('span', { 'class': 'secubox-stat-label' }, 'DĂ©sactivĂ©s') ]), E('div', { 'class': 'secubox-stat-badge secubox-stat-muted' }, [ E('span', { 'class': 'secubox-stat-value' }, total - installed), @@ -144,9 +144,20 @@ return view.extend({ renderModuleCard: function(module) { var self = this; - var isRunning = module.running; + var status = module.status || 'unknown'; var isInstalled = module.installed; - var statusClass = isRunning ? 'running' : (isInstalled ? 'stopped' : 'not-installed'); + var statusClass = isInstalled ? status : 'not-installed'; + + // Status label mapping (v0.3.1) + var statusLabels = { + 'active': '✓ ActivĂ©', + 'disabled': '○ DĂ©sactivĂ©', + 'error': '⚠ Erreur', + 'unknown': '? Inconnu', + 'not-installed': '- Not Installed' + }; + + var statusLabel = isInstalled ? (statusLabels[status] || '○ DĂ©sactivĂ©') : statusLabels['not-installed']; return E('div', { 'class': 'secubox-module-card secubox-module-' + statusClass, @@ -166,7 +177,7 @@ return view.extend({ ]), E('div', { 'class': 'secubox-status-indicator secubox-status-' + statusClass, - 'title': isRunning ? 'Running' : (isInstalled ? 'Stopped' : 'Not Installed') + 'title': statusLabel }) ]), @@ -184,7 +195,7 @@ return view.extend({ E('span', { 'class': 'secubox-detail-label' }, 'Status:'), E('span', { 'class': 'secubox-detail-value secubox-status-text-' + statusClass - }, isRunning ? '● Running' : (isInstalled ? '○ Stopped' : '- Not Installed')) + }, statusLabel) ]) ]) ]), @@ -207,36 +218,24 @@ return view.extend({ }, 'đŸ“„ Install') ); } else { - // Start/Stop button - if (module.running) { + // Enable/Disable button (v0.3.1) + if (module.enabled) { actions.push( E('button', { 'class': 'secubox-btn secubox-btn-danger secubox-btn-sm', 'click': function() { - self.stopModule(module); + self.disableModule(module); } - }, 'âč Stop') + }, 'âč DĂ©sactiver') ); } else { actions.push( E('button', { 'class': 'secubox-btn secubox-btn-success secubox-btn-sm', 'click': function() { - self.startModule(module); + self.enableModule(module); } - }, '▶ Start') - ); - } - - // Restart button (only if running) - if (module.running) { - actions.push( - E('button', { - 'class': 'secubox-btn secubox-btn-warning secubox-btn-sm', - 'click': function() { - self.restartModule(module); - } - }, '🔄 Restart') + }, '▶ Activer') ); } @@ -286,69 +285,65 @@ return view.extend({ return icons[category] || icons['other']; }, - startModule: function(module) { + // Enable module (v0.3.1) + enableModule: function(module) { var self = this; - ui.showModal(_('Starting Module'), [ - E('p', {}, _('Starting') + ' ' + module.name + '...') + ui.showModal(_('Activation du module'), [ + E('p', {}, 'Activation de ' + module.name + '...') ]); - API.startModule(module.id).then(function(result) { + API.enableModule(module.id).then(function(result) { ui.hideModal(); if (result && result.success !== false) { - ui.addNotification(null, E('p', module.name + ' started successfully'), 'info'); + ui.addNotification(null, E('p', module.name + ' activĂ© avec succĂšs'), 'info'); self.refreshData().then(function() { self.updateModulesGrid(); }); } else { - ui.addNotification(null, E('p', 'Failed to start ' + module.name), 'error'); + ui.addNotification(null, E('p', 'Échec de l\'activation de ' + module.name), 'error'); } }).catch(function(err) { ui.hideModal(); - ui.addNotification(null, E('p', 'Error: ' + err.message), 'error'); + ui.addNotification(null, E('p', 'Erreur: ' + err.message), 'error'); }); }, - stopModule: function(module) { + // Disable module (v0.3.1) + disableModule: function(module) { var self = this; - ui.showModal(_('Stopping Module'), [ - E('p', {}, _('Stopping') + ' ' + module.name + '...') + ui.showModal(_('DĂ©sactivation du module'), [ + E('p', {}, 'DĂ©sactivation de ' + module.name + '...') ]); - API.stopModule(module.id).then(function(result) { + API.disableModule(module.id).then(function(result) { ui.hideModal(); if (result && result.success !== false) { - ui.addNotification(null, E('p', module.name + ' stopped successfully'), 'info'); + ui.addNotification(null, E('p', module.name + ' dĂ©sactivĂ© avec succĂšs'), 'info'); self.refreshData().then(function() { self.updateModulesGrid(); }); } else { - ui.addNotification(null, E('p', 'Failed to stop ' + module.name), 'error'); + ui.addNotification(null, E('p', 'Échec de la dĂ©sactivation de ' + module.name), 'error'); } }).catch(function(err) { ui.hideModal(); - ui.addNotification(null, E('p', 'Error: ' + err.message), 'error'); + ui.addNotification(null, E('p', 'Erreur: ' + err.message), 'error'); }); }, + // DEPRECATED: Keeping for backward compatibility + startModule: function(module) { + return this.enableModule(module); + }, + + stopModule: function(module) { + return this.disableModule(module); + }, + restartModule: function(module) { var self = this; - ui.showModal(_('Restarting Module'), [ - E('p', {}, _('Restarting') + ' ' + module.name + '...') - ]); - - API.restartModule(module.id).then(function(result) { - ui.hideModal(); - if (result && result.success !== false) { - ui.addNotification(null, E('p', module.name + ' restarted successfully'), 'info'); - self.refreshData().then(function() { - self.updateModulesGrid(); - }); - } else { - ui.addNotification(null, E('p', 'Failed to restart ' + module.name), 'error'); - } - }).catch(function(err) { - ui.hideModal(); - ui.addNotification(null, E('p', 'Error: ' + err.message), 'error'); + return this.disableModule(module).then(function() { + return self.enableModule(module); }); }, diff --git a/luci-app-secubox/root/usr/libexec/rpcd/luci.secubox b/luci-app-secubox/root/usr/libexec/rpcd/luci.secubox index 4cb0e758..c03f3fb2 100755 --- a/luci-app-secubox/root/usr/libexec/rpcd/luci.secubox +++ b/luci-app-secubox/root/usr/libexec/rpcd/luci.secubox @@ -44,14 +44,25 @@ check_module_installed() { fi } +# Check if a module is enabled (UCI config) +check_module_enabled() { + local module="$1" + local enabled + + config_load secubox + config_get enabled "$module" enabled "1" + + echo "$enabled" +} + # Check if a module service is running check_module_running() { local module="$1" local config - + config_load secubox config_get config "$module" config "" - + case "$module" in crowdsec) pgrep -f crowdsec > /dev/null 2>&1 && echo "1" || echo "0" @@ -79,6 +90,22 @@ check_module_running() { esac } +# Determine module status based on enabled + running +get_module_status() { + local enabled="$1" + local running="$2" + + if [ "$enabled" = "1" ] && [ "$running" = "1" ]; then + echo "active" + elif [ "$enabled" = "1" ] && [ "$running" = "0" ]; then + echo "error" + elif [ "$enabled" = "0" ] && [ "$running" = "0" ]; then + echo "disabled" + else + echo "unknown" + fi +} + # Get overall system status get_status() { local total=0 @@ -159,7 +186,9 @@ get_modules() { config_get version "$module" version "0.0.9" local is_installed=$(check_module_installed "$module") + local is_enabled=$(check_module_enabled "$module") local is_running=$(check_module_running "$module") + local status=$(get_module_status "$is_enabled" "$is_running") # Get real version from opkg if installed if [ "$is_installed" = "1" ] && [ -n "$package" ]; then @@ -178,7 +207,9 @@ get_modules() { json_add_string "config" "$config" json_add_string "version" "$version" json_add_boolean "installed" "$is_installed" + json_add_boolean "enabled" "$is_enabled" json_add_boolean "running" "$is_running" + json_add_string "status" "$status" json_add_boolean "in_uci" "1" json_close_object @@ -213,7 +244,9 @@ get_modules() { esac local clean_module=$(echo "$module_id" | sed 's/_/-/g') + local is_enabled=$(check_module_enabled "$module_id") local is_running=$(check_module_running "$module_id") + local status=$(get_module_status "$is_enabled" "$is_running") json_add_object "" json_add_string "id" "$module_id" @@ -226,7 +259,9 @@ get_modules() { json_add_string "config" "$clean_module" json_add_string "version" "$version" json_add_boolean "installed" "1" + json_add_boolean "enabled" "$is_enabled" json_add_boolean "running" "$is_running" + json_add_string "status" "$status" json_add_boolean "in_uci" "0" json_close_object done @@ -265,7 +300,9 @@ get_modules_by_category() { config_get version "$module" version "0.0.9" local is_installed=$(check_module_installed "$module") + local is_enabled=$(check_module_enabled "$module") local is_running=$(check_module_running "$module") + local status=$(get_module_status "$is_enabled" "$is_running") # Get real version from opkg if installed if [ "$is_installed" = "1" ] && [ -n "$package" ]; then @@ -282,7 +319,9 @@ get_modules_by_category() { json_add_string "version" "$version" json_add_string "package" "$package" json_add_boolean "installed" "$is_installed" + json_add_boolean "enabled" "$is_enabled" json_add_boolean "running" "$is_running" + json_add_string "status" "$status" json_add_boolean "in_uci" "1" json_close_object @@ -321,7 +360,9 @@ get_modules_by_category() { name=$(echo "$package" | sed 's/^luci-app-//' | sed 's/-dashboard$//' | sed 's/-/ /g' | sed 's/\b\(.\)/\u\1/g') local is_installed="1" # Must be installed if detected + local is_enabled=$(check_module_enabled "$module_id") local is_running=$(check_module_running "$module_id") + local status=$(get_module_status "$is_enabled" "$is_running") json_add_object "" json_add_string "id" "$module_id" @@ -333,7 +374,9 @@ get_modules_by_category() { json_add_string "package" "$package" json_add_string "category" "$mod_category" json_add_boolean "installed" "$is_installed" + json_add_boolean "enabled" "$is_enabled" json_add_boolean "running" "$is_running" + json_add_string "status" "$status" json_add_boolean "in_uci" "0" json_close_object fi @@ -361,7 +404,9 @@ get_module_info() { config_get version "$module" version "0.0.9" local is_installed=$(check_module_installed "$module") + local is_enabled=$(check_module_enabled "$module") local is_running=$(check_module_running "$module") + local status=$(get_module_status "$is_enabled" "$is_running") json_init json_add_string "id" "$module" @@ -374,7 +419,9 @@ get_module_info() { json_add_string "config" "$config" json_add_string "version" "$version" json_add_boolean "installed" "$is_installed" + json_add_boolean "enabled" "$is_enabled" json_add_boolean "running" "$is_running" + json_add_string "status" "$status" json_dump } @@ -422,14 +469,14 @@ stop_module() { fi } -# Restart a module +# Restart a module (DEPRECATED - use disable/enable instead) restart_module() { local module="$1" local config - + config_load secubox config_get config "$module" config "" - + if [ -x "/etc/init.d/${config}" ]; then /etc/init.d/${config} restart json_init @@ -444,6 +491,64 @@ restart_module() { fi } +# Enable a module (NEW v0.3.1) +enable_module() { + local module="$1" + local config + + config_load secubox + config_get config "$module" config "" + + # Set enabled flag in UCI + uci set secubox.${module}.enabled='1' + uci commit secubox + + # Enable and start service if init script exists + if [ -x "/etc/init.d/${config}" ]; then + /etc/init.d/${config} enable + /etc/init.d/${config} start + + json_init + json_add_boolean "success" 1 + json_add_string "message" "Module activĂ©" + json_dump + else + json_init + json_add_boolean "success" 0 + json_add_string "message" "Init script not found" + json_dump + fi +} + +# Disable a module (NEW v0.3.1) +disable_module() { + local module="$1" + local config + + config_load secubox + config_get config "$module" config "" + + # Set disabled flag in UCI + uci set secubox.${module}.enabled='0' + uci commit secubox + + # Disable and stop service if init script exists + if [ -x "/etc/init.d/${config}" ]; then + /etc/init.d/${config} stop + /etc/init.d/${config} disable + + json_init + json_add_boolean "success" 1 + json_add_string "message" "Module dĂ©sactivĂ©" + json_dump + else + json_init + json_add_boolean "success" 0 + json_add_string "message" "Init script not found" + json_dump + fi +} + # Get health report get_health() { json_init @@ -752,12 +857,16 @@ get_dashboard_data() { config_get color "$module" color "#64748b" local is_installed=$(check_module_installed "$module") + local is_enabled="0" local is_running="0" + local status="disabled" total=$((total + 1)) if [ "$is_installed" = "1" ]; then + is_enabled=$(check_module_enabled "$module") is_running=$(check_module_running "$module") + status=$(get_module_status "$is_enabled" "$is_running") installed=$((installed + 1)) [ "$is_running" = "1" ] && running=$((running + 1)) fi @@ -770,7 +879,9 @@ get_dashboard_data() { json_add_string "icon" "$icon" json_add_string "color" "$color" json_add_boolean "installed" "$is_installed" + json_add_boolean "enabled" "$is_enabled" json_add_boolean "running" "$is_running" + json_add_string "status" "$status" json_close_object done json_close_array @@ -844,6 +955,34 @@ clear_alerts() { json_dump } +# Fix permissions (v0.3.1) +fix_permissions() { + local fix_script="/usr/libexec/secubox/fix-permissions.sh" + + if [ ! -x "$fix_script" ]; then + json_init + json_add_boolean "success" 0 + json_add_string "message" "Fix script not found or not executable" + json_dump + return 1 + fi + + # Run the fix script and capture output + local output=$($fix_script 2>&1) + local exit_code=$? + + json_init + if [ $exit_code -eq 0 ]; then + json_add_boolean "success" 1 + json_add_string "message" "Permissions fixed successfully" + else + json_add_boolean "success" 0 + json_add_string "message" "Failed to fix permissions" + fi + json_add_string "output" "$output" + json_dump +} + # Main dispatcher case "$1" in list) @@ -867,6 +1006,15 @@ case "$1" in json_add_object "restart_module" json_add_string "module" "string" json_close_object + json_add_object "enable_module" + json_add_string "module" "string" + json_close_object + json_add_object "disable_module" + json_add_string "module" "string" + json_close_object + json_add_object "check_module_enabled" + json_add_string "module" "string" + json_close_object json_add_object "health" json_close_object json_add_object "diagnostics" @@ -887,6 +1035,8 @@ case "$1" in json_close_object json_add_object "clear_alerts" json_close_object + json_add_object "fix_permissions" + json_close_object json_dump ;; call) @@ -927,6 +1077,27 @@ case "$1" in json_get_var module module "" restart_module "$module" ;; + enable_module) + read -r input + json_load "$input" + json_get_var module module "" + enable_module "$module" + ;; + disable_module) + read -r input + json_load "$input" + json_get_var module module "" + disable_module "$module" + ;; + check_module_enabled) + read -r input + json_load "$input" + json_get_var module module "" + local enabled=$(check_module_enabled "$module") + json_init + json_add_boolean "enabled" "$enabled" + json_dump + ;; health) get_health ;; @@ -960,6 +1131,9 @@ case "$1" in clear_alerts) clear_alerts ;; + fix_permissions) + fix_permissions + ;; *) echo '{"error":"Unknown method"}' ;; diff --git a/luci-app-secubox/root/usr/libexec/secubox/fix-permissions.sh b/luci-app-secubox/root/usr/libexec/secubox/fix-permissions.sh new file mode 100644 index 00000000..53c79abc --- /dev/null +++ b/luci-app-secubox/root/usr/libexec/secubox/fix-permissions.sh @@ -0,0 +1,169 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# SecuBox Permissions Fix Script +# Automatically fixes file permissions for SecuBox modules +# Copyright (C) 2025 CyberMind.fr + +set -e + +LOG_TAG="secubox-fix-perms" + +log_info() { + logger -t "$LOG_TAG" -p info "$1" + echo "[INFO] $1" +} + +log_error() { + logger -t "$LOG_TAG" -p err "$1" + echo "[ERROR] $1" >&2 +} + +fix_rpcd_permissions() { + log_info "Fixing RPCD script permissions..." + + local rpcd_scripts=" + /usr/libexec/rpcd/luci.secubox + /usr/libexec/rpcd/luci.system-hub + /usr/libexec/rpcd/luci.network-modes + /usr/libexec/rpcd/luci.crowdsec-dashboard + /usr/libexec/rpcd/luci.netdata-dashboard + /usr/libexec/rpcd/luci.netifyd-dashboard + /usr/libexec/rpcd/luci.wireguard-dashboard + /usr/libexec/rpcd/luci.client-guardian + /usr/libexec/rpcd/luci.bandwidth-manager + /usr/libexec/rpcd/luci.auth-guardian + /usr/libexec/rpcd/luci.media-flow + /usr/libexec/rpcd/luci.vhost-manager + /usr/libexec/rpcd/luci.traffic-shaper + /usr/libexec/rpcd/luci.cdn-cache + /usr/libexec/rpcd/luci.ksm-manager + " + + local count=0 + for script in $rpcd_scripts; do + if [ -f "$script" ]; then + chmod 755 "$script" 2>/dev/null && count=$((count + 1)) + fi + done + + log_info "Fixed $count RPCD scripts (755)" +} + +fix_web_permissions() { + log_info "Fixing web resources permissions..." + + # Fix CSS files + local css_count=0 + if [ -d "/www/luci-static/resources" ]; then + css_count=$(find /www/luci-static/resources -type f -name "*.css" -exec chmod 644 {} \; -print 2>/dev/null | wc -l) + fi + log_info "Fixed $css_count CSS files (644)" + + # Fix JS files + local js_count=0 + if [ -d "/www/luci-static/resources" ]; then + js_count=$(find /www/luci-static/resources -type f -name "*.js" -exec chmod 644 {} \; -print 2>/dev/null | wc -l) + fi + log_info "Fixed $js_count JS files (644)" +} + +fix_config_permissions() { + log_info "Fixing configuration file permissions..." + + local count=0 + + # Fix ACL files + for acl in /usr/share/rpcd/acl.d/luci-app-*.json; do + if [ -f "$acl" ]; then + chmod 644 "$acl" 2>/dev/null && count=$((count + 1)) + fi + done + + # Fix menu files + for menu in /usr/share/luci/menu.d/luci-app-*.json; do + if [ -f "$menu" ]; then + chmod 644 "$menu" 2>/dev/null && count=$((count + 1)) + fi + done + + log_info "Fixed $count config files (644)" +} + +restart_services() { + log_info "Restarting services..." + + if /etc/init.d/rpcd restart >/dev/null 2>&1; then + log_info "RPCD restarted successfully" + else + log_error "Failed to restart RPCD" + fi + + if /etc/init.d/uhttpd restart >/dev/null 2>&1; then + log_info "uHTTPd restarted successfully" + else + log_error "Failed to restart uHTTPd" + fi +} + +verify_permissions() { + log_info "Verifying permissions..." + + local errors=0 + + # Check RPCD scripts + for script in /usr/libexec/rpcd/luci.*; do + if [ -f "$script" ]; then + local perms=$(ls -l "$script" 2>/dev/null | cut -c1-10) + if [ "$perms" != "-rwxr-xr-x" ]; then + log_error "Invalid permissions on $script: $perms (expected -rwxr-xr-x)" + errors=$((errors + 1)) + fi + fi + done + + # Check critical files + for file in /www/luci-static/resources/secubox/api.js /www/luci-static/resources/secubox/dashboard.css; do + if [ -f "$file" ]; then + local perms=$(ls -l "$file" 2>/dev/null | cut -c1-10) + if [ "$perms" != "-rw-r--r--" ]; then + log_error "Invalid permissions on $file: $perms (expected -rw-r--r--)" + errors=$((errors + 1)) + fi + fi + done + + if [ $errors -eq 0 ]; then + log_info "All permissions verified successfully" + return 0 + else + log_error "Found $errors permission errors" + return 1 + fi +} + +main() { + echo "================================================" + echo " SecuBox Permissions Fix Script v0.3.1" + echo "================================================" + echo "" + + fix_rpcd_permissions + fix_web_permissions + fix_config_permissions + + echo "" + restart_services + + echo "" + verify_permissions + + echo "" + echo "================================================" + echo " Permissions fix completed!" + echo "================================================" +} + +# Run if executed directly +if [ "${0##*/}" = "fix-permissions.sh" ]; then + main "$@" +fi diff --git a/luci-app-secubox/root/usr/share/rpcd/acl.d/luci-app-secubox.json b/luci-app-secubox/root/usr/share/rpcd/acl.d/luci-app-secubox.json index 7f0ab1d2..0c8335f4 100644 --- a/luci-app-secubox/root/usr/share/rpcd/acl.d/luci-app-secubox.json +++ b/luci-app-secubox/root/usr/share/rpcd/acl.d/luci-app-secubox.json @@ -8,6 +8,7 @@ "modules", "modules_by_category", "module_info", + "check_module_enabled", "health", "diagnostics", "get_system_health", @@ -30,9 +31,12 @@ "start_module", "stop_module", "restart_module", + "enable_module", + "disable_module", "quick_action", "dismiss_alert", - "clear_alerts" + "clear_alerts", + "fix_permissions" ], "uci": [ "set", diff --git a/luci-app-system-hub/Makefile b/luci-app-system-hub/Makefile index 6cdac4af..ad8f4c73 100644 --- a/luci-app-system-hub/Makefile +++ b/luci-app-system-hub/Makefile @@ -11,6 +11,9 @@ LUCI_DESCRIPTION:=Central system control with monitoring, services, logs, and ba LUCI_DEPENDS:=+luci-base +rpcd +coreutils +coreutils-base64 LUCI_PKGARCH:=all +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.system-hub:755 + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-traffic-shaper/Makefile b/luci-app-traffic-shaper/Makefile index 4e844962..2bda9cc2 100644 --- a/luci-app-traffic-shaper/Makefile +++ b/luci-app-traffic-shaper/Makefile @@ -10,6 +10,10 @@ LUCI_TITLE:=Traffic Shaper - Advanced QoS Control LUCI_DESCRIPTION:=Advanced traffic shaping with TC/CAKE for precise bandwidth control LUCI_DEPENDS:=+luci-base +rpcd +tc +kmod-sched-core +kmod-sched-cake + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.traffic-shaper:755 + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-vhost-manager/Makefile b/luci-app-vhost-manager/Makefile index 966f6c89..a5c20e86 100644 --- a/luci-app-vhost-manager/Makefile +++ b/luci-app-vhost-manager/Makefile @@ -14,6 +14,10 @@ LUCI_DESCRIPTION:=Nginx reverse proxy manager with Let's Encrypt SSL certificate LUCI_DEPENDS:=+luci-base +rpcd +nginx-ssl +acme +curl LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.vhost-manager:755 + include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-wireguard-dashboard/Makefile b/luci-app-wireguard-dashboard/Makefile index 473c4f2c..41fad86b 100644 --- a/luci-app-wireguard-dashboard/Makefile +++ b/luci-app-wireguard-dashboard/Makefile @@ -20,6 +20,10 @@ LUCI_DEPENDS:=+luci-base +luci-app-secubox +luci-lib-jsonc +rpcd +rpcd-mod-luci LUCI_PKGARCH:=all + +# File permissions (RPCD scripts must be executable) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.wireguard-dashboard:755 + include $(TOPDIR)/feeds/luci/luci.mk define Package/$(PKG_NAME)/conffiles diff --git a/secubox-tools/add-pkg-file-modes.sh b/secubox-tools/add-pkg-file-modes.sh new file mode 100755 index 00000000..ecd86794 --- /dev/null +++ b/secubox-tools/add-pkg-file-modes.sh @@ -0,0 +1,209 @@ +#!/bin/bash +# Add PKG_FILE_MODES to OpenWrt Makefiles +# Automatically detects RPCD scripts and adds correct permissions +# +# Usage: ./add-pkg-file-modes.sh [module-path] +# ./add-pkg-file-modes.sh --all (process all luci-app-* modules) + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[OK]${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Detect RPCD scripts in a module +detect_rpcd_scripts() { + local module_path="$1" + local rpcd_dir="$module_path/root/usr/libexec/rpcd" + + if [ ! -d "$rpcd_dir" ]; then + return + fi + + find "$rpcd_dir" -type f -name "luci.*" 2>/dev/null | while read script; do + basename "$script" + done +} + +# Detect helper scripts in a module +detect_helper_scripts() { + local module_path="$1" + local helper_dir="$module_path/root/usr/libexec" + + if [ ! -d "$helper_dir" ]; then + return + fi + + # Find .sh files in subdirectories (not in rpcd/) + find "$helper_dir" -type f -name "*.sh" ! -path "*/rpcd/*" 2>/dev/null | while read script; do + echo "$script" | sed "s|^$module_path/root||" + done +} + +# Generate PKG_FILE_MODES line +generate_pkg_file_modes() { + local module_name="$1" + local rpcd_scripts="$2" + local helper_scripts="$3" + + local modes="" + + # Add RPCD scripts + for script in $rpcd_scripts; do + if [ -z "$modes" ]; then + modes="/usr/libexec/rpcd/$script:755" + else + modes="$modes \\\\\n\\t/usr/libexec/rpcd/$script:755" + fi + done + + # Add helper scripts + for script in $helper_scripts; do + if [ -z "$modes" ]; then + modes="$script:755" + else + modes="$modes \\\\\n\\t$script:755" + fi + done + + if [ -n "$modes" ]; then + echo -e "# File permissions (RPCD scripts must be executable)\nPKG_FILE_MODES:=$modes" + fi +} + +# Check if Makefile already has PKG_FILE_MODES +has_pkg_file_modes() { + local makefile="$1" + grep -q "^PKG_FILE_MODES:=" "$makefile" 2>/dev/null +} + +# Add PKG_FILE_MODES to Makefile +add_to_makefile() { + local makefile="$1" + local pkg_file_modes="$2" + + if [ ! -f "$makefile" ]; then + log_error "Makefile not found: $makefile" + return 1 + fi + + # Check if already exists + if has_pkg_file_modes "$makefile"; then + log_warning "PKG_FILE_MODES already exists in $makefile" + return 0 + fi + + # Find the line with 'include $(TOPDIR)/feeds/luci/luci.mk' + if ! grep -q "include.*luci.mk" "$makefile"; then + log_error "Cannot find luci.mk include in $makefile" + return 1 + fi + + # Create backup + cp "$makefile" "$makefile.bak" + + # Insert PKG_FILE_MODES before the include line + awk -v modes="$pkg_file_modes" ' + /^include.*luci\.mk/ { + print "" + print modes + print "" + } + { print } + ' "$makefile.bak" > "$makefile" + + log_success "Added PKG_FILE_MODES to $makefile" + rm -f "$makefile.bak" +} + +# Process a single module +process_module() { + local module_path="$1" + local module_name=$(basename "$module_path") + + log_info "Processing $module_name..." + + # Detect scripts + local rpcd_scripts=$(detect_rpcd_scripts "$module_path") + local helper_scripts=$(detect_helper_scripts "$module_path") + + if [ -z "$rpcd_scripts" ] && [ -z "$helper_scripts" ]; then + log_warning "No executable scripts found in $module_name" + return 0 + fi + + # Generate PKG_FILE_MODES + local pkg_file_modes=$(generate_pkg_file_modes "$module_name" "$rpcd_scripts" "$helper_scripts") + + if [ -z "$pkg_file_modes" ]; then + log_warning "Could not generate PKG_FILE_MODES for $module_name" + return 0 + fi + + # Add to Makefile + local makefile="$module_path/Makefile" + add_to_makefile "$makefile" "$pkg_file_modes" + + # Show what was added + echo "" + echo " Scripts found:" + [ -n "$rpcd_scripts" ] && echo " RPCD: $(echo $rpcd_scripts | tr '\n' ' ')" + [ -n "$helper_scripts" ] && echo " Helper: $(echo $helper_scripts | tr '\n' ' ')" + echo "" +} + +# Main +main() { + echo "================================================" + echo " PKG_FILE_MODES Auto-Configurator v0.3.1" + echo "================================================" + echo "" + + if [ "$1" = "--all" ]; then + log_info "Processing all luci-app-* modules..." + echo "" + + find "$PROJECT_ROOT" -maxdepth 1 -type d -name "luci-app-*" | sort | while read module_path; do + process_module "$module_path" + done + + elif [ -n "$1" ] && [ -d "$1" ]; then + process_module "$1" + + else + log_error "Usage: $0 [module-path] | --all" + log_info "Examples:" + log_info " $0 ../luci-app-secubox" + log_info " $0 --all" + exit 1 + fi + + echo "" + echo "================================================" + echo " Processing complete!" + echo "================================================" +} + +main "$@" diff --git a/templates/Makefile.template b/templates/Makefile.template index 104b6f46..e07c6a95 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -14,9 +14,14 @@ PKG_MAINTAINER:=CyberMind # LuCI specific LUCI_TITLE:=LuCI - Package Description LUCI_DESCRIPTION:=Detailed description of what this package does -LUCI_DEPENDS:=+luci-base +LUCI_DEPENDS:=+luci-base +rpcd LUCI_PKGARCH:=all +# File permissions (CRITICAL: RPCD scripts MUST be executable) +# CSS/JS files are 644 by default (correct) +# Only specify files that need non-default permissions (755 for executables) +PKG_FILE_MODES:=/usr/libexec/rpcd/luci.PACKAGE_NAME:755 + # Include LuCI build system include $(TOPDIR)/feeds/luci/luci.mk