Files
support_backend/tests/unit/identity/require-role.test.ts
T
saqib mirandClaude Sonnet 5 40687f68fa feat(010-identity-auth): real staff login, session verification, and role gating
Replaces the no-op fastify.authenticate stub and the never-implemented
identity/auth login with real bcrypt password verification, JWT session
issuance/verification (reusing the existing JWT_SECRET), and a Redis-backed
revocation denylist for logout. Adds requireRole('ADMIN') to admin-only
configuration writes across 002-009 that previously relied on a decorator
that never actually checked anything. Adds self-identity (GET /auth/me,
re-validated against live account state) and admin-provisioned accounts
(POST /admin/users).

Making the auth check genuinely reject invalid/missing tokens exposed that
~18 pre-existing integration test files called already-gated routes with no
Authorization header (safe against the old no-op stub, broken against a real
one) — fixed via a shared tests/helpers/auth.ts (loginAs/authHeader) and a
file-by-file pass, plus two related SLA-run cleanup races exposed once admin
setup calls in those files' own beforeAll blocks started actually succeeding.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 12:45:37 +05:30

38 lines
1.3 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { FastifyReply, FastifyRequest } from 'fastify';
import { requireRole } from '@/modules/identity/auth/service/require-role';
function fakeRequest(user?: { role: string }): FastifyRequest {
return { user } as unknown as FastifyRequest;
}
describe('requireRole', () => {
it('passes when the session role is in the allowed list', async () => {
const guard = requireRole('ADMIN');
await expect(
guard(fakeRequest({ role: 'ADMIN' }), {} as FastifyReply),
).resolves.toBeUndefined();
});
it('throws AuthorizationError when the session role is not in the allowed list', async () => {
const guard = requireRole('ADMIN');
await expect(guard(fakeRequest({ role: 'AGENT' }), {} as FastifyReply)).rejects.toMatchObject({
statusCode: 403,
});
});
it('throws AuthorizationError when there is no session at all', async () => {
const guard = requireRole('ADMIN');
await expect(guard(fakeRequest(undefined), {} as FastifyReply)).rejects.toMatchObject({
statusCode: 403,
});
});
it('accepts any role in a multi-role allow list', async () => {
const guard = requireRole('ADMIN', 'AGENT');
await expect(
guard(fakeRequest({ role: 'AGENT' }), {} as FastifyReply),
).resolves.toBeUndefined();
});
});