rl-core-api 0.2.0 → 0.4.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.
Files changed (89) hide show
  1. package/README.md +2 -2
  2. package/dist/core/config/env.schema.d.ts +2 -2
  3. package/dist/core/config/env.schema.js +3 -3
  4. package/dist/core/config/env.service.d.ts +1 -0
  5. package/dist/core/config/env.service.js +3 -0
  6. package/dist/core/context/requestLog.context.d.ts +10 -0
  7. package/dist/core/context/requestLog.context.js +26 -0
  8. package/dist/core/database/migrations/1710000000000-InitialSchema.js +63 -36
  9. package/dist/core/database/migrations/index.js +1 -9
  10. package/dist/core/events/appEvent.enum.d.ts +18 -1
  11. package/dist/core/events/appEvent.enum.js +1 -0
  12. package/dist/core/filters/allExceptions.filter.d.ts +6 -0
  13. package/dist/core/filters/allExceptions.filter.js +47 -2
  14. package/dist/core/query/parseFilter.util.js +6 -4
  15. package/dist/core/utils/ip.util.d.ts +1 -0
  16. package/dist/core/utils/ip.util.js +8 -0
  17. package/dist/coreEntities.d.ts +2 -3
  18. package/dist/coreEntities.js +2 -4
  19. package/dist/features/audit/audit.module.js +4 -7
  20. package/dist/features/audit/domain/audit.service.d.ts +6 -15
  21. package/dist/features/audit/domain/audit.service.js +9 -32
  22. package/dist/features/audit/domain/classifyError.util.d.ts +1 -1
  23. package/dist/features/audit/domain/classifyError.util.js +8 -8
  24. package/dist/features/audit/domain/enums/errorType.enum.d.ts +9 -0
  25. package/dist/features/audit/domain/enums/errorType.enum.js +13 -0
  26. package/dist/features/audit/domain/enums/requestOutcome.enum.d.ts +5 -0
  27. package/dist/features/audit/domain/enums/requestOutcome.enum.js +9 -0
  28. package/dist/features/audit/domain/index.d.ts +2 -0
  29. package/dist/features/audit/domain/index.js +2 -0
  30. package/dist/features/audit/infra/auditData.subscriber.js +17 -9
  31. package/dist/features/audit/infra/index.d.ts +2 -4
  32. package/dist/features/audit/infra/index.js +2 -4
  33. package/dist/features/audit/infra/repositories/requestLog.repository.d.ts +7 -0
  34. package/dist/features/audit/infra/repositories/{auditChange.repository.js → requestLog.repository.js} +10 -10
  35. package/dist/features/audit/infra/schema/auditDataChange.schema.d.ts +3 -3
  36. package/dist/features/audit/infra/schema/auditDataChange.schema.js +8 -7
  37. package/dist/features/audit/infra/schema/requestLog.schema.d.ts +20 -0
  38. package/dist/features/audit/infra/schema/requestLog.schema.js +92 -0
  39. package/dist/features/audit/presentation/audit.controller.d.ts +4 -8
  40. package/dist/features/audit/presentation/audit.controller.js +8 -31
  41. package/dist/features/audit/presentation/audit.interceptor.d.ts +5 -1
  42. package/dist/features/audit/presentation/audit.interceptor.js +47 -28
  43. package/dist/features/audit/presentation/decorators/auditable.decorator.d.ts +3 -0
  44. package/dist/features/audit/presentation/decorators/auditable.decorator.js +7 -0
  45. package/dist/features/audit/presentation/filters/audit.filters.d.ts +1 -2
  46. package/dist/features/audit/presentation/filters/audit.filters.js +65 -49
  47. package/dist/features/audit/presentation/httpError.listener.d.ts +8 -0
  48. package/dist/features/audit/presentation/httpError.listener.js +61 -0
  49. package/dist/features/audit/presentation/index.d.ts +2 -0
  50. package/dist/features/audit/presentation/index.js +2 -0
  51. package/dist/features/audit/presentation/responses/auditDataChange.response.js +1 -1
  52. package/dist/features/audit/presentation/responses/log.response.d.ts +12 -27
  53. package/dist/features/audit/presentation/responses/log.response.js +66 -88
  54. package/dist/features/auth/infra/schema/authToken.schema.d.ts +5 -5
  55. package/dist/features/auth/infra/schema/authToken.schema.js +7 -7
  56. package/dist/features/auth/presentation/auth.controller.js +10 -0
  57. package/dist/features/maintenance/domain/cleanup.service.d.ts +1 -4
  58. package/dist/features/maintenance/domain/cleanup.service.js +1 -21
  59. package/dist/features/maintenance/maintenance.module.js +1 -2
  60. package/dist/features/notifications/domain/enums/channelType.enum.d.ts +5 -5
  61. package/dist/features/notifications/domain/enums/channelType.enum.js +5 -5
  62. package/dist/features/notifications/domain/enums/deliveryStatus.enum.d.ts +6 -6
  63. package/dist/features/notifications/domain/enums/deliveryStatus.enum.js +6 -6
  64. package/dist/features/notifications/domain/enums/notificationType.enum.d.ts +4 -4
  65. package/dist/features/notifications/domain/enums/notificationType.enum.js +4 -4
  66. package/dist/features/notifications/domain/enums/scopeType.enum.d.ts +3 -3
  67. package/dist/features/notifications/domain/enums/scopeType.enum.js +3 -3
  68. package/dist/features/notifications/infra/schema/notification.schema.js +2 -2
  69. package/dist/features/notifications/infra/schema/notificationScope.schema.js +2 -2
  70. package/dist/features/notifications/presentation/commands/createNotification.command.js +2 -2
  71. package/dist/features/notifications/presentation/responses/notification.response.js +1 -1
  72. package/dist/features/rbac/presentation/rbac.controller.js +5 -0
  73. package/dist/features/users/presentation/users.controller.js +5 -0
  74. package/dist/index.d.ts +5 -3
  75. package/dist/index.js +10 -6
  76. package/package.json +1 -1
  77. package/dist/core/database/migrations/1786060800000-FirstAccessTokenType.d.ts +0 -6
  78. package/dist/core/database/migrations/1786060800000-FirstAccessTokenType.js +0 -19
  79. package/dist/core/database/migrations/1786147200000-PermanentAccountLock.d.ts +0 -6
  80. package/dist/core/database/migrations/1786147200000-PermanentAccountLock.js +0 -15
  81. package/dist/core/database/migrations/1786233600000-Notifications.d.ts +0 -6
  82. package/dist/core/database/migrations/1786233600000-Notifications.js +0 -59
  83. package/dist/features/audit/infra/repositories/auditChange.repository.d.ts +0 -7
  84. package/dist/features/audit/infra/repositories/errorLog.repository.d.ts +0 -7
  85. package/dist/features/audit/infra/repositories/errorLog.repository.js +0 -35
  86. package/dist/features/audit/infra/schema/auditChange.schema.d.ts +0 -14
  87. package/dist/features/audit/infra/schema/auditChange.schema.js +0 -68
  88. package/dist/features/audit/infra/schema/errorLog.schema.d.ts +0 -21
  89. package/dist/features/audit/infra/schema/errorLog.schema.js +0 -69
