// WS1-Abnahmetest (Option C) — Mandanten-Login gegen die globale Identity. // // Prüft `authorizeTenantCredentials` (src/server/auth.ts) gegen die Seed-DB: // 1. Single-Membership: admin@demo (ohne Slug) landet in seinem Mandanten. // 2. Falsches Passwort → null (kein Login). // 3. Multi-Membership OHNE Slug → null (Auswahlseite /select-tenant = WS2). // 4. Multi-Membership MIT Slug → richtiger Mandant + mandantenspezifische Rechte. // 5. Falscher/fremder Slug → null. // 6. Unbekannte E-Mail → null. // 7. Session-Shape trägt identityId, activeMembershipId und memberships[]. // // Lauf: npx tsx scripts/test-identity-login.ts (setzt den Demo-Seed voraus) import "dotenv/config"; import { prisma } from "../src/server/db"; import { authorizeTenantCredentials } from "../src/server/auth"; const PW = "Demo1234!"; let failures = 0; const ok = (cond: boolean, msg: string) => { console.log(`${cond ? "✓" : "✗ FEHLER"} ${msg}`); if (!cond) failures++; }; async function main() { console.log("\n— 1) Single-Membership: admin@demo ohne Slug —"); const admin = await authorizeTenantCredentials({ email: "admin@demo.example", password: PW }); ok(!!admin, "admin@demo meldet sich an"); ok(admin?.tenantSlug === "demo", `aktiver Mandant = demo (${admin?.tenantSlug})`); ok(!!admin?.identityId, "Session trägt identityId"); ok(admin?.activeMembershipId === admin?.id, "activeMembershipId = User.id der Mitgliedschaft"); ok((admin?.memberships?.length ?? 0) === 1, `memberships-Liste = 1 (${admin?.memberships?.length})`); ok(admin?.roles.includes("tenant-admin") ?? false, "Rolle tenant-admin im aktiven Mandanten"); console.log("\n— 2) Falsches Passwort → null —"); const wrong = await authorizeTenantCredentials({ email: "admin@demo.example", password: "falsch!!" }); ok(wrong === null, "falsches Passwort ⇒ null"); // Zähler zurücksetzen, damit wiederholte Läufe die Identity nicht sperren. await prisma.identity.update({ where: { email: "admin@demo.example" }, data: { failedLogins: 0, lockedUntil: null } }); console.log("\n— 3) Multi-Membership ohne Slug → Session ohne aktiven Mandanten (WS2) —"); const noTenant = await authorizeTenantCredentials({ email: "multi@demo.example", password: PW }); ok(!!noTenant && noTenant.tenantId === "", "multi@ ohne Slug ⇒ Session ohne aktiven Mandanten (tenantId leer → /select-tenant)"); ok((noTenant?.memberships?.length ?? 0) === 2, `memberships-Liste = 2 im No-Tenant-State (${noTenant?.memberships?.length})`); console.log("\n— 4) Multi-Membership mit Slug → korrekter Mandant + Rechte —"); const inDemo2 = await authorizeTenantCredentials({ email: "multi@demo.example", password: PW, tenant: "demo2" }); ok(inDemo2?.tenantSlug === "demo2", `Slug demo2 ⇒ aktiver Mandant demo2 (${inDemo2?.tenantSlug})`); ok(inDemo2?.roles.includes("tenant-admin") ?? false, "in demo2: Rolle tenant-admin"); ok((inDemo2?.memberships?.length ?? 0) === 2, `memberships-Liste = 2 (${inDemo2?.memberships?.length})`); const inDemo = await authorizeTenantCredentials({ email: "multi@demo.example", password: PW, tenant: "demo" }); ok(inDemo?.tenantSlug === "demo", `Slug demo ⇒ aktiver Mandant demo (${inDemo?.tenantSlug})`); ok(inDemo?.roles.includes("technician") ?? false, "in demo: Rolle technician"); // Rechte je aktivem Mandant verschieden (tenant-admin demo2 ≠ user demo). ok( JSON.stringify([...(inDemo?.permissions ?? [])].sort()) !== JSON.stringify([...(inDemo2?.permissions ?? [])].sort()), "Rechte je aktivem Mandant verschieden (demo user ≠ demo2 admin)" ); console.log("\n— 5) Fremder/falscher Slug → null —"); const wrongSlug = await authorizeTenantCredentials({ email: "admin@demo.example", password: PW, tenant: "gibtsnicht" }); ok(wrongSlug === null, "unbekannter Slug ⇒ null"); console.log("\n— 6) Unbekannte E-Mail → null —"); const unknown = await authorizeTenantCredentials({ email: "gibtsnicht@demo.example", password: PW }); ok(unknown === null, "unbekannte E-Mail ⇒ null"); } main() .then(async () => { await prisma.$disconnect(); if (failures > 0) { console.error(`\n✗ ${failures} Testfall/-fälle fehlgeschlagen.`); process.exit(1); } console.log("\nOK"); }) .catch(async (e) => { console.error(e); await prisma.$disconnect(); process.exit(1); });