3dda83314a
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>
84 lines
2.3 KiB
Bash
Executable File
84 lines
2.3 KiB
Bash
Executable File
#!/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
|