diff --git a/README.md b/README.md index cea8ef9..63737bb 100644 --- a/README.md +++ b/README.md @@ -102,14 +102,21 @@ Benutzername anmelden". Damit das funktioniert, muss im Portainer-Stack `JWT_SEC gesetzt sein (Schritt 4). Ein erstes Konto legt der Server **automatisch beim Start** an, wenn -`SEED_ADMIN_USERNAME` und `SEED_ADMIN_PASSWORD` als Stack-Env gesetzt sind (idempotent – -läuft bei jedem Neustart mit, legt aber nur an, was noch nicht existiert). Das -Klartext-Passwort steht dabei nur in der Portainer-Stack-Konfiguration, nie im Git-Repo – -der Server speichert ausschließlich einen bcrypt-Hash in der Datenbank. +`SEED_ADMIN_USERNAME` und `SEED_ADMIN_PASSWORD` als Stack-Env gesetzt sind (Upsert – +läuft bei jedem Neustart mit und synchronisiert das Passwort neu, solange die Variable +gesetzt ist – ein falsch übernommenes Passwort lässt sich also einfach per Neustart +korrigieren). Das Klartext-Passwort steht dabei nur in der Portainer-Stack-Konfiguration, +nie im Git-Repo – der Server speichert ausschließlich einen bcrypt-Hash in der Datenbank. + +**Vorsicht bei `$` im Passwort:** Docker-Compose/Portainer interpretieren `$` in +Env-Werten als Beginn einer Variablen-Referenz (`$xyz` wird als `${xyz}` gelesen und bei +fehlender Definition oft still zu leer aufgelöst) – ein Passwort mit `$` kann dadurch +unbemerkt anders ankommen, als eingetippt. Entweder jedes `$` im Passwortwert als `$$` +escapen, oder – einfacher – ein Passwort ohne `$` verwenden. Optional danach `SEED_ADMIN_PASSWORD` aus dem Stack wieder entfernen (Härtung), sobald -das Konto einmal erfolgreich angelegt wurde – `SEED_ADMIN_USERNAME` kann stehen bleiben, -ohne Passwort passiert dann nichts mehr. Weitere lokale Konten aktuell nur direkt in der +das Konto wie gewünscht funktioniert – `SEED_ADMIN_USERNAME` kann stehen bleiben, ohne +Passwort-Variable wird nichts mehr verändert. Weitere lokale Konten aktuell nur direkt in der Datenbank anlegbar (`INSERT INTO users …` mit einem bcrypt-Hash) – ein Verwaltungs-UI dafür gibt es noch nicht. diff --git a/server/src/index.ts b/server/src/index.ts index b4ab84a..cdd55fa 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -31,18 +31,21 @@ app.get(/^(?!\/api\/).*/, (_req, res) => { res.sendFile(path.join(PUBLIC_DIR, 'index.html')); }); -// Legt beim ersten Start ein lokales Fallback-Konto an, falls SEED_ADMIN_USERNAME/ -// SEED_ADMIN_PASSWORD gesetzt sind und noch kein Konto mit diesem Namen existiert. -// Idempotent – kann bei jedem Neustart stehen bleiben, legt nichts doppelt an. +// Legt beim Start ein lokales Fallback-Konto an bzw. hält es synchron, solange +// SEED_ADMIN_USERNAME/SEED_ADMIN_PASSWORD gesetzt sind (Upsert – so lässt sich ein +// falsch übernommenes Passwort einfach per Neustart korrigieren). Danach die +// SEED_ADMIN_PASSWORD-Variable aus dem Stack entfernen, um das Konto "einzufrieren". async function seedAdminIfConfigured() { const username = process.env.SEED_ADMIN_USERNAME; const password = process.env.SEED_ADMIN_PASSWORD; if (!username || !password) return; - const existing = await prisma.user.findUnique({ where: { username } }); - if (existing) return; const passwordHash = await bcrypt.hash(password, 12); - await prisma.user.create({ data: { username, passwordHash, name: username } }); - console.log(`Lokales Konto "${username}" angelegt.`); + await prisma.user.upsert({ + where: { username }, + update: { passwordHash }, + create: { username, passwordHash, name: username } + }); + console.log(`Lokales Konto "${username}" angelegt/aktualisiert.`); } seedAdminIfConfigured()