@api-client/core 0.19.40 → 0.19.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/build/src/index.d.ts +1 -1
  2. package/build/src/index.d.ts.map +1 -1
  3. package/build/src/index.js.map +1 -1
  4. package/build/src/modeling/RuntimeApiModel.d.ts +20 -0
  5. package/build/src/modeling/RuntimeApiModel.d.ts.map +1 -1
  6. package/build/src/modeling/RuntimeApiModel.js +133 -0
  7. package/build/src/modeling/RuntimeApiModel.js.map +1 -1
  8. package/build/src/modeling/index.d.ts +2 -0
  9. package/build/src/modeling/index.d.ts.map +1 -1
  10. package/build/src/modeling/index.js +1 -0
  11. package/build/src/modeling/index.js.map +1 -1
  12. package/build/src/modeling/rules/AccessRule.d.ts +40 -1
  13. package/build/src/modeling/rules/AccessRule.d.ts.map +1 -1
  14. package/build/src/modeling/rules/AccessRule.js +44 -2
  15. package/build/src/modeling/rules/AccessRule.js.map +1 -1
  16. package/build/src/modeling/rules/AllowAuthenticated.d.ts.map +1 -1
  17. package/build/src/modeling/rules/AllowAuthenticated.js +9 -2
  18. package/build/src/modeling/rules/AllowAuthenticated.js.map +1 -1
  19. package/build/src/modeling/rules/AllowPublic.d.ts.map +1 -1
  20. package/build/src/modeling/rules/AllowPublic.js +9 -2
  21. package/build/src/modeling/rules/AllowPublic.js.map +1 -1
  22. package/build/src/modeling/rules/LifecycleStatus.d.ts +36 -0
  23. package/build/src/modeling/rules/LifecycleStatus.d.ts.map +1 -0
  24. package/build/src/modeling/rules/LifecycleStatus.js +60 -0
  25. package/build/src/modeling/rules/LifecycleStatus.js.map +1 -0
  26. package/build/src/modeling/rules/MatchEmailDomain.d.ts.map +1 -1
  27. package/build/src/modeling/rules/MatchEmailDomain.js +9 -2
  28. package/build/src/modeling/rules/MatchEmailDomain.js.map +1 -1
  29. package/build/src/modeling/rules/MatchResourceAttribute.d.ts +38 -0
  30. package/build/src/modeling/rules/MatchResourceAttribute.d.ts.map +1 -0
  31. package/build/src/modeling/rules/MatchResourceAttribute.js +68 -0
  32. package/build/src/modeling/rules/MatchResourceAttribute.js.map +1 -0
  33. package/build/src/modeling/rules/MatchResourceOwner.d.ts.map +1 -1
  34. package/build/src/modeling/rules/MatchResourceOwner.js +8 -2
  35. package/build/src/modeling/rules/MatchResourceOwner.js.map +1 -1
  36. package/build/src/modeling/rules/MatchUserProperty.d.ts.map +1 -1
  37. package/build/src/modeling/rules/MatchUserProperty.js +9 -2
  38. package/build/src/modeling/rules/MatchUserProperty.js.map +1 -1
  39. package/build/src/modeling/rules/MatchUserRole.d.ts.map +1 -1
  40. package/build/src/modeling/rules/MatchUserRole.js +9 -2
  41. package/build/src/modeling/rules/MatchUserRole.js.map +1 -1
  42. package/build/src/modeling/rules/index.d.ts +8 -6
  43. package/build/src/modeling/rules/index.d.ts.map +1 -1
  44. package/build/src/modeling/rules/index.js +8 -2
  45. package/build/src/modeling/rules/index.js.map +1 -1
  46. package/build/tsconfig.tsbuildinfo +1 -1
  47. package/package.json +1 -1
  48. package/src/modeling/RuntimeApiModel.ts +166 -2
  49. package/src/modeling/rules/AccessRule.ts +70 -2
  50. package/src/modeling/rules/AllowAuthenticated.ts +13 -2
  51. package/src/modeling/rules/AllowPublic.ts +13 -2
  52. package/src/modeling/rules/LifecycleStatus.ts +71 -0
  53. package/src/modeling/rules/MatchEmailDomain.ts +13 -2
  54. package/src/modeling/rules/MatchResourceAttribute.ts +82 -0
  55. package/src/modeling/rules/MatchResourceOwner.ts +12 -2
  56. package/src/modeling/rules/MatchUserProperty.ts +13 -2
  57. package/src/modeling/rules/MatchUserRole.ts +13 -2
  58. package/tests/unit/modeling/RuntimeApiModel.spec.ts +189 -1
  59. package/tests/unit/modeling/actions/Action.spec.ts +2 -2
  60. package/tests/unit/modeling/actions/CreateAction.spec.ts +1 -1
  61. package/tests/unit/modeling/actions/ReadAction.spec.ts +2 -2
  62. package/tests/unit/modeling/exposed_entity.spec.ts +1 -1
  63. package/tests/unit/modeling/rules/AccessRule.spec.ts +5 -5
  64. package/tests/unit/modeling/rules/LifecycleStatus.spec.ts +55 -0
  65. package/tests/unit/modeling/rules/MatchResourceAttribute.spec.ts +66 -0
@@ -10,7 +10,7 @@ export * as Events from './events/index.js';
10
10
  export * as Exceptions from './exceptions/index.js';
11
11
  export * from './sdk/index.js';
12
12
  export * from './sdk/StoreSdkNode.js';
13
- export { RuntimeApiModel, type RuntimeApiModelSchema, type RoutingMap, type RouteDefinition, type RouteLookup, type RuntimeResolvedAction, } from './modeling/RuntimeApiModel.js';
13
+ export { RuntimeApiModel, type RuntimeApiModelSchema, type RoutingMap, type RouteDefinition, type RouteLookup, type RuntimeResolvedAction, type RuleEvaluator, } from './modeling/RuntimeApiModel.js';
14
14
  export { PayloadSerializer, type ISafePayload, type IMultipartBody, type Payload, type DeserializedPayload, type IBlobMeta, type IFileMeta, } from './lib/transformers/PayloadSerializer.js';
15
15
  export * from './lib/logging/index.js';
