Files
alpenwerk-hr/lib/passwort.ts
Andrei Laas c6cff9656e
Some checks failed
CI / Lint, Typen, Tests, Build (push) Failing after 5m27s
CI / Migrationen auf leerer Datenbank (push) Successful in 10m3s
Passwort-Anmeldung: Provider, Formulare, drei Zustaende der Shell
2026-09-08 16:51:14 +02:00

47 lines
2.3 KiB
TypeScript

// 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.