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
|
@@ -8,7 +8,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.MaintenanceModule = void 0;
|
|
10
10
|
const common_1 = require("@nestjs/common");
|
|
11
|
-
const audit_module_1 = require("../audit/audit.module");
|
|
12
11
|
const auth_module_1 = require("../auth/auth.module");
|
|
13
12
|
const cleanup_service_1 = require("./domain/cleanup.service");
|
|
14
13
|
const notifications_module_1 = require("../notifications/notifications.module");
|
|
@@ -18,7 +17,7 @@ let MaintenanceModule = class MaintenanceModule {
|
|
|
18
17
|
exports.MaintenanceModule = MaintenanceModule;
|
|
19
18
|
exports.MaintenanceModule = MaintenanceModule = __decorate([
|
|
20
19
|
(0, common_1.Module)({
|
|
21
|
-
imports: [auth_module_1.AuthModule,
|
|
20
|
+
imports: [auth_module_1.AuthModule, notifications_module_1.NotificationsModule, users_module_1.UsersModule],
|
|
22
21
|
providers: [cleanup_service_1.CleanupService],
|
|
23
22
|
})
|
|
24
23
|
], MaintenanceModule);
|
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ChannelType = void 0;
|
|
4
4
|
var ChannelType;
|
|
5
5
|
(function (ChannelType) {
|
|
6
|
-
ChannelType["IN_APP"] = "IN_APP";
|
|
7
|
-
ChannelType["EMAIL"] = "EMAIL";
|
|
8
|
-
ChannelType["PUSH"] = "PUSH";
|
|
9
|
-
ChannelType["SMS"] = "SMS";
|
|
10
|
-
ChannelType["WHATSAPP"] = "WHATSAPP";
|
|
6
|
+
ChannelType[ChannelType["IN_APP"] = 0] = "IN_APP";
|
|
7
|
+
ChannelType[ChannelType["EMAIL"] = 1] = "EMAIL";
|
|
8
|
+
ChannelType[ChannelType["PUSH"] = 2] = "PUSH";
|
|
9
|
+
ChannelType[ChannelType["SMS"] = 3] = "SMS";
|
|
10
|
+
ChannelType[ChannelType["WHATSAPP"] = 4] = "WHATSAPP";
|
|
11
11
|
})(ChannelType || (exports.ChannelType = ChannelType = {}));
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export declare enum DeliveryStatus {
|
|
2
|
-
PENDING =
|
|
3
|
-
QUEUED =
|
|
4
|
-
SENT =
|
|
5
|
-
DELIVERED =
|
|
6
|
-
FAILED =
|
|
7
|
-
CANCELLED =
|
|
2
|
+
PENDING = 0,
|
|
3
|
+
QUEUED = 1,
|
|
4
|
+
SENT = 2,
|
|
5
|
+
DELIVERED = 3,
|
|
6
|
+
FAILED = 4,
|
|
7
|
+
CANCELLED = 5
|
|
8
8
|
}
|
|
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DeliveryStatus = void 0;
|
|
4
4
|
var DeliveryStatus;
|
|
5
5
|
(function (DeliveryStatus) {
|
|
6
|
-
DeliveryStatus["PENDING"] = "PENDING";
|
|
7
|
-
DeliveryStatus["QUEUED"] = "QUEUED";
|
|
8
|
-
DeliveryStatus["SENT"] = "SENT";
|
|
9
|
-
DeliveryStatus["DELIVERED"] = "DELIVERED";
|
|
10
|
-
DeliveryStatus["FAILED"] = "FAILED";
|
|
11
|
-
DeliveryStatus["CANCELLED"] = "CANCELLED";
|
|
6
|
+
DeliveryStatus[DeliveryStatus["PENDING"] = 0] = "PENDING";
|
|
7
|
+
DeliveryStatus[DeliveryStatus["QUEUED"] = 1] = "QUEUED";
|
|
8
|
+
DeliveryStatus[DeliveryStatus["SENT"] = 2] = "SENT";
|
|
9
|
+
DeliveryStatus[DeliveryStatus["DELIVERED"] = 3] = "DELIVERED";
|
|
10
|
+
DeliveryStatus[DeliveryStatus["FAILED"] = 4] = "FAILED";
|
|
11
|
+
DeliveryStatus[DeliveryStatus["CANCELLED"] = 5] = "CANCELLED";
|
|
12
12
|
})(DeliveryStatus || (exports.DeliveryStatus = DeliveryStatus = {}));
|
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.NotificationType = void 0;
|
|
4
4
|
var NotificationType;
|
|
5
5
|
(function (NotificationType) {
|
|
6
|
-
NotificationType["INFO"] = "INFO";
|
|
7
|
-
NotificationType["SUCCESS"] = "SUCCESS";
|
|
8
|
-
NotificationType["WARNING"] = "WARNING";
|
|
9
|
-
NotificationType["ERROR"] = "ERROR";
|
|
6
|
+
NotificationType[NotificationType["INFO"] = 0] = "INFO";
|
|
7
|
+
NotificationType[NotificationType["SUCCESS"] = 1] = "SUCCESS";
|
|
8
|
+
NotificationType[NotificationType["WARNING"] = 2] = "WARNING";
|
|
9
|
+
NotificationType[NotificationType["ERROR"] = 3] = "ERROR";
|
|
10
10
|
})(NotificationType || (exports.NotificationType = NotificationType = {}));
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ScopeType = void 0;
|
|
4
4
|
var ScopeType;
|
|
5
5
|
(function (ScopeType) {
|
|
6
|
-
ScopeType["USER"] = "USER";
|
|
7
|
-
ScopeType["ROLE"] = "ROLE";
|
|
8
|
-
ScopeType["ALL"] = "ALL";
|
|
6
|
+
ScopeType[ScopeType["USER"] = 0] = "USER";
|
|
7
|
+
ScopeType[ScopeType["ROLE"] = 1] = "ROLE";
|
|
8
|
+
ScopeType[ScopeType["ALL"] = 2] = "ALL";
|
|
9
9
|
})(ScopeType || (exports.ScopeType = ScopeType = {}));
|
|
@@ -31,8 +31,8 @@ __decorate([
|
|
|
31
31
|
__metadata("design:type", Object)
|
|
32
32
|
], Notification.prototype, "payload", void 0);
|
|
33
33
|
__decorate([
|
|
34
|
-
(0, typeorm_1.Column)({ type: "
|
|
35
|
-
__metadata("design:type",
|
|
34
|
+
(0, typeorm_1.Column)({ type: "tinyint", unsigned: true }),
|
|
35
|
+
__metadata("design:type", Number)
|
|
36
36
|
], Notification.prototype, "type", void 0);
|
|
37
37
|
__decorate([
|
|
38
38
|
(0, typeorm_1.Column)({ name: "created_by", type: "char", length: 36, nullable: true }),
|
|
@@ -22,8 +22,8 @@ __decorate([
|
|
|
22
22
|
__metadata("design:type", String)
|
|
23
23
|
], NotificationScope.prototype, "notificationId", void 0);
|
|
24
24
|
__decorate([
|
|
25
|
-
(0, typeorm_1.Column)({ name: "scope_type", type: "
|
|
26
|
-
__metadata("design:type",
|
|
25
|
+
(0, typeorm_1.Column)({ name: "scope_type", type: "tinyint", unsigned: true }),
|
|
26
|
+
__metadata("design:type", Number)
|
|
27
27
|
], NotificationScope.prototype, "scopeType", void 0);
|
|
28
28
|
__decorate([
|
|
29
29
|
(0, typeorm_1.Column)({ name: "scope_key", type: "varchar", length: 100, nullable: true }),
|
|
@@ -21,7 +21,7 @@ exports.NotificationTargetCommand = NotificationTargetCommand;
|
|
|
21
21
|
__decorate([
|
|
22
22
|
(0, swagger_1.ApiProperty)({ enum: scopeType_enum_1.ScopeType, enumName: "ScopeType" }),
|
|
23
23
|
(0, class_validator_1.IsEnum)(scopeType_enum_1.ScopeType),
|
|
24
|
-
__metadata("design:type",
|
|
24
|
+
__metadata("design:type", Number)
|
|
25
25
|
], NotificationTargetCommand.prototype, "type", void 0);
|
|
26
26
|
__decorate([
|
|
27
27
|
(0, swagger_1.ApiProperty)({
|
|
@@ -50,7 +50,7 @@ __decorate([
|
|
|
50
50
|
__decorate([
|
|
51
51
|
(0, swagger_1.ApiProperty)({ enum: notificationType_enum_1.NotificationType, enumName: "NotificationType" }),
|
|
52
52
|
(0, class_validator_1.IsEnum)(notificationType_enum_1.NotificationType),
|
|
53
|
-
__metadata("design:type",
|
|
53
|
+
__metadata("design:type", Number)
|
|
54
54
|
], CreateNotificationCommand.prototype, "type", void 0);
|
|
55
55
|
__decorate([
|
|
56
56
|
(0, swagger_1.ApiProperty)({ type: [NotificationTargetCommand] }),
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { SystemCleanupFailedEvent, UserLockedEvent, UserPasswordExpiringEvent, UserPasswordResetRequestedEvent, UserTwoFactorResetEvent } from "../../../core/events/appEvent.enum";
|
|
1
|
+
import { SystemCleanupFailedEvent, UserLockedEvent, UserPasswordExpiringEvent, UserPasswordResetRequestedEvent, UserRolesChangedEvent, UserTwoFactorResetEvent } from "../../../core/events/appEvent.enum";
|
|
2
|
+
import { NotificationsGateway } from "./notifications.gateway";
|
|
2
3
|
import { NotificationsPublisher } from "./notifications.publisher";
|
|
3
4
|
export declare class DomainEventsListener {
|
|
4
5
|
private readonly publisher;
|
|
6
|
+
private readonly gateway;
|
|
5
7
|
private readonly logger;
|
|
6
|
-
constructor(publisher: NotificationsPublisher);
|
|
8
|
+
constructor(publisher: NotificationsPublisher, gateway: NotificationsGateway);
|
|
7
9
|
onUserLocked(event: UserLockedEvent): Promise<void>;
|
|
8
10
|
onTwoFactorReset(event: UserTwoFactorResetEvent): Promise<void>;
|
|
11
|
+
onRolesChanged(event: UserRolesChangedEvent): Promise<void>;
|
|
9
12
|
onPasswordResetRequested(event: UserPasswordResetRequestedEvent): Promise<void>;
|
|
10
13
|
onPasswordExpiring(event: UserPasswordExpiringEvent): Promise<void>;
|
|
11
14
|
onCleanupFailed(event: SystemCleanupFailedEvent): Promise<void>;
|
|
@@ -16,11 +16,13 @@ const event_emitter_1 = require("@nestjs/event-emitter");
|
|
|
16
16
|
const appEvent_enum_1 = require("../../../core/events/appEvent.enum");
|
|
17
17
|
const notificationType_enum_1 = require("../domain/enums/notificationType.enum");
|
|
18
18
|
const scopeType_enum_1 = require("../domain/enums/scopeType.enum");
|
|
19
|
+
const notifications_gateway_1 = require("./notifications.gateway");
|
|
19
20
|
const notifications_publisher_1 = require("./notifications.publisher");
|
|
20
21
|
const ADMIN_ROLE = "Super Admin";
|
|
21
22
|
let DomainEventsListener = DomainEventsListener_1 = class DomainEventsListener {
|
|
22
|
-
constructor(publisher) {
|
|
23
|
+
constructor(publisher, gateway) {
|
|
23
24
|
this.publisher = publisher;
|
|
25
|
+
this.gateway = gateway;
|
|
24
26
|
this.logger = new common_1.Logger(DomainEventsListener_1.name);
|
|
25
27
|
}
|
|
26
28
|
async onUserLocked(event) {
|
|
@@ -48,6 +50,19 @@ let DomainEventsListener = DomainEventsListener_1 = class DomainEventsListener {
|
|
|
48
50
|
targets: [{ type: scopeType_enum_1.ScopeType.USER, key: event.userId }],
|
|
49
51
|
}));
|
|
50
52
|
}
|
|
53
|
+
async onRolesChanged(event) {
|
|
54
|
+
await this.safePublish(appEvent_enum_1.AppEvent.USER_ROLES_CHANGED, async () => {
|
|
55
|
+
await this.publisher.publishAndPush({
|
|
56
|
+
title: "Suas permissões foram atualizadas",
|
|
57
|
+
body: event.roleNames.length
|
|
58
|
+
? `Um administrador alterou seus papéis de acesso. Agora você é: ${event.roleNames.join(", ")}.`
|
|
59
|
+
: "Um administrador removeu seus papéis de acesso. Parte do sistema deixa de aparecer para você.",
|
|
60
|
+
type: notificationType_enum_1.NotificationType.INFO,
|
|
61
|
+
targets: [{ type: scopeType_enum_1.ScopeType.USER, key: event.userId }],
|
|
62
|
+
});
|
|
63
|
+
this.gateway.requestSessionRefresh(event.userId);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
51
66
|
async onPasswordResetRequested(event) {
|
|
52
67
|
await this.safePublish(appEvent_enum_1.AppEvent.USER_PASSWORD_RESET_REQUESTED, () => this.publisher.publishAndPush({
|
|
53
68
|
title: "Redefinição de senha solicitada",
|
|
@@ -97,6 +112,12 @@ __decorate([
|
|
|
97
112
|
__metadata("design:paramtypes", [Object]),
|
|
98
113
|
__metadata("design:returntype", Promise)
|
|
99
114
|
], DomainEventsListener.prototype, "onTwoFactorReset", null);
|
|
115
|
+
__decorate([
|
|
116
|
+
(0, event_emitter_1.OnEvent)(appEvent_enum_1.AppEvent.USER_ROLES_CHANGED),
|
|
117
|
+
__metadata("design:type", Function),
|
|
118
|
+
__metadata("design:paramtypes", [Object]),
|
|
119
|
+
__metadata("design:returntype", Promise)
|
|
120
|
+
], DomainEventsListener.prototype, "onRolesChanged", null);
|
|
100
121
|
__decorate([
|
|
101
122
|
(0, event_emitter_1.OnEvent)(appEvent_enum_1.AppEvent.USER_PASSWORD_RESET_REQUESTED),
|
|
102
123
|
__metadata("design:type", Function),
|
|
@@ -117,5 +138,6 @@ __decorate([
|
|
|
117
138
|
], DomainEventsListener.prototype, "onCleanupFailed", null);
|
|
118
139
|
exports.DomainEventsListener = DomainEventsListener = DomainEventsListener_1 = __decorate([
|
|
119
140
|
(0, common_1.Injectable)(),
|
|
120
|
-
__metadata("design:paramtypes", [notifications_publisher_1.NotificationsPublisher
|
|
141
|
+
__metadata("design:paramtypes", [notifications_publisher_1.NotificationsPublisher,
|
|
142
|
+
notifications_gateway_1.NotificationsGateway])
|
|
121
143
|
], DomainEventsListener);
|
|
@@ -32,7 +32,7 @@ __decorate([
|
|
|
32
32
|
], UserNotificationResponse.prototype, "body", void 0);
|
|
33
33
|
__decorate([
|
|
34
34
|
(0, swagger_1.ApiProperty)({ enum: notificationType_enum_1.NotificationType, enumName: "NotificationType" }),
|
|
35
|
-
__metadata("design:type",
|
|
35
|
+
__metadata("design:type", Number)
|
|
36
36
|
], UserNotificationResponse.prototype, "type", void 0);
|
|
37
37
|
__decorate([
|
|
38
38
|
(0, swagger_1.ApiProperty)({
|
|
@@ -62,6 +62,30 @@ exports.PERMISSIONS = [
|
|
|
62
62
|
code: "users:invite:any",
|
|
63
63
|
description: "Enviar link de primeiro acesso a qualquer usuário",
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
code: "users:read:team",
|
|
67
|
+
description: "Ler usuários da própria equipe",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
code: "users:create:team",
|
|
71
|
+
description: "Criar usuário dentro da própria equipe",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
code: "users:update:team",
|
|
75
|
+
description: "Atualizar usuários da própria equipe",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
code: "users:invite:team",
|
|
79
|
+
description: "Enviar link de primeiro acesso a usuários da própria equipe",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
code: "users:reset-password:team",
|
|
83
|
+
description: "Resetar senha e 2FA de usuários da própria equipe",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
code: "users:deactivate:team",
|
|
87
|
+
description: "Ativar/desativar usuários da própria equipe",
|
|
88
|
+
},
|
|
65
89
|
{ code: "roles:create:any", description: "Criar papéis" },
|
|
66
90
|
{ code: "roles:read:any", description: "Ler papéis" },
|
|
67
91
|
{ code: "roles:update:any", description: "Atualizar papéis" },
|
|
@@ -132,9 +156,14 @@ exports.ROLES = [
|
|
|
132
156
|
},
|
|
133
157
|
{
|
|
134
158
|
name: "Manager",
|
|
135
|
-
description: "Gestor de
|
|
159
|
+
description: "Gestor de equipe — administra quem está na árvore dele",
|
|
136
160
|
permissions: [
|
|
137
|
-
"users:read:
|
|
161
|
+
"users:read:team",
|
|
162
|
+
"users:create:team",
|
|
163
|
+
"users:update:team",
|
|
164
|
+
"users:invite:team",
|
|
165
|
+
"users:reset-password:team",
|
|
166
|
+
"users:deactivate:team",
|
|
138
167
|
"reports:read:department",
|
|
139
168
|
"reports:read:any",
|
|
140
169
|
"audit:read:any",
|
|
@@ -59,6 +59,7 @@ export declare class RbacService {
|
|
|
59
59
|
addPermissionToRole(roleId: string, permissionId: string, actorPermissions?: string[]): Promise<Role>;
|
|
60
60
|
removePermissionFromRole(roleId: string, permissionId: string): Promise<Role>;
|
|
61
61
|
listGroups(): Promise<Group[]>;
|
|
62
|
+
listManagedGroups(managerId: string): Promise<Group[]>;
|
|
62
63
|
getGroup(id: string): Promise<Group>;
|
|
63
64
|
createGroup(dto: CreateGroupCommand): Promise<Group>;
|
|
64
65
|
updateGroup(id: string, dto: UpdateGroupCommand): Promise<Group>;
|
|
@@ -348,6 +348,16 @@ let RbacService = class RbacService {
|
|
|
348
348
|
order: { name: "ASC" },
|
|
349
349
|
});
|
|
350
350
|
}
|
|
351
|
+
async listManagedGroups(managerId) {
|
|
352
|
+
const ids = await this.groupRepo.findManagedGroupIds(managerId);
|
|
353
|
+
if (ids.length === 0) {
|
|
354
|
+
return [];
|
|
355
|
+
}
|
|
356
|
+
return this.groupRepo.find({
|
|
357
|
+
where: { id: (0, typeorm_1.In)(ids) },
|
|
358
|
+
order: { name: "ASC" },
|
|
359
|
+
});
|
|
360
|
+
}
|
|
351
361
|
async getGroup(id) {
|
|
352
362
|
const group = await this.groupRepo.findOne({
|
|
353
363
|
where: { id },
|
|
@@ -367,6 +377,7 @@ let RbacService = class RbacService {
|
|
|
367
377
|
description: dto.description,
|
|
368
378
|
type: dto.type ?? "team",
|
|
369
379
|
parentId: dto.parentId ?? null,
|
|
380
|
+
managerId: dto.managerId ?? null,
|
|
370
381
|
roles,
|
|
371
382
|
});
|
|
372
383
|
return this.groupRepo.save(group);
|
|
@@ -385,6 +396,9 @@ let RbacService = class RbacService {
|
|
|
385
396
|
if (dto.parentId !== undefined) {
|
|
386
397
|
group.parentId = dto.parentId;
|
|
387
398
|
}
|
|
399
|
+
if (dto.managerId !== undefined) {
|
|
400
|
+
group.managerId = dto.managerId;
|
|
401
|
+
}
|
|
388
402
|
if (dto.isActive !== undefined) {
|
|
389
403
|
group.isActive = dto.isActive;
|
|
390
404
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Actor } from "../../../core/auth/actor.interface";
|
|
2
|
+
import { RbacService } from "./rbac.service";
|
|
3
|
+
import { GroupRepository } from "../infra/repositories/group.repository";
|
|
4
|
+
export declare class TeamScopeService {
|
|
5
|
+
private readonly groupRepo;
|
|
6
|
+
private readonly rbac;
|
|
7
|
+
constructor(groupRepo: GroupRepository, rbac: RbacService);
|
|
8
|
+
reachableUserIds(actor: Actor, action: string): Promise<string[] | null>;
|
|
9
|
+
managedGroupIds(managerId: string): Promise<string[]>;
|
|
10
|
+
private reachOf;
|
|
11
|
+
assertCanAct(actor: Actor, targetUserId: string, action: string): Promise<void>;
|
|
12
|
+
private assertActorOutranks;
|
|
13
|
+
assertOwnsGroups(actor: Actor, groupIds: string[]): Promise<void>;
|
|
14
|
+
private has;
|
|
15
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
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.TeamScopeService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const permissionScope_util_1 = require("../../../core/auth/permissionScope.util");
|
|
15
|
+
const rbac_service_1 = require("./rbac.service");
|
|
16
|
+
const group_repository_1 = require("../infra/repositories/group.repository");
|
|
17
|
+
let TeamScopeService = class TeamScopeService {
|
|
18
|
+
constructor(groupRepo, rbac) {
|
|
19
|
+
this.groupRepo = groupRepo;
|
|
20
|
+
this.rbac = rbac;
|
|
21
|
+
}
|
|
22
|
+
async reachableUserIds(actor, action) {
|
|
23
|
+
if (this.has(actor, action, permissionScope_util_1.SCOPE_ANY)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (!this.has(actor, action, permissionScope_util_1.SCOPE_TEAM)) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
const reach = await this.reachOf(actor.id);
|
|
30
|
+
return reach.userIds;
|
|
31
|
+
}
|
|
32
|
+
async managedGroupIds(managerId) {
|
|
33
|
+
return this.groupRepo.findManagedGroupIds(managerId);
|
|
34
|
+
}
|
|
35
|
+
async reachOf(managerId) {
|
|
36
|
+
const groupIds = await this.groupRepo.findManagedGroupIds(managerId);
|
|
37
|
+
const userIds = await this.groupRepo.findMemberIds(groupIds);
|
|
38
|
+
return { groupIds, userIds };
|
|
39
|
+
}
|
|
40
|
+
async assertCanAct(actor, targetUserId, action) {
|
|
41
|
+
const reach = await this.reachableUserIds(actor, action);
|
|
42
|
+
if (reach === null) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (!reach.includes(targetUserId)) {
|
|
46
|
+
throw new common_1.ForbiddenException("Este usuário não faz parte da sua equipe");
|
|
47
|
+
}
|
|
48
|
+
await this.assertActorOutranks(actor, targetUserId);
|
|
49
|
+
}
|
|
50
|
+
async assertActorOutranks(actor, targetUserId) {
|
|
51
|
+
const targetPermissions = await this.rbac.getUserPermissionCodes(targetUserId);
|
|
52
|
+
const granted = new Set(actor.permissions);
|
|
53
|
+
const excess = targetPermissions.filter((code) => !granted.has(code));
|
|
54
|
+
if (excess.length > 0) {
|
|
55
|
+
throw new common_1.ForbiddenException("Este usuário tem permissões que você não possui — só um administrador pode administrá-lo");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async assertOwnsGroups(actor, groupIds) {
|
|
59
|
+
const managed = new Set(await this.managedGroupIds(actor.id));
|
|
60
|
+
const foreign = groupIds.filter((id) => !managed.has(id));
|
|
61
|
+
if (foreign.length > 0) {
|
|
62
|
+
throw new common_1.ForbiddenException("Você só pode incluir usuários em grupos que gerencia");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
has(actor, action, scope) {
|
|
66
|
+
return actor.permissions.includes(`${action}:${scope}`);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
exports.TeamScopeService = TeamScopeService;
|
|
70
|
+
exports.TeamScopeService = TeamScopeService = __decorate([
|
|
71
|
+
(0, common_1.Injectable)(),
|
|
72
|
+
__metadata("design:paramtypes", [group_repository_1.GroupRepository,
|
|
73
|
+
rbac_service_1.RbacService])
|
|
74
|
+
], TeamScopeService);
|
|
@@ -2,4 +2,6 @@ import { DataSource, Repository } from "typeorm";
|
|
|
2
2
|
import { Group } from "../schema/group.schema";
|
|
3
3
|
export declare class GroupRepository extends Repository<Group> {
|
|
4
4
|
constructor(dataSource: DataSource);
|
|
5
|
+
findManagedGroupIds(managerId: string): Promise<string[]>;
|
|
6
|
+
findMemberIds(groupIds: string[]): Promise<string[]>;
|
|
5
7
|
}
|
|
@@ -17,6 +17,32 @@ let GroupRepository = class GroupRepository extends typeorm_1.Repository {
|
|
|
17
17
|
constructor(dataSource) {
|
|
18
18
|
super(group_schema_1.Group, dataSource.createEntityManager());
|
|
19
19
|
}
|
|
20
|
+
async findManagedGroupIds(managerId) {
|
|
21
|
+
const rows = await this.query(`
|
|
22
|
+
WITH RECURSIVE team AS (
|
|
23
|
+
SELECT id FROM \`groups\`
|
|
24
|
+
WHERE manager_id = ? AND is_active = 1 AND deleted_at IS NULL
|
|
25
|
+
UNION ALL
|
|
26
|
+
SELECT child.id
|
|
27
|
+
FROM \`groups\` child
|
|
28
|
+
INNER JOIN team ON child.parent_id = team.id
|
|
29
|
+
WHERE child.is_active = 1 AND child.deleted_at IS NULL
|
|
30
|
+
)
|
|
31
|
+
SELECT id FROM team
|
|
32
|
+
`, [managerId]);
|
|
33
|
+
return rows.map((row) => row.id);
|
|
34
|
+
}
|
|
35
|
+
async findMemberIds(groupIds) {
|
|
36
|
+
if (groupIds.length === 0) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
const rows = await this.query(`
|
|
40
|
+
SELECT DISTINCT ug.user_id AS id
|
|
41
|
+
FROM user_groups ug
|
|
42
|
+
WHERE ug.group_id IN (?)
|
|
43
|
+
`, [groupIds]);
|
|
44
|
+
return rows.map((row) => row.id);
|
|
45
|
+
}
|
|
20
46
|
};
|
|
21
47
|
exports.GroupRepository = GroupRepository;
|
|
22
48
|
exports.GroupRepository = GroupRepository = __decorate([
|
|
@@ -41,6 +41,11 @@ __decorate([
|
|
|
41
41
|
(0, typeorm_1.JoinColumn)({ name: "parent_id" }),
|
|
42
42
|
__metadata("design:type", Object)
|
|
43
43
|
], Group.prototype, "parent", void 0);
|
|
44
|
+
__decorate([
|
|
45
|
+
(0, swagger_1.ApiProperty)({ required: false, nullable: true }),
|
|
46
|
+
(0, typeorm_1.Column)({ name: "manager_id", type: "char", length: 36, nullable: true }),
|
|
47
|
+
__metadata("design:type", Object)
|
|
48
|
+
], Group.prototype, "managerId", void 0);
|
|
44
49
|
__decorate([
|
|
45
50
|
(0, swagger_1.ApiProperty)(),
|
|
46
51
|
(0, typeorm_1.Column)({ name: "is_active", type: "boolean", default: true }),
|
|
@@ -44,6 +44,13 @@ __decorate([
|
|
|
44
44
|
(0, class_validator_1.IsUUID)(),
|
|
45
45
|
__metadata("design:type", String)
|
|
46
46
|
], CreateGroupCommand.prototype, "parentId", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
(0, swagger_1.ApiProperty)({ type: String, required: false, format: "uuid", nullable: true }),
|
|
49
|
+
(0, class_validator_1.IsOptional)(),
|
|
50
|
+
(0, class_validator_1.ValidateIf)((_, value) => value !== null),
|
|
51
|
+
(0, class_validator_1.IsUUID)(),
|
|
52
|
+
__metadata("design:type", Object)
|
|
53
|
+
], CreateGroupCommand.prototype, "managerId", void 0);
|
|
47
54
|
__decorate([
|
|
48
55
|
(0, swagger_1.ApiProperty)({ required: false, type: [String], format: "uuid" }),
|
|
49
56
|
(0, class_validator_1.IsOptional)(),
|
|
@@ -38,6 +38,7 @@ export declare class RbacController {
|
|
|
38
38
|
updatePermission(id: string, dto: UpdatePermissionCommand): Promise<Permission>;
|
|
39
39
|
deletePermission(id: string): Promise<void>;
|
|
40
40
|
groups(): Promise<Group[]>;
|
|
41
|
+
managedGroups(actor: AuthenticatedUser): Promise<Group[]>;
|
|
41
42
|
group(id: string): Promise<Group>;
|
|
42
43
|
createGroup(dto: CreateGroupCommand): Promise<Group>;
|
|
43
44
|
updateGroup(id: string, dto: UpdateGroupCommand): Promise<Group>;
|
|
@@ -18,6 +18,7 @@ const swagger_1 = require("@nestjs/swagger");
|
|
|
18
18
|
const currentUser_decorator_1 = require("../../../core/auth/decorators/currentUser.decorator");
|
|
19
19
|
const requirePermission_decorator_1 = require("../../../core/auth/decorators/requirePermission.decorator");
|
|
20
20
|
const permissions_guard_1 = require("../../../core/auth/guards/permissions.guard");
|
|
21
|
+
const auditable_decorator_1 = require("../../audit/presentation/decorators/auditable.decorator");
|
|
21
22
|
const rbac_service_1 = require("../domain/rbac.service");
|
|
22
23
|
const createAction_command_1 = require("./commands/createAction.command");
|
|
23
24
|
const createGroup_command_1 = require("./commands/createGroup.command");
|
|
@@ -87,6 +88,9 @@ let RbacController = class RbacController {
|
|
|
87
88
|
groups() {
|
|
88
89
|
return this.rbac.listGroups();
|
|
89
90
|
}
|
|
91
|
+
managedGroups(actor) {
|
|
92
|
+
return this.rbac.listManagedGroups(actor.id);
|
|
93
|
+
}
|
|
90
94
|
group(id) {
|
|
91
95
|
return this.rbac.getGroup(id);
|
|
92
96
|
}
|
|
@@ -280,6 +284,14 @@ __decorate([
|
|
|
280
284
|
__metadata("design:paramtypes", []),
|
|
281
285
|
__metadata("design:returntype", Promise)
|
|
282
286
|
], RbacController.prototype, "groups", null);
|
|
287
|
+
__decorate([
|
|
288
|
+
(0, common_1.Get)("groups/managed"),
|
|
289
|
+
(0, swagger_1.ApiOkResponse)({ type: rbac_response_1.GroupResponse, isArray: true }),
|
|
290
|
+
__param(0, (0, currentUser_decorator_1.CurrentUser)()),
|
|
291
|
+
__metadata("design:type", Function),
|
|
292
|
+
__metadata("design:paramtypes", [Object]),
|
|
293
|
+
__metadata("design:returntype", Promise)
|
|
294
|
+
], RbacController.prototype, "managedGroups", null);
|
|
283
295
|
__decorate([
|
|
284
296
|
(0, common_1.Get)("groups/:id"),
|
|
285
297
|
(0, requirePermission_decorator_1.RequirePermission)("groups:read:any"),
|
|
@@ -318,6 +330,7 @@ __decorate([
|
|
|
318
330
|
__metadata("design:returntype", Promise)
|
|
319
331
|
], RbacController.prototype, "deleteGroup", null);
|
|
320
332
|
__decorate([
|
|
333
|
+
(0, auditable_decorator_1.Auditable)("Usuário adicionado ao grupo"),
|
|
321
334
|
(0, common_1.Post)("groups/:id/users/:userId"),
|
|
322
335
|
(0, common_1.HttpCode)(204),
|
|
323
336
|
(0, requirePermission_decorator_1.RequirePermission)("groups:update:any"),
|
|
@@ -328,6 +341,7 @@ __decorate([
|
|
|
328
341
|
__metadata("design:returntype", Promise)
|
|
329
342
|
], RbacController.prototype, "addUserToGroup", null);
|
|
330
343
|
__decorate([
|
|
344
|
+
(0, auditable_decorator_1.Auditable)("Usuário removido do grupo"),
|
|
331
345
|
(0, common_1.Delete)("groups/:id/users/:userId"),
|
|
332
346
|
(0, common_1.HttpCode)(204),
|
|
333
347
|
(0, requirePermission_decorator_1.RequirePermission)("groups:update:any"),
|
|
@@ -384,6 +398,7 @@ __decorate([
|
|
|
384
398
|
__metadata("design:returntype", Promise)
|
|
385
399
|
], RbacController.prototype, "deleteRole", null);
|
|
386
400
|
__decorate([
|
|
401
|
+
(0, auditable_decorator_1.Auditable)("Permissão concedida ao papel"),
|
|
387
402
|
(0, common_1.Post)("roles/:id/permissions/:permissionId"),
|
|
388
403
|
(0, requirePermission_decorator_1.RequirePermission)("roles:update:any"),
|
|
389
404
|
(0, swagger_1.ApiOkResponse)({ type: rbac_response_1.RoleResponse }),
|
|
@@ -395,6 +410,7 @@ __decorate([
|
|
|
395
410
|
__metadata("design:returntype", Promise)
|
|
396
411
|
], RbacController.prototype, "addPermissionToRole", null);
|
|
397
412
|
__decorate([
|
|
413
|
+
(0, auditable_decorator_1.Auditable)("Permissão removida do papel"),
|
|
398
414
|
(0, common_1.Delete)("roles/:id/permissions/:permissionId"),
|
|
399
415
|
(0, requirePermission_decorator_1.RequirePermission)("roles:update:any"),
|
|
400
416
|
(0, swagger_1.ApiOkResponse)({ type: rbac_response_1.RoleResponse }),
|
|
@@ -151,6 +151,10 @@ __decorate([
|
|
|
151
151
|
(0, swagger_1.ApiProperty)({ type: String, required: false, nullable: true, format: "uuid" }),
|
|
152
152
|
__metadata("design:type", Object)
|
|
153
153
|
], GroupResponse.prototype, "parentId", void 0);
|
|
154
|
+
__decorate([
|
|
155
|
+
(0, swagger_1.ApiProperty)({ type: String, required: false, nullable: true, format: "uuid" }),
|
|
156
|
+
__metadata("design:type", Object)
|
|
157
|
+
], GroupResponse.prototype, "managerId", void 0);
|
|
154
158
|
__decorate([
|
|
155
159
|
(0, swagger_1.ApiProperty)(),
|
|
156
160
|
__metadata("design:type", Boolean)
|