// Die Passwortregeln — noch einmal, für die Oberfläche. // // Verbindlich ist app_passwort_regeln() in der Datenbank // (20260908120000). Hier stehen dieselben Regeln ein zweites Mal, damit die // Maske sie beim Tippen anzeigen kann statt erst nach dem Absenden. Dieselbe // Doppelung wie in lib/history.ts, aus demselben Grund und mit derselben // Rangfolge: läuft eine Seite der anderen davon, gewinnt die Datenbank — sie // weist ab, und die Meldung von dort wird angezeigt. /** Was in der Maske als Hinweis steht. Reihenfolge wie in der SQL-Funktion. */ export const PASSWORT_REGELN = [ "mindestens 12 Zeichen", "mindestens ein Grossbuchstabe", "mindestens ein Kleinbuchstabe", "mindestens eine Ziffer", ] as const; /** * Liefert die Beanstandung im Klartext oder null. * * Wortgleich mit app_passwort_regeln(). Ein Unterschied bleibt und ist * unvermeidbar: `length()` in PostgreSQL zählt Zeichen, `String.length` in * JavaScript zählt UTF-16-Einheiten. Bei einem Emoji im Passwort weichen die * beiden um eins ab. Das betrifft nur die Vorabanzeige — abgewiesen oder * angenommen wird in der Datenbank. */ export function passwortBeanstandung(passwort: string): string | null { if (passwort.length < 12) return "Das Passwort muss mindestens 12 Zeichen lang sein."; if (passwort.length > 72) return "Das Passwort darf höchstens 72 Zeichen lang sein."; if (!/\p{Lu}/u.test(passwort)) return "Das Passwort muss mindestens einen Grossbuchstaben enthalten."; if (!/\p{Ll}/u.test(passwort)) return "Das Passwort muss mindestens einen Kleinbuchstaben enthalten."; if (!/\p{Nd}/u.test(passwort)) return "Das Passwort muss mindestens eine Ziffer enthalten."; return null; } // Das gemeinsame Initialpasswort steht **nicht** in dieser Datei. // // Sie wird von den Anmelde- und Wechselformularen eingebunden, und die laufen // im Browser. Jede Konstante hier landete damit im ausgelieferten Bündel — und // das Initialpasswort wäre für jede Besucherin der offenen Anmeldeseite // lesbar, ohne dass sie auch nur eine E-Mail-Adresse kennen müsste. Heute // braucht ein Fremder beides. // // Es liegt deshalb in actions/benutzer.ts, also in einem Modul mit // "use server", das nie in den Browser gelangt. Dort wird es auch nur // gebraucht: beim Anlegen und beim Zurücksetzen.