205 lines
5.8 KiB
TypeScript
205 lines
5.8 KiB
TypeScript
import { Test, TestingModule } from '@nestjs/testing';
|
|
import { AuditLogRepository } from '../../src/infrastructure/persistence/repositories/audit-log.repository';
|
|
import { PrismaService } from '../../src/infrastructure/persistence/prisma/prisma.service';
|
|
import { MockPrismaService } from '../utils/mock-prisma.service';
|
|
|
|
describe('AuditLogRepository Integration', () => {
|
|
let repository: AuditLogRepository;
|
|
let mockPrisma: MockPrismaService;
|
|
|
|
beforeEach(async () => {
|
|
mockPrisma = new MockPrismaService();
|
|
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
providers: [
|
|
AuditLogRepository,
|
|
{ provide: PrismaService, useValue: mockPrisma },
|
|
],
|
|
}).compile();
|
|
|
|
repository = module.get<AuditLogRepository>(AuditLogRepository);
|
|
});
|
|
|
|
afterEach(() => {
|
|
mockPrisma.reset();
|
|
});
|
|
|
|
describe('log', () => {
|
|
it('should create an audit log entry for STORE action', async () => {
|
|
await repository.log({
|
|
shareId: BigInt(1),
|
|
userId: BigInt(12345),
|
|
action: 'STORE',
|
|
sourceService: 'identity-service',
|
|
sourceIp: '192.168.1.1',
|
|
success: true,
|
|
});
|
|
|
|
expect(mockPrisma.shareAccessLog.create).toHaveBeenCalledWith({
|
|
data: expect.objectContaining({
|
|
shareId: BigInt(1),
|
|
userId: BigInt(12345),
|
|
action: 'STORE',
|
|
sourceService: 'identity-service',
|
|
sourceIp: '192.168.1.1',
|
|
success: true,
|
|
}),
|
|
});
|
|
});
|
|
|
|
it('should create an audit log entry for RETRIEVE action', async () => {
|
|
await repository.log({
|
|
shareId: BigInt(2),
|
|
userId: BigInt(67890),
|
|
action: 'RETRIEVE',
|
|
sourceService: 'recovery-service',
|
|
sourceIp: '10.0.0.1',
|
|
success: true,
|
|
});
|
|
|
|
expect(mockPrisma.shareAccessLog.create).toHaveBeenCalledWith({
|
|
data: expect.objectContaining({
|
|
action: 'RETRIEVE',
|
|
sourceService: 'recovery-service',
|
|
}),
|
|
});
|
|
});
|
|
|
|
it('should create an audit log entry for REVOKE action', async () => {
|
|
await repository.log({
|
|
shareId: BigInt(3),
|
|
userId: BigInt(11111),
|
|
action: 'REVOKE',
|
|
sourceService: 'identity-service',
|
|
sourceIp: '172.16.0.1',
|
|
success: true,
|
|
});
|
|
|
|
expect(mockPrisma.shareAccessLog.create).toHaveBeenCalledWith({
|
|
data: expect.objectContaining({
|
|
action: 'REVOKE',
|
|
}),
|
|
});
|
|
});
|
|
|
|
it('should log failed operations with error message', async () => {
|
|
await repository.log({
|
|
shareId: BigInt(0),
|
|
userId: BigInt(22222),
|
|
action: 'RETRIEVE',
|
|
sourceService: 'identity-service',
|
|
sourceIp: '192.168.1.100',
|
|
success: false,
|
|
errorMessage: 'Share not found',
|
|
});
|
|
|
|
expect(mockPrisma.shareAccessLog.create).toHaveBeenCalledWith({
|
|
data: expect.objectContaining({
|
|
success: false,
|
|
errorMessage: 'Share not found',
|
|
}),
|
|
});
|
|
});
|
|
|
|
it('should not throw when database error occurs', async () => {
|
|
mockPrisma.shareAccessLog.create.mockRejectedValueOnce(new Error('DB Error'));
|
|
|
|
await expect(
|
|
repository.log({
|
|
shareId: BigInt(1),
|
|
userId: BigInt(12345),
|
|
action: 'STORE',
|
|
sourceService: 'identity-service',
|
|
sourceIp: '127.0.0.1',
|
|
success: true,
|
|
}),
|
|
).resolves.not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('findByShareId', () => {
|
|
it('should find logs by share ID', async () => {
|
|
const shareId = BigInt(100);
|
|
|
|
// Create some logs
|
|
await repository.log({
|
|
shareId,
|
|
userId: BigInt(12345),
|
|
action: 'STORE',
|
|
sourceService: 'identity-service',
|
|
sourceIp: '127.0.0.1',
|
|
success: true,
|
|
});
|
|
await repository.log({
|
|
shareId,
|
|
userId: BigInt(12345),
|
|
action: 'RETRIEVE',
|
|
sourceService: 'identity-service',
|
|
sourceIp: '127.0.0.1',
|
|
success: true,
|
|
});
|
|
|
|
await repository.findByShareId(shareId);
|
|
|
|
expect(mockPrisma.shareAccessLog.findMany).toHaveBeenCalledWith({
|
|
where: { shareId },
|
|
orderBy: { createdAt: 'desc' },
|
|
take: 100,
|
|
});
|
|
});
|
|
|
|
it('should respect limit parameter', async () => {
|
|
await repository.findByShareId(BigInt(1), 50);
|
|
|
|
expect(mockPrisma.shareAccessLog.findMany).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
take: 50,
|
|
}),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('findByUserId', () => {
|
|
it('should find logs by user ID', async () => {
|
|
const userId = BigInt(55555);
|
|
|
|
await repository.findByUserId(userId);
|
|
|
|
expect(mockPrisma.shareAccessLog.findMany).toHaveBeenCalledWith({
|
|
where: { userId },
|
|
orderBy: { createdAt: 'desc' },
|
|
take: 100,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('countRetrievesByUserToday', () => {
|
|
it('should count today\'s retrieves for a user', async () => {
|
|
const userId = BigInt(33333);
|
|
|
|
await repository.countRetrievesByUserToday(userId);
|
|
|
|
expect(mockPrisma.shareAccessLog.count).toHaveBeenCalledWith({
|
|
where: {
|
|
userId,
|
|
action: 'RETRIEVE',
|
|
createdAt: expect.objectContaining({
|
|
gte: expect.any(Date),
|
|
}),
|
|
},
|
|
});
|
|
});
|
|
|
|
it('should return correct count', async () => {
|
|
const userId = BigInt(44444);
|
|
|
|
// Simulate 2 retrieves today
|
|
mockPrisma.shareAccessLog.count.mockResolvedValueOnce(2);
|
|
|
|
const count = await repository.countRetrievesByUserToday(userId);
|
|
|
|
expect(count).toBe(2);
|
|
});
|
|
});
|
|
});
|