@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.
- package/CHANGELOG.md +15 -0
- package/README.md +3556 -0
- package/package.json +41 -0
- package/src/index.d.ts +8 -0
- package/src/index.js +15 -0
- package/src/index.js.map +1 -0
- package/src/lib/constants/index.d.ts +14 -0
- package/src/lib/constants/index.js +18 -0
- package/src/lib/constants/index.js.map +1 -0
- package/src/lib/decorators/acl-controller.decorator.d.ts +4 -0
- package/src/lib/decorators/acl-controller.decorator.js +19 -0
- package/src/lib/decorators/acl-controller.decorator.js.map +1 -0
- package/src/lib/decorators/index.d.ts +1 -0
- package/src/lib/decorators/index.js +6 -0
- package/src/lib/decorators/index.js.map +1 -0
- package/src/lib/factories/ability-proxy.factory.d.ts +17 -0
- package/src/lib/factories/ability-proxy.factory.js +100 -0
- package/src/lib/factories/ability-proxy.factory.js.map +1 -0
- package/src/lib/factories/ability.factory.d.ts +49 -0
- package/src/lib/factories/ability.factory.js +235 -0
- package/src/lib/factories/ability.factory.js.map +1 -0
- package/src/lib/factories/index.d.ts +2 -0
- package/src/lib/factories/index.js +6 -0
- package/src/lib/factories/index.js.map +1 -0
- package/src/lib/guards/acl.guard.d.ts +21 -0
- package/src/lib/guards/acl.guard.js +68 -0
- package/src/lib/guards/acl.guard.js.map +1 -0
- package/src/lib/guards/index.d.ts +1 -0
- package/src/lib/guards/index.js +5 -0
- package/src/lib/guards/index.js.map +1 -0
- package/src/lib/nestjs-acl-permissions.module.d.ts +9 -0
- package/src/lib/nestjs-acl-permissions.module.js +56 -0
- package/src/lib/nestjs-acl-permissions.module.js.map +1 -0
- package/src/lib/services/acl-authorization.service.d.ts +10 -0
- package/src/lib/services/acl-authorization.service.js +100 -0
- package/src/lib/services/acl-authorization.service.js.map +1 -0
- package/src/lib/services/index.d.ts +2 -0
- package/src/lib/services/index.js +6 -0
- package/src/lib/services/index.js.map +1 -0
- package/src/lib/services/rule-materializer.service.d.ts +73 -0
- package/src/lib/services/rule-materializer.service.js +251 -0
- package/src/lib/services/rule-materializer.service.js.map +1 -0
- package/src/lib/types/acl-context.types.d.ts +14 -0
- package/src/lib/types/acl-context.types.js +3 -0
- package/src/lib/types/acl-context.types.js.map +1 -0
- package/src/lib/types/acl-options.types.d.ts +97 -0
- package/src/lib/types/acl-options.types.js +3 -0
- package/src/lib/types/acl-options.types.js.map +1 -0
- package/src/lib/types/acl-rules.types.d.ts +201 -0
- package/src/lib/types/acl-rules.types.js +27 -0
- package/src/lib/types/acl-rules.types.js.map +1 -0
- package/src/lib/types/decorator-options.types.d.ts +64 -0
- package/src/lib/types/decorator-options.types.js +3 -0
- package/src/lib/types/decorator-options.types.js.map +1 -0
- package/src/lib/types/index.d.ts +4 -0
- package/src/lib/types/index.js +8 -0
- package/src/lib/types/index.js.map +1 -0
- package/src/lib/utils/index.d.ts +10 -0
- package/src/lib/utils/index.js +53 -0
- package/src/lib/utils/index.js.map +1 -0
- package/src/lib/utils/orm-proxy/extract-field-paths.d.ts +73 -0
- package/src/lib/utils/orm-proxy/extract-field-paths.js +155 -0
- package/src/lib/utils/orm-proxy/extract-field-paths.js.map +1 -0
- package/src/lib/utils/orm-proxy/handle-acl-query-error.d.ts +19 -0
- package/src/lib/utils/orm-proxy/handle-acl-query-error.js +53 -0
- package/src/lib/utils/orm-proxy/handle-acl-query-error.js.map +1 -0
- package/src/lib/utils/orm-proxy/index.d.ts +9 -0
- package/src/lib/utils/orm-proxy/index.js +24 -0
- package/src/lib/utils/orm-proxy/index.js.map +1 -0
- package/src/lib/utils/orm-proxy/merge-query-with-acl-data.d.ts +27 -0
- package/src/lib/utils/orm-proxy/merge-query-with-acl-data.js +78 -0
- package/src/lib/utils/orm-proxy/merge-query-with-acl-data.js.map +1 -0
- package/src/lib/utils/orm-proxy/prepare-acl-query.d.ts +11 -0
- package/src/lib/utils/orm-proxy/prepare-acl-query.js +35 -0
- package/src/lib/utils/orm-proxy/prepare-acl-query.js.map +1 -0
- package/src/lib/utils/orm-proxy/process-item-field-restrictions.d.ts +24 -0
- package/src/lib/utils/orm-proxy/process-item-field-restrictions.js +42 -0
- package/src/lib/utils/orm-proxy/process-item-field-restrictions.js.map +1 -0
- package/src/lib/utils/orm-proxy/remove-acl-added-fields.d.ts +31 -0
- package/src/lib/utils/orm-proxy/remove-acl-added-fields.js +104 -0
- package/src/lib/utils/orm-proxy/remove-acl-added-fields.js.map +1 -0
- package/src/lib/utils/orm-proxy/unset-deep.d.ts +13 -0
- package/src/lib/utils/orm-proxy/unset-deep.js +41 -0
- package/src/lib/utils/orm-proxy/unset-deep.js.map +1 -0
- package/src/lib/utils/orm-proxy/validate-no-current-in-rules.d.ts +19 -0
- package/src/lib/utils/orm-proxy/validate-no-current-in-rules.js +33 -0
- package/src/lib/utils/orm-proxy/validate-no-current-in-rules.js.map +1 -0
- package/src/lib/utils/orm-proxy/validate-rules-for-orm.d.ts +16 -0
- package/src/lib/utils/orm-proxy/validate-rules-for-orm.js +35 -0
- package/src/lib/utils/orm-proxy/validate-rules-for-orm.js.map +1 -0
- package/src/lib/wrappers/index.d.ts +9 -0
- package/src/lib/wrappers/index.js +32 -0
- package/src/lib/wrappers/index.js.map +1 -0
- package/src/lib/wrappers/logger-init.d.ts +2 -0
- package/src/lib/wrappers/logger-init.js +9 -0
- package/src/lib/wrappers/logger-init.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/get-proxy-orm.d.ts +4 -0
- package/src/lib/wrappers/wrapper-json-method-controller/get-proxy-orm.js +47 -0
- package/src/lib/wrappers/wrapper-json-method-controller/get-proxy-orm.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/index.d.ts +3 -0
- package/src/lib/wrappers/wrapper-json-method-controller/index.js +21 -0
- package/src/lib/wrappers/wrapper-json-method-controller/index.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-one-proxy.d.ts +3 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-one-proxy.js +51 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-one-proxy.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-relationship-proxy.d.ts +4 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-relationship-proxy.js +59 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-relationship-proxy.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-all-proxy.d.ts +13 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-all-proxy.js +67 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-all-proxy.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-one-proxy.d.ts +12 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-one-proxy.js +50 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-one-proxy.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-relationship-proxy.d.ts +4 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-relationship-proxy.js +50 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-relationship-proxy.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/index.d.ts +9 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/index.js +13 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/index.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-one-proxy.d.ts +3 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-one-proxy.js +132 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-one-proxy.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-relationship-proxy.d.ts +4 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-relationship-proxy.js +68 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-relationship-proxy.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-one-proxy.d.ts +3 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-one-proxy.js +73 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-one-proxy.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-relationship-proxy.d.ts +4 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-relationship-proxy.js +66 -0
- package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-relationship-proxy.js.map +1 -0
- package/src/lib/wrappers/wrapper-json-method-controller/on-module-init.d.ts +2 -0
- package/src/lib/wrappers/wrapper-json-method-controller/on-module-init.js +16 -0
- package/src/lib/wrappers/wrapper-json-method-controller/on-module-init.js.map +1 -0
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@klerick/acl-json-api-nestjs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"@casl/ability": "^6.0.0"
|
|
6
|
+
},
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"main": "./src/index.js",
|
|
9
|
+
"typings": "./src/index.d.ts",
|
|
10
|
+
"peerDependencies": {
|
|
11
|
+
"@klerick/json-api-nestjs": "^10.0.0-beta.6"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
"./package.json": "./package.json",
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./src/index.d.ts",
|
|
17
|
+
"default": "./src/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"types": "./src/index.d.ts",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"contributors": [
|
|
23
|
+
{
|
|
24
|
+
"email": "klerick666@gmain.com",
|
|
25
|
+
"name": "Aleksandr Kharkovey"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/klerick/nestjs-json-api.git"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">= 20.0.0"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"**/*"
|
|
37
|
+
],
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NestJS ACL Permissions Module
|
|
3
|
+
* CASL-based access control for JSON API controllers
|
|
4
|
+
*/
|
|
5
|
+
export { AclPermissionsModule } from './lib/nestjs-acl-permissions.module';
|
|
6
|
+
export { AclAction, AclRule, AclRulesLoader, AclSubject } from './lib/types';
|
|
7
|
+
export { ExtendAbility } from './lib/factories';
|
|
8
|
+
export { wrapperJsonApiController } from './lib/wrappers';
|
package/src/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* NestJS ACL Permissions Module
|
|
4
|
+
* CASL-based access control for JSON API controllers
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.wrapperJsonApiController = exports.ExtendAbility = exports.AclPermissionsModule = void 0;
|
|
8
|
+
// Main module
|
|
9
|
+
var nestjs_acl_permissions_module_1 = require("./lib/nestjs-acl-permissions.module");
|
|
10
|
+
Object.defineProperty(exports, "AclPermissionsModule", { enumerable: true, get: function () { return nestjs_acl_permissions_module_1.AclPermissionsModule; } });
|
|
11
|
+
var factories_1 = require("./lib/factories");
|
|
12
|
+
Object.defineProperty(exports, "ExtendAbility", { enumerable: true, get: function () { return factories_1.ExtendAbility; } });
|
|
13
|
+
var wrappers_1 = require("./lib/wrappers");
|
|
14
|
+
Object.defineProperty(exports, "wrapperJsonApiController", { enumerable: true, get: function () { return wrappers_1.wrapperJsonApiController; } });
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/acl-permissions/nestjs-acl-permissions/src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,cAAc;AACd,qFAA2E;AAAlE,qIAAA,oBAAoB,OAAA;AAG7B,6CAAgD;AAAvC,0GAAA,aAAa,OAAA;AACtB,2CAA0D;AAAjD,oHAAA,wBAAwB,OAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token for injecting ACL module options
|
|
3
|
+
*/
|
|
4
|
+
export declare const ACL_MODULE_OPTIONS: unique symbol;
|
|
5
|
+
/**
|
|
6
|
+
* Metadata key for @AclController decorator
|
|
7
|
+
*/
|
|
8
|
+
export declare const ACL_CONTROLLER_METADATA: unique symbol;
|
|
9
|
+
/**
|
|
10
|
+
* Key for storing ACL data in context
|
|
11
|
+
*/
|
|
12
|
+
export declare const ACL_CONTEXT_KEY: unique symbol;
|
|
13
|
+
export declare const MODULE_REF_PROPS: unique symbol;
|
|
14
|
+
export declare const ORIGINAL_ORM_SERVICE: unique symbol;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ORIGINAL_ORM_SERVICE = exports.MODULE_REF_PROPS = exports.ACL_CONTEXT_KEY = exports.ACL_CONTROLLER_METADATA = exports.ACL_MODULE_OPTIONS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Token for injecting ACL module options
|
|
6
|
+
*/
|
|
7
|
+
exports.ACL_MODULE_OPTIONS = Symbol('ACL_MODULE_OPTIONS');
|
|
8
|
+
/**
|
|
9
|
+
* Metadata key for @AclController decorator
|
|
10
|
+
*/
|
|
11
|
+
exports.ACL_CONTROLLER_METADATA = Symbol('ACL_CONTROLLER_METADATA');
|
|
12
|
+
/**
|
|
13
|
+
* Key for storing ACL data in context
|
|
14
|
+
*/
|
|
15
|
+
exports.ACL_CONTEXT_KEY = Symbol('ACL_CONTEXT_KEY');
|
|
16
|
+
exports.MODULE_REF_PROPS = Symbol('MODULE_REF_PROPS');
|
|
17
|
+
exports.ORIGINAL_ORM_SERVICE = Symbol('ORIGINAL_ORM_SERVICE');
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/constants/index.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACU,QAAA,kBAAkB,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAE/D;;GAEG;AACU,QAAA,uBAAuB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AACzE;;GAEG;AACU,QAAA,eAAe,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAG5C,QAAA,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAC9C,QAAA,oBAAoB,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AnyEntity } from '@klerick/json-api-nestjs-shared';
|
|
2
|
+
import type { JsonBaseController } from '@klerick/json-api-nestjs';
|
|
3
|
+
import type { AclControllerOptions } from '../types';
|
|
4
|
+
export declare function AclController<E extends AnyEntity = AnyEntity, Controller = JsonBaseController<E, 'id'>>(options: AclControllerOptions<E, Controller>): <T extends abstract new (...args: any[]) => any>(target: T) => T;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AclController = AclController;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
const guards_1 = require("../guards");
|
|
7
|
+
function AclController(options) {
|
|
8
|
+
return function (target) {
|
|
9
|
+
const metadata = {
|
|
10
|
+
subject: options.subject,
|
|
11
|
+
methods: (options.methods || {}),
|
|
12
|
+
enabled: options.enabled ?? true,
|
|
13
|
+
};
|
|
14
|
+
Reflect.defineMetadata(constants_1.ACL_CONTROLLER_METADATA, metadata, target);
|
|
15
|
+
(0, common_1.UseGuards)(guards_1.AclGuard)(target);
|
|
16
|
+
return target;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=acl-controller.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acl-controller.decorator.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/decorators/acl-controller.decorator.ts"],"names":[],"mappings":";;AAQA,sCAiBC;AAvBD,2CAA2C;AAC3C,4CAAuD;AAGvD,sCAAqC;AAErC,SAAgB,aAAa,CAG3B,OAA4C;IAC5C,OAAO,UACL,MAAS;QAET,MAAM,QAAQ,GAA6B;YACzC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAgD;YAC/E,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI;SACjC,CAAC;QAEF,OAAO,CAAC,cAAc,CAAC,mCAAuB,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClE,IAAA,kBAAS,EAAC,iBAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AclController } from './acl-controller.decorator';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AclController = void 0;
|
|
4
|
+
var acl_controller_decorator_1 = require("./acl-controller.decorator");
|
|
5
|
+
Object.defineProperty(exports, "AclController", { enumerable: true, get: function () { return acl_controller_decorator_1.AclController; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/decorators/index.ts"],"names":[],"mappings":";;;AAAA,uEAA2D;AAAlD,yHAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ModuleRef } from '@nestjs/core';
|
|
2
|
+
import type { AclModuleOptions } from '../types';
|
|
3
|
+
import { ExtendAbility } from './ability.factory';
|
|
4
|
+
import { FactoryProvider } from '@nestjs/common';
|
|
5
|
+
/**
|
|
6
|
+
* Creates a Proxy for ExtendableAbility that lazily retrieves the actual ability
|
|
7
|
+
* from CLS (Continuation Local Storage) on each method/property access.
|
|
8
|
+
*
|
|
9
|
+
* This allows the provider to be a SINGLETON while still accessing request-specific
|
|
10
|
+
* ability instances without using Scope.REQUEST.
|
|
11
|
+
*
|
|
12
|
+
* @param moduleRef - NestJS ModuleRef for lazy dependency resolution
|
|
13
|
+
* @param options - ACL module options containing contextStore configuration
|
|
14
|
+
* @returns Proxy that acts as ExtendableAbility
|
|
15
|
+
*/
|
|
16
|
+
export declare function createAbilityProxy(moduleRef: ModuleRef, options: AclModuleOptions): ExtendAbility;
|
|
17
|
+
export declare const AbilityProvider: FactoryProvider<ExtendAbility>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbilityProvider = void 0;
|
|
4
|
+
exports.createAbilityProxy = createAbilityProxy;
|
|
5
|
+
const core_1 = require("@nestjs/core");
|
|
6
|
+
const ability_factory_1 = require("./ability.factory");
|
|
7
|
+
const constants_1 = require("../constants");
|
|
8
|
+
/**
|
|
9
|
+
* Creates a Proxy for ExtendableAbility that lazily retrieves the actual ability
|
|
10
|
+
* from CLS (Continuation Local Storage) on each method/property access.
|
|
11
|
+
*
|
|
12
|
+
* This allows the provider to be a SINGLETON while still accessing request-specific
|
|
13
|
+
* ability instances without using Scope.REQUEST.
|
|
14
|
+
*
|
|
15
|
+
* @param moduleRef - NestJS ModuleRef for lazy dependency resolution
|
|
16
|
+
* @param options - ACL module options containing contextStore configuration
|
|
17
|
+
* @returns Proxy that acts as ExtendableAbility
|
|
18
|
+
*/
|
|
19
|
+
function createAbilityProxy(moduleRef, options) {
|
|
20
|
+
let contextStore;
|
|
21
|
+
/**
|
|
22
|
+
* Lazily initializes and retrieves the context store
|
|
23
|
+
*/
|
|
24
|
+
const getContextStore = () => {
|
|
25
|
+
if (!contextStore && options.contextStore) {
|
|
26
|
+
contextStore = moduleRef.get(options.contextStore, {
|
|
27
|
+
strict: false,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return contextStore;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Retrieves ExtendableAbility from CLS for the current request
|
|
34
|
+
* Throws descriptive error if ability is not found
|
|
35
|
+
*/
|
|
36
|
+
const getAbility = () => {
|
|
37
|
+
const store = getContextStore();
|
|
38
|
+
if (!store) {
|
|
39
|
+
throw new Error('[ACL] contextStore is not configured. ' +
|
|
40
|
+
'Make sure you configured AclPermissionsModule.forRoot() with contextStore option. ' +
|
|
41
|
+
'Example: { contextStore: ClsService }');
|
|
42
|
+
}
|
|
43
|
+
const ability = store.get(constants_1.ACL_CONTEXT_KEY);
|
|
44
|
+
if (!ability) {
|
|
45
|
+
throw new Error('[ACL] ExtendAbility not found in context store. ' +
|
|
46
|
+
'Possible causes:\n' +
|
|
47
|
+
' 1. Service is called BEFORE AclGuard executed (ability not yet created)\n' +
|
|
48
|
+
' 2. No rules loaded for this action (check your RulesLoader.loadRules())\n' +
|
|
49
|
+
' 3. AclGuard was not applied to this controller (check @AclController or wrapperJsonApiController hook)\n' +
|
|
50
|
+
' 4. contextStore middleware is not mounted (check ClsModule configuration)');
|
|
51
|
+
}
|
|
52
|
+
return ability;
|
|
53
|
+
};
|
|
54
|
+
// Create Proxy that forwards all method/property access to the real ExtendableAbility
|
|
55
|
+
return new Proxy({}, {
|
|
56
|
+
get(target, prop) {
|
|
57
|
+
if (!Reflect.has(ability_factory_1.ExtendAbility.prototype, prop)) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
// Special handling for Symbol.toStringTag (used by Object.prototype.toString)
|
|
61
|
+
if (prop === Symbol.toStringTag) {
|
|
62
|
+
return 'ExtendableAbility';
|
|
63
|
+
}
|
|
64
|
+
// Special handling for typeof checks
|
|
65
|
+
if (prop === 'constructor') {
|
|
66
|
+
return ability_factory_1.ExtendAbility;
|
|
67
|
+
}
|
|
68
|
+
// Get the actual ability from CLS
|
|
69
|
+
const ability = getAbility();
|
|
70
|
+
// Get the property/method from the real ability
|
|
71
|
+
const value = Reflect.get(ability, prop, ability);
|
|
72
|
+
// If it's a function, bind it to the ability instance
|
|
73
|
+
if (typeof value === 'function') {
|
|
74
|
+
return value.bind(ability);
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
},
|
|
78
|
+
// Support for 'prop in ability' checks
|
|
79
|
+
has(target, prop) {
|
|
80
|
+
const ability = getAbility();
|
|
81
|
+
return Reflect.has(ability, prop);
|
|
82
|
+
},
|
|
83
|
+
// Support for Object.keys(), Object.getOwnPropertyNames(), etc.
|
|
84
|
+
ownKeys(target) {
|
|
85
|
+
const ability = getAbility();
|
|
86
|
+
return Reflect.ownKeys(ability);
|
|
87
|
+
},
|
|
88
|
+
// Support for Object.getOwnPropertyDescriptor()
|
|
89
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
90
|
+
const ability = getAbility();
|
|
91
|
+
return Reflect.getOwnPropertyDescriptor(ability, prop);
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
exports.AbilityProvider = {
|
|
96
|
+
provide: ability_factory_1.ExtendAbility,
|
|
97
|
+
useFactory: createAbilityProxy,
|
|
98
|
+
inject: [core_1.ModuleRef, constants_1.ACL_MODULE_OPTIONS],
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=ability-proxy.factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ability-proxy.factory.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/factories/ability-proxy.factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { FactoryProvider } from '@nestjs/common';
|
|
2
|
+
import { AbilityTuple, MongoQuery, PureAbility, RawRuleFrom } from '@casl/ability';
|
|
3
|
+
import { RuleMaterializer } from '../services';
|
|
4
|
+
import { AclInputData, AclRule } from '../types';
|
|
5
|
+
import { Query, QueryOne } from '@klerick/json-api-nestjs';
|
|
6
|
+
import { QueryField } from '@klerick/json-api-nestjs-shared';
|
|
7
|
+
export type AbilityFactory = (subject: string, action: string, rules: AclRule[], context: Record<string, unknown>, helpers: Record<string, (...args: unknown[]) => unknown>) => ExtendAbility;
|
|
8
|
+
export declare const ABILITY_FACTORY: unique symbol;
|
|
9
|
+
export declare const AbilityFactoryProvider: FactoryProvider;
|
|
10
|
+
export declare class ExtendAbility<A extends AbilityTuple = AbilityTuple, C extends MongoQuery = MongoQuery> extends PureAbility<A, C> {
|
|
11
|
+
private ruleMaterializer;
|
|
12
|
+
private currentSubject;
|
|
13
|
+
private currentAction;
|
|
14
|
+
private allRules;
|
|
15
|
+
private readonly context;
|
|
16
|
+
private readonly helpers;
|
|
17
|
+
private _hasFields;
|
|
18
|
+
private _hasConditions;
|
|
19
|
+
constructor(ruleMaterializer: RuleMaterializer, currentSubject: string, currentAction: string, allRules: RawRuleFrom<A, C>[], context: Record<string, unknown>, helpers: Record<string, (...args: unknown[]) => unknown>);
|
|
20
|
+
updateWithInput(input: AclInputData): void;
|
|
21
|
+
get hasConditions(): boolean;
|
|
22
|
+
get hasFields(): boolean;
|
|
23
|
+
get action(): string;
|
|
24
|
+
get subject(): string;
|
|
25
|
+
hasConditionsAndFields(): boolean;
|
|
26
|
+
getQueryObject<E extends object, IdKey extends string, Q extends QueryOne<E, IdKey> | Query<E, IdKey>>(): {
|
|
27
|
+
fields?: Q[QueryField.fields];
|
|
28
|
+
include?: Q[QueryField.include];
|
|
29
|
+
rulesForQuery?: Record<string, unknown>;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Process conditions recursively: extract fields, transform structure, transform operators for MikroORM
|
|
33
|
+
*/
|
|
34
|
+
private processConditionsForQuery;
|
|
35
|
+
/**
|
|
36
|
+
* Transform CASL operators to MikroORM operators in field values
|
|
37
|
+
* $regex → $re, $all → $contains
|
|
38
|
+
*/
|
|
39
|
+
private transformOperatorsInValue;
|
|
40
|
+
/**
|
|
41
|
+
* Check if MongoDB query is empty
|
|
42
|
+
*/
|
|
43
|
+
private isEmptyQuery;
|
|
44
|
+
/**
|
|
45
|
+
* Splits rules into those with @input templates and without
|
|
46
|
+
* Rules with @input will be materialized lazily
|
|
47
|
+
*/
|
|
48
|
+
private static splitRulesByInput;
|
|
49
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExtendAbility = exports.AbilityFactoryProvider = exports.ABILITY_FACTORY = void 0;
|
|
4
|
+
const ability_1 = require("@casl/ability");
|
|
5
|
+
const extra_1 = require("@casl/ability/extra");
|
|
6
|
+
const services_1 = require("../services");
|
|
7
|
+
const types_1 = require("../types");
|
|
8
|
+
const core_1 = require("@nestjs/core");
|
|
9
|
+
exports.ABILITY_FACTORY = Symbol('ABILITY_FACTORY');
|
|
10
|
+
exports.AbilityFactoryProvider = {
|
|
11
|
+
provide: exports.ABILITY_FACTORY,
|
|
12
|
+
useFactory: function AbilityFactory(moduleRef) {
|
|
13
|
+
return function createEmptyAbility(subject, action, rules, context, helpers) {
|
|
14
|
+
return new ExtendAbility(moduleRef.get(services_1.RuleMaterializer), subject, action, rules, context, helpers);
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
inject: [core_1.ModuleRef],
|
|
18
|
+
};
|
|
19
|
+
class ExtendAbility extends ability_1.PureAbility {
|
|
20
|
+
ruleMaterializer;
|
|
21
|
+
currentSubject;
|
|
22
|
+
currentAction;
|
|
23
|
+
allRules;
|
|
24
|
+
context;
|
|
25
|
+
helpers;
|
|
26
|
+
_hasFields = undefined;
|
|
27
|
+
_hasConditions = undefined;
|
|
28
|
+
constructor(ruleMaterializer, currentSubject, currentAction, allRules, context, helpers) {
|
|
29
|
+
const { withoutInput } = ExtendAbility.splitRulesByInput(allRules);
|
|
30
|
+
const materialized = ruleMaterializer.materialize(withoutInput, context, helpers, undefined // NO @input
|
|
31
|
+
);
|
|
32
|
+
super(materialized, {
|
|
33
|
+
conditionsMatcher: ability_1.mongoQueryMatcher,
|
|
34
|
+
fieldMatcher: ability_1.fieldPatternMatcher,
|
|
35
|
+
});
|
|
36
|
+
this.ruleMaterializer = ruleMaterializer;
|
|
37
|
+
this.currentSubject = currentSubject;
|
|
38
|
+
this.currentAction = currentAction;
|
|
39
|
+
this.allRules = allRules;
|
|
40
|
+
this.context = context;
|
|
41
|
+
this.helpers = helpers;
|
|
42
|
+
}
|
|
43
|
+
updateWithInput(input) {
|
|
44
|
+
const materialized = this.ruleMaterializer.materialize(this.allRules, this.context, this.helpers, input);
|
|
45
|
+
this.update(materialized);
|
|
46
|
+
}
|
|
47
|
+
get hasConditions() {
|
|
48
|
+
if (this._hasConditions === undefined) {
|
|
49
|
+
this.hasConditionsAndFields();
|
|
50
|
+
}
|
|
51
|
+
return this._hasConditions;
|
|
52
|
+
}
|
|
53
|
+
get hasFields() {
|
|
54
|
+
if (this._hasFields === undefined) {
|
|
55
|
+
this.hasConditionsAndFields();
|
|
56
|
+
}
|
|
57
|
+
return this._hasFields;
|
|
58
|
+
}
|
|
59
|
+
get action() {
|
|
60
|
+
return this.currentAction;
|
|
61
|
+
}
|
|
62
|
+
get subject() {
|
|
63
|
+
return this.currentSubject;
|
|
64
|
+
}
|
|
65
|
+
hasConditionsAndFields() {
|
|
66
|
+
const rules = this.allRules;
|
|
67
|
+
for (let i = 0; i < rules.length; i++) {
|
|
68
|
+
if (rules[i].conditions !== undefined) {
|
|
69
|
+
this._hasConditions = true;
|
|
70
|
+
}
|
|
71
|
+
if (rules[i].fields !== undefined) {
|
|
72
|
+
this._hasFields = true;
|
|
73
|
+
}
|
|
74
|
+
if (this._hasConditions === true && this._hasFields === true)
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
// Set false if not found
|
|
78
|
+
if (this._hasConditions === undefined) {
|
|
79
|
+
this._hasConditions = false;
|
|
80
|
+
}
|
|
81
|
+
if (this._hasFields === undefined) {
|
|
82
|
+
this._hasFields = false;
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
getQueryObject() {
|
|
87
|
+
const fieldMap = new Map();
|
|
88
|
+
const includeSet = new Set();
|
|
89
|
+
const rulesForQuery = (0, extra_1.rulesToQuery)(this, this.currentAction, this.currentSubject, (rule) => {
|
|
90
|
+
const { conditions, inverted } = rule;
|
|
91
|
+
if (!conditions)
|
|
92
|
+
return {};
|
|
93
|
+
const transformed = this.processConditionsForQuery(conditions, fieldMap, includeSet);
|
|
94
|
+
return inverted ? { $not: transformed } : transformed;
|
|
95
|
+
});
|
|
96
|
+
// Build fields as object (not array)
|
|
97
|
+
let fields = undefined;
|
|
98
|
+
let include = undefined;
|
|
99
|
+
if (fieldMap.size > 0) {
|
|
100
|
+
fields = {};
|
|
101
|
+
Array.from(fieldMap.entries()).forEach(([key, valueSet]) => {
|
|
102
|
+
fields[key] = Array.from(valueSet);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (includeSet.size > 0) {
|
|
106
|
+
include = Array.from(includeSet);
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
...(fields && { fields }),
|
|
110
|
+
...(include && { include }),
|
|
111
|
+
// Return undefined if rulesForQuery is null or empty object
|
|
112
|
+
...(rulesForQuery &&
|
|
113
|
+
!this.isEmptyQuery(rulesForQuery) && {
|
|
114
|
+
rulesForQuery,
|
|
115
|
+
}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Process conditions recursively: extract fields, transform structure, transform operators for MikroORM
|
|
120
|
+
*/
|
|
121
|
+
processConditionsForQuery(conditions, fieldMap, includeSet) {
|
|
122
|
+
const result = {};
|
|
123
|
+
for (const [fieldPath, value] of Object.entries(conditions)) {
|
|
124
|
+
// MongoDB operators at top level ($or, $and, $nor, etc.)
|
|
125
|
+
if (fieldPath.startsWith('$')) {
|
|
126
|
+
// Transform $nor → $not: { $or: [...] }
|
|
127
|
+
if (fieldPath === '$nor' && Array.isArray(value)) {
|
|
128
|
+
result['$not'] = {
|
|
129
|
+
$or: value.map((subCondition) => this.processConditionsForQuery(subCondition, fieldMap, includeSet)),
|
|
130
|
+
};
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
// For $or/$and, recursively process
|
|
134
|
+
if ((fieldPath === '$or' || fieldPath === '$and') && Array.isArray(value)) {
|
|
135
|
+
result[fieldPath] = value.map((subCondition) => this.processConditionsForQuery(subCondition, fieldMap, includeSet));
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// Keep other operators as is
|
|
139
|
+
result[fieldPath] = value;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
// Parse field path
|
|
143
|
+
const [firstPart, secondPart] = fieldPath.split('.');
|
|
144
|
+
if (!secondPart) {
|
|
145
|
+
// Target entity field: 'authorId'
|
|
146
|
+
const targetSet = fieldMap.get('target') || new Set();
|
|
147
|
+
targetSet.add(firstPart);
|
|
148
|
+
fieldMap.set('target', targetSet);
|
|
149
|
+
// Transform operators in field values
|
|
150
|
+
result[firstPart] = this.transformOperatorsInValue(value);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// Relation field: 'profile.name'
|
|
154
|
+
const relationSet = fieldMap.get(firstPart) || new Set();
|
|
155
|
+
relationSet.add(secondPart);
|
|
156
|
+
fieldMap.set(firstPart, relationSet);
|
|
157
|
+
includeSet.add(firstPart);
|
|
158
|
+
// Transform: 'profile.name' → { profile: { name: value } }
|
|
159
|
+
// Merge multiple fields from same relation
|
|
160
|
+
if (!result[firstPart]) {
|
|
161
|
+
result[firstPart] = {};
|
|
162
|
+
}
|
|
163
|
+
result[firstPart][secondPart] =
|
|
164
|
+
this.transformOperatorsInValue(value);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Transform CASL operators to MikroORM operators in field values
|
|
171
|
+
* $regex → $re, $all → $contains
|
|
172
|
+
*/
|
|
173
|
+
transformOperatorsInValue(value) {
|
|
174
|
+
if (value === null || typeof value !== 'object') {
|
|
175
|
+
return value;
|
|
176
|
+
}
|
|
177
|
+
if (Array.isArray(value)) {
|
|
178
|
+
return value.map((item) => this.transformOperatorsInValue(item));
|
|
179
|
+
}
|
|
180
|
+
const result = {};
|
|
181
|
+
for (const [key, val] of Object.entries(value)) {
|
|
182
|
+
// Transform $regex → $re
|
|
183
|
+
if (key === '$regex') {
|
|
184
|
+
result['$re'] = val;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
// Transform $all → $contains
|
|
188
|
+
if (key === '$all') {
|
|
189
|
+
result['$contains'] = val;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
// Recursively process other values
|
|
193
|
+
result[key] = this.transformOperatorsInValue(val);
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Check if MongoDB query is empty
|
|
199
|
+
*/
|
|
200
|
+
isEmptyQuery(query) {
|
|
201
|
+
const keys = Object.keys(query);
|
|
202
|
+
if (keys.length === 0)
|
|
203
|
+
return true;
|
|
204
|
+
// Check for {$or: [{}]} or {$and: [{}]} patterns
|
|
205
|
+
if (keys.length === 1 && (keys[0] === '$or' || keys[0] === '$and')) {
|
|
206
|
+
const value = query[keys[0]];
|
|
207
|
+
if (Array.isArray(value)) {
|
|
208
|
+
return value.every((item) => typeof item === 'object' &&
|
|
209
|
+
item !== null &&
|
|
210
|
+
Object.keys(item).length === 0);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Splits rules into those with @input templates and without
|
|
217
|
+
* Rules with @input will be materialized lazily
|
|
218
|
+
*/
|
|
219
|
+
static splitRulesByInput(rules) {
|
|
220
|
+
const withoutInput = [];
|
|
221
|
+
const withInput = [];
|
|
222
|
+
for (const rule of rules) {
|
|
223
|
+
const jsonStr = JSON.stringify(rule);
|
|
224
|
+
if (jsonStr.includes(types_1.ACL_INPUT_TEMPLATE)) {
|
|
225
|
+
withInput.push(rule);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
withoutInput.push(rule);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return { withoutInput, withInput };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
exports.ExtendAbility = ExtendAbility;
|
|
235
|
+
//# sourceMappingURL=ability.factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ability.factory.js","sourceRoot":"","sources":["../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/factories/ability.factory.ts"],"names":[],"mappings":";;;AACA,2CAOuB;AACvB,+CAAmD;AACnD,0CAA+C;AAE/C,oCAAqE;AACrE,uCAAyC;AAY5B,QAAA,eAAe,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAC5C,QAAA,sBAAsB,GAAoB;IACrD,OAAO,EAAE,uBAAe;IACxB,UAAU,EAAE,SAAS,cAAc,CAAC,SAAoB;QACtD,OAAO,SAAS,kBAAkB,CAIhC,OAAe,EACf,MAAc,EACd,KAA0B,EAC1B,OAAgC,EAChC,OAAwD;YAExD,OAAO,IAAI,aAAa,CACtB,SAAS,CAAC,GAAG,CAAC,2BAAgB,CAAC,EAC/B,OAAO,EACP,MAAM,EACN,KAAK,EACL,OAAO,EACP,OAAO,CACR,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,CAAC,gBAAS,CAAC;CACpB,CAAC;AAEF,MAAa,aAGX,SAAQ,qBAAiB;IAKf;IACA;IACA;IACA;IAES;IACA;IAVX,UAAU,GAAwB,SAAS,CAAC;IAC5C,cAAc,GAAwB,SAAS,CAAC;IAExD,YACU,gBAAkC,EAClC,cAAsB,EACtB,aAAqB,EACrB,QAA6B,EAEpB,OAAgC,EAChC,OAAwD;QAEzE,MAAM,EAAE,YAAY,EAAE,GAAG,aAAa,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAEnE,MAAM,YAAY,GAAG,gBAAgB,CAAC,WAAW,CAC/C,YAAY,EACZ,OAAO,EACP,OAAO,EACP,SAAS,CAAC,YAAY;SACvB,CAAC;QAEF,KAAK,CAAC,YAAY,EAAE;YAClB,iBAAiB,EAAE,2BAAiB;YACpC,YAAY,EAAE,6BAAmB;SAClC,CAAC,CAAC;QApBK,qBAAgB,GAAhB,gBAAgB,CAAkB;QAClC,mBAAc,GAAd,cAAc,CAAQ;QACtB,kBAAa,GAAb,aAAa,CAAQ;QACrB,aAAQ,GAAR,QAAQ,CAAqB;QAEpB,YAAO,GAAP,OAAO,CAAyB;QAChC,YAAO,GAAP,OAAO,CAAiD;IAe3E,CAAC;IAED,eAAe,CAAC,KAAmB;QACjC,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,CACpD,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,OAAO,EACZ,KAAK,CACN,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI,aAAa;QACf,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAChC,CAAC;QACD,OAAO,IAAI,CAAC,cAAyB,CAAC;IACxC,CAAC;IAED,IAAI,SAAS;QACX,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAChC,CAAC;QACD,OAAO,IAAI,CAAC,UAAqB,CAAC;IACpC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,sBAAsB;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBACtC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC7B,CAAC;YACD,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAClC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACzB,CAAC;YACD,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;gBAC1D,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,yBAAyB;QACzB,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC9B,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAC1B,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,cAAc;QASZ,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QAErC,MAAM,aAAa,GAAG,IAAA,oBAAY,EAChC,IAAI,EACJ,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,cAAqB,EAC1B,CAAC,IAAI,EAAE,EAAE;YACP,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;YAEtC,IAAI,CAAC,UAAU;gBAAE,OAAO,EAAE,CAAC;YAE3B,MAAM,WAAW,GAAG,IAAI,CAAC,yBAAyB,CAChD,UAAU,EACV,QAAQ,EACR,UAAU,CACX,CAAC;YAEF,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;QACxD,CAAC,CACyB,CAAC;QAE7B,qCAAqC;QACrC,IAAI,MAAM,GAA0C,SAAS,CAAC;QAC9D,IAAI,OAAO,GAA2C,SAAS,CAAC;QAEhE,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,GAAG,EAAS,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE;gBACxD,MAAc,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAQ,CAAC;QAC1C,CAAC;QAED,OAAO;YACL,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,CAAC;YACzB,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC;YAC3B,4DAA4D;YAC5D,GAAG,CAAC,aAAa;gBACf,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI;gBACnC,aAAa;aACd,CAAC;SACL,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,yBAAyB,CAC/B,UAAmC,EACnC,QAAkC,EAClC,UAAuB;QAEvB,MAAM,MAAM,GAA4B,EAAE,CAAC;QAE3C,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5D,yDAAyD;YACzD,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,wCAAwC;gBACxC,IAAI,SAAS,KAAK,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACjD,MAAM,CAAC,MAAM,CAAC,GAAG;wBACf,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAC9B,IAAI,CAAC,yBAAyB,CAAC,YAAY,EAAE,QAAQ,EAAE,UAAU,CAAC,CACnE;qBACF,CAAC;oBACF,SAAS;gBACX,CAAC;gBAED,oCAAoC;gBACpC,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC1E,MAAM,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAC7C,IAAI,CAAC,yBAAyB,CAAC,YAAY,EAAE,QAAQ,EAAE,UAAU,CAAC,CACnE,CAAC;oBACF,SAAS;gBACX,CAAC;gBAED,6BAA6B;gBAC7B,MAAM,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;gBAC1B,SAAS;YACX,CAAC;YAED,mBAAmB;YACnB,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAErD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,kCAAkC;gBAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;gBACtD,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACzB,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;gBAElC,sCAAsC;gBACtC,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC;YAC5D,CAAC;iBAAM,CAAC;gBACN,iCAAiC;gBACjC,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;gBACzD,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBAC5B,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;gBACrC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAE1B,2DAA2D;gBAC3D,2CAA2C;gBAC3C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;oBACvB,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;gBACzB,CAAC;gBACA,MAAM,CAAC,SAAS,CAA6B,CAAC,UAAU,CAAC;oBACxD,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACK,yBAAyB,CAAC,KAAc;QAC9C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAChD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,MAAM,GAA4B,EAAE,CAAC;QAE3C,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,yBAAyB;YACzB,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACrB,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;gBACpB,SAAS;YACX,CAAC;YAED,6BAA6B;YAC7B,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACnB,MAAM,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC;gBAC1B,SAAS;YACX,CAAC;YAED,mCAAmC;YACnC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,KAA8B;QACjD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEhC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEnC,iDAAiD;QACjD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC;YACnE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,KAAK,CAAC,KAAK,CAChB,CAAC,IAAI,EAAE,EAAE,CACP,OAAO,IAAI,KAAK,QAAQ;oBACxB,IAAI,KAAK,IAAI;oBACb,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CACjC,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACK,MAAM,CAAC,iBAAiB,CAI9B,KAA0B;QAK1B,MAAM,YAAY,GAAwB,EAAE,CAAC;QAC7C,MAAM,SAAS,GAAwB,EAAE,CAAC;QAE1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAErC,IAAI,OAAO,CAAC,QAAQ,CAAC,0BAAkB,CAAC,EAAE,CAAC;gBACzC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;IACrC,CAAC;CACF;AA3SD,sCA2SC"}
|
|
@@ -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("./ability.factory"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./ability-proxy.factory"), 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/factories/index.ts"],"names":[],"mappings":";;;AAAA,4DAAiC;AACjC,kEAAuC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
/**
|
|
3
|
+
* Guard for ACL permission checking
|
|
4
|
+
*
|
|
5
|
+
* Thin wrapper that delegates all logic to AclAuthorizationService
|
|
6
|
+
*
|
|
7
|
+
* Applied automatically by @AclController decorator
|
|
8
|
+
*
|
|
9
|
+
* Lifecycle: Guards run BEFORE interceptors and pipes
|
|
10
|
+
*
|
|
11
|
+
* Benefits:
|
|
12
|
+
* - Fails fast (before handler execution)
|
|
13
|
+
* - Semantic correctness (Guard = authorization)
|
|
14
|
+
* - Supports onNoRules policy (deny/allow/warn)
|
|
15
|
+
*/
|
|
16
|
+
export declare class AclGuard implements CanActivate {
|
|
17
|
+
private readonly moduleRef;
|
|
18
|
+
private readonly reflector;
|
|
19
|
+
private readonly logger;
|
|
20
|
+
canActivate(executionContext: ExecutionContext): Promise<boolean>;
|
|
21
|
+
}
|