Admin User v1

This commit is contained in:
Eric Gullickson
2025-11-05 19:04:06 -06:00
parent e4e7e32a4f
commit 8174e0d5f9
48 changed files with 11289 additions and 1112 deletions

View 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
);
});
});
});