39 lines
1.8 KiB
TypeScript
39 lines
1.8 KiB
TypeScript
import { AuthenticationService } from '../src/modules/auth/authentication.service';
|
|
|
|
describe('AuthenticationService', () => {
|
|
let service: AuthenticationService;
|
|
const mockOidc: any = { verifyToken: jest.fn() };
|
|
const mockPrisma: any = {};
|
|
const mockRoleSync: any = { syncUserRolesFromAuthentik: jest.fn() };
|
|
const mockAuthz: any = { getUserPermissions: jest.fn() };
|
|
const mockEvents: any = { publish: jest.fn() };
|
|
|
|
beforeEach(() => {
|
|
mockPrisma.user = { findUnique: jest.fn(), create: jest.fn() };
|
|
mockPrisma.userRole = { findMany: jest.fn() };
|
|
|
|
service = new AuthenticationService(mockOidc as any, mockPrisma as any, mockRoleSync as any, mockAuthz as any, mockEvents as any);
|
|
});
|
|
|
|
test('authenticate creates context on valid token', async () => {
|
|
const token = 'valid';
|
|
mockOidc.verifyToken.mockResolvedValue({ sub: 'sub1', email: 'u@example.com', groups: ['RL-Owner'] });
|
|
mockPrisma.user.findUnique.mockResolvedValue(null);
|
|
mockPrisma.user.create.mockResolvedValue({ id: 'uid', authentikId: 'sub1', email: 'u@example.com' });
|
|
mockRoleSync.syncUserRolesFromAuthentik.mockResolvedValue({ skipped: false, assignedRoleIds: ['r1'] });
|
|
mockAuthz.getUserPermissions.mockResolvedValue(['users.read']);
|
|
mockPrisma.userRole.findMany.mockResolvedValue([{ roleId: 'r1' }]);
|
|
|
|
const ctx = await service.authenticate(token);
|
|
|
|
expect(ctx.user.id).toBe('uid');
|
|
expect(ctx.permissions).toContain('users.read');
|
|
expect(mockEvents.publish).toHaveBeenCalledWith('user.authenticated', expect.any(Object));
|
|
});
|
|
|
|
test('authenticate throws for missing sub', async () => {
|
|
mockOidc.verifyToken.mockResolvedValue({ email: 'u@example.com' });
|
|
await expect(service.authenticate('bad')).rejects.toThrow('Invalid token: missing sub');
|
|
});
|
|
});
|