@flusys/nestjs-iam 3.0.0 → 4.0.0-rc

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/cjs/config/index.js +1 -0
  3. package/cjs/config/message-keys.js +102 -0
  4. package/cjs/controllers/action.controller.js +4 -0
  5. package/cjs/controllers/company-action-permission.controller.js +2 -0
  6. package/cjs/controllers/my-permission.controller.js +2 -0
  7. package/cjs/controllers/role-permission.controller.js +5 -2
  8. package/cjs/controllers/role.controller.js +1 -0
  9. package/cjs/controllers/user-action-permission.controller.js +4 -2
  10. package/cjs/dtos/permission.dto.js +8 -0
  11. package/cjs/helpers/company-access.helper.js +6 -2
  12. package/cjs/services/action.service.js +9 -2
  13. package/cjs/services/iam-datasource.service.js +7 -3
  14. package/cjs/services/permission-cache.service.js +97 -71
  15. package/cjs/services/permission.service.js +72 -12
  16. package/cjs/services/role.service.js +1 -1
  17. package/config/index.d.ts +1 -0
  18. package/config/message-keys.d.ts +106 -0
  19. package/dtos/permission.dto.d.ts +1 -0
  20. package/fesm/config/index.js +1 -0
  21. package/fesm/config/message-keys.js +64 -0
  22. package/fesm/controllers/action.controller.js +4 -0
  23. package/fesm/controllers/company-action-permission.controller.js +2 -0
  24. package/fesm/controllers/my-permission.controller.js +2 -0
  25. package/fesm/controllers/role-permission.controller.js +5 -2
  26. package/fesm/controllers/role.controller.js +1 -0
  27. package/fesm/controllers/user-action-permission.controller.js +4 -2
  28. package/fesm/dtos/permission.dto.js +8 -0
  29. package/fesm/helpers/company-access.helper.js +6 -2
  30. package/fesm/services/action.service.js +9 -2
  31. package/fesm/services/iam-datasource.service.js +8 -4
  32. package/fesm/services/permission-cache.service.js +99 -73
  33. package/fesm/services/permission.service.js +74 -14
  34. package/fesm/services/role.service.js +1 -1
  35. package/helpers/company-access.helper.d.ts +1 -1
  36. package/package.json +3 -3
  37. package/services/iam-datasource.service.d.ts +0 -2
  38. package/services/permission-cache.service.d.ts +1 -2
  39. package/services/permission.service.d.ts +0 -1
@@ -8,6 +8,8 @@ Object.defineProperty(exports, "PermissionService", {
8
8
  return PermissionService;
9
9
  }
10
10
  });
11
+ const _config = require("../config");
12
+ const _nestjsshared = require("@flusys/nestjs-shared");
11
13
  const _common = require("@nestjs/common");
12
14
  const _typeorm = require("typeorm");
13
15
  const _permissiondto = require("../dtos/permission.dto");
