From 4fee9e4c1267bf69493a7c32dc676b980293f738 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Wed, 25 Feb 2026 13:42:41 +0100 Subject: [PATCH] feat(secubox-users): Add Gitea integration with password sync - Add Gitea as a service option in SecuBox Users UI - Add Gitea checkbox in Add User modal - Add Gitea service badge in status display - Implement password sync to Gitea via API on password change - Fix Gitea API call to include login_name parameter - Add gitea to check_service() and get_status() - Sync passwords to all enabled services (email, jabber, nextcloud, gitea) Co-Authored-By: Claude Opus 4.5 --- .claude/HISTORY.md | 30 +++++++ .../resources/view/secubox-users/overview.js | 7 +- .../root/usr/libexec/rpcd/luci.secubox-users | 86 ++++++++++++++++++- 3 files changed, 120 insertions(+), 3 deletions(-) diff --git a/.claude/HISTORY.md b/.claude/HISTORY.md index 7e854554..302c5888 100644 --- a/.claude/HISTORY.md +++ b/.claude/HISTORY.md @@ -3639,3 +3639,33 @@ git checkout HEAD -- index.html - Added route to mitmproxy-in for WAF inspection - **Files Modified:** - `luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit`: upload_app, upload_and_deploy with KISS ZIP handling + +36. **ALERTE.DEPOT Whistleblower Platform (2026-02-25)** + - **Anonymous Whistleblower Application (Loi Waserman compliant):** + - Pseudonymized submissions - no personal data required + - Token-based tracking (16-char alphanumeric tokens) + - Three modes: Submit / Track / Admin + - SecuBox Users authentication for investigators + - Gitea backend (private repo: gandalf/alertes-depot) + - QR code generation for attestations + - **Tracking Portal:** + - Token lookup searches Gitea issues + - Status display with visual badges + - Two-way communication with investigators + - Add supplementary information capability + - **Admin Dashboard:** + - SecuBox Users RPCD authentication + - Case management with status workflow + - Internal notes vs public responses + - Statistics overview + - **Security & Compliance:** + - Audit trail blockchain (/srv/secubox/mesh/alertes-chain.json) + - Deadline monitoring cron (7-day ack, 3-month response) + - Immutable hash chain for all actions + - **Dual-Channel Access:** + - HTTPS: alerte.gk2.secubox.in (production SSL cert) + - Tor: i7j46m67zvdksfhddbq273yydpuo5xvewsl2fjl5zlycjyo4qelysnid.onion + - **Files:** + - `/srv/streamlit/apps/alerte_depot/app.py`: Full whistleblower platform + - `/srv/secubox/mesh/alertes-chain.json`: Audit blockchain + - `/usr/sbin/alerte-depot-cron`: Deadline monitor diff --git a/package/secubox/luci-app-secubox-users/htdocs/luci-static/resources/view/secubox-users/overview.js b/package/secubox/luci-app-secubox-users/htdocs/luci-static/resources/view/secubox-users/overview.js index b9d574e3..b85f65a8 100644 --- a/package/secubox/luci-app-secubox-users/htdocs/luci-static/resources/view/secubox-users/overview.js +++ b/package/secubox/luci-app-secubox-users/htdocs/luci-static/resources/view/secubox-users/overview.js @@ -116,7 +116,8 @@ return view.extend({ E('label', { 'style': 'margin-left:10px;' }, [E('input', { 'type': 'checkbox', 'id': 'svc-peertube', 'checked': true }), ' PeerTube']), E('label', { 'style': 'margin-left:10px;' }, [E('input', { 'type': 'checkbox', 'id': 'svc-jabber', 'checked': true }), ' Jabber']), E('label', { 'style': 'margin-left:10px;' }, [E('input', { 'type': 'checkbox', 'id': 'svc-matrix', 'checked': true }), ' Matrix']), - E('label', { 'style': 'margin-left:10px;' }, [E('input', { 'type': 'checkbox', 'id': 'svc-email', 'checked': true }), ' Email']) + E('label', { 'style': 'margin-left:10px;' }, [E('input', { 'type': 'checkbox', 'id': 'svc-email', 'checked': true }), ' Email']), + E('label', { 'style': 'margin-left:10px;' }, [E('input', { 'type': 'checkbox', 'id': 'svc-gitea', 'checked': true }), ' Gitea']) ]) ]) ]), @@ -136,6 +137,7 @@ return view.extend({ if (document.getElementById('svc-jabber').checked) services.push('jabber'); if (document.getElementById('svc-matrix').checked) services.push('matrix'); if (document.getElementById('svc-email').checked) services.push('email'); + if (document.getElementById('svc-gitea').checked) services.push('gitea'); if (!username) { ui.addNotification(null, E('p', {}, _('Username required')), 'error'); @@ -263,7 +265,8 @@ return view.extend({ this.renderServiceBadge('PeerTube', services.peertube), this.renderServiceBadge('Matrix', services.matrix), this.renderServiceBadge('Jabber', services.jabber), - this.renderServiceBadge('Email', services.email) + this.renderServiceBadge('Email', services.email), + this.renderServiceBadge('Gitea', services.gitea) ]), E('p', { 'style': 'color:#666;' }, _('Domain: %s | Users: %d').format(status.domain, status.user_count)) ])); diff --git a/package/secubox/luci-app-secubox-users/root/usr/libexec/rpcd/luci.secubox-users b/package/secubox/luci-app-secubox-users/root/usr/libexec/rpcd/luci.secubox-users index e9089295..5a64359b 100644 --- a/package/secubox/luci-app-secubox-users/root/usr/libexec/rpcd/luci.secubox-users +++ b/package/secubox/luci-app-secubox-users/root/usr/libexec/rpcd/luci.secubox-users @@ -16,6 +16,7 @@ check_service() { matrix) [ -x /usr/sbin/matrixctl ] && lxc-info -n matrix 2>/dev/null | grep -q "RUNNING" && echo "1" || echo "0" ;; jabber) [ -x /usr/sbin/jabberctl ] && lxc-info -n jabber 2>/dev/null | grep -q "RUNNING" && echo "1" || echo "0" ;; email) [ -x /usr/sbin/mailserverctl ] && lxc-info -n mailserver 2>/dev/null | grep -q "RUNNING" && echo "1" || echo "0" ;; + gitea) [ -x /usr/sbin/giteactl ] && lxc-info -n gitea 2>/dev/null | grep -q "RUNNING" && echo "1" || echo "0" ;; *) echo "0" ;; esac } @@ -30,6 +31,7 @@ get_status() { local mx_running=$(check_service matrix) local jb_running=$(check_service jabber) local em_running=$(check_service email) + local gt_running=$(check_service gitea) cat </dev/null | tr ' ' '\n' | sort -u) + local synced="" + local failed="" + + for svc in $services; do + case "$svc" in + gitea) + local gitea_url=$(uci -q get gitea.main.url 2>/dev/null || echo "http://192.168.255.1:3001") + local gitea_token=$(uci -q get gitea.main.token 2>/dev/null) + if [ -n "$gitea_token" ]; then + local result=$(curl -s -X PATCH \ + -H "Authorization: token $gitea_token" \ + -H "Content-Type: application/json" \ + -d "{\"login_name\":\"$username\",\"password\":\"$password\"}" \ + "${gitea_url}/api/v1/admin/users/${username}" 2>/dev/null) + if echo "$result" | grep -q "\"username\""; then + synced="$synced gitea" + else + failed="$failed gitea" + fi + fi + ;; + email) + if [ -x /usr/sbin/mailserverctl ]; then + local domain=$(uci -q get ${CONFIG}.main.domain || echo "secubox.in") + local email="${username}@${domain}" + . /usr/lib/mailserver/users.sh 2>/dev/null + if user_passwd "$email" "$password" >/dev/null 2>&1; then + synced="$synced email" + else + failed="$failed email" + fi + fi + ;; + jabber) + if [ -x /usr/sbin/jabberctl ]; then + local domain=$(uci -q get ${CONFIG}.main.domain || echo "secubox.in") + if jabberctl user passwd "${username}@${domain}" "$password" >/dev/null 2>&1; then + synced="$synced jabber" + else + failed="$failed jabber" + fi + fi + ;; + nextcloud) + if [ -x /usr/sbin/nextcloudctl ]; then + export OC_PASS="$password" + if nextcloudctl occ user:resetpassword "$username" --password-from-env >/dev/null 2>&1; then + synced="$synced nextcloud" + else + failed="$failed nextcloud" + fi + fi + ;; + esac + done + + logger -t secubox-users "Password updated for $username (synced:$synced failed:$failed)" + json_init json_add_boolean "success" 1 json_add_string "password" "$password" + json_add_string "synced" "$synced" + json_add_string "failed" "$failed" json_dump else json_init @@ -367,6 +432,25 @@ change_password() { fi fi ;; + gitea) + # Sync password to Gitea via API + local gitea_url=$(uci -q get gitea.main.url 2>/dev/null || echo "http://192.168.255.1:3001") + local gitea_token=$(uci -q get gitea.main.token 2>/dev/null) + if [ -n "$gitea_token" ]; then + local result=$(curl -s -X PATCH \ + -H "Authorization: token $gitea_token" \ + -H "Content-Type: application/json" \ + -d "{\"login_name\":\"$username\",\"password\":\"$new_password\"}" \ + "${gitea_url}/api/v1/admin/users/${username}" 2>/dev/null) + if echo "$result" | grep -q "\"username\""; then + synced="$synced gitea" + else + failed="$failed gitea" + fi + else + failed="$failed gitea(no-token)" + fi + ;; nextcloud) if [ -x /usr/sbin/nextcloudctl ]; then export OC_PASS="$new_password"