@flusys/nestjs-iam 1.1.0-beta → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +285 -115
  2. package/cjs/controllers/action.controller.js +45 -2
  3. package/cjs/controllers/company-action-permission.controller.js +16 -10
  4. package/cjs/controllers/my-permission.controller.js +7 -3
  5. package/cjs/controllers/role-permission.controller.js +35 -17
  6. package/cjs/controllers/role.controller.js +46 -3
  7. package/cjs/controllers/user-action-permission.controller.js +26 -11
  8. package/cjs/dtos/action.dto.js +0 -27
  9. package/cjs/dtos/permission.dto.js +117 -27
  10. package/cjs/dtos/role.dto.js +0 -27
  11. package/cjs/entities/permission-base.entity.js +0 -12
  12. package/cjs/helpers/company-access.helper.js +19 -0
  13. package/cjs/helpers/index.js +1 -1
  14. package/cjs/interfaces/iam-module-options.interface.js +0 -14
  15. package/cjs/interfaces/index.js +0 -1
  16. package/cjs/modules/iam.module.js +50 -102
  17. package/cjs/services/action.service.js +30 -41
  18. package/cjs/services/iam-config.service.js +2 -5
  19. package/cjs/services/{iam-datasource.provider.js → iam-datasource.service.js} +33 -36
  20. package/cjs/services/index.js +1 -1
  21. package/cjs/services/permission-cache.service.js +31 -61
  22. package/cjs/services/permission.service.js +160 -188
  23. package/cjs/services/role.service.js +8 -8
  24. package/cjs/types/logic-node.type.js +0 -24
  25. package/controllers/company-action-permission.controller.d.ts +3 -3
  26. package/controllers/my-permission.controller.d.ts +2 -2
  27. package/controllers/role-permission.controller.d.ts +7 -5
  28. package/controllers/user-action-permission.controller.d.ts +6 -4
  29. package/dtos/action.dto.d.ts +0 -7
  30. package/dtos/permission.dto.d.ts +4 -0
  31. package/dtos/role.dto.d.ts +0 -7
  32. package/entities/permission-base.entity.d.ts +0 -4
  33. package/fesm/controllers/action.controller.js +47 -4
  34. package/fesm/controllers/company-action-permission.controller.js +18 -12
  35. package/fesm/controllers/index.js +1 -1
  36. package/fesm/controllers/my-permission.controller.js +7 -3
  37. package/fesm/controllers/role-permission.controller.js +37 -19
  38. package/fesm/controllers/role.controller.js +45 -2
  39. package/fesm/controllers/user-action-permission.controller.js +28 -13
  40. package/fesm/dtos/action.dto.js +0 -24
  41. package/fesm/dtos/permission.dto.js +117 -29
  42. package/fesm/dtos/role.dto.js +0 -24
  43. package/fesm/entities/permission-base.entity.js +0 -12
  44. package/fesm/helpers/company-access.helper.js +14 -0
  45. package/fesm/helpers/index.js +1 -1
  46. package/fesm/interfaces/iam-module-options.interface.js +3 -1
  47. package/fesm/interfaces/index.js +0 -1
  48. package/fesm/modules/iam.module.js +52 -104
  49. package/fesm/services/action.service.js +32 -43
  50. package/fesm/services/iam-config.service.js +2 -5
  51. package/fesm/services/{iam-datasource.provider.js → iam-datasource.service.js} +31 -34
  52. package/fesm/services/index.js +1 -1
  53. package/fesm/services/permission-cache.service.js +31 -61
  54. package/fesm/services/permission.service.js +161 -189
  55. package/fesm/services/role.service.js +8 -8
  56. package/fesm/types/logic-node.type.js +1 -10
  57. package/helpers/company-access.helper.d.ts +3 -0
  58. package/helpers/index.d.ts +1 -1
  59. package/interfaces/iam-module-options.interface.d.ts +9 -1
  60. package/interfaces/index.d.ts +0 -1
  61. package/modules/iam.module.d.ts +2 -2
  62. package/package.json +3 -3
  63. package/services/action.service.d.ts +6 -4
  64. package/services/iam-config.service.d.ts +2 -2
  65. package/services/{iam-datasource.provider.d.ts → iam-datasource.service.d.ts} +4 -5
  66. package/services/index.d.ts +1 -1
  67. package/services/permission-cache.service.d.ts +4 -6
  68. package/services/permission.service.d.ts +8 -4
  69. package/services/role.service.d.ts +3 -3
  70. package/types/logic-node.type.d.ts +0 -8
  71. package/cjs/helpers/permission-evaluator.helper.js +0 -175
  72. package/cjs/interfaces/iam-module-async-options.interface.js +0 -4
  73. package/fesm/helpers/permission-evaluator.helper.js +0 -165
  74. package/fesm/interfaces/iam-module-async-options.interface.js +0 -3
  75. package/helpers/permission-evaluator.helper.d.ts +0 -26
  76. package/interfaces/iam-module-async-options.interface.d.ts +0 -11
