81 lines
2.4 KiB
TypeScript
81 lines
2.4 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { DataSource } from 'typeorm';
|
|
import { TenantAwareRepository } from '@it0/database';
|
|
import { AuditLog } from '../../domain/entities/audit-log.entity';
|
|
|
|
export interface AuditLogFilters {
|
|
actionType?: string;
|
|
actorType?: string;
|
|
actorId?: string;
|
|
resourceType?: string;
|
|
from?: string;
|
|
to?: string;
|
|
page?: number;
|
|
limit?: number;
|
|
}
|
|
|
|
@Injectable()
|
|
export class AuditLogRepository extends TenantAwareRepository<AuditLog> {
|
|
constructor(dataSource: DataSource) {
|
|
super(dataSource, AuditLog);
|
|
}
|
|
|
|
async queryLogs(filters: AuditLogFilters): Promise<{ data: AuditLog[]; total: number }> {
|
|
return this.withRepository(async (repo) => {
|
|
const qb = repo.createQueryBuilder('log');
|
|
|
|
if (filters.actionType) {
|
|
qb.andWhere('log.actionType = :actionType', { actionType: filters.actionType });
|
|
}
|
|
|
|
if (filters.actorType) {
|
|
qb.andWhere('log.actorType = :actorType', { actorType: filters.actorType });
|
|
}
|
|
|
|
if (filters.actorId) {
|
|
qb.andWhere('log.actorId = :actorId', { actorId: filters.actorId });
|
|
}
|
|
|
|
if (filters.resourceType) {
|
|
qb.andWhere('log.resourceType = :resourceType', { resourceType: filters.resourceType });
|
|
}
|
|
|
|
if (filters.from) {
|
|
qb.andWhere('log.createdAt >= :from', { from: new Date(filters.from) });
|
|
}
|
|
|
|
if (filters.to) {
|
|
qb.andWhere('log.createdAt <= :to', { to: new Date(filters.to) });
|
|
}
|
|
|
|
qb.orderBy('log.createdAt', 'DESC');
|
|
|
|
const page = filters.page ?? 1;
|
|
const limit = filters.limit ?? 50;
|
|
qb.skip((page - 1) * limit).take(limit);
|
|
|
|
const [data, total] = await qb.getManyAndCount();
|
|
return { data, total };
|
|
});
|
|
}
|
|
|
|
async exportLogs(format: 'json' | 'csv'): Promise<AuditLog[] | string> {
|
|
return this.withRepository(async (repo) => {
|
|
const logs = await repo.find({ order: { createdAt: 'DESC' } as any });
|
|
|
|
if (format === 'csv') {
|
|
const headers = ['id', 'tenantId', 'actionType', 'actorType', 'actorId', 'resourceType', 'resourceId', 'ipAddress', 'createdAt'];
|
|
const rows = logs.map(log =>
|
|
headers.map(h => {
|
|
const value = (log as any)[h];
|
|
return value !== undefined && value !== null ? String(value) : '';
|
|
}).join(','),
|
|
);
|
|
return [headers.join(','), ...rows].join('\n');
|
|
}
|
|
|
|
return logs;
|
|
});
|
|
}
|
|
}
|