@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
@@ -27,11 +27,12 @@ function _ts_param(paramIndex, decorator) {
27
27
  }
28
28
  import { RequestScopedApiService, HybridCache } from '@flusys/nestjs-shared/classes';
29
29
  import { UtilsService } from '@flusys/nestjs-shared/modules';
30
+ import { applyCompanyFilter } from '@flusys/nestjs-shared/utils';
30
31
  import { Inject, Injectable, Scope } from '@nestjs/common';
31
32
  import { RoleWithCompany } from '../entities/role-with-company.entity';
32
33
  import { Role } from '../entities/role.entity';
33
34
  import { IAMConfigService } from './iam-config.service';
34
- import { IAMDataSourceProvider } from './iam-datasource.provider';
35
+ import { IAMDataSourceService } from './iam-datasource.service';
35
36
  export class RoleService extends RequestScopedApiService {
36
37
  resolveEntity() {
37
38
  return this.iamConfigService.isCompanyFeatureEnabled() ? RoleWithCompany : Role;
@@ -85,11 +86,10 @@ export class RoleService extends RequestScopedApiService {
85
86
  }
86
87
  async getExtraManipulateQuery(query, filterDto, user) {
87
88
  const result = await super.getExtraManipulateQuery(query, filterDto, user);
88
- if (this.iamConfigService.isCompanyFeatureEnabled() && user?.companyId) {
89
- query.andWhere('role.companyId = :companyId', {
90
- companyId: user.companyId
91
- });
92
- }
89
+ applyCompanyFilter(query, {
90
+ isCompanyFeatureEnabled: this.iamConfigService.isCompanyFeatureEnabled(),
91
+ entityAlias: 'role'
92
+ }, user);
93
93
  return result;
94
94
  }
95
95
  // Response Conversion
@@ -122,12 +122,12 @@ RoleService = _ts_decorate([
122
122
  _ts_param(0, Inject('CACHE_INSTANCE')),
123
123
  _ts_param(1, Inject(UtilsService)),
124
124
  _ts_param(2, Inject(IAMConfigService)),
125
- _ts_param(3, Inject(IAMDataSourceProvider)),
125
+ _ts_param(3, Inject(IAMDataSourceService)),
126
126
  _ts_metadata("design:type", Function),
127
127
  _ts_metadata("design:paramtypes", [
128
128
  typeof HybridCache === "undefined" ? Object : HybridCache,
129
129
  typeof UtilsService === "undefined" ? Object : UtilsService,
130
130
  typeof IAMConfigService === "undefined" ? Object : IAMConfigService,
131
- typeof IAMDataSourceProvider === "undefined" ? Object : IAMDataSourceProvider
131
+ typeof IAMDataSourceService === "undefined" ? Object : IAMDataSourceService
132
132
  ])
133
133
  ], RoleService);
@@ -24,13 +24,4 @@
24
24
  * ]
25
25
  * };