16
16
  export { Headers } from './lib/headers/Headers.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// all exports that are save for NodeJS process processing.\n\n//\n// Ecosystem-shared Config\n//\nexport * from './config/index.js'\n\nexport { nanoid } from './nanoid.js'\n\n//\n// Models\n//\nexport * as Models from './models/index.js'\nexport * as Kinds from './models/kinds.js'\nexport * as Modeling from './modeling/index.js'\nexport * as Data from './data/index.js'\nexport * as Patch from './patch/index.js'\nexport * as Authorization from './authorization/index.js'\nexport * as Events from './events/index.js'\nexport * as Exceptions from './exceptions/index.js'\nexport * from './sdk/index.js'\nexport * from './sdk/StoreSdkNode.js'\n\n// Node only.\nexport {\n RuntimeApiModel,\n type RuntimeApiModelSchema,\n type RoutingMap,\n type RouteDefinition,\n type RouteLookup,\n type RuntimeResolvedAction,\n} from './modeling/RuntimeApiModel.js'\n\n//\n// Libs\n//\nexport {\n PayloadSerializer,\n type ISafePayload,\n type IMultipartBody,\n type Payload,\n type DeserializedPayload,\n type IBlobMeta,\n type IFileMeta,\n} from './lib/transformers/PayloadSerializer.js'\nexport * from './lib/logging/index.js'\nexport { Headers } from './lib/headers/Headers.js'\nexport * as EventUtils from './lib/events/Utils.js'\nexport { default as uuidV4 } from './lib/uuid.js'\nexport * as fs from './lib/fs/Fs.js'\nexport { UrlParser } from './lib/parsers/UrlParser.js'\nexport { UrlEncoder } from './lib/parsers/UrlEncoder.js'\nexport * as Timers from './lib/timers/Timers.js'\nexport { UriTemplate, type IUriTemplateOptions } from './lib/parsers/UriTemplate.js'\nexport * from './lib/parsers/UrlProcessor.js'\nexport * as HttpDefinitions from './lib/definitions/HttpDefinitions.js'\nexport * as Buffer from './lib/Buffer.js'\nexport * as Random from './lib/math/Random.js'\nexport * as ColorConverter from './lib/color/ColorConverter.js'\n\n//\n// Cookies\n//\nexport { CookieParser, type SameSiteValue } from './cookies/CookieParser.js'\nexport { CookieJar } from './cookies/CookieJar.js'\nexport { InMemoryCookieJar, clearStore as ClearInMemoryCookieJar } from './cookies/InMemoryCookieJar.js'\n\n//\n// Runtime\n//\nexport { VariablesProcessor } from './runtime/variables/VariablesProcessor.js'\nexport { ProjectRequestRunner } from './runtime/node/ProjectRequestRunner.js'\nexport { HttpRequestRunner } from './runtime/http-runner/HttpRequestRunner.js'\nexport { ProjectSerialRunner } from './runtime/node/ProjectSerialRunner.js'\nexport { ProjectParallelRunner, type IWorkerInfo } from './runtime/node/ProjectParallelRunner.js'\nexport { ProjectRunner } from './runtime/node/ProjectRunner.js'\nexport * from './runtime/node/InteropInterfaces.js'\n\n//\n// Execution reporters\n//\nexport { Reporter } from './runtime/reporters/Reporter.js'\nexport { ProjectRunCliReporter } from './runtime/reporters/ProjectRunCliReporter.js'\n\n//\n// HTTP engine\n//\nexport {\n CoreEngine,\n type HttpEngineOptions,\n type RequestStats,\n type HeadersReceivedDetail,\n type BeforeRedirectDetail,\n type ResponseErrorInit,\n type IRequestAuthState,\n} from './runtime/http-engine/CoreEngine.js'\n\n//\n// Testing\n//\nexport * from './testing/TestCliHelper.js'\nexport * from './testing/getPort.js'\n\n//\n// Mocking\n//\nexport * from './mocking/ProjectMock.js'\n\n//\n// Calculators\n//\nexport { DataCalculator } from './lib/calculators/DataCalculator.js'\n\n//\n// Proxy logic\n//\nexport { type IProxyResult, default as ProxyLib } from './proxy/Proxy.js'\nexport {\n type IHttpProjectProxyInit,\n type IHttpProjectStoreProxyInit,\n default as HttpProjectProxy,\n} from './proxy/HttpProjectProxy.js'\nexport { type IRequestProxyInit, default as RequestProxy } from './proxy/RequestProxy.js'\nexport { default as ProxyService } from './proxy/ProxyService.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAE3D,EAAE;AACF,0BAA0B;AAC1B,EAAE;AACF,cAAc,mBAAmB,CAAA;AAEjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,EAAE;AACF,SAAS;AACT,EAAE;AACF,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAA;AAC1C,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAA;AAC/C,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AACzC,OAAO,KAAK,aAAa,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAA;AACnD,cAAc,gBAAgB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AAErC,aAAa;AACb,OAAO,EACL,eAAe,GAOhB,MAAM,+BAA+B,CAAA;AAEtC,EAAE;AACF,OAAO;AACP,EAAE;AACF,OAAO,EACL,iBAAiB,GAOlB,MAAM,yCAAyC,CAAA;AAChD,cAAc,wBAAwB,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAClD,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AACxD,OAAO,KAAK,MAAM,MAAM,wBAAwB,CAAA;AAChD,OAAO,EAAE,WAAW,EAA4B,MAAM,8BAA8B,CAAA;AACpF,cAAc,+BAA+B,CAAA;AAC7C,OAAO,KAAK,eAAe,MAAM,sCAAsC,CAAA;AACvE,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAA;AAC9C,OAAO,KAAK,cAAc,MAAM,+BAA+B,CAAA;AAE/D,EAAE;AACF,UAAU;AACV,EAAE;AACF,OAAO,EAAE,YAAY,EAAsB,MAAM,2BAA2B,CAAA;AAC5E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,iBAAiB,EAAE,UAAU,IAAI,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAExG,EAAE;AACF,UAAU;AACV,EAAE;AACF,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAA;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAA;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAA;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAA;AAC3E,OAAO,EAAE,qBAAqB,EAAoB,MAAM,yCAAyC,CAAA;AACjG,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AAC/D,cAAc,qCAAqC,CAAA;AAEnD,EAAE;AACF,sBAAsB;AACtB,EAAE;AACF,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAA;AAEpF,EAAE;AACF,cAAc;AACd,EAAE;AACF,OAAO,EACL,UAAU,GAOX,MAAM,qCAAqC,CAAA;AAE5C,EAAE;AACF,UAAU;AACV,EAAE;AACF,cAAc,4BAA4B,CAAA;AAC1C,cAAc,sBAAsB,CAAA;AAEpC,EAAE;AACF,UAAU;AACV,EAAE;AACF,cAAc,0BAA0B,CAAA;AAExC,EAAE;AACF,cAAc;AACd,EAAE;AACF,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AAEpE,EAAE;AACF,cAAc;AACd,EAAE;AACF,OAAO,EAAqB,OAAO,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AACzE,OAAO,EAGL,OAAO,IAAI,gBAAgB,GAC5B,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAA0B,OAAO,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACzF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAA","sourcesContent":["// all exports that are save for NodeJS process processing.\n\n//\n// Ecosystem-shared Config\n//\nexport * from './config/index.js'\n\nexport { nanoid } from './nanoid.js'\n\n//\n// Models\n//\nexport * as Models from './models/index.js'\nexport * as Kinds from './models/kinds.js'\nexport * as Modeling from './modeling/index.js'\nexport * as Data from './data/index.js'\nexport * as Patch from './patch/index.js'\nexport * as Authorization from './authorization/index.js'\nexport * as Events from './events/index.js'\nexport * as Exceptions from './exceptions/index.js'\nexport * from './sdk/index.js'\nexport * from './sdk/StoreSdkNode.js'\n\n// Node only.\nexport {\n RuntimeApiModel,\n type RuntimeApiModelSchema,\n type RoutingMap,\n type RouteDefinition,\n type RouteLookup,\n type RuntimeResolvedAction,\n type RuleEvaluator,\n} from './modeling/RuntimeApiModel.js'\n\n//\n// Libs\n//\nexport {\n PayloadSerializer,\n type ISafePayload,\n type IMultipartBody,\n type Payload,\n type DeserializedPayload,\n type IBlobMeta,\n type IFileMeta,\n} from './lib/transformers/PayloadSerializer.js'\nexport * from './lib/logging/index.js'\nexport { Headers } from './lib/headers/Headers.js'\nexport * as EventUtils from './lib/events/Utils.js'\nexport { default as uuidV4 } from './lib/uuid.js'\nexport * as fs from './lib/fs/Fs.js'\nexport { UrlParser } from './lib/parsers/UrlParser.js'\nexport { UrlEncoder } from './lib/parsers/UrlEncoder.js'\nexport * as Timers from './lib/timers/Timers.js'\nexport { UriTemplate, type IUriTemplateOptions } from './lib/parsers/UriTemplate.js'\nexport * from './lib/parsers/UrlProcessor.js'\nexport * as HttpDefinitions from './lib/definitions/HttpDefinitions.js'\nexport * as Buffer from './lib/Buffer.js'\nexport * as Random from './lib/math/Random.js'\nexport * as ColorConverter from './lib/color/ColorConverter.js'\n\n//\n// Cookies\n//\nexport { CookieParser, type SameSiteValue } from './cookies/CookieParser.js'\nexport { CookieJar } from './cookies/CookieJar.js'\nexport { InMemoryCookieJar, clearStore as ClearInMemoryCookieJar } from './cookies/InMemoryCookieJar.js'\n\n//\n// Runtime\n//\nexport { VariablesProcessor } from './runtime/variables/VariablesProcessor.js'\nexport { ProjectRequestRunner } from './runtime/node/ProjectRequestRunner.js'\nexport { HttpRequestRunner } from './runtime/http-runner/HttpRequestRunner.js'\nexport { ProjectSerialRunner } from './runtime/node/ProjectSerialRunner.js'\nexport { ProjectParallelRunner, type IWorkerInfo } from './runtime/node/ProjectParallelRunner.js'\nexport { ProjectRunner } from './runtime/node/ProjectRunner.js'\nexport * from './runtime/node/InteropInterfaces.js'\n\n//\n// Execution reporters\n//\nexport { Reporter } from './runtime/reporters/Reporter.js'\nexport { ProjectRunCliReporter } from './runtime/reporters/ProjectRunCliReporter.js'\n\n//\n// HTTP engine\n//\nexport {\n CoreEngine,\n type HttpEngineOptions,\n type RequestStats,\n type HeadersReceivedDetail,\n type BeforeRedirectDetail,\n type ResponseErrorInit,\n type IRequestAuthState,\n} from './runtime/http-engine/CoreEngine.js'\n\n//\n// Testing\n//\nexport * from './testing/TestCliHelper.js'\nexport * from './testing/getPort.js'\n\n//\n// Mocking\n//\nexport * from './mocking/ProjectMock.js'\n\n//\n// Calculators\n//\nexport { DataCalculator } from './lib/calculators/DataCalculator.js'\n\n//\n// Proxy logic\n//\nexport { type IProxyResult, default as ProxyLib } from './proxy/Proxy.js'\nexport {\n type IHttpProjectProxyInit,\n type IHttpProjectStoreProxyInit,\n default as HttpProjectProxy,\n} from './proxy/HttpProjectProxy.js'\nexport { type IRequestProxyInit, default as RequestProxy } from './proxy/RequestProxy.js'\nexport { default as ProxyService } from './proxy/ProxyService.js'\n"]}
@@ -5,6 +5,7 @@ import type { ExposedEntity } from './ExposedEntity.js';
5
5
  import type { Action } from './actions/Action.js';
6
6
  import type { DomainEntity } from './DomainEntity.js';
7
7
  import type { DomainProperty } from './DomainProperty.js';
8
+ import { AccessRule, AccessRuleExecutionPhase } from './rules/AccessRule.js';
8
9
  /**
9
10
  * Identifies a specific exposed entity and its action kind.
10
11
  */
@@ -34,6 +35,7 @@ export interface RuntimeResolvedAction {
34
35
  action: Action;
35
36
  params: Record<string, string>;
36
37
  }
38
+ export type RuleEvaluator = (rule: AccessRule) => Promise<boolean | undefined> | boolean | undefined;
37
39
  /**
38
40
  * An optimized API Model subclass designed for fast runtime lookups.
39
41
  * It pre-compiles the RoutingMap into a radix tree for O(log N) or faster endpoint resolution.
@@ -63,6 +65,24 @@ export declare class RuntimeApiModel extends ApiModel {
63
65
  * @returns An object with the entity, action, and extracted path parameters if a match is found.
64
66
  */
65
67
  lookupAction(method: string, path: string): RuntimeResolvedAction | undefined;
