@studiosonrai/nestjs-audit-log 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -0
- package/dist/src/audit-context.interceptor.d.ts +10 -0
- package/dist/src/audit-context.interceptor.js +48 -0
- package/dist/src/audit-context.interceptor.js.map +1 -0
- package/dist/src/audit.builder.d.ts +3 -0
- package/dist/src/audit.builder.js +15 -0
- package/dist/src/audit.builder.js.map +1 -0
- package/dist/src/audit.constants.d.ts +3 -0
- package/dist/src/audit.constants.js +7 -0
- package/dist/src/audit.constants.js.map +1 -0
- package/dist/src/audit.helper.d.ts +5 -0
- package/dist/src/audit.helper.js +41 -0
- package/dist/src/audit.helper.js.map +1 -0
- package/dist/src/audit.module.d.ts +9 -0
- package/dist/src/audit.module.js +90 -0
- package/dist/src/audit.module.js.map +1 -0
- package/dist/src/audit.service.d.ts +22 -0
- package/dist/src/audit.service.js +185 -0
- package/dist/src/audit.service.js.map +1 -0
- package/dist/src/audit.subscriber.d.ts +11 -0
- package/dist/src/audit.subscriber.js +100 -0
- package/dist/src/audit.subscriber.js.map +1 -0
- package/dist/src/decorators/auditable.decorator.d.ts +3 -0
- package/dist/src/decorators/auditable.decorator.js +22 -0
- package/dist/src/decorators/auditable.decorator.js.map +1 -0
- package/dist/src/dto/audit-filter.dto.d.ts +10 -0
- package/dist/src/dto/audit-filter.dto.js +101 -0
- package/dist/src/dto/audit-filter.dto.js.map +1 -0
- package/dist/src/dto/audit-log-response.dto.d.ts +13 -0
- package/dist/src/dto/audit-log-response.dto.js +91 -0
- package/dist/src/dto/audit-log-response.dto.js.map +1 -0
- package/dist/src/dto/paginated-result.dto.d.ts +9 -0
- package/dist/src/dto/paginated-result.dto.js +52 -0
- package/dist/src/dto/paginated-result.dto.js.map +1 -0
- package/dist/src/entities/audit-log.entity.d.ts +15 -0
- package/dist/src/entities/audit-log.entity.js +101 -0
- package/dist/src/entities/audit-log.entity.js.map +1 -0
- package/dist/src/index.d.ts +13 -0
- package/dist/src/index.js +30 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces/audit.interfaces.d.ts +34 -0
- package/dist/src/interfaces/audit.interfaces.js +3 -0
- package/dist/src/interfaces/audit.interfaces.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @studiosonrai/nestjs-audit-log
|
|
2
|
+
|
|
3
|
+
Audit logging for NestJS + TypeORM. Mark an entity `@Auditable()` and CREATE/UPDATE
|
|
4
|
+
are recorded automatically by a TypeORM subscriber — no per-service code. DELETE is a
|
|
5
|
+
single explicit call. The acting user is captured from the request via CLS, so you never
|
|
6
|
+
thread `userId` through your services.
|
|
7
|
+
|
|
8
|
+
## Documentation
|
|
9
|
+
|
|
10
|
+
- [Setup & Usage](docs/setup.md) — prerequisites, install, configuration, and day-to-day use.
|
|
11
|
+
- [How It Works](docs/internals.md) — architecture, core logic, and design decisions.
|
|
12
|
+
- [Migration Guide](docs/migration.md) — move an existing hand-rolled audit module onto this package.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @studiosonrai/nestjs-audit-log
|
|
18
|
+
# peers (already present in most NestJS apps):
|
|
19
|
+
npm install @nestjs/typeorm @nestjs/swagger typeorm class-validator class-transformer
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { AuditModule } from '@studiosonrai/nestjs-audit-log';
|
|
26
|
+
import { AuditLog } from '@studiosonrai/nestjs-audit-log';
|
|
27
|
+
|
|
28
|
+
@Module({
|
|
29
|
+
imports: [
|
|
30
|
+
AuditModule.forRootAsync({
|
|
31
|
+
inject: [getRepositoryToken(User)],
|
|
32
|
+
useFactory: (userRepo: Repository<User>) => ({
|
|
33
|
+
// read-time enrichment of `changedBy` -> name/email (optional)
|
|
34
|
+
resolveUser: async (id) => {
|
|
35
|
+
const u = await userRepo.findOneBy({ id });
|
|
36
|
+
return u && { name: `${u.firstName} ${u.lastName ?? ''}`.trim(), email: u.email };
|
|
37
|
+
},
|
|
38
|
+
// how to read the acting user id from the request (default: req.user?.id)
|
|
39
|
+
getUserId: (req) => (req as { user?: { id?: number } }).user?.id,
|
|
40
|
+
}),
|
|
41
|
+
}),
|
|
42
|
+
],
|
|
43
|
+
})
|
|
44
|
+
export class AppModule {}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Register the `AuditLog` entity with your DataSource (e.g. `autoLoadEntities: true`, or add
|
|
48
|
+
`AuditLog` to your `entities` array / migrations) so the `auditLog` table exists.
|
|
49
|
+
|
|
50
|
+
> The module mounts `nestjs-cls` middleware globally to carry the request user into the
|
|
51
|
+
> TypeORM subscriber. If your app already configures `nestjs-cls`, import `AuditModule` only
|
|
52
|
+
> once and avoid registering a second `ClsModule.forRoot`.
|
|
53
|
+
|
|
54
|
+
## Automatic capture
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { Auditable } from '@studiosonrai/nestjs-audit-log';
|
|
58
|
+
|
|
59
|
+
@Auditable({ nameField: 'fullName' }) // entityType defaults to the class name
|
|
60
|
+
@Entity()
|
|
61
|
+
export class Contact { /* ... */ }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- `entityType?` — logical type stored in the log (default: class name)
|
|
65
|
+
- `nameField?` — property used as the human-readable name
|
|
66
|
+
- `exclude?: string[]` — extra fields to omit from the diff (beyond `id/createdAt/updatedAt`)
|
|
67
|
+
|
|
68
|
+
CREATE and UPDATE are now logged automatically whenever the entity is inserted or saved
|
|
69
|
+
(loaded-then-`save()`), inside the same transaction as the operation.
|
|
70
|
+
|
|
71
|
+
## DELETE and manual logging
|
|
72
|
+
|
|
73
|
+
`repository.delete(id)` does not fire TypeORM remove subscribers, so record deletes explicitly:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
await this.auditService.logEntity(contact, AuditActionType.DELETE);
|
|
77
|
+
await this.contactRepository.delete(id);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For full control use `auditService.log({ entityType, entityId, action, changes, entityName })`.
|
|
81
|
+
`changedBy` is filled from CLS when omitted.
|
|
82
|
+
|
|
83
|
+
## Querying
|
|
84
|
+
|
|
85
|
+
`AuditService` exposes `findAll(filter)` (paginated), `findByEntity`, `findByUser`, `findByAction`.
|
|
86
|
+
Mount your own controller with your app's guards — the package ships no routes.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { ClsService } from 'nestjs-cls';
|
|
4
|
+
import { AuditModuleOptions } from './interfaces/audit.interfaces';
|
|
5
|
+
export declare class AuditContextInterceptor implements NestInterceptor {
|
|
6
|
+
private readonly options;
|
|
7
|
+
private readonly cls;
|
|
8
|
+
constructor(options: AuditModuleOptions, cls: ClsService);
|
|
9
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.AuditContextInterceptor = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
18
|
+
const audit_constants_1 = require("./audit.constants");
|
|
19
|
+
function defaultGetUserId(request) {
|
|
20
|
+
const user = request?.user;
|
|
21
|
+
return user?.id;
|
|
22
|
+
}
|
|
23
|
+
let AuditContextInterceptor = class AuditContextInterceptor {
|
|
24
|
+
options;
|
|
25
|
+
cls;
|
|
26
|
+
constructor(options, cls) {
|
|
27
|
+
this.options = options;
|
|
28
|
+
this.cls = cls;
|
|
29
|
+
}
|
|
30
|
+
intercept(context, next) {
|
|
31
|
+
if (context.getType() === 'http' && this.cls.isActive()) {
|
|
32
|
+
const request = context.switchToHttp().getRequest();
|
|
33
|
+
const extractor = this.options.getUserId ?? defaultGetUserId;
|
|
34
|
+
const userId = extractor(request);
|
|
35
|
+
if (userId !== undefined) {
|
|
36
|
+
this.cls.set(audit_constants_1.AUDIT_CLS_USER_ID, userId);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return next.handle();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
exports.AuditContextInterceptor = AuditContextInterceptor;
|
|
43
|
+
exports.AuditContextInterceptor = AuditContextInterceptor = __decorate([
|
|
44
|
+
(0, common_1.Injectable)(),
|
|
45
|
+
__param(0, (0, common_1.Inject)(audit_constants_1.AUDIT_MODULE_OPTIONS)),
|
|
46
|
+
__metadata("design:paramtypes", [Object, nestjs_cls_1.ClsService])
|
|
47
|
+
], AuditContextInterceptor);
|
|
48
|
+
//# sourceMappingURL=audit-context.interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-context.interceptor.js","sourceRoot":"","sources":["../../src/audit-context.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAMwB;AAExB,2CAAwC;AACxC,uDAA4E;AAG5E,SAAS,gBAAgB,CAAC,OAAgB;IACxC,MAAM,IAAI,GAAI,OAAkD,EAAE,IAAI,CAAC;IACvE,OAAO,IAAI,EAAE,EAAE,CAAC;AAClB,CAAC;AAQM,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IAGf;IACA;IAHnB,YAEmB,OAA2B,EAC3B,GAAe;QADf,YAAO,GAAP,OAAO,CAAoB;QAC3B,QAAG,GAAH,GAAG,CAAY;IAC/B,CAAC;IAEJ,SAAS,CAAC,OAAyB,EAAE,IAAiB;QACpD,IAAI,OAAO,CAAC,OAAO,EAAE,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;YACxD,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAW,CAAC;YAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,gBAAgB,CAAC;YAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,mCAAiB,EAAE,MAAM,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;CACF,CAAA;AAlBY,0DAAuB;kCAAvB,uBAAuB;IADnC,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,sCAAoB,CAAC,CAAA;6CAEP,uBAAU;GAJvB,uBAAuB,CAkBnC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toAuditLog = toAuditLog;
|
|
4
|
+
const audit_log_entity_1 = require("./entities/audit-log.entity");
|
|
5
|
+
function toAuditLog(input) {
|
|
6
|
+
const auditLog = new audit_log_entity_1.AuditLog();
|
|
7
|
+
auditLog.entityType = input.entityType;
|
|
8
|
+
auditLog.entityId = input.entityId;
|
|
9
|
+
auditLog.entityName = input.entityName;
|
|
10
|
+
auditLog.action = input.action;
|
|
11
|
+
auditLog.changedBy = input.changedBy;
|
|
12
|
+
auditLog.changes = input.changes ? JSON.stringify(input.changes) : undefined;
|
|
13
|
+
return auditLog;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=audit.builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.builder.js","sourceRoot":"","sources":["../../src/audit.builder.ts"],"names":[],"mappings":";;AAIA,gCASC;AAbD,kEAAuD;AAIvD,SAAgB,UAAU,CAAC,KAAoB;IAC7C,MAAM,QAAQ,GAAG,IAAI,2BAAQ,EAAE,CAAC;IAChC,QAAQ,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IACvC,QAAQ,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IACnC,QAAQ,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IACvC,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IACrC,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7E,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AUDIT_CLS_USER_ID = exports.AUDITABLE_METADATA = exports.AUDIT_MODULE_OPTIONS = void 0;
|
|
4
|
+
exports.AUDIT_MODULE_OPTIONS = 'AUDIT_MODULE_OPTIONS';
|
|
5
|
+
exports.AUDITABLE_METADATA = 'audit:auditable';
|
|
6
|
+
exports.AUDIT_CLS_USER_ID = 'audit:userId';
|
|
7
|
+
//# sourceMappingURL=audit.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.constants.js","sourceRoot":"","sources":["../../src/audit.constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,oBAAoB,GAAG,sBAAsB,CAAC;AAG9C,QAAA,kBAAkB,GAAG,iBAAiB,CAAC;AAGvC,QAAA,iBAAiB,GAAG,cAAc,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function calculateChanges(oldData: Record<string, unknown> | undefined, newData: Record<string, unknown>): Record<string, {
|
|
2
|
+
old?: unknown;
|
|
3
|
+
new: unknown;
|
|
4
|
+
}>;
|
|
5
|
+
export declare function extractAuditableFields(entity: Record<string, unknown> | object, fieldsToExclude?: string[]): Record<string, unknown>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateChanges = calculateChanges;
|
|
4
|
+
exports.extractAuditableFields = extractAuditableFields;
|
|
5
|
+
function calculateChanges(oldData, newData) {
|
|
6
|
+
const changes = {};
|
|
7
|
+
if (!oldData) {
|
|
8
|
+
for (const [key, value] of Object.entries(newData)) {
|
|
9
|
+
changes[key] = { new: value };
|
|
10
|
+
}
|
|
11
|
+
return changes;
|
|
12
|
+
}
|
|
13
|
+
for (const [key, newValue] of Object.entries(newData)) {
|
|
14
|
+
const oldValue = oldData[key];
|
|
15
|
+
if (JSON.stringify(oldValue) !== JSON.stringify(newValue)) {
|
|
16
|
+
changes[key] = { old: oldValue, new: newValue };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
for (const [key, oldValue] of Object.entries(oldData)) {
|
|
20
|
+
if (!(key in newData)) {
|
|
21
|
+
changes[key] = { old: oldValue, new: undefined };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return changes;
|
|
25
|
+
}
|
|
26
|
+
function extractAuditableFields(entity, fieldsToExclude = []) {
|
|
27
|
+
const defaultExcludedFields = [
|
|
28
|
+
'createdAt',
|
|
29
|
+
'updatedAt',
|
|
30
|
+
'id',
|
|
31
|
+
...fieldsToExclude,
|
|
32
|
+
];
|
|
33
|
+
const result = {};
|
|
34
|
+
for (const [key, value] of Object.entries(entity)) {
|
|
35
|
+
if (!defaultExcludedFields.includes(key)) {
|
|
36
|
+
result[key] = value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=audit.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.helper.js","sourceRoot":"","sources":["../../src/audit.helper.ts"],"names":[],"mappings":";;AAIA,4CA+BC;AAMD,wDAoBC;AAzDD,SAAgB,gBAAgB,CAC9B,OAA4C,EAC5C,OAAgC;IAEhC,MAAM,OAAO,GAAoD,EAAE,CAAC;IAEpE,IAAI,CAAC,OAAO,EAAE,CAAC;QAEb,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QAChC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAGD,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAE9B,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;QAClD,CAAC;IACH,CAAC;IAGD,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAMD,SAAgB,sBAAsB,CACpC,MAAwC,EACxC,kBAA4B,EAAE;IAE9B,MAAM,qBAAqB,GAAG;QAC5B,WAAW;QACX,WAAW;QACX,IAAI;QACJ,GAAG,eAAe;KACnB,CAAC;IAEF,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACzC,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { AuditModuleAsyncOptions, AuditModuleOptions } from './interfaces/audit.interfaces';
|
|
3
|
+
export declare class AuditModule {
|
|
4
|
+
static forRoot(options?: AuditModuleOptions): DynamicModule;
|
|
5
|
+
static forRootAsync(options: AuditModuleAsyncOptions): DynamicModule;
|
|
6
|
+
private static baseImports;
|
|
7
|
+
private static createAsyncProviders;
|
|
8
|
+
private static createAsyncOptionsProvider;
|
|
9
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var AuditModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.AuditModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const core_1 = require("@nestjs/core");
|
|
13
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
14
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
15
|
+
const audit_log_entity_1 = require("./entities/audit-log.entity");
|
|
16
|
+
const audit_service_1 = require("./audit.service");
|
|
17
|
+
const audit_subscriber_1 = require("./audit.subscriber");
|
|
18
|
+
const audit_context_interceptor_1 = require("./audit-context.interceptor");
|
|
19
|
+
const audit_constants_1 = require("./audit.constants");
|
|
20
|
+
const sharedProviders = [
|
|
21
|
+
audit_service_1.AuditService,
|
|
22
|
+
audit_subscriber_1.AuditSubscriber,
|
|
23
|
+
{ provide: core_1.APP_INTERCEPTOR, useClass: audit_context_interceptor_1.AuditContextInterceptor },
|
|
24
|
+
];
|
|
25
|
+
let AuditModule = AuditModule_1 = class AuditModule {
|
|
26
|
+
static forRoot(options = {}) {
|
|
27
|
+
return {
|
|
28
|
+
module: AuditModule_1,
|
|
29
|
+
imports: [...AuditModule_1.baseImports()],
|
|
30
|
+
providers: [
|
|
31
|
+
{ provide: audit_constants_1.AUDIT_MODULE_OPTIONS, useValue: options },
|
|
32
|
+
...sharedProviders,
|
|
33
|
+
],
|
|
34
|
+
exports: [audit_service_1.AuditService, audit_constants_1.AUDIT_MODULE_OPTIONS],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
static forRootAsync(options) {
|
|
38
|
+
return {
|
|
39
|
+
module: AuditModule_1,
|
|
40
|
+
imports: [...AuditModule_1.baseImports(), ...(options.imports ?? [])],
|
|
41
|
+
providers: [
|
|
42
|
+
...AuditModule_1.createAsyncProviders(options),
|
|
43
|
+
...sharedProviders,
|
|
44
|
+
],
|
|
45
|
+
exports: [audit_service_1.AuditService, audit_constants_1.AUDIT_MODULE_OPTIONS],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
static baseImports() {
|
|
49
|
+
return [
|
|
50
|
+
nestjs_cls_1.ClsModule.forRoot({ global: true, guard: { mount: true } }),
|
|
51
|
+
typeorm_1.TypeOrmModule.forFeature([audit_log_entity_1.AuditLog]),
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
static createAsyncProviders(options) {
|
|
55
|
+
if (options.useExisting || options.useFactory) {
|
|
56
|
+
return [AuditModule_1.createAsyncOptionsProvider(options)];
|
|
57
|
+
}
|
|
58
|
+
if (options.useClass) {
|
|
59
|
+
return [
|
|
60
|
+
AuditModule_1.createAsyncOptionsProvider(options),
|
|
61
|
+
{ provide: options.useClass, useClass: options.useClass },
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
throw new Error('Invalid AuditModuleAsyncOptions: provide useExisting, useClass, or useFactory');
|
|
65
|
+
}
|
|
66
|
+
static createAsyncOptionsProvider(options) {
|
|
67
|
+
if (options.useFactory) {
|
|
68
|
+
return {
|
|
69
|
+
provide: audit_constants_1.AUDIT_MODULE_OPTIONS,
|
|
70
|
+
useFactory: options.useFactory,
|
|
71
|
+
inject: options.inject ?? [],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const inject = options.useExisting ?? options.useClass;
|
|
75
|
+
if (!inject) {
|
|
76
|
+
throw new Error('Invalid AuditModuleAsyncOptions: provide useExisting, useClass, or useFactory');
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
provide: audit_constants_1.AUDIT_MODULE_OPTIONS,
|
|
80
|
+
useFactory: (factory) => factory.createAuditOptions(),
|
|
81
|
+
inject: [inject],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
exports.AuditModule = AuditModule;
|
|
86
|
+
exports.AuditModule = AuditModule = AuditModule_1 = __decorate([
|
|
87
|
+
(0, common_1.Global)(),
|
|
88
|
+
(0, common_1.Module)({})
|
|
89
|
+
], AuditModule);
|
|
90
|
+
//# sourceMappingURL=audit.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.module.js","sourceRoot":"","sources":["../../src/audit.module.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Repository } from 'typeorm';
|
|
2
|
+
import { ClsService } from 'nestjs-cls';
|
|
3
|
+
import { AuditLog, AuditActionType } from './entities/audit-log.entity';
|
|
4
|
+
import { AuditFilterDto } from './dto/audit-filter.dto';
|
|
5
|
+
import { AuditLogResponseDto } from './dto/audit-log-response.dto';
|
|
6
|
+
import { PaginatedResultDto } from './dto/paginated-result.dto';
|
|
7
|
+
import { AuditLogInput, AuditModuleOptions } from './interfaces/audit.interfaces';
|
|
8
|
+
export declare class AuditService {
|
|
9
|
+
private readonly auditRepository;
|
|
10
|
+
private readonly options;
|
|
11
|
+
private readonly cls?;
|
|
12
|
+
private readonly logger;
|
|
13
|
+
constructor(auditRepository: Repository<AuditLog>, options: AuditModuleOptions, cls?: ClsService | undefined);
|
|
14
|
+
private currentUserId;
|
|
15
|
+
private enrichAuditLog;
|
|
16
|
+
log(input: AuditLogInput): Promise<AuditLog | undefined>;
|
|
17
|
+
logEntity(entity: object, action: AuditActionType, changedBy?: number): Promise<AuditLog | undefined>;
|
|
18
|
+
findByEntity(entityType: string, entityId: number): Promise<AuditLogResponseDto[]>;
|
|
19
|
+
findByUser(userId: number): Promise<AuditLogResponseDto[]>;
|
|
20
|
+
findByAction(action: AuditActionType): Promise<AuditLogResponseDto[]>;
|
|
21
|
+
findAll(filterDto: AuditFilterDto): Promise<PaginatedResultDto<AuditLogResponseDto>>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var AuditService_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.AuditService = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
19
|
+
const typeorm_2 = require("typeorm");
|
|
20
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
21
|
+
const audit_log_entity_1 = require("./entities/audit-log.entity");
|
|
22
|
+
const audit_helper_1 = require("./audit.helper");
|
|
23
|
+
const audit_builder_1 = require("./audit.builder");
|
|
24
|
+
const auditable_decorator_1 = require("./decorators/auditable.decorator");
|
|
25
|
+
const audit_constants_1 = require("./audit.constants");
|
|
26
|
+
let AuditService = AuditService_1 = class AuditService {
|
|
27
|
+
auditRepository;
|
|
28
|
+
options;
|
|
29
|
+
cls;
|
|
30
|
+
logger = new common_1.Logger(AuditService_1.name);
|
|
31
|
+
constructor(auditRepository, options, cls) {
|
|
32
|
+
this.auditRepository = auditRepository;
|
|
33
|
+
this.options = options;
|
|
34
|
+
this.cls = cls;
|
|
35
|
+
}
|
|
36
|
+
currentUserId() {
|
|
37
|
+
return this.cls?.get(audit_constants_1.AUDIT_CLS_USER_ID);
|
|
38
|
+
}
|
|
39
|
+
async enrichAuditLog(log) {
|
|
40
|
+
const response = {
|
|
41
|
+
...log,
|
|
42
|
+
changedByName: undefined,
|
|
43
|
+
changedByEmail: undefined,
|
|
44
|
+
};
|
|
45
|
+
if (log.changedBy && this.options.resolveUser) {
|
|
46
|
+
try {
|
|
47
|
+
const user = await this.options.resolveUser(log.changedBy);
|
|
48
|
+
if (user) {
|
|
49
|
+
response.changedByName = user.name;
|
|
50
|
+
response.changedByEmail = user.email;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
this.logger.error(`Failed to enrich user data for audit log ${log.id}`, String(error));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return response;
|
|
58
|
+
}
|
|
59
|
+
async log(input) {
|
|
60
|
+
try {
|
|
61
|
+
const auditLog = (0, audit_builder_1.toAuditLog)({
|
|
62
|
+
...input,
|
|
63
|
+
changedBy: input.changedBy ?? this.currentUserId(),
|
|
64
|
+
});
|
|
65
|
+
const saved = await this.auditRepository.save(auditLog);
|
|
66
|
+
this.logger.log(`Audit: ${saved.entityType} ${saved.action} id=${saved.entityId} (log #${saved.id})`);
|
|
67
|
+
return saved;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
this.logger.error('Error recording audit log', String(error));
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async logEntity(entity, action, changedBy) {
|
|
75
|
+
const auditable = (0, auditable_decorator_1.getAuditableOptions)(entity);
|
|
76
|
+
if (!auditable) {
|
|
77
|
+
this.logger.warn(`logEntity called for a non-@Auditable entity: ${entity?.constructor?.name}`);
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
const record = entity;
|
|
81
|
+
const entityName = auditable.nameField
|
|
82
|
+
? record[auditable.nameField]
|
|
83
|
+
: undefined;
|
|
84
|
+
return this.log({
|
|
85
|
+
entityType: auditable.entityType,
|
|
86
|
+
entityId: record.id,
|
|
87
|
+
entityName,
|
|
88
|
+
action,
|
|
89
|
+
changes: (0, audit_helper_1.extractAuditableFields)(entity, auditable.exclude),
|
|
90
|
+
changedBy,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async findByEntity(entityType, entityId) {
|
|
94
|
+
try {
|
|
95
|
+
const logs = await this.auditRepository.find({
|
|
96
|
+
where: { entityType, entityId },
|
|
97
|
+
order: { changedAt: 'DESC' },
|
|
98
|
+
});
|
|
99
|
+
return Promise.all(logs.map((log) => this.enrichAuditLog(log)));
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
this.logger.error(`Error fetching audit logs for ${entityType} ${entityId}`, String(error));
|
|
103
|
+
throw new common_1.InternalServerErrorException('Failed to fetch audit logs');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async findByUser(userId) {
|
|
107
|
+
try {
|
|
108
|
+
const logs = await this.auditRepository.find({
|
|
109
|
+
where: { changedBy: userId },
|
|
110
|
+
order: { changedAt: 'DESC' },
|
|
111
|
+
});
|
|
112
|
+
return Promise.all(logs.map((log) => this.enrichAuditLog(log)));
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
this.logger.error(`Error fetching audit logs for user ${userId}`, String(error));
|
|
116
|
+
throw new common_1.InternalServerErrorException('Failed to fetch audit logs');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async findByAction(action) {
|
|
120
|
+
try {
|
|
121
|
+
const logs = await this.auditRepository.find({
|
|
122
|
+
where: { action },
|
|
123
|
+
order: { changedAt: 'DESC' },
|
|
124
|
+
});
|
|
125
|
+
return Promise.all(logs.map((log) => this.enrichAuditLog(log)));
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
this.logger.error(`Error fetching audit logs for action ${action}`, String(error));
|
|
129
|
+
throw new common_1.InternalServerErrorException('Failed to fetch audit logs');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async findAll(filterDto) {
|
|
133
|
+
try {
|
|
134
|
+
const { page = 0, limit = 10, entityType, entityId, changedBy, action, search, } = filterDto;
|
|
135
|
+
const queryBuilder = this.auditRepository.createQueryBuilder('audit');
|
|
136
|
+
if (search) {
|
|
137
|
+
const searchQuery = `%${search.toLowerCase()}%`;
|
|
138
|
+
queryBuilder.andWhere('(LOWER(audit.entityType) LIKE :search OR LOWER(audit.entityName) LIKE :search)', { search: searchQuery });
|
|
139
|
+
}
|
|
140
|
+
if (entityType) {
|
|
141
|
+
queryBuilder.andWhere('audit.entityType = :entityType', { entityType });
|
|
142
|
+
}
|
|
143
|
+
if (entityId) {
|
|
144
|
+
queryBuilder.andWhere('audit.entityId = :entityId', { entityId });
|
|
145
|
+
}
|
|
146
|
+
if (changedBy) {
|
|
147
|
+
queryBuilder.andWhere('audit.changedBy = :changedBy', { changedBy });
|
|
148
|
+
}
|
|
149
|
+
if (action) {
|
|
150
|
+
queryBuilder.andWhere('audit.action = :action', { action });
|
|
151
|
+
}
|
|
152
|
+
const total = await queryBuilder.getCount();
|
|
153
|
+
const logs = await queryBuilder
|
|
154
|
+
.orderBy('audit.changedAt', 'DESC')
|
|
155
|
+
.addOrderBy('audit.id', 'DESC')
|
|
156
|
+
.skip(page * limit)
|
|
157
|
+
.take(limit)
|
|
158
|
+
.getMany();
|
|
159
|
+
const enrichedLogs = await Promise.all(logs.map((log) => this.enrichAuditLog(log)));
|
|
160
|
+
const totalPages = Math.ceil(total / limit);
|
|
161
|
+
return {
|
|
162
|
+
data: enrichedLogs,
|
|
163
|
+
total,
|
|
164
|
+
page,
|
|
165
|
+
limit,
|
|
166
|
+
totalPages,
|
|
167
|
+
hasNextPage: page < totalPages - 1,
|
|
168
|
+
hasPreviousPage: page > 0,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
this.logger.error('Error fetching audit logs', String(error));
|
|
173
|
+
throw new common_1.InternalServerErrorException('Failed to fetch audit logs');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
exports.AuditService = AuditService;
|
|
178
|
+
exports.AuditService = AuditService = AuditService_1 = __decorate([
|
|
179
|
+
(0, common_1.Injectable)(),
|
|
180
|
+
__param(0, (0, typeorm_1.InjectRepository)(audit_log_entity_1.AuditLog)),
|
|
181
|
+
__param(1, (0, common_1.Inject)(audit_constants_1.AUDIT_MODULE_OPTIONS)),
|
|
182
|
+
__param(2, (0, common_1.Optional)()),
|
|
183
|
+
__metadata("design:paramtypes", [typeorm_2.Repository, Object, nestjs_cls_1.ClsService])
|
|
184
|
+
], AuditService);
|
|
185
|
+
//# sourceMappingURL=audit.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.service.js","sourceRoot":"","sources":["../../src/audit.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DataSource, EntitySubscriberInterface, InsertEvent, UpdateEvent } from 'typeorm';
|
|
2
|
+
import { ClsService } from 'nestjs-cls';
|
|
3
|
+
export declare class AuditSubscriber implements EntitySubscriberInterface {
|
|
4
|
+
private readonly cls;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
constructor(dataSource: DataSource, cls: ClsService);
|
|
7
|
+
private currentUserId;
|
|
8
|
+
afterInsert(event: InsertEvent<object>): Promise<void>;
|
|
9
|
+
afterUpdate(event: UpdateEvent<object>): Promise<void>;
|
|
10
|
+
private persist;
|
|
11
|
+
}
|