rl-core-api 0.13.1 → 0.14.1
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/dist/core/filters/allExceptions.filter.d.ts +1 -1
- package/dist/core/filters/allExceptions.filter.js +13 -1
- package/dist/features/auth/domain/auth.service.js +3 -0
- package/dist/features/notifications/domain/notifications.service.js +1 -7
- package/dist/features/notifications/infra/repositories/notification.repository.d.ts +1 -0
- package/dist/features/notifications/infra/repositories/notification.repository.js +34 -0
- package/dist/features/rbac/domain/rbac.service.d.ts +5 -3
- package/dist/features/rbac/domain/rbac.service.js +56 -12
- package/dist/features/rbac/infra/repositories/group.repository.d.ts +1 -0
- package/dist/features/rbac/infra/repositories/group.repository.js +15 -0
- package/dist/features/rbac/presentation/rbac.controller.d.ts +3 -3
- package/dist/features/rbac/presentation/rbac.controller.js +12 -9
- package/dist/features/users/domain/avatar.service.d.ts +1 -0
- package/dist/features/users/domain/avatar.service.js +3 -3
- package/dist/features/users/presentation/users.controller.js +5 -2
- package/package.json +1 -1
|
@@ -6,6 +6,6 @@ export declare class AllExceptionsFilter implements ExceptionFilter {
|
|
|
6
6
|
private readonly env;
|
|
7
7
|
private readonly logger;
|
|
8
8
|
constructor(events: EventEmitter2, env: EnvService);
|
|
9
|
-
catch(
|
|
9
|
+
catch(rawException: unknown, host: ArgumentsHost): void;
|
|
10
10
|
private publish;
|
|
11
11
|
}
|
|
@@ -16,13 +16,25 @@ const env_service_1 = require("../config/env.service");
|
|
|
16
16
|
const requestLog_context_1 = require("../context/requestLog.context");
|
|
17
17
|
const appEvent_enum_1 = require("../events/appEvent.enum");
|
|
18
18
|
const ip_util_1 = require("../utils/ip.util");
|
|
19
|
+
const asHttpException = (exception) => {
|
|
20
|
+
if (!(exception instanceof Error) ||
|
|
21
|
+
exception.name !== "MulterError") {
|
|
22
|
+
return exception;
|
|
23
|
+
}
|
|
24
|
+
const code = exception.code;
|
|
25
|
+
if (code === "LIMIT_FILE_SIZE") {
|
|
26
|
+
return new common_1.PayloadTooLargeException("Arquivo excede o tamanho permitido");
|
|
27
|
+
}
|
|
28
|
+
return new common_1.BadRequestException("Envio de arquivo inválido");
|
|
29
|
+
};
|
|
19
30
|
let AllExceptionsFilter = class AllExceptionsFilter {
|
|
20
31
|
constructor(events, env) {
|
|
21
32
|
this.events = events;
|
|
22
33
|
this.env = env;
|
|
23
34
|
this.logger = new common_1.Logger("Exception");
|
|
24
35
|
}
|
|
25
|
-
catch(
|
|
36
|
+
catch(rawException, host) {
|
|
37
|
+
const exception = asHttpException(rawException);
|
|
26
38
|
const ctx = host.switchToHttp();
|
|
27
39
|
const response = ctx.getResponse();
|
|
28
40
|
const request = ctx.getRequest();
|
|
@@ -103,6 +103,9 @@ let AuthService = class AuthService {
|
|
|
103
103
|
async verifyTwoFactor(dto, ctx) {
|
|
104
104
|
const payload = await this.decodePending(dto.pendingToken);
|
|
105
105
|
const user = await this.users.findById(payload.sub);
|
|
106
|
+
if (!user.isActive) {
|
|
107
|
+
throw accountInactive();
|
|
108
|
+
}
|
|
106
109
|
const maxAttempts = this.env.get("LOGIN_MAX_ATTEMPTS");
|
|
107
110
|
if (user.isLocked(maxAttempts)) {
|
|
108
111
|
throw accountLocked();
|
|
@@ -67,13 +67,7 @@ let NotificationsService = class NotificationsService {
|
|
|
67
67
|
async cleanupOldRead(retentionDays) {
|
|
68
68
|
const limit = new Date();
|
|
69
69
|
limit.setDate(limit.getDate() - retentionDays);
|
|
70
|
-
|
|
71
|
-
.createQueryBuilder()
|
|
72
|
-
.softDelete()
|
|
73
|
-
.where("created_at < :limit", { limit })
|
|
74
|
-
.andWhere(`EXISTS (SELECT 1 FROM notification_reads r WHERE r.notification_id = id)`)
|
|
75
|
-
.execute();
|
|
76
|
-
return result.affected ?? 0;
|
|
70
|
+
return await this.notifications.softDeleteReadByAllBefore(limit);
|
|
77
71
|
}
|
|
78
72
|
visibilityOf(user) {
|
|
79
73
|
return { userId: user.id, roleNames: user.roles ?? [] };
|
|
@@ -10,5 +10,6 @@ export declare class NotificationRepository extends Repository<Notification> {
|
|
|
10
10
|
countUnread(params: VisibilityParams): Promise<number>;
|
|
11
11
|
isVisibleToUser(notificationId: string, params: VisibilityParams): Promise<boolean>;
|
|
12
12
|
findUnreadIds(params: VisibilityParams): Promise<string[]>;
|
|
13
|
+
softDeleteReadByAllBefore(limit: Date): Promise<number>;
|
|
13
14
|
private baseVisibleQuery;
|
|
14
15
|
}
|
|
@@ -25,6 +25,28 @@ const VISIBLE_TO_USER = `EXISTS (
|
|
|
25
25
|
)
|
|
26
26
|
)`;
|
|
27
27
|
const NO_ROLES = ["-"];
|
|
28
|
+
const HAS_PENDING_READER = `EXISTS (
|
|
29
|
+
SELECT 1
|
|
30
|
+
FROM users u
|
|
31
|
+
JOIN notification_scopes s
|
|
32
|
+
ON s.notification_id = notifications.id
|
|
33
|
+
AND s.deleted_at IS NULL
|
|
34
|
+
AND (
|
|
35
|
+
(s.scope_type = :userScope AND s.scope_key = u.id)
|
|
36
|
+
OR (s.scope_type = :roleScope AND EXISTS (
|
|
37
|
+
SELECT 1
|
|
38
|
+
FROM user_roles ur
|
|
39
|
+
JOIN roles r ON r.id = ur.role_id AND r.deleted_at IS NULL
|
|
40
|
+
WHERE ur.user_id = u.id AND r.name = s.scope_key))
|
|
41
|
+
OR s.scope_type = :allScope
|
|
42
|
+
)
|
|
43
|
+
WHERE u.deleted_at IS NULL
|
|
44
|
+
AND u.is_active = 1
|
|
45
|
+
AND NOT EXISTS (
|
|
46
|
+
SELECT 1 FROM notification_reads nr
|
|
47
|
+
WHERE nr.notification_id = notifications.id AND nr.user_id = u.id
|
|
48
|
+
)
|
|
49
|
+
)`;
|
|
28
50
|
let NotificationRepository = class NotificationRepository extends typeorm_1.Repository {
|
|
29
51
|
constructor(dataSource) {
|
|
30
52
|
super(notification_schema_1.Notification, dataSource.createEntityManager());
|
|
@@ -54,6 +76,18 @@ let NotificationRepository = class NotificationRepository extends typeorm_1.Repo
|
|
|
54
76
|
.getRawMany();
|
|
55
77
|
return rows.map((row) => row.id);
|
|
56
78
|
}
|
|
79
|
+
async softDeleteReadByAllBefore(limit) {
|
|
80
|
+
const result = await this.createQueryBuilder()
|
|
81
|
+
.softDelete()
|
|
82
|
+
.where("created_at < :limit", { limit })
|
|
83
|
+
.andWhere(`NOT ${HAS_PENDING_READER}`, {
|
|
84
|
+
userScope: scopeType_enum_1.ScopeType.USER,
|
|
85
|
+
roleScope: scopeType_enum_1.ScopeType.ROLE,
|
|
86
|
+
allScope: scopeType_enum_1.ScopeType.ALL,
|
|
87
|
+
})
|
|
88
|
+
.execute();
|
|
89
|
+
return result.affected ?? 0;
|
|
90
|
+
}
|
|
57
91
|
baseVisibleQuery(params) {
|
|
58
92
|
return this.createQueryBuilder("notification")
|
|
59
93
|
.leftJoinAndSelect("notification.reads", "read", "read.user_id = :userId", { userId: params.userId })
|
|
@@ -54,7 +54,7 @@ export declare class RbacService {
|
|
|
54
54
|
deletePermission(id: string): Promise<void>;
|
|
55
55
|
listRoles(): Promise<Role[]>;
|
|
56
56
|
getRole(id: string): Promise<Role>;
|
|
57
|
-
createRole(dto: CreateRoleCommand): Promise<Role>;
|
|
57
|
+
createRole(dto: CreateRoleCommand, actorPermissions?: string[]): Promise<Role>;
|
|
58
58
|
updateRole(id: string, dto: UpdateRoleCommand, actorPermissions?: string[]): Promise<Role>;
|
|
59
59
|
private assertGrantableByActor;
|
|
60
60
|
deleteRole(id: string): Promise<void>;
|
|
@@ -71,8 +71,10 @@ export declare class RbacService {
|
|
|
71
71
|
listGroups(): Promise<Group[]>;
|
|
72
72
|
listManagedGroups(managerId: string): Promise<Group[]>;
|
|
73
73
|
getGroup(id: string): Promise<Group>;
|
|
74
|
-
createGroup(dto: CreateGroupCommand): Promise<Group>;
|
|
75
|
-
updateGroup(id: string, dto: UpdateGroupCommand): Promise<Group>;
|
|
74
|
+
createGroup(dto: CreateGroupCommand, actorPermissions?: string[]): Promise<Group>;
|
|
75
|
+
updateGroup(id: string, dto: UpdateGroupCommand, actorPermissions?: string[]): Promise<Group>;
|
|
76
|
+
private resolveGrantableRoles;
|
|
77
|
+
private assertParentIsValid;
|
|
76
78
|
deleteGroup(id: string): Promise<void>;
|
|
77
79
|
addUserToGroup(groupId: string, userId: string): Promise<void>;
|
|
78
80
|
removeUserFromGroup(groupId: string, userId: string): Promise<void>;
|
|
@@ -21,6 +21,7 @@ const resource_repository_1 = require("../infra/repositories/resource.repository
|
|
|
21
21
|
const role_repository_1 = require("../infra/repositories/role.repository");
|
|
22
22
|
const scope_repository_1 = require("../infra/repositories/scope.repository");
|
|
23
23
|
const user_repository_1 = require("../../users/infra/repositories/user.repository");
|
|
24
|
+
const isEnabled = (row) => row.isActive !== false;
|
|
24
25
|
let RbacService = class RbacService {
|
|
25
26
|
constructor(resourceRepo, actionRepo, scopeRepo, permissionRepo, roleRepo, groupRepo, userRepo, events) {
|
|
26
27
|
this.resourceRepo = resourceRepo;
|
|
@@ -45,9 +46,16 @@ let RbacService = class RbacService {
|
|
|
45
46
|
return [];
|
|
46
47
|
}
|
|
47
48
|
const codes = new Set();
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const addFrom = (permissions) => {
|
|
50
|
+
permissions
|
|
51
|
+
?.filter((p) => isEnabled(p))
|
|
52
|
+
.forEach((p) => codes.add(p.code));
|
|
53
|
+
};
|
|
54
|
+
addFrom(user.directPermissions);
|
|
55
|
+
user.roles?.filter(isEnabled).forEach((r) => addFrom(r.permissions));
|
|
56
|
+
user.groups
|
|
57
|
+
?.filter(isEnabled)
|
|
58
|
+
.forEach((g) => g.roles?.filter(isEnabled).forEach((r) => addFrom(r.permissions)));
|
|
51
59
|
return [...codes];
|
|
52
60
|
}
|
|
53
61
|
async getUserRoleNames(userId) {
|
|
@@ -276,7 +284,7 @@ let RbacService = class RbacService {
|
|
|
276
284
|
}
|
|
277
285
|
return role;
|
|
278
286
|
}
|
|
279
|
-
async createRole(dto) {
|
|
287
|
+
async createRole(dto, actorPermissions) {
|
|
280
288
|
const exists = await this.roleRepo.findOne({
|
|
281
289
|
where: { name: dto.name },
|
|
282
290
|
withDeleted: true,
|
|
@@ -287,6 +295,7 @@ let RbacService = class RbacService {
|
|
|
287
295
|
const permissions = dto.permissionIds?.length
|
|
288
296
|
? await this.permissionRepo.findBy({ id: (0, typeorm_1.In)(dto.permissionIds) })
|
|
289
297
|
: [];
|
|
298
|
+
this.assertGrantableByActor(permissions, actorPermissions);
|
|
290
299
|
const role = this.roleRepo.create({
|
|
291
300
|
name: dto.name,
|
|
292
301
|
description: dto.description,
|
|
@@ -440,22 +449,25 @@ let RbacService = class RbacService {
|
|
|
440
449
|
}
|
|
441
450
|
return group;
|
|
442
451
|
}
|
|
443
|
-
async createGroup(dto) {
|
|
444
|
-
const roles = dto.roleIds
|
|
445
|
-
|
|
446
|
-
: [];
|
|
452
|
+
async createGroup(dto, actorPermissions) {
|
|
453
|
+
const roles = await this.resolveGrantableRoles(dto.roleIds, actorPermissions);
|
|
454
|
+
await this.assertParentIsValid(null, dto.parentId ?? null);
|
|
447
455
|
const group = this.groupRepo.create({
|
|
448
456
|
name: dto.name,
|
|
449
457
|
description: dto.description,
|
|
450
458
|
type: dto.type ?? "team",
|
|
451
459
|
parentId: dto.parentId ?? null,
|
|
452
460
|
managerId: dto.managerId ?? null,
|
|
453
|
-
roles,
|
|
461
|
+
roles: roles ?? [],
|
|
454
462
|
});
|
|
455
463
|
return this.groupRepo.save(group);
|
|
456
464
|
}
|
|
457
|
-
async updateGroup(id, dto) {
|
|
465
|
+
async updateGroup(id, dto, actorPermissions) {
|
|
458
466
|
const group = await this.getGroup(id);
|
|
467
|
+
const roles = await this.resolveGrantableRoles(dto.roleIds, actorPermissions);
|
|
468
|
+
if (dto.parentId !== undefined) {
|
|
469
|
+
await this.assertParentIsValid(id, dto.parentId ?? null);
|
|
470
|
+
}
|
|
459
471
|
if (dto.name !== undefined) {
|
|
460
472
|
group.name = dto.name;
|
|
461
473
|
}
|
|
@@ -474,11 +486,43 @@ let RbacService = class RbacService {
|
|
|
474
486
|
if (dto.isActive !== undefined) {
|
|
475
487
|
group.isActive = dto.isActive;
|
|
476
488
|
}
|
|
477
|
-
if (
|
|
478
|
-
group.roles =
|
|
489
|
+
if (roles) {
|
|
490
|
+
group.roles = roles;
|
|
479
491
|
}
|
|
480
492
|
return this.groupRepo.save(group);
|
|
481
493
|
}
|
|
494
|
+
async resolveGrantableRoles(roleIds, actorPermissions) {
|
|
495
|
+
if (!roleIds) {
|
|
496
|
+
return undefined;
|
|
497
|
+
}
|
|
498
|
+
if (roleIds.length === 0) {
|
|
499
|
+
return [];
|
|
500
|
+
}
|
|
501
|
+
const roles = await this.roleRepo.find({
|
|
502
|
+
where: { id: (0, typeorm_1.In)(roleIds) },
|
|
503
|
+
relations: { permissions: true },
|
|
504
|
+
});
|
|
505
|
+
if (roles.length !== roleIds.length) {
|
|
506
|
+
throw new common_1.NotFoundException("Algum dos papéis informados não existe");
|
|
507
|
+
}
|
|
508
|
+
this.assertGrantableByActor(roles.flatMap((role) => role.permissions ?? []), actorPermissions);
|
|
509
|
+
return roles;
|
|
510
|
+
}
|
|
511
|
+
async assertParentIsValid(groupId, parentId) {
|
|
512
|
+
if (!parentId) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (parentId === groupId) {
|
|
516
|
+
throw new common_1.BadRequestException("Um grupo não pode ser pai de si mesmo");
|
|
517
|
+
}
|
|
518
|
+
const ancestorIds = await this.groupRepo.findAncestorIds(parentId);
|
|
519
|
+
if (ancestorIds.length === 0) {
|
|
520
|
+
throw new common_1.NotFoundException("Grupo pai não encontrado");
|
|
521
|
+
}
|
|
522
|
+
if (groupId && ancestorIds.includes(groupId)) {
|
|
523
|
+
throw new common_1.BadRequestException("O grupo pai não pode estar abaixo do próprio grupo");
|
|
524
|
+
}
|
|
525
|
+
}
|
|
482
526
|
async deleteGroup(id) {
|
|
483
527
|
const group = await this.getGroup(id);
|
|
484
528
|
await this.groupRepo.softRemove(group);
|
|
@@ -3,5 +3,6 @@ import { Group } from "../schema/group.schema";
|
|
|
3
3
|
export declare class GroupRepository extends Repository<Group> {
|
|
4
4
|
constructor(dataSource: DataSource);
|
|
5
5
|
findManagedGroupIds(managerId: string): Promise<string[]>;
|
|
6
|
+
findAncestorIds(groupId: string): Promise<string[]>;
|
|
6
7
|
findMemberIds(groupIds: string[]): Promise<string[]>;
|
|
7
8
|
}
|
|
@@ -32,6 +32,21 @@ let GroupRepository = class GroupRepository extends typeorm_1.Repository {
|
|
|
32
32
|
`, [managerId]);
|
|
33
33
|
return rows.map((row) => row.id);
|
|
34
34
|
}
|
|
35
|
+
async findAncestorIds(groupId) {
|
|
36
|
+
const rows = await this.query(`
|
|
37
|
+
WITH RECURSIVE ancestors AS (
|
|
38
|
+
SELECT id, parent_id FROM \`groups\`
|
|
39
|
+
WHERE id = ? AND deleted_at IS NULL
|
|
40
|
+
UNION ALL
|
|
41
|
+
SELECT parent.id, parent.parent_id
|
|
42
|
+
FROM \`groups\` parent
|
|
43
|
+
INNER JOIN ancestors ON ancestors.parent_id = parent.id
|
|
44
|
+
WHERE parent.deleted_at IS NULL
|
|
45
|
+
)
|
|
46
|
+
SELECT id FROM ancestors
|
|
47
|
+
`, [groupId]);
|
|
48
|
+
return rows.map((row) => row.id);
|
|
49
|
+
}
|
|
35
50
|
async findMemberIds(groupIds) {
|
|
36
51
|
if (groupIds.length === 0) {
|
|
37
52
|
return [];
|
|
@@ -41,14 +41,14 @@ export declare class RbacController {
|
|
|
41
41
|
groups(): Promise<Group[]>;
|
|
42
42
|
managedGroups(actor: AuthenticatedUser): Promise<Group[]>;
|
|
43
43
|
group(id: string): Promise<Group>;
|
|
44
|
-
createGroup(dto: CreateGroupCommand): Promise<Group>;
|
|
45
|
-
updateGroup(id: string, dto: UpdateGroupCommand): Promise<Group>;
|
|
44
|
+
createGroup(dto: CreateGroupCommand, actor: AuthenticatedUser): Promise<Group>;
|
|
45
|
+
updateGroup(id: string, dto: UpdateGroupCommand, actor: AuthenticatedUser): Promise<Group>;
|
|
46
46
|
deleteGroup(id: string): Promise<void>;
|
|
47
47
|
addUserToGroup(id: string, userId: string): Promise<void>;
|
|
48
48
|
removeUserFromGroup(id: string, userId: string): Promise<void>;
|
|
49
49
|
roles(): Promise<Role[]>;
|
|
50
50
|
role(id: string): Promise<Role>;
|
|
51
|
-
createRole(dto: CreateRoleCommand): Promise<Role>;
|
|
51
|
+
createRole(dto: CreateRoleCommand, actor: AuthenticatedUser): Promise<Role>;
|
|
52
52
|
updateRole(id: string, dto: UpdateRoleCommand, actor: AuthenticatedUser): Promise<Role>;
|
|
53
53
|
deleteRole(id: string): Promise<void>;
|
|
54
54
|
addPermissionToRole(id: string, permissionId: string, actor: AuthenticatedUser): Promise<Role>;
|
|
@@ -95,11 +95,11 @@ let RbacController = class RbacController {
|
|
|
95
95
|
group(id) {
|
|
96
96
|
return this.rbac.getGroup(id);
|
|
97
97
|
}
|
|
98
|
-
createGroup(dto) {
|
|
99
|
-
return this.rbac.createGroup(dto);
|
|
98
|
+
createGroup(dto, actor) {
|
|
99
|
+
return this.rbac.createGroup(dto, actor.permissions);
|
|
100
100
|
}
|
|
101
|
-
updateGroup(id, dto) {
|
|
102
|
-
return this.rbac.updateGroup(id, dto);
|
|
101
|
+
updateGroup(id, dto, actor) {
|
|
102
|
+
return this.rbac.updateGroup(id, dto, actor.permissions);
|
|
103
103
|
}
|
|
104
104
|
deleteGroup(id) {
|
|
105
105
|
return this.rbac.deleteGroup(id);
|
|
@@ -116,8 +116,8 @@ let RbacController = class RbacController {
|
|
|
116
116
|
role(id) {
|
|
117
117
|
return this.rbac.getRole(id);
|
|
118
118
|
}
|
|
119
|
-
createRole(dto) {
|
|
120
|
-
return this.rbac.createRole(dto);
|
|
119
|
+
createRole(dto, actor) {
|
|
120
|
+
return this.rbac.createRole(dto, actor.permissions);
|
|
121
121
|
}
|
|
122
122
|
updateRole(id, dto, actor) {
|
|
123
123
|
return this.rbac.updateRole(id, dto, actor.permissions);
|
|
@@ -319,8 +319,9 @@ __decorate([
|
|
|
319
319
|
(0, requirePermission_decorator_1.RequirePermission)("groups:create:any"),
|
|
320
320
|
(0, swagger_1.ApiOkResponse)({ type: rbac_response_1.GroupResponse }),
|
|
321
321
|
__param(0, (0, common_1.Body)()),
|
|
322
|
+
__param(1, (0, currentUser_decorator_1.CurrentUser)()),
|
|
322
323
|
__metadata("design:type", Function),
|
|
323
|
-
__metadata("design:paramtypes", [createGroup_command_1.CreateGroupCommand]),
|
|
324
|
+
__metadata("design:paramtypes", [createGroup_command_1.CreateGroupCommand, Object]),
|
|
324
325
|
__metadata("design:returntype", Promise)
|
|
325
326
|
], RbacController.prototype, "createGroup", null);
|
|
326
327
|
__decorate([
|
|
@@ -329,8 +330,9 @@ __decorate([
|
|
|
329
330
|
(0, swagger_1.ApiOkResponse)({ type: rbac_response_1.GroupResponse }),
|
|
330
331
|
__param(0, (0, common_1.Param)("id", common_1.ParseUUIDPipe)),
|
|
331
332
|
__param(1, (0, common_1.Body)()),
|
|
333
|
+
__param(2, (0, currentUser_decorator_1.CurrentUser)()),
|
|
332
334
|
__metadata("design:type", Function),
|
|
333
|
-
__metadata("design:paramtypes", [String, updateGroup_command_1.UpdateGroupCommand]),
|
|
335
|
+
__metadata("design:paramtypes", [String, updateGroup_command_1.UpdateGroupCommand, Object]),
|
|
334
336
|
__metadata("design:returntype", Promise)
|
|
335
337
|
], RbacController.prototype, "updateGroup", null);
|
|
336
338
|
__decorate([
|
|
@@ -386,8 +388,9 @@ __decorate([
|
|
|
386
388
|
(0, requirePermission_decorator_1.RequirePermission)("roles:create:any"),
|
|
387
389
|
(0, swagger_1.ApiOkResponse)({ type: rbac_response_1.RoleResponse }),
|
|
388
390
|
__param(0, (0, common_1.Body)()),
|
|
391
|
+
__param(1, (0, currentUser_decorator_1.CurrentUser)()),
|
|
389
392
|
__metadata("design:type", Function),
|
|
390
|
-
__metadata("design:paramtypes", [createRole_command_1.CreateRoleCommand]),
|
|
393
|
+
__metadata("design:paramtypes", [createRole_command_1.CreateRoleCommand, Object]),
|
|
391
394
|
__metadata("design:returntype", Promise)
|
|
392
395
|
], RbacController.prototype, "createRole", null);
|
|
393
396
|
__decorate([
|
|
@@ -9,14 +9,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
9
9
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.AvatarService = void 0;
|
|
12
|
+
exports.AvatarService = exports.AVATAR_MAX_BYTES = void 0;
|
|
13
13
|
const common_1 = require("@nestjs/common");
|
|
14
14
|
const fs_1 = require("fs");
|
|
15
15
|
const path_1 = require("path");
|
|
16
16
|
const sharp_1 = __importDefault(require("sharp"));
|
|
17
17
|
const UPLOAD_DIR = (0, path_1.join)(process.cwd(), "uploads", "avatars");
|
|
18
18
|
const ALLOWED = ["image/jpeg", "image/png", "image/webp"];
|
|
19
|
-
|
|
19
|
+
exports.AVATAR_MAX_BYTES = 5 * 1024 * 1024;
|
|
20
20
|
const MAGIC_BYTES_CHECK = {
|
|
21
21
|
"image/jpeg": (buf) => buf.length >= 3 && buf[0] === 0xff && buf[1] === 0xd8 && buf[2] === 0xff,
|
|
22
22
|
"image/png": (buf) => buf.length >= 8 &&
|
|
@@ -38,7 +38,7 @@ let AvatarService = class AvatarService {
|
|
|
38
38
|
if (!MAGIC_BYTES_CHECK[file.mimetype]?.(file.buffer)) {
|
|
39
39
|
throw new common_1.BadRequestException("O conteúdo do arquivo não corresponde ao formato declarado");
|
|
40
40
|
}
|
|
41
|
-
if (file.size >
|
|
41
|
+
if (file.size > exports.AVATAR_MAX_BYTES) {
|
|
42
42
|
throw new common_1.BadRequestException("Imagem excede o limite de 5MB");
|
|
43
43
|
}
|
|
44
44
|
await fs_1.promises.mkdir(UPLOAD_DIR, { recursive: true });
|
|
@@ -83,7 +83,7 @@ let UsersController = class UsersController {
|
|
|
83
83
|
}
|
|
84
84
|
async remove(id, current) {
|
|
85
85
|
if (current.id === id) {
|
|
86
|
-
|
|
86
|
+
throw new common_1.BadRequestException("Você não pode excluir a própria conta");
|
|
87
87
|
}
|
|
88
88
|
await this.users.remove(id);
|
|
89
89
|
}
|
|
@@ -120,7 +120,10 @@ __decorate([
|
|
|
120
120
|
(0, common_1.Post)("me/avatar"),
|
|
121
121
|
(0, swagger_1.ApiConsumes)("multipart/form-data"),
|
|
122
122
|
(0, swagger_1.ApiOkResponse)({ type: user_response_1.UserResponse }),
|
|
123
|
-
(0, common_1.UseInterceptors)((0, platform_express_1.FileInterceptor)("file", {
|
|
123
|
+
(0, common_1.UseInterceptors)((0, platform_express_1.FileInterceptor)("file", {
|
|
124
|
+
storage: (0, multer_1.memoryStorage)(),
|
|
125
|
+
limits: { fileSize: avatar_service_1.AVATAR_MAX_BYTES, files: 1 },
|
|
126
|
+
})),
|
|
124
127
|
__param(0, (0, currentUser_decorator_1.CurrentUser)("id")),
|
|
125
128
|
__param(1, (0, common_1.UploadedFile)()),
|
|
126
129
|
__metadata("design:type", Function),
|
package/package.json
CHANGED