Files
opencrm/scripts/admin-rescue.sh
T
duffyduck 3dda83314a Admin-Rescue: PW-Reset direkt in DB + Rate-Limit-Reset
Use Case: Admin sperrt sich aus (admin@admin.com ist keine echte
Mailadresse, Passwort-vergessen-Flow kann keine Mail liefern) oder
Brute-Force-Lockout will sich nicht von selbst auflösen.

backend/prisma/reset-admin-password.ts:
- Findet User per Email, hasht neues PW mit bcrypt cost 12
- Schreibt direkt in user.password, setzt tokenInvalidatedAt=now()
  (kickt alle bestehenden Sessions), löscht Reset-Tokens
- Eigenes PW: Komplexitäts-Check 25 Zeichen
- Kein PW-Argument: 28-char Zufallspasswort (alle 4 Klassen
  garantiert), wird einmal in stdout ausgegeben

scripts/admin-rescue.sh:
- password <email> [pw]  → docker exec npx tsx … reset-admin-password
- unlock                  → docker restart opencrm-app (leert
                            In-Memory-Rate-Limit-Store)
- all <email> [pw]        → beides

Live-verifiziert: random-Modus, schwaches PW → klare Fehlerliste,
langes eigenes PW → akzeptiert, unbekannter User → exit 2, bash -n
syntax-check ok.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 15:47:02 +02:00

84 lines
2.3 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
#
# Notfall-Wrapper für ausgesperrte Admins.
#
# 1. password Setzt das Passwort eines Mitarbeiter-Users direkt in der
# DB (umgeht jegliche Auth). Wird im laufenden Backend-
# Container über npx tsx ausgeführt, damit bcrypt + Prisma-
# Schema garantiert konsistent sind.
# 2. unlock Restartet den Backend-Container → leert den In-Memory-
# Rate-Limit-Store komplett (alle gesperrten IPs).
# 3. all Beides: PW setzen UND Rate-Limit leeren.
#
# Aufruf (im Repo-Root):
# ./scripts/admin-rescue.sh password <email> [neues-passwort]
# ./scripts/admin-rescue.sh unlock
# ./scripts/admin-rescue.sh all <email> [neues-passwort]
#
# Ohne neues-passwort wird ein 28-Zeichen-Zufallspasswort generiert und
# einmalig in stdout ausgegeben.
set -e
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
cd "$REPO_ROOT"
CONTAINER="opencrm-app"
usage() {
echo "Aufruf:"
echo " $0 password <email> [neues-passwort] Admin-Passwort direkt in DB setzen"
echo " $0 unlock Rate-Limit-Store leeren (Container-Restart)"
echo " $0 all <email> [neues-passwort] beides"
exit 1
}
require_container_running() {
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER}\$"; then
echo "Container '${CONTAINER}' läuft nicht. Erst docker compose up -d." >&2
exit 2
fi
}
reset_password() {
local email="$1"
local pw="$2"
require_container_running
if [ -z "$email" ]; then
echo "Email fehlt." >&2
usage
fi
echo "Setze Passwort für ${email} im Container ${CONTAINER}"
if [ -n "$pw" ]; then
docker exec -it "$CONTAINER" npx tsx prisma/reset-admin-password.ts "$email" "$pw"
else
docker exec -it "$CONTAINER" npx tsx prisma/reset-admin-password.ts "$email"
fi
}
unlock_rate_limit() {
require_container_running
echo "Restarte ${CONTAINER} → Rate-Limit-Store wird geleert…"
docker restart "$CONTAINER" >/dev/null
echo "Fertig. Container hochgefahren."
}
case "${1:-}" in
password)
shift
reset_password "$@"
;;
unlock)
unlock_rate_limit
;;
all)
shift
reset_password "$@"
unlock_rate_limit
;;
*)
usage
;;
esac