feat: implement audit logging system with service, controller, and interceptor to track user actions across core services
This commit is contained in:
@@ -2,10 +2,15 @@ import { Injectable, NotFoundException, ConflictException, BadRequestException }
|
||||
import { Prisma, FieldType } from '@prisma/client';
|
||||
import { PrismaService } from '../prisma';
|
||||
import { CreateFieldDto, UpdateFieldDto } from './dto';
|
||||
import { AuditService } from '../audit/audit.service';
|
||||
import { AuditAction } from '../audit/audit.constants';
|
||||
|
||||
@Injectable()
|
||||
export class ProfileFieldsService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly audit: AuditService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generate a URL-friendly slug from the name
|
||||
@@ -153,7 +158,7 @@ export class ProfileFieldsService {
|
||||
data.slug = newSlug;
|
||||
}
|
||||
|
||||
return this.prisma.profileField.update({
|
||||
const updated = await this.prisma.profileField.update({
|
||||
where: { id },
|
||||
data,
|
||||
include: {
|
||||
@@ -162,6 +167,15 @@ export class ProfileFieldsService {
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.audit.log({
|
||||
action: AuditAction.PROFILE_FIELD_UPDATE,
|
||||
resourceType: 'ProfileField',
|
||||
resourceId: id,
|
||||
metadata: { sectionId: field.sectionId, slug: updated.slug, name: updated.name },
|
||||
});
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,9 +195,18 @@ export class ProfileFieldsService {
|
||||
);
|
||||
}
|
||||
|
||||
return this.prisma.profileField.delete({
|
||||
const deleted = await this.prisma.profileField.delete({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
this.audit.log({
|
||||
action: AuditAction.PROFILE_FIELD_UPDATE,
|
||||
resourceType: 'ProfileField',
|
||||
resourceId: id,
|
||||
metadata: { action: 'delete' },
|
||||
});
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { Injectable, NotFoundException, ConflictException, ForbiddenException } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma';
|
||||
import { CreateSectionDto, UpdateSectionDto, AssignSectionDto, UpdateAssignmentDto } from './dto';
|
||||
import { AuditService } from '../audit/audit.service';
|
||||
import { AuditAction } from '../audit/audit.constants';
|
||||
|
||||
@Injectable()
|
||||
export class ProfileSectionsService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly audit: AuditService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generate a URL-friendly slug from the name
|
||||
@@ -127,7 +132,7 @@ export class ProfileSectionsService {
|
||||
data.slug = effectiveSlug;
|
||||
}
|
||||
|
||||
return this.prisma.profileSection.update({
|
||||
const updated = await this.prisma.profileSection.update({
|
||||
where: { id },
|
||||
data,
|
||||
include: {
|
||||
@@ -136,6 +141,15 @@ export class ProfileSectionsService {
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.audit.log({
|
||||
action: AuditAction.PROFILE_SECTION_UPDATE,
|
||||
resourceType: 'ProfileSection',
|
||||
resourceId: id,
|
||||
metadata: { name: updated.name, slug: updated.slug },
|
||||
});
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,9 +172,18 @@ export class ProfileSectionsService {
|
||||
);
|
||||
}
|
||||
|
||||
return this.prisma.profileSection.delete({
|
||||
const deleted = await this.prisma.profileSection.delete({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
this.audit.log({
|
||||
action: AuditAction.PROFILE_SECTION_UPDATE,
|
||||
resourceType: 'ProfileSection',
|
||||
resourceId: id,
|
||||
metadata: { action: 'delete', name: section.name },
|
||||
});
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user