// test/auftraegeGeruest.test.js import { test, after } from 'node:test' import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { startAppwriteMock } from './support/appwriteMock.js' import { useTestEnv } from './support/testEnv.js' // Gerüste der Router (L0): geprüft wird nur, was auch nach dem Füllen durch L1, L3 und L5 gilt: Zugangsschutz, unbekannte // Tiefenpfade (…/a/b/c/d) und die Reihenfolge der Einbindung im Quelltext. const aw = await startAppwriteMock() useTestEnv({ appwriteUrl: aw.url, stripeUrl: 'http://127.0.0.1:1' }) const { startTestApp, rawGet } = await import('./support/testApp.js') const { seedFixtures, customerCookie } = await import('./support/fixtures.js') const { default: projektkonten } = await import('../server/routes/admin/projektkonten.js') const { default: auftraegeAdmin } = await import('../server/routes/admin/auftraege.js') const { default: auftragOeffentlich } = await import('../server/routes/auftrag.js') const { default: auftraegeKunde } = await import('../server/routes/auftraegeKunde.js') const { default: teamRoutes } = await import('../server/routes/team/index.js') const app = await startTestApp({ '/api/admin/finanzen/projektkonten': projektkonten, '/api/admin/finanzen/auftraege': auftraegeAdmin, '/api/team': teamRoutes, '/api/auftrag': auftragOeffentlich, '/api/auftraege': auftraegeKunde, }) after(() => Promise.all([app.close(), aw.close()])) seedFixtures(aw) const bearer = (jwt) => ({ headers: { authorization: `Bearer ${jwt}` } }) const quelle = (pfad) => readFileSync(new URL(`../${pfad}`, import.meta.url), 'utf8') test('Admin-Router: ohne JWT 401, Mitarbeiter ohne Admin-Label und Kunden 403, Admin kommt durch', async () => { for (const pfad of ['/api/admin/finanzen/projektkonten/a/b/c/d', '/api/admin/finanzen/auftraege/a/b/c/d']) { assert.equal((await rawGet(pfad)).status, 401, pfad) assert.equal((await rawGet(pfad, bearer('jwt-staff'))).status, 403, `${pfad} jwt-staff`) assert.equal((await rawGet(pfad, bearer('jwt-kunde'))).status, 403, `${pfad} jwt-kunde`) assert.equal((await rawGet(pfad, bearer('jwt-admin'))).status, 404, `${pfad} jwt-admin: unbekannter Pfad`) } }) test('Team-Router: /arbeitsblaetter liegt hinter requireStaffJwt (jeder Mitarbeiter darf, Kunden nicht)', async () => { const pfad = '/api/team/arbeitsblaetter/a/b/c/d' assert.equal((await rawGet(pfad)).status, 401) assert.equal((await rawGet(pfad, bearer('jwt-kunde'))).status, 403) assert.equal((await rawGet(pfad, bearer('jwt-staff'))).status, 404, 'Mitarbeiter ohne Admin-Label kommen durch') assert.equal((await rawGet('/api/team/arbeitsblaetter/abgerechnet?ticketId=t1')).status, 401) }) test('Kunden-Router verlangt eine Anmeldung, der öffentliche Router nicht', async () => { const ohne = await rawGet('/api/auftraege/a/b/c/d') assert.equal(ohne.status, 401) assert.deepEqual(ohne.body, { error: 'Nicht angemeldet' }) assert.equal((await rawGet('/api/auftraege/a/b/c/d', { cookie: customerCookie('c1') })).status, 404) for (const pfad of ['/api/auftrag/a/b/c/d', '/api/auftrag/a/b/c/d/pdf']) assert.equal((await rawGet(pfad)).status, 404, pfad) }) test('server/index.js: Admin-Router vor dem Finanzen-Router, Kunden- und öffentlicher Router hinter Wächter und Parser', () => { const index = quelle('server/index.js') const stelle = (zeile) => { const pos = index.indexOf(zeile) assert.ok(pos >= 0, `${zeile} fehlt`) assert.equal(index.indexOf(zeile, pos + 1), -1, `${zeile} steht mehrfach`) return pos } const projekt = stelle("app.use('/api/admin/finanzen/projektkonten', adminProjektkontenRoutes)") const auftraege = stelle("app.use('/api/admin/finanzen/auftraege', adminAuftraegeRoutes)") const finanzen = stelle("app.use('/api/admin/finanzen', adminFinanzenRoutes)") assert.ok(projekt < finanzen && auftraege < finanzen, 'sonst prüft der Finanzen-Router zuerst') const waechter = stelle('app.use(kundenansichtGuard)') const parser = stelle("app.use(express.json({ limit: '2mb'") const oeffentlich = stelle("app.use('/api/auftrag', publicAuftragRoutes)") const kunde = stelle("app.use('/api/auftraege', kundeAuftraegeRoutes)") assert.ok(waechter < oeffentlich && waechter < kunde && parser < oeffentlich && parser < kunde) for (const [name, datei] of [ ['adminProjektkontenRoutes', 'admin/projektkonten'], ['adminAuftraegeRoutes', 'admin/auftraege'], ['publicAuftragRoutes', 'auftrag'], ['kundeAuftraegeRoutes', 'auftraegeKunde'], ]) { assert.ok(index.includes(`import ${name} from './routes/${datei}.js'`), name) } }) test('server/routes/team/index.js: /arbeitsblaetter hängt hinter requireStaffJwt', () => { const team = quelle('server/routes/team/index.js') const jwt = team.indexOf('router.use(requireStaffJwt)') const mount = team.indexOf("router.use('/arbeitsblaetter', arbeitsblaetterTeamRoutes)") assert.ok(jwt >= 0 && mount > jwt) assert.equal(team.indexOf("router.use('/arbeitsblaetter'", mount + 1), -1) assert.ok(team.includes("import arbeitsblaetterTeamRoutes from './arbeitsblaetter.js'")) })