68
+ /**
69
+ * Evaluates access rules for a given action and phase.
70
+ *
71
+ * The evaluation process follows two phases per execution phase (PRE_FETCH, FETCH, POST_FETCH):
72
+ * 1. Mandatory Phase: All rules marked as `mandatory: true` across all levels must return true.
73
+ * If any fail, the request is immediately rejected.
74
+ * 2. Permission Phase: Evaluation follows the hierarchy from most specific to most general:
75
+ * Action -> Endpoint (ExposedEntity) -> API Model.
76
+ * If an explicit allow (true) or deny (false) is hit, evaluation stops and returns the result.
77
+ * If no rules match (all return undefined), the request is rejected by default.
78
+ *
79
+ * @param action The resolved action to evaluate.
80
+ * @param evaluator A callback that evaluates a single rule. Should return true (allow),
81
+ * false (deny), or undefined (no hit).
82
+ * @param phase The execution phase to evaluate.
83
+ * @returns A promise that resolves to true if access is granted, false if denied.
84
+ */
85
+ evaluateAccess(action: RuntimeResolvedAction, evaluator: RuleEvaluator, phase: AccessRuleExecutionPhase): Promise<boolean>;
66
86
  toJSON(): RuntimeApiModelSchema;
67
87
  }
68
88
  //# sourceMappingURL=RuntimeApiModel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RuntimeApiModel.d.ts","sourceRoot":"","sources":["../../../src/modeling/RuntimeApiModel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,WAAW,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;AAE1D;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IAC3D,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,aAAa,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B;AAED;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;;IAY3C;;OAEG;IACH,cAAc,EAAE;QACd,IAAI,CAAC,EAAE,YAAY,CAAA;KACpB,CAAK;IAEN;;OAEG;IACH,gBAAgB,EAAE;QAChB,QAAQ,CAAC,EAAE,cAAc,CAAA;QACzB,QAAQ,CAAC,EAAE,cAAc,CAAA;QACzB,IAAI,CAAC,EAAE,cAAc,CAAA;KACtB,CAAK;gBAEM,MAAM,EAAE,qBAAqB,EAAE,YAAY,EAAE,gBAAgB;IAkDzE;;;;;;OAMG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAoCpE,MAAM,IAAI,qBAAqB;CAazC"}
1
+ {"version":3,"file":"RuntimeApiModel.d.ts","sourceRoot":"","sources":["../../../src/modeling/RuntimeApiModel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAE5E;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,WAAW,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;AAE1D;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IAC3D,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,aAAa,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,GAAG,OAAO,GAAG,SAAS,CAAA;AAapG;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;;IAY3C;;OAEG;IACH,cAAc,EAAE;QACd,IAAI,CAAC,EAAE,YAAY,CAAA;KACpB,CAAK;IAEN;;OAEG;IACH,gBAAgB,EAAE;QAChB,QAAQ,CAAC,EAAE,cAAc,CAAA;QACzB,QAAQ,CAAC,EAAE,cAAc,CAAA;QACzB,IAAI,CAAC,EAAE,cAAc,CAAA;KACtB,CAAK;gBAOM,MAAM,EAAE,qBAAqB,EAAE,YAAY,EAAE,gBAAgB;IAsIzE;;;;;;OAMG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAoC7E;;;;;;;;;;;;;;;;OAgBG;IACG,cAAc,CAClB,MAAM,EAAE,qBAAqB,EAC7B,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,OAAO,CAAC;IAwCV,MAAM,IAAI,qBAAqB;CAazC"}
@@ -1,6 +1,7 @@
1
1
  import { match, parse, exec } from '@poppinss/matchit';
2
2
  import { ApiModel } from './ApiModel.js';
3
3
  import { SemanticType } from './Semantics.js';
4
+ import { AccessRuleExecutionPhase } from './rules/AccessRule.js';
4
5
  /**
5
6
  * An optimized API Model subclass designed for fast runtime lookups.
6
7
  * It pre-compiles the RoutingMap into a radix tree for O(log N) or faster endpoint resolution.
@@ -23,12 +24,90 @@ export class RuntimeApiModel extends ApiModel {
23
24
  * Cached references to commonly used properties for fast runtime lookup.
24
25
  */
25
26
  cachedProperties = {};
27
+ /**
28
+ * Cached access rules for each action to avoid runtime computation overhead.
29
+ */
30
+ #actionRulesCache = new WeakMap();
26
31
  constructor(schema, domainSchema) {
27
32
  super(schema, domainSchema);
28
33
  if (schema.routingMap) {
29
34
  this.#initializeRouter(schema.routingMap);
30
35
  }
31
36
  this.#cacheEntitiesAndProperties();
37
+ this.#precomputeAccessRules();
38
+ }
39
+ #precomputeAccessRules() {
40
+ for (const entity of this.exposes.values()) {
41
+ for (const action of entity.actions) {
42
+ this.#actionRulesCache.set(action, this.#computeEffectiveRules(action, entity));
43
+ }
44
+ }
45
+ }
46
+ #computeEffectiveRules(action, entity) {
47
+ const hierarchy = [];
48
+ if (action.accessRule && action.accessRule.length > 0) {
49
+ hierarchy.push(action.accessRule);
50
+ }
51
+ let currentEntity = entity;
52
+ while (currentEntity) {
53
+ if (currentEntity.accessRule && currentEntity.accessRule.length > 0) {
54
+ hierarchy.push(currentEntity.accessRule);
55
+ }
56
+ currentEntity = currentEntity.parent ? this.exposes.get(currentEntity.parent.key) : undefined;
57
+ }
58
+ if (this.accessRule && this.accessRule.length > 0) {
59
+ hierarchy.push(this.accessRule);
60
+ }
61
+ const result = {
62
+ preFetch: {
63
+ permissionRules: [],
64
+ mandatoryRules: [],
65
+ },
66
+ fetch: {
67
+ permissionRules: [],
68
+ mandatoryRules: [],
69
+ },
70
+ postFetch: {
71
+ permissionRules: [],
72
+ mandatoryRules: [],
73
+ },
74
+ };
75
+ const seenTypes = new Set();
76
+ for (const rulesLevel of hierarchy) {
77
+ const typesInThisLevel = new Set();
78
+ for (const rule of rulesLevel) {
79
+ const phase = rule.metadata[action.kind];
80
+ // If the rule does not specify an execution phase for this action kind, it is not evaluated
81
+ if (!phase) {
82
+ continue;
83
+ }
84
+ // Shadowing: If a rule of the same type was defined closer to the action, ignore this one.
85
+ if (seenTypes.has(rule.type)) {
86
+ continue;
87
+ }
88
+ typesInThisLevel.add(rule.type);
89
+ let bucket;
90
+ if (phase === AccessRuleExecutionPhase.POST_FETCH) {
91
+ bucket = result.postFetch;
92
+ }
93
+ else if (phase === AccessRuleExecutionPhase.FETCH) {
94
+ bucket = result.fetch;
95
+ }
96
+ else {
97
+ bucket = result.preFetch;
98
+ }
99
+ if (rule.mandatory) {
100
+ bucket.mandatoryRules.push(rule);
101
+ }
102
+ else {
103
+ bucket.permissionRules.push(rule);
104
+ }
105
+ }
106
+ for (const type of typesInThisLevel) {
107
+ seenTypes.add(type);
108
+ }
109
+ }
110
+ return result;
32
111
  }
33
112
  #cacheEntitiesAndProperties() {
34
113
  if (!this.user || !this.domain) {
@@ -101,6 +180,60 @@ export class RuntimeApiModel extends ApiModel {
101
180
  params,
102
181
  };
103
182
  }