@@ -14,7 +14,7 @@ const _common = require("@nestjs/common");
14
14
  const _typeorm = require("typeorm");
15
15
  const _actionentity = require("../entities/action.entity");
16
16
  const _iamconfigservice = require("./iam-config.service");
17
- const _iamdatasourceprovider = require("./iam-datasource.provider");
17
+ const _iamdatasourceservice = require("./iam-datasource.service");
18
18
  const _permissionservice = require("./permission.service");
19
19
  function _define_property(obj, key, value) {
20
20
  if (key in obj) {
@@ -103,55 +103,33 @@ let ActionService = class ActionService extends _classes.RequestScopedApiService
103
103
  deletedById: entity.deletedById
104
104
  };
105
105
  }
106
- // Custom Methods
107
- /** Get actions available for permission assignment (filtered by company whitelist) */ async getActionsForPermission(user) {
108
- await this.ensureRepositoryInitialized();
106
+ requireUser(user, methodName) {
109
107
  if (!user) {
110
- throw new Error('User is required for getActionsForPermission');
108
+ throw new _common.BadRequestException(`User is required for ${methodName}`);
111
109
  }
112
- const selectFields = [
113
- 'id',
114
- 'code',
115
- 'name',
116
- 'description',
117
- 'actionType',
118
- 'permissionLogic',
119
- 'isActive',
120
- 'parentId',
121
- 'serial'
122
- ];
123
- const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
124
- if (enableCompanyFeature && user.companyId) {
110
+ }
111
+ /** Get actions available for permission assignment (filtered by company whitelist) */ async getActionsForPermission(user) {
112
+ await this.ensureRepositoryInitialized();
113
+ this.requireUser(user, 'getActionsForPermission');
114
+ let whereClause = {};
115
+ if (this.iamConfigService.isCompanyFeatureEnabled() && user.companyId) {
125
116
  const companyActionIds = await this.permissionService.getCompanyActionIds(user.companyId);
126
117
  if (companyActionIds.length === 0) {
127
118
  return [];
128
119
  }
129
- const actions = await this.repository.find({
130
- where: {
131
- id: (0, _typeorm.In)(companyActionIds)
132
- },
133
- select: selectFields
134
- });
135
- return actions.map((action)=>this.convertEntityToResponseDto(action, false));
120
+ whereClause = {
121
+ id: (0, _typeorm.In)(companyActionIds)
122
+ };
136
123
  }
137
124
  const actions = await this.repository.find({
138
- select: selectFields
125
+ where: whereClause,
126
+ select: this.actionSelectFields
139
127
  });
140
128
  return actions.map((action)=>this.convertEntityToResponseDto(action, false));
141
129
  }
142
- /**
143
- * Get actions in hierarchical tree structure
144
- *
145
- * @param user - Logged in user info for company filtering
146
- * @param search - Optional search term (name or code)
147
- * @param isActive - Optional filter by active status
148
- * @param withDeleted - Include deleted actions (default: false)
149
- * @returns Array of root actions with nested children
150
- */ async getActionTree(user, search, isActive, withDeleted = false) {
130
+ /** Get actions in hierarchical tree structure */ async getActionTree(user, search, isActive, withDeleted = false) {
151
131
  await this.ensureRepositoryInitialized();
152
- if (!user) {
153
- throw new Error('User is required for getActionTree');
154
- }
132
+ this.requireUser(user, 'getActionTree');
155
133
  const query = this.repository.createQueryBuilder('action');
156
134
  if (!withDeleted) {
157
135
  query.andWhere('action.deletedAt IS NULL');
@@ -199,7 +177,18 @@ let ActionService = class ActionService extends _classes.RequestScopedApiService
199
177
  return rootNodes;
200
178
  }
201
179
  constructor(cacheManager, utilsService, iamConfigService, dataSourceProvider, permissionService){
202
- 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), this.cacheManager = cacheManager, this.utilsService = utilsService, this.iamConfigService = iamConfigService, this.dataSourceProvider = dataSourceProvider, this.permissionService = permissionService;
180
+ 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
181
+ _define_property(this, "actionSelectFields", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.iamConfigService = iamConfigService, this.dataSourceProvider = dataSourceProvider, this.permissionService = permissionService, this.actionSelectFields = [
182
+ 'id',
183
+ 'code',
184
+ 'name',
185
+ 'description',
186
+ 'actionType',
187
+ 'permissionLogic',
188
+ 'isActive',
189
+ 'parentId',
190
+ 'serial'
191
+ ];
203
192
  }
204
193
  };
205
194
  ActionService = _ts_decorate([
@@ -209,14 +198,14 @@ ActionService = _ts_decorate([
209
198
  _ts_param(0, (0, _common.Inject)('CACHE_INSTANCE')),
210
199
  _ts_param(1, (0, _common.Inject)(_modules.UtilsService)),
211
200
  _ts_param(2, (0, _common.Inject)(_iamconfigservice.IAMConfigService)),
212
- _ts_param(3, (0, _common.Inject)(_iamdatasourceprovider.IAMDataSourceProvider)),
201
+ _ts_param(3, (0, _common.Inject)(_iamdatasourceservice.IAMDataSourceService)),
213
202
  _ts_param(4, (0, _common.Inject)(_permissionservice.PermissionService)),
214
203
  _ts_metadata("design:type", Function),
215
204
  _ts_metadata("design:paramtypes", [
216
205
  typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
217
206
  typeof _modules.UtilsService === "undefined" ? Object : _modules.UtilsService,
218
207
  typeof _iamconfigservice.IAMConfigService === "undefined" ? Object : _iamconfigservice.IAMConfigService,
219
- typeof _iamdatasourceprovider.IAMDataSourceProvider === "undefined" ? Object : _iamdatasourceprovider.IAMDataSourceProvider,
208
+ typeof _iamdatasourceservice.IAMDataSourceService === "undefined" ? Object : _iamdatasourceservice.IAMDataSourceService,
220
209
  typeof _permissionservice.PermissionService === "undefined" ? Object : _permissionservice.PermissionService
221
210
  ])
222
211
  ], ActionService);
@@ -48,12 +48,9 @@ let IAMConfigService = class IAMConfigService {
48
48
  isMultiTenant() {
49
49
  return this.getDatabaseMode() === 'multi-tenant';
50
50
  }
51
- // Company Feature
52
- getEnableCompanyFeature() {
53
- return this.options.bootstrapAppConfig?.enableCompanyFeature ?? false;
54
- }
51
+ // Feature Flags
55
52
  isCompanyFeatureEnabled() {
56
- return this.getEnableCompanyFeature();
53
+ return this.options.bootstrapAppConfig?.enableCompanyFeature ?? false;
57
54
  }
58
55
  // Permission Mode
59
56
  getPermissionMode() {
@@ -2,18 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "IAMDataSourceProvider", {
5
+ Object.defineProperty(exports, "IAMDataSourceService", {
6
6
  enumerable: true,
7
7
  get: function() {
8
- return IAMDataSourceProvider;
8
+ return IAMDataSourceService;
9
9
  }
10
10
  });
11
11
  const _modules = require("@flusys/nestjs-shared/modules");
12
12
  const _common = require("@nestjs/common");
13
13
  const _core = require("@nestjs/core");
14
14
  const _express = require("express");
15
- const _iamconstants = require("../config/iam.constants");
16
- const _iammoduleoptionsinterface = require("../interfaces/iam-module-options.interface");
15
+ const _helpers = require("../helpers");
16
+ const _iamconfigservice = require("./iam-config.service");
17
17
  function _define_property(obj, key, value) {
18
18
  if (key in obj) {
19
19
  Object.defineProperty(obj, key, {
@@ -82,7 +82,7 @@ function _ts_param(paramIndex, decorator) {
82
82
  decorator(target, key, paramIndex);
83
83
  };
84
84
  }
85
- let IAMDataSourceProvider = class IAMDataSourceProvider extends _modules.MultiTenantDataSourceService {
85
+ let IAMDataSourceService = class IAMDataSourceService extends _modules.MultiTenantDataSourceService {
86
86
  // Factory Methods
87
87
  static buildParentOptions(options) {
88
88
  return {
@@ -93,20 +93,17 @@ let IAMDataSourceProvider = class IAMDataSourceProvider extends _modules.MultiTe
93
93
  };
94
94
  }
95
95
  // Feature Flags
96
- getEnableCompanyFeature() {
97
- return this.iamOptions.bootstrapAppConfig?.enableCompanyFeature ?? false;
98
- }
99
96
  getEnableCompanyFeatureForTenant(tenant) {
100
- return tenant?.enableCompanyFeature ?? this.getEnableCompanyFeature();
97
+ return tenant?.enableCompanyFeature ?? this.configService.isCompanyFeatureEnabled();
101
98
  }
102
99
  getEnableCompanyFeatureForCurrentTenant() {
103
100
  return this.getEnableCompanyFeatureForTenant(this.getCurrentTenant() ?? undefined);
104
101
  }
105
102
  // Entity Management
106
103
  async getIAMEntities() {
107
- const { Action, Role, RoleWithCompany, UserIamPermission, UserIamPermissionWithCompany, getIAMEntitiesByConfig } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("../entities")));
104
+ const { getIAMEntitiesByConfig } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("../entities")));
108
105
  const enableCompanyFeature = this.getEnableCompanyFeatureForCurrentTenant();
109
- const permissionMode = this.iamOptions.bootstrapAppConfig?.permissionMode || 'FULL';
106
+ const permissionMode = _helpers.PermissionModeHelper.toString(this.configService.getPermissionMode());
110
107
  return getIAMEntitiesByConfig(enableCompanyFeature, permissionMode);
111
108
  }
112
109
  // Overrides
@@ -115,9 +112,9 @@ let IAMDataSourceProvider = class IAMDataSourceProvider extends _modules.MultiTe
115
112
  return super.createDataSourceFromConfig(config, entities);
116
113
  }
117
114
  async getSingleDataSource() {
118
- if (!IAMDataSourceProvider.singleDataSource) {
119
- if (IAMDataSourceProvider.singleConnectionLock) {
120
- return IAMDataSourceProvider.singleConnectionLock;
115
+ if (!IAMDataSourceService.singleDataSource) {
116
+ if (IAMDataSourceService.singleConnectionLock) {
117
+ return IAMDataSourceService.singleConnectionLock;
121
118
  }
122
119
  const lockPromise = (async ()=>{
123
120
  const config = this.getDefaultDatabaseConfig();
@@ -125,63 +122,63 @@ let IAMDataSourceProvider = class IAMDataSourceProvider extends _modules.MultiTe
125
122
  throw new Error('Default database config is not available');
126
123
  }
127
124
  const ds = await this.createDataSourceFromConfig(config);
128
- IAMDataSourceProvider.singleDataSource = ds;
129
- IAMDataSourceProvider.initialized = true;
125
+ IAMDataSourceService.singleDataSource = ds;
126
+ IAMDataSourceService.initialized = true;
130
127
  return ds;
131
128
  })();
132
- IAMDataSourceProvider.singleConnectionLock = lockPromise;
129
+ IAMDataSourceService.singleConnectionLock = lockPromise;
133
130
  try {
134
131
  return await lockPromise;
135
132
  } finally{
136
- IAMDataSourceProvider.singleConnectionLock = null;
133
+ IAMDataSourceService.singleConnectionLock = null;
137
134
  }
138
135
  }
139
- return IAMDataSourceProvider.singleDataSource;
136
+ return IAMDataSourceService.singleDataSource;
140
137
  }
141
138
  async getOrCreateTenantConnection(tenant) {
142
139
  // Return existing initialized connection from IAM-specific cache
143
- const existing = IAMDataSourceProvider.tenantConnections.get(tenant.id);
140
+ const existing = IAMDataSourceService.tenantConnections.get(tenant.id);
144
141
  if (existing?.isInitialized) {
145
142
  return existing;
146
143
  }
147
144
  // If another request is creating this tenant's connection, wait for it
148
- const pendingConnection = IAMDataSourceProvider.connectionLocks.get(tenant.id);
145
+ const pendingConnection = IAMDataSourceService.connectionLocks.get(tenant.id);
149
146
  if (pendingConnection) {
150
147
  return pendingConnection;
151
148
  }
152
149
  // Create connection with lock to prevent race conditions
153
150
  const config = this.buildTenantDatabaseConfig(tenant);
154
151
  const connectionPromise = this.createDataSourceFromConfig(config);
155
- IAMDataSourceProvider.connectionLocks.set(tenant.id, connectionPromise);
152
+ IAMDataSourceService.connectionLocks.set(tenant.id, connectionPromise);
156
153
  try {
157
154
  const dataSource = await connectionPromise;
158
- IAMDataSourceProvider.tenantConnections.set(tenant.id, dataSource);
155
+ IAMDataSourceService.tenantConnections.set(tenant.id, dataSource);
159
156
  return dataSource;
160
157
  } finally{
161
- IAMDataSourceProvider.connectionLocks.delete(tenant.id);
158
+ IAMDataSourceService.connectionLocks.delete(tenant.id);
162
159
  }
163
160
  }
164
- constructor(iamOptions, request){
165
- super(IAMDataSourceProvider.buildParentOptions(iamOptions), request), _define_property(this, "iamOptions", void 0), _define_property(this, "logger", void 0), this.iamOptions = iamOptions, this.logger = new _common.Logger(IAMDataSourceProvider.name);
161
+ constructor(configService, request){
162
+ super(IAMDataSourceService.buildParentOptions(configService.getOptions()), request), _define_property(this, "configService", void 0), _define_property(this, "logger", void 0), this.configService = configService, this.logger = new _common.Logger(IAMDataSourceService.name);
166
163
  }
167
164
  };
168
165
  // Override parent's static properties to have IAM-specific cache
169
- _define_property(IAMDataSourceProvider, "tenantConnections", new Map());
170
- _define_property(IAMDataSourceProvider, "singleDataSource", null);
171
- _define_property(IAMDataSourceProvider, "tenantsRegistry", new Map());
172
- _define_property(IAMDataSourceProvider, "initialized", false);
173
- _define_property(IAMDataSourceProvider, "connectionLocks", new Map());
174
- _define_property(IAMDataSourceProvider, "singleConnectionLock", null);
175
- IAMDataSourceProvider = _ts_decorate([
166
+ _define_property(IAMDataSourceService, "tenantConnections", new Map());
167
+ _define_property(IAMDataSourceService, "singleDataSource", null);
168
+ _define_property(IAMDataSourceService, "tenantsRegistry", new Map());
169
+ _define_property(IAMDataSourceService, "initialized", false);
170
+ _define_property(IAMDataSourceService, "connectionLocks", new Map());
171
+ _define_property(IAMDataSourceService, "singleConnectionLock", null);
172
+ IAMDataSourceService = _ts_decorate([
176
173
  (0, _common.Injectable)({
177
174
  scope: _common.Scope.REQUEST
178
175
  }),
179
- _ts_param(0, (0, _common.Inject)(_iamconstants.IAM_MODULE_OPTIONS)),
176
+ _ts_param(0, (0, _common.Inject)(_iamconfigservice.IAMConfigService)),
180
177
  _ts_param(1, (0, _common.Optional)()),
181
178
  _ts_param(1, (0, _common.Inject)(_core.REQUEST)),
182
179
  _ts_metadata("design:type", Function),
183
180
  _ts_metadata("design:paramtypes", [
184
- typeof _iammoduleoptionsinterface.IAMModuleOptions === "undefined" ? Object : _iammoduleoptionsinterface.IAMModuleOptions,
181
+ typeof _iamconfigservice.IAMConfigService === "undefined" ? Object : _iamconfigservice.IAMConfigService,
185
182
  typeof _express.Request === "undefined" ? Object : _express.Request
186
183
  ])
187
- ], IAMDataSourceProvider);
184
+ ], IAMDataSourceService);
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  _export_star(require("./action.service"), exports);
6
6
  _export_star(require("./iam-config.service"), exports);
7
- _export_star(require("./iam-datasource.provider"), exports);
7
+ _export_star(require("./iam-datasource.service"), exports);
8
8
  _export_star(require("./permission-cache.service"), exports);
9
9
  _export_star(require("./permission.service"), exports);
10
10
  _export_star(require("./role.service"), exports);
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "PermissionCacheService", {
9
9
  }
10
10
  });
11
11
  const _nestjsshared = require("@flusys/nestjs-shared");
12
+ const _utils = require("@flusys/nestjs-shared/utils");
12
13
  const _common = require("@nestjs/common");
13
14
  function _define_property(obj, key, value) {
14
15
  if (key in obj) {
@@ -40,18 +41,17 @@ function _ts_param(paramIndex, decorator) {
40
41
  let PermissionCacheService = class PermissionCacheService {
41
42
  // Cache Key Generation
42
43
  generateCacheKey(options) {
43
- const { userId, companyId, branchId, enableCompanyFeature } = options;
44
- if (enableCompanyFeature && companyId) {
45
- return `${this.CACHE_PREFIX}:company:${companyId}:branch:${branchId || 'null'}:user:${userId}`;
46
- }
47
- return `${this.CACHE_PREFIX}:user:${userId}`;
44
+ return this.buildCacheKey(this.CACHE_PREFIX, options);
48
45
  }
49
46
  generateMyPermissionsCacheKey(options) {
47
+ return this.buildCacheKey(this.MY_PERMISSIONS_PREFIX, options);
48
+ }
49
+ buildCacheKey(prefix, options) {
50
50
  const { userId, companyId, branchId, enableCompanyFeature } = options;
51
51
  if (enableCompanyFeature && companyId) {
52
- return `${this.MY_PERMISSIONS_PREFIX}:company:${companyId}:branch:${branchId || 'null'}:user:${userId}`;
52
+ return `${prefix}:company:${companyId}:branch:${branchId || 'null'}:user:${userId}`;
53
53
  }
54
- return `${this.MY_PERMISSIONS_PREFIX}:user:${userId}`;
54
+ return `${prefix}:user:${userId}`;
55
55
  }
56
56
  // Cache Operations
57
57
  async setPermissions(options, permissions) {
@@ -60,20 +60,11 @@ let PermissionCacheService = class PermissionCacheService {
60
60
  await this.cacheManager.set(key, permissions, this.TTL);
61
61
  this.logger.debug(`Cached ${permissions.length} permissions for key: ${key}`);
62
62
  } catch (error) {
63
- this.logger.error(`Failed to cache permissions: ${error}`);
63
+ const errorMessage = _utils.ErrorHandler.getErrorMessage(error);
64
+ this.logger.error(`Failed to cache permissions: ${errorMessage}`);
64
65
  // Don't throw - cache failure shouldn't break the operation
65
66
  }
66
67
  }
67
- async getPermissions(options) {
68
- try {
69
- const key = this.generateCacheKey(options);
70
- const result = await this.cacheManager.get(key);
71
- return result || null;
72
- } catch (error) {
73
- this.logger.error(`Failed to get permissions from cache: ${error}`);
74
- return null;
75
- }
76
- }
77
68
  // My-Permissions Cache Operations
78
69
  async setMyPermissions(options, data) {
79
70
  try {
@@ -81,7 +72,8 @@ let PermissionCacheService = class PermissionCacheService {
81
72
  await this.cacheManager.set(key, data, this.TTL);
82
73
  this.logger.debug(`Cached my-permissions for key: ${key} (${data.frontendActions.length} frontend, ${data.backendCodes.length} backend)`);
83
74
  } catch (error) {
84
- this.logger.error(`Failed to cache my-permissions: ${error}`);
75
+ const errorMessage = _utils.ErrorHandler.getErrorMessage(error);
76
+ this.logger.error(`Failed to cache my-permissions: ${errorMessage}`);
85
77
  }
86
78
  }
87
79
  async getMyPermissions(options) {
@@ -93,28 +85,35 @@ let PermissionCacheService = class PermissionCacheService {
93
85
  }
94
86
  return result || null;
95
87
  } catch (error) {
96
- this.logger.error(`Failed to get my-permissions from cache: ${error}`);
88
+ const errorMessage = _utils.ErrorHandler.getErrorMessage(error);
89
+ this.logger.error(`Failed to get my-permissions from cache: ${errorMessage}`);
97
90
  return null;
98
91
  }
99
92
  }
100
- // Action Code Cache Operations
101
- async setActionCodeMap(codeToIdMap) {
93
+ // Action Code Cache Operations (tenant-aware for multi-tenant mode)
94
+ /** Generate tenant-aware cache key for action codes */ generateActionCodeCacheKey(tenantId) {
95
+ if (tenantId) {
96
+ return `${this.ACTION_CODE_PREFIX}:tenant:${tenantId}:map`;
97
+ }
98
+ return `${this.ACTION_CODE_PREFIX}:map`;
99
+ }
100
+ async setActionCodeMap(codeToIdMap, tenantId) {
102
101
  try {
103
- const key = `${this.ACTION_CODE_PREFIX}:map`;
102
+ const key = this.generateActionCodeCacheKey(tenantId);
104
103
  await this.cacheManager.set(key, codeToIdMap, this.ACTION_CODE_TTL);
105
- this.logger.debug(`Cached ${Object.keys(codeToIdMap).length} action code mappings`);
104
+ this.logger.debug(`Cached ${Object.keys(codeToIdMap).length} action code mappings${tenantId ? ` for tenant ${tenantId}` : ''}`);
106
105
  } catch (error) {
107
- this.logger.error(`Failed to cache action code map: ${error}`);
106
+ const errorMessage = _utils.ErrorHandler.getErrorMessage(error);
107
+ this.logger.error(`Failed to cache action code map: ${errorMessage}`);
108
108
  }
109
109
  }
110
- async getActionIdsByCodes(codes) {
110
+ async getActionIdsByCodes(codes, tenantId) {
111
111
  try {
112
- const key = `${this.ACTION_CODE_PREFIX}:map`;
112
+ const key = this.generateActionCodeCacheKey(tenantId);
113
113
  const fullMap = await this.cacheManager.get(key);
114
114
  if (!fullMap) {
115
115
  return null;
116
116
  }
117
- // Return only requested codes
118
117
  const result = {};
119
118
  for (const code of codes){
120
119
  if (fullMap[code]) {
@@ -123,19 +122,11 @@ let PermissionCacheService = class PermissionCacheService {
123
122
  }
124
123
  return Object.keys(result).length > 0 ? result : null;
125
124
  } catch (error) {
126
- this.logger.error(`Failed to get action IDs from cache: ${error}`);
125
+ const errorMessage = _utils.ErrorHandler.getErrorMessage(error);
126
+ this.logger.error(`Failed to get action IDs from cache: ${errorMessage}`);
127
127
  return null;
128
128
  }
129
129
  }
130
- async invalidateActionCodeCache() {
131
- try {
132
- const key = `${this.ACTION_CODE_PREFIX}:map`;
133
- await this.cacheManager.del(key);
134
- this.logger.debug('Invalidated action code cache');
135
- } catch (error) {
136
- this.logger.warn(`Failed to invalidate action code cache: ${error}`);
137
- }
138
- }
139
130
  // Cache Invalidation
140
131
  async invalidateUser(userId, companyId, branchIds) {
141
132
  try {
@@ -145,10 +136,7 @@ let PermissionCacheService = class PermissionCacheService {
145
136
  // My-permissions cache (full response) - user-based key
146
137
  `${this.MY_PERMISSIONS_PREFIX}:user:${userId}`
147
138
  ];
148
- // Add company-based keys if companyId provided
149
139
  if (companyId) {
150
- // If branchIds provided, invalidate all specified branches
151
- // Otherwise, invalidate only null branch (company-wide)
152
140
  const branches = branchIds?.length ? branchIds : [
153
141
  null
154
142
  ];
@@ -156,18 +144,17 @@ let PermissionCacheService = class PermissionCacheService {
156
144
  keysToDelete.push(`${this.CACHE_PREFIX}:company:${companyId}:branch:${branchId || 'null'}:user:${userId}`, `${this.MY_PERMISSIONS_PREFIX}:company:${companyId}:branch:${branchId || 'null'}:user:${userId}`);
157
145
  }
158
146
  }
159
- // Parallel deletion for better performance
160
147
  await Promise.all(keysToDelete.map((key)=>this.cacheManager.del(key)));
161
148
  this.logger.debug(`Invalidated ${keysToDelete.length} cache keys for user ${userId}`);
162
149
  } catch (error) {
163
- this.logger.warn(`Failed to invalidate user cache for ${userId}: ${error}`);
150
+ const errorMessage = _utils.ErrorHandler.getErrorMessage(error);
151
+ this.logger.warn(`Failed to invalidate user cache for ${userId}: ${errorMessage}`);
164
152
  }
165
153
  }
166
154
  async invalidateUsers(userIds, companyId, branchIds) {
167
155
  if (userIds.length === 0) {
168
156
  return 0;
169
157
  }
170
- // Parallel invalidation for better performance
171
158
  const results = await Promise.allSettled(userIds.map((userId)=>this.invalidateUser(userId, companyId, branchIds)));
172
159
  const successCount = results.filter((r)=>r.status === 'fulfilled').length;
173
160
  const failedCount = results.filter((r)=>r.status === 'rejected').length;
@@ -179,13 +166,6 @@ let PermissionCacheService = class PermissionCacheService {
179
166
  }
180
167
  return successCount;
181
168
  }
182
- /** Invalidate cache for all users in company (requires userIds via invalidateUsers) */ async invalidateCompany(companyId) {
183
- // Note: HybridCache doesn't support pattern matching (keys() method)
184
- // Company-wide invalidation requires passing individual user IDs
185
- // This is a placeholder that logs a warning
186
- this.logger.warn(`invalidateCompany called for ${companyId}, but pattern matching is not supported. ` + `Use invalidateUsers() with specific user IDs instead.`);
187
- return 0;
188
- }
189
169
  async invalidateRole(roleId, userIds, companyId, branchIds) {
190
170
  if (userIds.length === 0) {
191
171
  this.logger.debug(`No users found for role ${roleId}`);
@@ -197,16 +177,6 @@ let PermissionCacheService = class PermissionCacheService {
197
177
  }
198
178
  return count;
199
179
  }
200
- // Administrative Operations
201
- /** Clear all permission caches (memory and redis) */ async clearAll() {
202
- try {
203
- await this.cacheManager.reset(); // Clear memory cache
204
- await this.cacheManager.resetL2(); // Clear redis cache
205
- this.logger.warn('Cleared all cache entries (memory and redis)');
206
- } catch (error) {
207
- this.logger.error(`Failed to clear all caches: ${error}`);
208
- }
209
- }
210
180
  constructor(cacheManager){
211
181
  _define_property(this, "cacheManager", void 0);
212
182
  _define_property(this, "logger", void 0);