71 lines
2.1 KiB
JavaScript
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');
|
|
});
|
|
});
|