import { test, after } from 'node:test' import assert from 'node:assert/strict' import { startAppwriteMock } from './support/appwriteMock.js' import { startFakeStripe } from './support/fakeStripe.js' import { useTestEnv } from './support/testEnv.js' // Portal-Login: Kunden wie bisher; Mitarbeiter (mit oder ohne 2FA) arbeiten im Ticketsystem (Etappe 4) const aw = await startAppwriteMock() const st = await startFakeStripe() useTestEnv({ appwriteUrl: aw.url, stripeUrl: st.url }) const { config } = await import('../server/config.js') const { startTestApp, post, rawGet, sessionCookie } = await import('./support/testApp.js') const { viewAsCookie } = await import('./support/fixtures.js') const { default: authRoutes } = await import('../server/routes/auth.js') const app = await startTestApp({ '/api/auth': authRoutes }) after(() => Promise.all([app.close(), aw.close(), st.close()])) aw.addUser({ $id: 'u_kunde', email: 'kunde@example.invalid', password: 'kunde-kunde' }) aw.addUser({ $id: 'u_ohne', email: 'justin@webklar.com', password: 'ohne-ohne-ohne' }) aw.addUser({ $id: 'u_mfa', email: 'kenso@webklar.com', password: 'mit-mit-mit', mfa: true, emailVerification: true, labels: ['admin'] }) aw.addUser({ $id: 'u_label', email: 'label@webklar.com', password: 'label-label', labels: ['admin'] }) aw.seed('customers', { $id: 'c1', appwriteUserId: 'u_kunde', email: 'kunde@example.invalid', name: 'Kunde', customerStatus: 'active', portalAccessEnabled: true }) aw.seed('customerPortalAccess', { $id: 'pa1', customerId: 'c1', enabled: true }) aw.seed('employees', { $id: 'e1', userId: 'u_ohne', displayName: 'Justin', email: 'justin@webklar.com' }) aw.seed('employees', { $id: 'e2', userId: 'u_mfa', displayName: 'Kenso', email: 'kenso@webklar.com' }) const SESSION = config.cookieName const STAFF_BLOCKED = { error: 'Mitarbeiter arbeiten im Ticketsystem.', ticketUrl: 'https://ticket.webklar.com' } const setCookies = (res) => res.headers.getSetCookie() const cleared = (c) => /Expires=Thu, 01 Jan 1970/.test(c) const liveCookies = (res, name) => setCookies(res).filter((c) => c.startsWith(`${name}=`) && !cleared(c)) const clears = (res, name) => setCookies(res).some((c) => c.startsWith(`${name}=`) && cleared(c)) const login = (email, password) => post('/api/auth/login', { email, password }) test('Kunde meldet sich weiter normal an', async () => { const before = aw.sessionDeletes() const res = await login('kunde@example.invalid', 'kunde-kunde') assert.equal(res.status, 200) assert.equal(res.body.role, 'customer') assert.equal(liveCookies(res, SESSION).length, 1) assert.equal(aw.sessionDeletes(), before) }) test('Mitarbeiter ohne 2FA: 403 mit Link ins Ticketsystem, keine Sitzung, Appwrite-Sitzung beendet', async () => { const before = aw.sessionDeletes() const res = await login('justin@webklar.com', 'ohne-ohne-ohne') assert.equal(res.status, 403) assert.deepEqual(res.body, STAFF_BLOCKED) assert.equal(liveCookies(res, SESSION).length, 0) assert.equal(liveCookies(res, 'preview_session').length, 0) assert.equal(aw.sessionDeletes(), before + 1) }) test('Mitarbeiter mit 2FA: dieselbe Antwort, keine Code-Mail', async () => { const before = aw.sessionDeletes() const res = await login('kenso@webklar.com', 'mit-mit-mit') assert.equal(res.status, 403) assert.deepEqual(res.body, STAFF_BLOCKED) assert.equal(setCookies(res).filter((c) => !cleared(c)).length, 0) assert.equal(aw.mailsSent('u_mfa'), 0) assert.equal(aw.sessionDeletes(), before + 1) }) test('Nur Label admin (ohne employees-Eintrag): ebenfalls gesperrt', async () => { const res = await login('label@webklar.com', 'label-label') assert.equal(res.status, 403) assert.deepEqual(res.body, STAFF_BLOCKED) assert.equal(liveCookies(res, SESSION).length, 0) }) test('Konto-Abruf gestoert: Mitarbeiter bleibt gesperrt (employees-Treffer)', async () => { aw.failUserLookups(true) try { const res = await login('kenso@webklar.com', 'mit-mit-mit') assert.equal(res.status, 403) assert.deepEqual(res.body, STAFF_BLOCKED) assert.equal(liveCookies(res, SESSION).length, 0) } finally { aw.failUserLookups(false) } }) test('/me mit alter Mitarbeiter-Sitzung: reason staff, Weiterleitung, Cookies geloescht', async () => { const res = await rawGet('/api/auth/me', { cookie: sessionCookie({ role: 'admin', appwriteUserId: 'u_mfa', name: 'Kenso', email: 'kenso@webklar.com' }) }) assert.equal(res.status, 200) assert.deepEqual(res.body, { authenticated: false, reason: 'staff', redirect: 'https://ticket.webklar.com' }) assert.ok(clears(res, SESSION)) assert.ok(clears(res, 'preview_session')) assert.equal(liveCookies(res, 'preview_session').length, 0) }) test('/me mit Alt-Ansicht (viewAs ohne viewId): ebenso reason staff', async () => { const res = await rawGet('/api/auth/me', { cookie: viewAsCookie('c1') }) assert.deepEqual(res.body, { authenticated: false, reason: 'staff', redirect: 'https://ticket.webklar.com' }) assert.ok(clears(res, SESSION)) }) test('/login/mfa, /login/mfa/resend und /staff-switch gibt es nicht mehr (404)', async () => { assert.equal((await post('/api/auth/login/mfa', { otp: '123456' })).status, 404) assert.equal((await post('/api/auth/login/mfa/resend', {})).status, 404) assert.equal((await rawGet('/api/auth/staff-switch?token=abc')).status, 404) })