75 lines
2.2 KiB
TypeScript
75 lines
2.2 KiB
TypeScript
import { AuditService } from './audit.service';
|
|
|
|
describe('AuditService', () => {
|
|
const create = jest.fn();
|
|
const findMany = jest.fn();
|
|
const prisma = { auditEvent: { create, findMany } } as any;
|
|
const service = new AuditService(prisma);
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
it('writes append-only audit events with sensitive fields redacted', async () => {
|
|
create.mockResolvedValue({ id: 'audit-1' });
|
|
|
|
await service.record({
|
|
actor: { id: 'm-8', name: '超级管理员', roleId: 'role-admin' },
|
|
action: 'product.update',
|
|
entityType: 'product',
|
|
entityId: 'product-1',
|
|
productId: 'product-1',
|
|
before: { name: 'Old', password: '123456' },
|
|
after: { name: 'New', nested: { apiKey: 'sk-test', keep: 'visible' } },
|
|
metadata: { authorization: 'Bearer token', reason: 'manual edit' },
|
|
});
|
|
|
|
expect(create).toHaveBeenCalledWith({
|
|
data: expect.objectContaining({
|
|
actorId: 'm-8',
|
|
actorName: '超级管理员',
|
|
action: 'product.update',
|
|
entityType: 'product',
|
|
entityId: 'product-1',
|
|
productId: 'product-1',
|
|
before: { name: 'Old', password: '[REDACTED]' },
|
|
after: { name: 'New', nested: { apiKey: '[REDACTED]', keep: 'visible' } },
|
|
metadata: { authorization: '[REDACTED]', reason: 'manual edit' },
|
|
}),
|
|
});
|
|
});
|
|
|
|
it('queries by actor, entity, scope, and date range with bounded page size', async () => {
|
|
findMany.mockResolvedValue([]);
|
|
|
|
await service.query({
|
|
actorId: 'm-8',
|
|
entityType: 'bug',
|
|
entityId: 'bug-1',
|
|
productId: 'product-1',
|
|
projectId: 'project-1',
|
|
versionId: 'version-1',
|
|
dateFrom: '2026-07-01T00:00:00.000Z',
|
|
dateTo: '2026-07-08T23:59:59.000Z',
|
|
take: '500',
|
|
});
|
|
|
|
expect(findMany).toHaveBeenCalledWith({
|
|
where: {
|
|
actorId: 'm-8',
|
|
entityType: 'bug',
|
|
entityId: 'bug-1',
|
|
productId: 'product-1',
|
|
projectId: 'project-1',
|
|
versionId: 'version-1',
|
|
createdAt: {
|
|
gte: new Date('2026-07-01T00:00:00.000Z'),
|
|
lte: new Date('2026-07-08T23:59:59.000Z'),
|
|
},
|
|
},
|
|
orderBy: { createdAt: 'desc' },
|
|
take: 100,
|
|
});
|
|
});
|
|
});
|