@elsikora/nestjs-crud-automator 4.1.0 → 4.2.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 CHANGED
@@ -976,6 +976,16 @@ Custom `@ApiMethod(...)` actions pass through unchanged after the namespace. For
976
976
 
977
977
  The runtime resolves a `principal`, dispatches to the selected mode, and stores a unified `authorizationDecision` on the request. Hooks mode traces matched rules and resolved permissions; IAM mode traces attachments, documents, statements, boundaries, and final decision type. For out-of-band checks, inject `ApiAuthorizationSimulator` and call `evaluate(...)` with the same controller authorization metadata you use at runtime.
978
978
 
979
+ Custom handlers can inject that evaluated decision without accepting the raw request. The decorator returns the exact guard-attached object and fails closed with `403 Forbidden` when a securable route did not produce one:
980
+
981
+ ```typescript
982
+ public async publish(
983
+ @ApiAuthorizationDecision<PostEntity>() authorizationDecision: IApiAuthorizationDecision<PostEntity>,
984
+ ): Promise<PostEntity> {
985
+ return await this.service.publish(authorizationDecision.principal.id);
986
+ }
987
+ ```
988
+
979
989
  Important IAM details from the current implementation:
980
990
 
981
991
  - `resource.id` and `resource.operatorId` are safe planner-friendly paths for `GET` and `GET_LIST` when declared in `resourceDefinition.fields`
@@ -0,0 +1,9 @@
1
+ import { IApiBaseEntity } from '../../../interface/api-base-entity.interface';
2
+ import { TApiAuthorizationRuleTransformPayload } from '../../../type/class/api/authorization/rule/transform-payload.type';
3
+ /**
4
+ * Injects the authorization decision attached to the current HTTP request by the Automator authorization guard.
5
+ * @template E - Authorized entity type.
6
+ * @template R - Authorized route result payload type.
7
+ * @returns {ParameterDecorator} Parameter decorator that fails closed when the request has no authorization decision.
8
+ */
9
+ export declare function ApiAuthorizationDecision<E extends IApiBaseEntity, R extends TApiAuthorizationRuleTransformPayload<E> = TApiAuthorizationRuleTransformPayload<E>>(): ParameterDecorator;
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ var common = require('@nestjs/common');
4
+ var resolveFromRequest_utility = require('../../../utility/authorization/decision/resolve-from-request.utility.js');
5
+
6
+ /**
7
+ * Injects the authorization decision attached to the current HTTP request by the Automator authorization guard.
8
+ * @template E - Authorized entity type.
9
+ * @template R - Authorized route result payload type.
10
+ * @returns {ParameterDecorator} Parameter decorator that fails closed when the request has no authorization decision.
11
+ */
12
+ // Nest's ParameterDecorator cannot carry its factory output type, so these generics bind the factory contract used by each decorator application.
13
+ // eslint-disable-next-line @elsikora/typescript/no-unnecessary-type-parameters
14
+ function ApiAuthorizationDecision() {
15
+ return common.createParamDecorator((_data, context) => {
16
+ const request = context.switchToHttp().getRequest();
17
+ const decision = resolveFromRequest_utility.AuthorizationDecisionResolveFromRequest(request);
18
+ if (!decision) {
19
+ throw new common.ForbiddenException();
20
+ }
21
+ return decision;
22
+ })();
23
+ }
24
+
25
+ exports.ApiAuthorizationDecision = ApiAuthorizationDecision;
26
+ //# sourceMappingURL=decision.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.decorator.js","sources":["../../../../../../src/decorator/api/authorization/decision.decorator.ts"],"sourcesContent":[null],"names":["createParamDecorator","AuthorizationDecisionResolveFromRequest","ForbiddenException"],"mappings":";;;;;AASA;;;;;AAKG;AACH;AACA;SACgB,wBAAwB,GAAA;AACvC,IAAA,OAAOA,2BAAoB,CAA6C,CAAC,KAAgB,EAAE,OAAyB,KAAqC;QACxJ,MAAM,OAAO,GAA8B,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAA6B;AACzG,QAAA,MAAM,QAAQ,GAAgDC,kEAAuC,CAAO,OAAO,CAAC;QAEpH,IAAI,CAAC,QAAQ,EAAE;YACd,MAAM,IAAIC,yBAAkB,EAAE;QAC/B;AAEA,QAAA,OAAO,QAAQ;IAChB,CAAC,CAAC,EAAE;AACL;;;;"}
@@ -1,4 +1,5 @@
1
1
  export { ApiAuthorizationPolicy } from './authorization-policy.decorator';
