@flusys/nestjs-iam 7.1.0 → 8.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 (175) hide show
  1. package/config/index.d.ts +3 -3
  2. package/config/message-keys.d.ts +2 -0
  3. package/controllers/action.controller.d.ts +4 -4
  4. package/controllers/company-action-permission.controller.d.ts +2 -2
  5. package/controllers/index.d.ts +6 -6
  6. package/controllers/my-permission.controller.d.ts +3 -3
  7. package/controllers/role-permission.controller.d.ts +5 -4
  8. package/controllers/role.controller.d.ts +2 -2
  9. package/controllers/user-action-permission.controller.d.ts +5 -4
  10. package/docs/iam-swagger.config.d.ts +2 -2
  11. package/docs/index.d.ts +1 -1
  12. package/dtos/action.dto.d.ts +2 -2
  13. package/dtos/index.d.ts +3 -3
  14. package/dtos/permission.dto.d.ts +16 -0
  15. package/entities/action.entity.d.ts +2 -2
  16. package/entities/index.d.ts +11 -11
  17. package/entities/permission-with-company.entity.d.ts +1 -1
  18. package/entities/role-with-company.entity.d.ts +1 -1
  19. package/entities/role.entity.d.ts +1 -1
  20. package/entities/user-iam-permission.entity.d.ts +1 -1
  21. package/enums/index.d.ts +4 -4
  22. package/fesm/284.js +1316 -0
  23. package/fesm/867.js +3801 -0
  24. package/fesm/chunks/364.js +86 -0
  25. package/fesm/config/index.js +135 -3
  26. package/fesm/controllers/index.js +18 -7
  27. package/fesm/docs/index.js +240 -1
  28. package/fesm/dtos/index.js +1168 -3
  29. package/fesm/entities/index.js +670 -31
  30. package/fesm/enums/index.js +97 -4
  31. package/fesm/helpers/index.js +125 -2
  32. package/fesm/index.js +818 -11
  33. package/fesm/interfaces/index.js +17 -3
  34. package/fesm/modules/index.js +259 -1
  35. package/fesm/runtime.js +134 -0
  36. package/fesm/services/index.js +43 -6
  37. package/fesm/types/index.js +15 -1
  38. package/helpers/company-access.helper.d.ts +2 -2
  39. package/helpers/index.d.ts +2 -2
  40. package/helpers/permission-mode.helper.d.ts +1 -1
  41. package/index.d.ts +11 -11
  42. package/interfaces/action.interface.d.ts +2 -2
  43. package/interfaces/iam-module-options.interface.d.ts +3 -3
  44. package/interfaces/index.d.ts +3 -3
  45. package/modules/iam.module.d.ts +2 -2
  46. package/modules/index.d.ts +1 -1
  47. package/package.json +30 -37
  48. package/services/action.service.d.ts +9 -9
  49. package/services/iam-config.service.d.ts +4 -4
  50. package/services/iam-datasource.service.d.ts +3 -3
  51. package/services/index.d.ts +6 -6
  52. package/services/permission-cache.service.d.ts +5 -5
  53. package/services/permission.service.d.ts +6 -4
  54. package/services/role.service.d.ts +8 -8
  55. package/types/index.d.ts +1 -1
  56. package/cjs/config/event-actions.js +0 -36
  57. package/cjs/config/iam.constants.js +0 -11
  58. package/cjs/config/index.js +0 -20
  59. package/cjs/config/message-keys.js +0 -71
  60. package/cjs/controllers/action.controller.js +0 -174
  61. package/cjs/controllers/action.controller.spec.js +0 -79
  62. package/cjs/controllers/company-action-permission.controller.js +0 -119
  63. package/cjs/controllers/company-action-permission.controller.spec.js +0 -65
  64. package/cjs/controllers/index.js +0 -23
  65. package/cjs/controllers/my-permission.controller.js +0 -147
  66. package/cjs/controllers/my-permission.controller.spec.js +0 -128
  67. package/cjs/controllers/role-permission.controller.js +0 -191
  68. package/cjs/controllers/role-permission.controller.spec.js +0 -140
  69. package/cjs/controllers/role.controller.js +0 -102
  70. package/cjs/controllers/role.controller.spec.js +0 -86
  71. package/cjs/controllers/user-action-permission.controller.js +0 -129
  72. package/cjs/controllers/user-action-permission.controller.spec.js +0 -68
  73. package/cjs/docs/iam-swagger.config.js +0 -209
  74. package/cjs/docs/iam-swagger.config.spec.js +0 -99
  75. package/cjs/docs/index.js +0 -18
  76. package/cjs/dtos/action.dto.js +0 -282
  77. package/cjs/dtos/index.js +0 -21
  78. package/cjs/dtos/permission.dto.js +0 -637
  79. package/cjs/dtos/role.dto.js +0 -155
  80. package/cjs/entities/action.entity.js +0 -138
  81. package/cjs/entities/index.js +0 -80
  82. package/cjs/entities/index.spec.js +0 -56
  83. package/cjs/entities/permission-base.entity.js +0 -107
  84. package/cjs/entities/permission-with-company.entity.js +0 -100
  85. package/cjs/entities/role-base.entity.js +0 -80
  86. package/cjs/entities/role-with-company.entity.js +0 -55
  87. package/cjs/entities/role.entity.js +0 -25
  88. package/cjs/entities/user-iam-permission.entity.js +0 -43
  89. package/cjs/enums/action-type.enum.js +0 -22
  90. package/cjs/enums/iam-entity-type.enum.js +0 -17
  91. package/cjs/enums/iam-permission-type.enum.js +0 -17
  92. package/cjs/enums/index.js +0 -21
  93. package/cjs/enums/permission-type.enum.js +0 -16
  94. package/cjs/helpers/company-access.helper.js +0 -23
  95. package/cjs/helpers/company-access.helper.spec.js +0 -68
  96. package/cjs/helpers/index.js +0 -19
  97. package/cjs/helpers/permission-mode.helper.js +0 -49
  98. package/cjs/helpers/permission-mode.helper.spec.js +0 -54
  99. package/cjs/index.js +0 -28
  100. package/cjs/interfaces/action.interface.js +0 -4
  101. package/cjs/interfaces/iam-module-options.interface.js +0 -4
  102. package/cjs/interfaces/index.js +0 -20
  103. package/cjs/interfaces/role.interface.js +0 -7
  104. package/cjs/modules/iam.module.js +0 -186
  105. package/cjs/modules/iam.module.spec.js +0 -282
  106. package/cjs/modules/index.js +0 -18
  107. package/cjs/services/action.service.js +0 -337
  108. package/cjs/services/action.service.spec.js +0 -351
  109. package/cjs/services/iam-config.service.js +0 -87
  110. package/cjs/services/iam-config.service.spec.js +0 -110
  111. package/cjs/services/iam-datasource.service.js +0 -129
  112. package/cjs/services/iam-datasource.service.spec.js +0 -110
  113. package/cjs/services/index.js +0 -23
  114. package/cjs/services/permission-cache.service.js +0 -544
  115. package/cjs/services/permission-cache.service.spec.js +0 -718
  116. package/cjs/services/permission.service.js +0 -914
  117. package/cjs/services/permission.service.spec.js +0 -918
  118. package/cjs/services/role.service.js +0 -224
  119. package/cjs/services/role.service.spec.js +0 -347
  120. package/cjs/types/index.js +0 -18
  121. package/cjs/types/logic-node.type.js +0 -30
  122. package/fesm/config/event-actions.js +0 -15
  123. package/fesm/config/iam.constants.js +0 -1
  124. package/fesm/config/message-keys.js +0 -35
  125. package/fesm/controllers/action.controller.js +0 -164
  126. package/fesm/controllers/action.controller.spec.js +0 -75
  127. package/fesm/controllers/company-action-permission.controller.js +0 -109
  128. package/fesm/controllers/company-action-permission.controller.spec.js +0 -61
  129. package/fesm/controllers/my-permission.controller.js +0 -137
  130. package/fesm/controllers/my-permission.controller.spec.js +0 -124
  131. package/fesm/controllers/role-permission.controller.js +0 -181
  132. package/fesm/controllers/role-permission.controller.spec.js +0 -136
  133. package/fesm/controllers/role.controller.js +0 -92
  134. package/fesm/controllers/role.controller.spec.js +0 -82
  135. package/fesm/controllers/user-action-permission.controller.js +0 -119
  136. package/fesm/controllers/user-action-permission.controller.spec.js +0 -64
  137. package/fesm/docs/iam-swagger.config.js +0 -199
  138. package/fesm/docs/iam-swagger.config.spec.js +0 -95
  139. package/fesm/dtos/action.dto.js +0 -252
  140. package/fesm/dtos/permission.dto.js +0 -571
  141. package/fesm/dtos/role.dto.js +0 -134
  142. package/fesm/entities/action.entity.js +0 -128
  143. package/fesm/entities/index.spec.js +0 -52
  144. package/fesm/entities/permission-base.entity.js +0 -100
  145. package/fesm/entities/permission-with-company.entity.js +0 -90
  146. package/fesm/entities/role-base.entity.js +0 -70
  147. package/fesm/entities/role-with-company.entity.js +0 -45
  148. package/fesm/entities/role.entity.js +0 -15
  149. package/fesm/entities/user-iam-permission.entity.js +0 -33
  150. package/fesm/enums/action-type.enum.js +0 -12
  151. package/fesm/enums/iam-entity-type.enum.js +0 -7
  152. package/fesm/enums/iam-permission-type.enum.js +0 -7
  153. package/fesm/enums/permission-type.enum.js +0 -6
  154. package/fesm/helpers/company-access.helper.js +0 -18
  155. package/fesm/helpers/company-access.helper.spec.js +0 -64
  156. package/fesm/helpers/permission-mode.helper.js +0 -49
  157. package/fesm/helpers/permission-mode.helper.spec.js +0 -50
  158. package/fesm/interfaces/action.interface.js +0 -3
  159. package/fesm/interfaces/iam-module-options.interface.js +0 -3
  160. package/fesm/interfaces/role.interface.js +0 -4
  161. package/fesm/modules/iam.module.js +0 -176
  162. package/fesm/modules/iam.module.spec.js +0 -278
  163. package/fesm/services/action.service.js +0 -327
  164. package/fesm/services/action.service.spec.js +0 -347
  165. package/fesm/services/iam-config.service.js +0 -77
  166. package/fesm/services/iam-config.service.spec.js +0 -106
  167. package/fesm/services/iam-datasource.service.js +0 -78
  168. package/fesm/services/iam-datasource.service.spec.js +0 -106
  169. package/fesm/services/permission-cache.service.js +0 -527
  170. package/fesm/services/permission-cache.service.spec.js +0 -714
  171. package/fesm/services/permission.service.js +0 -904
  172. package/fesm/services/permission.service.spec.js +0 -914
  173. package/fesm/services/role.service.js +0 -214
  174. package/fesm/services/role.service.spec.js +0 -343
  175. package/fesm/types/logic-node.type.js +0 -27
