rl-core-api 0.3.0 → 0.5.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 +1 -1
- package/dist/core/auth/actor.interface.d.ts +4 -0
- package/dist/core/auth/actor.interface.js +2 -0
- package/dist/core/auth/permissionScope.util.d.ts +3 -0
- package/dist/core/auth/permissionScope.util.js +10 -0
- package/dist/core/config/env.schema.d.ts +3 -3
- package/dist/core/config/env.schema.js +3 -3
- package/dist/core/config/env.service.d.ts +1 -0
- package/dist/core/config/env.service.js +3 -0
- package/dist/core/context/auditContext.d.ts +1 -0
- package/dist/core/context/auditContext.js +8 -1
- package/dist/core/context/requestLog.context.d.ts +10 -0
- package/dist/core/context/requestLog.context.js +26 -0
- package/dist/core/database/migrations/1710000000000-InitialSchema.js +63 -36
- package/dist/core/database/migrations/{1786233600000-Notifications.d.ts → 1787270400000-GroupManager.d.ts} +1 -1
- package/dist/core/database/migrations/1787270400000-GroupManager.js +26 -0
- package/dist/core/database/migrations/index.js +2 -6
- package/dist/core/events/appEvent.enum.d.ts +19 -1
- package/dist/core/events/appEvent.enum.js +1 -0
- package/dist/core/filters/allExceptions.filter.d.ts +6 -0
- package/dist/core/filters/allExceptions.filter.js +47 -2
- package/dist/core/filters/appErrorCode.enum.d.ts +3 -1
- package/dist/core/filters/appErrorCode.enum.js +2 -0
- package/dist/core/query/parseFilter.util.js +6 -4
- package/dist/core/utils/ip.util.d.ts +1 -0
- package/dist/core/utils/ip.util.js +8 -0
- package/dist/core/websocket/baseGateway.d.ts +1 -0
- package/dist/core/websocket/baseGateway.js +3 -0
- package/dist/coreEntities.d.ts +2 -3
- package/dist/coreEntities.js +2 -4
- package/dist/features/audit/audit.module.js +5 -7
- package/dist/features/audit/domain/audit.service.d.ts +14 -17
- package/dist/features/audit/domain/audit.service.js +22 -35
- package/dist/features/audit/domain/classifyError.util.d.ts +1 -1
- package/dist/features/audit/domain/classifyError.util.js +8 -8
- package/dist/features/audit/domain/enums/errorType.enum.d.ts +9 -0
- package/dist/features/audit/domain/enums/errorType.enum.js +13 -0
- package/dist/features/audit/domain/enums/requestOutcome.enum.d.ts +5 -0
- package/dist/features/audit/domain/enums/requestOutcome.enum.js +9 -0
- package/dist/features/audit/domain/index.d.ts +2 -0
- package/dist/features/audit/domain/index.js +2 -0
- package/dist/features/audit/infra/auditData.subscriber.js +21 -12
- package/dist/features/audit/infra/index.d.ts +2 -4
- package/dist/features/audit/infra/index.js +2 -4
- package/dist/features/audit/infra/repositories/requestLog.repository.d.ts +7 -0
- package/dist/features/audit/infra/repositories/{auditChange.repository.js → requestLog.repository.js} +10 -10
- package/dist/features/audit/infra/schema/auditDataChange.schema.d.ts +3 -3
- package/dist/features/audit/infra/schema/auditDataChange.schema.js +8 -7
- package/dist/features/audit/infra/schema/requestLog.schema.d.ts +20 -0
- package/dist/features/audit/infra/schema/requestLog.schema.js +92 -0
- package/dist/features/audit/presentation/audit.controller.d.ts +4 -8
- package/dist/features/audit/presentation/audit.controller.js +8 -31
- package/dist/features/audit/presentation/audit.interceptor.d.ts +5 -1
- package/dist/features/audit/presentation/audit.interceptor.js +53 -28
- package/dist/features/audit/presentation/decorators/auditable.decorator.d.ts +10 -0
- package/dist/features/audit/presentation/decorators/auditable.decorator.js +10 -0
- package/dist/features/audit/presentation/filters/audit.filters.d.ts +1 -2
- package/dist/features/audit/presentation/filters/audit.filters.js +65 -49
- package/dist/features/audit/presentation/httpError.listener.d.ts +8 -0
- package/dist/features/audit/presentation/httpError.listener.js +61 -0
- package/dist/features/audit/presentation/index.d.ts +3 -0
- package/dist/features/audit/presentation/index.js +3 -0
- package/dist/features/audit/presentation/responses/auditDataChange.response.js +1 -1
- package/dist/features/audit/presentation/responses/log.response.d.ts +12 -27
- package/dist/features/audit/presentation/responses/log.response.js +66 -88
- package/dist/features/audit/presentation/userRolesChanged.listener.d.ts +7 -0
- package/dist/features/audit/presentation/userRolesChanged.listener.js +43 -0
- package/dist/features/auth/domain/auth.service.d.ts +7 -4
- package/dist/features/auth/domain/auth.service.js +22 -4
- package/dist/features/auth/domain/twoFactor.service.d.ts +2 -0
- package/dist/features/auth/domain/twoFactor.service.js +7 -2
- package/dist/features/auth/infra/schema/authToken.schema.d.ts +5 -5
- package/dist/features/auth/infra/schema/authToken.schema.js +7 -7
- package/dist/features/auth/presentation/auth.controller.d.ts +2 -5
- package/dist/features/auth/presentation/auth.controller.js +11 -0
- package/dist/features/maintenance/domain/cleanup.service.d.ts +1 -4
- package/dist/features/maintenance/domain/cleanup.service.js +1 -26
- package/dist/features/maintenance/maintenance.module.js +1 -2
- package/dist/features/notifications/domain/enums/channelType.enum.d.ts +5 -5
- package/dist/features/notifications/domain/enums/channelType.enum.js +5 -5
- package/dist/features/notifications/domain/enums/deliveryStatus.enum.d.ts +6 -6
- package/dist/features/notifications/domain/enums/deliveryStatus.enum.js +6 -6
- package/dist/features/notifications/domain/enums/notificationType.enum.d.ts +4 -4
- package/dist/features/notifications/domain/enums/notificationType.enum.js +4 -4
- package/dist/features/notifications/domain/enums/scopeType.enum.d.ts +3 -3
- package/dist/features/notifications/domain/enums/scopeType.enum.js +3 -3
- package/dist/features/notifications/infra/schema/notification.schema.js +2 -2
- package/dist/features/notifications/infra/schema/notificationScope.schema.js +2 -2
- package/dist/features/notifications/presentation/commands/createNotification.command.js +2 -2
- package/dist/features/notifications/presentation/domainEvents.listener.d.ts +5 -2
- package/dist/features/notifications/presentation/domainEvents.listener.js +24 -2
- package/dist/features/notifications/presentation/responses/notification.response.js +1 -1
- package/dist/features/rbac/domain/rbac.catalog.js +31 -2
- package/dist/features/rbac/domain/rbac.service.d.ts +1 -0
- package/dist/features/rbac/domain/rbac.service.js +14 -0
- package/dist/features/rbac/domain/teamScope.service.d.ts +15 -0
- package/dist/features/rbac/domain/teamScope.service.js +74 -0
- package/dist/features/rbac/infra/repositories/group.repository.d.ts +2 -0
- package/dist/features/rbac/infra/repositories/group.repository.js +26 -0
- package/dist/features/rbac/infra/schema/group.schema.d.ts +1 -0
- package/dist/features/rbac/infra/schema/group.schema.js +5 -0
- package/dist/features/rbac/presentation/commands/createGroup.command.d.ts +1 -0
- package/dist/features/rbac/presentation/commands/createGroup.command.js +7 -0
- package/dist/features/rbac/presentation/rbac.controller.d.ts +1 -0
- package/dist/features/rbac/presentation/rbac.controller.js +16 -0
- package/dist/features/rbac/presentation/responses/rbac.response.d.ts +1 -0
- package/dist/features/rbac/presentation/responses/rbac.response.js +4 -0
- package/dist/features/rbac/rbac.module.js +3 -0
- package/dist/features/users/domain/users.service.d.ts +16 -8
- package/dist/features/users/domain/users.service.js +72 -14
- package/dist/features/users/infra/repositories/user.repository.d.ts +1 -1
- package/dist/features/users/infra/repositories/user.repository.js +9 -1
- package/dist/features/users/presentation/commands/createUser.command.d.ts +1 -0
- package/dist/features/users/presentation/commands/createUser.command.js +8 -0
- package/dist/features/users/presentation/filters/users.filters.js +8 -0
- package/dist/features/users/presentation/users.controller.d.ts +5 -5
- package/dist/features/users/presentation/users.controller.js +38 -27
- package/dist/features/users/users.module.js +2 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +14 -6
- package/package.json +1 -1
- package/dist/core/database/migrations/1786060800000-FirstAccessTokenType.d.ts +0 -6
- package/dist/core/database/migrations/1786060800000-FirstAccessTokenType.js +0 -19
- package/dist/core/database/migrations/1786147200000-PermanentAccountLock.d.ts +0 -6
- package/dist/core/database/migrations/1786147200000-PermanentAccountLock.js +0 -15
- package/dist/core/database/migrations/1786233600000-Notifications.js +0 -59
- package/dist/features/audit/infra/repositories/auditChange.repository.d.ts +0 -7
- package/dist/features/audit/infra/repositories/errorLog.repository.d.ts +0 -7
- package/dist/features/audit/infra/repositories/errorLog.repository.js +0 -35
- package/dist/features/audit/infra/schema/auditChange.schema.d.ts +0 -14
- package/dist/features/audit/infra/schema/auditChange.schema.js +0 -68
- package/dist/features/audit/infra/schema/errorLog.schema.d.ts +0 -21
- package/dist/features/audit/infra/schema/errorLog.schema.js +0 -69
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ migrations do core vêm no pacote — você nunca copia nem reescreve nenhuma.
|
|
|
58
58
|
|---|---|
|
|
59
59
|
| **Auth** | login, refresh por cookie httpOnly, 2FA obrigatório (TOTP + fallback por e-mail + códigos de backup), primeiro acesso, reset de senha, bloqueio por tentativas, expiração de senha |
|
|
60
60
|
| **RBAC** | resources, actions, scopes, permissions, roles e groups, com guard por `resource:action:scope` |
|
|
61
|
-
| **Auditoria** | trilha de alterações de dados, log de requisições e log de erros,
|
|
61
|
+
| **Auditoria** | trilha de alterações de dados, log de requisições e log de erros, mantidos indefinidamente (sem retenção automática) |
|
|
62
62
|
| **Notificações** | WebSocket com handshake por cookie ou Bearer, escopo resolvido na leitura |
|
|
63
63
|
| **Listagens** | paginação, ordenação e filtro dinâmico com catálogo por listagem (`$AND`/`$OR` aninhados, 17 operadores) |
|
|
64
64
|
| **Infra** | config validada com Zod, mailer, agendador, rate-limit, CSRF, filtro global de exceções, logger Winston |
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.anyOrTeam = exports.SCOPE_TEAM = exports.SCOPE_ANY = void 0;
|
|
4
|
+
exports.SCOPE_ANY = "any";
|
|
5
|
+
exports.SCOPE_TEAM = "team";
|
|
6
|
+
const anyOrTeam = (action) => [
|
|
7
|
+
`${action}:${exports.SCOPE_ANY}`,
|
|
8
|
+
`${action}:${exports.SCOPE_TEAM}`,
|
|
9
|
+
];
|
|
10
|
+
exports.anyOrTeam = anyOrTeam;
|
|
@@ -28,6 +28,7 @@ export declare const envSchema: z.ZodObject<{
|
|
|
28
28
|
JWT_ACCESS_SECRET: z.ZodString;
|
|
29
29
|
JWT_PENDING_SECRET: z.ZodString;
|
|
30
30
|
JWT_ACCESS_EXPIRES: z.ZodDefault<z.ZodString>;
|
|
31
|
+
JWT_PENDING_EXPIRES: z.ZodDefault<z.ZodString>;
|
|
31
32
|
JWT_REFRESH_EXPIRES_MINUTES: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
32
33
|
TOTP_ENC_KEY: z.ZodString;
|
|
33
34
|
COOKIE_SECURE: z.ZodDefault<z.ZodPipe<z.ZodEnum<{
|
|
@@ -57,9 +58,8 @@ export declare const envSchema: z.ZodObject<{
|
|
|
57
58
|
FIRST_ACCESS_TOKEN_EXPIRY: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
58
59
|
PASSWORD_MAX_AGE_DAYS: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
59
60
|
TOKEN_CLEANUP_CRON: z.ZodDefault<z.ZodString>;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
AUDIT_DATA_RETENTION_DAYS: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
61
|
+
AUDIT_SLOW_REQUEST_MS: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
62
|
+
AUDIT_IP_SALT: z.ZodOptional<z.ZodString>;
|
|
63
63
|
NOTIFICATION_RETENTION_DAYS: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
64
64
|
SEED_ADMIN_NAME: z.ZodDefault<z.ZodString>;
|
|
65
65
|
SEED_ADMIN_EMAIL: z.ZodDefault<z.ZodString>;
|
|
@@ -31,6 +31,7 @@ exports.envSchema = zod_1.z
|
|
|
31
31
|
JWT_ACCESS_SECRET: zod_1.z.string().min(32),
|
|
32
32
|
JWT_PENDING_SECRET: zod_1.z.string().min(32),
|
|
33
33
|
JWT_ACCESS_EXPIRES: zod_1.z.string().default("4h"),
|
|
34
|
+
JWT_PENDING_EXPIRES: zod_1.z.string().default("15m"),
|
|
34
35
|
JWT_REFRESH_EXPIRES_MINUTES: zod_1.z.coerce
|
|
35
36
|
.number()
|
|
36
37
|
.int()
|
|
@@ -68,9 +69,8 @@ exports.envSchema = zod_1.z
|
|
|
68
69
|
.default(1440),
|
|
69
70
|
PASSWORD_MAX_AGE_DAYS: zod_1.z.coerce.number().int().positive().default(90),
|
|
70
71
|
TOKEN_CLEANUP_CRON: zod_1.z.string().default("0 */6 * * *"),
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
AUDIT_DATA_RETENTION_DAYS: zod_1.z.coerce.number().int().positive().default(30),
|
|
72
|
+
AUDIT_SLOW_REQUEST_MS: zod_1.z.coerce.number().int().positive().default(1000),
|
|
73
|
+
AUDIT_IP_SALT: zod_1.z.string().optional(),
|
|
74
74
|
NOTIFICATION_RETENTION_DAYS: zod_1.z.coerce
|
|
75
75
|
.number()
|
|
76
76
|
.int()
|
|
@@ -19,6 +19,9 @@ let EnvService = class EnvService {
|
|
|
19
19
|
get(key) {
|
|
20
20
|
return this.config.get(key, { infer: true });
|
|
21
21
|
}
|
|
22
|
+
auditIpSalt() {
|
|
23
|
+
return this.get("AUDIT_IP_SALT") ?? this.get("JWT_ACCESS_SECRET");
|
|
24
|
+
}
|
|
22
25
|
brand() {
|
|
23
26
|
const name = this.get("APP_NAME");
|
|
24
27
|
return {
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.auditContext = void 0;
|
|
3
|
+
exports.setAuditUser = exports.auditContext = void 0;
|
|
4
4
|
const node_async_hooks_1 = require("node:async_hooks");
|
|
5
5
|
exports.auditContext = new node_async_hooks_1.AsyncLocalStorage();
|
|
6
|
+
const setAuditUser = (userId) => {
|
|
7
|
+
const store = exports.auditContext.getStore();
|
|
8
|
+
if (store) {
|
|
9
|
+
store.userId = userId;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
exports.setAuditUser = setAuditUser;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Request } from "express";
|
|
2
|
+
export interface RequestLogContext {
|
|
3
|
+
action: string | null;
|
|
4
|
+
startedAt: number;
|
|
5
|
+
userId: string | null;
|
|
6
|
+
}
|
|
7
|
+
export declare const routePathOf: (request: Request) => string | null;
|
|
8
|
+
export declare const setRequestLogContext: (request: Request, context: RequestLogContext) => void;
|
|
9
|
+
export declare const getRequestLogContext: (request: Request) => RequestLogContext | null;
|
|
10
|
+
export declare const setRequestLogUser: (request: Request, userId: string | null) => void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setRequestLogUser = exports.getRequestLogContext = exports.setRequestLogContext = exports.routePathOf = void 0;
|
|
4
|
+
const KEY = "__requestLogContext";
|
|
5
|
+
const routePathOf = (request) => {
|
|
6
|
+
const route = request.route;
|
|
7
|
+
if (route && typeof route === "object" && "path" in route) {
|
|
8
|
+
const path = route.path;
|
|
9
|
+
return typeof path === "string" ? path : null;
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
};
|
|
13
|
+
exports.routePathOf = routePathOf;
|
|
14
|
+
const setRequestLogContext = (request, context) => {
|
|
15
|
+
request[KEY] = context;
|
|
16
|
+
};
|
|
17
|
+
exports.setRequestLogContext = setRequestLogContext;
|
|
18
|
+
const getRequestLogContext = (request) => request[KEY] ?? null;
|
|
19
|
+
exports.getRequestLogContext = getRequestLogContext;
|
|
20
|
+
const setRequestLogUser = (request, userId) => {
|
|
21
|
+
const context = (0, exports.getRequestLogContext)(request);
|
|
22
|
+
if (context) {
|
|
23
|
+
context.userId = userId;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.setRequestLogUser = setRequestLogUser;
|
|
@@ -26,7 +26,6 @@ class InitialSchema1710000000000 {
|
|
|
26
26
|
two_factor_confirmed_at datetime NULL,
|
|
27
27
|
backup_codes json NULL,
|
|
28
28
|
failed_login_attempts int NOT NULL DEFAULT 0,
|
|
29
|
-
locked_until datetime NULL,
|
|
30
29
|
password_changed_at datetime NULL,
|
|
31
30
|
must_change_password tinyint NOT NULL DEFAULT 0,
|
|
32
31
|
${ts},
|
|
@@ -49,7 +48,7 @@ class InitialSchema1710000000000 {
|
|
|
49
48
|
id char(36) NOT NULL,
|
|
50
49
|
user_id char(36) NOT NULL,
|
|
51
50
|
token_hash varchar(255) NOT NULL,
|
|
52
|
-
type
|
|
51
|
+
type tinyint unsigned NOT NULL,
|
|
53
52
|
family char(36) NULL,
|
|
54
53
|
expires_at datetime NOT NULL,
|
|
55
54
|
used tinyint NOT NULL DEFAULT 0,
|
|
@@ -192,44 +191,31 @@ class InitialSchema1710000000000 {
|
|
|
192
191
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
193
192
|
`);
|
|
194
193
|
await queryRunner.query(`
|
|
195
|
-
CREATE TABLE
|
|
194
|
+
CREATE TABLE request_logs (
|
|
196
195
|
id char(36) NOT NULL,
|
|
197
|
-
|
|
198
|
-
action varchar(100)
|
|
199
|
-
entity varchar(100) NULL,
|
|
200
|
-
entity_id varchar(36) NULL,
|
|
196
|
+
outcome tinyint unsigned NOT NULL,
|
|
197
|
+
action varchar(100) NULL,
|
|
201
198
|
method varchar(10) NULL,
|
|
202
199
|
path varchar(255) NULL,
|
|
203
|
-
|
|
204
|
-
metadata json NULL,
|
|
200
|
+
route varchar(255) NULL,
|
|
205
201
|
status_code int NULL,
|
|
206
202
|
duration_ms int NULL,
|
|
207
|
-
request_id char(36) NULL,
|
|
208
|
-
${ts},
|
|
209
|
-
PRIMARY KEY (id),
|
|
210
|
-
KEY IDX_audit_changes_user (user_id),
|
|
211
|
-
KEY IDX_audit_changes_entity (entity),
|
|
212
|
-
KEY IDX_audit_changes_request_id (request_id),
|
|
213
|
-
KEY IDX_audit_changes_status_code (status_code)
|
|
214
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
215
|
-
`);
|
|
216
|
-
await queryRunner.query(`
|
|
217
|
-
CREATE TABLE error_logs (
|
|
218
|
-
id char(36) NOT NULL,
|
|
219
|
-
status_code int NULL,
|
|
220
|
-
message varchar(255) NOT NULL,
|
|
221
|
-
stack text NULL,
|
|
222
|
-
method varchar(10) NULL,
|
|
223
|
-
path varchar(255) NULL,
|
|
224
203
|
user_id char(36) NULL,
|
|
225
|
-
|
|
226
|
-
|
|
204
|
+
ip_hash char(64) NULL,
|
|
205
|
+
user_agent varchar(255) NULL,
|
|
227
206
|
request_id char(36) NULL,
|
|
207
|
+
error_type tinyint unsigned NULL,
|
|
208
|
+
error_code varchar(100) NULL,
|
|
209
|
+
error_message varchar(255) NULL,
|
|
210
|
+
error_stack text NULL,
|
|
228
211
|
${ts},
|
|
229
212
|
PRIMARY KEY (id),
|
|
230
|
-
KEY
|
|
231
|
-
KEY
|
|
232
|
-
KEY
|
|
213
|
+
KEY IDX_request_logs_created_at (created_at),
|
|
214
|
+
KEY IDX_request_logs_outcome (outcome, created_at),
|
|
215
|
+
KEY IDX_request_logs_status (status_code, created_at),
|
|
216
|
+
KEY IDX_request_logs_user (user_id, created_at),
|
|
217
|
+
KEY IDX_request_logs_route (route, created_at),
|
|
218
|
+
KEY IDX_request_logs_request_id (request_id)
|
|
233
219
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
234
220
|
`);
|
|
235
221
|
await queryRunner.query(`
|
|
@@ -237,22 +223,63 @@ class InitialSchema1710000000000 {
|
|
|
237
223
|
id char(36) NOT NULL,
|
|
238
224
|
entity varchar(100) NOT NULL,
|
|
239
225
|
entity_id varchar(36) NULL,
|
|
240
|
-
action
|
|
226
|
+
action tinyint unsigned NOT NULL,
|
|
241
227
|
old_data json NULL,
|
|
242
228
|
new_data json NULL,
|
|
243
229
|
user_id char(36) NULL,
|
|
244
230
|
ip_address varchar(45) NULL,
|
|
245
231
|
${ts},
|
|
246
232
|
PRIMARY KEY (id),
|
|
247
|
-
KEY
|
|
248
|
-
KEY
|
|
233
|
+
KEY IDX_audit_data_changes_created_at (created_at),
|
|
234
|
+
KEY IDX_audit_data_changes_entity (entity, entity_id, created_at),
|
|
235
|
+
KEY IDX_audit_data_changes_user (user_id, created_at)
|
|
236
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
237
|
+
`);
|
|
238
|
+
await queryRunner.query(`
|
|
239
|
+
CREATE TABLE notifications (
|
|
240
|
+
id char(36) NOT NULL,
|
|
241
|
+
title varchar(255) NOT NULL,
|
|
242
|
+
body text NOT NULL,
|
|
243
|
+
payload json NULL,
|
|
244
|
+
type tinyint unsigned NOT NULL,
|
|
245
|
+
created_by char(36) NULL,
|
|
246
|
+
${ts},
|
|
247
|
+
PRIMARY KEY (id),
|
|
248
|
+
KEY IDX_notifications_created_at (created_at)
|
|
249
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
250
|
+
`);
|
|
251
|
+
await queryRunner.query(`
|
|
252
|
+
CREATE TABLE notification_scopes (
|
|
253
|
+
id char(36) NOT NULL,
|
|
254
|
+
notification_id char(36) NOT NULL,
|
|
255
|
+
scope_type tinyint unsigned NOT NULL,
|
|
256
|
+
scope_key varchar(100) NULL,
|
|
257
|
+
${ts},
|
|
258
|
+
PRIMARY KEY (id),
|
|
259
|
+
KEY IDX_notification_scopes_notification (notification_id),
|
|
260
|
+
KEY IDX_notification_scopes_target (scope_type, scope_key),
|
|
261
|
+
CONSTRAINT FK_notification_scopes_notification
|
|
262
|
+
FOREIGN KEY (notification_id) REFERENCES notifications (id) ON DELETE CASCADE
|
|
263
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
264
|
+
`);
|
|
265
|
+
await queryRunner.query(`
|
|
266
|
+
CREATE TABLE notification_reads (
|
|
267
|
+
notification_id char(36) NOT NULL,
|
|
268
|
+
user_id char(36) NOT NULL,
|
|
269
|
+
read_at datetime NOT NULL,
|
|
270
|
+
PRIMARY KEY (notification_id, user_id),
|
|
271
|
+
KEY IDX_notification_reads_user (user_id),
|
|
272
|
+
CONSTRAINT FK_notification_reads_notification
|
|
273
|
+
FOREIGN KEY (notification_id) REFERENCES notifications (id) ON DELETE CASCADE
|
|
249
274
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
250
275
|
`);
|
|
251
276
|
}
|
|
252
277
|
async down(queryRunner) {
|
|
278
|
+
await queryRunner.query("DROP TABLE IF EXISTS notification_reads;");
|
|
279
|
+
await queryRunner.query("DROP TABLE IF EXISTS notification_scopes;");
|
|
280
|
+
await queryRunner.query("DROP TABLE IF EXISTS notifications;");
|
|
253
281
|
await queryRunner.query("DROP TABLE IF EXISTS audit_data_changes;");
|
|
254
|
-
await queryRunner.query("DROP TABLE IF EXISTS
|
|
255
|
-
await queryRunner.query("DROP TABLE IF EXISTS audit_changes;");
|
|
282
|
+
await queryRunner.query("DROP TABLE IF EXISTS request_logs;");
|
|
256
283
|
await queryRunner.query("DROP TABLE IF EXISTS group_roles;");
|
|
257
284
|
await queryRunner.query("DROP TABLE IF EXISTS user_groups;");
|
|
258
285
|
await queryRunner.query("DROP TABLE IF EXISTS user_permissions;");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
-
export declare class
|
|
2
|
+
export declare class GroupManager1787270400000 implements MigrationInterface {
|
|
3
3
|
name: string;
|
|
4
4
|
up(queryRunner: QueryRunner): Promise<void>;
|
|
5
5
|
down(queryRunner: QueryRunner): Promise<void>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GroupManager1787270400000 = void 0;
|
|
4
|
+
class GroupManager1787270400000 {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = "GroupManager1787270400000";
|
|
7
|
+
}
|
|
8
|
+
async up(queryRunner) {
|
|
9
|
+
await queryRunner.query(`
|
|
10
|
+
ALTER TABLE \`groups\`
|
|
11
|
+
ADD COLUMN manager_id char(36) NULL AFTER parent_id,
|
|
12
|
+
ADD KEY IDX_groups_manager (manager_id),
|
|
13
|
+
ADD CONSTRAINT FK_groups_manager FOREIGN KEY (manager_id)
|
|
14
|
+
REFERENCES users (id) ON DELETE SET NULL;
|
|
15
|
+
`);
|
|
16
|
+
}
|
|
17
|
+
async down(queryRunner) {
|
|
18
|
+
await queryRunner.query(`
|
|
19
|
+
ALTER TABLE \`groups\`
|
|
20
|
+
DROP FOREIGN KEY FK_groups_manager,
|
|
21
|
+
DROP KEY IDX_groups_manager,
|
|
22
|
+
DROP COLUMN manager_id;
|
|
23
|
+
`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.GroupManager1787270400000 = GroupManager1787270400000;
|
|
@@ -2,12 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.coreMigrations = void 0;
|
|
4
4
|
const _1710000000000_InitialSchema_1 = require("./1710000000000-InitialSchema");
|
|
5
|
-
const
|
|
6
|
-
const _1786147200000_PermanentAccountLock_1 = require("./1786147200000-PermanentAccountLock");
|
|
7
|
-
const _1786233600000_Notifications_1 = require("./1786233600000-Notifications");
|
|
5
|
+
const _1787270400000_GroupManager_1 = require("./1787270400000-GroupManager");
|
|
8
6
|
exports.coreMigrations = [
|
|
9
7
|
_1710000000000_InitialSchema_1.InitialSchema1710000000000,
|
|
10
|
-
|
|
11
|
-
_1786147200000_PermanentAccountLock_1.PermanentAccountLock1786147200000,
|
|
12
|
-
_1786233600000_Notifications_1.Notifications1786233600000,
|
|
8
|
+
_1787270400000_GroupManager_1.GroupManager1787270400000,
|
|
13
9
|
];
|
|
@@ -4,7 +4,8 @@ export declare enum AppEvent {
|
|
|
4
4
|
USER_ROLES_CHANGED = "user.roles-changed",
|
|
5
5
|
USER_PASSWORD_RESET_REQUESTED = "user.password-reset-requested",
|
|
6
6
|
USER_PASSWORD_EXPIRING = "user.password-expiring",
|
|
7
|
-
SYSTEM_CLEANUP_FAILED = "system.cleanup-failed"
|
|
7
|
+
SYSTEM_CLEANUP_FAILED = "system.cleanup-failed",
|
|
8
|
+
HTTP_ERROR = "http.error"
|
|
8
9
|
}
|
|
9
10
|
export interface UserLockedEvent {
|
|
10
11
|
userId: string;
|
|
@@ -17,6 +18,7 @@ export interface UserTwoFactorResetEvent {
|
|
|
17
18
|
export interface UserRolesChangedEvent {
|
|
18
19
|
userId: string;
|
|
19
20
|
roleNames: string[];
|
|
21
|
+
previousRoleNames: string[];
|
|
20
22
|
}
|
|
21
23
|
export interface UserPasswordResetRequestedEvent {
|
|
22
24
|
userId: string;
|
|
@@ -29,3 +31,19 @@ export interface SystemCleanupFailedEvent {
|
|
|
29
31
|
routine: string;
|
|
30
32
|
reason: string;
|
|
31
33
|
}
|
|
34
|
+
export interface HttpErrorEvent {
|
|
35
|
+
statusCode: number;
|
|
36
|
+
errorCode: string | null;
|
|
37
|
+
errorName: string | null;
|
|
38
|
+
message: string;
|
|
39
|
+
stack?: string | null;
|
|
40
|
+
method: string;
|
|
41
|
+
path: string;
|
|
42
|
+
route?: string | null;
|
|
43
|
+
action?: string | null;
|
|
44
|
+
durationMs?: number | null;
|
|
45
|
+
userId?: string | null;
|
|
46
|
+
ipHash?: string | null;
|
|
47
|
+
userAgent?: string | null;
|
|
48
|
+
requestId?: string | null;
|
|
49
|
+
}
|
|
@@ -9,4 +9,5 @@ var AppEvent;
|
|
|
9
9
|
AppEvent["USER_PASSWORD_RESET_REQUESTED"] = "user.password-reset-requested";
|
|
10
10
|
AppEvent["USER_PASSWORD_EXPIRING"] = "user.password-expiring";
|
|
11
11
|
AppEvent["SYSTEM_CLEANUP_FAILED"] = "system.cleanup-failed";
|
|
12
|
+
AppEvent["HTTP_ERROR"] = "http.error";
|
|
12
13
|
})(AppEvent || (exports.AppEvent = AppEvent = {}));
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ArgumentsHost, ExceptionFilter } from "@nestjs/common";
|
|
2
|
+
import { EventEmitter2 } from "@nestjs/event-emitter";
|
|
3
|
+
import { EnvService } from "../config/env.service";
|
|
2
4
|
export declare class AllExceptionsFilter implements ExceptionFilter {
|
|
5
|
+
private readonly events;
|
|
6
|
+
private readonly env;
|
|
3
7
|
private readonly logger;
|
|
8
|
+
constructor(events: EventEmitter2, env: EnvService);
|
|
4
9
|
catch(exception: unknown, host: ArgumentsHost): void;
|
|
10
|
+
private publish;
|
|
5
11
|
}
|
|
@@ -5,11 +5,21 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
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
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
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
|
+
};
|
|
8
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
12
|
exports.AllExceptionsFilter = void 0;
|
|
10
13
|
const common_1 = require("@nestjs/common");
|
|
14
|
+
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
15
|
+
const env_service_1 = require("../config/env.service");
|
|
16
|
+
const requestLog_context_1 = require("../context/requestLog.context");
|
|
17
|
+
const appEvent_enum_1 = require("../events/appEvent.enum");
|
|
18
|
+
const ip_util_1 = require("../utils/ip.util");
|
|
11
19
|
let AllExceptionsFilter = class AllExceptionsFilter {
|
|
12
|
-
constructor() {
|
|
20
|
+
constructor(events, env) {
|
|
21
|
+
this.events = events;
|
|
22
|
+
this.env = env;
|
|
13
23
|
this.logger = new common_1.Logger("Exception");
|
|
14
24
|
}
|
|
15
25
|
catch(exception, host) {
|
|
@@ -44,6 +54,12 @@ let AllExceptionsFilter = class AllExceptionsFilter {
|
|
|
44
54
|
this.logger.error(`[${requestId}] ${exception.message}`, exception.stack);
|
|
45
55
|
}
|
|
46
56
|
}
|
|
57
|
+
this.publish(exception, request, {
|
|
58
|
+
statusCode: status,
|
|
59
|
+
errorCode,
|
|
60
|
+
message,
|
|
61
|
+
requestId,
|
|
62
|
+
});
|
|
47
63
|
response.status(status).json({
|
|
48
64
|
statusCode: status,
|
|
49
65
|
message,
|
|
@@ -54,8 +70,37 @@ let AllExceptionsFilter = class AllExceptionsFilter {
|
|
|
54
70
|
requestId,
|
|
55
71
|
});
|
|
56
72
|
}
|
|
73
|
+
publish(exception, request, data) {
|
|
74
|
+
try {
|
|
75
|
+
const user = request.user;
|
|
76
|
+
const logContext = (0, requestLog_context_1.getRequestLogContext)(request);
|
|
77
|
+
this.events.emit(appEvent_enum_1.AppEvent.HTTP_ERROR, {
|
|
78
|
+
statusCode: data.statusCode,
|
|
79
|
+
errorCode: data.errorCode,
|
|
80
|
+
errorName: exception?.name ?? null,
|
|
81
|
+
message: typeof data.message === "string"
|
|
82
|
+
? data.message
|
|
83
|
+
: JSON.stringify(data.message),
|
|
84
|
+
stack: exception instanceof Error ? exception.stack : null,
|
|
85
|
+
method: request.method,
|
|
86
|
+
path: request.path,
|
|
87
|
+
route: (0, requestLog_context_1.routePathOf)(request),
|
|
88
|
+
action: logContext?.action ?? null,
|
|
89
|
+
durationMs: logContext ? Date.now() - logContext.startedAt : null,
|
|
90
|
+
userId: logContext?.userId ?? user?.id ?? null,
|
|
91
|
+
ipHash: (0, ip_util_1.hashIp)((0, ip_util_1.normalizeIp)(request.ip), this.env.auditIpSalt()) ?? null,
|
|
92
|
+
userAgent: request.headers["user-agent"] ?? null,
|
|
93
|
+
requestId: data.requestId,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
this.logger.warn(`Falha ao publicar ${appEvent_enum_1.AppEvent.HTTP_ERROR}: ${err.message}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
57
100
|
};
|
|
58
101
|
exports.AllExceptionsFilter = AllExceptionsFilter;
|
|
59
102
|
exports.AllExceptionsFilter = AllExceptionsFilter = __decorate([
|
|
60
|
-
(0, common_1.Catch)()
|
|
103
|
+
(0, common_1.Catch)(),
|
|
104
|
+
__metadata("design:paramtypes", [event_emitter_1.EventEmitter2,
|
|
105
|
+
env_service_1.EnvService])
|
|
61
106
|
], AllExceptionsFilter);
|
|
@@ -3,7 +3,9 @@ export declare enum AppErrorCode {
|
|
|
3
3
|
ACCOUNT_INACTIVE = "ACCOUNT_INACTIVE",
|
|
4
4
|
INVALID_CREDENTIALS = "INVALID_CREDENTIALS",
|
|
5
5
|
INVALID_TWO_FACTOR_CODE = "INVALID_TWO_FACTOR_CODE",
|
|
6
|
+
PENDING_TOKEN_EXPIRED = "PENDING_TOKEN_EXPIRED",
|
|
6
7
|
PASSWORD_REUSED = "PASSWORD_REUSED",
|
|
7
8
|
TOO_MANY_REQUESTS = "TOO_MANY_REQUESTS",
|
|
8
|
-
INVALID_FILTER = "INVALID_FILTER"
|
|
9
|
+
INVALID_FILTER = "INVALID_FILTER",
|
|
10
|
+
GROUP_REQUIRED = "GROUP_REQUIRED"
|
|
9
11
|
}
|
|
@@ -7,7 +7,9 @@ var AppErrorCode;
|
|
|
7
7
|
AppErrorCode["ACCOUNT_INACTIVE"] = "ACCOUNT_INACTIVE";
|
|
8
8
|
AppErrorCode["INVALID_CREDENTIALS"] = "INVALID_CREDENTIALS";
|
|
9
9
|
AppErrorCode["INVALID_TWO_FACTOR_CODE"] = "INVALID_TWO_FACTOR_CODE";
|
|
10
|
+
AppErrorCode["PENDING_TOKEN_EXPIRED"] = "PENDING_TOKEN_EXPIRED";
|
|
10
11
|
AppErrorCode["PASSWORD_REUSED"] = "PASSWORD_REUSED";
|
|
11
12
|
AppErrorCode["TOO_MANY_REQUESTS"] = "TOO_MANY_REQUESTS";
|
|
12
13
|
AppErrorCode["INVALID_FILTER"] = "INVALID_FILTER";
|
|
14
|
+
AppErrorCode["GROUP_REQUIRED"] = "GROUP_REQUIRED";
|
|
13
15
|
})(AppErrorCode || (exports.AppErrorCode = AppErrorCode = {}));
|
|
@@ -8,6 +8,7 @@ const filterOperator_enum_1 = require("./filterOperator.enum");
|
|
|
8
8
|
const codedError_util_1 = require("../utils/codedError.util");
|
|
9
9
|
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10
10
|
const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
11
|
+
const NUMERIC_ENUM_VALUE = /^\d+$/;
|
|
11
12
|
const NULLABILITY_OPERATORS = [
|
|
12
13
|
filterOperator_enum_1.FilterOperator.Is,
|
|
13
14
|
filterOperator_enum_1.FilterOperator.Not,
|
|
@@ -197,14 +198,15 @@ const coerceScalar = (definition, value, upperBound = false) => {
|
|
|
197
198
|
return date;
|
|
198
199
|
}
|
|
199
200
|
case filterFieldType_enum_1.FilterFieldType.Enum: {
|
|
200
|
-
if (typeof value !== "string") {
|
|
201
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
|
201
202
|
throw invalid(`"${field}" espera um dos valores da lista`);
|
|
202
203
|
}
|
|
204
|
+
const raw = String(value);
|
|
203
205
|
const options = definition.options ?? [];
|
|
204
|
-
if (!options.some((option) => option.value ===
|
|
205
|
-
throw invalid(`"${
|
|
206
|
+
if (!options.some((option) => option.value === raw)) {
|
|
207
|
+
throw invalid(`"${raw}" não é um valor válido para "${field}"`);
|
|
206
208
|
}
|
|
207
|
-
return
|
|
209
|
+
return NUMERIC_ENUM_VALUE.test(raw) ? Number(raw) : raw;
|
|
208
210
|
}
|
|
209
211
|
case filterFieldType_enum_1.FilterFieldType.Select:
|
|
210
212
|
if (typeof value !== "string" || value === "") {
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hashIp = hashIp;
|
|
3
4
|
exports.normalizeIp = normalizeIp;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
function hashIp(ip, secret) {
|
|
7
|
+
if (!ip) {
|
|
8
|
+
return ip;
|
|
9
|
+
}
|
|
10
|
+
return (0, node_crypto_1.createHmac)("sha256", secret).update(ip).digest("hex");
|
|
11
|
+
}
|
|
4
12
|
function normalizeIp(ip) {
|
|
5
13
|
if (!ip) {
|
|
6
14
|
return ip;
|
|
@@ -16,6 +16,7 @@ export declare abstract class BaseGateway implements OnGatewayConnection, OnGate
|
|
|
16
16
|
constructor(wsAuth: WsAuthService, env: EnvService);
|
|
17
17
|
handleConnection(socket: Socket): Promise<void>;
|
|
18
18
|
handleDisconnect(socket: Socket): void;
|
|
19
|
+
requestSessionRefresh(userId: string): void;
|
|
19
20
|
protected emitTo<T>(rooms: string[], event: string, data: T): void;
|
|
20
21
|
private scheduleExpiry;
|
|
21
22
|
}
|
|
@@ -40,6 +40,9 @@ class BaseGateway {
|
|
|
40
40
|
}
|
|
41
41
|
socket.removeAllListeners();
|
|
42
42
|
}
|
|
43
|
+
requestSessionRefresh(userId) {
|
|
44
|
+
this.emitTo([(0, socket_constants_1.userRoom)(userId)], socket_constants_1.SESSION_REFRESH_EVENT, { userId });
|
|
45
|
+
}
|
|
43
46
|
emitTo(rooms, event, data) {
|
|
44
47
|
const targets = rooms.filter((room) => room.length > 0);
|
|
45
48
|
if (targets.length === 0) {
|
package/dist/coreEntities.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { AuditChange } from "./features/audit/infra/schema/auditChange.schema";
|
|
2
1
|
import { AuditDataChange } from "./features/audit/infra/schema/auditDataChange.schema";
|
|
3
|
-
import {
|
|
2
|
+
import { RequestLog } from "./features/audit/infra/schema/requestLog.schema";
|
|
4
3
|
import { AuthToken } from "./features/auth/infra/schema/authToken.schema";
|
|
5
4
|
import { Notification } from "./features/notifications/infra/schema/notification.schema";
|
|
6
5
|
import { NotificationRead } from "./features/notifications/infra/schema/notificationRead.schema";
|
|
@@ -9,4 +8,4 @@ import { Action } from "./features/rbac/infra/schema/action.schema";
|
|
|
9
8
|
import { Permission } from "./features/rbac/infra/schema/permission.schema";
|
|
10
9
|
import { PasswordHistory } from "./features/users/infra/schema/passwordHistory.schema";
|
|
11
10
|
import { User } from "./features/users/infra/schema/user.schema";
|
|
12
|
-
export declare const coreEntities: (typeof
|
|
11
|
+
export declare const coreEntities: (typeof AuditDataChange | typeof RequestLog | typeof AuthToken | typeof NotificationRead | typeof Notification | typeof NotificationScope | typeof Action | typeof Permission | typeof PasswordHistory | typeof User)[];
|
package/dist/coreEntities.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.coreEntities = void 0;
|
|
4
|
-
const auditChange_schema_1 = require("./features/audit/infra/schema/auditChange.schema");
|
|
5
4
|
const auditDataChange_schema_1 = require("./features/audit/infra/schema/auditDataChange.schema");
|
|
6
|
-
const
|
|
5
|
+
const requestLog_schema_1 = require("./features/audit/infra/schema/requestLog.schema");
|
|
7
6
|
const authToken_schema_1 = require("./features/auth/infra/schema/authToken.schema");
|
|
8
7
|
const notification_schema_1 = require("./features/notifications/infra/schema/notification.schema");
|
|
9
8
|
const notificationRead_schema_1 = require("./features/notifications/infra/schema/notificationRead.schema");
|
|
@@ -26,8 +25,7 @@ exports.coreEntities = [
|
|
|
26
25
|
permission_schema_1.Permission,
|
|
27
26
|
role_schema_1.Role,
|
|
28
27
|
group_schema_1.Group,
|
|
29
|
-
|
|
30
|
-
errorLog_schema_1.ErrorLog,
|
|
28
|
+
requestLog_schema_1.RequestLog,
|
|
31
29
|
auditDataChange_schema_1.AuditDataChange,
|
|
32
30
|
notification_schema_1.Notification,
|
|
33
31
|
notificationScope_schema_1.NotificationScope,
|
|
@@ -20,22 +20,20 @@ let AuditModule = class AuditModule {
|
|
|
20
20
|
exports.AuditModule = AuditModule;
|
|
21
21
|
exports.AuditModule = AuditModule = __decorate([
|
|
22
22
|
(0, common_1.Module)({
|
|
23
|
-
imports: [
|
|
24
|
-
typeorm_1.TypeOrmModule.forFeature([infra_1.AuditChange, infra_1.ErrorLog, infra_1.AuditDataChange, user_schema_1.User]),
|
|
25
|
-
],
|
|
23
|
+
imports: [typeorm_1.TypeOrmModule.forFeature([infra_1.RequestLog, infra_1.AuditDataChange, user_schema_1.User])],
|
|
26
24
|
controllers: [presentation_1.AuditController],
|
|
27
25
|
providers: [
|
|
28
|
-
infra_1.
|
|
29
|
-
infra_1.ErrorLogRepository,
|
|
26
|
+
infra_1.RequestLogRepository,
|
|
30
27
|
infra_1.AuditDataChangeRepository,
|
|
31
28
|
user_repository_1.UserRepository,
|
|
32
29
|
domain_1.AuditService,
|
|
33
30
|
{ provide: core_1.APP_INTERCEPTOR, useClass: presentation_1.AuditInterceptor },
|
|
31
|
+
presentation_1.HttpErrorListener,
|
|
32
|
+
presentation_1.UserRolesChangedListener,
|
|
34
33
|
infra_1.AuditDataSubscriber,
|
|
35
34
|
],
|
|
36
35
|
exports: [
|
|
37
|
-
infra_1.
|
|
38
|
-
infra_1.ErrorLogRepository,
|
|
36
|
+
infra_1.RequestLogRepository,
|
|
39
37
|
infra_1.AuditDataChangeRepository,
|
|
40
38
|
user_repository_1.UserRepository,
|
|
41
39
|
domain_1.AuditService,
|