add the emergency relocate/reset-mfa scripts the tests exercise

This commit is contained in:
Jarek Krochmalski committed 2026-08-27 07:41:02 +02:00
1 parent d34a7733f7
commit e7ee9b41c7
7 files changed
+621

No files matched your search

+72
View File
@@ -0,0 +1,72 @@
#!/bin/sh
#
# SQLite: relocate stored stack paths after a DATA_DIR change.
# See ../relocate-stack-paths.sh for usage. Does NOT move files - updates DB only.
set -e
DB_LABEL="SQLite"
# Locate the database (env override, Docker default, then local dev).
DB_PATH="${DOCKHAND_DB:-/app/data/db/dockhand.db}"
if [ ! -f "$DB_PATH" ] && [ -f "./data/db/dockhand.db" ]; then
DB_PATH="./data/db/dockhand.db"
fi
if [ ! -f "$DB_PATH" ]; then
echo "Error: SQLite database not found at $DB_PATH"
echo "Set DOCKHAND_DB to the database path."
exit 1
fi
DB_DISPLAY="$DB_PATH"
# SQL-escape a value for single-quoted string literals.
_sql_escape() { printf "%s" "$1" | sed "s/'/''/g"; }
db_list_stack_paths() {
# One line per non-null compose/env path: <id>\t<field>\t<label>\t<path>
sqlite3 -separator ' ' "$DB_PATH" "
SELECT s.id, 'compose',
s.stack_name || CASE WHEN e.name IS NOT NULL THEN ' (' || e.name || ')' ELSE '' END,
s.compose_path
FROM stack_sources s LEFT JOIN environments e ON e.id = s.environment_id
WHERE s.compose_path IS NOT NULL AND s.compose_path <> ''
UNION ALL
SELECT s.id, 'env',
s.stack_name || CASE WHEN e.name IS NOT NULL THEN ' (' || e.name || ')' ELSE '' END,
s.env_path
FROM stack_sources s LEFT JOIN environments e ON e.id = s.environment_id
WHERE s.env_path IS NOT NULL AND s.env_path <> ''
ORDER BY 1;
"
}
db_list_external_paths() {
# settings.external_stack_paths is a JSON array; emit <index>\t<path> per entry.
# Use json_each so commas/quotes/escapes inside a path are handled correctly.
sqlite3 -separator ' ' "$DB_PATH" "
SELECT je.key, je.value
FROM settings s, json_each(s.value) je
WHERE s.key = 'external_stack_paths';
" 2>/dev/null
}
db_update_stack_path() {
id="$1"; field="$2"; new="$(_sql_escape "$3")"
col="compose_path"; [ "$field" = "env" ] && col="env_path"
sqlite3 "$DB_PATH" "UPDATE stack_sources SET $col = '$new', updated_at = datetime('now') WHERE id = $id;"
}
db_update_external_path() {
idx="$1"; new="$(_sql_escape "$2")"
# Replace ONLY entry <idx> via json_set; other entries (and any commas/escapes in
# them) are left byte-for-byte intact.
sqlite3 "$DB_PATH" "
UPDATE settings
SET value = json_set(value, '\$[$idx]', '$new'), updated_at = datetime('now')
WHERE key = 'external_stack_paths';
"
}
. "$(dirname "$0")/../_relocate-common.sh"
parse_relocate_args "$@"
run_relocation
+96
View File
@@ -0,0 +1,96 @@
#!/bin/sh
#
# SQLite: Emergency script to disable a user's MFA (TOTP)
# Use this if a user is locked out of MFA (lost their authenticator app)
#
# Usage:
# docker exec -it dockhand /app/scripts/emergency/sqlite/reset-mfa.sh <username>
#
# Example:
# docker exec -it dockhand /app/scripts/emergency/sqlite/reset-mfa.sh admin
#
set -e
echo "========================================"
echo " Dockhand - Reset User MFA (SQLite)"
echo "========================================"
echo ""
# Check arguments
if [ -z "$1" ]; then
echo "Usage: $0 <username>"
echo ""
echo "Example:"
echo " $0 admin"
exit 1
fi
USERNAME="$1"
# Default database path
DB_PATH="${DOCKHAND_DB:-/app/data/db/dockhand.db}"
# Check if running locally (not in Docker)
if [ ! -f "$DB_PATH" ] && [ -f "./data/db/dockhand.db" ]; then
DB_PATH="./data/db/dockhand.db"
fi
if [ ! -f "$DB_PATH" ]; then
echo "Error: Database not found at $DB_PATH"
echo "Set DOCKHAND_DB environment variable to specify the database path"
exit 1
fi
# Check if user exists
EXISTING=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM users WHERE username='$USERNAME';")
if [ "$EXISTING" -eq "0" ]; then
echo "Error: User '$USERNAME' not found"
echo ""
echo "Available users:"
sqlite3 "$DB_PATH" "SELECT username FROM users;" | while read user; do
echo " - $user"
done
exit 1
fi
# Show current MFA state
MFA_ENABLED=$(sqlite3 "$DB_PATH" "SELECT mfa_enabled FROM users WHERE username='$USERNAME';")
if [ "$MFA_ENABLED" = "1" ] || [ "$MFA_ENABLED" = "true" ]; then
STATUS="enabled"
else
STATUS="already disabled"
fi
echo "This script will disable MFA (TOTP) for user '$USERNAME'."
echo "Backup codes will also be wiped — they cannot be reused."
echo ""
echo "Database: $DB_PATH"
echo "Username: $USERNAME"
echo "Current MFA: $STATUS"
echo ""
printf "Continue? [y/N]: "
read CONFIRM
case "$CONFIRM" in
[yY]|[yY][eE][sS])
;;
*)
echo "Aborted."
exit 0
;;
esac
echo ""
echo "Disabling MFA for user '$USERNAME'..."
sqlite3 "$DB_PATH" "UPDATE users SET mfa_enabled=0, mfa_secret=NULL, updated_at=datetime('now') WHERE username='$USERNAME';"
if [ $? -eq 0 ]; then
echo ""
echo "MFA disabled successfully for user '$USERNAME'."
echo "The user can now log in with just their password and can re-enable MFA from their profile."
else
echo "Error: Failed to disable MFA"
exit 1
fi