@elsikora/nestjs-crud-automator 1.16.0-dev.1 → 1.17.0-dev.1
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/README.md +43 -0
- package/dist/cjs/class/api/authorization/engine.class.d.ts +8 -0
- package/dist/cjs/class/api/authorization/engine.class.js +92 -0
- package/dist/cjs/class/api/authorization/engine.class.js.map +1 -0
- package/dist/cjs/class/api/authorization/guard.class.d.ts +13 -0
- package/dist/cjs/class/api/authorization/guard.class.js +79 -0
- package/dist/cjs/class/api/authorization/guard.class.js.map +1 -0
- package/dist/cjs/class/api/authorization/index.d.ts +3 -0
- package/dist/cjs/class/api/authorization/policy/base.class.d.ts +37 -0
- package/dist/cjs/class/api/authorization/policy/base.class.js +68 -0
- package/dist/cjs/class/api/authorization/policy/base.class.js.map +1 -0
- package/dist/cjs/class/api/authorization/policy/discovery-service.class.d.ts +10 -0
- package/dist/cjs/class/api/authorization/policy/discovery-service.class.js +53 -0
- package/dist/cjs/class/api/authorization/policy/discovery-service.class.js.map +1 -0
- package/dist/cjs/class/api/authorization/policy/executor.class.d.ts +8 -0
- package/dist/cjs/class/api/authorization/policy/executor.class.js +43 -0
- package/dist/cjs/class/api/authorization/policy/executor.class.js.map +1 -0
- package/dist/cjs/class/api/authorization/policy/index.d.ts +4 -0
- package/dist/cjs/class/api/authorization/policy/registry.class.d.ts +26 -0
- package/dist/cjs/class/api/authorization/policy/registry.class.js +151 -0
- package/dist/cjs/class/api/authorization/policy/registry.class.js.map +1 -0
- package/dist/cjs/class/api/service-base.class.d.ts +2 -2
- package/dist/cjs/class/api/service-base.class.js.map +1 -1
- package/dist/cjs/class/index.d.ts +1 -0
- package/dist/cjs/constant/authorization/index.d.ts +3 -0
- package/dist/cjs/constant/authorization/metadata/decision.constant.d.ts +3 -0
- package/dist/cjs/constant/authorization/metadata/decision.constant.js +9 -0
- package/dist/cjs/constant/authorization/metadata/decision.constant.js.map +1 -0
- package/dist/cjs/constant/authorization/metadata/index.d.ts +1 -0
- package/dist/cjs/constant/authorization/policy/decorator.constant.d.ts +4 -0
- package/dist/cjs/constant/authorization/policy/decorator.constant.js +11 -0
- package/dist/cjs/constant/authorization/policy/decorator.constant.js.map +1 -0
- package/dist/cjs/constant/authorization/policy/index.d.ts +1 -0
- package/dist/cjs/constant/authorization/token/index.d.ts +1 -0
- package/dist/cjs/constant/authorization/token/registry.constant.d.ts +1 -0
- package/dist/cjs/constant/authorization/token/registry.constant.js +7 -0
- package/dist/cjs/constant/authorization/token/registry.constant.js.map +1 -0
- package/dist/cjs/constant/decorator/api/controller.constant.d.ts +2 -0
- package/dist/cjs/constant/decorator/api/controller.constant.js +4 -0
- package/dist/cjs/constant/decorator/api/controller.constant.js.map +1 -1
- package/dist/cjs/constant/index.d.ts +1 -0
- package/dist/cjs/decorator/api/authorization/index.d.ts +1 -0
- package/dist/cjs/decorator/api/authorization/policy.decorator.d.ts +9 -0
- package/dist/cjs/decorator/api/authorization/policy.decorator.js +25 -0
- package/dist/cjs/decorator/api/authorization/policy.decorator.js.map +1 -0
- package/dist/cjs/decorator/api/controller/index.d.ts +1 -0
- package/dist/cjs/decorator/api/controller/securable.decorator.d.ts +6 -0
- package/dist/cjs/decorator/api/controller/securable.decorator.js +17 -0
- package/dist/cjs/decorator/api/controller/securable.decorator.js.map +1 -0
- package/dist/cjs/decorator/api/index.d.ts +1 -0
- package/dist/cjs/decorator/api/method.decorator.js +7 -1
- package/dist/cjs/decorator/api/method.decorator.js.map +1 -1
- package/dist/cjs/enum/authorization/effect.enum.d.ts +4 -0
- package/dist/cjs/enum/authorization/effect.enum.js +8 -0
- package/dist/cjs/enum/authorization/effect.enum.js.map +1 -0
- package/dist/cjs/enum/authorization/index.d.ts +2 -0
- package/dist/cjs/enum/authorization/policy/index.d.ts +1 -0
- package/dist/cjs/enum/authorization/policy/on-type.enum.d.ts +3 -0
- package/dist/cjs/enum/authorization/policy/on-type.enum.js +7 -0
- package/dist/cjs/enum/authorization/policy/on-type.enum.js.map +1 -0
- package/dist/cjs/enum/index.d.ts +1 -0
- package/dist/cjs/external/tslib/tslib.es6.js +5 -0
- package/dist/cjs/external/tslib/tslib.es6.js.map +1 -1
- package/dist/cjs/factory/api/controller.factory.js +63 -28
- package/dist/cjs/factory/api/controller.factory.js.map +1 -1
- package/dist/cjs/index.js +60 -4
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interface/api-authentication-request.interface.d.ts +3 -0
- package/dist/cjs/interface/authorization/decision.interface.d.ts +17 -0
- package/dist/cjs/interface/authorization/engine.interface.d.ts +6 -0
- package/dist/cjs/interface/authorization/evaluate-options.interface.d.ts +9 -0
- package/dist/cjs/interface/authorization/index.d.ts +7 -0
- package/dist/cjs/interface/authorization/policy/index.d.ts +3 -0
- package/dist/cjs/interface/authorization/policy/interface.d.ts +9 -0
- package/dist/cjs/interface/authorization/policy/registry.interface.d.ts +10 -0
- package/dist/cjs/interface/authorization/policy/subscriber/context.interface.d.ts +9 -0
- package/dist/cjs/interface/authorization/policy/subscriber/index.d.ts +5 -0
- package/dist/cjs/interface/authorization/policy/subscriber/interface.d.ts +14 -0
- package/dist/cjs/interface/authorization/policy/subscriber/properties.interface.d.ts +7 -0
- package/dist/cjs/interface/authorization/policy/subscriber/registration.interface.d.ts +9 -0
- package/dist/cjs/interface/authorization/policy/subscriber/rule.interface.d.ts +13 -0
- package/dist/cjs/interface/authorization/rule/context.interface.d.ts +6 -0
- package/dist/cjs/interface/authorization/rule/index.d.ts +2 -0
- package/dist/cjs/interface/authorization/rule/interface.d.ts +15 -0
- package/dist/cjs/interface/authorization/scope.interface.d.ts +5 -0
- package/dist/cjs/interface/authorization/subject.interface.d.ts +6 -0
- package/dist/cjs/interface/class/api/subscriber/route-execution-context-data.interface.d.ts +7 -1
- package/dist/cjs/interface/index.d.ts +1 -0
- package/dist/cjs/module/api/authorization.module.d.ts +7 -0
- package/dist/cjs/module/api/authorization.module.js +39 -0
- package/dist/cjs/module/api/authorization.module.js.map +1 -0
- package/dist/cjs/module/api/index.d.ts +2 -0
- package/dist/cjs/module/{api-subscriber.module.js → api/subscriber.module.js} +3 -3
- package/dist/cjs/module/api/subscriber.module.js.map +1 -0
- package/dist/cjs/module/index.d.ts +1 -1
- package/dist/cjs/type/class/api/authorization/guard-request.type.d.ts +7 -0
- package/dist/cjs/type/class/api/authorization/index.d.ts +4 -0
- package/dist/cjs/type/class/api/authorization/policy/hook/index.d.ts +2 -0
- package/dist/cjs/type/class/api/authorization/policy/hook/result.type.d.ts +8 -0
- package/dist/cjs/type/class/api/authorization/policy/hook/type.d.ts +5 -0
- package/dist/cjs/type/class/api/authorization/policy/index.d.ts +2 -0
- package/dist/cjs/type/class/api/authorization/policy/policy-subscriber-rule-result.type.d.ts +3 -0
- package/dist/cjs/type/class/api/authorization/rule/condition.type.d.ts +3 -0
- package/dist/cjs/type/class/api/authorization/rule/index.d.ts +4 -0
- package/dist/cjs/type/class/api/authorization/rule/result-transform.type.d.ts +4 -0
- package/dist/cjs/type/class/api/authorization/rule/scope-resolver.type.d.ts +4 -0
- package/dist/cjs/type/class/api/authorization/rule/transform-payload.type.d.ts +3 -0
- package/dist/cjs/type/class/api/authorization/scope-where.type.d.ts +3 -0
- package/dist/cjs/type/class/api/subscriber/route/after/create-context.type.d.ts +1 -1
- package/dist/cjs/type/class/api/subscriber/route/after/delete-context.type.d.ts +1 -1
- package/dist/cjs/type/class/api/subscriber/route/after/get/context.type.d.ts +1 -1
- package/dist/cjs/type/class/api/subscriber/route/after/get/list-context.type.d.ts +2 -1
- package/dist/cjs/type/class/api/subscriber/route/after/get/many-context.type.d.ts +1 -1
- package/dist/cjs/type/class/api/subscriber/route/after/update-context.type.d.ts +1 -1
- package/dist/cjs/type/index.d.ts +1 -0
- package/dist/cjs/utility/api/controller/apply-metadata.utility.js +3 -5
- package/dist/cjs/utility/api/controller/apply-metadata.utility.js.map +1 -1
- package/dist/cjs/utility/authorization/decision/apply-result.utility.d.ts +12 -0
- package/dist/cjs/utility/authorization/decision/apply-result.utility.js +27 -0
- package/dist/cjs/utility/authorization/decision/apply-result.utility.js.map +1 -0
- package/dist/cjs/utility/authorization/decision/attach-resource.utility.d.ts +11 -0
- package/dist/cjs/utility/authorization/decision/attach-resource.utility.js +20 -0
- package/dist/cjs/utility/authorization/decision/attach-resource.utility.js.map +1 -0
- package/dist/cjs/utility/authorization/decision/index.d.ts +3 -0
- package/dist/cjs/utility/authorization/decision/resolve-from-request.utility.d.ts +12 -0
- package/dist/cjs/utility/authorization/decision/resolve-from-request.utility.js +22 -0
- package/dist/cjs/utility/authorization/decision/resolve-from-request.utility.js.map +1 -0
- package/dist/cjs/utility/authorization/index.d.ts +3 -0
- package/dist/cjs/utility/authorization/scope/index.d.ts +1 -0
- package/dist/cjs/utility/authorization/scope/merge/index.d.ts +1 -0
- package/dist/cjs/utility/authorization/scope/merge/where.utility.d.ts +10 -0
- package/dist/cjs/utility/authorization/scope/merge/where.utility.js +32 -0
- package/dist/cjs/utility/authorization/scope/merge/where.utility.js.map +1 -0
- package/dist/cjs/utility/authorization/subject/index.d.ts +1 -0
- package/dist/cjs/utility/authorization/subject/resolve-default-subject.utility.d.ts +7 -0
- package/dist/cjs/utility/authorization/subject/resolve-default-subject.utility.js +52 -0
- package/dist/cjs/utility/authorization/subject/resolve-default-subject.utility.js.map +1 -0
- package/dist/cjs/utility/index.d.ts +1 -0
- package/dist/esm/class/api/authorization/engine.class.d.ts +8 -0
- package/dist/esm/class/api/authorization/engine.class.js +92 -0
- package/dist/esm/class/api/authorization/engine.class.js.map +1 -0
- package/dist/esm/class/api/authorization/guard.class.d.ts +13 -0
- package/dist/esm/class/api/authorization/guard.class.js +79 -0
- package/dist/esm/class/api/authorization/guard.class.js.map +1 -0
- package/dist/esm/class/api/authorization/index.d.ts +3 -0
- package/dist/esm/class/api/authorization/policy/base.class.d.ts +37 -0
- package/dist/esm/class/api/authorization/policy/base.class.js +66 -0
- package/dist/esm/class/api/authorization/policy/base.class.js.map +1 -0
- package/dist/esm/class/api/authorization/policy/discovery-service.class.d.ts +10 -0
- package/dist/esm/class/api/authorization/policy/discovery-service.class.js +53 -0
- package/dist/esm/class/api/authorization/policy/discovery-service.class.js.map +1 -0
- package/dist/esm/class/api/authorization/policy/executor.class.d.ts +8 -0
- package/dist/esm/class/api/authorization/policy/executor.class.js +41 -0
- package/dist/esm/class/api/authorization/policy/executor.class.js.map +1 -0
- package/dist/esm/class/api/authorization/policy/index.d.ts +4 -0
- package/dist/esm/class/api/authorization/policy/registry.class.d.ts +26 -0
- package/dist/esm/class/api/authorization/policy/registry.class.js +148 -0
- package/dist/esm/class/api/authorization/policy/registry.class.js.map +1 -0
- package/dist/esm/class/api/service-base.class.d.ts +2 -2
- package/dist/esm/class/api/service-base.class.js.map +1 -1
- package/dist/esm/class/index.d.ts +1 -0
- package/dist/esm/constant/authorization/index.d.ts +3 -0
- package/dist/esm/constant/authorization/metadata/decision.constant.d.ts +3 -0
- package/dist/esm/constant/authorization/metadata/decision.constant.js +7 -0
- package/dist/esm/constant/authorization/metadata/decision.constant.js.map +1 -0
- package/dist/esm/constant/authorization/metadata/index.d.ts +1 -0
- package/dist/esm/constant/authorization/policy/decorator.constant.d.ts +4 -0
- package/dist/esm/constant/authorization/policy/decorator.constant.js +9 -0
- package/dist/esm/constant/authorization/policy/decorator.constant.js.map +1 -0
- package/dist/esm/constant/authorization/policy/index.d.ts +1 -0
- package/dist/esm/constant/authorization/token/index.d.ts +1 -0
- package/dist/esm/constant/authorization/token/registry.constant.d.ts +1 -0
- package/dist/esm/constant/authorization/token/registry.constant.js +5 -0
- package/dist/esm/constant/authorization/token/registry.constant.js.map +1 -0
- package/dist/esm/constant/decorator/api/controller.constant.d.ts +2 -0
- package/dist/esm/constant/decorator/api/controller.constant.js +4 -0
- package/dist/esm/constant/decorator/api/controller.constant.js.map +1 -1
- package/dist/esm/constant/index.d.ts +1 -0
- package/dist/esm/decorator/api/authorization/index.d.ts +1 -0
- package/dist/esm/decorator/api/authorization/policy.decorator.d.ts +9 -0
- package/dist/esm/decorator/api/authorization/policy.decorator.js +23 -0
- package/dist/esm/decorator/api/authorization/policy.decorator.js.map +1 -0
- package/dist/esm/decorator/api/controller/index.d.ts +1 -0
- package/dist/esm/decorator/api/controller/securable.decorator.d.ts +6 -0
- package/dist/esm/decorator/api/controller/securable.decorator.js +15 -0
- package/dist/esm/decorator/api/controller/securable.decorator.js.map +1 -0
- package/dist/esm/decorator/api/index.d.ts +1 -0
- package/dist/esm/decorator/api/method.decorator.js +7 -1
- package/dist/esm/decorator/api/method.decorator.js.map +1 -1
- package/dist/esm/enum/authorization/effect.enum.d.ts +4 -0
- package/dist/esm/enum/authorization/effect.enum.js +8 -0
- package/dist/esm/enum/authorization/effect.enum.js.map +1 -0
- package/dist/esm/enum/authorization/index.d.ts +2 -0
- package/dist/esm/enum/authorization/policy/index.d.ts +1 -0
- package/dist/esm/enum/authorization/policy/on-type.enum.d.ts +3 -0
- package/dist/esm/enum/authorization/policy/on-type.enum.js +7 -0
- package/dist/esm/enum/authorization/policy/on-type.enum.js.map +1 -0
- package/dist/esm/enum/index.d.ts +1 -0
- package/dist/esm/external/tslib/tslib.es6.js +5 -1
- package/dist/esm/external/tslib/tslib.es6.js.map +1 -1
- package/dist/esm/factory/api/controller.factory.js +63 -28
- package/dist/esm/factory/api/controller.factory.js.map +1 -1
- package/dist/esm/index.js +20 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interface/api-authentication-request.interface.d.ts +3 -0
- package/dist/esm/interface/authorization/decision.interface.d.ts +17 -0
- package/dist/esm/interface/authorization/engine.interface.d.ts +6 -0
- package/dist/esm/interface/authorization/evaluate-options.interface.d.ts +9 -0
- package/dist/esm/interface/authorization/index.d.ts +7 -0
- package/dist/esm/interface/authorization/policy/index.d.ts +3 -0
- package/dist/esm/interface/authorization/policy/interface.d.ts +9 -0
- package/dist/esm/interface/authorization/policy/registry.interface.d.ts +10 -0
- package/dist/esm/interface/authorization/policy/subscriber/context.interface.d.ts +9 -0
- package/dist/esm/interface/authorization/policy/subscriber/index.d.ts +5 -0
- package/dist/esm/interface/authorization/policy/subscriber/interface.d.ts +14 -0
- package/dist/esm/interface/authorization/policy/subscriber/properties.interface.d.ts +7 -0
- package/dist/esm/interface/authorization/policy/subscriber/registration.interface.d.ts +9 -0
- package/dist/esm/interface/authorization/policy/subscriber/rule.interface.d.ts +13 -0
- package/dist/esm/interface/authorization/rule/context.interface.d.ts +6 -0
- package/dist/esm/interface/authorization/rule/index.d.ts +2 -0
- package/dist/esm/interface/authorization/rule/interface.d.ts +15 -0
- package/dist/esm/interface/authorization/scope.interface.d.ts +5 -0
- package/dist/esm/interface/authorization/subject.interface.d.ts +6 -0
- package/dist/esm/interface/class/api/subscriber/route-execution-context-data.interface.d.ts +7 -1
- package/dist/esm/interface/index.d.ts +1 -0
- package/dist/esm/module/api/authorization.module.d.ts +7 -0
- package/dist/esm/module/api/authorization.module.js +39 -0
- package/dist/esm/module/api/authorization.module.js.map +1 -0
- package/dist/esm/module/api/index.d.ts +2 -0
- package/dist/esm/module/{api-subscriber.module.js → api/subscriber.module.js} +3 -3
- package/dist/esm/module/api/subscriber.module.js.map +1 -0
- package/dist/esm/module/index.d.ts +1 -1
- package/dist/esm/type/class/api/authorization/guard-request.type.d.ts +7 -0
- package/dist/esm/type/class/api/authorization/index.d.ts +4 -0
- package/dist/esm/type/class/api/authorization/policy/hook/index.d.ts +2 -0
- package/dist/esm/type/class/api/authorization/policy/hook/result.type.d.ts +8 -0
- package/dist/esm/type/class/api/authorization/policy/hook/type.d.ts +5 -0
- package/dist/esm/type/class/api/authorization/policy/index.d.ts +2 -0
- package/dist/esm/type/class/api/authorization/policy/policy-subscriber-rule-result.type.d.ts +3 -0
- package/dist/esm/type/class/api/authorization/rule/condition.type.d.ts +3 -0
- package/dist/esm/type/class/api/authorization/rule/index.d.ts +4 -0
- package/dist/esm/type/class/api/authorization/rule/result-transform.type.d.ts +4 -0
- package/dist/esm/type/class/api/authorization/rule/scope-resolver.type.d.ts +4 -0
- package/dist/esm/type/class/api/authorization/rule/transform-payload.type.d.ts +3 -0
- package/dist/esm/type/class/api/authorization/scope-where.type.d.ts +3 -0
- package/dist/esm/type/class/api/subscriber/route/after/create-context.type.d.ts +1 -1
- package/dist/esm/type/class/api/subscriber/route/after/delete-context.type.d.ts +1 -1
- package/dist/esm/type/class/api/subscriber/route/after/get/context.type.d.ts +1 -1
- package/dist/esm/type/class/api/subscriber/route/after/get/list-context.type.d.ts +2 -1
- package/dist/esm/type/class/api/subscriber/route/after/get/many-context.type.d.ts +1 -1
- package/dist/esm/type/class/api/subscriber/route/after/update-context.type.d.ts +1 -1
- package/dist/esm/type/index.d.ts +1 -0
- package/dist/esm/utility/api/controller/apply-metadata.utility.js +3 -5
- package/dist/esm/utility/api/controller/apply-metadata.utility.js.map +1 -1
- package/dist/esm/utility/authorization/decision/apply-result.utility.d.ts +12 -0
- package/dist/esm/utility/authorization/decision/apply-result.utility.js +25 -0
- package/dist/esm/utility/authorization/decision/apply-result.utility.js.map +1 -0
- package/dist/esm/utility/authorization/decision/attach-resource.utility.d.ts +11 -0
- package/dist/esm/utility/authorization/decision/attach-resource.utility.js +18 -0
- package/dist/esm/utility/authorization/decision/attach-resource.utility.js.map +1 -0
- package/dist/esm/utility/authorization/decision/index.d.ts +3 -0
- package/dist/esm/utility/authorization/decision/resolve-from-request.utility.d.ts +12 -0
- package/dist/esm/utility/authorization/decision/resolve-from-request.utility.js +20 -0
- package/dist/esm/utility/authorization/decision/resolve-from-request.utility.js.map +1 -0
- package/dist/esm/utility/authorization/index.d.ts +3 -0
- package/dist/esm/utility/authorization/scope/index.d.ts +1 -0
- package/dist/esm/utility/authorization/scope/merge/index.d.ts +1 -0
- package/dist/esm/utility/authorization/scope/merge/where.utility.d.ts +10 -0
- package/dist/esm/utility/authorization/scope/merge/where.utility.js +30 -0
- package/dist/esm/utility/authorization/scope/merge/where.utility.js.map +1 -0
- package/dist/esm/utility/authorization/subject/index.d.ts +1 -0
- package/dist/esm/utility/authorization/subject/resolve-default-subject.utility.d.ts +7 -0
- package/dist/esm/utility/authorization/subject/resolve-default-subject.utility.js +50 -0
- package/dist/esm/utility/authorization/subject/resolve-default-subject.utility.js.map +1 -0
- package/dist/esm/utility/index.d.ts +1 -0
- package/package.json +1 -1
- package/dist/cjs/module/api-subscriber.module.js.map +0 -1
- package/dist/esm/module/api-subscriber.module.js.map +0 -1
- /package/dist/cjs/module/{api-subscriber.module.d.ts → api/subscriber.module.d.ts} +0 -0
- /package/dist/esm/module/{api-subscriber.module.d.ts → api/subscriber.module.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ The core philosophy of this library is built on four pillars: being **Declarativ
|
|
|
46
46
|
- ✨ **Hooks and Subscriber System:** Intercept and extend business logic at both the controller and service level.
|
|
47
47
|
- ✨ **Dynamic and Polymorphic DTOs:** Generate DTOs on-the-fly based on discriminator fields.
|
|
48
48
|
- ✨ **Field-Level RBAC:** Show/hide fields in responses based on user roles using guards.
|
|
49
|
+
- ✨ **🔐 Declarative Authorization Policies:** Subscriber-style policies with automatic guard wiring, scopes, and response transforms.
|
|
49
50
|
- ✨ **Request Tracing:** Built-in `CorrelationIDResponseBodyInterceptor` to correlate requests and logs.
|
|
50
51
|
- ✨ **Convention over Configuration:** Smart defaults for service and DTO naming to reduce boilerplate.
|
|
51
52
|
|
|
@@ -352,6 +353,48 @@ export class UserController {
|
|
|
352
353
|
}
|
|
353
354
|
```
|
|
354
355
|
|
|
356
|
+
### Declarative Authorization Policies
|
|
357
|
+
|
|
358
|
+
Import `ApiAuthorizationModule` once and describe access rules as policies. The guard is attached to every generated route automatically—no controller configuration required.
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
// app.module.ts
|
|
362
|
+
import { Module } from "@nestjs/common";
|
|
363
|
+
import { ApiAuthorizationModule } from "@elsikora/nestjs-crud-automator";
|
|
364
|
+
|
|
365
|
+
@Module({
|
|
366
|
+
imports: [
|
|
367
|
+
/* ... */
|
|
368
|
+
ApiAuthorizationModule,
|
|
369
|
+
],
|
|
370
|
+
})
|
|
371
|
+
export class AppModule {}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
// policies/user-access.policy.ts
|
|
376
|
+
import { ApiAuthorizationPolicy, ApiAuthorizationPolicyBase } from "@elsikora/nestjs-crud-automator";
|
|
377
|
+
import { UserEntity } from "../user.entity";
|
|
378
|
+
|
|
379
|
+
@ApiAuthorizationPolicy<UserEntity>({ entity: UserEntity, priority: 200 })
|
|
380
|
+
export class UserAccessPolicy extends ApiAuthorizationPolicyBase<UserEntity> {
|
|
381
|
+
onBeforeGet() {
|
|
382
|
+
return this.allow({
|
|
383
|
+
scope: ({ subject }) => ({ where: { id: subject.id } }),
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
onBeforeDelete() {
|
|
388
|
+
return this.deny({
|
|
389
|
+
description: "Only admins can delete users",
|
|
390
|
+
condition: ({ subject }) => !subject.roles.includes("admin"),
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Policies can return allow/deny rules, merge scope conditions into generated queries, and transform responses before they are sent back to the client.
|
|
397
|
+
|
|
355
398
|
### `CorrelationIDResponseBodyInterceptor`: Request Tracing
|
|
356
399
|
|
|
357
400
|
To simplify debugging and request tracing in complex systems, the library provides the `CorrelationIDResponseBodyInterceptor`. This interceptor should be registered globally in your `main.ts`.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IApiBaseEntity } from '../../../interface/api-base-entity.interface';
|
|
2
|
+
import { IApiAuthorizationDecision, IApiAuthorizationEngine, IApiAuthorizationEngineEvaluateOptions } from '../../../interface/authorization/index';
|
|
3
|
+
export declare class ApiAuthorizationEngine implements IApiAuthorizationEngine<IApiBaseEntity> {
|
|
4
|
+
evaluate<E extends IApiBaseEntity, R>(options: IApiAuthorizationEngineEvaluateOptions<E, R>): Promise<IApiAuthorizationDecision<E, R>>;
|
|
5
|
+
private buildDecision;
|
|
6
|
+
private evaluateCondition;
|
|
7
|
+
private mergeScope;
|
|
8
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tslib_es6 = require('../../../external/tslib/tslib.es6.js');
|
|
4
|
+
var effect_enum = require('../../../enum/authorization/effect.enum.js');
|
|
5
|
+
var common = require('@nestjs/common');
|
|
6
|
+
var where_utility = require('../../../utility/authorization/scope/merge/where.utility.js');
|
|
7
|
+
|
|
8
|
+
exports.ApiAuthorizationEngine = class ApiAuthorizationEngine {
|
|
9
|
+
async evaluate(options) {
|
|
10
|
+
const context = {
|
|
11
|
+
resource: options.resource,
|
|
12
|
+
subject: options.subject,
|
|
13
|
+
};
|
|
14
|
+
const matchedRules = [];
|
|
15
|
+
let scope;
|
|
16
|
+
const transforms = [];
|
|
17
|
+
for (const rule of options.policy.rules) {
|
|
18
|
+
const isConditionPassed = await this.evaluateCondition(rule, context);
|
|
19
|
+
if (!isConditionPassed) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (rule.effect === effect_enum.EAuthorizationEffect.DENY) {
|
|
23
|
+
return this.buildDecision(options, {
|
|
24
|
+
appliedRules: [rule],
|
|
25
|
+
effect: effect_enum.EAuthorizationEffect.DENY,
|
|
26
|
+
scope: undefined,
|
|
27
|
+
transforms: [],
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
matchedRules.push(rule);
|
|
31
|
+
scope = await this.mergeScope(scope, rule, context);
|
|
32
|
+
if (rule.resultTransform) {
|
|
33
|
+
transforms.push(rule.resultTransform);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (matchedRules.length === 0) {
|
|
37
|
+
return this.buildDecision(options, {
|
|
38
|
+
appliedRules: [],
|
|
39
|
+
effect: effect_enum.EAuthorizationEffect.DENY,
|
|
40
|
+
scope: undefined,
|
|
41
|
+
transforms: [],
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return this.buildDecision(options, {
|
|
45
|
+
appliedRules: matchedRules,
|
|
46
|
+
effect: effect_enum.EAuthorizationEffect.ALLOW,
|
|
47
|
+
scope,
|
|
48
|
+
transforms,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
buildDecision(options, payload) {
|
|
52
|
+
return {
|
|
53
|
+
action: options.action,
|
|
54
|
+
appliedRules: payload.appliedRules,
|
|
55
|
+
effect: payload.effect,
|
|
56
|
+
policyId: options.policy.policyId,
|
|
57
|
+
resource: options.resource,
|
|
58
|
+
resourceType: options.policy.entity.name ?? "UnknownResource",
|
|
59
|
+
scope: payload.scope,
|
|
60
|
+
subject: options.subject,
|
|
61
|
+
transforms: payload.transforms,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async evaluateCondition(rule, context) {
|
|
65
|
+
if (!rule.condition) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
const result = await rule.condition(context);
|
|
69
|
+
return result === true;
|
|
70
|
+
}
|
|
71
|
+
async mergeScope(currentScope, rule, context) {
|
|
72
|
+
if (!rule.scope) {
|
|
73
|
+
return currentScope;
|
|
74
|
+
}
|
|
75
|
+
const scopePatch = await rule.scope(context);
|
|
76
|
+
if (!scopePatch) {
|
|
77
|
+
return currentScope;
|
|
78
|
+
}
|
|
79
|
+
if (!currentScope) {
|
|
80
|
+
return scopePatch;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
...currentScope,
|
|
84
|
+
...scopePatch,
|
|
85
|
+
where: where_utility.AuthorizationScopeMergeWhere(currentScope.where, scopePatch.where),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
exports.ApiAuthorizationEngine = tslib_es6.__decorate([
|
|
90
|
+
common.Injectable()
|
|
91
|
+
], exports.ApiAuthorizationEngine);
|
|
92
|
+
//# sourceMappingURL=engine.class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.class.js","sources":["../../../../../../src/class/api/authorization/engine.class.ts"],"sourcesContent":[null],"names":["ApiAuthorizationEngine","EAuthorizationEffect","AuthorizationScopeMergeWhere","__decorate","Injectable"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IApiAuthorizationPolicyRegistry } from '../../../interface/authorization/policy/registry.interface';
|
|
2
|
+
import { ApiAuthorizationEngine } from './engine.class';
|
|
3
|
+
import { CanActivate, ExecutionContext } from "@nestjs/common";
|
|
4
|
+
export declare class ApiAuthorizationGuard implements CanActivate {
|
|
5
|
+
private readonly policyRegistry;
|
|
6
|
+
private readonly authorizationEngine;
|
|
7
|
+
constructor(policyRegistry: IApiAuthorizationPolicyRegistry, authorizationEngine: ApiAuthorizationEngine);
|
|
8
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
9
|
+
private attachDecisionToRequest;
|
|
10
|
+
private isControllerSecurable;
|
|
11
|
+
private resolveAction;
|
|
12
|
+
private resolveEntityConstructor;
|
|
13
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tslib_es6 = require('../../../external/tslib/tslib.es6.js');
|
|
4
|
+
var engine_class = require('./engine.class.js');
|
|
5
|
+
var decision_constant = require('../../../constant/authorization/metadata/decision.constant.js');
|
|
6
|
+
var registry_constant = require('../../../constant/authorization/token/registry.constant.js');
|
|
7
|
+
var controller_constant = require('../../../constant/decorator/api/controller.constant.js');
|
|
8
|
+
var effect_enum = require('../../../enum/authorization/effect.enum.js');
|
|
9
|
+
var common = require('@nestjs/common');
|
|
10
|
+
var resolveDefaultSubject_utility = require('../../../utility/authorization/subject/resolve-default-subject.utility.js');
|
|
11
|
+
var logger_utility = require('../../../utility/logger.utility.js');
|
|
12
|
+
|
|
13
|
+
const authorizationGuardLogger = logger_utility.LoggerUtility.getLogger("ApiAuthorizationGuard");
|
|
14
|
+
exports.ApiAuthorizationGuard = class ApiAuthorizationGuard {
|
|
15
|
+
policyRegistry;
|
|
16
|
+
authorizationEngine;
|
|
17
|
+
constructor(policyRegistry, authorizationEngine) {
|
|
18
|
+
this.policyRegistry = policyRegistry;
|
|
19
|
+
this.authorizationEngine = authorizationEngine;
|
|
20
|
+
}
|
|
21
|
+
async canActivate(context) {
|
|
22
|
+
if (!this.isControllerSecurable(context)) {
|
|
23
|
+
authorizationGuardLogger.debug("Controller is not marked as @ApiControllerSecurable, skipping authorization");
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
const entityConstructor = this.resolveEntityConstructor(context);
|
|
27
|
+
if (!entityConstructor) {
|
|
28
|
+
authorizationGuardLogger.debug("No entity constructor found in controller metadata, skipping authorization");
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
const action = this.resolveAction(context);
|
|
32
|
+
authorizationGuardLogger.verbose(`Evaluating authorization for entity "${entityConstructor.name}" action "${action}"`);
|
|
33
|
+
const policy = await this.policyRegistry.buildAggregatedPolicy(entityConstructor, action);
|
|
34
|
+
if (!policy) {
|
|
35
|
+
authorizationGuardLogger.debug(`No policy found for entity "${entityConstructor.name}" action "${action}", allowing access`);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
authorizationGuardLogger.verbose(`Found policy "${policy.policyId}" with ${policy.rules.length} rules for entity "${entityConstructor.name}" action "${action}"`);
|
|
39
|
+
const request = context.switchToHttp().getRequest();
|
|
40
|
+
const subject = resolveDefaultSubject_utility.AuthorizationResolveDefaultSubject(request.user);
|
|
41
|
+
const decision = await this.authorizationEngine.evaluate({
|
|
42
|
+
action,
|
|
43
|
+
policy,
|
|
44
|
+
resource: undefined,
|
|
45
|
+
subject,
|
|
46
|
+
});
|
|
47
|
+
this.attachDecisionToRequest(request, decision);
|
|
48
|
+
if (decision.effect === effect_enum.EAuthorizationEffect.DENY) {
|
|
49
|
+
authorizationGuardLogger.warn(`Access denied for entity "${entityConstructor.name}" action "${action}" subject "${subject.id}"`);
|
|
50
|
+
throw new common.ForbiddenException("Access denied");
|
|
51
|
+
}
|
|
52
|
+
authorizationGuardLogger.verbose(`Access granted for entity "${entityConstructor.name}" action "${action}" subject "${subject.id}"`);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
attachDecisionToRequest(request, decision) {
|
|
56
|
+
request.authorizationDecision = decision;
|
|
57
|
+
request[decision_constant.AUTHORIZATION_DECISION_METADATA_CONSTANT.REQUEST_KEY] = decision;
|
|
58
|
+
}
|
|
59
|
+
isControllerSecurable(context) {
|
|
60
|
+
return Boolean(Reflect.getMetadata(controller_constant.CONTROLLER_API_DECORATOR_CONSTANT.SECURABLE_METADATA_KEY, context.getClass()));
|
|
61
|
+
}
|
|
62
|
+
resolveAction(context) {
|
|
63
|
+
const handlerName = context.getHandler().name;
|
|
64
|
+
const prefix = controller_constant.CONTROLLER_API_DECORATOR_CONSTANT.RESERVED_METHOD_PREFIX ?? "";
|
|
65
|
+
if (handlerName.startsWith(prefix)) {
|
|
66
|
+
return handlerName.slice(prefix.length);
|
|
67
|
+
}
|
|
68
|
+
return handlerName;
|
|
69
|
+
}
|
|
70
|
+
resolveEntityConstructor(context) {
|
|
71
|
+
return Reflect.getMetadata(controller_constant.CONTROLLER_API_DECORATOR_CONSTANT.ENTITY_METADATA_KEY, context.getClass());
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
exports.ApiAuthorizationGuard = tslib_es6.__decorate([
|
|
75
|
+
common.Injectable(),
|
|
76
|
+
tslib_es6.__param(0, common.Inject(registry_constant.AUTHORIZATION_POLICY_REGISTRY_TOKEN)),
|
|
77
|
+
tslib_es6.__metadata("design:paramtypes", [Object, engine_class.ApiAuthorizationEngine])
|
|
78
|
+
], exports.ApiAuthorizationGuard);
|
|
79
|
+
//# sourceMappingURL=guard.class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.class.js","sources":["../../../../../../src/class/api/authorization/guard.class.ts"],"sourcesContent":[null],"names":["LoggerUtility","ApiAuthorizationGuard","AuthorizationResolveDefaultSubject","EAuthorizationEffect","ForbiddenException","AUTHORIZATION_DECISION_METADATA_CONSTANT","CONTROLLER_API_DECORATOR_CONSTANT","__decorate","Injectable","__param","Inject","AUTHORIZATION_POLICY_REGISTRY_TOKEN","ApiAuthorizationEngine"],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { IApiBaseEntity } from '../../../../interface/api-base-entity.interface';
|
|
2
|
+
import type { IApiAuthorizationPolicySubscriberRule } from '../../../../interface/authorization/policy/subscriber/index';
|
|
3
|
+
import { ApiSubscriberBase } from '../../subscriber/base.class';
|
|
4
|
+
/**
|
|
5
|
+
* Base class for all authorization policies. It mirrors ApiFunctionSubscriberBase
|
|
6
|
+
* and provides helper methods to create allow/deny rules that are later executed by the policy executor.
|
|
7
|
+
* @template E - Entity type extending IApiBaseEntity
|
|
8
|
+
*/
|
|
9
|
+
export declare abstract class ApiAuthorizationPolicyBase<E extends IApiBaseEntity> extends ApiSubscriberBase {
|
|
10
|
+
/**
|
|
11
|
+
* Creates an ALLOW rule with optional overrides.
|
|
12
|
+
* @param {Omit<IApiAuthorizationPolicySubscriberRule<E>, "effect">} [rule] - Rule fields to merge.
|
|
13
|
+
* @returns {IApiAuthorizationPolicySubscriberRule<E>} Allow rule.
|
|
14
|
+
*/
|
|
15
|
+
protected allow<R>(rule?: Omit<IApiAuthorizationPolicySubscriberRule<E, R>, "effect">): IApiAuthorizationPolicySubscriberRule<E, R>;
|
|
16
|
+
/**
|
|
17
|
+
* Helper that creates an allow rule conditioned on the subject having at least one of the provided roles.
|
|
18
|
+
* @param {Array<string>} roles - Roles that grant access.
|
|
19
|
+
* @param {Omit<IApiAuthorizationPolicySubscriberRule<E>, "effect">} [rule] - Optional overrides.
|
|
20
|
+
* @returns {IApiAuthorizationPolicySubscriberRule<E>} Allow rule targeting the given roles.
|
|
21
|
+
*/
|
|
22
|
+
protected allowForRoles<R>(roles: Array<string>, rule?: Omit<IApiAuthorizationPolicySubscriberRule<E, R>, "effect">): IApiAuthorizationPolicySubscriberRule<E, R>;
|
|
23
|
+
/**
|
|
24
|
+
* Creates a DENY rule with optional overrides.
|
|
25
|
+
* @param {Omit<IApiAuthorizationPolicySubscriberRule<E>, "effect">} [rule] - Rule fields to merge.
|
|
26
|
+
* @returns {IApiAuthorizationPolicySubscriberRule<E>} Deny rule.
|
|
27
|
+
*/
|
|
28
|
+
protected deny<R>(rule?: Omit<IApiAuthorizationPolicySubscriberRule<E, R>, "effect">): IApiAuthorizationPolicySubscriberRule<E, R>;
|
|
29
|
+
/**
|
|
30
|
+
* Helper that scopes data access to the owner identified by a field.
|
|
31
|
+
* Automatically handles relations by using nested id structure.
|
|
32
|
+
* @param {keyof E} [ownerField] - Entity field used to match the subject id, defaults to ownerId.
|
|
33
|
+
* @param {Omit<IApiAuthorizationPolicySubscriberRule<E>, "effect">} [rule] - Optional overrides.
|
|
34
|
+
* @returns {IApiAuthorizationPolicySubscriberRule<E>} Allow rule with owner scope.
|
|
35
|
+
*/
|
|
36
|
+
protected scopeToOwner<R>(ownerField?: keyof E, rule?: Omit<IApiAuthorizationPolicySubscriberRule<E, R>, "effect">): IApiAuthorizationPolicySubscriberRule<E, R>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var base_class = require('../../subscriber/base.class.js');
|
|
4
|
+
var effect_enum = require('../../../../enum/authorization/effect.enum.js');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Base class for all authorization policies. It mirrors ApiFunctionSubscriberBase
|
|
8
|
+
* and provides helper methods to create allow/deny rules that are later executed by the policy executor.
|
|
9
|
+
* @template E - Entity type extending IApiBaseEntity
|
|
10
|
+
*/
|
|
11
|
+
class ApiAuthorizationPolicyBase extends base_class.ApiSubscriberBase {
|
|
12
|
+
/**
|
|
13
|
+
* Creates an ALLOW rule with optional overrides.
|
|
14
|
+
* @param {Omit<IApiAuthorizationPolicySubscriberRule<E>, "effect">} [rule] - Rule fields to merge.
|
|
15
|
+
* @returns {IApiAuthorizationPolicySubscriberRule<E>} Allow rule.
|
|
16
|
+
*/
|
|
17
|
+
allow(rule = {}) {
|
|
18
|
+
return {
|
|
19
|
+
effect: effect_enum.EAuthorizationEffect.ALLOW,
|
|
20
|
+
...rule,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Helper that creates an allow rule conditioned on the subject having at least one of the provided roles.
|
|
25
|
+
* @param {Array<string>} roles - Roles that grant access.
|
|
26
|
+
* @param {Omit<IApiAuthorizationPolicySubscriberRule<E>, "effect">} [rule] - Optional overrides.
|
|
27
|
+
* @returns {IApiAuthorizationPolicySubscriberRule<E>} Allow rule targeting the given roles.
|
|
28
|
+
*/
|
|
29
|
+
allowForRoles(roles, rule = {}) {
|
|
30
|
+
return this.allow({
|
|
31
|
+
condition: ({ subject }) => roles.some((role) => subject.roles.includes(role)),
|
|
32
|
+
...rule,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a DENY rule with optional overrides.
|
|
37
|
+
* @param {Omit<IApiAuthorizationPolicySubscriberRule<E>, "effect">} [rule] - Rule fields to merge.
|
|
38
|
+
* @returns {IApiAuthorizationPolicySubscriberRule<E>} Deny rule.
|
|
39
|
+
*/
|
|
40
|
+
deny(rule = {}) {
|
|
41
|
+
return {
|
|
42
|
+
effect: effect_enum.EAuthorizationEffect.DENY,
|
|
43
|
+
...rule,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Helper that scopes data access to the owner identified by a field.
|
|
48
|
+
* Automatically handles relations by using nested id structure.
|
|
49
|
+
* @param {keyof E} [ownerField] - Entity field used to match the subject id, defaults to ownerId.
|
|
50
|
+
* @param {Omit<IApiAuthorizationPolicySubscriberRule<E>, "effect">} [rule] - Optional overrides.
|
|
51
|
+
* @returns {IApiAuthorizationPolicySubscriberRule<E>} Allow rule with owner scope.
|
|
52
|
+
*/
|
|
53
|
+
scopeToOwner(ownerField = "ownerId", rule = {}) {
|
|
54
|
+
return this.allow({
|
|
55
|
+
scope: ({ subject }) => {
|
|
56
|
+
return {
|
|
57
|
+
where: {
|
|
58
|
+
[ownerField]: { id: subject.id },
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
...rule,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
exports.ApiAuthorizationPolicyBase = ApiAuthorizationPolicyBase;
|
|
68
|
+
//# sourceMappingURL=base.class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.class.js","sources":["../../../../../../../src/class/api/authorization/policy/base.class.ts"],"sourcesContent":[null],"names":["ApiSubscriberBase","EAuthorizationEffect"],"mappings":";;;;;AAQA;;;;AAIG;AACG,MAAgB,0BAAqD,SAAQA,4BAAiB,CAAA;AACnG;;;;AAIG;IACO,KAAK,CAAI,OAAoE,EAAiE,EAAA;QACvJ,OAAO;YACN,MAAM,EAAEC,gCAAoB,CAAC,KAAK;AAClC,YAAA,GAAG,IAAI;SACP;IACF;AAEA;;;;;AAKG;AACO,IAAA,aAAa,CAAI,KAAoB,EAAE,IAAA,GAAoE,EAAiE,EAAA;QACrL,OAAO,IAAI,CAAC,KAAK,CAAC;YACjB,SAAS,EAAE,CAAC,EAAE,OAAO,EAAmC,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,IAAY,KAAK,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACvH,YAAA,GAAG,IAAI;AACP,SAAA,CAAC;IACH;AAEA;;;;AAIG;IACO,IAAI,CAAI,OAAoE,EAAiE,EAAA;QACtJ,OAAO;YACN,MAAM,EAAEA,gCAAoB,CAAC,IAAI;AACjC,YAAA,GAAG,IAAI;SACP;IACF;AAEA;;;;;;AAMG;AACO,IAAA,YAAY,CAAI,UAAA,GAAsB,SAAoB,EAAE,OAAoE,EAAiE,EAAA;QAC1M,OAAO,IAAI,CAAC,KAAK,CAAC;AACjB,YAAA,KAAK,EAAE,CAAC,EAAE,OAAO,EAAmC,KAAI;gBACvD,OAAO;AACN,oBAAA,KAAK,EAAE;wBACN,CAAC,UAAoB,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE;AACnB,qBAAA;iBACxB;YACF,CAAC;AACD,YAAA,GAAG,IAAI;AACP,SAAA,CAAC;IACH;AACA;;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { OnModuleInit } from "@nestjs/common";
|
|
2
|
+
import { DiscoveryService } from "@nestjs/core";
|
|
3
|
+
import { ApiAuthorizationPolicyRegistry } from './registry.class';
|
|
4
|
+
export declare class ApiAuthorizationPolicyDiscoveryService implements OnModuleInit {
|
|
5
|
+
private readonly discoveryService;
|
|
6
|
+
private readonly registry;
|
|
7
|
+
constructor(discoveryService: DiscoveryService, registry: ApiAuthorizationPolicyRegistry);
|
|
8
|
+
onModuleInit(): void;
|
|
9
|
+
private isPolicyWrapper;
|
|
10
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tslib_es6 = require('../../../../external/tslib/tslib.es6.js');
|
|
4
|
+
var decorator_constant = require('../../../../constant/authorization/policy/decorator.constant.js');
|
|
5
|
+
var common = require('@nestjs/common');
|
|
6
|
+
var core = require('@nestjs/core');
|
|
7
|
+
var logger_utility = require('../../../../utility/logger.utility.js');
|
|
8
|
+
var base_class = require('./base.class.js');
|
|
9
|
+
var registry_class = require('./registry.class.js');
|
|
10
|
+
|
|
11
|
+
const policyDiscoveryLogger = logger_utility.LoggerUtility.getLogger("ApiAuthorizationPolicyDiscoveryService");
|
|
12
|
+
exports.ApiAuthorizationPolicyDiscoveryService = class ApiAuthorizationPolicyDiscoveryService {
|
|
13
|
+
discoveryService;
|
|
14
|
+
registry;
|
|
15
|
+
constructor(discoveryService, registry) {
|
|
16
|
+
this.discoveryService = discoveryService;
|
|
17
|
+
this.registry = registry;
|
|
18
|
+
}
|
|
19
|
+
onModuleInit() {
|
|
20
|
+
policyDiscoveryLogger.verbose("Starting authorization policy discovery...");
|
|
21
|
+
const providers = this.discoveryService.getProviders();
|
|
22
|
+
const policyProviders = providers.filter((wrapper) => this.isPolicyWrapper(wrapper));
|
|
23
|
+
for (const wrapper of policyProviders) {
|
|
24
|
+
if (!wrapper.metatype) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const metadata = Reflect.getMetadata(decorator_constant.AUTHORIZATION_POLICY_DECORATOR_CONSTANT.METADATA_KEY, wrapper.metatype);
|
|
28
|
+
const properties = metadata;
|
|
29
|
+
if (!properties) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const policyId = properties.policyId ?? `${properties.entity.name?.toLowerCase() ?? "unknown"}${decorator_constant.AUTHORIZATION_POLICY_DECORATOR_CONSTANT.DEFAULT_POLICY_ID_SUFFIX}`;
|
|
33
|
+
this.registry.registerSubscriber({
|
|
34
|
+
description: properties.description,
|
|
35
|
+
entity: properties.entity,
|
|
36
|
+
policyId,
|
|
37
|
+
priority: properties.priority ?? 0,
|
|
38
|
+
subscriber: wrapper.instance,
|
|
39
|
+
});
|
|
40
|
+
policyDiscoveryLogger.verbose(`Registered authorization policy ${wrapper.name ?? properties.entity.name ?? "UnknownPolicy"} for entity ${properties.entity.name ?? "UnknownEntity"} with priority ${properties.priority ?? 0}`);
|
|
41
|
+
}
|
|
42
|
+
policyDiscoveryLogger.verbose(`Authorization policy discovery finished. Registered ${policyProviders.length} providers.`);
|
|
43
|
+
}
|
|
44
|
+
isPolicyWrapper(wrapper) {
|
|
45
|
+
return Boolean(wrapper.instance && wrapper.metatype && wrapper.instance instanceof base_class.ApiAuthorizationPolicyBase && Reflect.hasMetadata(decorator_constant.AUTHORIZATION_POLICY_DECORATOR_CONSTANT.METADATA_KEY, wrapper.metatype));
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
exports.ApiAuthorizationPolicyDiscoveryService = tslib_es6.__decorate([
|
|
49
|
+
common.Injectable(),
|
|
50
|
+
tslib_es6.__metadata("design:paramtypes", [core.DiscoveryService,
|
|
51
|
+
registry_class.ApiAuthorizationPolicyRegistry])
|
|
52
|
+
], exports.ApiAuthorizationPolicyDiscoveryService);
|
|
53
|
+
//# sourceMappingURL=discovery-service.class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery-service.class.js","sources":["../../../../../../../src/class/api/authorization/policy/discovery-service.class.ts"],"sourcesContent":[null],"names":["LoggerUtility","ApiAuthorizationPolicyDiscoveryService","AUTHORIZATION_POLICY_DECORATOR_CONSTANT","ApiAuthorizationPolicyBase","__decorate","Injectable","DiscoveryService","ApiAuthorizationPolicyRegistry"],"mappings":";;;;;;;;;;AAYA,MAAM,qBAAqB,GAAkBA,4BAAa,CAAC,SAAS,CAAC,wCAAwC,CAAC;AAGjGC,8CAAsC,GAA5C,MAAM,sCAAsC,CAAA;AAEhC,IAAA,gBAAA;AACA,IAAA,QAAA;IAFlB,WAAA,CACkB,gBAAkC,EAClC,QAAwC,EAAA;QADxC,IAAA,CAAA,gBAAgB,GAAhB,gBAAgB;QAChB,IAAA,CAAA,QAAQ,GAAR,QAAQ;IACvB;IAEI,YAAY,GAAA;AAClB,QAAA,qBAAqB,CAAC,OAAO,CAAC,4CAA4C,CAAC;QAC3E,MAAM,SAAS,GAA2B,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE;AAC9E,QAAA,MAAM,eAAe,GAA2B,SAAS,CAAC,MAAM,CAAC,CAAC,OAAwB,KAAK,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;AAE7H,QAAA,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE;AACtC,YAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;gBACtB;YACD;AAEA,YAAA,MAAM,QAAQ,GAAY,OAAO,CAAC,WAAW,CAACC,0DAAuC,CAAC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC;YACrH,MAAM,UAAU,GAA4E,QAAmF;YAE/K,IAAI,CAAC,UAAU,EAAE;gBAChB;YACD;YAEA,MAAM,QAAQ,GAAW,UAAU,CAAC,QAAQ,IAAI,CAAA,EAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,SAAS,GAAGA,0DAAuC,CAAC,wBAAwB,CAAA,CAAE;AAE1K,YAAA,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC;gBAChC,WAAW,EAAE,UAAU,CAAC,WAAW;gBACnC,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,QAAQ;AACR,gBAAA,QAAQ,EAAE,UAAU,CAAC,QAAQ,IAAI,CAAC;gBAClC,UAAU,EAAE,OAAO,CAAC,QAA6D;AACjF,aAAA,CAAC;AAEF,YAAA,qBAAqB,CAAC,OAAO,CAAC,CAAA,gCAAA,EAAmC,OAAO,CAAC,IAAI,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,IAAI,eAAe,CAAA,YAAA,EAAe,UAAU,CAAC,MAAM,CAAC,IAAI,IAAI,eAAe,CAAA,eAAA,EAAkB,UAAU,CAAC,QAAQ,IAAI,CAAC,CAAA,CAAE,CAAC;QAChO;QAEA,qBAAqB,CAAC,OAAO,CAAC,CAAA,oDAAA,EAAuD,eAAe,CAAC,MAAM,CAAA,WAAA,CAAa,CAAC;IAC1H;AAEQ,IAAA,eAAe,CAAC,OAAwB,EAAA;AAC/C,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,YAAYC,qCAA0B,IAAI,OAAO,CAAC,WAAW,CAACD,0DAAuC,CAAC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9M;;AAzCYD,8CAAsC,GAAAG,oBAAA,CAAA;AADlD,IAAAC,iBAAU,EAAE;+CAGwBC,qBAAgB;QACxBC,6CAA8B,CAAA;AAH9C,CAAA,EAAAN,8CAAsC,CA0ClD;;"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IApiBaseEntity } from '../../../../interface/api-base-entity.interface';
|
|
2
|
+
import type { IApiAuthorizationPolicySubscriber, IApiAuthorizationPolicySubscriberContext, IApiAuthorizationPolicySubscriberRule } from '../../../../interface/authorization/policy/subscriber/index';
|
|
3
|
+
import type { TApiAuthorizationPolicyHookResult } from '../../../../type/class/api/authorization/policy/hook/index';
|
|
4
|
+
export declare class ApiAuthorizationPolicyExecutor {
|
|
5
|
+
static execute<E extends IApiBaseEntity, TAction extends string>(subscriber: IApiAuthorizationPolicySubscriber<E>, action: TAction, context: IApiAuthorizationPolicySubscriberContext<E>): Promise<Array<IApiAuthorizationPolicySubscriberRule<E, TApiAuthorizationPolicyHookResult<TAction, E>>>>;
|
|
6
|
+
private static normalizeRuleResult;
|
|
7
|
+
private static resolveRouteType;
|
|
8
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var onType_enum = require('../../../../enum/authorization/policy/on-type.enum.js');
|
|
4
|
+
var routeType_enum = require('../../../../enum/decorator/api/route-type.enum.js');
|
|
5
|
+
var capitalizeString_utility = require('../../../../utility/capitalize-string.utility.js');
|
|
6
|
+
var logger_utility = require('../../../../utility/logger.utility.js');
|
|
7
|
+
|
|
8
|
+
const policyExecutorLogger = logger_utility.LoggerUtility.getLogger("ApiAuthorizationPolicyExecutor");
|
|
9
|
+
class ApiAuthorizationPolicyExecutor {
|
|
10
|
+
static async execute(subscriber, action, context) {
|
|
11
|
+
const routeType = context.routeType ?? this.resolveRouteType(action);
|
|
12
|
+
if (routeType) {
|
|
13
|
+
const hookName = `on${onType_enum.EApiAuthorizationPolicyOnType.BEFORE}${capitalizeString_utility.CapitalizeString(routeType)}`;
|
|
14
|
+
const hook = subscriber[hookName];
|
|
15
|
+
if (typeof hook === "function") {
|
|
16
|
+
policyExecutorLogger.verbose(`Executing authorization policy hook ${hookName} from ${subscriber.constructor.name} for action "${action}"`);
|
|
17
|
+
const typedHook = hook;
|
|
18
|
+
const result = typedHook.call(subscriber, context);
|
|
19
|
+
return this.normalizeRuleResult(await result);
|
|
20
|
+
}
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
if (typeof subscriber.getCustomActionRule !== "function") {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
const customActionHook = subscriber.getCustomActionRule.bind(subscriber);
|
|
27
|
+
const customResult = customActionHook(action, context);
|
|
28
|
+
return this.normalizeRuleResult(await customResult);
|
|
29
|
+
}
|
|
30
|
+
static normalizeRuleResult(result) {
|
|
31
|
+
if (Array.isArray(result)) {
|
|
32
|
+
return result.filter((rule) => rule != null);
|
|
33
|
+
}
|
|
34
|
+
return result ? [result] : [];
|
|
35
|
+
}
|
|
36
|
+
static resolveRouteType(action) {
|
|
37
|
+
const routeTypes = Object.values(routeType_enum.EApiRouteType);
|
|
38
|
+
return routeTypes.find((routeType) => routeType === action);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
exports.ApiAuthorizationPolicyExecutor = ApiAuthorizationPolicyExecutor;
|
|
43
|
+
//# sourceMappingURL=executor.class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.class.js","sources":["../../../../../../../src/class/api/authorization/policy/executor.class.ts"],"sourcesContent":[null],"names":["LoggerUtility","EApiAuthorizationPolicyOnType","CapitalizeString","EApiRouteType"],"mappings":";;;;;;;AAUA,MAAM,oBAAoB,GAAkBA,4BAAa,CAAC,SAAS,CAAC,gCAAgC,CAAC;MAIxF,8BAA8B,CAAA;IACnC,aAAa,OAAO,CAAmD,UAAgD,EAAE,MAAe,EAAE,OAAoD,EAAA;AACpM,QAAA,MAAM,SAAS,GAA8B,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;QAE/F,IAAI,SAAS,EAAE;AACd,YAAA,MAAM,QAAQ,GAAW,CAAA,EAAA,EAAKC,yCAA6B,CAAC,MAAM,CAAA,EAAGC,yCAAgB,CAAC,SAAS,CAAC,CAAA,CAAE;AAClG,YAAA,MAAM,IAAI,GAAY,UAAU,CAAC,QAAsD,CAAC;AAExF,YAAA,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE;AAC/B,gBAAA,oBAAoB,CAAC,OAAO,CAAC,CAAA,oCAAA,EAAuC,QAAQ,CAAA,MAAA,EAAS,UAAU,CAAC,WAAW,CAAC,IAAI,CAAA,aAAA,EAAgB,MAAM,CAAA,CAAA,CAAG,CAAC;gBAC1I,MAAM,SAAS,GAAqH,IAAwH;gBAC5P,MAAM,MAAM,GAA2D,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC;AAE1G,gBAAA,OAAO,IAAI,CAAC,mBAAmB,CAAC,MAAM,MAAM,CAAC;YAC9C;AAEA,YAAA,OAAO,EAAE;QACV;AAEA,QAAA,IAAI,OAAO,UAAU,CAAC,mBAAmB,KAAK,UAAU,EAAE;AACzD,YAAA,OAAO,EAAE;QACV;QAEA,MAAM,gBAAgB,GAA+I,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAA+I;QAElW,MAAM,YAAY,GAA2D,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC;AAE9G,QAAA,OAAO,IAAI,CAAC,mBAAmB,CAAC,MAAM,YAAY,CAAC;IACpD;IAEQ,OAAO,mBAAmB,CAA8B,MAAyD,EAAA;AACxH,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;AAC1B,YAAA,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAoE,KAA0D,IAAI,IAAI,IAAI,CAAC;QAClK;QAEA,OAAO,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE;IAC9B;IAEQ,OAAO,gBAAgB,CAAC,MAAc,EAAA;QAC7C,MAAM,UAAU,GAAkB,MAAM,CAAC,MAAM,CAACC,4BAAa,CAAkB;AAE/E,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,SAAiB,KAAK,SAAS,KAAK,MAAM,CAA8B;IACjG;AACA;;;;"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ApiAuthorizationPolicyBase } from './base.class';
|
|
2
|
+
export { ApiAuthorizationPolicyDiscoveryService } from './discovery-service.class';
|
|
3
|
+
export { ApiAuthorizationPolicyExecutor } from './executor.class';
|
|
4
|
+
export { ApiAuthorizationPolicyRegistry } from './registry.class';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { IApiBaseEntity } from '../../../../interface/api-base-entity.interface';
|
|
2
|
+
import type { IApiAuthorizationPolicy, IApiAuthorizationPolicyRegistry, IApiAuthorizationPolicySubscriberRegistration } from '../../../../interface/authorization/index';
|
|
3
|
+
import type { TApiAuthorizationPolicyHookResult } from '../../../../type/class/api/authorization/policy/hook/index';
|
|
4
|
+
type TEntityConstructor<E extends IApiBaseEntity> = new () => E;
|
|
5
|
+
export declare class ApiAuthorizationPolicyRegistry implements IApiAuthorizationPolicyRegistry {
|
|
6
|
+
private readonly LEGACY_POLICIES;
|
|
7
|
+
private readonly POLICY_CACHE;
|
|
8
|
+
private readonly POLICY_REGISTRATIONS_BY_ENTITY;
|
|
9
|
+
private readonly POLICY_REGISTRATIONS_BY_ID;
|
|
10
|
+
constructor();
|
|
11
|
+
buildAggregatedPolicy<E extends IApiBaseEntity, TAction extends string>(entity: TEntityConstructor<E>, action: TAction): Promise<IApiAuthorizationPolicy<E, TApiAuthorizationPolicyHookResult<TAction, E>> | undefined>;
|
|
12
|
+
clear(): void;
|
|
13
|
+
registerPolicy<E extends IApiBaseEntity, R>(policy: IApiAuthorizationPolicy<E, R>): void;
|
|
14
|
+
registerSubscriber<E extends IApiBaseEntity>(registration: IApiAuthorizationPolicySubscriberRegistration<E>): void;
|
|
15
|
+
private cachePolicy;
|
|
16
|
+
private createCacheKey;
|
|
17
|
+
private getEntityName;
|
|
18
|
+
private invalidateCacheForEntity;
|
|
19
|
+
private normalizeRule;
|
|
20
|
+
private resolvePolicyId;
|
|
21
|
+
private resolveRouteType;
|
|
22
|
+
private setLegacyPolicy;
|
|
23
|
+
private toBasePolicy;
|
|
24
|
+
}
|
|
25
|
+
export declare const apiAuthorizationPolicyRegistry: ApiAuthorizationPolicyRegistry;
|
|
26
|
+
export {};
|