/** * Diagnose: findet Portal-Kunden, deren gespeichertes (verschlüsseltes) * Passwort NICHT zum Login-Hash (bcrypt) passt. Solche „Desyncs" führen dazu, * dass der Reveal/Send-Credentials ein Passwort ausgibt, das beim Login * scheitert. Seit dem Reveal-Konsistenzcheck werden sie nicht mehr ausgegeben – * dieses Script findet bestehende Altlasten (z.B. aus manuellen DB-Eingriffen * oder alten Code-Versionen), damit man sie gezielt neu setzen kann. * * Aufruf (im Backend-Container/-Verzeichnis): * npx tsx scripts/check-portal-password-sync.ts * Nur Diagnose – ändert NICHTS. */ import { PrismaClient } from '@prisma/client'; import bcrypt from 'bcryptjs'; import { decrypt } from '../src/utils/encryption.js'; const prisma = new PrismaClient(); async function main() { const customers = await prisma.customer.findMany({ where: { portalPasswordEncrypted: { not: null }, portalPasswordHash: { not: null } }, select: { id: true, customerNumber: true, portalEmail: true, portalPasswordEncrypted: true, portalPasswordHash: true, }, }); let desync = 0; for (const c of customers) { let decrypted: string; try { decrypted = decrypt(c.portalPasswordEncrypted!); } catch { desync++; console.log(`DESYNC (Entschlüsselung fehlgeschlagen): Kunde #${c.id} ${c.customerNumber}`); continue; } const matches = await bcrypt.compare(decrypted, c.portalPasswordHash!); if (!matches) { desync++; console.log(`DESYNC: Kunde #${c.id} ${c.customerNumber} (${c.portalEmail ?? '-'}) – gespeichertes Passwort passt nicht zum Login-Hash`); } } console.log(`\nGeprüft: ${customers.length} Portal-Kunden mit beiden Feldern. Desync: ${desync}.`); if (desync > 0) { console.log('→ Für diese Kunden bitte ein neues Portal-Passwort setzen/generieren.'); } else { console.log('→ Alles konsistent.'); } await prisma.$disconnect(); } main().catch((e) => { console.error(e); process.exit(1); });