2
+ export { ApiAuthorizationDecision } from './authorization/decision.decorator';
2
3
  export * from './controller';
3
4
  export * from './function';
4
5
  export { ApiMethod } from './method.decorator';
package/dist/cjs/index.js CHANGED
@@ -78,6 +78,7 @@ require('./constant/utility/api/get-default-string-format-properties/customizer-
78
78
  var constant = require('./constant/utility/dto/constant.js');
79
79
  var generate_constant = require('./constant/utility/dto/generate.constant.js');
80
80
  var authorizationPolicy_decorator = require('./decorator/api/authorization-policy.decorator.js');
81
+ var decision_decorator = require('./decorator/api/authorization/decision.decorator.js');
81
82
  var decorator = require('./decorator/api/controller/decorator.js');
82
83
  var observable_decorator = require('./decorator/api/controller/observable.decorator.js');
83
84
  var securable_decorator = require('./decorator/api/controller/securable.decorator.js');
@@ -378,6 +379,7 @@ exports.GET_DEFAULT_STRING_FORMAT_PROPERTIES_API_UTILITY_CONSTANT = constant$1.G
378
379
  exports.DTO_UTILITY_CONSTANT = constant.DTO_UTILITY_CONSTANT;
379
380
  exports.DTO_GENERATE_CONSTANT = generate_constant.DTO_GENERATE_CONSTANT;
380
381
  exports.ApiAuthorizationPolicy = authorizationPolicy_decorator.ApiAuthorizationPolicy;
382
+ exports.ApiAuthorizationDecision = decision_decorator.ApiAuthorizationDecision;
381
383
  exports.ApiController = decorator.ApiController;
382
384
  exports.ApiControllerObservable = observable_decorator.ApiControllerObservable;
383
385
  exports.ApiControllerSecurable = securable_decorator.ApiControllerSecurable;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -5,7 +5,8 @@ import { IApiAuthorizationPrincipal } from '../principal/interface';
5
5
  import { IApiAuthorizationRule } from '../rule/interface';
6
6
  import { IApiAuthorizationScope } from '../scope.interface';
7
7
  import { TApiAuthorizationRuleResultTransform } from '../../../../../type/class/api/authorization/rule/result-transform.type';
8
- export interface IApiAuthorizationDecision<E extends IApiBaseEntity, R> {
8
+ import { TApiAuthorizationRuleTransformPayload } from '../../../../../type/class/api/authorization/rule/transform-payload.type';
9
+ export interface IApiAuthorizationDecision<E extends IApiBaseEntity, R = TApiAuthorizationRuleTransformPayload<E>> {
9
10
  action: string;
10
11
  appliedRules: Array<IApiAuthorizationRule<E, R>>;
11
12
  effect: EApiPolicyEffect;
@@ -0,0 +1,9 @@
1
+ import { IApiBaseEntity } from '../../../interface/api-base-entity.interface';
2
+ import { TApiAuthorizationRuleTransformPayload } from '../../../type/class/api/authorization/rule/transform-payload.type';
3
+ /**
4
+ * Injects the authorization decision attached to the current HTTP request by the Automator authorization guard.
5
+ * @template E - Authorized entity type.
6
+ * @template R - Authorized route result payload type.
7
+ * @returns {ParameterDecorator} Parameter decorator that fails closed when the request has no authorization decision.
8
+ */
9
+ export declare function ApiAuthorizationDecision<E extends IApiBaseEntity, R extends TApiAuthorizationRuleTransformPayload<E> = TApiAuthorizationRuleTransformPayload<E>>(): ParameterDecorator;
@@ -0,0 +1,24 @@
1
+ import { createParamDecorator, ForbiddenException } from '@nestjs/common';
2
+ import { AuthorizationDecisionResolveFromRequest } from '../../../utility/authorization/decision/resolve-from-request.utility.js';
3
+
4
+ /**
5
+ * Injects the authorization decision attached to the current HTTP request by the Automator authorization guard.
6
+ * @template E - Authorized entity type.
7
+ * @template R - Authorized route result payload type.
8
+ * @returns {ParameterDecorator} Parameter decorator that fails closed when the request has no authorization decision.
9
+ */
10
+ // Nest's ParameterDecorator cannot carry its factory output type, so these generics bind the factory contract used by each decorator application.
11
+ // eslint-disable-next-line @elsikora/typescript/no-unnecessary-type-parameters
12
+ function ApiAuthorizationDecision() {
13
+ return createParamDecorator((_data, context) => {
14
+ const request = context.switchToHttp().getRequest();
15
+ const decision = AuthorizationDecisionResolveFromRequest(request);
16
+ if (!decision) {
17
+ throw new ForbiddenException();
18
+ }
19
+ return decision;
20
+ })();
21
+ }
22
+
23
+ export { ApiAuthorizationDecision };
24
+ //# sourceMappingURL=decision.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.decorator.js","sources":["../../../../../../src/decorator/api/authorization/decision.decorator.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AASA;;;;;AAKG;AACH;AACA;SACgB,wBAAwB,GAAA;AACvC,IAAA,OAAO,oBAAoB,CAA6C,CAAC,KAAgB,EAAE,OAAyB,KAAqC;QACxJ,MAAM,OAAO,GAA8B,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAA6B;AACzG,QAAA,MAAM,QAAQ,GAAgD,uCAAuC,CAAO,OAAO,CAAC;QAEpH,IAAI,CAAC,QAAQ,EAAE;YACd,MAAM,IAAI,kBAAkB,EAAE;QAC/B;AAEA,QAAA,OAAO,QAAQ;IAChB,CAAC,CAAC,EAAE;AACL;;;;"}
@@ -1,4 +1,5 @@
1
1
  export { ApiAuthorizationPolicy } from './authorization-policy.decorator';
2
+ export { ApiAuthorizationDecision } from './authorization/decision.decorator';
2
3
  export * from './controller';
3
4
  export * from './function';
4
5
  export { ApiMethod } from './method.decorator';
package/dist/esm/index.js CHANGED
@@ -76,6 +76,7 @@ import './constant/utility/api/get-default-string-format-properties/customizer-m
76
76
  export { DTO_UTILITY_CONSTANT } from './constant/utility/dto/constant.js';
77
77
  export { DTO_GENERATE_CONSTANT } from './constant/utility/dto/generate.constant.js';
78
78
  export { ApiAuthorizationPolicy } from './decorator/api/authorization-policy.decorator.js';
79
+ export { ApiAuthorizationDecision } from './decorator/api/authorization/decision.decorator.js';
79
80
  export { ApiController } from './decorator/api/controller/decorator.js';
80
81
  export { ApiControllerObservable } from './decorator/api/controller/observable.decorator.js';
81
82
  export { ApiControllerSecurable } from './decorator/api/controller/securable.decorator.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -5,7 +5,8 @@ import { IApiAuthorizationPrincipal } from '../principal/interface';
5
5
  import { IApiAuthorizationRule } from '../rule/interface';
6
6
  import { IApiAuthorizationScope } from '../scope.interface';
7
7
  import { TApiAuthorizationRuleResultTransform } from '../../../../../type/class/api/authorization/rule/result-transform.type';
8
- export interface IApiAuthorizationDecision<E extends IApiBaseEntity, R> {
8
+ import { TApiAuthorizationRuleTransformPayload } from '../../../../../type/class/api/authorization/rule/transform-payload.type';
9
+ export interface IApiAuthorizationDecision<E extends IApiBaseEntity, R = TApiAuthorizationRuleTransformPayload<E>> {
9
10
  action: string;
10
11
  appliedRules: Array<IApiAuthorizationRule<E, R>>;
11
12
  effect: EApiPolicyEffect;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elsikora/nestjs-crud-automator",
3
- "version": "4.1.0",
3
+ "version": "4.2.0-dev.1",
4
4
  "description": "A library for automating the creation of CRUD operations in NestJS.",
5
5
  "keywords": [
6
6
  "NestJS",