Make admin seed idempotent-upsert so a corrupted password can be fixed by restart
Grund: $ in SEED_ADMIN_PASSWORD wird von Docker-Compose/Portainer als Variablen-Referenz interpretiert und kann dadurch verstümmelt beim Container ankommen. Seed synct das Passwort jetzt bei jedem Start neu, solange die Variable gesetzt ist, statt nur einmalig anzulegen. README um Warnhinweis ergänzt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
11a3753d76
commit
ca5d240cf6
@@ -102,14 +102,21 @@ Benutzername anmelden". Damit das funktioniert, muss im Portainer-Stack `JWT_SEC
|
|||||||
gesetzt sein (Schritt 4).
|
gesetzt sein (Schritt 4).
|
||||||
|
|
||||||
Ein erstes Konto legt der Server **automatisch beim Start** an, wenn
|
Ein erstes Konto legt der Server **automatisch beim Start** an, wenn
|
||||||
`SEED_ADMIN_USERNAME` und `SEED_ADMIN_PASSWORD` als Stack-Env gesetzt sind (idempotent –
|
`SEED_ADMIN_USERNAME` und `SEED_ADMIN_PASSWORD` als Stack-Env gesetzt sind (Upsert –
|
||||||
läuft bei jedem Neustart mit, legt aber nur an, was noch nicht existiert). Das
|
läuft bei jedem Neustart mit und synchronisiert das Passwort neu, solange die Variable
|
||||||
Klartext-Passwort steht dabei nur in der Portainer-Stack-Konfiguration, nie im Git-Repo –
|
gesetzt ist – ein falsch übernommenes Passwort lässt sich also einfach per Neustart
|
||||||
der Server speichert ausschließlich einen bcrypt-Hash in der Datenbank.
|
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
|
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,
|
das Konto wie gewünscht funktioniert – `SEED_ADMIN_USERNAME` kann stehen bleiben, ohne
|
||||||
ohne Passwort passiert dann nichts mehr. Weitere lokale Konten aktuell nur direkt in der
|
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
|
Datenbank anlegbar (`INSERT INTO users …` mit einem bcrypt-Hash) – ein Verwaltungs-UI
|
||||||
dafür gibt es noch nicht.
|
dafür gibt es noch nicht.
|
||||||
|
|
||||||
|
|||||||
+10
-7
@@ -31,18 +31,21 @@ app.get(/^(?!\/api\/).*/, (_req, res) => {
|
|||||||
res.sendFile(path.join(PUBLIC_DIR, 'index.html'));
|
res.sendFile(path.join(PUBLIC_DIR, 'index.html'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Legt beim ersten Start ein lokales Fallback-Konto an, falls SEED_ADMIN_USERNAME/
|
// Legt beim Start ein lokales Fallback-Konto an bzw. hält es synchron, solange
|
||||||
// SEED_ADMIN_PASSWORD gesetzt sind und noch kein Konto mit diesem Namen existiert.
|
// SEED_ADMIN_USERNAME/SEED_ADMIN_PASSWORD gesetzt sind (Upsert – so lässt sich ein
|
||||||
// Idempotent – kann bei jedem Neustart stehen bleiben, legt nichts doppelt an.
|
// falsch übernommenes Passwort einfach per Neustart korrigieren). Danach die
|
||||||
|
// SEED_ADMIN_PASSWORD-Variable aus dem Stack entfernen, um das Konto "einzufrieren".
|
||||||
async function seedAdminIfConfigured() {
|
async function seedAdminIfConfigured() {
|
||||||
const username = process.env.SEED_ADMIN_USERNAME;
|
const username = process.env.SEED_ADMIN_USERNAME;
|
||||||
const password = process.env.SEED_ADMIN_PASSWORD;
|
const password = process.env.SEED_ADMIN_PASSWORD;
|
||||||
if (!username || !password) return;
|
if (!username || !password) return;
|
||||||
const existing = await prisma.user.findUnique({ where: { username } });
|
|
||||||
if (existing) return;
|
|
||||||
const passwordHash = await bcrypt.hash(password, 12);
|
const passwordHash = await bcrypt.hash(password, 12);
|
||||||
await prisma.user.create({ data: { username, passwordHash, name: username } });
|
await prisma.user.upsert({
|
||||||
console.log(`Lokales Konto "${username}" angelegt.`);
|
where: { username },
|
||||||
|
update: { passwordHash },
|
||||||
|
create: { username, passwordHash, name: username }
|
||||||
|
});
|
||||||
|
console.log(`Lokales Konto "${username}" angelegt/aktualisiert.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
seedAdminIfConfigured()
|
seedAdminIfConfigured()
|
||||||
|
|||||||
Reference in New Issue
Block a user