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 <noreply@anthropic.com>
This commit is contained in:
parent
33426e90e5
commit
4fee9e4c12
@ -3639,3 +3639,33 @@ git checkout HEAD -- index.html
|
|||||||
- Added route to mitmproxy-in for WAF inspection
|
- Added route to mitmproxy-in for WAF inspection
|
||||||
- **Files Modified:**
|
- **Files Modified:**
|
||||||
- `luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit`: upload_app, upload_and_deploy with KISS ZIP handling
|
- `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
|
||||||
|
|||||||
@ -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-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-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-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-jabber').checked) services.push('jabber');
|
||||||
if (document.getElementById('svc-matrix').checked) services.push('matrix');
|
if (document.getElementById('svc-matrix').checked) services.push('matrix');
|
||||||
if (document.getElementById('svc-email').checked) services.push('email');
|
if (document.getElementById('svc-email').checked) services.push('email');
|
||||||
|
if (document.getElementById('svc-gitea').checked) services.push('gitea');
|
||||||
|
|
||||||
if (!username) {
|
if (!username) {
|
||||||
ui.addNotification(null, E('p', {}, _('Username required')), 'error');
|
ui.addNotification(null, E('p', {}, _('Username required')), 'error');
|
||||||
@ -263,7 +265,8 @@ return view.extend({
|
|||||||
this.renderServiceBadge('PeerTube', services.peertube),
|
this.renderServiceBadge('PeerTube', services.peertube),
|
||||||
this.renderServiceBadge('Matrix', services.matrix),
|
this.renderServiceBadge('Matrix', services.matrix),
|
||||||
this.renderServiceBadge('Jabber', services.jabber),
|
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))
|
E('p', { 'style': 'color:#666;' }, _('Domain: %s | Users: %d').format(status.domain, status.user_count))
|
||||||
]));
|
]));
|
||||||
|
|||||||
@ -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" ;;
|
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" ;;
|
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" ;;
|
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" ;;
|
*) echo "0" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@ -30,6 +31,7 @@ get_status() {
|
|||||||
local mx_running=$(check_service matrix)
|
local mx_running=$(check_service matrix)
|
||||||
local jb_running=$(check_service jabber)
|
local jb_running=$(check_service jabber)
|
||||||
local em_running=$(check_service email)
|
local em_running=$(check_service email)
|
||||||
|
local gt_running=$(check_service gitea)
|
||||||
|
|
||||||
cat <<EOFJ
|
cat <<EOFJ
|
||||||
{
|
{
|
||||||
@ -41,7 +43,8 @@ get_status() {
|
|||||||
"peertube": $pt_running,
|
"peertube": $pt_running,
|
||||||
"matrix": $mx_running,
|
"matrix": $mx_running,
|
||||||
"jabber": $jb_running,
|
"jabber": $jb_running,
|
||||||
"email": $em_running
|
"email": $em_running,
|
||||||
|
"gitea": $gt_running
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOFJ
|
EOFJ
|
||||||
@ -156,9 +159,71 @@ update_password() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if echo "$output" | grep -q "Password updated"; then
|
if echo "$output" | grep -q "Password updated"; then
|
||||||
|
# Sync to all enabled services
|
||||||
|
local services=$(uci -q get ${CONFIG}.${username}.services 2>/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_init
|
||||||
json_add_boolean "success" 1
|
json_add_boolean "success" 1
|
||||||
json_add_string "password" "$password"
|
json_add_string "password" "$password"
|
||||||
|
json_add_string "synced" "$synced"
|
||||||
|
json_add_string "failed" "$failed"
|
||||||
json_dump
|
json_dump
|
||||||
else
|
else
|
||||||
json_init
|
json_init
|
||||||
@ -367,6 +432,25 @@ change_password() {
|
|||||||
fi
|
fi
|
||||||
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)
|
nextcloud)
|
||||||
if [ -x /usr/sbin/nextcloudctl ]; then
|
if [ -x /usr/sbin/nextcloudctl ]; then
|
||||||
export OC_PASS="$new_password"
|
export OC_PASS="$new_password"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user