@@ -1,49 +0,0 @@
1
- import { IAMPermissionMode } from '../enums/permission-type.enum';
2
- /**
3
- * Helper for converting permission mode strings to enum values
4
- *
5
- * **Purpose:** Centralize the conversion logic from IBootstrapAppConfig.permissionMode
6
- * (string) to IAMPermissionMode enum to prevent duplication and sync issues.
7
- *
8
- * **Used by:**
9
- * - iam.module.ts (forRoot, forRootAsync)
10
- * - iam-config.service.ts (getPermissionMode)
11
- * - main.ts (Swagger setup)
12
- */ export class PermissionModeHelper {
13
- /**
14
- * Convert permission mode string to enum value
15
- *
16
- * @param modeStr - Permission mode string ('FULL', 'RBAC', 'DIRECT')
17
- * @returns IAMPermissionMode enum value
18
- * @default IAMPermissionMode.FULL if invalid/missing
19
- *
20
- * @example
21
- * ```typescript
22
- * const mode = PermissionModeHelper.fromString('RBAC');
23
- * // Returns: IAMPermissionMode.RBAC
24
- *
25
- * const mode = PermissionModeHelper.fromString(undefined);
26
- * // Returns: IAMPermissionMode.FULL (default)
27
- * ```
28
- */ static fromString(modeStr) {
29
- if (!modeStr) {
30
- return IAMPermissionMode.FULL;
31
- }
32
- const mode = IAMPermissionMode[modeStr];
33
- return mode ?? IAMPermissionMode.FULL;
34
- }
35
- /**
36
- * Convert enum value to string (for serialization/logging)
37
- *
38
- * @param mode - IAMPermissionMode enum value
39
- * @returns String representation
40
- *
41
- * @example
42
- * ```typescript
43
- * const str = PermissionModeHelper.toString(IAMPermissionMode.RBAC);
44
- * // Returns: 'RBAC'
45
- * ```
46
- */ static toString(mode) {
47
- return IAMPermissionMode[mode];
48
- }
49
- }
@@ -1,50 +0,0 @@
1
- import { IAMPermissionMode } from '../enums/permission-type.enum';
2
- import { PermissionModeHelper } from './permission-mode.helper';
3
- describe('PermissionModeHelper', ()=>{
4
- describe('fromString', ()=>{
5
- it('converts "RBAC" to IAMPermissionMode.RBAC', ()=>{
6
- expect(PermissionModeHelper.fromString('RBAC')).toBe(IAMPermissionMode.RBAC);
7
- });
8
- it('converts "DIRECT" to IAMPermissionMode.DIRECT', ()=>{
9
- expect(PermissionModeHelper.fromString('DIRECT')).toBe(IAMPermissionMode.DIRECT);
10
- });
11
- it('converts "FULL" to IAMPermissionMode.FULL', ()=>{
12
- expect(PermissionModeHelper.fromString('FULL')).toBe(IAMPermissionMode.FULL);
13
- });
14
- it('defaults to FULL when the string is undefined', ()=>{
15
- expect(PermissionModeHelper.fromString(undefined)).toBe(IAMPermissionMode.FULL);
16
- });
17
- it('defaults to FULL when the string is empty', ()=>{
18
- expect(PermissionModeHelper.fromString('')).toBe(IAMPermissionMode.FULL);
19
- });
20
- it('defaults to FULL when the string is not a known mode', ()=>{
21
- expect(PermissionModeHelper.fromString('INVALID_MODE')).toBe(IAMPermissionMode.FULL);
22
- });
23
- it('is case-sensitive and falls back to FULL for lowercase input', ()=>{
24
- expect(PermissionModeHelper.fromString('rbac')).toBe(IAMPermissionMode.FULL);
25
- });
26
- });
27
- describe('toString', ()=>{
28
- it('converts IAMPermissionMode.RBAC to "RBAC"', ()=>{
29
- expect(PermissionModeHelper.toString(IAMPermissionMode.RBAC)).toBe('RBAC');
30
- });
31
- it('converts IAMPermissionMode.DIRECT to "DIRECT"', ()=>{
32
- expect(PermissionModeHelper.toString(IAMPermissionMode.DIRECT)).toBe('DIRECT');
33
- });
34
- it('converts IAMPermissionMode.FULL to "FULL"', ()=>{
35
- expect(PermissionModeHelper.toString(IAMPermissionMode.FULL)).toBe('FULL');
36
- });
37
- });
38
- describe('round trip', ()=>{
39
- it('fromString(toString(mode)) returns the original mode for every enum value', ()=>{
40
- const modes = [
41
- IAMPermissionMode.RBAC,
42
- IAMPermissionMode.DIRECT,
43
- IAMPermissionMode.FULL
44
- ];
45
- for (const mode of modes){
46
- expect(PermissionModeHelper.fromString(PermissionModeHelper.toString(mode))).toBe(mode);
47
- }
48
- });
49
- });
50
- });
@@ -1,3 +0,0 @@
1
- /**
2
- * Action with children (tree structure)
3
- */ export { };
@@ -1,3 +0,0 @@
1
- /**
2
- * Async options for IAMModule registration
3
- */ export { };
@@ -1,4 +0,0 @@
1
- /**
2
- * Role Interface
3
- * Represents a role entity in responses
4
- */ export { };
@@ -1,176 +0,0 @@
1
- function _ts_decorate(decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- 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;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- }
7
- import { PERMISSION_GUARD_CONFIG, PERMISSIONS_CACHE_PREFIX } from '@flusys/nestjs-shared';
8
- import { CacheModule, UtilsModule, createModuleEventsProvider } from '@flusys/nestjs-shared/modules';
9
- import { Module } from '@nestjs/common';
10
- import { IAM_MODULE_OPTIONS } from '../config/iam.constants';
11
- import { ActionController, CompanyActionPermissionController, MyPermissionController, RoleController, RolePermissionController, UserActionPermissionController } from '../controllers';
12
- import { IAMPermissionMode } from '../enums/permission-type.enum';
13
- import { PermissionModeHelper } from '../helpers';
14
- import { ActionService, PermissionService, RoleService } from '../services';
15
- import { IAMConfigService } from '../services/iam-config.service';
16
- import { IAMDataSourceService } from '../services/iam-datasource.service';
17
- import { PermissionCacheService } from '../services/permission-cache.service';
18
- export class IAMModule {
19
- static getControllers(permissionMode, enableCompanyFeature) {
20
- const baseControllers = [
21
- ActionController,
22
- MyPermissionController
23
- ];
24
- // Direct permission mode - user actions only
25
- if (permissionMode === IAMPermissionMode.DIRECT) {
26
- baseControllers.push(UserActionPermissionController);
27
- }
28
- // RBAC mode - role actions and user roles only
29
- if (permissionMode === IAMPermissionMode.RBAC) {
30
- baseControllers.push(RoleController);
31
- baseControllers.push(RolePermissionController);
32
- }
33
- // FULL mode - all permission controllers
34
- if (permissionMode === IAMPermissionMode.FULL) {
35
- baseControllers.push(RoleController);
36
- baseControllers.push(UserActionPermissionController);
37
- baseControllers.push(RolePermissionController);
38
- }
39
- // Company action permissions - only if company feature enabled
40
- if (enableCompanyFeature) {
41
- baseControllers.push(CompanyActionPermissionController);
42
- }
43
- return baseControllers;
44
- }
45
- static getServices(permissionMode) {
46
- const services = [
47
- ActionService,
48
- PermissionService,
49
- PermissionCacheService
50
- ];
51
- // RoleService - Only for RBAC or FULL mode
52
- if (permissionMode === IAMPermissionMode.RBAC || permissionMode === IAMPermissionMode.FULL) {
53
- services.push(RoleService);
54
- }
55
- return services;
56
- }
57
- static getPermissionGuardConfigProvider(enableCompanyFeature) {
58
- return {
59
- provide: PERMISSION_GUARD_CONFIG,
60
- useValue: {
61
- enableCompanyFeature,
62
- userPermissionKeyFormat: `${PERMISSIONS_CACHE_PREFIX}:user:{userId}`,
63
- companyPermissionKeyFormat: `${PERMISSIONS_CACHE_PREFIX}:company:{companyId}:branch:{branchId}:user:{userId}`
64
- }
65
- };
66
- }
67
- static getExports(permissionMode) {
68
- const baseExports = [
69
- IAMConfigService,
70
- IAMDataSourceService,
71
- ActionService,
72
- PermissionService,
73
- PermissionCacheService,
74
- PERMISSION_GUARD_CONFIG
75
- ];
76
- if (permissionMode === IAMPermissionMode.RBAC || permissionMode === IAMPermissionMode.FULL) {
77
- baseExports.push(RoleService);
78
- }
79
- return baseExports;
80
- }
81
- static forRoot(options = {}) {
82
- const { global = false, includeController = false } = options;
83
- const enableCompanyFeature = options.bootstrapAppConfig?.enableCompanyFeature ?? false;
84
- const permissionMode = PermissionModeHelper.fromString(options.bootstrapAppConfig?.permissionMode);
85
- const controllers = includeController ? this.getControllers(permissionMode, enableCompanyFeature) : [];
86
- const providers = [
87
- {
88
- provide: IAM_MODULE_OPTIONS,
89
- useValue: options
90
- },
91
- IAMConfigService,
92
- IAMDataSourceService,
93
- ...this.getServices(permissionMode),
94
- this.getPermissionGuardConfigProvider(enableCompanyFeature),
95
- createModuleEventsProvider('iam', IAM_MODULE_OPTIONS)
96
- ];
97
- const module = {
98
- module: IAMModule,
99
- imports: [
100
- CacheModule,
101
- UtilsModule
102
- ],
103
- controllers,
104
- providers,
105
- exports: this.getExports(permissionMode)
106
- };
107
- return global ? {
108
- ...module,
109
- global: true
110
- } : module;
111
- }
112
- static forRootAsync(asyncOptions) {
113
- const { global = false, includeController = false, imports: externalImports = [] } = asyncOptions;
114
- const enableCompanyFeature = asyncOptions.bootstrapAppConfig?.enableCompanyFeature ?? false;
115
- const permissionMode = PermissionModeHelper.fromString(asyncOptions.bootstrapAppConfig?.permissionMode);
116
- const controllers = includeController ? this.getControllers(permissionMode, enableCompanyFeature) : [];
117
- const providers = [
118
- ...this.createAsyncProviders(asyncOptions),
119
- IAMConfigService,
120
- IAMDataSourceService,
121
- ...this.getServices(permissionMode),
122
- this.getPermissionGuardConfigProvider(enableCompanyFeature),
123
- createModuleEventsProvider('iam', IAM_MODULE_OPTIONS)
124
- ];
125
- const module = {
126
- module: IAMModule,
127
- imports: [
128
- ...externalImports,
129
- CacheModule,
130
- UtilsModule
131
- ],
132
- controllers,
133
- providers,
134
- exports: this.getExports(permissionMode)
135
- };
136
- return global ? {
137
- ...module,
138
- global: true
139
- } : module;
140
- }
141
- static createAsyncProviders(options) {
142
- if (options.useExisting || options.useFactory) {
143
- return [
144
- this.createAsyncOptionsProvider(options)
145
- ];
146
- }
147
- const useClass = options.useClass;
148
- return [
149
- this.createAsyncOptionsProvider(options),
150
- {
151
- provide: useClass,
152
- useClass
153
- }
154
- ];
155
- }
156
- static createAsyncOptionsProvider(options) {
157
- if (options.useFactory) {
158
- return {
159
- provide: IAM_MODULE_OPTIONS,
160
- useFactory: options.useFactory,
161
- inject: options.inject || []
162
- };
163
- }
164
- const inject = [
165
- options.useClass || options.useExisting
166
- ];
167
- return {
168
- provide: IAM_MODULE_OPTIONS,
169
- useFactory: async (optionsFactory)=>optionsFactory.createIAMOptions(),
170
- inject
171
- };
172
- }
173
- }
174
- IAMModule = _ts_decorate([
175
- Module({})
176
- ], IAMModule);
@@ -1,278 +0,0 @@
1
- function _define_property(obj, key, value) {
2
- if (key in obj) {
3
- Object.defineProperty(obj, key, {
4
- value: value,
5
- enumerable: true,
6
- configurable: true,
7
- writable: true
8
- });
9
- } else {
10
- obj[key] = value;
11
- }
12
- return obj;
13
- }
14
- import { PERMISSION_GUARD_CONFIG } from '@flusys/nestjs-shared';
15
- import { IAMModule } from './iam.module';
16
- import { IAM_MODULE_OPTIONS } from '../config/iam.constants';
17
- import { ActionController, CompanyActionPermissionController, MyPermissionController, RoleController, RolePermissionController, UserActionPermissionController } from '../controllers';
18
- import { ActionService, PermissionService, RoleService } from '../services';
19
- import { IAMConfigService } from '../services/iam-config.service';
20
- import { IAMDataSourceService } from '../services/iam-datasource.service';
21
- import { PermissionCacheService } from '../services/permission-cache.service';
22
- function providerTokens(providers) {
23
- return providers.map((p)=>typeof p === 'function' ? p : p.provide);
24
- }
25
- describe('IAMModule', ()=>{
26
- describe('forRoot - controller/service registration matrix', ()=>{
27
- it('should register no controllers by default (includeController defaults to false)', ()=>{
28
- const dynamicModule = IAMModule.forRoot();
29
- expect(dynamicModule.controllers).toEqual([]);
30
- });
31
- it('DIRECT mode: registers only UserActionPermissionController beyond the base set', ()=>{
32
- const dynamicModule = IAMModule.forRoot({
33
- includeController: true,
34
- bootstrapAppConfig: {
35
- permissionMode: 'DIRECT'
36
- }
37
- });
38
- expect(dynamicModule.controllers).toEqual([
39
- ActionController,
40
- MyPermissionController,
41
- UserActionPermissionController
42
- ]);
43
- expect(providerTokens(dynamicModule.providers)).not.toContain(RoleService);
44
- });
45
- it('RBAC mode: registers RoleController + RolePermissionController but not UserActionPermissionController', ()=>{
46
- const dynamicModule = IAMModule.forRoot({
47
- includeController: true,
48
- bootstrapAppConfig: {
49
- permissionMode: 'RBAC'
50
- }
51
- });
52
- expect(dynamicModule.controllers).toEqual([
53
- ActionController,
54
- MyPermissionController,
55
- RoleController,
56
- RolePermissionController
57
- ]);
58
- expect(providerTokens(dynamicModule.providers)).toContain(RoleService);
59
- });
60
- it('FULL mode: registers every permission controller', ()=>{
61
- const dynamicModule = IAMModule.forRoot({
62
- includeController: true,
63
- bootstrapAppConfig: {
64
- permissionMode: 'FULL'
65
- }
66
- });
67
- expect(dynamicModule.controllers).toEqual([
68
- ActionController,
69
- MyPermissionController,
70
- RoleController,
71
- UserActionPermissionController,
72
- RolePermissionController
73
- ]);
74
- });
75
- it('defaults to FULL mode when permissionMode is omitted', ()=>{
76
- const dynamicModule = IAMModule.forRoot({
77
- includeController: true
78
- });
79
- expect(dynamicModule.controllers).toEqual(expect.arrayContaining([
80
- RoleController,
81
- UserActionPermissionController,
82
- RolePermissionController
83
- ]));
84
- });
85
- it('defaults to FULL mode when permissionMode is an unrecognized string', ()=>{
86
- const dynamicModule = IAMModule.forRoot({
87
- includeController: true,
88
- bootstrapAppConfig: {
89
- permissionMode: 'BOGUS'
90
- }
91
- });
92
- expect(dynamicModule.controllers).toEqual(expect.arrayContaining([
93
- RoleController,
94
- UserActionPermissionController,
95
- RolePermissionController
96
- ]));
97
- });
98
- it('adds CompanyActionPermissionController only when enableCompanyFeature is true', ()=>{
99
- const withCompany = IAMModule.forRoot({
100
- includeController: true,
101
- bootstrapAppConfig: {
102
- enableCompanyFeature: true
103
- }
104
- });
105
- const withoutCompany = IAMModule.forRoot({
106
- includeController: true,
107
- bootstrapAppConfig: {
108
- enableCompanyFeature: false
109
- }
110
- });
111
- expect(withCompany.controllers).toContain(CompanyActionPermissionController);
112
- expect(withoutCompany.controllers).not.toContain(CompanyActionPermissionController);
113
- });
114
- it('excludes RoleService for DIRECT mode but includes it for RBAC/FULL', ()=>{
115
- const direct = IAMModule.forRoot({
116
- bootstrapAppConfig: {
117
- permissionMode: 'DIRECT'
118
- }
119
- });
120
- const rbac = IAMModule.forRoot({
121
- bootstrapAppConfig: {
122
- permissionMode: 'RBAC'
123
- }
124
- });
125
- const full = IAMModule.forRoot({
126
- bootstrapAppConfig: {
127
- permissionMode: 'FULL'
128
- }
129
- });
130
- expect(providerTokens(direct.providers)).not.toContain(RoleService);
131
- expect(providerTokens(rbac.providers)).toContain(RoleService);
132
- expect(providerTokens(full.providers)).toContain(RoleService);
133
- expect(providerTokens(direct.exports)).not.toContain(RoleService);
134
- expect(providerTokens(rbac.exports)).toContain(RoleService);
135
- });
136
- it('always registers the base providers/exports (ActionService, PermissionService, PermissionCacheService)', ()=>{
137
- const dynamicModule = IAMModule.forRoot();
138
- expect(providerTokens(dynamicModule.providers)).toEqual(expect.arrayContaining([
139
- IAMConfigService,
140
- IAMDataSourceService,
141
- ActionService,
142
- PermissionService,
143
- PermissionCacheService
144
- ]));
145
- expect(dynamicModule.exports).toEqual(expect.arrayContaining([
146
- IAMConfigService,
147
- IAMDataSourceService,
148
- ActionService,
149
- PermissionService,
150
- PermissionCacheService,
151
- PERMISSION_GUARD_CONFIG
152
- ]));
153
- });
154
- });
155
- describe('forRoot - options/global handling', ()=>{
156
- it('should not set `global` on the returned module when global is false/omitted', ()=>{
157
- const dynamicModule = IAMModule.forRoot();
158
- expect(dynamicModule.global).toBeUndefined();
159
- });
160
- it('should set global: true when requested', ()=>{
161
- const dynamicModule = IAMModule.forRoot({
162
- global: true
163
- });
164
- expect(dynamicModule.global).toBe(true);
165
- });
166
- it('should register IAM_MODULE_OPTIONS with the given options', ()=>{
167
- const options = {
168
- includeController: true
169
- };
170
- const dynamicModule = IAMModule.forRoot(options);
171
- const provider = dynamicModule.providers.find((p)=>p.provide === IAM_MODULE_OPTIONS);
172
- expect(provider.useValue).toBe(options);
173
- });
174
- it('should build a company-aware PERMISSION_GUARD_CONFIG provider', ()=>{
175
- const dynamicModule = IAMModule.forRoot({
176
- bootstrapAppConfig: {
177
- enableCompanyFeature: true
178
- }
179
- });
180
- const provider = dynamicModule.providers.find((p)=>p.provide === PERMISSION_GUARD_CONFIG);
181
- expect(provider.useValue.enableCompanyFeature).toBe(true);
182
- expect(provider.useValue.userPermissionKeyFormat).toContain('{userId}');
183
- expect(provider.useValue.companyPermissionKeyFormat).toContain('{companyId}');
184
- });
185
- });
186
- describe('forRootAsync', ()=>{
187
- it('mirrors the controller/service registration matrix of forRoot', ()=>{
188
- const dynamicModule = IAMModule.forRootAsync({
189
- includeController: true,
190
- bootstrapAppConfig: {
191
- permissionMode: 'DIRECT'
192
- }
193
- });
194
- expect(dynamicModule.controllers).toEqual([
195
- ActionController,
196
- MyPermissionController,
197
- UserActionPermissionController
198
- ]);
199
- });
200
- it('should forward external imports alongside CacheModule/UtilsModule', ()=>{
201
- let FakeImportedModule = class FakeImportedModule {
202
- };
203
- const dynamicModule = IAMModule.forRootAsync({
204
- imports: [
205
- FakeImportedModule
206
- ]
207
- });
208
- expect(dynamicModule.imports).toEqual(expect.arrayContaining([
209
- FakeImportedModule
210
- ]));
211
- });
212
- it('useFactory: registers a single options provider using the given inject tokens', async ()=>{
213
- const useFactory = jest.fn().mockResolvedValue({
214
- foo: 'bar'
215
- });
216
- const dynamicModule = IAMModule.forRootAsync({
217
- useFactory,
218
- inject: [
219
- 'SOME_TOKEN'
220
- ]
221
- });
222
- const optionsProviders = dynamicModule.providers.filter((p)=>p.provide === IAM_MODULE_OPTIONS);
223
- expect(optionsProviders).toHaveLength(1);
224
- const provider = optionsProviders[0];
225
- expect(provider.useFactory).toBe(useFactory);
226
- expect(provider.inject).toEqual([
227
- 'SOME_TOKEN'
228
- ]);
229
- });
230
- it('useClass: registers both the class provider and an options provider that calls createIAMOptions()', async ()=>{
231
- let MyOptionsFactory = class MyOptionsFactory {
232
- constructor(){
233
- _define_property(this, "createIAMOptions", jest.fn().mockResolvedValue({
234
- foo: 'from-class'
235
- }));
236
- }
237
- };
238
- const dynamicModule = IAMModule.forRootAsync({
239
- useClass: MyOptionsFactory
240
- });
241
- const classProvider = dynamicModule.providers.find((p)=>p.provide === MyOptionsFactory);
242
- expect(classProvider.useClass).toBe(MyOptionsFactory);
243
- const optionsProvider = dynamicModule.providers.find((p)=>p.provide === IAM_MODULE_OPTIONS);
244
- expect(optionsProvider.inject).toEqual([
245
- MyOptionsFactory
246
- ]);
247
- const instance = new MyOptionsFactory();
248
- const resolved = await optionsProvider.useFactory(instance);
249
- expect(instance.createIAMOptions).toHaveBeenCalled();
250
- expect(resolved).toEqual({
251
- foo: 'from-class'
252
- });
253
- });
254
- it('useExisting: registers a single options provider injecting the existing factory', async ()=>{
255
- let MyOptionsFactory = class MyOptionsFactory {
256
- constructor(){
257
- _define_property(this, "createIAMOptions", jest.fn().mockResolvedValue({
258
- foo: 'from-existing'
259
- }));
260
- }
261
- };
262
- const dynamicModule = IAMModule.forRootAsync({
263
- useExisting: MyOptionsFactory
264
- });
265
- const optionsProviders = dynamicModule.providers.filter((p)=>p.provide === IAM_MODULE_OPTIONS);
266
- expect(optionsProviders).toHaveLength(1);
267
- const provider = optionsProviders[0];
268
- expect(provider.inject).toEqual([
269
- MyOptionsFactory
270
- ]);
271
- const instance = new MyOptionsFactory();
272
- const resolved = await provider.useFactory(instance);
273
- expect(resolved).toEqual({
274
- foo: 'from-existing'
275
- });
276
- });
277
- });
278
- });