183
+ /**
184
+ * Evaluates access rules for a given action and phase.
185
+ *
186
+ * The evaluation process follows two phases per execution phase (PRE_FETCH, FETCH, POST_FETCH):
187
+ * 1. Mandatory Phase: All rules marked as `mandatory: true` across all levels must return true.
188
+ * If any fail, the request is immediately rejected.
189
+ * 2. Permission Phase: Evaluation follows the hierarchy from most specific to most general:
190
+ * Action -> Endpoint (ExposedEntity) -> API Model.
191
+ * If an explicit allow (true) or deny (false) is hit, evaluation stops and returns the result.
192
+ * If no rules match (all return undefined), the request is rejected by default.
193
+ *
194
+ * @param action The resolved action to evaluate.
195
+ * @param evaluator A callback that evaluates a single rule. Should return true (allow),
196
+ * false (deny), or undefined (no hit).
197
+ * @param phase The execution phase to evaluate.
198
+ * @returns A promise that resolves to true if access is granted, false if denied.
199
+ */
200
+ async evaluateAccess(action, evaluator, phase) {
201
+ let cachedRules = this.#actionRulesCache.get(action.action);
202
+ if (!cachedRules) {
203
+ // Fallback if somehow action is not cached (e.g. dynamically added after initialization or in tests)
204
+ cachedRules = this.#computeEffectiveRules(action.action, action.entity);
205
+ this.#actionRulesCache.set(action.action, cachedRules);
206
+ }
207
+ let rulesForPhase;
208
+ if (phase === AccessRuleExecutionPhase.POST_FETCH) {
209
+ rulesForPhase = cachedRules.postFetch;
210
+ }
211
+ else if (phase === AccessRuleExecutionPhase.FETCH) {
212
+ rulesForPhase = cachedRules.fetch;
213
+ }
214
+ else {
215
+ rulesForPhase = cachedRules.preFetch;
216
+ }
217
+ // Step 1: Mandatory Phase
218
+ for (const rule of rulesForPhase.mandatoryRules) {
219
+ const result = await evaluator(rule);
220
+ if (result !== true) {
221
+ return false; // Immediately reject if any mandatory rule fails
222
+ }
223
+ }
224
+ // Step 2-4: Permission Phase
225
+ for (const rule of rulesForPhase.permissionRules) {
226
+ const result = await evaluator(rule);
227
+ if (result === true) {
228
+ return true;
229
+ }
230
+ if (result === false) {
231
+ return false;
232
+ }
233
+ }
234
+ // Default: no hit
235
+ return false;
236
+ }
104
237
  toJSON() {
105
238
  const base = super.toJSON();
106
239
  const routingMap = {};
@@ -1 +1 @@
1
- {"version":3,"file":"RuntimeApiModel.js","sourceRoot":"","sources":["../../../src/modeling/RuntimeApiModel.ts"],"names":[],"mappings":"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","sourcesContent":["import { match, parse, exec, type RouteToken } from '@poppinss/matchit'\nimport { ApiModel, type ApiModelSchema } from './ApiModel.js'\nimport type { DataDomainSchema } from './DataDomain.js'\nimport type { ActionKind } from './actions/index.js'\nimport type { ExposedEntity } from './ExposedEntity.js'\nimport type { Action } from './actions/Action.js'\nimport { SemanticType } from './Semantics.js'\nimport type { DomainEntity } from './DomainEntity.js'\nimport type { DomainProperty } from './DomainProperty.js'\n\n/**\n * Identifies a specific exposed entity and its action kind.\n */\nexport interface RouteLookup {\n exposedEntityKey: string\n actionKind: ActionKind\n}\n\n/**\n * A routing definition mapping a path to an action lookup.\n */\nexport interface RouteDefinition {\n path: string\n lookup: RouteLookup\n}\n\n/**\n * A map of HTTP methods to their route definitions.\n */\nexport type RoutingMap = Record<string, RouteDefinition[]>\n\n/**\n * Schema for an API Model optimized for runtime routing.\n */\nexport interface RuntimeApiModelSchema extends ApiModelSchema {\n routingMap: RoutingMap\n}\n\nexport interface RuntimeResolvedAction {\n entity: ExposedEntity\n action: Action\n params: Record<string, string>\n}\n\n/**\n * An optimized API Model subclass designed for fast runtime lookups.\n * It pre-compiles the RoutingMap into a radix tree for O(log N) or faster endpoint resolution.\n */\nexport class RuntimeApiModel extends ApiModel {\n /**\n * The parsed radix tree for fast routing.\n * Method -> ParsedRoutes\n */\n #routes = new Map<string, RouteToken[][]>()\n\n /**\n * Quick map from matchit parsed route format to our RouteDefinition for returning results\n */\n #definitions = new WeakMap<RouteToken[], RouteDefinition>()\n\n /**\n * Cached references to commonly used entities for fast runtime lookup.\n */\n cachedEntities: {\n user?: DomainEntity\n } = {}\n\n /**\n * Cached references to commonly used properties for fast runtime lookup.\n */\n cachedProperties: {\n username?: DomainProperty\n password?: DomainProperty\n role?: DomainProperty\n } = {}\n\n constructor(schema: RuntimeApiModelSchema, domainSchema: DataDomainSchema) {\n super(schema, domainSchema)\n\n if (schema.routingMap) {\n this.#initializeRouter(schema.routingMap)\n }\n\n this.#cacheEntitiesAndProperties()\n }\n\n #cacheEntitiesAndProperties() {\n if (!this.user || !this.domain) {\n return\n }\n\n const userEntity = this.domain.findEntity(this.user.key, this.user.domain)\n if (!userEntity) {\n return\n }\n\n this.cachedEntities.user = userEntity\n\n for (const prop of userEntity.properties) {\n if (prop.hasSemantic(SemanticType.Username)) {\n this.cachedProperties.username = prop\n }\n if (prop.hasSemantic(SemanticType.Password)) {\n this.cachedProperties.password = prop\n }\n if (prop.hasSemantic(SemanticType.UserRole)) {\n this.cachedProperties.role = prop\n }\n }\n }\n\n #initializeRouter(routingMap: RoutingMap) {\n for (const [method, definitions] of Object.entries(routingMap)) {\n const parsedRoutes = []\n for (const def of definitions) {\n // matchit's parse() transforms a route string into an object representation.\n // It expects `:param` syntax, while our API models use OpenAPI `{param}` syntax.\n const matchitPath = def.path.replace(/\\{([^}]+)\\}/g, ':$1')\n const parsed = parse(matchitPath)\n this.#definitions.set(parsed, def)\n parsedRoutes.push(parsed)\n }\n this.#routes.set(method.toUpperCase(), parsedRoutes)\n }\n }\n\n /**\n * Looks up the corresponding exposed entity and action for a given request.\n *\n * @param method The HTTP method (e.g., 'GET', 'POST').\n * @param path The request path (e.g., '/users/123').\n * @returns An object with the entity, action, and extracted path parameters if a match is found.\n */\n lookupAction(method: string, path: string): RuntimeResolvedAction | undefined {\n const parsedRoutes = this.#routes.get(method.toUpperCase())\n if (!parsedRoutes) {\n return undefined\n }\n\n // `match` returns the matching parsed route (which is an array of segments), or empty array if no match\n const matchedRoute = match(path, parsedRoutes)\n if (!matchedRoute || matchedRoute.length === 0) {\n return undefined\n }\n\n const def = this.#definitions.get(matchedRoute)\n if (!def) {\n return undefined\n }\n\n const params = exec(path, matchedRoute)\n\n const entity = this.exposes.get(def.lookup.exposedEntityKey)\n if (!entity) {\n return undefined\n }\n\n const action = entity.actions.find((a) => a.kind === def.lookup.actionKind)\n if (!action) {\n return undefined\n }\n\n return {\n entity,\n action,\n params,\n }\n }\n\n override toJSON(): RuntimeApiModelSchema {\n const base = super.toJSON() as RuntimeApiModelSchema\n\n const routingMap: RoutingMap = {}\n for (const [method, parsedRoutes] of this.#routes.entries()) {\n routingMap[method] = parsedRoutes.map((pr) => this.#definitions.get(pr) as RouteDefinition)\n }\n\n return {\n ...base,\n routingMap,\n }\n }\n}\n"]}
1
+ {"version":3,"file":"RuntimeApiModel.js","sourceRoot":"","sources":["../../../src/modeling/RuntimeApiModel.ts"],"names":[],"mappings":"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","sourcesContent":["import { match, parse, exec, type RouteToken } from '@poppinss/matchit'\nimport { ApiModel, type ApiModelSchema } from './ApiModel.js'\nimport type { DataDomainSchema } from './DataDomain.js'\nimport type { ActionKind } from './actions/index.js'\nimport type { ExposedEntity } from './ExposedEntity.js'\nimport type { Action } from './actions/Action.js'\nimport { SemanticType } from './Semantics.js'\nimport type { DomainEntity } from './DomainEntity.js'\nimport type { DomainProperty } from './DomainProperty.js'\nimport { AccessRule, AccessRuleExecutionPhase } from './rules/AccessRule.js'\n\n/**\n * Identifies a specific exposed entity and its action kind.\n */\nexport interface RouteLookup {\n exposedEntityKey: string\n actionKind: ActionKind\n}\n\n/**\n * A routing definition mapping a path to an action lookup.\n */\nexport interface RouteDefinition {\n path: string\n lookup: RouteLookup\n}\n\n/**\n * A map of HTTP methods to their route definitions.\n */\nexport type RoutingMap = Record<string, RouteDefinition[]>\n\n/**\n * Schema for an API Model optimized for runtime routing.\n */\nexport interface RuntimeApiModelSchema extends ApiModelSchema {\n routingMap: RoutingMap\n}\n\nexport interface RuntimeResolvedAction {\n entity: ExposedEntity\n action: Action\n params: Record<string, string>\n}\n\nexport type RuleEvaluator = (rule: AccessRule) => Promise<boolean | undefined> | boolean | undefined\n\ninterface PhaseRules {\n permissionRules: AccessRule[]\n mandatoryRules: AccessRule[]\n}\n\ninterface ActionRulesCache {\n preFetch: PhaseRules\n fetch: PhaseRules\n postFetch: PhaseRules\n}\n\n/**\n * An optimized API Model subclass designed for fast runtime lookups.\n * It pre-compiles the RoutingMap into a radix tree for O(log N) or faster endpoint resolution.\n */\nexport class RuntimeApiModel extends ApiModel {\n /**\n * The parsed radix tree for fast routing.\n * Method -> ParsedRoutes\n */\n #routes = new Map<string, RouteToken[][]>()\n\n /**\n * Quick map from matchit parsed route format to our RouteDefinition for returning results\n */\n #definitions = new WeakMap<RouteToken[], RouteDefinition>()\n\n /**\n * Cached references to commonly used entities for fast runtime lookup.\n */\n cachedEntities: {\n user?: DomainEntity\n } = {}\n\n /**\n * Cached references to commonly used properties for fast runtime lookup.\n */\n cachedProperties: {\n username?: DomainProperty\n password?: DomainProperty\n role?: DomainProperty\n } = {}\n\n /**\n * Cached access rules for each action to avoid runtime computation overhead.\n */\n #actionRulesCache = new WeakMap<Action, ActionRulesCache>()\n\n constructor(schema: RuntimeApiModelSchema, domainSchema: DataDomainSchema) {\n super(schema, domainSchema)\n\n if (schema.routingMap) {\n this.#initializeRouter(schema.routingMap)\n }\n\n this.#cacheEntitiesAndProperties()\n this.#precomputeAccessRules()\n }\n\n #precomputeAccessRules(): void {\n for (const entity of this.exposes.values()) {\n for (const action of entity.actions) {\n this.#actionRulesCache.set(action, this.#computeEffectiveRules(action, entity))\n }\n }\n }\n\n #computeEffectiveRules(action: Action, entity: ExposedEntity): ActionRulesCache {\n const hierarchy: AccessRule[][] = []\n\n if (action.accessRule && action.accessRule.length > 0) {\n hierarchy.push(action.accessRule)\n }\n\n let currentEntity: ExposedEntity | undefined = entity\n while (currentEntity) {\n if (currentEntity.accessRule && currentEntity.accessRule.length > 0) {\n hierarchy.push(currentEntity.accessRule)\n }\n currentEntity = currentEntity.parent ? this.exposes.get(currentEntity.parent.key) : undefined\n }\n\n if (this.accessRule && this.accessRule.length > 0) {\n hierarchy.push(this.accessRule)\n }\n\n const result: ActionRulesCache = {\n preFetch: {\n permissionRules: [],\n mandatoryRules: [],\n },\n fetch: {\n permissionRules: [],\n mandatoryRules: [],\n },\n postFetch: {\n permissionRules: [],\n mandatoryRules: [],\n },\n }\n\n const seenTypes = new Set<string>()\n\n for (const rulesLevel of hierarchy) {\n const typesInThisLevel = new Set<string>()\n for (const rule of rulesLevel) {\n const phase = rule.metadata[action.kind as keyof typeof rule.metadata]\n\n // If the rule does not specify an execution phase for this action kind, it is not evaluated\n if (!phase) {\n continue\n }\n\n // Shadowing: If a rule of the same type was defined closer to the action, ignore this one.\n if (seenTypes.has(rule.type)) {\n continue\n }\n typesInThisLevel.add(rule.type)\n\n let bucket\n if (phase === AccessRuleExecutionPhase.POST_FETCH) {\n bucket = result.postFetch\n } else if (phase === AccessRuleExecutionPhase.FETCH) {\n bucket = result.fetch\n } else {\n bucket = result.preFetch\n }\n\n if (rule.mandatory) {\n bucket.mandatoryRules.push(rule)\n } else {\n bucket.permissionRules.push(rule)\n }\n }\n for (const type of typesInThisLevel) {\n seenTypes.add(type)\n }\n }\n\n return result\n }\n\n #cacheEntitiesAndProperties(): void {\n if (!this.user || !this.domain) {\n return\n }\n\n const userEntity = this.domain.findEntity(this.user.key, this.user.domain)\n if (!userEntity) {\n return\n }\n\n this.cachedEntities.user = userEntity\n\n for (const prop of userEntity.properties) {\n if (prop.hasSemantic(SemanticType.Username)) {\n this.cachedProperties.username = prop\n }\n if (prop.hasSemantic(SemanticType.Password)) {\n this.cachedProperties.password = prop\n }\n if (prop.hasSemantic(SemanticType.UserRole)) {\n this.cachedProperties.role = prop\n }\n }\n }\n\n #initializeRouter(routingMap: RoutingMap): void {\n for (const [method, definitions] of Object.entries(routingMap)) {\n const parsedRoutes = []\n for (const def of definitions) {\n // matchit's parse() transforms a route string into an object representation.\n // It expects `:param` syntax, while our API models use OpenAPI `{param}` syntax.\n const matchitPath = def.path.replace(/\\{([^}]+)\\}/g, ':$1')\n const parsed = parse(matchitPath)\n this.#definitions.set(parsed, def)\n parsedRoutes.push(parsed)\n }\n this.#routes.set(method.toUpperCase(), parsedRoutes)\n }\n }\n\n /**\n * Looks up the corresponding exposed entity and action for a given request.\n *\n * @param method The HTTP method (e.g., 'GET', 'POST').\n * @param path The request path (e.g., '/users/123').\n * @returns An object with the entity, action, and extracted path parameters if a match is found.\n */\n lookupAction(method: string, path: string): RuntimeResolvedAction | undefined {\n const parsedRoutes = this.#routes.get(method.toUpperCase())\n if (!parsedRoutes) {\n return undefined\n }\n\n // `match` returns the matching parsed route (which is an array of segments), or empty array if no match\n const matchedRoute = match(path, parsedRoutes)\n if (!matchedRoute || matchedRoute.length === 0) {\n return undefined\n }\n\n const def = this.#definitions.get(matchedRoute)\n if (!def) {\n return undefined\n }\n\n const params = exec(path, matchedRoute)\n\n const entity = this.exposes.get(def.lookup.exposedEntityKey)\n if (!entity) {\n return undefined\n }\n\n const action = entity.actions.find((a) => a.kind === def.lookup.actionKind)\n if (!action) {\n return undefined\n }\n\n return {\n entity,\n action,\n params,\n }\n }\n\n /**\n * Evaluates access rules for a given action and phase.\n *\n * The evaluation process follows two phases per execution phase (PRE_FETCH, FETCH, POST_FETCH):\n * 1. Mandatory Phase: All rules marked as `mandatory: true` across all levels must return true.\n * If any fail, the request is immediately rejected.\n * 2. Permission Phase: Evaluation follows the hierarchy from most specific to most general:\n * Action -> Endpoint (ExposedEntity) -> API Model.\n * If an explicit allow (true) or deny (false) is hit, evaluation stops and returns the result.\n * If no rules match (all return undefined), the request is rejected by default.\n *\n * @param action The resolved action to evaluate.\n * @param evaluator A callback that evaluates a single rule. Should return true (allow),\n * false (deny), or undefined (no hit).\n * @param phase The execution phase to evaluate.\n * @returns A promise that resolves to true if access is granted, false if denied.\n */\n async evaluateAccess(\n action: RuntimeResolvedAction,\n evaluator: RuleEvaluator,\n phase: AccessRuleExecutionPhase\n ): Promise<boolean> {\n let cachedRules = this.#actionRulesCache.get(action.action)\n if (!cachedRules) {\n // Fallback if somehow action is not cached (e.g. dynamically added after initialization or in tests)\n cachedRules = this.#computeEffectiveRules(action.action, action.entity)\n this.#actionRulesCache.set(action.action, cachedRules)\n }\n\n let rulesForPhase\n if (phase === AccessRuleExecutionPhase.POST_FETCH) {\n rulesForPhase = cachedRules.postFetch\n } else if (phase === AccessRuleExecutionPhase.FETCH) {\n rulesForPhase = cachedRules.fetch\n } else {\n rulesForPhase = cachedRules.preFetch\n }\n\n // Step 1: Mandatory Phase\n for (const rule of rulesForPhase.mandatoryRules) {\n const result = await evaluator(rule)\n if (result !== true) {\n return false // Immediately reject if any mandatory rule fails\n }\n }\n\n // Step 2-4: Permission Phase\n for (const rule of rulesForPhase.permissionRules) {\n const result = await evaluator(rule)\n if (result === true) {\n return true\n }\n if (result === false) {\n return false\n }\n }\n\n // Default: no hit\n return false\n }\n\n override toJSON(): RuntimeApiModelSchema {\n const base = super.toJSON() as RuntimeApiModelSchema\n\n const routingMap: RoutingMap = {}\n for (const [method, parsedRoutes] of this.#routes.entries()) {\n routingMap[method] = parsedRoutes.map((pr) => this.#definitions.get(pr) as RouteDefinition)\n }\n\n return {\n ...base,\n routingMap,\n }\n }\n}\n"]}
@@ -21,10 +21,12 @@ export * as DomainVersioning from './DomainVersioning.js';
21
21
  export { DomainFile, type IDomainFile, type DomainFileSchema } from './DomainFile.js';
22
22
  export { ApiFile, type IApiFile, type ApiFileSchema } from './ApiFile.js';
23
23
  export { type DomainValidationSchema } from './validation/rules.js';
24
+ export { DomainValidation } from './DomainValidation.js';
24
25
  export { EntityValidation } from './validation/entity_validation.js';
25
26
  export { PropertyValidation } from './validation/property_validation.js';
26
27
  export { AssociationValidation } from './validation/association_validation.js';
27
28
  export { ApiValidation } from './ApiValidation.js';
28
29
  export { validateApiModelInfo, validateApiModelDependency, validateApiModelSecurity, validateApiModelMetadata, validateExposedEntity, } from './validation/api_model_rules.js';
29
30
  export * as Semantics from './Semantics.js';
31
+ export type { RuleEvaluator, RuntimeResolvedAction, RouteDefinition, RouteLookup, RoutingMap, RuntimeApiModelSchema, } from './RuntimeApiModel.js';
30
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modeling/index.ts"],"names":[],"mappings":"AACA,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/F,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,KAAK,uBAAuB,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC3G,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC7G,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,kBAAkB,MAAM,iCAAiC,CAAA;AACrE,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAC7C,YAAY,EACV,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,eAAe,CAAA;AACtB,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACrF,OAAO,EAAE,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AACzE,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAA;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,iCAAiC,CAAA;AACxC,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modeling/index.ts"],"names":[],"mappings":"AACA,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/F,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,KAAK,uBAAuB,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC3G,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC7G,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,kBAAkB,MAAM,iCAAiC,CAAA;AACrE,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAC7C,YAAY,EACV,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,eAAe,CAAA;AACtB,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACrF,OAAO,EAAE,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AACzE,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAA;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,iCAAiC,CAAA;AACxC,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAC3C,YAAY,EACV,aAAa,EACb,qBAAqB,EACrB,eAAe,EACf,WAAW,EACX,UAAU,EACV,qBAAqB,GACtB,MAAM,sBAAsB,CAAA"}
@@ -18,6 +18,7 @@ export * as DomainSerialization from './DomainSerialization.js';
18
18
  export * as DomainVersioning from './DomainVersioning.js';
19
19
  export { DomainFile } from './DomainFile.js';
20
20
  export { ApiFile } from './ApiFile.js';
21
+ export { DomainValidation } from './DomainValidation.js';
21
22
  export { EntityValidation } from './validation/entity_validation.js';
22
23
  export { PropertyValidation } from './validation/property_validation.js';
23
24
  export { AssociationValidation } from './validation/association_validation.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modeling/index.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAEhC,OAAO,EAAE,QAAQ,EAAyD,MAAM,eAAe,CAAA;AAC/F,OAAO,EAAE,UAAU,EAAyB,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAmD,MAAM,wBAAwB,CAAA;AAC3G,OAAO,EAAE,YAAY,EAAmD,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,WAAW,EAAiD,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAE,eAAe,EAAyD,MAAM,sBAAsB,CAAA;AAC7G,OAAO,EAAE,cAAc,EAA6B,MAAM,qBAAqB,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,kBAAkB,MAAM,iCAAiC,CAAA;AACrE,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAW7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,UAAU,EAA2C,MAAM,iBAAiB,CAAA;AACrF,OAAO,EAAE,OAAO,EAAqC,MAAM,cAAc,CAAA;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAA;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,iCAAiC,CAAA;AACxC,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA","sourcesContent":["// These interfaces work both in Node and Browser. Do not add any runtime specific imports.\nexport * from './actions/index.js'\nexport * from './ai/index.js'\nexport * from './amf/index.js'\nexport * from './rules/index.js'\nexport type * from './types.js'\nexport { ApiModel, type ApiModelSchema, type ApiContact, type ApiLicense } from './ApiModel.js'\nexport { DataDomain, type DataDomainSchema } from './DataDomain.js'\nexport { DomainAssociation, type DomainAssociationSchema, type OnDeleteRule } from './DomainAssociation.js'\nexport { DomainEntity, type DomainEntitySchema, type EntityOrderedItem } from './DomainEntity.js'\nexport { DomainModel, type DomainModelSchema, type ModelOrderedItem } from './DomainModel.js'\nexport { DomainNamespace, type DomainNamespaceSchema, type NamespaceOrderedItem } from './DomainNamespace.js'\nexport { DomainProperty, type DomainPropertySchema } from './DomainProperty.js'\nexport { ExposedEntity } from './ExposedEntity.js'\nexport * as ApiModelValidation from './validation/api_model_rules.js'\nexport * as DataFormat from './DataFormat.js'\nexport type {\n PropertyBinding,\n PropertyProtobufBindings,\n PropertyWebBindings,\n AssociationBinding,\n AssociationBindings,\n AssociationWebBindings,\n PropertyBindings,\n} from './Bindings.js'\nexport type * from './types.js'\nexport { DomainImpactAnalysis } from './DomainImpactAnalysis.js'\nexport * as DomainSerialization from './DomainSerialization.js'\nexport * as DomainVersioning from './DomainVersioning.js'\nexport { DomainFile, type IDomainFile, type DomainFileSchema } from './DomainFile.js'\nexport { ApiFile, type IApiFile, type ApiFileSchema } from './ApiFile.js'\nexport { type DomainValidationSchema } from './validation/rules.js'\nexport { EntityValidation } from './validation/entity_validation.js'\nexport { PropertyValidation } from './validation/property_validation.js'\nexport { AssociationValidation } from './validation/association_validation.js'\nexport { ApiValidation } from './ApiValidation.js'\nexport {\n validateApiModelInfo,\n validateApiModelDependency,\n validateApiModelSecurity,\n validateApiModelMetadata,\n validateExposedEntity,\n} from './validation/api_model_rules.js'\nexport * as Semantics from './Semantics.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modeling/index.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAEhC,OAAO,EAAE,QAAQ,EAAyD,MAAM,eAAe,CAAA;AAC/F,OAAO,EAAE,UAAU,EAAyB,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAmD,MAAM,wBAAwB,CAAA;AAC3G,OAAO,EAAE,YAAY,EAAmD,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,WAAW,EAAiD,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAE,eAAe,EAAyD,MAAM,sBAAsB,CAAA;AAC7G,OAAO,EAAE,cAAc,EAA6B,MAAM,qBAAqB,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,kBAAkB,MAAM,iCAAiC,CAAA;AACrE,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAW7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,UAAU,EAA2C,MAAM,iBAAiB,CAAA;AACrF,OAAO,EAAE,OAAO,EAAqC,MAAM,cAAc,CAAA;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAA;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,iCAAiC,CAAA;AACxC,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA","sourcesContent":["// These interfaces work both in Node and Browser. Do not add any runtime specific imports.\nexport * from './actions/index.js'\nexport * from './ai/index.js'\nexport * from './amf/index.js'\nexport * from './rules/index.js'\nexport type * from './types.js'\nexport { ApiModel, type ApiModelSchema, type ApiContact, type ApiLicense } from './ApiModel.js'\nexport { DataDomain, type DataDomainSchema } from './DataDomain.js'\nexport { DomainAssociation, type DomainAssociationSchema, type OnDeleteRule } from './DomainAssociation.js'\nexport { DomainEntity, type DomainEntitySchema, type EntityOrderedItem } from './DomainEntity.js'\nexport { DomainModel, type DomainModelSchema, type ModelOrderedItem } from './DomainModel.js'\nexport { DomainNamespace, type DomainNamespaceSchema, type NamespaceOrderedItem } from './DomainNamespace.js'\nexport { DomainProperty, type DomainPropertySchema } from './DomainProperty.js'\nexport { ExposedEntity } from './ExposedEntity.js'\nexport * as ApiModelValidation from './validation/api_model_rules.js'\nexport * as DataFormat from './DataFormat.js'\nexport type {\n PropertyBinding,\n PropertyProtobufBindings,\n PropertyWebBindings,\n AssociationBinding,\n AssociationBindings,\n AssociationWebBindings,\n PropertyBindings,\n} from './Bindings.js'\nexport type * from './types.js'\nexport { DomainImpactAnalysis } from './DomainImpactAnalysis.js'\nexport * as DomainSerialization from './DomainSerialization.js'\nexport * as DomainVersioning from './DomainVersioning.js'\nexport { DomainFile, type IDomainFile, type DomainFileSchema } from './DomainFile.js'\nexport { ApiFile, type IApiFile, type ApiFileSchema } from './ApiFile.js'\nexport { type DomainValidationSchema } from './validation/rules.js'\nexport { DomainValidation } from './DomainValidation.js'\nexport { EntityValidation } from './validation/entity_validation.js'\nexport { PropertyValidation } from './validation/property_validation.js'\nexport { AssociationValidation } from './validation/association_validation.js'\nexport { ApiValidation } from './ApiValidation.js'\nexport {\n validateApiModelInfo,\n validateApiModelDependency,\n validateApiModelSecurity,\n validateApiModelMetadata,\n validateExposedEntity,\n} from './validation/api_model_rules.js'\nexport * as Semantics from './Semantics.js'\nexport type {\n RuleEvaluator,\n RuntimeResolvedAction,\n RouteDefinition,\n RouteLookup,\n RoutingMap,\n RuntimeApiModelSchema,\n} from './RuntimeApiModel.js'\n"]}
@@ -1,20 +1,59 @@
1
1
  import type { Action } from '../actions/Action.js';
2
2
  import type { ApiModel } from '../ApiModel.js';
3
3
  import type { ExposedEntity } from '../ExposedEntity.js';
4
+ export declare enum AccessRuleExecutionPhase {
5
+ /**
6
+ * The action that happens before the fetch.
7
+ * For example MatchUserRole and MatchUserProperty are executed in this phase.
8
+ */
9
+ PRE_FETCH = "pre-fetch",
10
+ /**
11
+ * The action that happens during the fetch, for example injecting clauses into a query.
12
+ */
13
+ FETCH = "fetch",
14
+ /**
15
+ * The action that happens after the resource is fetched from the database.
16
+ */
17
+ POST_FETCH = "post-fetch"
18
+ }
4
19
  export interface AccessRuleSchema {
5
20
  /**
6
21
  * The unique identifier for the access rule.
7
22
  * This is used to reference the rule in the API configuration.
8
23
  */
9
24
  type: string;
25
+ /**
26
+ * Whether this rule is mandatory. If true, the rule must be satisfied for the action to be allowed,
27
+ * regardless of other rules. If a mandatory rule is not satisfied, the action is denied.
28
+ */
29
+ mandatory?: boolean;
30
+ }
31
+ /**
32
+ * The definition of when exactly the access rule should be evaluated.
33
+ * If the action is not specified, the rule is not evaluated for that action.
34
+ */
35
+ export interface AccessRuleExecutionMetadata {
36
+ readonly list?: AccessRuleExecutionPhase;
37
+ readonly create?: AccessRuleExecutionPhase;
38
+ readonly search?: AccessRuleExecutionPhase;
39
+ readonly read?: AccessRuleExecutionPhase;
40
+ readonly update?: AccessRuleExecutionPhase;
41
+ readonly delete?: AccessRuleExecutionPhase;
10
42
  }
11
43
  /**
12
44
  * Base class for all access rules.
13
45
  */
14
46
  export declare class AccessRule extends EventTarget implements AccessRuleSchema {
47
+ #private;
15
48
  readonly type: string;
16
49
  readonly parent: ExposedEntity | ApiModel | Action;
17
- constructor(parent: ExposedEntity | ApiModel | Action, state?: Partial<AccessRuleSchema>);
50
+ /**
51
+ * Whether this rule is mandatory. If true, the rule must be satisfied for the action to be allowed,
52
+ * regardless of other rules. If a mandatory rule is not satisfied, the action is denied.
53
+ */
54
+ mandatory: boolean;
55
+ get metadata(): AccessRuleExecutionMetadata;
56
+ constructor(parent: ExposedEntity | ApiModel | Action, metadata: AccessRuleExecutionMetadata, state?: Partial<AccessRuleSchema>);
18
57
  toJSON(): AccessRuleSchema;
19
58
  notifyChange(): void;
20
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AccessRule.d.ts","sourceRoot":"","sources":["../../../../src/modeling/rules/AccessRule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,WAAY,YAAW,gBAAgB;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAA;gBAEtC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,MAAM,EAAE,KAAK,GAAE,OAAO,CAAC,gBAAgB,CAAM;IAM5F,MAAM,IAAI,gBAAgB;IAM1B,YAAY;CAIb"}
1
+ {"version":3,"file":"AccessRule.d.ts","sourceRoot":"","sources":["../../../../src/modeling/rules/AccessRule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,oBAAY,wBAAwB;IAClC;;;OAGG;IACH,SAAS,cAAc;IACvB;;OAEG;IACH,KAAK,UAAU;IACf;;OAEG;IACH,UAAU,eAAe;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;IAEZ;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,wBAAwB,CAAA;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,wBAAwB,CAAA;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAC3C;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,WAAY,YAAW,gBAAgB;;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAA;IAElD;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAA;IAYlB,IAAI,QAAQ,IAAI,2BAA2B,CAK1C;gBAGC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,MAAM,EACzC,QAAQ,EAAE,2BAA2B,EACrC,KAAK,GAAE,OAAO,CAAC,gBAAgB,CAAM;IASvC,MAAM,IAAI,gBAAgB;IAU1B,YAAY;CAIb"}
@@ -1,18 +1,60 @@
1
+ export var AccessRuleExecutionPhase;
2
+ (function (AccessRuleExecutionPhase) {
3
+ /**
4
+ * The action that happens before the fetch.
5
+ * For example MatchUserRole and MatchUserProperty are executed in this phase.
6
+ */
7
+ AccessRuleExecutionPhase["PRE_FETCH"] = "pre-fetch";
8
+ /**
9
+ * The action that happens during the fetch, for example injecting clauses into a query.
10
+ */
11
+ AccessRuleExecutionPhase["FETCH"] = "fetch";
12
+ /**
13
+ * The action that happens after the resource is fetched from the database.
14
+ */
15
+ AccessRuleExecutionPhase["POST_FETCH"] = "post-fetch";
16
+ })(AccessRuleExecutionPhase || (AccessRuleExecutionPhase = {}));
1
17
  /**
2
18
  * Base class for all access rules.
3
19
  */
4
20
  export class AccessRule extends EventTarget {
5
21
  type;
6
22
  parent;
7
- constructor(parent, state = {}) {
23
+ /**
24
+ * Whether this rule is mandatory. If true, the rule must be satisfied for the action to be allowed,
25
+ * regardless of other rules. If a mandatory rule is not satisfied, the action is denied.
26
+ */
27
+ mandatory;
28
+ /**
29
+ * The execution phase dictates when the rule is evaluated during the request lifecycle.
30
+ * - 'pre-fetch': Evaluated before the underlying resource is fetched from the database.
31
+ * - 'post-fetch': Evaluated after the underlying resource is fetched from the database.
32
+ *
33
+ * In some situations (like List and MatchResourceOwner) this is executed when a query is
34
+ * build to inject additional clauses for example.
35
+ */
36
+ #metadata;
37
+ get metadata() {
38
+ if (!this.#metadata) {
39
+ throw new Error('Metadata not set for access rule ' + this.type);
40
+ }
41
+ return this.#metadata;
42
+ }
43
+ constructor(parent, metadata, state = {}) {
8
44
  super();
9
45
  this.parent = parent;
10
46
  this.type = state.type ?? '';
47
+ this.mandatory = state.mandatory ?? false;
48
+ this.#metadata = metadata;
11
49
  }
12
50
  toJSON() {
13
- return {
51
+ const result = {
14
52
  type: this.type,
15
53
  };
54
+ if (this.mandatory) {
55
+ result.mandatory = true;
56
+ }
57
+ return result;
16
58
  }
17
59
  notifyChange() {
18
60
  this.dispatchEvent(new Event('change'));
@@ -1 +1 @@
1
- {"version":3,"file":"AccessRule.js","sourceRoot":"","sources":["../../../../src/modeling/rules/AccessRule.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,WAAW;IAChC,IAAI,CAAQ;IACZ,MAAM,CAAmC;IAElD,YAAY,MAAyC,EAAE,QAAmC,EAAE;QAC1F,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAA;IAC9B,CAAC;IAED,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAA;IACH,CAAC;IAED,YAAY;QACV,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;QACvC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;IAC5B,CAAC;CACF","sourcesContent":["import type { Action } from '../actions/Action.js'\nimport type { ApiModel } from '../ApiModel.js'\nimport type { ExposedEntity } from '../ExposedEntity.js'\n\nexport interface AccessRuleSchema {\n /**\n * The unique identifier for the access rule.\n * This is used to reference the rule in the API configuration.\n */\n type: string\n}\n\n/**\n * Base class for all access rules.\n */\nexport class AccessRule extends EventTarget implements AccessRuleSchema {\n readonly type: string\n readonly parent: ExposedEntity | ApiModel | Action\n\n constructor(parent: ExposedEntity | ApiModel | Action, state: Partial<AccessRuleSchema> = {}) {\n super()\n this.parent = parent\n this.type = state.type ?? ''\n }\n\n toJSON(): AccessRuleSchema {\n return {\n type: this.type,\n }\n }\n\n notifyChange() {\n this.dispatchEvent(new Event('change'))\n this.parent.notifyChange()\n }\n}\n"]}
1
+ {"version":3,"file":"AccessRule.js","sourceRoot":"","sources":["../../../../src/modeling/rules/AccessRule.ts"],"names":[],"mappings":"AAIA,MAAM,CAAN,IAAY,wBAcX;AAdD,WAAY,wBAAwB;IAClC;;;OAGG;IACH,mDAAuB,CAAA;IACvB;;OAEG;IACH,2CAAe,CAAA;IACf;;OAEG;IACH,qDAAyB,CAAA;AAC3B,CAAC,EAdW,wBAAwB,KAAxB,wBAAwB,QAcnC;AA6BD;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,WAAW;IAChC,IAAI,CAAQ;IACZ,MAAM,CAAmC;IAElD;;;OAGG;IACH,SAAS,CAAS;IAElB;;;;;;;OAOG;IACH,SAAS,CAA6B;IAEtC,IAAI,QAAQ;QACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,mCAAmC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;QAClE,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAED,YACE,MAAyC,EACzC,QAAqC,EACrC,QAAmC,EAAE;QAErC,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAA;QAC5B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAA;QACzC,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;IAC3B,CAAC;IAED,MAAM;QACJ,MAAM,MAAM,GAAqB;YAC/B,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAA;QACD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,CAAC,SAAS,GAAG,IAAI,CAAA;QACzB,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED,YAAY;QACV,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;QACvC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;IAC5B,CAAC;CACF","sourcesContent":["import type { Action } from '../actions/Action.js'\nimport type { ApiModel } from '../ApiModel.js'\nimport type { ExposedEntity } from '../ExposedEntity.js'\n\nexport enum AccessRuleExecutionPhase {\n /**\n * The action that happens before the fetch.\n * For example MatchUserRole and MatchUserProperty are executed in this phase.\n */\n PRE_FETCH = 'pre-fetch',\n /**\n * The action that happens during the fetch, for example injecting clauses into a query.\n */\n FETCH = 'fetch',\n /**\n * The action that happens after the resource is fetched from the database.\n */\n POST_FETCH = 'post-fetch',\n}\n\nexport interface AccessRuleSchema {\n /**\n * The unique identifier for the access rule.\n * This is used to reference the rule in the API configuration.\n */\n type: string\n\n /**\n * Whether this rule is mandatory. If true, the rule must be satisfied for the action to be allowed,\n * regardless of other rules. If a mandatory rule is not satisfied, the action is denied.\n */\n mandatory?: boolean\n}\n\n/**\n * The definition of when exactly the access rule should be evaluated.\n * If the action is not specified, the rule is not evaluated for that action.\n */\nexport interface AccessRuleExecutionMetadata {\n readonly list?: AccessRuleExecutionPhase\n readonly create?: AccessRuleExecutionPhase\n readonly search?: AccessRuleExecutionPhase\n readonly read?: AccessRuleExecutionPhase\n readonly update?: AccessRuleExecutionPhase\n readonly delete?: AccessRuleExecutionPhase\n}\n\n/**\n * Base class for all access rules.\n */\nexport class AccessRule extends EventTarget implements AccessRuleSchema {\n readonly type: string\n readonly parent: ExposedEntity | ApiModel | Action\n\n /**\n * Whether this rule is mandatory. If true, the rule must be satisfied for the action to be allowed,\n * regardless of other rules. If a mandatory rule is not satisfied, the action is denied.\n */\n mandatory: boolean\n\n /**\n * The execution phase dictates when the rule is evaluated during the request lifecycle.\n * - 'pre-fetch': Evaluated before the underlying resource is fetched from the database.\n * - 'post-fetch': Evaluated after the underlying resource is fetched from the database.\n *\n * In some situations (like List and MatchResourceOwner) this is executed when a query is\n * build to inject additional clauses for example.\n */\n #metadata: AccessRuleExecutionMetadata\n\n get metadata(): AccessRuleExecutionMetadata {\n if (!this.#metadata) {\n throw new Error('Metadata not set for access rule ' + this.type)\n }\n return this.#metadata\n }\n\n constructor(\n parent: ExposedEntity | ApiModel | Action,\n metadata: AccessRuleExecutionMetadata,\n state: Partial<AccessRuleSchema> = {}\n ) {\n super()\n this.parent = parent\n this.type = state.type ?? ''\n this.mandatory = state.mandatory ?? false\n this.#metadata = metadata\n }\n\n toJSON(): AccessRuleSchema {\n const result: AccessRuleSchema = {\n type: this.type,\n }\n if (this.mandatory) {\n result.mandatory = true\n }\n return result\n }\n\n notifyChange() {\n this.dispatchEvent(new Event('change'))\n this.parent.notifyChange()\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AllowAuthenticated.d.ts","sourceRoot":"","sources":["../../../../src/modeling/rules/AllowAuthenticated.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEnE;;;;GAIG;AACH,MAAM,WAAW,kCAAmC,SAAQ,gBAAgB;IAC1E,IAAI,EAAE,oBAAoB,CAAA;CAC3B;AAED;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,UAAW,YAAW,kCAAkC;IACxG,SAAkB,IAAI,EAAE,oBAAoB,CAAA;gBAEhC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,MAAM,EAAE,KAAK,GAAE,OAAO,CAAC,kCAAkC,CAAM;CAI/G"}
1
+ {"version":3,"file":"AllowAuthenticated.d.ts","sourceRoot":"","sources":["../../../../src/modeling/rules/AllowAuthenticated.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,UAAU,EAA4B,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAE7F;;;;GAIG;AACH,MAAM,WAAW,kCAAmC,SAAQ,gBAAgB;IAC1E,IAAI,EAAE,oBAAoB,CAAA;CAC3B;AAED;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,UAAW,YAAW,kCAAkC;IACxG,SAAkB,IAAI,EAAE,oBAAoB,CAAA;gBAEhC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,MAAM,EAAE,KAAK,GAAE,OAAO,CAAC,kCAAkC,CAAM;CAe/G"}
@@ -1,4 +1,4 @@
1
- import { AccessRule } from './AccessRule.js';
1
+ import { AccessRule, AccessRuleExecutionPhase } from './AccessRule.js';
2
2
  /**
3
3
  * The action is allowed for any authenticated user.
4
4
  * This rule does not impose any additional restrictions based on user properties or resource ownership.
@@ -7,7 +7,14 @@ import { AccessRule } from './AccessRule.js';
7
7
  export class AllowAuthenticatedAccessRule extends AccessRule {
8
8
  type;
9
9
  constructor(parent, state = {}) {
10
- super(parent, state);
10
+ super(parent, {
11
+ list: AccessRuleExecutionPhase.PRE_FETCH,
12
+ create: AccessRuleExecutionPhase.PRE_FETCH,
13
+ search: AccessRuleExecutionPhase.PRE_FETCH,
14
+ read: AccessRuleExecutionPhase.PRE_FETCH,
15
+ update: AccessRuleExecutionPhase.PRE_FETCH,
16
+ delete: AccessRuleExecutionPhase.PRE_FETCH,
17
+ }, state);
11
18
  this.type = 'allowAuthenticated';
12
19
  }
13
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AllowAuthenticated.js","sourceRoot":"","sources":["../../../../src/modeling/rules/AllowAuthenticated.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAyB,MAAM,iBAAiB,CAAA;AAWnE;;;;GAIG;AACH,MAAM,OAAO,4BAA6B,SAAQ,UAAU;IACxC,IAAI,CAAsB;IAE5C,YAAY,MAAyC,EAAE,QAAqD,EAAE;QAC5G,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACpB,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;IAClC,CAAC;CACF","sourcesContent":["import type { Action } from '../actions/Action.js'\nimport type { ApiModel } from '../ApiModel.js'\nimport type { ExposedEntity } from '../ExposedEntity.js'\nimport { AccessRule, type AccessRuleSchema } from './AccessRule.js'\n\n/**\n * The action is allowed for any authenticated user.\n * This rule does not impose any additional restrictions based on user properties or resource ownership.\n * It is used for resources that should be accessible to all logged-in users.\n */\nexport interface AllowAuthenticatedAccessRuleSchema extends AccessRuleSchema {\n type: 'allowAuthenticated'\n}\n\n/**\n * The action is allowed for any authenticated user.\n * This rule does not impose any additional restrictions based on user properties or resource ownership.\n * It is used for resources that should be accessible to all logged-in users.\n */\nexport class AllowAuthenticatedAccessRule extends AccessRule implements AllowAuthenticatedAccessRuleSchema {\n override readonly type: 'allowAuthenticated'\n\n constructor(parent: ExposedEntity | ApiModel | Action, state: Partial<AllowAuthenticatedAccessRuleSchema> = {}) {\n super(parent, state)\n this.type = 'allowAuthenticated'\n }\n}\n"]}
1
+ {"version":3,"file":"AllowAuthenticated.js","sourceRoot":"","sources":["../../../../src/modeling/rules/AllowAuthenticated.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAyB,MAAM,iBAAiB,CAAA;AAW7F;;;;GAIG;AACH,MAAM,OAAO,4BAA6B,SAAQ,UAAU;IACxC,IAAI,CAAsB;IAE5C,YAAY,MAAyC,EAAE,QAAqD,EAAE;QAC5G,KAAK,CACH,MAAM,EACN;YACE,IAAI,EAAE,wBAAwB,CAAC,SAAS;YACxC,MAAM,EAAE,wBAAwB,CAAC,SAAS;YAC1C,MAAM,EAAE,wBAAwB,CAAC,SAAS;YAC1C,IAAI,EAAE,wBAAwB,CAAC,SAAS;YACxC,MAAM,EAAE,wBAAwB,CAAC,SAAS;YAC1C,MAAM,EAAE,wBAAwB,CAAC,SAAS;SAC3C,EACD,KAAK,CACN,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;IAClC,CAAC;CACF","sourcesContent":["import type { Action } from '../actions/Action.js'\nimport type { ApiModel } from '../ApiModel.js'\nimport type { ExposedEntity } from '../ExposedEntity.js'\nimport { AccessRule, AccessRuleExecutionPhase, type AccessRuleSchema } from './AccessRule.js'\n\n/**\n * The action is allowed for any authenticated user.\n * This rule does not impose any additional restrictions based on user properties or resource ownership.\n * It is used for resources that should be accessible to all logged-in users.\n */\nexport interface AllowAuthenticatedAccessRuleSchema extends AccessRuleSchema {\n type: 'allowAuthenticated'\n}\n\n/**\n * The action is allowed for any authenticated user.\n * This rule does not impose any additional restrictions based on user properties or resource ownership.\n * It is used for resources that should be accessible to all logged-in users.\n */\nexport class AllowAuthenticatedAccessRule extends AccessRule implements AllowAuthenticatedAccessRuleSchema {\n override readonly type: 'allowAuthenticated'\n\n constructor(parent: ExposedEntity | ApiModel | Action, state: Partial<AllowAuthenticatedAccessRuleSchema> = {}) {\n super(\n parent,\n {\n list: AccessRuleExecutionPhase.PRE_FETCH,\n create: AccessRuleExecutionPhase.PRE_FETCH,\n search: AccessRuleExecutionPhase.PRE_FETCH,\n read: AccessRuleExecutionPhase.PRE_FETCH,\n update: AccessRuleExecutionPhase.PRE_FETCH,\n delete: AccessRuleExecutionPhase.PRE_FETCH,\n },\n state\n )\n this.type = 'allowAuthenticated'\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AllowPublic.d.ts","sourceRoot":"","sources":["../../../../src/modeling/rules/AllowPublic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEnE;;;;GAIG;AACH,MAAM,WAAW,2BAA4B,SAAQ,gBAAgB;IACnE,IAAI,EAAE,aAAa,CAAA;CACpB;AAED;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,UAAW,YAAW,2BAA2B;IAC1F,SAAkB,IAAI,EAAE,aAAa,CAAA;gBAEzB,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,MAAM,EAAE,KAAK,GAAE,OAAO,CAAC,2BAA2B,CAAM;CAIxG"}
1
+ {"version":3,"file":"AllowPublic.d.ts","sourceRoot":"","sources":["../../../../src/modeling/rules/AllowPublic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,UAAU,EAA4B,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAE7F;;;;GAIG;AACH,MAAM,WAAW,2BAA4B,SAAQ,gBAAgB;IACnE,IAAI,EAAE,aAAa,CAAA;CACpB;AAED;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,UAAW,YAAW,2BAA2B;IAC1F,SAAkB,IAAI,EAAE,aAAa,CAAA;gBAEzB,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,MAAM,EAAE,KAAK,GAAE,OAAO,CAAC,2BAA2B,CAAM;CAexG"}
@@ -1,4 +1,4 @@
1
- import { AccessRule } from './AccessRule.js';
1
+ import { AccessRule, AccessRuleExecutionPhase } from './AccessRule.js';
2
2
  /**
3
3
  * The action is allowed for all users, including unauthenticated ones.
4
4
  * This is typically used for public APIs or resources that do not require authentication.
@@ -7,7 +7,14 @@ import { AccessRule } from './AccessRule.js';
7
7
  export class AllowPublicAccessRule extends AccessRule {
8
8
  type;
9
9
  constructor(parent, state = {}) {
10
- super(parent, state);
10
+ super(parent, {
11
+ list: AccessRuleExecutionPhase.PRE_FETCH,
12
+ create: AccessRuleExecutionPhase.PRE_FETCH,
13
+ search: AccessRuleExecutionPhase.PRE_FETCH,
14
+ read: AccessRuleExecutionPhase.PRE_FETCH,
15
+ update: AccessRuleExecutionPhase.PRE_FETCH,
16
+ delete: AccessRuleExecutionPhase.PRE_FETCH,
17
+ }, state);
11
18
  this.type = 'allowPublic';
12
19
  }
13
20
  }