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>
This commit is contained in:
Executable
+83
@@ -0,0 +1,83 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user