Admin User v1
This commit is contained in:
203
backend/src/features/admin/tests/unit/admin.service.test.ts
Normal file
203
backend/src/features/admin/tests/unit/admin.service.test.ts
Normal file
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* @ai-summary Admin service unit tests
|
||||
* @ai-context Tests business logic for admin management
|
||||
*/
|
||||
|
||||
import { AdminService } from '../../domain/admin.service';
|
||||
import { AdminRepository } from '../../data/admin.repository';
|
||||
|
||||
describe('AdminService', () => {
|
||||
let adminService: AdminService;
|
||||
let mockRepository: jest.Mocked<AdminRepository>;
|
||||
|
||||
beforeEach(() => {
|
||||
mockRepository = {
|
||||
getAdminByAuth0Sub: jest.fn(),
|
||||
getAdminByEmail: jest.fn(),
|
||||
getAllAdmins: jest.fn(),
|
||||
getActiveAdmins: jest.fn(),
|
||||
createAdmin: jest.fn(),
|
||||
revokeAdmin: jest.fn(),
|
||||
reinstateAdmin: jest.fn(),
|
||||
logAuditAction: jest.fn(),
|
||||
getAuditLogs: jest.fn(),
|
||||
} as any;
|
||||
|
||||
adminService = new AdminService(mockRepository);
|
||||
});
|
||||
|
||||
describe('getAdminByAuth0Sub', () => {
|
||||
it('should return admin when found', async () => {
|
||||
const mockAdmin = {
|
||||
auth0Sub: 'auth0|123456',
|
||||
email: 'admin@motovaultpro.com',
|
||||
role: 'admin',
|
||||
createdAt: new Date(),
|
||||
createdBy: 'system',
|
||||
revokedAt: null,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
mockRepository.getAdminByAuth0Sub.mockResolvedValue(mockAdmin);
|
||||
|
||||
const result = await adminService.getAdminByAuth0Sub('auth0|123456');
|
||||
|
||||
expect(result).toEqual(mockAdmin);
|
||||
expect(mockRepository.getAdminByAuth0Sub).toHaveBeenCalledWith('auth0|123456');
|
||||
});
|
||||
|
||||
it('should return null when admin not found', async () => {
|
||||
mockRepository.getAdminByAuth0Sub.mockResolvedValue(null);
|
||||
|
||||
const result = await adminService.getAdminByAuth0Sub('auth0|unknown');
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createAdmin', () => {
|
||||
it('should create new admin and log audit', async () => {
|
||||
const mockAdmin = {
|
||||
auth0Sub: 'auth0|newadmin',
|
||||
email: 'newadmin@motovaultpro.com',
|
||||
role: 'admin',
|
||||
createdAt: new Date(),
|
||||
createdBy: 'auth0|existing',
|
||||
revokedAt: null,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
mockRepository.getAdminByEmail.mockResolvedValue(null);
|
||||
mockRepository.createAdmin.mockResolvedValue(mockAdmin);
|
||||
mockRepository.logAuditAction.mockResolvedValue({} as any);
|
||||
|
||||
const result = await adminService.createAdmin(
|
||||
'newadmin@motovaultpro.com',
|
||||
'admin',
|
||||
'auth0|newadmin',
|
||||
'auth0|existing'
|
||||
);
|
||||
|
||||
expect(result).toEqual(mockAdmin);
|
||||
expect(mockRepository.createAdmin).toHaveBeenCalled();
|
||||
expect(mockRepository.logAuditAction).toHaveBeenCalledWith(
|
||||
'auth0|existing',
|
||||
'CREATE',
|
||||
mockAdmin.auth0Sub,
|
||||
'admin_user',
|
||||
mockAdmin.email,
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
it('should reject if admin already exists', async () => {
|
||||
const existingAdmin = {
|
||||
auth0Sub: 'auth0|existing',
|
||||
email: 'admin@motovaultpro.com',
|
||||
role: 'admin',
|
||||
createdAt: new Date(),
|
||||
createdBy: 'system',
|
||||
revokedAt: null,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
mockRepository.getAdminByEmail.mockResolvedValue(existingAdmin);
|
||||
|
||||
await expect(
|
||||
adminService.createAdmin('admin@motovaultpro.com', 'admin', 'auth0|new', 'auth0|existing')
|
||||
).rejects.toThrow('already exists');
|
||||
});
|
||||
});
|
||||
|
||||
describe('revokeAdmin', () => {
|
||||
it('should revoke admin when multiple active admins exist', async () => {
|
||||
const revokedAdmin = {
|
||||
auth0Sub: 'auth0|toadmin',
|
||||
email: 'toadmin@motovaultpro.com',
|
||||
role: 'admin',
|
||||
createdAt: new Date(),
|
||||
createdBy: 'system',
|
||||
revokedAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
const activeAdmins = [
|
||||
{
|
||||
auth0Sub: 'auth0|admin1',
|
||||
email: 'admin1@motovaultpro.com',
|
||||
role: 'admin',
|
||||
createdAt: new Date(),
|
||||
createdBy: 'system',
|
||||
revokedAt: null,
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
{
|
||||
auth0Sub: 'auth0|admin2',
|
||||
email: 'admin2@motovaultpro.com',
|
||||
role: 'admin',
|
||||
createdAt: new Date(),
|
||||
createdBy: 'system',
|
||||
revokedAt: null,
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
];
|
||||
|
||||
mockRepository.getActiveAdmins.mockResolvedValue(activeAdmins);
|
||||
mockRepository.revokeAdmin.mockResolvedValue(revokedAdmin);
|
||||
mockRepository.logAuditAction.mockResolvedValue({} as any);
|
||||
|
||||
const result = await adminService.revokeAdmin('auth0|toadmin', 'auth0|admin1');
|
||||
|
||||
expect(result).toEqual(revokedAdmin);
|
||||
expect(mockRepository.revokeAdmin).toHaveBeenCalledWith('auth0|toadmin');
|
||||
expect(mockRepository.logAuditAction).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should prevent revoking last active admin', async () => {
|
||||
const lastAdmin = {
|
||||
auth0Sub: 'auth0|lastadmin',
|
||||
email: 'last@motovaultpro.com',
|
||||
role: 'admin',
|
||||
createdAt: new Date(),
|
||||
createdBy: 'system',
|
||||
revokedAt: null,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
mockRepository.getActiveAdmins.mockResolvedValue([lastAdmin]);
|
||||
|
||||
await expect(
|
||||
adminService.revokeAdmin('auth0|lastadmin', 'auth0|lastadmin')
|
||||
).rejects.toThrow('Cannot revoke the last active admin');
|
||||
});
|
||||
});
|
||||
|
||||
describe('reinstateAdmin', () => {
|
||||
it('should reinstate revoked admin and log audit', async () => {
|
||||
const reinstatedAdmin = {
|
||||
auth0Sub: 'auth0|reinstate',
|
||||
email: 'reinstate@motovaultpro.com',
|
||||
role: 'admin',
|
||||
createdAt: new Date(),
|
||||
createdBy: 'system',
|
||||
revokedAt: null,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
mockRepository.reinstateAdmin.mockResolvedValue(reinstatedAdmin);
|
||||
mockRepository.logAuditAction.mockResolvedValue({} as any);
|
||||
|
||||
const result = await adminService.reinstateAdmin('auth0|reinstate', 'auth0|admin');
|
||||
|
||||
expect(result).toEqual(reinstatedAdmin);
|
||||
expect(mockRepository.reinstateAdmin).toHaveBeenCalledWith('auth0|reinstate');
|
||||
expect(mockRepository.logAuditAction).toHaveBeenCalledWith(
|
||||
'auth0|admin',
|
||||
'REINSTATE',
|
||||
'auth0|reinstate',
|
||||
'admin_user',
|
||||
reinstatedAdmin.email
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user