Files
back_end_oudelaa/src/modules/audit/audit.service.ts
T

66 lines
1.9 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { buildPaginatedResponse } from '../../common/utils/pagination.util';
import { resolveMongoSortDirection } from '../../common/utils/sort.util';
import { AuditRepository } from './audit.repository';
import { escapeRegex } from '../../common/utils/regex.util';
import { AuditQueryDto } from './dto/audit-query.dto';
@Injectable()
export class AuditService {
constructor(private readonly auditRepository: AuditRepository) {}
async logSuperAdminAction(
actorIdentifier: string,
action: string,
targetType: string,
targetId?: string,
metadata?: Record<string, unknown>,
): Promise<void> {
await this.auditRepository.create({
actorType: 'superadmin',
actorIdentifier,
action,
targetType,
targetId,
metadata,
});
}
async listSuperAdminLogs(query: AuditQueryDto) {
const page = query.page ?? 1;
const limit = query.limit ?? 20;
const skip = (page - 1) * limit;
const filter: Record<string, unknown> = {};
if (query.q?.trim()) {
filter.$or = [
{ action: { $regex: escapeRegex(query.q.trim()), $options: 'i' } },
{ targetType: { $regex: escapeRegex(query.q.trim()), $options: 'i' } },
{ targetId: { $regex: escapeRegex(query.q.trim()), $options: 'i' } },
{ actorIdentifier: { $regex: escapeRegex(query.q.trim()), $options: 'i' } },
];
}
if (query.actorType) {
filter.actorType = query.actorType;
}
if (query.targetType?.trim()) {
filter.targetType = query.targetType.trim();
}
const sort = { createdAt: resolveMongoSortDirection(query.sortOrder) } as Record<string, 1 | -1>;
const [items, total] = await Promise.all([
this.auditRepository.findMany(filter, skip, limit, sort),
this.auditRepository.count(filter),
]);
return buildPaginatedResponse(items, {
page,
limit,
total,
offset: skip,
});
}
}