@@ -1,24 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.classifyError = classifyError;
4
- const errorLog_schema_1 = require("../infra/schema/errorLog.schema");
4
+ const errorType_enum_1 = require("./enums/errorType.enum");
5
5
  function classifyError(exception, status) {
6
- if (status === 400) {
7
- return errorLog_schema_1.ErrorType.VALIDATION;
6
+ if (status === 400 || status === 422) {
7
+ return errorType_enum_1.ErrorType.VALIDATION;
8
8
  }
9
9
  if (status === 401 || status === 403) {
10
- return errorLog_schema_1.ErrorType.AUTH;
10
+ return errorType_enum_1.ErrorType.AUTH;
11
11
  }
12
12
  if (status === 404) {
13
- return errorLog_schema_1.ErrorType.NOT_FOUND;
13
+ return errorType_enum_1.ErrorType.NOT_FOUND;
14
14
  }
15
15
  if (status === 429) {
16
- return errorLog_schema_1.ErrorType.RATE_LIMIT;
16
+ return errorType_enum_1.ErrorType.RATE_LIMIT;
17
17
  }
18
18
  const name = exception?.name ?? "";
19
19
  if (name.includes("QueryFailedError") ||
20
20
  name.includes("EntityNotFoundError")) {
21
- return errorLog_schema_1.ErrorType.DATABASE;
21
+ return errorType_enum_1.ErrorType.DATABASE;
22
22
  }
23
- return errorLog_schema_1.ErrorType.INTERNAL;
23
+ return errorType_enum_1.ErrorType.INTERNAL;
24
24
  }
@@ -0,0 +1,9 @@
1
+ export declare enum ErrorType {
2
+ VALIDATION = 0,
3
+ AUTH = 1,
4
+ NOT_FOUND = 2,
5
+ RATE_LIMIT = 3,
6
+ DATABASE = 4,
7
+ INTEGRATION = 5,
8
+ INTERNAL = 6
9
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ErrorType = void 0;
4
+ var ErrorType;
5
+ (function (ErrorType) {
6
+ ErrorType[ErrorType["VALIDATION"] = 0] = "VALIDATION";
7
+ ErrorType[ErrorType["AUTH"] = 1] = "AUTH";
8
+ ErrorType[ErrorType["NOT_FOUND"] = 2] = "NOT_FOUND";
9
+ ErrorType[ErrorType["RATE_LIMIT"] = 3] = "RATE_LIMIT";
10
+ ErrorType[ErrorType["DATABASE"] = 4] = "DATABASE";
11
+ ErrorType[ErrorType["INTEGRATION"] = 5] = "INTEGRATION";
12
+ ErrorType[ErrorType["INTERNAL"] = 6] = "INTERNAL";
13
+ })(ErrorType || (exports.ErrorType = ErrorType = {}));
@@ -0,0 +1,5 @@
1
+ export declare enum RequestOutcome {
2
+ SUCCESS = 0,
3
+ ERROR = 1,
4
+ ABORTED = 2
5
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RequestOutcome = void 0;
4
+ var RequestOutcome;
5
+ (function (RequestOutcome) {
6
+ RequestOutcome[RequestOutcome["SUCCESS"] = 0] = "SUCCESS";
7
+ RequestOutcome[RequestOutcome["ERROR"] = 1] = "ERROR";
8
+ RequestOutcome[RequestOutcome["ABORTED"] = 2] = "ABORTED";
9
+ })(RequestOutcome || (exports.RequestOutcome = RequestOutcome = {}));
@@ -1,2 +1,4 @@
1
1
  export * from "./audit.service";
2
2
  export * from "./classifyError.util";
3
+ export * from "./enums/errorType.enum";
4
+ export * from "./enums/requestOutcome.enum";
@@ -16,3 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./audit.service"), exports);
18
18
  __exportStar(require("./classifyError.util"), exports);
19
+ __exportStar(require("./enums/errorType.enum"), exports);
20
+ __exportStar(require("./enums/requestOutcome.enum"), exports);
@@ -15,6 +15,9 @@ const common_1 = require("@nestjs/common");
15
15
  const typeorm_1 = require("typeorm");
16
16
  const auditContext_1 = require("../../../core/context/auditContext");
17
17
  const auditDataChange_schema_1 = require("./schema/auditDataChange.schema");
18
+ const requestLog_schema_1 = require("./schema/requestLog.schema");
19
+ const authToken_schema_1 = require("../../auth/infra/schema/authToken.schema");
20
+ const passwordHistory_schema_1 = require("../../users/infra/schema/passwordHistory.schema");
18
21
  function entityIdOf(source) {
19
22
  if (source && typeof source === "object" && "id" in source) {
20
23
  const id = source.id;
@@ -22,17 +25,22 @@ function entityIdOf(source) {
22
25
  }
23
26
  return null;
24
27
  }
25
- const EXCLUDED_ENTITIES = new Set([
26
- "AuditChange",
27
- "ErrorLog",
28
- "AuditDataChange",
29
- "AuthToken",
30
- "PasswordHistory",
31
- ]);
28
+ const EXCLUDED_ENTITIES = new Set([requestLog_schema_1.RequestLog, auditDataChange_schema_1.AuditDataChange, authToken_schema_1.AuthToken, passwordHistory_schema_1.PasswordHistory].map((entity) => entity.name));
32
29
  const BASE_FIELDS = new Set(["id", "createdAt", "updatedAt", "deletedAt"]);
33
30
  const SENSITIVE_FIELDS = {
34
31
  User: new Set(["password", "twoFactorSecret", "backupCodes"]),
35
32
  };
33
+ const OPERATIONAL_FIELDS = {
34
+ User: new Set([
35
+ "failedLoginAttempts",
36
+ "twoFactorEnabled",
37
+ "twoFactorConfirmedAt",
38
+ ]),
39
+ };
40
+ const excludedFieldsOf = (entityName) => new Set([
41
+ ...(SENSITIVE_FIELDS[entityName] ?? []),
42
+ ...(OPERATIONAL_FIELDS[entityName] ?? []),
43
+ ]);
36
44
  let AuditDataSubscriber = AuditDataSubscriber_1 = class AuditDataSubscriber {
37
45
  constructor(dataSource) {
38
46
  this.logger = new common_1.Logger(AuditDataSubscriber_1.name);
@@ -56,7 +64,7 @@ let AuditDataSubscriber = AuditDataSubscriber_1 = class AuditDataSubscriber {
56
64
  if (!event.updatedColumns.length) {
57
65
  return;
58
66
  }
59
- const excluded = SENSITIVE_FIELDS[event.metadata.name] ?? new Set();
67
+ const excluded = excludedFieldsOf(event.metadata.name);
60
68
  const oldData = {};
61
69
  const newData = {};
62
70
  for (const col of event.updatedColumns) {
@@ -95,7 +103,7 @@ let AuditDataSubscriber = AuditDataSubscriber_1 = class AuditDataSubscriber {
95
103
  });
96
104
  }
97
105
  snapshot(source, metadata) {
98
- const excluded = SENSITIVE_FIELDS[metadata.name] ?? new Set();
106
+ const excluded = excludedFieldsOf(metadata.name);
99
107
  const result = {};
100
108
  for (const col of metadata.columns) {
101
109
  const prop = col.propertyName;
@@ -1,7 +1,5 @@
1
1
  export * from "./auditData.subscriber";
2
- export * from "./repositories/auditChange.repository";
3
2
  export * from "./repositories/auditDataChange.repository";
4
- export * from "./repositories/errorLog.repository";
5
- export * from "./schema/auditChange.schema";
3
+ export * from "./repositories/requestLog.repository";
6
4
  export * from "./schema/auditDataChange.schema";
7
- export * from "./schema/errorLog.schema";
5
+ export * from "./schema/requestLog.schema";
@@ -15,9 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./auditData.subscriber"), exports);
18
- __exportStar(require("./repositories/auditChange.repository"), exports);
19
18
  __exportStar(require("./repositories/auditDataChange.repository"), exports);
20
- __exportStar(require("./repositories/errorLog.repository"), exports);
21
- __exportStar(require("./schema/auditChange.schema"), exports);
19
+ __exportStar(require("./repositories/requestLog.repository"), exports);
22
20
  __exportStar(require("./schema/auditDataChange.schema"), exports);
23
- __exportStar(require("./schema/errorLog.schema"), exports);
21
+ __exportStar(require("./schema/requestLog.schema"), exports);
@@ -0,0 +1,7 @@
1
+ import { DataSource, Repository } from "typeorm";
2
+ import { PaginationQuery } from "../../../../core/utils/pagination.util";
3
+ import { RequestLog } from "../schema/requestLog.schema";
4
+ export declare class RequestLogRepository extends Repository<RequestLog> {
5
+ constructor(dataSource: DataSource);
6
+ findPaginated(query: PaginationQuery): Promise<[RequestLog[], number]>;
7
+ }
@@ -9,27 +9,27 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.AuditChangeRepository = void 0;
12
+ exports.RequestLogRepository = void 0;
13
13
  const common_1 = require("@nestjs/common");
14
14
  const typeorm_1 = require("typeorm");
15
15
  const paginateWithFilter_util_1 = require("../../../../core/query/paginateWithFilter.util");
16
- const auditChange_schema_1 = require("../schema/auditChange.schema");
16
+ const requestLog_schema_1 = require("../schema/requestLog.schema");
17
17
  const audit_filters_1 = require("../../presentation/filters/audit.filters");
18
- let AuditChangeRepository = class AuditChangeRepository extends typeorm_1.Repository {
18
+ let RequestLogRepository = class RequestLogRepository extends typeorm_1.Repository {
19
19
  constructor(dataSource) {
20
- super(auditChange_schema_1.AuditChange, dataSource.createEntityManager());
20
+ super(requestLog_schema_1.RequestLog, dataSource.createEntityManager());
21
21
  }
22
22
  findPaginated(query) {
23
- return (0, paginateWithFilter_util_1.paginateWithFilter)(this.createQueryBuilder("auditChange"), {
23
+ return (0, paginateWithFilter_util_1.paginateWithFilter)(this.createQueryBuilder("requestLog"), {
24
24
  query,
25
- catalog: audit_filters_1.AUDIT_CHANGES_FILTER_CATALOG,
25
+ catalog: audit_filters_1.REQUEST_LOGS_FILTER_CATALOG,
26
26
  defaultSort: "createdAt",
27
- searchFields: ["path", "action"],
27
+ searchFields: ["path", "action", "errorMessage"],
28
28
  });
29
29
  }
30
30
  };
31
- exports.AuditChangeRepository = AuditChangeRepository;
32
- exports.AuditChangeRepository = AuditChangeRepository = __decorate([
31
+ exports.RequestLogRepository = RequestLogRepository;
32
+ exports.RequestLogRepository = RequestLogRepository = __decorate([
33
33
  (0, common_1.Injectable)(),
34
34
  __metadata("design:paramtypes", [typeorm_1.DataSource])
35
- ], AuditChangeRepository);
35
+ ], RequestLogRepository);
@@ -1,8 +1,8 @@
1
1
  import { BaseEntity } from "../../../../core/database/base.schema";
2
2
  export declare enum AuditDataAction {
3
- CREATE = "CREATE",
4
- UPDATE = "UPDATE",
5
- DELETE = "DELETE"
3
+ CREATE = 0,
4
+ UPDATE = 1,
5
+ DELETE = 2
6
6
  }
7
7
  export declare class AuditDataChange extends BaseEntity {
8
8
  entity: string;
@@ -14,9 +14,9 @@ const typeorm_1 = require("typeorm");
14
14
  const base_schema_1 = require("../../../../core/database/base.schema");
15
15
  var AuditDataAction;
16
16
  (function (AuditDataAction) {
17
- AuditDataAction["CREATE"] = "CREATE";
18
- AuditDataAction["UPDATE"] = "UPDATE";
19
- AuditDataAction["DELETE"] = "DELETE";
17
+ AuditDataAction[AuditDataAction["CREATE"] = 0] = "CREATE";
18
+ AuditDataAction[AuditDataAction["UPDATE"] = 1] = "UPDATE";
19
+ AuditDataAction[AuditDataAction["DELETE"] = 2] = "DELETE";
20
20
  })(AuditDataAction || (exports.AuditDataAction = AuditDataAction = {}));
21
21
  let AuditDataChange = class AuditDataChange extends base_schema_1.BaseEntity {
22
22
  };
@@ -30,8 +30,8 @@ __decorate([
30
30
  __metadata("design:type", Object)
31
31
  ], AuditDataChange.prototype, "entityId", void 0);
32
32
  __decorate([
33
- (0, typeorm_1.Column)({ type: "enum", enum: AuditDataAction }),
34
- __metadata("design:type", String)
33
+ (0, typeorm_1.Column)({ type: "tinyint", unsigned: true }),
34
+ __metadata("design:type", Number)
35
35
  ], AuditDataChange.prototype, "action", void 0);
36
36
  __decorate([
37
37
  (0, typeorm_1.Column)({ name: "old_data", type: "json", nullable: true }),
@@ -51,6 +51,7 @@ __decorate([
51
51
  ], AuditDataChange.prototype, "ipAddress", void 0);
52
52
  exports.AuditDataChange = AuditDataChange = __decorate([
53
53
  (0, typeorm_1.Entity)("audit_data_changes"),
54
- (0, typeorm_1.Index)(["entity", "entityId"]),
55
- (0, typeorm_1.Index)(["userId"])
54
+ (0, typeorm_1.Index)(["createdAt"]),
55
+ (0, typeorm_1.Index)(["entity", "entityId", "createdAt"]),
56
+ (0, typeorm_1.Index)(["userId", "createdAt"])
56
57
  ], AuditDataChange);
@@ -0,0 +1,20 @@
1
+ import { BaseEntity } from "../../../../core/database/base.schema";
2
+ import { ErrorType } from "../../domain/enums/errorType.enum";
3
+ import { RequestOutcome } from "../../domain/enums/requestOutcome.enum";
4
+ export declare class RequestLog extends BaseEntity {
5
+ outcome: RequestOutcome;
6
+ action?: string | null;
7
+ method?: string | null;
8
+ path?: string | null;
9
+ route?: string | null;
10
+ statusCode?: number | null;
11
+ durationMs?: number | null;
12
+ userId?: string | null;
13
+ ipHash?: string | null;
14
+ userAgent?: string | null;
15
+ requestId?: string | null;
16
+ errorType?: ErrorType | null;
17
+ errorCode?: string | null;
18
+ errorMessage?: string | null;
19
+ errorStack?: string | null;
20
+ }
@@ -0,0 +1,92 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RequestLog = void 0;
13
+ const typeorm_1 = require("typeorm");
14
+ const base_schema_1 = require("../../../../core/database/base.schema");
15
+ const requestOutcome_enum_1 = require("../../domain/enums/requestOutcome.enum");
16
+ let RequestLog = class RequestLog extends base_schema_1.BaseEntity {
17
+ };
18
+ exports.RequestLog = RequestLog;
19
+ __decorate([
20
+ (0, typeorm_1.Column)({ type: "tinyint", unsigned: true }),
21
+ __metadata("design:type", Number)
22
+ ], RequestLog.prototype, "outcome", void 0);
23
+ __decorate([
24
+ (0, typeorm_1.Column)({ type: "varchar", length: 100, nullable: true }),
25
+ __metadata("design:type", Object)
26
+ ], RequestLog.prototype, "action", void 0);
27
+ __decorate([
28
+ (0, typeorm_1.Column)({ type: "varchar", length: 10, nullable: true }),
29
+ __metadata("design:type", Object)
30
+ ], RequestLog.prototype, "method", void 0);
31
+ __decorate([
32
+ (0, typeorm_1.Column)({ type: "varchar", length: 255, nullable: true }),
33
+ __metadata("design:type", Object)
34
+ ], RequestLog.prototype, "path", void 0);
35
+ __decorate([
36
+ (0, typeorm_1.Column)({ type: "varchar", length: 255, nullable: true }),
37
+ __metadata("design:type", Object)
38
+ ], RequestLog.prototype, "route", void 0);
39
+ __decorate([
40
+ (0, typeorm_1.Column)({ name: "status_code", type: "int", nullable: true }),
41
+ __metadata("design:type", Object)
42
+ ], RequestLog.prototype, "statusCode", void 0);
43
+ __decorate([
44
+ (0, typeorm_1.Column)({ name: "duration_ms", type: "int", nullable: true }),
45
+ __metadata("design:type", Object)
46
+ ], RequestLog.prototype, "durationMs", void 0);
47
+ __decorate([
48
+ (0, typeorm_1.Column)({ name: "user_id", type: "char", length: 36, nullable: true }),
49
+ __metadata("design:type", Object)
50
+ ], RequestLog.prototype, "userId", void 0);
51
+ __decorate([
52
+ (0, typeorm_1.Column)({ name: "ip_hash", type: "char", length: 64, nullable: true }),
53
+ __metadata("design:type", Object)
54
+ ], RequestLog.prototype, "ipHash", void 0);
55
+ __decorate([
56
+ (0, typeorm_1.Column)({ name: "user_agent", type: "varchar", length: 255, nullable: true }),
57
+ __metadata("design:type", Object)
58
+ ], RequestLog.prototype, "userAgent", void 0);
59
+ __decorate([
60
+ (0, typeorm_1.Column)({ name: "request_id", type: "char", length: 36, nullable: true }),
61
+ __metadata("design:type", Object)
62
+ ], RequestLog.prototype, "requestId", void 0);
63
+ __decorate([
64
+ (0, typeorm_1.Column)({
65
+ name: "error_type",
66
+ type: "tinyint",
67
+ unsigned: true,
68
+ nullable: true,
69
+ }),
70
+ __metadata("design:type", Object)
71
+ ], RequestLog.prototype, "errorType", void 0);
72
+ __decorate([
73
+ (0, typeorm_1.Column)({ name: "error_code", type: "varchar", length: 100, nullable: true }),
74
+ __metadata("design:type", Object)
75
+ ], RequestLog.prototype, "errorCode", void 0);
76
+ __decorate([
77
+ (0, typeorm_1.Column)({ name: "error_message", type: "varchar", length: 255, nullable: true }),
78
+ __metadata("design:type", Object)
79
+ ], RequestLog.prototype, "errorMessage", void 0);
80
+ __decorate([
81
+ (0, typeorm_1.Column)({ name: "error_stack", type: "text", nullable: true }),
82
+ __metadata("design:type", Object)
83
+ ], RequestLog.prototype, "errorStack", void 0);
84
+ exports.RequestLog = RequestLog = __decorate([
85
+ (0, typeorm_1.Entity)("request_logs"),
86
+ (0, typeorm_1.Index)(["createdAt"]),
87
+ (0, typeorm_1.Index)(["outcome", "createdAt"]),
88
+ (0, typeorm_1.Index)(["statusCode", "createdAt"]),
89
+ (0, typeorm_1.Index)(["userId", "createdAt"]),
90
+ (0, typeorm_1.Index)(["route", "createdAt"]),
91
+ (0, typeorm_1.Index)(["requestId"])
92
+ ], RequestLog);
@@ -1,16 +1,12 @@
1
1
  import { FilterFieldResponse } from "../../../core/query/filterSchema.response";
2
2
  import { Paginated, PaginationQuery } from "../../../core/utils/pagination.util";
3
- import { AuditService } from "../domain/audit.service";
4
- import { AuditDataChangeWithUser, WithUserRef } from "../domain/audit.service";
5
- import { AuditChange } from "../infra/schema/auditChange.schema";
6
- import { ErrorLog } from "../infra/schema/errorLog.schema";
3
+ import { AuditDataChangeWithUser, AuditService, WithUserRef } from "../domain/audit.service";
4
+ import { RequestLog } from "../infra/schema/requestLog.schema";
7
5
  export declare class AuditController {
8
6
  private readonly audit;
9
7
  constructor(audit: AuditService);
10
- changes(query: PaginationQuery): Promise<Paginated<WithUserRef<AuditChange>>>;
11
- changesFilterSchema(): FilterFieldResponse[];
12
- errors(query: PaginationQuery): Promise<Paginated<WithUserRef<ErrorLog>>>;
13
- errorsFilterSchema(): FilterFieldResponse[];
8
+ requests(query: PaginationQuery): Promise<Paginated<WithUserRef<RequestLog>>>;
9
+ requestsFilterSchema(): FilterFieldResponse[];
14
10
  dataChanges(query: PaginationQuery): Promise<Paginated<AuditDataChangeWithUser>>;
15
11
  dataChangesFilterSchema(): FilterFieldResponse[];
16
12
  }
@@ -27,17 +27,11 @@ let AuditController = class AuditController {
27
27
  constructor(audit) {
28
28
  this.audit = audit;
29
29
  }
30
- changes(query) {
31
- return this.audit.listChanges(query);
30
+ requests(query) {
31
+ return this.audit.listRequests(query);
32
32
  }
33
- changesFilterSchema() {
34
- return (0, filterSchema_response_1.toFilterSchema)(audit_filters_1.AUDIT_CHANGES_FILTER_CATALOG);
35
- }
36
- errors(query) {
37
- return this.audit.listErrors(query);
38
- }
39
- errorsFilterSchema() {
40
- return (0, filterSchema_response_1.toFilterSchema)(audit_filters_1.ERROR_LOGS_FILTER_CATALOG);
33
+ requestsFilterSchema() {
34
+ return (0, filterSchema_response_1.toFilterSchema)(audit_filters_1.REQUEST_LOGS_FILTER_CATALOG);
41
35
  }
42
36
  dataChanges(query) {
43
37
  return this.audit.listDataChanges(query);
@@ -48,39 +42,22 @@ let AuditController = class AuditController {
48
42
  };
49
43
  exports.AuditController = AuditController;
50
44
  __decorate([
51
- (0, common_1.Get)("changes"),
45
+ (0, common_1.Get)("requests"),
52
46
  (0, requirePermission_decorator_1.RequirePermission)("audit:read:any"),
53
47
  (0, swagger_1.ApiOkResponse)({ type: log_response_1.PaginatedRequestLogsResponse }),
54
48
  __param(0, (0, common_1.Query)()),
55
49
  __metadata("design:type", Function),
56
50
  __metadata("design:paramtypes", [pagination_util_1.PaginationQuery]),
57
51
  __metadata("design:returntype", Promise)
58
- ], AuditController.prototype, "changes", null);
59
- __decorate([
60
- (0, common_1.Get)("changes/filter-schema"),
61
- (0, requirePermission_decorator_1.RequirePermission)("audit:read:any"),
62
- (0, swagger_1.ApiOkResponse)({ type: filterSchema_response_1.FilterFieldResponse, isArray: true }),
63
- __metadata("design:type", Function),
64
- __metadata("design:paramtypes", []),
65
- __metadata("design:returntype", Array)
66
- ], AuditController.prototype, "changesFilterSchema", null);
67
- __decorate([
68
- (0, common_1.Get)("errors"),
69
- (0, requirePermission_decorator_1.RequirePermission)("audit:read:any"),
70
- (0, swagger_1.ApiOkResponse)({ type: log_response_1.PaginatedErrorLogsResponse }),
71
- __param(0, (0, common_1.Query)()),
72
- __metadata("design:type", Function),
73
- __metadata("design:paramtypes", [pagination_util_1.PaginationQuery]),
74
- __metadata("design:returntype", Promise)
75
- ], AuditController.prototype, "errors", null);
52
+ ], AuditController.prototype, "requests", null);
76
53
  __decorate([
77
- (0, common_1.Get)("errors/filter-schema"),
54
+ (0, common_1.Get)("requests/filter-schema"),
78
55
  (0, requirePermission_decorator_1.RequirePermission)("audit:read:any"),
79
56
  (0, swagger_1.ApiOkResponse)({ type: filterSchema_response_1.FilterFieldResponse, isArray: true }),
80
57
  __metadata("design:type", Function),
81
58
  __metadata("design:paramtypes", []),
82
59
  __metadata("design:returntype", Array)
83
- ], AuditController.prototype, "errorsFilterSchema", null);
60
+ ], AuditController.prototype, "requestsFilterSchema", null);
84
61
  __decorate([
85
62
  (0, common_1.Get)("data-changes"),
86
63
  (0, requirePermission_decorator_1.RequirePermission)("audit:read-trail:any"),
@@ -1,8 +1,12 @@
1
1
  import { CallHandler, ExecutionContext, NestInterceptor } from "@nestjs/common";
2
+ import { Reflector } from "@nestjs/core";
2
3
  import { Observable } from "rxjs";
4
+ import { EnvService } from "../../../core/config/env.service";
3
5
  import { AuditService } from "../domain/audit.service";
4
6
  export declare class AuditInterceptor implements NestInterceptor {
5
7
  private readonly audit;
6
- constructor(audit: AuditService);
8
+ private readonly env;
9
+ private readonly reflector;
10
+ constructor(audit: AuditService, env: EnvService, reflector: Reflector);
7
11
  intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
8
12
  }
@@ -12,15 +12,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.AuditInterceptor = void 0;
13
13
  const node_crypto_1 = require("node:crypto");
14
14
  const common_1 = require("@nestjs/common");
15
+ const core_1 = require("@nestjs/core");
15
16
  const rxjs_1 = require("rxjs");
17
+ const env_service_1 = require("../../../core/config/env.service");
16
18
  const auditContext_1 = require("../../../core/context/auditContext");
19
+ const requestLog_context_1 = require("../../../core/context/requestLog.context");
17
20
  const ip_util_1 = require("../../../core/utils/ip.util");
18
21
  const audit_service_1 = require("../domain/audit.service");
19
- const classifyError_util_1 = require("../domain/classifyError.util");
22
+ const requestOutcome_enum_1 = require("../domain/enums/requestOutcome.enum");
23
+ const auditable_decorator_1 = require("./decorators/auditable.decorator");
20
24
  const REQUEST_ID_HEADER = "x-request-id";
21
25
  let AuditInterceptor = class AuditInterceptor {
22
- constructor(audit) {
26
+ constructor(audit, env, reflector) {
23
27
  this.audit = audit;
28
+ this.env = env;
29
+ this.reflector = reflector;
24
30
  }
25
31
  intercept(context, next) {
26
32
  const req = context.switchToHttp().getRequest();
@@ -32,41 +38,52 @@ let AuditInterceptor = class AuditInterceptor {
32
38
  const requestId = req.headers[REQUEST_ID_HEADER] || (0, node_crypto_1.randomUUID)();
33
39
  res.setHeader("X-Request-Id", requestId);
34
40
  req.requestId = requestId;
41
+ const auditable = this.reflector.getAllAndOverride(auditable_decorator_1.AUDITABLE_KEY, [context.getHandler(), context.getClass()]);
42
+ const action = typeof auditable === "string" ? auditable : auditable ? `${method} ${req.path}` : null;
43
+ const logContext = { action, startedAt: start, userId: user?.id ?? null };
44
+ (0, requestLog_context_1.setRequestLogContext)(req, logContext);
35
45
  res.once("finish", () => {
36
- void this.audit.recordChange({
37
- userId: user?.id ?? null,
38
- action: `${method} ${req.path}`,
46
+ const durationMs = Date.now() - start;
47
+ if (res.statusCode >= 400) {
48
+ return;
49
+ }
50
+ if (!action && durationMs < this.env.get("AUDIT_SLOW_REQUEST_MS")) {
51
+ return;
52
+ }
53
+ void this.audit.recordRequest({
54
+ outcome: requestOutcome_enum_1.RequestOutcome.SUCCESS,
55
+ action,
39
56
  method,
40
57
  path: req.path,
41
- ipAddress,
58
+ route: (0, requestLog_context_1.routePathOf)(req),
42
59
  statusCode: res.statusCode,
60
+ durationMs,
61
+ userId: logContext.userId,
62
+ ipHash: (0, ip_util_1.hashIp)(ipAddress, this.env.auditIpSalt()) ?? null,
63
+ userAgent: req.headers["user-agent"]?.slice(0, 255) ?? null,
64
+ requestId,
65
+ });
66
+ });
67
+ res.once("close", () => {
68
+ if (res.writableFinished) {
69
+ return;
70
+ }
71
+ void this.audit.recordRequest({
72
+ outcome: requestOutcome_enum_1.RequestOutcome.ABORTED,
73
+ action,
74
+ method,
75
+ path: req.path,
76
+ route: (0, requestLog_context_1.routePathOf)(req),
43
77
  durationMs: Date.now() - start,
78
+ userId: logContext.userId,
79
+ ipHash: (0, ip_util_1.hashIp)(ipAddress, this.env.auditIpSalt()) ?? null,
80
+ userAgent: req.headers["user-agent"]?.slice(0, 255) ?? null,
44
81
  requestId,
45
82
  });
46
83
  });
47
84
  return new rxjs_1.Observable((subscriber) => {
48
85
  auditContext_1.auditContext.run({ userId: user?.id ?? null, ipAddress, requestId }, () => {
49
- next
50
- .handle()
51
- .pipe((0, rxjs_1.tap)({
52
- error: (err) => {
53
- const status = err?.status ?? 500;
54
- if (status >= 400) {
55
- void this.audit.recordError({
56
- statusCode: status,
57
- type: (0, classifyError_util_1.classifyError)(err, status),
58
- message: err?.message ?? "Erro desconhecido",
59
- stack: err?.stack ?? null,
60
- method,
61
- path: req.path,
62
- userId: user?.id ?? null,
63
- ipAddress,
64
- requestId,
65
- });
66
- }
67
- },
68
- }))
69
- .subscribe(subscriber);
86
+ next.handle().subscribe(subscriber);
70
87
  });
71
88
  });
72
89
  }
@@ -74,5 +91,7 @@ let AuditInterceptor = class AuditInterceptor {
74
91
  exports.AuditInterceptor = AuditInterceptor;
75
92
  exports.AuditInterceptor = AuditInterceptor = __decorate([
76
93
  (0, common_1.Injectable)(),
77
- __metadata("design:paramtypes", [audit_service_1.AuditService])
94
+ __metadata("design:paramtypes", [audit_service_1.AuditService,
95
+ env_service_1.EnvService,
96
+ core_1.Reflector])
78
97
  ], AuditInterceptor);
@@ -0,0 +1,3 @@
1
+ import { CustomDecorator } from "@nestjs/common";
2
+ export declare const AUDITABLE_KEY = "auditable";
3
+ export declare const Auditable: (action?: string) => CustomDecorator<string>;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Auditable = exports.AUDITABLE_KEY = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ exports.AUDITABLE_KEY = "auditable";
6
+ const Auditable = (action) => (0, common_1.SetMetadata)(exports.AUDITABLE_KEY, action ?? true);
7
+ exports.Auditable = Auditable;
@@ -1,4 +1,3 @@
1
1
  import { FilterCatalog } from "../../../../core/query/filterField.interface";
2
- export declare const AUDIT_CHANGES_FILTER_CATALOG: FilterCatalog;
3
- export declare const ERROR_LOGS_FILTER_CATALOG: FilterCatalog;
2
+ export declare const REQUEST_LOGS_FILTER_CATALOG: FilterCatalog;
4
3
  export declare const AUDIT_DATA_CHANGES_FILTER_CATALOG: FilterCatalog;