import test from 'node:test'; import assert from 'node:assert/strict'; import Fastify from 'fastify'; import cookie from '@fastify/cookie'; import rateLimit from '@fastify/rate-limit'; import api from '../src/api.js'; import { hashPassword } from '../src/auth.js'; async function makeApp() { const passwordHash = await hashPassword('Veilig123'); const calls = []; const pool = { async query(sql, params=[]) { calls.push({sql, params}); if (sql.includes('FROM users WHERE school_id = $1')) return {rows:[{ id: 7, username: 'docent', display_name: 'Docent', role: 'teacher', school_id: 2, class_id: null, password_hash: passwordHash, data: {}, }]}; return {rows:[]}; }, }; const app = Fastify({trustProxy: 2}); await app.register(cookie); await app.register(rateLimit, {global:false}); app.decorate('pg', pool); await app.register(api, {prefix:'/api'}); await app.ready(); return {app, calls}; } test('login zet HttpOnly-cookie en bewaart alleen een tokenhash', async () => { const oldNodeEnv = process.env.NODE_ENV; process.env.NODE_ENV = 'production'; const {app, calls} = await makeApp(); const res = await app.inject({method:'POST', url:'/api/auth/login', payload:{ schoolId:2, username:'docent', password:'Veilig123', }}); assert.equal(res.statusCode, 200, res.body); assert.equal('token' in res.json(), false); const setCookie = res.headers['set-cookie']; assert.match(setCookie, /teach_session=/); assert.match(setCookie, /HttpOnly/); assert.match(setCookie, /Secure/); assert.match(setCookie, /SameSite=Strict/); const rawToken = /teach_session=([^;]+)/.exec(setCookie)[1]; const insert = calls.find(c=>c.sql.includes('INSERT INTO sessions')); assert.ok(insert); assert.notEqual(insert.params[0], rawToken); assert.match(insert.params[0], /^[a-f0-9]{64}$/); await app.close(); if (oldNodeEnv === undefined) delete process.env.NODE_ENV; else process.env.NODE_ENV = oldNodeEnv; }); test('state-changing request met vreemde Origin wordt geweigerd', async () => { const {app} = await makeApp(); const res = await app.inject({method:'POST', url:'/api/auth/logout', headers:{ origin:'https://aanvaller.example', host:'teach.example', }, payload:{}}); assert.equal(res.statusCode, 403); await app.close(); });