@klerick/acl-json-api-nestjs 0.1.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 (135) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +3556 -0
  3. package/package.json +41 -0
  4. package/src/index.d.ts +8 -0
  5. package/src/index.js +15 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/constants/index.d.ts +14 -0
  8. package/src/lib/constants/index.js +18 -0
  9. package/src/lib/constants/index.js.map +1 -0
  10. package/src/lib/decorators/acl-controller.decorator.d.ts +4 -0
  11. package/src/lib/decorators/acl-controller.decorator.js +19 -0
  12. package/src/lib/decorators/acl-controller.decorator.js.map +1 -0
  13. package/src/lib/decorators/index.d.ts +1 -0
  14. package/src/lib/decorators/index.js +6 -0
  15. package/src/lib/decorators/index.js.map +1 -0
  16. package/src/lib/factories/ability-proxy.factory.d.ts +17 -0
  17. package/src/lib/factories/ability-proxy.factory.js +100 -0
  18. package/src/lib/factories/ability-proxy.factory.js.map +1 -0
  19. package/src/lib/factories/ability.factory.d.ts +49 -0
  20. package/src/lib/factories/ability.factory.js +235 -0
  21. package/src/lib/factories/ability.factory.js.map +1 -0
  22. package/src/lib/factories/index.d.ts +2 -0
  23. package/src/lib/factories/index.js +6 -0
  24. package/src/lib/factories/index.js.map +1 -0
  25. package/src/lib/guards/acl.guard.d.ts +21 -0
  26. package/src/lib/guards/acl.guard.js +68 -0
  27. package/src/lib/guards/acl.guard.js.map +1 -0
  28. package/src/lib/guards/index.d.ts +1 -0
  29. package/src/lib/guards/index.js +5 -0
  30. package/src/lib/guards/index.js.map +1 -0
  31. package/src/lib/nestjs-acl-permissions.module.d.ts +9 -0
  32. package/src/lib/nestjs-acl-permissions.module.js +56 -0
  33. package/src/lib/nestjs-acl-permissions.module.js.map +1 -0
  34. package/src/lib/services/acl-authorization.service.d.ts +10 -0
  35. package/src/lib/services/acl-authorization.service.js +100 -0
  36. package/src/lib/services/acl-authorization.service.js.map +1 -0
  37. package/src/lib/services/index.d.ts +2 -0
  38. package/src/lib/services/index.js +6 -0
  39. package/src/lib/services/index.js.map +1 -0
  40. package/src/lib/services/rule-materializer.service.d.ts +73 -0
  41. package/src/lib/services/rule-materializer.service.js +251 -0
  42. package/src/lib/services/rule-materializer.service.js.map +1 -0
  43. package/src/lib/types/acl-context.types.d.ts +14 -0
  44. package/src/lib/types/acl-context.types.js +3 -0
  45. package/src/lib/types/acl-context.types.js.map +1 -0
  46. package/src/lib/types/acl-options.types.d.ts +97 -0
  47. package/src/lib/types/acl-options.types.js +3 -0
  48. package/src/lib/types/acl-options.types.js.map +1 -0
  49. package/src/lib/types/acl-rules.types.d.ts +201 -0
  50. package/src/lib/types/acl-rules.types.js +27 -0
  51. package/src/lib/types/acl-rules.types.js.map +1 -0
  52. package/src/lib/types/decorator-options.types.d.ts +64 -0
  53. package/src/lib/types/decorator-options.types.js +3 -0
  54. package/src/lib/types/decorator-options.types.js.map +1 -0
  55. package/src/lib/types/index.d.ts +4 -0
  56. package/src/lib/types/index.js +8 -0
  57. package/src/lib/types/index.js.map +1 -0
  58. package/src/lib/utils/index.d.ts +10 -0
  59. package/src/lib/utils/index.js +53 -0
  60. package/src/lib/utils/index.js.map +1 -0
  61. package/src/lib/utils/orm-proxy/extract-field-paths.d.ts +73 -0
  62. package/src/lib/utils/orm-proxy/extract-field-paths.js +155 -0
  63. package/src/lib/utils/orm-proxy/extract-field-paths.js.map +1 -0
  64. package/src/lib/utils/orm-proxy/handle-acl-query-error.d.ts +19 -0
  65. package/src/lib/utils/orm-proxy/handle-acl-query-error.js +53 -0
  66. package/src/lib/utils/orm-proxy/handle-acl-query-error.js.map +1 -0
  67. package/src/lib/utils/orm-proxy/index.d.ts +9 -0
  68. package/src/lib/utils/orm-proxy/index.js +24 -0
  69. package/src/lib/utils/orm-proxy/index.js.map +1 -0
  70. package/src/lib/utils/orm-proxy/merge-query-with-acl-data.d.ts +27 -0
  71. package/src/lib/utils/orm-proxy/merge-query-with-acl-data.js +78 -0
  72. package/src/lib/utils/orm-proxy/merge-query-with-acl-data.js.map +1 -0
  73. package/src/lib/utils/orm-proxy/prepare-acl-query.d.ts +11 -0
  74. package/src/lib/utils/orm-proxy/prepare-acl-query.js +35 -0
  75. package/src/lib/utils/orm-proxy/prepare-acl-query.js.map +1 -0
  76. package/src/lib/utils/orm-proxy/process-item-field-restrictions.d.ts +24 -0
  77. package/src/lib/utils/orm-proxy/process-item-field-restrictions.js +42 -0
  78. package/src/lib/utils/orm-proxy/process-item-field-restrictions.js.map +1 -0
  79. package/src/lib/utils/orm-proxy/remove-acl-added-fields.d.ts +31 -0
  80. package/src/lib/utils/orm-proxy/remove-acl-added-fields.js +104 -0
  81. package/src/lib/utils/orm-proxy/remove-acl-added-fields.js.map +1 -0
  82. package/src/lib/utils/orm-proxy/unset-deep.d.ts +13 -0
  83. package/src/lib/utils/orm-proxy/unset-deep.js +41 -0
  84. package/src/lib/utils/orm-proxy/unset-deep.js.map +1 -0
  85. package/src/lib/utils/orm-proxy/validate-no-current-in-rules.d.ts +19 -0
  86. package/src/lib/utils/orm-proxy/validate-no-current-in-rules.js +33 -0
  87. package/src/lib/utils/orm-proxy/validate-no-current-in-rules.js.map +1 -0
  88. package/src/lib/utils/orm-proxy/validate-rules-for-orm.d.ts +16 -0
  89. package/src/lib/utils/orm-proxy/validate-rules-for-orm.js +35 -0
  90. package/src/lib/utils/orm-proxy/validate-rules-for-orm.js.map +1 -0
  91. package/src/lib/wrappers/index.d.ts +9 -0
  92. package/src/lib/wrappers/index.js +32 -0
  93. package/src/lib/wrappers/index.js.map +1 -0
  94. package/src/lib/wrappers/logger-init.d.ts +2 -0
  95. package/src/lib/wrappers/logger-init.js +9 -0
  96. package/src/lib/wrappers/logger-init.js.map +1 -0
  97. package/src/lib/wrappers/wrapper-json-method-controller/get-proxy-orm.d.ts +4 -0
  98. package/src/lib/wrappers/wrapper-json-method-controller/get-proxy-orm.js +47 -0
  99. package/src/lib/wrappers/wrapper-json-method-controller/get-proxy-orm.js.map +1 -0
  100. package/src/lib/wrappers/wrapper-json-method-controller/index.d.ts +3 -0
  101. package/src/lib/wrappers/wrapper-json-method-controller/index.js +21 -0
  102. package/src/lib/wrappers/wrapper-json-method-controller/index.js.map +1 -0
  103. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-one-proxy.d.ts +3 -0
  104. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-one-proxy.js +51 -0
  105. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-one-proxy.js.map +1 -0
  106. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-relationship-proxy.d.ts +4 -0
  107. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-relationship-proxy.js +59 -0
  108. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-relationship-proxy.js.map +1 -0
  109. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-all-proxy.d.ts +13 -0
  110. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-all-proxy.js +67 -0
  111. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-all-proxy.js.map +1 -0
  112. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-one-proxy.d.ts +12 -0
  113. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-one-proxy.js +50 -0
  114. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-one-proxy.js.map +1 -0
  115. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-relationship-proxy.d.ts +4 -0
  116. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-relationship-proxy.js +50 -0
  117. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-relationship-proxy.js.map +1 -0
  118. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/index.d.ts +9 -0
  119. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/index.js +13 -0
  120. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/index.js.map +1 -0
  121. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-one-proxy.d.ts +3 -0
  122. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-one-proxy.js +132 -0
  123. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-one-proxy.js.map +1 -0
  124. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-relationship-proxy.d.ts +4 -0
  125. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-relationship-proxy.js +68 -0
  126. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-relationship-proxy.js.map +1 -0
  127. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-one-proxy.d.ts +3 -0
  128. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-one-proxy.js +73 -0
  129. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-one-proxy.js.map +1 -0
  130. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-relationship-proxy.d.ts +4 -0
  131. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-relationship-proxy.js +66 -0
  132. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-relationship-proxy.js.map +1 -0
  133. package/src/lib/wrappers/wrapper-json-method-controller/on-module-init.d.ts +2 -0
  134. package/src/lib/wrappers/wrapper-json-method-controller/on-module-init.js +16 -0
  135. package/src/lib/wrappers/wrapper-json-method-controller/on-module-init.js.map +1 -0
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var AclGuard_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.AclGuard = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const core_1 = require("@nestjs/core");
8
+ const services_1 = require("../services");
9
+ const constants_1 = require("../constants");
10
+ /**
11
+ * Guard for ACL permission checking
12
+ *
13
+ * Thin wrapper that delegates all logic to AclAuthorizationService
14
+ *
15
+ * Applied automatically by @AclController decorator
16
+ *
17
+ * Lifecycle: Guards run BEFORE interceptors and pipes
18
+ *
19
+ * Benefits:
20
+ * - Fails fast (before handler execution)
21
+ * - Semantic correctness (Guard = authorization)
22
+ * - Supports onNoRules policy (deny/allow/warn)
23
+ */
24
+ let AclGuard = AclGuard_1 = class AclGuard {
25
+ moduleRef;
26
+ reflector;
27
+ logger = new common_1.Logger(AclGuard_1.name);
28
+ async canActivate(executionContext) {
29
+ const controller = executionContext.getClass();
30
+ const handler = executionContext.getHandler();
31
+ const controllerName = controller.name;
32
+ const methodName = handler.name;
33
+ const metadata = this.reflector.get(constants_1.ACL_CONTROLLER_METADATA, controller);
34
+ if (!metadata) {
35
+ this.logger.debug(`No @AclController metadata found on ${controllerName}, allowing access`);
36
+ return true;
37
+ }
38
+ // If ACL is disabled for this controller
39
+ if (metadata.enabled === false) {
40
+ this.logger.debug(`ACL disabled for controller ${controllerName}, allowing access`);
41
+ return true;
42
+ }
43
+ // Check if ACL is enabled for this specific method
44
+ const isMethodEnabled = metadata.methods[methodName];
45
+ // If method configuration is explicitly false, allow access
46
+ if (isMethodEnabled === false) {
47
+ this.logger.debug(`ACL disabled for method ${controllerName}.${methodName}, allowing access`);
48
+ return true;
49
+ }
50
+ // Delegate all logic to authorization service
51
+ return this.moduleRef.get(services_1.AclAuthorizationService, {
52
+ strict: false,
53
+ }).authorize(controllerName, methodName, metadata);
54
+ }
55
+ };
56
+ exports.AclGuard = AclGuard;
57
+ tslib_1.__decorate([
58
+ (0, common_1.Inject)(core_1.ModuleRef),
59
+ tslib_1.__metadata("design:type", core_1.ModuleRef)
60
+ ], AclGuard.prototype, "moduleRef", void 0);
61
+ tslib_1.__decorate([
62
+ (0, common_1.Inject)(core_1.Reflector),
63
+ tslib_1.__metadata("design:type", core_1.Reflector)
64
+ ], AclGuard.prototype, "reflector", void 0);
65
+ exports.AclGuard = AclGuard = AclGuard_1 = tslib_1.__decorate([
66
+ (0, common_1.Injectable)()
67
+ ], AclGuard);
68
+ //# sourceMappingURL=acl.guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acl.guard.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/guards/acl.guard.ts"],"names":[],"mappings":";;;;;AAAA,2CAA2F;AAC3F,uCAAoD;AACpD,0CAAsD;AAEtD,4CAAuD;AAEvD;;;;;;;;;;;;;GAaG;AAEI,IAAM,QAAQ,gBAAd,MAAM,QAAQ;IACiB,SAAS,CAAa;IACtB,SAAS,CAAa;IAEzC,MAAM,GAAG,IAAI,eAAM,CAAC,UAAQ,CAAC,IAAI,CAAC,CAAC;IAEpD,KAAK,CAAC,WAAW,CAAC,gBAAkC;QAElD,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,EAAE,CAAC;QAC9C,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;QACvC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;QAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CACjC,mCAAuB,EACvB,UAAU,CACX,CAAC;QAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,uCAAuC,cAAc,mBAAmB,CACzE,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,yCAAyC;QACzC,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,+BAA+B,cAAc,mBAAmB,CACjE,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mDAAmD;QACnD,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAErD,4DAA4D;QAC5D,IAAI,eAAe,KAAK,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,2BAA2B,cAAc,IAAI,UAAU,mBAAmB,CAC3E,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,8CAA8C;QAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kCAAuB,EAAE;YACjD,MAAM,EAAE,KAAK;SACd,CAAC,CAAC,SAAS,CAAC,cAAc,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;CACF,CAAA;AAjDY,4BAAQ;AACiB;IAAnC,IAAA,eAAM,EAAC,gBAAS,CAAC;sCAA8B,gBAAS;2CAAC;AACtB;IAAnC,IAAA,eAAM,EAAC,gBAAS,CAAC;sCAA8B,gBAAS;2CAAC;mBAF/C,QAAQ;IADpB,IAAA,mBAAU,GAAE;GACA,QAAQ,CAiDpB"}
@@ -0,0 +1 @@
1
+ export * from './acl.guard';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./acl.guard"), exports);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/guards/index.ts"],"names":[],"mappings":";;;AAAA,sDAA4B"}
@@ -0,0 +1,9 @@
1
+ import { DynamicModule, OnModuleInit } from '@nestjs/common';
2
+ import type { AclModuleOptions } from './types';
3
+ export declare class AclPermissionsModule implements OnModuleInit {
4
+ private readonly moduleRef;
5
+ private readonly options;
6
+ private readonly logger;
7
+ static forRoot(options: AclModuleOptions): DynamicModule;
8
+ onModuleInit(): void;
9
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var AclPermissionsModule_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.AclPermissionsModule = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const core_1 = require("@nestjs/core");
8
+ const constants_1 = require("./constants");
9
+ const services_1 = require("./services");
10
+ const guards_1 = require("./guards");
11
+ const factories_1 = require("./factories");
12
+ let AclPermissionsModule = AclPermissionsModule_1 = class AclPermissionsModule {
13
+ moduleRef;
14
+ options;
15
+ logger = new common_1.Logger(AclPermissionsModule_1.name);
16
+ static forRoot(options) {
17
+ return {
18
+ module: AclPermissionsModule_1,
19
+ providers: [
20
+ {
21
+ provide: constants_1.ACL_MODULE_OPTIONS,
22
+ useValue: options,
23
+ },
24
+ guards_1.AclGuard,
25
+ services_1.AclAuthorizationService,
26
+ services_1.RuleMaterializer,
27
+ factories_1.AbilityFactoryProvider,
28
+ factories_1.AbilityProvider,
29
+ ],
30
+ exports: [guards_1.AclGuard, services_1.AclAuthorizationService, factories_1.AbilityProvider],
31
+ };
32
+ }
33
+ onModuleInit() {
34
+ try {
35
+ this.moduleRef.get(this.options.rulesLoader, { strict: false });
36
+ this.moduleRef.get(this.options.contextStore, { strict: false });
37
+ }
38
+ catch (error) {
39
+ this.logger.warn(`RulesLoader or ContextStore not found, ACL will not work`);
40
+ throw error;
41
+ }
42
+ }
43
+ };
44
+ exports.AclPermissionsModule = AclPermissionsModule;
45
+ tslib_1.__decorate([
46
+ (0, common_1.Inject)(core_1.ModuleRef),
47
+ tslib_1.__metadata("design:type", core_1.ModuleRef)
48
+ ], AclPermissionsModule.prototype, "moduleRef", void 0);
49
+ tslib_1.__decorate([
50
+ (0, common_1.Inject)(constants_1.ACL_MODULE_OPTIONS),
51
+ tslib_1.__metadata("design:type", Object)
52
+ ], AclPermissionsModule.prototype, "options", void 0);
53
+ exports.AclPermissionsModule = AclPermissionsModule = AclPermissionsModule_1 = tslib_1.__decorate([
54
+ (0, common_1.Module)({})
55
+ ], AclPermissionsModule);
56
+ //# sourceMappingURL=nestjs-acl-permissions.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nestjs-acl-permissions.module.js","sourceRoot":"","sources":["../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/nestjs-acl-permissions.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAMwB;AACxB,uCAAyC;AACzC,2CAAiD;AAEjD,yCAAuE;AACvE,qCAAoC;AACpC,2CAAsE;AAG/D,IAAM,oBAAoB,4BAA1B,MAAM,oBAAoB;IACK,SAAS,CAAa;IACb,OAAO,CAAoB;IACvD,MAAM,GAAG,IAAI,eAAM,CAAC,sBAAoB,CAAC,IAAI,CAAC,CAAC;IAChE,MAAM,CAAC,OAAO,CAAC,OAAyB;QACtC,OAAO;YACL,MAAM,EAAE,sBAAoB;YAC5B,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,8BAAkB;oBAC3B,QAAQ,EAAE,OAAO;iBAClB;gBACD,iBAAQ;gBACR,kCAAuB;gBACvB,2BAAgB;gBAChB,kCAAsB;gBACtB,2BAAe;aAChB;YACD,OAAO,EAAE,CAAC,iBAAQ,EAAE,kCAAuB,EAAE,2BAAe,CAAC;SAC9D,CAAC;IACJ,CAAC;IAED,YAAY;QACV,IAAI,CAAC;YACH,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAC,MAAM,EAAE,KAAK,EAAC,CAAC,CAAC;YAC9D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAC,MAAM,EAAE,KAAK,EAAC,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,0DAA0D,CAC3D,CAAC;YACF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF,CAAA;AAjCY,oDAAoB;AACK;IAAnC,IAAA,eAAM,EAAC,gBAAS,CAAC;sCAA8B,gBAAS;uDAAC;AACb;IAA5C,IAAA,eAAM,EAAC,8BAAkB,CAAC;;qDAA6C;+BAF7D,oBAAoB;IADhC,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,oBAAoB,CAiChC"}
@@ -0,0 +1,10 @@
1
+ import { AclControllerMetadata } from '../types';
2
+ export declare class AclAuthorizationService {
3
+ private readonly moduleRef;
4
+ private readonly options;
5
+ private readonly abilityFactory;
6
+ private readonly logger;
7
+ authorize(controllerName: string, action: string, metaData: AclControllerMetadata): Promise<boolean>;
8
+ private getDefaultRulesForAction;
9
+ private getSubjectFromInput;
10
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var AclAuthorizationService_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.AclAuthorizationService = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const core_1 = require("@nestjs/core");
8
+ const constants_1 = require("../constants");
9
+ const utils_1 = require("../utils");
10
+ const factories_1 = require("../factories");
11
+ let AclAuthorizationService = AclAuthorizationService_1 = class AclAuthorizationService {
12
+ moduleRef;
13
+ options;
14
+ abilityFactory;
15
+ logger = new common_1.Logger(AclAuthorizationService_1.name);
16
+ async authorize(controllerName, action, metaData) {
17
+ const { subject: subjectForRules } = metaData;
18
+ const actionOptions = (0, utils_1.getActionOptions)(this.options, metaData.methods[action]);
19
+ const subject = this.getSubjectFromInput(subjectForRules);
20
+ const rulesLoader = this.moduleRef.get(this.options.rulesLoader, { strict: false });
21
+ const [rules, context, helpers] = await Promise.all([
22
+ rulesLoader.loadRules(subjectForRules, action),
23
+ rulesLoader.getContext(),
24
+ rulesLoader.getHelpers(),
25
+ ]);
26
+ const resultRules = Array.isArray(rules) && rules.length > 0
27
+ ? rules
28
+ : this.getDefaultRulesForAction(controllerName, action, subject, actionOptions);
29
+ const ability = this.abilityFactory(subject, action, resultRules, context, helpers);
30
+ if (!ability.can(action, subject)) {
31
+ this.logger.debug(`Access denied for ${controllerName}.${action} (action: ${action}, subject: ${subject})`);
32
+ throw new common_1.ForbiddenException([
33
+ {
34
+ code: 'forbidden',
35
+ message: `not allow "${action}"`,
36
+ path: ['action'],
37
+ },
38
+ ], {
39
+ description: `Access denied for ${action} on ${subject}`,
40
+ });
41
+ }
42
+ const contextStore = this.moduleRef.get(this.options.contextStore, {
43
+ strict: false,
44
+ });
45
+ contextStore.set(constants_1.ACL_CONTEXT_KEY, ability);
46
+ return true;
47
+ }
48
+ getDefaultRulesForAction(controllerName, action, subject, actionOptions) {
49
+ if (actionOptions.defaultRules && actionOptions.defaultRules.length > 0) {
50
+ this.logger.debug(`No rules for ${controllerName}.${action}, applying defaultRules`);
51
+ return actionOptions.defaultRules;
52
+ }
53
+ const policy = actionOptions.onNoRules || 'deny';
54
+ if (policy === 'deny') {
55
+ this.logger.error(`No ACL rules defined for ${controllerName}.${action}, denying access (onNoRules: '${policy}')`);
56
+ throw new common_1.ForbiddenException([
57
+ {
58
+ code: 'forbidden',
59
+ message: `not allow access`,
60
+ path: [],
61
+ },
62
+ ], {
63
+ description: `No ACL rules defined for ${controllerName}.${action}`,
64
+ });
65
+ }
66
+ this.logger.warn(`No ACL rules defined for ${controllerName}.${action}, allowing access with permissive rule (onNoRules: '${policy}')`);
67
+ return [
68
+ {
69
+ action,
70
+ subject,
71
+ },
72
+ ];
73
+ }
74
+ getSubjectFromInput(subject) {
75
+ if (typeof subject === 'string') {
76
+ return subject;
77
+ }
78
+ if (typeof subject === 'function' && subject.name) {
79
+ return subject.name;
80
+ }
81
+ throw new Error('Entity shouldbe class or string');
82
+ }
83
+ };
84
+ exports.AclAuthorizationService = AclAuthorizationService;
85
+ tslib_1.__decorate([
86
+ (0, common_1.Inject)(core_1.ModuleRef),
87
+ tslib_1.__metadata("design:type", core_1.ModuleRef)
88
+ ], AclAuthorizationService.prototype, "moduleRef", void 0);
89
+ tslib_1.__decorate([
90
+ (0, common_1.Inject)(constants_1.ACL_MODULE_OPTIONS),
91
+ tslib_1.__metadata("design:type", Object)
92
+ ], AclAuthorizationService.prototype, "options", void 0);
93
+ tslib_1.__decorate([
94
+ (0, common_1.Inject)(factories_1.ABILITY_FACTORY),
95
+ tslib_1.__metadata("design:type", Function)
96
+ ], AclAuthorizationService.prototype, "abilityFactory", void 0);
97
+ exports.AclAuthorizationService = AclAuthorizationService = AclAuthorizationService_1 = tslib_1.__decorate([
98
+ (0, common_1.Injectable)()
99
+ ], AclAuthorizationService);
100
+ //# sourceMappingURL=acl-authorization.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acl-authorization.service.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/services/acl-authorization.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './acl-authorization.service';
2
+ export * from './rule-materializer.service';
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./acl-authorization.service"), exports);
5
+ tslib_1.__exportStar(require("./rule-materializer.service"), exports);
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/services/index.ts"],"names":[],"mappings":";;;AAAA,sEAA4C;AAC5C,sEAA2C"}
@@ -0,0 +1,73 @@
1
+ import { Logger } from '@nestjs/common';
2
+ import { AbilityTuple, MongoQuery, RawRuleFrom } from '@casl/ability';
3
+ import type { AclInputData } from '../types';
4
+ /**
5
+ * Service for materializing ACL rules by interpolating template variables
6
+ *
7
+ * Converts rules with templates like { userId: '${@input.userId}' }
8
+ * into materialized rules with actual values like { userId: 123 }
9
+ *
10
+ * Uses Tagged Template Literals via Function for safe and efficient evaluation
11
+ */
12
+ export declare class RuleMaterializer {
13
+ readonly logger: Logger;
14
+ private readonly QUOTE_PLACEHOLDER;
15
+ private readonly options;
16
+ private get strictMode();
17
+ /**
18
+ * Materializes ACL rules by replacing template variables with actual values
19
+ *
20
+ * @param rules - Array of rules with template strings
21
+ * @param context - Variables from getContext()
22
+ * @param helpers - Helper functions from getHelpers()
23
+ * @param input - External input data (available as @input in templates)
24
+ * @returns Materialized rules with interpolated values
25
+ *
26
+ * TODO: Support old/current values in addition to new input
27
+ * For patchOne operations, we need access to both:
28
+ * - @input.* - new values from request
29
+ * - @input.__current.* - old values from database
30
+ * This enables rules like "allow removing only self from array"
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const rules = [{ conditions: { userId: '${@input.id}' } }];
35
+ * const context = { currentUserId: 123 };
36
+ * const helpers = {};
37
+ * const input = { id: 456 };
38
+ *
39
+ * const materialized = materializer.materialize(rules, context, helpers, input);
40
+ * // Result: [{ conditions: { userId: 456 } }]
41
+ * ```
42
+ */
43
+ materialize<A extends AbilityTuple = AbilityTuple, C extends MongoQuery = MongoQuery>(rules: RawRuleFrom<A, C>[], context: Record<string, any>, helpers: Record<string, Function>, input?: AclInputData): RawRuleFrom<A, C>[];
44
+ /**
45
+ * Escapes special characters for use in template literal
46
+ */
47
+ private escapeForTemplateLiteral;
48
+ /**
49
+ * Evaluates JSON template using Tagged Template Literals
50
+ *
51
+ * Uses a tagged function that correctly formats different types:
52
+ * - strings → wrapped in quotes
53
+ * - arrays → JSON.stringify
54
+ * - numbers/booleans → as-is
55
+ */
56
+ private evaluateTaggedTemplate;
57
+ /**
58
+ * Creates tagged template function that formats placeholders by type
59
+ *
60
+ * IMPORTANT: Values are already inside JSON string quotes from stringify
61
+ * We need to REMOVE the quotes and insert raw JSON values
62
+ */
63
+ private createTaggedFunction;
64
+ /**
65
+ * Creates strict Proxy that throws error on undefined property access
66
+ * Used in strict mode to catch template errors early
67
+ */
68
+ private createStrictProxy;
69
+ /**
70
+ * Handles interpolation errors based on strict mode
71
+ */
72
+ private handleError;
73
+ }
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ var RuleMaterializer_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.RuleMaterializer = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const types_1 = require("../types");
8
+ const constants_1 = require("../constants");
9
+ /**
10
+ * Service for materializing ACL rules by interpolating template variables
11
+ *
12
+ * Converts rules with templates like { userId: '${@input.userId}' }
13
+ * into materialized rules with actual values like { userId: 123 }
14
+ *
15
+ * Uses Tagged Template Literals via Function for safe and efficient evaluation
16
+ */
17
+ let RuleMaterializer = RuleMaterializer_1 = class RuleMaterializer {
18
+ logger = new common_1.Logger(RuleMaterializer_1.name);
19
+ // Temporary placeholder to distinguish quotes inside strings from quotes around placeholders
20
+ // Example: {"name":"John"} has quotes inside, but {"name":"${userName}"} has placeholder quotes
21
+ QUOTE_PLACEHOLDER = '\u0000QUOTE\u0000';
22
+ options;
23
+ get strictMode() {
24
+ return !this.options ? true : !!this.options.strictInterpolation;
25
+ }
26
+ /**
27
+ * Materializes ACL rules by replacing template variables with actual values
28
+ *
29
+ * @param rules - Array of rules with template strings
30
+ * @param context - Variables from getContext()
31
+ * @param helpers - Helper functions from getHelpers()
32
+ * @param input - External input data (available as @input in templates)
33
+ * @returns Materialized rules with interpolated values
34
+ *
35
+ * TODO: Support old/current values in addition to new input
36
+ * For patchOne operations, we need access to both:
37
+ * - @input.* - new values from request
38
+ * - @input.__current.* - old values from database
39
+ * This enables rules like "allow removing only self from array"
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const rules = [{ conditions: { userId: '${@input.id}' } }];
44
+ * const context = { currentUserId: 123 };
45
+ * const helpers = {};
46
+ * const input = { id: 456 };
47
+ *
48
+ * const materialized = materializer.materialize(rules, context, helpers, input);
49
+ * // Result: [{ conditions: { userId: 456 } }]
50
+ * ```
51
+ */
52
+ materialize(rules, context, helpers, input) {
53
+ // In strict mode, wrap input in Proxy to catch undefined property access
54
+ const inputData = input || {};
55
+ const wrappedInput = this.strictMode
56
+ ? this.createStrictProxy(inputData, types_1.ACL_INPUT_VAR)
57
+ : inputData;
58
+ // Build scope with context, helpers, and input (without @)
59
+ const scope = {
60
+ ...context,
61
+ ...helpers,
62
+ [types_1.ACL_INPUT_VAR]: wrappedInput, // 'input' not '@input'
63
+ };
64
+ try {
65
+ // Convert rules to JSON string
66
+ let jsonStr = JSON.stringify(rules, (k, v) => k === 'subject' && typeof v === 'function' ? v.name : v);
67
+ // Replace @input with input (@ is not valid in JS variable names)
68
+ jsonStr = jsonStr.replaceAll(types_1.ACL_INPUT_TEMPLATE, types_1.ACL_INPUT_VAR);
69
+ // Replace \" with ' inside ${...} template expressions
70
+ // JSON.stringify escapes quotes as \" but inside template expressions we need '
71
+ // Example: ${checkStatus(user.status, \"active\")} → ${checkStatus(user.status, 'active')}
72
+ jsonStr = jsonStr.replace(/\$\{([^}]+)\}/g, (match, expr) => {
73
+ const fixedExpr = expr.replace(/\\"/g, "'");
74
+ return `\${${fixedExpr}}`;
75
+ });
76
+ // Replace remaining \" with placeholder (outside of ${...})
77
+ // This helps distinguish quotes around placeholders from quotes inside string values
78
+ jsonStr = jsonStr.replace(/\\"/g, this.QUOTE_PLACEHOLDER);
79
+ // Escape backticks for template literal
80
+ jsonStr = this.escapeForTemplateLiteral(jsonStr);
81
+ this.logger.debug(`JSON template prepared: ${jsonStr.substring(0, 200)}...`);
82
+ // Evaluate using tagged template
83
+ const result = this.evaluateTaggedTemplate(jsonStr, scope);
84
+ // Parse back to object
85
+ const materialized = JSON.parse(result);
86
+ this.logger.debug(`Materialized ${rules.length} rule(s) successfully`);
87
+ return materialized;
88
+ }
89
+ catch (error) {
90
+ const errorMessage = error instanceof Error ? error.message : String(error);
91
+ this.handleError(errorMessage, scope);
92
+ throw error; // Re-throw after logging
93
+ }
94
+ }
95
+ /**
96
+ * Escapes special characters for use in template literal
97
+ */
98
+ escapeForTemplateLiteral(str) {
99
+ return (str
100
+ // Escape backticks only
101
+ // Don't escape $ because we WANT ${...} to work as template expressions
102
+ .replace(/`/g, '\\`'));
103
+ }
104
+ /**
105
+ * Evaluates JSON template using Tagged Template Literals
106
+ *
107
+ * Uses a tagged function that correctly formats different types:
108
+ * - strings → wrapped in quotes
109
+ * - arrays → JSON.stringify
110
+ * - numbers/booleans → as-is
111
+ */
112
+ evaluateTaggedTemplate(jsonTemplate, scope) {
113
+ const scopeKeys = Object.keys(scope);
114
+ const scopeValues = Object.values(scope);
115
+ // Tagged template function that handles type formatting
116
+ const taggedFunc = this.createTaggedFunction();
117
+ // Create function: taggedFunc`${userId}${groupIds}...`
118
+ // Example: new Function('tag', 'userId', 'groupIds', 'return tag`...${userId}...${groupIds}...`')
119
+ const functionBody = `return tag\`${jsonTemplate}\`;`;
120
+ // Debug logging
121
+ if (functionBody.length > 500) {
122
+ this.logger.debug(`Function body (first 500 chars): ${functionBody.substring(0, 500)}`);
123
+ }
124
+ else {
125
+ this.logger.debug(`Function body: ${functionBody}`);
126
+ }
127
+ const evalFn = new Function('tag', ...scopeKeys, functionBody);
128
+ // Execute with tagged function and scope values
129
+ const result = evalFn(taggedFunc, ...scopeValues);
130
+ return result;
131
+ }
132
+ /**
133
+ * Creates tagged template function that formats placeholders by type
134
+ *
135
+ * IMPORTANT: Values are already inside JSON string quotes from stringify
136
+ * We need to REMOVE the quotes and insert raw JSON values
137
+ */
138
+ createTaggedFunction() {
139
+ return (literals, ...placeholders) => {
140
+ let result = '';
141
+ const placeholdersLength = placeholders.length;
142
+ for (let i = 0; i < placeholdersLength; i++) {
143
+ let literal = literals[i];
144
+ // Restore placeholder back to \"
145
+ literal = literal.replace(new RegExp(this.QUOTE_PLACEHOLDER, 'g'), '\\"');
146
+ // Check if literal ends with opening quote: "
147
+ // If so, we need to remove it and the closing quote from next literal
148
+ const endsWithQuote = literal.endsWith('"');
149
+ if (endsWithQuote) {
150
+ literal = literal.slice(0, -1); // Remove trailing "
151
+ }
152
+ result += literal;
153
+ const value = placeholders[i];
154
+ // Format value based on type
155
+ if (value === null) {
156
+ result += 'null';
157
+ }
158
+ else if (value === undefined) {
159
+ result += 'null'; // JSON doesn't have undefined
160
+ }
161
+ else if (typeof value === 'string') {
162
+ // Escape quotes and special characters for JSON string
163
+ const escaped = value
164
+ .replace(/\\/g, '\\\\')
165
+ .replace(/"/g, '\\"')
166
+ .replace(/\n/g, '\\n')
167
+ .replace(/\r/g, '\\r')
168
+ .replace(/\t/g, '\\t');
169
+ result += `"${escaped}"`;
170
+ }
171
+ else if (typeof value === 'number' || typeof value === 'boolean') {
172
+ result += String(value);
173
+ }
174
+ else if (Array.isArray(value)) {
175
+ result += JSON.stringify(value);
176
+ }
177
+ else if (value instanceof Date) {
178
+ result += `"${value.toISOString()}"`;
179
+ }
180
+ else if (typeof value === 'object') {
181
+ result += JSON.stringify(value);
182
+ }
183
+ else {
184
+ // Fallback
185
+ result += JSON.stringify(value);
186
+ }
187
+ // Handle closing quote if we removed opening quote
188
+ if (endsWithQuote && i + 1 < literals.length) {
189
+ const nextLiteral = literals[i + 1];
190
+ if (nextLiteral.startsWith('"')) {
191
+ // Skip the closing quote
192
+ literals = Object.assign([], literals, {
193
+ [i + 1]: nextLiteral.slice(1),
194
+ });
195
+ }
196
+ }
197
+ }
198
+ // Add final literal (restore placeholder here too)
199
+ let finalLiteral = literals[literals.length - 1];
200
+ finalLiteral = finalLiteral.replace(new RegExp(this.QUOTE_PLACEHOLDER, 'g'), '\\"');
201
+ result += finalLiteral;
202
+ return result;
203
+ };
204
+ }
205
+ /**
206
+ * Creates strict Proxy that throws error on undefined property access
207
+ * Used in strict mode to catch template errors early
208
+ */
209
+ createStrictProxy(obj, name) {
210
+ return new Proxy(obj, {
211
+ get: (target, prop) => {
212
+ // Allow symbol properties (like Symbol.toStringTag, Symbol.iterator, etc.)
213
+ if (typeof prop === 'symbol') {
214
+ return target[prop];
215
+ }
216
+ // Check if property exists
217
+ if (!(prop in target)) {
218
+ throw new ReferenceError(`Property '${name}.${String(prop)}' is not defined in strict mode`);
219
+ }
220
+ const value = target[prop];
221
+ // If value is an object, wrap it in Proxy too (for nested access)
222
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
223
+ return this.createStrictProxy(value, `${name}.${String(prop)}`);
224
+ }
225
+ return value;
226
+ },
227
+ });
228
+ }
229
+ /**
230
+ * Handles interpolation errors based on strict mode
231
+ */
232
+ handleError(errorMessage, scope) {
233
+ const scopeInfo = `Available variables: ${Object.keys(scope).join(', ')}`;
234
+ const fullMessage = `Failed to materialize rules: ${errorMessage}. ${scopeInfo}`;
235
+ if (this.strictMode) {
236
+ this.logger.error(fullMessage);
237
+ }
238
+ else {
239
+ this.logger.warn(fullMessage);
240
+ }
241
+ }
242
+ };
243
+ exports.RuleMaterializer = RuleMaterializer;
244
+ tslib_1.__decorate([
245
+ (0, common_1.Inject)(constants_1.ACL_MODULE_OPTIONS),
246
+ tslib_1.__metadata("design:type", Object)
247
+ ], RuleMaterializer.prototype, "options", void 0);
248
+ exports.RuleMaterializer = RuleMaterializer = RuleMaterializer_1 = tslib_1.__decorate([
249
+ (0, common_1.Injectable)()
250
+ ], RuleMaterializer);
251
+ //# sourceMappingURL=rule-materializer.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-materializer.service.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/services/rule-materializer.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Interface for context storage (e.g., ClsService from nestjs-cls)
3
+ * Allows passing rules and data through the request pipeline
4
+ */
5
+ export interface AclContextStore {
6
+ /**
7
+ * Set value in context
8
+ */
9
+ set<T = any>(key: any, value: T): void;
10
+ /**
11
+ * Get value from context
12
+ */
13
+ get<T = any>(key: any): T | undefined;
14
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=acl-context.types.js.map