PPPAIMT-Crest/backend/test/adminAuthz.test.js

71 lines
2.1 KiB
JavaScript

import { afterEach, describe, expect, it } from 'vitest';
import { createServer } from '../src/app.js';
import { db } from '../src/db/knex.js';
import { truncateTables } from './truncate.js';
describe('admin route authorization', () => {
/** @type {import('@hapi/hapi').Server | undefined} */
let server;
afterEach(async () => {
delete process.env.TRUST_PROXY;
await server?.stop();
await truncateTables();
});
it('returns 401 for every admin route except login', async () => {
server = await createServer();
const routes = server
.table()
.filter(
(route) => route.path.startsWith('/api/admin/') && route.path !== '/api/admin/auth/login',
);
expect(routes.length).toBeGreaterThan(10);
for (const route of routes) {
const response = await server.inject({
method: route.method,
url: route.path.replace('{id}', '1'),
payload: route.method === 'get' ? undefined : {},
});
expect(response.statusCode, `${route.method} ${route.path}`).toBe(401);
}
});
it('limits anonymous login attempts', async () => {
server = await createServer();
for (let attempt = 0; attempt < 10; attempt += 1) {
const response = await server.inject({
method: 'POST',
url: '/api/admin/auth/login',
payload: {},
});
expect(response.statusCode).toBe(400);
}
const blocked = await server.inject({
method: 'POST',
url: '/api/admin/auth/login',
payload: {},
});
expect(blocked.statusCode).toBe(429);
});
it('uses the forwarded address when the proxy is trusted', async () => {
process.env.TRUST_PROXY = 'true';
server = await createServer();
const response = await server.inject({
method: 'POST',
url: '/api/admin/auth/login',
headers: { 'x-forwarded-for': '203.0.113.10, 10.0.0.4' },
payload: { email: 'missing@example.com', password: 'wrong-password' },
});
expect(response.statusCode).toBe(401);
const audit = await db('audit_log').where({ action: 'ADMIN_LOGIN_FAILED' }).first();
expect(audit.ip).toBe('203.0.113.10');
});
});