26
26
  * ```
27
- */ export var LogicOperator = /*#__PURE__*/ function(LogicOperator) {
28
- LogicOperator["AND"] = "AND";
29
- LogicOperator["OR"] = "OR";
30
- return LogicOperator;
31
- }({});
32
- export var LogicNodeType = /*#__PURE__*/ function(LogicNodeType) {
33
- LogicNodeType["GROUP"] = "group";
34
- LogicNodeType["ACTION"] = "action";
35
- return LogicNodeType;
36
- }({});
27
+ */ export { };
@@ -0,0 +1,3 @@
1
+ import { ILoggedUserInfo } from '@flusys/nestjs-shared';
2
+ import { IAMConfigService } from '../services/iam-config.service';
3
+ export declare function validateCompanyAccess(config: IAMConfigService, companyId: string | undefined, user: ILoggedUserInfo, errorMessage?: string): void;
@@ -1,2 +1,2 @@
1
- export * from './permission-evaluator.helper';
1
+ export * from './company-access.helper';
2
2
  export * from './permission-mode.helper';
@@ -1,4 +1,5 @@
1
1
  import { IBootstrapAppConfig, IDataSourceServiceOptions, IDynamicModuleConfig, IModuleOptionsFactory } from '@flusys/nestjs-core';
2
+ import { ModuleMetadata, Type } from '@nestjs/common';
2
3
  export interface IIAMModuleConfig extends IDataSourceServiceOptions {
3
4
  }
4
5
  export interface IAMModuleOptions extends IDynamicModuleConfig {
@@ -9,4 +10,11 @@ export interface IAMOptionsFactory extends IModuleOptionsFactory<IIAMModuleConfi
9
10
  createIAMOptions(): Promise<IIAMModuleConfig> | IIAMModuleConfig;
10
11
  createOptions(): Promise<IIAMModuleConfig> | IIAMModuleConfig;
11
12
  }
12
- export * from './iam-module-async-options.interface';
13
+ export interface IAMModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'>, IDynamicModuleConfig {
14
+ bootstrapAppConfig?: IBootstrapAppConfig;
15
+ config?: IIAMModuleConfig;
16
+ useFactory?: (...args: any[]) => Promise<IIAMModuleConfig> | IIAMModuleConfig;
17
+ inject?: any[];
18
+ useClass?: Type<IAMOptionsFactory>;
19
+ useExisting?: Type<IAMOptionsFactory>;
20
+ }
@@ -1,4 +1,3 @@
1
1
  export * from './action.interface';
2
2
  export * from './role.interface';
3
3
  export * from './iam-module-options.interface';
4
- export * from './iam-module-async-options.interface';
@@ -2,9 +2,9 @@ import { DynamicModule } from '@nestjs/common';
2
2
  import { IAMModuleAsyncOptions, IAMModuleOptions } from '../interfaces/iam-module-options.interface';
3
3
  export declare class IAMModule {
4
4
  private static getControllers;
5
- private static getEntities;
6
5
  private static getServices;
7
- private static getRepositoryProviders;
6
+ private static getPermissionGuardConfigProvider;
7
+ private static getExports;
8
8
  static forRoot(options?: IAMModuleOptions): DynamicModule;
9
9
  static forRootAsync(asyncOptions: IAMModuleAsyncOptions): DynamicModule;
10
10
  private static createAsyncProviders;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flusys/nestjs-iam",
3
- "version": "1.1.0-beta",
3
+ "version": "2.0.0",
4
4
  "description": "Identity and Access Management (IAM) module for NestJS applications",
5
5
  "main": "cjs/index.js",
6
6
  "module": "fesm/index.js",
@@ -89,7 +89,7 @@
89
89
  "typeorm": "^0.3.0"
90
90
  },
91
91
  "dependencies": {
92
- "@flusys/nestjs-core": "1.1.0-beta",
93
- "@flusys/nestjs-shared": "1.1.0-beta"
92
+ "@flusys/nestjs-core": "2.0.0",
93
+ "@flusys/nestjs-shared": "2.0.0"
94
94
  }
95
95
  }
@@ -1,4 +1,4 @@
1
- import { RequestScopedApiService, HybridCache } from '@flusys/nestjs-shared/classes';
1
+ import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
2
2
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
3
  import { UtilsService } from '@flusys/nestjs-shared/modules';
4
4
  import { EntityTarget, Repository, SelectQueryBuilder } from 'typeorm';
@@ -6,7 +6,7 @@ import { CreateActionDto, UpdateActionDto } from '../dtos/action.dto';
6
6
  import { ActionBase } from '../entities/action-base.entity';
7
7
  import { IAction, IActionTree } from '../interfaces/action.interface';
8
8
  import { IAMConfigService } from './iam-config.service';
9
- import { IAMDataSourceProvider } from './iam-datasource.provider';
9
+ import { IAMDataSourceService } from './iam-datasource.service';
10
10
  import { PermissionService } from './permission.service';
11
11
  export declare class ActionService extends RequestScopedApiService<CreateActionDto, UpdateActionDto, IAction, ActionBase, Repository<ActionBase>> {
12
12
  protected cacheManager: HybridCache;
@@ -14,9 +14,9 @@ export declare class ActionService extends RequestScopedApiService<CreateActionD
14
14
  private readonly iamConfigService;
15
15
  private readonly dataSourceProvider;
16
16
  private readonly permissionService;
17
- constructor(cacheManager: HybridCache, utilsService: UtilsService, iamConfigService: IAMConfigService, dataSourceProvider: IAMDataSourceProvider, permissionService: PermissionService);
17
+ constructor(cacheManager: HybridCache, utilsService: UtilsService, iamConfigService: IAMConfigService, dataSourceProvider: IAMDataSourceService, permissionService: PermissionService);
18
18
  protected resolveEntity(): EntityTarget<ActionBase>;
19
- protected getDataSourceProvider(): IAMDataSourceProvider;
19
+ protected getDataSourceProvider(): IAMDataSourceService;
20
20
  getSelectQuery(query: SelectQueryBuilder<ActionBase>, _user: ILoggedUserInfo | null, select?: string[]): Promise<{
21
21
  query: SelectQueryBuilder<ActionBase>;
22
22
  isRaw: boolean;
@@ -26,6 +26,8 @@ export declare class ActionService extends RequestScopedApiService<CreateActionD
26
26
  isRaw: boolean;
27
27
  }>;
28
28
  protected convertEntityToResponseDto(entity: ActionBase, _isRaw: boolean): IAction;
29
+ private readonly actionSelectFields;
30
+ private requireUser;
29
31
  getActionsForPermission(user: ILoggedUserInfo): Promise<IAction[]>;
30
32
  getActionTree(user: ILoggedUserInfo, search?: string, isActive?: boolean, withDeleted?: boolean): Promise<IActionTree[]>;
31
33
  private buildActionTree;
@@ -1,12 +1,12 @@
1
1
  import { DatabaseMode } from '@flusys/nestjs-core';
2
+ import { IModuleConfigService } from '@flusys/nestjs-shared/interfaces';
2
3
  import { IAMPermissionMode } from '../enums/permission-type.enum';
3
4
  import { IAMModuleOptions } from '../interfaces/iam-module-options.interface';
4
- export declare class IAMConfigService {
5
+ export declare class IAMConfigService implements IModuleConfigService {
5
6
  private readonly options;
6
7
  constructor(injectedOptions?: IAMModuleOptions);
7
8
  getDatabaseMode(): DatabaseMode;
8
9
  isMultiTenant(): boolean;
9
- getEnableCompanyFeature(): boolean;
10
10
  isCompanyFeatureEnabled(): boolean;
11
11
  getPermissionMode(): IAMPermissionMode;
12
12
  isRbacEnabled(): boolean;
@@ -3,9 +3,9 @@ import { IDatabaseConfig, ITenantDatabaseConfig } from '@flusys/nestjs-core';
3
3
  import { Logger } from '@nestjs/common';
4
4
  import { Request } from 'express';
5
5
  import { DataSource } from 'typeorm';
6
- import { IAMModuleOptions } from '../interfaces/iam-module-options.interface';
7
- export declare class IAMDataSourceProvider extends MultiTenantDataSourceService {
8
- private readonly iamOptions;
6
+ import { IAMConfigService } from './iam-config.service';
7
+ export declare class IAMDataSourceService extends MultiTenantDataSourceService {
8
+ private readonly configService;
9
9
  protected readonly logger: Logger;
10
10
  protected static readonly tenantConnections: Map<string, DataSource>;
11
11
  protected static singleDataSource: DataSource | null;
@@ -13,9 +13,8 @@ export declare class IAMDataSourceProvider extends MultiTenantDataSourceService
13
13
  protected static initialized: boolean;
14
14
  protected static readonly connectionLocks: Map<string, Promise<DataSource>>;
15
15
  protected static singleConnectionLock: Promise<DataSource> | null;
16
- constructor(iamOptions: IAMModuleOptions, request?: Request);
16
+ constructor(configService: IAMConfigService, request?: Request);
17
17
  private static buildParentOptions;
18
- getEnableCompanyFeature(): boolean;
19
18
  getEnableCompanyFeatureForTenant(tenant?: ITenantDatabaseConfig): boolean;
20
19
  getEnableCompanyFeatureForCurrentTenant(): boolean;
21
20
  getIAMEntities(): Promise<any[]>;
@@ -1,6 +1,6 @@
1
1
  export * from './action.service';
2
2
  export * from './iam-config.service';
3
- export * from './iam-datasource.provider';
3
+ export * from './iam-datasource.service';
4
4
  export * from './permission-cache.service';
5
5
  export * from './permission.service';
6
6
  export * from './role.service';
@@ -26,16 +26,14 @@ export declare class PermissionCacheService {
26
26
  constructor(cacheManager: HybridCache);
27
27
  generateCacheKey(options: PermissionCacheKeyOptions): string;
28
28
  generateMyPermissionsCacheKey(options: PermissionCacheKeyOptions): string;
29
+ private buildCacheKey;
29
30
  setPermissions(options: PermissionCacheKeyOptions, permissions: string[]): Promise<void>;
30
- getPermissions(options: PermissionCacheKeyOptions): Promise<string[] | null>;
31
31
  setMyPermissions(options: PermissionCacheKeyOptions, data: CachedMyPermissions): Promise<void>;
32
32
  getMyPermissions(options: PermissionCacheKeyOptions): Promise<CachedMyPermissions | null>;
33
- setActionCodeMap(codeToIdMap: Record<string, string>): Promise<void>;
34
- getActionIdsByCodes(codes: string[]): Promise<Record<string, string> | null>;
35
- invalidateActionCodeCache(): Promise<void>;
33
+ private generateActionCodeCacheKey;
34
+ setActionCodeMap(codeToIdMap: Record<string, string>, tenantId?: string): Promise<void>;
35
+ getActionIdsByCodes(codes: string[], tenantId?: string): Promise<Record<string, string> | null>;
36
36
  invalidateUser(userId: string, companyId?: string | null, branchIds?: (string | null)[]): Promise<void>;
37
37
  invalidateUsers(userIds: string[], companyId?: string | null, branchIds?: (string | null)[]): Promise<number>;
38
- invalidateCompany(companyId: string): Promise<number>;
39
38
  invalidateRole(roleId: string, userIds: string[], companyId?: string | null, branchIds?: (string | null)[]): Promise<number>;
40
- clearAll(): Promise<void>;
41
39
  }
@@ -1,15 +1,13 @@
1
1
  import { AssignCompanyActionsDto, AssignRoleActionsDto, AssignUserActionsDto, AssignUserRolesDto, CompanyActionResponseDto, MyPermissionsResponseDto, PermissionOperationResultDto, RoleActionResponseDto, UserActionResponseDto, UserRoleResponseDto } from '../dtos/permission.dto';
2
- import { PermissionEvaluatorHelper } from '../helpers/permission-evaluator.helper';
3
2
  import { IAMConfigService } from './iam-config.service';
4
- import { IAMDataSourceProvider } from './iam-datasource.provider';
3
+ import { IAMDataSourceService } from './iam-datasource.service';
5
4
  import { PermissionCacheService } from './permission-cache.service';
6
5
  export declare class PermissionService {
7
- private readonly permissionEvaluator;
8
6
  private readonly permissionCacheService;
9
7
  private readonly iamConfigService;
10
8
  private readonly dataSourceProvider;
11
9
  private readonly logger;
12
- constructor(permissionEvaluator: PermissionEvaluatorHelper, permissionCacheService: PermissionCacheService, iamConfigService: IAMConfigService, dataSourceProvider: IAMDataSourceProvider);
10
+ constructor(permissionCacheService: PermissionCacheService, iamConfigService: IAMConfigService, dataSourceProvider: IAMDataSourceService);
13
11
  private getPermissionRepository;
14
12
  private getActionRepository;
15
13
  private getRoleRepository;
@@ -26,8 +24,14 @@ export declare class PermissionService {
26
24
  getUserRoles(userId: string, branchId?: string | undefined, companyId?: string | undefined): Promise<UserRoleResponseDto[]>;
27
25
  getMyPermissions(userId: string, branchId: string | null, companyId?: string | null, parentCodes?: string[]): Promise<MyPermissionsResponseDto>;
28
26
  private buildResponseFromCache;
27
+ private getCurrentTenantId;
29
28
  private getParentIdsByCodesWithCache;
30
29
  private fetchAndCachePermissions;
30
+ private collectAllActionIds;
31
+ private applyCompanyWhitelist;
32
+ private buildAndCachePermissionData;
33
+ private splitItemsByAction;
34
+ private buildOperationResult;
31
35
  private getUserRoleIds;
32
36
  private getRoleActionIds;
33
37
  private getUserActionIds;
@@ -6,15 +6,15 @@ import { CreateRoleDto, UpdateRoleDto } from '../dtos/role.dto';
6
6
  import { RoleBase } from '../entities/role-base.entity';
7
7
  import { IRole } from '../interfaces/role.interface';
8
8
  import { IAMConfigService } from './iam-config.service';
9
- import { IAMDataSourceProvider } from './iam-datasource.provider';
9
+ import { IAMDataSourceService } from './iam-datasource.service';
10
10
  export declare class RoleService extends RequestScopedApiService<CreateRoleDto, UpdateRoleDto, IRole, RoleBase, Repository<RoleBase>> {
11
11
  protected cacheManager: HybridCache;
12
12
  protected utilsService: UtilsService;
13
13
  private readonly iamConfigService;
14
14
  private readonly dataSourceProvider;
15
- constructor(cacheManager: HybridCache, utilsService: UtilsService, iamConfigService: IAMConfigService, dataSourceProvider: IAMDataSourceProvider);
15
+ constructor(cacheManager: HybridCache, utilsService: UtilsService, iamConfigService: IAMConfigService, dataSourceProvider: IAMDataSourceService);
16
16
  protected resolveEntity(): EntityTarget<RoleBase>;
17
- protected getDataSourceProvider(): IAMDataSourceProvider;
17
+ protected getDataSourceProvider(): IAMDataSourceService;
18
18
  convertSingleDtoToEntity(dto: CreateRoleDto | UpdateRoleDto, user: ILoggedUserInfo | null): Promise<RoleBase>;
19
19
  getSelectQuery(query: SelectQueryBuilder<RoleBase>, _user: ILoggedUserInfo | null, select?: string[]): Promise<{
20
20
  query: SelectQueryBuilder<RoleBase>;
@@ -5,11 +5,3 @@ export interface LogicNode {
5
5
  actionId?: string;
6
6
  children?: LogicNode[];
7
7
  }
8
- export declare enum LogicOperator {
9
- AND = "AND",
10
- OR = "OR"
11
- }
12
- export declare enum LogicNodeType {
13
- GROUP = "group",
14
- ACTION = "action"
15
- }
@@ -1,175 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "PermissionEvaluatorHelper", {
6
- enumerable: true,
7
- get: function() {
8
- return PermissionEvaluatorHelper;
9
- }
10
- });
11
- const _common = require("@nestjs/common");
12
- function _ts_decorate(decorators, target, key, desc) {
13
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
14
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
15
- 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;
16
- return c > 3 && r && Object.defineProperty(target, key, r), r;
17
- }
18
- let PermissionEvaluatorHelper = class PermissionEvaluatorHelper {
19
- /**
20
- * Evaluate if user has access based on permission logic
21
- *
22
- * @param logic - Permission logic to evaluate
23
- * @param context - User permission context
24
- * @returns true if user has access, false otherwise
25
- */ evaluate(logic, context) {
26
- // If no logic defined, access is granted
27
- if (!logic) {
28
- return true;
29
- }
30
- return this.evaluateNode(logic, context);
31
- }
32
- /**
33
- * Evaluate a single logic node
34
- */ evaluateNode(node, context) {
35
- switch(node.type){
36
- case 'action':
37
- return this.evaluateAction(node.actionId, context);
38
- case 'group':
39
- return this.evaluateGroup(node, context);
40
- default:
41
- // Unknown node type, deny access
42
- return false;
43
- }
44
- }
45
- /**
46
- * Evaluate action permission
47
- * Priority: Deny > Grant > Inherited
48
- */ evaluateAction(actionId, context) {
49
- // 1. Check explicit deny (highest priority)
50
- if (context.deniedActionIds.has(actionId)) {
51
- return false;
52
- }
53
- // 2. Check explicit grant
54
- if (context.grantedActionIds.has(actionId)) {
55
- return true;
56
- }
57
- // 3. Check inherited actions (from parent actions)
58
- if (context.inheritedActionIds?.has(actionId)) {
59
- return true;
60
- }
61
- // No permission found
62
- return false;
63
- }
64
- /**
65
- * Evaluate group (AND/OR logic)
66
- */ evaluateGroup(node, context) {
67
- if (!node.children || node.children.length === 0) {
68
- return false;
69
- }
70
- const results = node.children.map((child)=>this.evaluateNode(child, context));
71
- if (node.operator === 'AND') {
72
- // ALL children must be true
73
- return results.every((result)=>result === true);
74
- } else if (node.operator === 'OR') {
75
- // ANY child must be true
76
- return results.some((result)=>result === true);
77
- }
78
- // Unknown operator, deny access
79
- return false;
80
- }
81
- /**
82
- * Batch evaluate multiple logic nodes
83
- * Useful for checking multiple permissions at once
84
- *
85
- * @param logics - Array of logic nodes to evaluate
86
- * @param context - User permission context
87
- * @returns Map of logic ID to evaluation result
88
- */ batchEvaluate(logics, context) {
89
- const results = new Map();
90
- for (const item of logics){
91
- results.set(item.id, this.evaluate(item.logic, context));
92
- }
93
- return results;
94
- }
95
- /**
96
- * Check if user has ANY of the specified actions
97
- *
98
- * @param actionIds - Array of action IDs
99
- * @param context - User permission context
100
- * @returns true if user has at least one action
101
- */ hasAnyAction(actionIds, context) {
102
- return actionIds.some((actionId)=>this.evaluateAction(actionId, context));
103
- }
104
- /**
105
- * Check if user has ALL of the specified actions
106
- *
107
- * @param actionIds - Array of action IDs
108
- * @param context - User permission context
109
- * @returns true if user has all actions
110
- */ hasAllActions(actionIds, context) {
111
- return actionIds.every((actionId)=>this.evaluateAction(actionId, context));
112
- }
113
- /**
114
- * Check if user has ANY of the specified roles
115
- *
116
- * @param roleIds - Array of role IDs
117
- * @param context - User permission context
118
- * @returns true if user has at least one role
119
- */ hasAnyRole(roleIds, context) {
120
- return roleIds.some((roleId)=>context.roleIds.has(roleId));
121
- }
122
- /**
123
- * Check if user has ALL of the specified roles
124
- *
125
- * @param roleIds - Array of role IDs
126
- * @param context - User permission context
127
- * @returns true if user has all roles
128
- */ hasAllRoles(roleIds, context) {
129
- return roleIds.every((roleId)=>context.roleIds.has(roleId));
130
- }
131
- /**
132
- * Simplified evaluation for menu filtering
133
- * Uses action codes instead of action IDs
134
- *
135
- * @param logic - Permission logic to evaluate
136
- * @param actionCodes - Set of action codes the user has
137
- * @returns true if user has access, false otherwise
138
- */ evaluateLogicNode(logic, actionCodes) {
139
- if (!logic) {
140
- return true;
141
- }
142
- return this.evaluateNodeSimple(logic, actionCodes);
143
- }
144
- /**
145
- * Simplified node evaluation using codes
146
- */ evaluateNodeSimple(node, actionCodes) {
147
- switch(node.type){
148
- case 'action':
149
- // Check if user has action by actionId (which matches action.code)
150
- return node.actionId ? actionCodes.has(node.actionId) : false;
151
- case 'group':
152
- return this.evaluateGroupSimple(node, actionCodes);
153
- default:
154
- return false;
155
- }
156
- }
157
- /**
158
- * Simplified group evaluation
159
- */ evaluateGroupSimple(node, actionCodes) {
160
- if (!node.children || node.children.length === 0) {
161
- // Empty AND = true, Empty OR = false
162
- return node.operator === 'AND';
163
- }
164
- const results = node.children.map((child)=>this.evaluateNodeSimple(child, actionCodes));
165
- if (node.operator === 'AND') {
166
- return results.every((result)=>result === true);
167
- } else if (node.operator === 'OR') {
168
- return results.some((result)=>result === true);
169
- }
170
- return false;
171
- }
172
- };
173
- PermissionEvaluatorHelper = _ts_decorate([
174
- (0, _common.Injectable)()
175
- ], PermissionEvaluatorHelper);
@@ -1,4 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
@@ -1,165 +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 { Injectable } from '@nestjs/common';
8
- export class PermissionEvaluatorHelper {
9
- /**
10
- * Evaluate if user has access based on permission logic
11
- *
12
- * @param logic - Permission logic to evaluate
13
- * @param context - User permission context
14
- * @returns true if user has access, false otherwise
15
- */ evaluate(logic, context) {
16
- // If no logic defined, access is granted
17
- if (!logic) {
18
- return true;
19
- }
20
- return this.evaluateNode(logic, context);
21
- }
22
- /**
23
- * Evaluate a single logic node
24
- */ evaluateNode(node, context) {
25
- switch(node.type){
26
- case 'action':
27
- return this.evaluateAction(node.actionId, context);
28
- case 'group':
29
- return this.evaluateGroup(node, context);
30
- default:
31
- // Unknown node type, deny access
32
- return false;
33
- }
34
- }
35
- /**
36
- * Evaluate action permission
37
- * Priority: Deny > Grant > Inherited
38
- */ evaluateAction(actionId, context) {
39
- // 1. Check explicit deny (highest priority)
40
- if (context.deniedActionIds.has(actionId)) {
41
- return false;
42
- }
43
- // 2. Check explicit grant
44
- if (context.grantedActionIds.has(actionId)) {
45
- return true;
46
- }
47
- // 3. Check inherited actions (from parent actions)
48
- if (context.inheritedActionIds?.has(actionId)) {
49
- return true;
50
- }
51
- // No permission found
52
- return false;
53
- }
54
- /**
55
- * Evaluate group (AND/OR logic)
56
- */ evaluateGroup(node, context) {
57
- if (!node.children || node.children.length === 0) {
58
- return false;
59
- }
60
- const results = node.children.map((child)=>this.evaluateNode(child, context));
61
- if (node.operator === 'AND') {
62
- // ALL children must be true
63
- return results.every((result)=>result === true);
64
- } else if (node.operator === 'OR') {
65
- // ANY child must be true
66
- return results.some((result)=>result === true);
67
- }
68
- // Unknown operator, deny access
69
- return false;
70
- }
71
- /**
72
- * Batch evaluate multiple logic nodes
73
- * Useful for checking multiple permissions at once
74
- *
75
- * @param logics - Array of logic nodes to evaluate
76
- * @param context - User permission context
77
- * @returns Map of logic ID to evaluation result
78
- */ batchEvaluate(logics, context) {
79
- const results = new Map();
80
- for (const item of logics){
81
- results.set(item.id, this.evaluate(item.logic, context));
82
- }
83
- return results;
84
- }
85
- /**
86
- * Check if user has ANY of the specified actions
87
- *
88
- * @param actionIds - Array of action IDs
89
- * @param context - User permission context
90
- * @returns true if user has at least one action
91
- */ hasAnyAction(actionIds, context) {
92
- return actionIds.some((actionId)=>this.evaluateAction(actionId, context));
93
- }
94
- /**
95
- * Check if user has ALL of the specified actions
96
- *
97
- * @param actionIds - Array of action IDs
98
- * @param context - User permission context
99
- * @returns true if user has all actions
100
- */ hasAllActions(actionIds, context) {
101
- return actionIds.every((actionId)=>this.evaluateAction(actionId, context));
102
- }
103
- /**
104
- * Check if user has ANY of the specified roles
105
- *
106
- * @param roleIds - Array of role IDs
107
- * @param context - User permission context
108
- * @returns true if user has at least one role
109
- */ hasAnyRole(roleIds, context) {
110
- return roleIds.some((roleId)=>context.roleIds.has(roleId));
111
- }
112
- /**
113
- * Check if user has ALL of the specified roles
114
- *
115
- * @param roleIds - Array of role IDs
116
- * @param context - User permission context
117
- * @returns true if user has all roles
118
- */ hasAllRoles(roleIds, context) {
119
- return roleIds.every((roleId)=>context.roleIds.has(roleId));
120
- }
121
- /**
122
- * Simplified evaluation for menu filtering
123
- * Uses action codes instead of action IDs
124
- *
125
- * @param logic - Permission logic to evaluate
126
- * @param actionCodes - Set of action codes the user has
127
- * @returns true if user has access, false otherwise
128
- */ evaluateLogicNode(logic, actionCodes) {
129
- if (!logic) {
130
- return true;
131
- }
132
- return this.evaluateNodeSimple(logic, actionCodes);
133
- }
134
- /**
135
- * Simplified node evaluation using codes
136
- */ evaluateNodeSimple(node, actionCodes) {
137
- switch(node.type){
138
- case 'action':
139
- // Check if user has action by actionId (which matches action.code)
140
- return node.actionId ? actionCodes.has(node.actionId) : false;
141
- case 'group':
142
- return this.evaluateGroupSimple(node, actionCodes);
143
- default:
144
- return false;
145
- }
146
- }
147
- /**
148
- * Simplified group evaluation
149
- */ evaluateGroupSimple(node, actionCodes) {
150
- if (!node.children || node.children.length === 0) {
151
- // Empty AND = true, Empty OR = false
152
- return node.operator === 'AND';
153
- }
154
- const results = node.children.map((child)=>this.evaluateNodeSimple(child, actionCodes));
155
- if (node.operator === 'AND') {
156
- return results.every((result)=>result === true);
157
- } else if (node.operator === 'OR') {
158
- return results.some((result)=>result === true);
159
- }
160
- return false;
161
- }
162
- }
163
- PermissionEvaluatorHelper = _ts_decorate([
164
- Injectable()
165
- ], PermissionEvaluatorHelper);
@@ -1,3 +0,0 @@
1
- /**
2
- * Async options for IAMModule registration
3
- */ export { };