@@ -66,7 +68,10 @@ let PermissionService = class PermissionService {
66
68
  // User-Action Permissions
67
69
  async assignUserActions(dto) {
68
70
  if (!this.iamConfigService.isDirectPermissionEnabled()) {
69
- throw new _common.BadRequestException('Direct permission assignment not available in RBAC-only mode. Use role-based permissions instead.');
71
+ throw new _common.BadRequestException({
72
+ message: 'Direct permission assignment not available in RBAC-only mode. Use role-based permissions instead.',
73
+ messageKey: _config.IAM_MODE_MESSAGES.DIRECT_MODE_UNAVAILABLE
74
+ });
70
75
  }
71
76
  const permissionRepo = await this.getPermissionRepository();
72
77
  const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
@@ -111,7 +116,10 @@ let PermissionService = class PermissionService {
111
116
  added = newPermissions.length;
112
117
  } catch (error) {
113
118
  if (error?.code === 'ER_DUP_ENTRY' || error?.message?.includes('Duplicate entry')) {
114
- throw new _common.ConflictException('Some permissions already exist for this user. Please refresh and try again.');
119
+ throw new _common.ConflictException({
120
+ message: 'Some permissions already exist for this user. Please refresh and try again.',
121
+ messageKey: _config.PERMISSION_OPERATION_MESSAGES.ALREADY_EXISTS
122
+ });
115
123
  }
116
124
  throw error;
117
125
  }
@@ -182,7 +190,10 @@ let PermissionService = class PermissionService {
182
190
  // Role-Action Permissions
183
191
  async assignRoleActions(dto) {
184
192
  if (!this.iamConfigService.isRbacEnabled()) {
185
- throw new _common.BadRequestException('Role-based permission assignment not available in DIRECT-only mode. Use direct user permissions instead.');
193
+ throw new _common.BadRequestException({
194
+ message: 'Role-based permission assignment not available in DIRECT-only mode. Use direct user permissions instead.',
195
+ messageKey: _config.IAM_MODE_MESSAGES.RBAC_MODE_UNAVAILABLE
196
+ });
186
197
  }
187
198
  const permissionRepo = await this.getPermissionRepository();
188
199
  const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
@@ -234,7 +245,10 @@ let PermissionService = class PermissionService {
234
245
  added = newPermissions.length;
235
246
  } catch (error) {
236
247
  if (error?.code === 'ER_DUP_ENTRY' || error?.message?.includes('Duplicate entry')) {
237
- throw new _common.ConflictException('Some role-action permissions already exist. Please refresh and try again.');
248
+ throw new _common.ConflictException({
249
+ message: 'Some role-action permissions already exist. Please refresh and try again.',
250
+ messageKey: _config.PERMISSION_OPERATION_MESSAGES.ALREADY_EXISTS
251
+ });
238
252
  }
239
253
  throw error;
240
254
  }
@@ -388,9 +402,6 @@ let PermissionService = class PermissionService {
388
402
  });
389
403
  removedUserActions = userResult.affected || 0;
390
404
  }
391
- if (removedRoleActions > 0 || removedUserActions > 0) {
392
- this.logger.log(`Cascade deleted for company ${companyId}: ${removedRoleActions} role actions, ${removedUserActions} user actions`);
393
- }
394
405
  return {
395
406
  removedCompanyActions: companyResult.affected || 0,
396
407
  removedRoleActions,
@@ -449,7 +460,10 @@ let PermissionService = class PermissionService {
449
460
  // User-Role Permissions
450
461
  /** Assign user to roles (branch-scoped when company feature is enabled) */ async assignUserRoles(dto) {
451
462
  if (!this.iamConfigService.isRbacEnabled()) {
452
- throw new _common.BadRequestException('Role assignment not available in DIRECT-only mode. Use direct user permissions instead.');
463
+ throw new _common.BadRequestException({
464
+ message: 'Role assignment not available in DIRECT-only mode. Use direct user permissions instead.',
465
+ messageKey: _config.IAM_MODE_MESSAGES.ROLE_ASSIGNMENT_UNAVAILABLE
466
+ });
453
467
  }
454
468
  const permissionRepo = await this.getPermissionRepository();
455
469
  const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
@@ -494,7 +508,10 @@ let PermissionService = class PermissionService {
494
508
  added = newPermissions.length;
495
509
  } catch (error) {
496
510
  if (error?.code === 'ER_DUP_ENTRY' || error?.message?.includes('Duplicate entry')) {
497
- throw new _common.ConflictException('Some user-role permissions already exist. Please refresh and try again.');
511
+ throw new _common.ConflictException({
512
+ message: 'Some user-role permissions already exist. Please refresh and try again.',
513
+ messageKey: _config.PERMISSION_OPERATION_MESSAGES.ALREADY_EXISTS
514
+ });
498
515
  }
499
516
  throw error;
500
517
  }
@@ -720,7 +737,8 @@ let PermissionService = class PermissionService {
720
737
  success: true,
721
738
  added,
722
739
  removed,
723
- message: `Successfully processed ${totalItems} items: ${added} added, ${removed} removed${additionalMessage}`
740
+ message: `Successfully processed ${totalItems} items: ${added} added, ${removed} removed${additionalMessage}`,
741
+ messageKey: _config.PERMISSION_OPERATION_MESSAGES.PROCESS_SUCCESS
724
742
  };
725
743
  }
726
744
  /** Get role IDs assigned to a user (merges company-wide + branch-specific roles) */ async getUserRoleIds(userId, branchId, companyId) {
@@ -897,13 +915,55 @@ let PermissionService = class PermissionService {
897
915
  _define_property(this, "permissionCacheService", void 0);
898
916
  _define_property(this, "iamConfigService", void 0);
899
917
  _define_property(this, "dataSourceProvider", void 0);
900
- _define_property(this, "logger", void 0);
901
918
  this.permissionCacheService = permissionCacheService;
902
919
  this.iamConfigService = iamConfigService;
903
920
  this.dataSourceProvider = dataSourceProvider;
904
- this.logger = new _common.Logger(PermissionService.name);
905
921
  }
906
922
  };
923
+ _ts_decorate([
924
+ (0, _nestjsshared.LogAction)({
925
+ action: 'iam.assignUserActions',
926
+ module: 'iam'
927
+ }),
928
+ _ts_metadata("design:type", Function),
929
+ _ts_metadata("design:paramtypes", [
930
+ typeof _permissiondto.AssignUserActionsDto === "undefined" ? Object : _permissiondto.AssignUserActionsDto
931
+ ]),
932
+ _ts_metadata("design:returntype", Promise)
933
+ ], PermissionService.prototype, "assignUserActions", null);
934
+ _ts_decorate([
935
+ (0, _nestjsshared.LogAction)({
936
+ action: 'iam.assignRoleActions',
937
+ module: 'iam'
938
+ }),
939
+ _ts_metadata("design:type", Function),
940
+ _ts_metadata("design:paramtypes", [
941
+ typeof _permissiondto.AssignRoleActionsDto === "undefined" ? Object : _permissiondto.AssignRoleActionsDto
942
+ ]),
943
+ _ts_metadata("design:returntype", Promise)
944
+ ], PermissionService.prototype, "assignRoleActions", null);
945
+ _ts_decorate([
946
+ (0, _nestjsshared.LogAction)({
947
+ action: 'iam.assignCompanyActions',
948
+ module: 'iam'
949
+ }),
950
+ _ts_metadata("design:type", Function),
951
+ _ts_metadata("design:paramtypes", [
952
+ typeof _permissiondto.AssignCompanyActionsDto === "undefined" ? Object : _permissiondto.AssignCompanyActionsDto
953
+ ]),
954
+ _ts_metadata("design:returntype", Promise)
955
+ ], PermissionService.prototype, "assignCompanyActions", null);
956
+ _ts_decorate([
957
+ (0, _nestjsshared.LogAction)({
958
+ action: 'iam.assignUserRoles',
959
+ module: 'iam'
960
+ }),
961
+ _ts_metadata("design:type", Function),
962
+ _ts_metadata("design:paramtypes", [
963
+ typeof _permissiondto.AssignUserRolesDto === "undefined" ? Object : _permissiondto.AssignUserRolesDto
964
+ ]),
965
+ _ts_metadata("design:returntype", Promise)
966
+ ], PermissionService.prototype, "assignUserRoles", null);
907
967
  PermissionService = _ts_decorate([
908
968
  (0, _common.Injectable)({
909
969
  scope: _common.Scope.REQUEST
@@ -122,7 +122,7 @@ let RoleService = class RoleService extends _classes.RequestScopedApiService {
122
122
  };
123
123
  }
124
124
  constructor(cacheManager, utilsService, iamConfigService, dataSourceProvider){
125
- super('role', null, cacheManager, utilsService, RoleService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "iamConfigService", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.iamConfigService = iamConfigService, this.dataSourceProvider = dataSourceProvider;
125
+ super('role', null, cacheManager, utilsService, RoleService.name, true, 'iam'), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "iamConfigService", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.iamConfigService = iamConfigService, this.dataSourceProvider = dataSourceProvider;
126
126
  }
127
127
  };
128
128
  RoleService = _ts_decorate([
package/config/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './iam.constants';
2
+ export * from './message-keys';
@@ -0,0 +1,106 @@
1
+ export declare const ACTION_MESSAGES: {
2
+ readonly CREATE_SUCCESS: "action.create.success";
3
+ readonly CREATE_MANY_SUCCESS: "action.create.many.success";
4
+ readonly GET_SUCCESS: "action.get.success";
5
+ readonly GET_ALL_SUCCESS: "action.get.all.success";
6
+ readonly UPDATE_SUCCESS: "action.update.success";
7
+ readonly UPDATE_MANY_SUCCESS: "action.update.many.success";
8
+ readonly DELETE_SUCCESS: "action.delete.success";
9
+ readonly RESTORE_SUCCESS: "action.restore.success";
10
+ readonly NOT_FOUND: "action.not.found";
11
+ };
12
+ export declare const ROLE_MESSAGES: {
13
+ readonly CREATE_SUCCESS: "role.create.success";
14
+ readonly CREATE_MANY_SUCCESS: "role.create.many.success";
15
+ readonly GET_SUCCESS: "role.get.success";
16
+ readonly GET_ALL_SUCCESS: "role.get.all.success";
17
+ readonly UPDATE_SUCCESS: "role.update.success";
18
+ readonly UPDATE_MANY_SUCCESS: "role.update.many.success";
19
+ readonly DELETE_SUCCESS: "role.delete.success";
20
+ readonly RESTORE_SUCCESS: "role.restore.success";
21
+ readonly NOT_FOUND: "role.not.found";
22
+ };
23
+ export declare const ROLE_PERMISSION_MESSAGES: {
24
+ readonly GET_SUCCESS: "role.permission.get.success";
25
+ readonly ASSIGN_SUCCESS: "role.permission.assign.success";
26
+ readonly ACTIONS_SUCCESS: "role.permission.actions.success";
27
+ readonly USERS_SUCCESS: "role.permission.users.success";
28
+ readonly USER_ROLES_SUCCESS: "role.permission.user.roles.success";
29
+ };
30
+ export declare const USER_ACTION_PERMISSION_MESSAGES: {
31
+ readonly GET_SUCCESS: "user.action.permission.get.success";
32
+ readonly ASSIGN_SUCCESS: "user.action.permission.assign.success";
33
+ readonly REVOKE_SUCCESS: "user.action.permission.revoke.success";
34
+ };
35
+ export declare const COMPANY_ACTION_PERMISSION_MESSAGES: {
36
+ readonly GET_SUCCESS: "company.action.permission.get.success";
37
+ readonly ASSIGN_SUCCESS: "company.action.permission.assign.success";
38
+ readonly REVOKE_SUCCESS: "company.action.permission.revoke.success";
39
+ };
40
+ export declare const MY_PERMISSION_MESSAGES: {
41
+ readonly GET_SUCCESS: "my.permission.get.success";
42
+ };
43
+ export declare const IAM_MODE_MESSAGES: {
44
+ readonly DIRECT_MODE_UNAVAILABLE: "iam.direct.mode.unavailable";
45
+ readonly RBAC_MODE_UNAVAILABLE: "iam.rbac.mode.unavailable";
46
+ readonly ROLE_ASSIGNMENT_UNAVAILABLE: "iam.role.assignment.unavailable";
47
+ };
48
+ export declare const PERMISSION_OPERATION_MESSAGES: {
49
+ readonly PROCESS_SUCCESS: "permission.process.success";
50
+ readonly ALREADY_EXISTS: "permission.already.exists";
51
+ readonly USER_REQUIRED: "permission.user.required";
52
+ };
53
+ export declare const IAM_MODULE_MESSAGES: {
54
+ readonly ACTION: {
55
+ readonly CREATE_SUCCESS: "action.create.success";
56
+ readonly CREATE_MANY_SUCCESS: "action.create.many.success";
57
+ readonly GET_SUCCESS: "action.get.success";
58
+ readonly GET_ALL_SUCCESS: "action.get.all.success";
59
+ readonly UPDATE_SUCCESS: "action.update.success";
60
+ readonly UPDATE_MANY_SUCCESS: "action.update.many.success";
61
+ readonly DELETE_SUCCESS: "action.delete.success";
62
+ readonly RESTORE_SUCCESS: "action.restore.success";
63
+ readonly NOT_FOUND: "action.not.found";
64
+ };
65
+ readonly ROLE: {
66
+ readonly CREATE_SUCCESS: "role.create.success";
67
+ readonly CREATE_MANY_SUCCESS: "role.create.many.success";
68
+ readonly GET_SUCCESS: "role.get.success";
69
+ readonly GET_ALL_SUCCESS: "role.get.all.success";
70
+ readonly UPDATE_SUCCESS: "role.update.success";
71
+ readonly UPDATE_MANY_SUCCESS: "role.update.many.success";
72
+ readonly DELETE_SUCCESS: "role.delete.success";
73
+ readonly RESTORE_SUCCESS: "role.restore.success";
74
+ readonly NOT_FOUND: "role.not.found";
75
+ };
76
+ readonly ROLE_PERMISSION: {
77
+ readonly GET_SUCCESS: "role.permission.get.success";
78
+ readonly ASSIGN_SUCCESS: "role.permission.assign.success";
79
+ readonly ACTIONS_SUCCESS: "role.permission.actions.success";
80
+ readonly USERS_SUCCESS: "role.permission.users.success";
81
+ readonly USER_ROLES_SUCCESS: "role.permission.user.roles.success";
82
+ };
83
+ readonly USER_ACTION_PERMISSION: {
84
+ readonly GET_SUCCESS: "user.action.permission.get.success";
85
+ readonly ASSIGN_SUCCESS: "user.action.permission.assign.success";
86
+ readonly REVOKE_SUCCESS: "user.action.permission.revoke.success";
87
+ };
88
+ readonly COMPANY_ACTION_PERMISSION: {
89
+ readonly GET_SUCCESS: "company.action.permission.get.success";
90
+ readonly ASSIGN_SUCCESS: "company.action.permission.assign.success";
91
+ readonly REVOKE_SUCCESS: "company.action.permission.revoke.success";
92
+ };
93
+ readonly MY_PERMISSION: {
94
+ readonly GET_SUCCESS: "my.permission.get.success";
95
+ };
96
+ readonly IAM_MODE: {
97
+ readonly DIRECT_MODE_UNAVAILABLE: "iam.direct.mode.unavailable";
98
+ readonly RBAC_MODE_UNAVAILABLE: "iam.rbac.mode.unavailable";
99
+ readonly ROLE_ASSIGNMENT_UNAVAILABLE: "iam.role.assignment.unavailable";
100
+ };
101
+ readonly PERMISSION_OPERATION: {
102
+ readonly PROCESS_SUCCESS: "permission.process.success";
103
+ readonly ALREADY_EXISTS: "permission.already.exists";
104
+ readonly USER_REQUIRED: "permission.user.required";
105
+ };
106
+ };
@@ -93,4 +93,5 @@ export declare class PermissionOperationResultDto {
93
93
  added: number;
94
94
  removed: number;
95
95
  message: string;
96
+ messageKey?: string;
96
97
  }
@@ -1 +1,2 @@
1
1
  export * from './iam.constants';
2
+ export * from './message-keys';
@@ -0,0 +1,64 @@
1
+ // ==================== IAM MODULE MESSAGE KEYS ====================
2
+ export const ACTION_MESSAGES = {
3
+ CREATE_SUCCESS: 'action.create.success',
4
+ CREATE_MANY_SUCCESS: 'action.create.many.success',
5
+ GET_SUCCESS: 'action.get.success',
6
+ GET_ALL_SUCCESS: 'action.get.all.success',
7
+ UPDATE_SUCCESS: 'action.update.success',
8
+ UPDATE_MANY_SUCCESS: 'action.update.many.success',
9
+ DELETE_SUCCESS: 'action.delete.success',
10
+ RESTORE_SUCCESS: 'action.restore.success',
11
+ NOT_FOUND: 'action.not.found'
12
+ };
13
+ export const ROLE_MESSAGES = {
14
+ CREATE_SUCCESS: 'role.create.success',
15
+ CREATE_MANY_SUCCESS: 'role.create.many.success',
16
+ GET_SUCCESS: 'role.get.success',
17
+ GET_ALL_SUCCESS: 'role.get.all.success',
18
+ UPDATE_SUCCESS: 'role.update.success',
19
+ UPDATE_MANY_SUCCESS: 'role.update.many.success',
20
+ DELETE_SUCCESS: 'role.delete.success',
21
+ RESTORE_SUCCESS: 'role.restore.success',
22
+ NOT_FOUND: 'role.not.found'
23
+ };
24
+ export const ROLE_PERMISSION_MESSAGES = {
25
+ GET_SUCCESS: 'role.permission.get.success',
26
+ ASSIGN_SUCCESS: 'role.permission.assign.success',
27
+ ACTIONS_SUCCESS: 'role.permission.actions.success',
28
+ USERS_SUCCESS: 'role.permission.users.success',
29
+ USER_ROLES_SUCCESS: 'role.permission.user.roles.success'
30
+ };
31
+ export const USER_ACTION_PERMISSION_MESSAGES = {
32
+ GET_SUCCESS: 'user.action.permission.get.success',
33
+ ASSIGN_SUCCESS: 'user.action.permission.assign.success',
34
+ REVOKE_SUCCESS: 'user.action.permission.revoke.success'
35
+ };
36
+ export const COMPANY_ACTION_PERMISSION_MESSAGES = {
37
+ GET_SUCCESS: 'company.action.permission.get.success',
38
+ ASSIGN_SUCCESS: 'company.action.permission.assign.success',
39
+ REVOKE_SUCCESS: 'company.action.permission.revoke.success'
40
+ };
41
+ export const MY_PERMISSION_MESSAGES = {
42
+ GET_SUCCESS: 'my.permission.get.success'
43
+ };
44
+ export const IAM_MODE_MESSAGES = {
45
+ DIRECT_MODE_UNAVAILABLE: 'iam.direct.mode.unavailable',
46
+ RBAC_MODE_UNAVAILABLE: 'iam.rbac.mode.unavailable',
47
+ ROLE_ASSIGNMENT_UNAVAILABLE: 'iam.role.assignment.unavailable'
48
+ };
49
+ export const PERMISSION_OPERATION_MESSAGES = {
50
+ PROCESS_SUCCESS: 'permission.process.success',
51
+ ALREADY_EXISTS: 'permission.already.exists',
52
+ USER_REQUIRED: 'permission.user.required'
53
+ };
54
+ // Aggregated export for backward compatibility
55
+ export const IAM_MODULE_MESSAGES = {
56
+ ACTION: ACTION_MESSAGES,
57
+ ROLE: ROLE_MESSAGES,
58
+ ROLE_PERMISSION: ROLE_PERMISSION_MESSAGES,
59
+ USER_ACTION_PERMISSION: USER_ACTION_PERMISSION_MESSAGES,
60
+ COMPANY_ACTION_PERMISSION: COMPANY_ACTION_PERMISSION_MESSAGES,
61
+ MY_PERMISSION: MY_PERMISSION_MESSAGES,
62
+ IAM_MODE: IAM_MODE_MESSAGES,
63
+ PERMISSION_OPERATION: PERMISSION_OPERATION_MESSAGES
64
+ };
@@ -27,11 +27,13 @@ function _ts_param(paramIndex, decorator) {
27
27
  }
28
28
  import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
29
29
  import { createApiController, CurrentUser, ILoggedUserInfo, SingleResponseDto, ACTION_PERMISSIONS } from '@flusys/nestjs-shared';
30
+ import { ACTION_MESSAGES } from '../config';
30
31
  import { Body, Controller, Inject, Post, UseGuards } from '@nestjs/common';
31
32
  import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
32
33
  import { ActionResponseDto, ActionTreeQueryDto, CreateActionDto, UpdateActionDto } from '../dtos/action.dto';
33
34
  import { ActionService } from '../services/action.service';
34
35
  export class ActionController extends createApiController(CreateActionDto, UpdateActionDto, ActionResponseDto, {
36
+ entityName: 'action',
35
37
  security: {
36
38
  insert: {
37
39
  level: 'permission',
@@ -82,6 +84,7 @@ export class ActionController extends createApiController(CreateActionDto, Updat
82
84
  return {
83
85
  success: true,
84
86
  message: 'Actions retrieved successfully',
87
+ messageKey: ACTION_MESSAGES.GET_ALL_SUCCESS,
85
88
  data: actions
86
89
  };
87
90
  }
@@ -90,6 +93,7 @@ export class ActionController extends createApiController(CreateActionDto, Updat
90
93
  return {
91
94
  success: true,
92
95
  message: 'Action tree retrieved successfully',
96
+ messageKey: ACTION_MESSAGES.GET_ALL_SUCCESS,
93
97
  data: tree
94
98
  };
95
99
  }
@@ -26,6 +26,7 @@ function _ts_param(paramIndex, decorator) {
26
26
  };
27
27
  }
28
28
  import { COMPANY_ACTION_PERMISSIONS, CurrentUser, ILoggedUserInfo, JwtAuthGuard, RequirePermission, SingleResponseDto } from '@flusys/nestjs-shared';
29
+ import { COMPANY_ACTION_PERMISSION_MESSAGES } from '../config';
29
30
  import { Body, Controller, Inject, Post, UseGuards } from '@nestjs/common';
30
31
  import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
31
32
  import { AssignCompanyActionsDto, GetCompanyActionsDto, PermissionOperationResultDto } from '../dtos/permission.dto';
@@ -39,6 +40,7 @@ export class CompanyActionPermissionController {
39
40
  return {
40
41
  success: true,
41
42
  message: 'Company actions retrieved successfully',
43
+ messageKey: COMPANY_ACTION_PERMISSION_MESSAGES.GET_SUCCESS,
42
44
  data: actions
43
45
  };
44
46
  }
@@ -26,6 +26,7 @@ function _ts_param(paramIndex, decorator) {
26
26
  };
27
27
  }
28
28
  import { CurrentUser, ILoggedUserInfo, JwtAuthGuard } from '@flusys/nestjs-shared';
29
+ import { MY_PERMISSION_MESSAGES } from '../config';
29
30
  import { Body, Controller, Inject, Post, UseGuards } from '@nestjs/common';
30
31
  import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
31
32
  import { MyPermissionsQueryDto, MyPermissionsResponseDto } from '../dtos/permission.dto';
@@ -36,6 +37,7 @@ export class MyPermissionController {
36
37
  return {
37
38
  success: true,
38
39
  message: 'Permissions loaded successfully',
40
+ messageKey: MY_PERMISSION_MESSAGES.GET_SUCCESS,
39
41
  data
40
42
  };
41
43
  }
@@ -26,6 +26,7 @@ function _ts_param(paramIndex, decorator) {
26
26
  };
27
27
  }
28
28
  import { JwtAuthGuard, SingleResponseDto, RequirePermission, ROLE_ACTION_PERMISSIONS, USER_ROLE_PERMISSIONS, CurrentUser, ILoggedUserInfo } from '@flusys/nestjs-shared';
29
+ import { ROLE_PERMISSION_MESSAGES } from '../config';
29
30
  import { Body, Controller, Inject, Post, UseGuards } from '@nestjs/common';
30
31
  import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
31
32
  import { AssignRoleActionsDto, AssignUserRolesDto, GetRoleActionsDto, GetUserRolesDto, PermissionOperationResultDto } from '../dtos/permission.dto';
@@ -41,19 +42,21 @@ export class RolePermissionController {
41
42
  return {
42
43
  success: true,
43
44
  message: 'Role actions retrieved successfully',
45
+ messageKey: ROLE_PERMISSION_MESSAGES.ACTIONS_SUCCESS,
44
46
  data: actions
45
47
  };
46
48
  }
47
49
  async assignUserRoles(dto, user) {
48
- validateCompanyAccess(this.config, dto.companyId, user, 'Cannot manage permissions for users in another company');
50
+ validateCompanyAccess(this.config, dto.companyId, user);
49
51
  return this.permissionService.assignUserRoles(dto);
50
52
  }
51
53
  async getUserRoles(dto, user) {
52
- validateCompanyAccess(this.config, dto.companyId, user, 'Cannot manage permissions for users in another company');
54
+ validateCompanyAccess(this.config, dto.companyId, user);
53
55
  const roles = await this.permissionService.getUserRoles(dto.userId, dto.branchId, dto.companyId);
54
56
  return {
55
57
  success: true,
56
58
  message: 'User roles retrieved successfully',
59
+ messageKey: ROLE_PERMISSION_MESSAGES.USER_ROLES_SUCCESS,
57
60
  data: roles
58
61
  };
59
62
  }
@@ -31,6 +31,7 @@ import { ApiTags } from '@nestjs/swagger';
31
31
  import { CreateRoleDto, RoleResponseDto, UpdateRoleDto } from '../dtos/role.dto';
32
32
  import { RoleService } from '../services/role.service';
33
33
  export class RoleController extends createApiController(CreateRoleDto, UpdateRoleDto, RoleResponseDto, {
34
+ entityName: 'role',
34
35
  security: {
35
36
  insert: {
36
37
  level: 'permission',
@@ -26,6 +26,7 @@ function _ts_param(paramIndex, decorator) {
26
26
  };
27
27
  }
28
28
  import { JwtAuthGuard, SingleResponseDto, RequirePermission, USER_ACTION_PERMISSIONS, CurrentUser, ILoggedUserInfo } from '@flusys/nestjs-shared';
29
+ import { USER_ACTION_PERMISSION_MESSAGES } from '../config';
29
30
  import { Body, Controller, Inject, Post, UseGuards } from '@nestjs/common';
30
31
  import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
31
32
  import { AssignUserActionsDto, GetUserActionsDto, PermissionOperationResultDto } from '../dtos/permission.dto';
@@ -34,15 +35,16 @@ import { PermissionService } from '../services/permission.service';
34
35
  import { IAMConfigService } from '../services/iam-config.service';
35
36
  export class UserActionPermissionController {
36
37
  async assignUserActions(dto, user) {
37
- validateCompanyAccess(this.config, dto.companyId, user, 'Cannot manage permissions for users in another company');
38
+ validateCompanyAccess(this.config, dto.companyId, user);
38
39
  return this.permissionService.assignUserActions(dto);
39
40
  }
40
41
  async getUserActions(dto, user) {
41
- validateCompanyAccess(this.config, dto.companyId, user, 'Cannot manage permissions for users in another company');
42
+ validateCompanyAccess(this.config, dto.companyId, user);
42
43
  const actions = await this.permissionService.getUserActions(dto.userId, dto.branchId, dto.companyId);
43
44
  return {
44
45
  success: true,
45
46
  message: 'User actions retrieved successfully',
47
+ messageKey: USER_ACTION_PERMISSION_MESSAGES.GET_SUCCESS,
46
48
  data: actions
47
49
  };
48
50
  }
@@ -550,6 +550,7 @@ export class PermissionOperationResultDto {
550
550
  _define_property(this, "added", void 0);
551
551
  _define_property(this, "removed", void 0);
552
552
  _define_property(this, "message", void 0);
553
+ _define_property(this, "messageKey", void 0);
553
554
  }
554
555
  }
555
556
  _ts_decorate([
@@ -576,3 +577,10 @@ _ts_decorate([
576
577
  }),
577
578
  _ts_metadata("design:type", String)
578
579
  ], PermissionOperationResultDto.prototype, "message", void 0);
580
+ _ts_decorate([
581
+ ApiPropertyOptional({
582
+ description: 'Translation key for localization',
583
+ example: 'permission.process.success'
584
+ }),
585
+ _ts_metadata("design:type", String)
586
+ ], PermissionOperationResultDto.prototype, "messageKey", void 0);
@@ -1,14 +1,18 @@
1
1
  import { ForbiddenException } from '@nestjs/common';
2
+ import { AUTH_MESSAGES } from '@flusys/nestjs-shared/constants';
2
3
  /**
3
4
  * Validates that user has access to the specified company.
4
5
  * Used for user-action and role-permission operations when company feature is enabled.
5
6
  *
6
7
  * @throws ForbiddenException if user doesn't have access to the company
7
- */ export function validateCompanyAccess(config, companyId, user, errorMessage = 'You do not have access to this company') {
8
+ */ export function validateCompanyAccess(config, companyId, user, errorMessage = 'You do not have access to this company', messageKey = AUTH_MESSAGES.COMPANY_NO_ACCESS) {
8
9
  if (!config.isCompanyFeatureEnabled() || !companyId) {
9
10
  return;
10
11
  }
11
12
  if (user.companyId !== companyId) {
12
- throw new ForbiddenException(errorMessage);
13
+ throw new ForbiddenException({
14
+ message: errorMessage,
15
+ messageKey
16
+ });
13
17
  }
14
18
  }
@@ -26,6 +26,7 @@ function _ts_param(paramIndex, decorator) {
26
26
  };
27
27
  }
28
28
  import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
29
+ import { PERMISSION_OPERATION_MESSAGES } from '../config';
29
30
  import { UtilsService } from '@flusys/nestjs-shared/modules';
30
31
  import { BadRequestException, Inject, Injectable, Scope } from '@nestjs/common';
31
32
  import { In } from 'typeorm';
@@ -95,7 +96,13 @@ export class ActionService extends RequestScopedApiService {
95
96
  }
96
97
  requireUser(user, methodName) {
97
98
  if (!user) {
98
- throw new BadRequestException(`User is required for ${methodName}`);
99
+ throw new BadRequestException({
100
+ message: `User is required for ${methodName}`,
101
+ messageKey: PERMISSION_OPERATION_MESSAGES.USER_REQUIRED,
102
+ messageParams: {
103
+ method: methodName
104
+ }
105
+ });
99
106
  }
100
107
  }
101
108
  /** Get actions available for permission assignment (filtered by company whitelist) */ async getActionsForPermission(user) {
@@ -167,7 +174,7 @@ export class ActionService extends RequestScopedApiService {
167
174
  return rootNodes;
168
175
  }
169
176
  constructor(cacheManager, utilsService, iamConfigService, dataSourceProvider, permissionService){
170
- super('action', null, cacheManager, utilsService, ActionService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "iamConfigService", void 0), _define_property(this, "dataSourceProvider", void 0), _define_property(this, "permissionService", void 0), // Custom Methods
177
+ super('action', null, cacheManager, utilsService, ActionService.name, true, 'iam'), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "iamConfigService", void 0), _define_property(this, "dataSourceProvider", void 0), _define_property(this, "permissionService", void 0), // Custom Methods
171
178
  _define_property(this, "actionSelectFields", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.iamConfigService = iamConfigService, this.dataSourceProvider = dataSourceProvider, this.permissionService = permissionService, this.actionSelectFields = [
172
179
  'id',
173
180
  'code',
@@ -26,7 +26,8 @@ function _ts_param(paramIndex, decorator) {
26
26
  };
27
27
  }
28
28
  import { MultiTenantDataSourceService } from '@flusys/nestjs-shared/modules';
29
- import { Inject, Injectable, Logger, Optional, Scope } from '@nestjs/common';
29
+ import { SYSTEM_MESSAGES } from '@flusys/nestjs-shared/constants';
30
+ import { Inject, Injectable, InternalServerErrorException, Optional, Scope } from '@nestjs/common';
30
31
  import { REQUEST } from '@nestjs/core';
31
32
  import { Request } from 'express';
32
33
  import { PermissionModeHelper } from '../helpers';
@@ -58,7 +59,7 @@ export class IAMDataSourceService extends MultiTenantDataSourceService {
58
59
  // Overrides
59
60
  async createDataSourceFromConfig(config) {
60
61
  const entities = await this.getIAMEntities();
61
- return super.createDataSourceFromConfig(config, entities);
62
+ return await super.createDataSourceFromConfig(config, entities);
62
63
  }
63
64
  async getSingleDataSource() {
64
65
  if (!IAMDataSourceService.singleDataSource) {
@@ -68,7 +69,10 @@ export class IAMDataSourceService extends MultiTenantDataSourceService {
68
69
  const lockPromise = (async ()=>{
69
70
  const config = this.getDefaultDatabaseConfig();
70
71
  if (!config) {
71
- throw new Error('Default database config is not available');
72
+ throw new InternalServerErrorException({
73
+ message: 'Default database config is not available',
74
+ messageKey: SYSTEM_MESSAGES.DATABASE_CONFIG_NOT_AVAILABLE
75
+ });
72
76
  }
73
77
  const ds = await this.createDataSourceFromConfig(config);
74
78
  IAMDataSourceService.singleDataSource = ds;
@@ -108,7 +112,7 @@ export class IAMDataSourceService extends MultiTenantDataSourceService {
108
112
  }
109
113
  }
110
114
  constructor(configService, request){
111
- super(IAMDataSourceService.buildParentOptions(configService.getOptions()), request), _define_property(this, "configService", void 0), _define_property(this, "logger", void 0), this.configService = configService, this.logger = new Logger(IAMDataSourceService.name);
115
+ super(IAMDataSourceService.buildParentOptions(configService.getOptions()), request), _define_property(this, "configService", void 0), this.configService = configService;
112
116
  }
113
117
  }
114
118
  // Override parent's static properties to have IAM-specific cache