@twin.org/rights-management-plugins 0.0.3-next.29 → 0.0.3-next.30
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/dist/es/index.js +5 -2
- package/dist/es/index.js.map +1 -1
- package/dist/es/models/IAutomationPolicyExecutionActionConfig.js +4 -0
- package/dist/es/models/IAutomationPolicyExecutionActionConfig.js.map +1 -0
- package/dist/es/models/IAutomationPolicyExecutionActionConstructorOptions.js +2 -0
- package/dist/es/models/IAutomationPolicyExecutionActionConstructorOptions.js.map +1 -0
- package/dist/es/policyArbiters/defaultPolicyArbiter.js +232 -86
- package/dist/es/policyArbiters/defaultPolicyArbiter.js.map +1 -1
- package/dist/es/policyExecutionActions/automationPolicyExecutionAction.js +76 -0
- package/dist/es/policyExecutionActions/automationPolicyExecutionAction.js.map +1 -0
- package/dist/es/policyExecutionActions/loggingPolicyExecutionAction.js.map +1 -1
- package/dist/types/index.d.ts +5 -2
- package/dist/types/models/IAutomationPolicyExecutionActionConfig.d.ts +9 -0
- package/dist/types/models/IAutomationPolicyExecutionActionConstructorOptions.d.ts +15 -0
- package/dist/types/policyExecutionActions/automationPolicyExecutionAction.d.ts +49 -0
- package/dist/types/policyExecutionActions/loggingPolicyExecutionAction.d.ts +1 -1
- package/docs/changelog.md +77 -48
- package/docs/examples.md +0 -29
- package/docs/reference/classes/AutomationPolicyExecutionAction.md +143 -0
- package/docs/reference/classes/LoggingPolicyExecutionAction.md +1 -1
- package/docs/reference/index.md +3 -0
- package/docs/reference/interfaces/IAutomationPolicyExecutionActionConfig.md +11 -0
- package/docs/reference/interfaces/IAutomationPolicyExecutionActionConstructorOptions.md +25 -0
- package/locales/en.json +1 -0
- package/package.json +3 -2
package/dist/es/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// Copyright 2025 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
-
export * from "./models/
|
|
3
|
+
export * from "./models/IAutomationPolicyExecutionActionConfig.js";
|
|
4
|
+
export * from "./models/IAutomationPolicyExecutionActionConstructorOptions.js";
|
|
4
5
|
export * from "./models/IDefaultPolicyArbiterConfig.js";
|
|
6
|
+
export * from "./models/IDefaultPolicyArbiterConstructorOptions.js";
|
|
5
7
|
export * from "./models/IDefaultPolicyEnforcementProcessorConstructorOptions.js";
|
|
6
8
|
export * from "./models/IIdentityPolicyInformationSourceConstructorOptions.js";
|
|
7
9
|
export * from "./models/ILoggingPolicyExecutionActionConfig.js";
|
|
@@ -18,10 +20,11 @@ export * from "./policyArbiters/defaultPolicyArbiter.js";
|
|
|
18
20
|
export * from "./policyArbiters/passThroughPolicyArbiter.js";
|
|
19
21
|
export * from "./policyEnforcementProcessor/defaultPolicyEnforcementProcessor.js";
|
|
20
22
|
export * from "./policyEnforcementProcessor/passThroughPolicyEnforcementProcessor.js";
|
|
23
|
+
export * from "./policyExecutionActions/automationPolicyExecutionAction.js";
|
|
21
24
|
export * from "./policyExecutionActions/loggingPolicyExecutionAction.js";
|
|
22
|
-
export * from "./policyObligationEnforcers/passThroughPolicyObligationEnforcer.js";
|
|
23
25
|
export * from "./policyInformationSources/identityPolicyInformationSource.js";
|
|
24
26
|
export * from "./policyInformationSources/staticPolicyInformationSource.js";
|
|
25
27
|
export * from "./policyNegotiators/passThroughPolicyNegotiator.js";
|
|
28
|
+
export * from "./policyObligationEnforcers/passThroughPolicyObligationEnforcer.js";
|
|
26
29
|
export * from "./policyRequesters/passThroughPolicyRequester.js";
|
|
27
30
|
//# sourceMappingURL=index.js.map
|
package/dist/es/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,oDAAoD,CAAC;AACnE,cAAc,gEAAgE,CAAC;AAC/E,cAAc,yCAAyC,CAAC;AACxD,cAAc,qDAAqD,CAAC;AACpE,cAAc,kEAAkE,CAAC;AACjF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,iDAAiD,CAAC;AAChE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,yDAAyD,CAAC;AACxE,cAAc,sEAAsE,CAAC;AACrF,cAAc,4DAA4D,CAAC;AAC3E,cAAc,oEAAoE,CAAC;AACnF,cAAc,2DAA2D,CAAC;AAC1E,cAAc,4CAA4C,CAAC;AAC3D,cAAc,kDAAkD,CAAC;AACjE,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0CAA0C,CAAC;AACzD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,mEAAmE,CAAC;AAClF,cAAc,uEAAuE,CAAC;AACtF,cAAc,6DAA6D,CAAC;AAC5E,cAAc,0DAA0D,CAAC;AACzE,cAAc,+DAA+D,CAAC;AAC9E,cAAc,6DAA6D,CAAC;AAC5E,cAAc,oDAAoD,CAAC;AACnE,cAAc,oEAAoE,CAAC;AACnF,cAAc,kDAAkD,CAAC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./models/IAutomationPolicyExecutionActionConfig.js\";\nexport * from \"./models/IAutomationPolicyExecutionActionConstructorOptions.js\";\nexport * from \"./models/IDefaultPolicyArbiterConfig.js\";\nexport * from \"./models/IDefaultPolicyArbiterConstructorOptions.js\";\nexport * from \"./models/IDefaultPolicyEnforcementProcessorConstructorOptions.js\";\nexport * from \"./models/IIdentityPolicyInformationSourceConstructorOptions.js\";\nexport * from \"./models/ILoggingPolicyExecutionActionConfig.js\";\nexport * from \"./models/ILoggingPolicyExecutionActionConstructorOptions.js\";\nexport * from \"./models/IPassThroughPolicyArbiterConstructorOptions.js\";\nexport * from \"./models/IPassThroughPolicyEnforcementProcessorConstructorOptions.js\";\nexport * from \"./models/IPassThroughPolicyNegotiatorConstructorOptions.js\";\nexport * from \"./models/IPassThroughPolicyObligationEnforcerConstructorOptions.js\";\nexport * from \"./models/IPassThroughPolicyRequesterConstructorOptions.js\";\nexport * from \"./models/IStaticPolicyInformationSource.js\";\nexport * from \"./models/IStaticPolicyInformationSourceConfig.js\";\nexport * from \"./models/IStaticPolicyInformationSourceConstructorOptions.js\";\nexport * from \"./policyArbiters/defaultPolicyArbiter.js\";\nexport * from \"./policyArbiters/passThroughPolicyArbiter.js\";\nexport * from \"./policyEnforcementProcessor/defaultPolicyEnforcementProcessor.js\";\nexport * from \"./policyEnforcementProcessor/passThroughPolicyEnforcementProcessor.js\";\nexport * from \"./policyExecutionActions/automationPolicyExecutionAction.js\";\nexport * from \"./policyExecutionActions/loggingPolicyExecutionAction.js\";\nexport * from \"./policyInformationSources/identityPolicyInformationSource.js\";\nexport * from \"./policyInformationSources/staticPolicyInformationSource.js\";\nexport * from \"./policyNegotiators/passThroughPolicyNegotiator.js\";\nexport * from \"./policyObligationEnforcers/passThroughPolicyObligationEnforcer.js\";\nexport * from \"./policyRequesters/passThroughPolicyRequester.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IAutomationPolicyExecutionActionConfig.js","sourceRoot":"","sources":["../../../src/models/IAutomationPolicyExecutionActionConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Options for the Automation Policy Execution Action Component.\n */\nexport interface IAutomationPolicyExecutionActionConfig {\n\t/**\n\t * The policy decision stages to trigger the automation actions, if undefined defaults to \"inform\".\n\t */\n\ttriggerActions?: string[];\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IAutomationPolicyExecutionActionConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IAutomationPolicyExecutionActionConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IAutomationPolicyExecutionActionConfig } from \"./IAutomationPolicyExecutionActionConfig.js\";\n\n/**\n * Options for the Automation Policy Execution Action.\n */\nexport interface IAutomationPolicyExecutionActionConstructorOptions {\n\t/**\n\t * The automation component for executing automation policies.\n\t * @default automation\n\t */\n\tautomationComponentType?: string;\n\n\t/**\n\t * The configuration for the automation policy execution.\n\t */\n\tconfig?: IAutomationPolicyExecutionActionConfig;\n}\n"]}
|
|
@@ -24,20 +24,31 @@ export class DefaultPolicyArbiter {
|
|
|
24
24
|
*/
|
|
25
25
|
static _DEFAULT_MAX_INHERITANCE_DEPTH = 10;
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Datasource key for the primary JSON path data source.
|
|
28
28
|
* @internal
|
|
29
29
|
*/
|
|
30
|
-
static
|
|
30
|
+
static _DATA_SOURCE_KEY = "data";
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
32
|
+
* Datasource key for the information source used in JSON path expressions.
|
|
33
33
|
* @internal
|
|
34
34
|
*/
|
|
35
|
-
static
|
|
35
|
+
static _INFORMATION_SOURCE_KEY = "information";
|
|
36
36
|
/**
|
|
37
|
-
* TWIN prefix
|
|
37
|
+
* TWIN prefix JSONPath canonical alias.
|
|
38
38
|
* @internal
|
|
39
39
|
*/
|
|
40
|
-
static
|
|
40
|
+
static _TWIN_JSONPATH = "twin:jsonPath";
|
|
41
|
+
/**
|
|
42
|
+
* Canonical jsonPath expression property.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
static _TWIN_JSONPATH_EXPRESSION = "twin:jsonPathExpression";
|
|
46
|
+
/**
|
|
47
|
+
* Optional data source key property for canonical twin:jsonPath targets.
|
|
48
|
+
* When absent, defaults to the primary data source.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
static _TWIN_JSONPATH_DATA_SOURCE = "twin:jsonPathDataSource";
|
|
41
52
|
/**
|
|
42
53
|
* The logging component.
|
|
43
54
|
* @internal
|
|
@@ -141,8 +152,8 @@ export class DefaultPolicyArbiter {
|
|
|
141
152
|
const mergedPolicy = await this.mergeInheritedPolicies(agreement);
|
|
142
153
|
const expandedPolicy = this.expandCompactPolicyRules(mergedPolicy);
|
|
143
154
|
const dataSources = {
|
|
144
|
-
[
|
|
145
|
-
[
|
|
155
|
+
[DefaultPolicyArbiter._DATA_SOURCE_KEY]: data,
|
|
156
|
+
[DefaultPolicyArbiter._INFORMATION_SOURCE_KEY]: information
|
|
146
157
|
};
|
|
147
158
|
// Extract agreement parties once for use in rule evaluation
|
|
148
159
|
const agreementAssigner = OdrlPolicyHelper.getPartyIds(agreement.assigner);
|
|
@@ -797,7 +808,7 @@ export class DefaultPolicyArbiter {
|
|
|
797
808
|
*/
|
|
798
809
|
async enforceDuty(policy, duty, dataSources, ruleDataContext) {
|
|
799
810
|
const enforcerNames = PolicyObligationEnforcerFactory.names();
|
|
800
|
-
const information = dataSources[
|
|
811
|
+
const information = dataSources[DefaultPolicyArbiter._INFORMATION_SOURCE_KEY];
|
|
801
812
|
if (enforcerNames.length === 0) {
|
|
802
813
|
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "noObligationEnforcersRegistered");
|
|
803
814
|
}
|
|
@@ -827,51 +838,70 @@ export class DefaultPolicyArbiter {
|
|
|
827
838
|
* @internal
|
|
828
839
|
*/
|
|
829
840
|
tryResolveTargetDataSource(targetId, dataSources, resolveValue = false) {
|
|
830
|
-
// If there is no target id, default to the
|
|
841
|
+
// If there is no target id, default to the data datasource
|
|
831
842
|
if (Is.empty(targetId)) {
|
|
832
843
|
return {
|
|
833
|
-
|
|
834
|
-
source: dataSources[`${DefaultPolicyArbiter._TWIN_PREFIX_OPERATIONS}${DefaultPolicyArbiter._TWIN_PREFIX_JSONPATH}`],
|
|
844
|
+
source: dataSources[DefaultPolicyArbiter._DATA_SOURCE_KEY],
|
|
835
845
|
target: "$",
|
|
836
|
-
value: dataSources[
|
|
846
|
+
value: dataSources[DefaultPolicyArbiter._DATA_SOURCE_KEY]
|
|
837
847
|
};
|
|
838
848
|
}
|
|
839
|
-
//
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
target
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
|
-
const matches = JsonPathHelper.query(target, source);
|
|
858
|
-
if (matches.length === 0) {
|
|
859
|
-
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "ruleTargetNotSupported", {
|
|
860
|
-
target: targetId
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
|
-
return {
|
|
864
|
-
prefix,
|
|
865
|
-
source,
|
|
866
|
-
target,
|
|
867
|
-
value: matches.length === 1 ? matches[0].value : matches.map(m => m.value)
|
|
868
|
-
};
|
|
869
|
-
}
|
|
849
|
+
// Handle twin:jsonPath:<datasource>:<expression> format.
|
|
850
|
+
// The datasource segment is optional; when absent the expression starts with "$"
|
|
851
|
+
// and falls back to the primary data source.
|
|
852
|
+
if (targetId.startsWith(`${DefaultPolicyArbiter._TWIN_JSONPATH}:`)) {
|
|
853
|
+
const rest = targetId.slice(DefaultPolicyArbiter._TWIN_JSONPATH.length + 1);
|
|
854
|
+
const matchingKey = Object.keys(dataSources).find(k => rest.startsWith(`${k}:`));
|
|
855
|
+
const sourceKey = matchingKey ?? DefaultPolicyArbiter._DATA_SOURCE_KEY;
|
|
856
|
+
const expression = matchingKey ? rest.slice(matchingKey.length + 1) : rest;
|
|
857
|
+
return this.resolveDataSourceByKey(sourceKey, expression, dataSources, resolveValue);
|
|
858
|
+
}
|
|
859
|
+
// Handle <datasource>:<expression> format
|
|
860
|
+
const matchingKey = Object.keys(dataSources).find(k => targetId.startsWith(`${k}:`));
|
|
861
|
+
if (matchingKey) {
|
|
862
|
+
const expression = targetId.slice(matchingKey.length + 1);
|
|
863
|
+
return this.resolveDataSourceByKey(matchingKey, expression, dataSources, resolveValue);
|
|
870
864
|
}
|
|
871
865
|
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "ruleTargetNotSupported", {
|
|
872
866
|
target: targetId
|
|
873
867
|
});
|
|
874
868
|
}
|
|
869
|
+
/**
|
|
870
|
+
* Resolve a datasource by key and evaluate a JSONPath expression against it.
|
|
871
|
+
* @param sourceKey The datasource key.
|
|
872
|
+
* @param expression The JSONPath expression.
|
|
873
|
+
* @param dataSources The available datasources.
|
|
874
|
+
* @param resolveValue Whether to evaluate the expression and return the matched value.
|
|
875
|
+
* @returns The resolved source, target expression, and optionally the matched value.
|
|
876
|
+
* @internal
|
|
877
|
+
*/
|
|
878
|
+
resolveDataSourceByKey(sourceKey, expression, dataSources, resolveValue = false) {
|
|
879
|
+
if (!Is.stringValue(expression)) {
|
|
880
|
+
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "jsonPathExpressionMissing", {
|
|
881
|
+
operand: "target"
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
if (!expression.startsWith("$")) {
|
|
885
|
+
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "ruleTargetNotSupported", {
|
|
886
|
+
target: `${sourceKey}:${expression}`
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
const source = dataSources[sourceKey];
|
|
890
|
+
if (!resolveValue) {
|
|
891
|
+
return { source, target: expression };
|
|
892
|
+
}
|
|
893
|
+
const matches = JsonPathHelper.query(expression, source);
|
|
894
|
+
if (matches.length === 0) {
|
|
895
|
+
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "ruleTargetNotSupported", {
|
|
896
|
+
target: `${sourceKey}:${expression}`
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
return {
|
|
900
|
+
source,
|
|
901
|
+
target: expression,
|
|
902
|
+
value: matches.length === 1 ? matches[0].value : matches.map(m => m.value)
|
|
903
|
+
};
|
|
904
|
+
}
|
|
875
905
|
/**
|
|
876
906
|
* Extract the target id from the permission.
|
|
877
907
|
* @param target The permission target.
|
|
@@ -889,7 +919,23 @@ export class DefaultPolicyArbiter {
|
|
|
889
919
|
if (arr.length === 0) {
|
|
890
920
|
return undefined;
|
|
891
921
|
}
|
|
892
|
-
|
|
922
|
+
const first = arr[0];
|
|
923
|
+
if (Is.string(first)) {
|
|
924
|
+
return first;
|
|
925
|
+
}
|
|
926
|
+
if (this.isTwinJsonPathTarget(first)) {
|
|
927
|
+
const t = first;
|
|
928
|
+
const expression = t[DefaultPolicyArbiter._TWIN_JSONPATH_EXPRESSION];
|
|
929
|
+
if (Is.stringValue(expression)) {
|
|
930
|
+
const dataSource = t[DefaultPolicyArbiter._TWIN_JSONPATH_DATA_SOURCE];
|
|
931
|
+
const sourceKey = Is.stringValue(dataSource)
|
|
932
|
+
? dataSource
|
|
933
|
+
: DefaultPolicyArbiter._DATA_SOURCE_KEY;
|
|
934
|
+
return `${sourceKey}:${expression}`;
|
|
935
|
+
}
|
|
936
|
+
return undefined;
|
|
937
|
+
}
|
|
938
|
+
return OdrlPolicyHelper.getUid(first);
|
|
893
939
|
}
|
|
894
940
|
/**
|
|
895
941
|
* Resolve the target identifier used for rule data context lookup.
|
|
@@ -952,6 +998,14 @@ export class DefaultPolicyArbiter {
|
|
|
952
998
|
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "multipleTargetsNotSupported");
|
|
953
999
|
}
|
|
954
1000
|
const firstTarget = arr[0];
|
|
1001
|
+
if (this.isTwinJsonPathTarget(firstTarget)) {
|
|
1002
|
+
const t = firstTarget;
|
|
1003
|
+
const resolved = this.resolveDataSourceByKey(t[DefaultPolicyArbiter._TWIN_JSONPATH_DATA_SOURCE] ?? DefaultPolicyArbiter._DATA_SOURCE_KEY, t[DefaultPolicyArbiter._TWIN_JSONPATH_EXPRESSION], dataSources);
|
|
1004
|
+
return {
|
|
1005
|
+
target: resolved.target,
|
|
1006
|
+
refinements: []
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
955
1009
|
if (Is.object(firstTarget)) {
|
|
956
1010
|
// Guard against unsupported ODRL asset properties
|
|
957
1011
|
if (Is.notEmpty(firstTarget.hasPolicy)) {
|
|
@@ -962,7 +1016,8 @@ export class DefaultPolicyArbiter {
|
|
|
962
1016
|
}
|
|
963
1017
|
if (Is.object(firstTarget) &&
|
|
964
1018
|
OdrlPolicyHelper.getType(firstTarget) === OdrlTypes.AssetCollection) {
|
|
965
|
-
if (!Is.stringValue(firstTarget.source)
|
|
1019
|
+
if (!Is.stringValue(firstTarget.source) ||
|
|
1020
|
+
!firstTarget.source.startsWith(`${DefaultPolicyArbiter._TWIN_JSONPATH}:`)) {
|
|
966
1021
|
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "assetCollectionSourceNotSupported", {
|
|
967
1022
|
source: firstTarget.source ?? ""
|
|
968
1023
|
});
|
|
@@ -1054,11 +1109,18 @@ export class DefaultPolicyArbiter {
|
|
|
1054
1109
|
};
|
|
1055
1110
|
}
|
|
1056
1111
|
const regularConstraint = refinement;
|
|
1057
|
-
|
|
1112
|
+
const constraintWithExtensions = regularConstraint;
|
|
1113
|
+
const canonicalExpression = constraintWithExtensions[DefaultPolicyArbiter._TWIN_JSONPATH_EXPRESSION];
|
|
1114
|
+
const rewrittenConstraint = {
|
|
1058
1115
|
...regularConstraint,
|
|
1059
1116
|
leftOperand: this.rewriteOperandForDecisionTarget(regularConstraint.leftOperand, sourceTarget, itemTarget),
|
|
1060
1117
|
rightOperand: this.rewriteOperandForDecisionTarget(regularConstraint.rightOperand, sourceTarget, itemTarget)
|
|
1061
1118
|
};
|
|
1119
|
+
if (Is.stringValue(canonicalExpression)) {
|
|
1120
|
+
rewrittenConstraint[DefaultPolicyArbiter._TWIN_JSONPATH_EXPRESSION] =
|
|
1121
|
+
this.rewriteWildcardPath(canonicalExpression, sourceTarget, itemTarget);
|
|
1122
|
+
}
|
|
1123
|
+
return rewrittenConstraint;
|
|
1062
1124
|
}
|
|
1063
1125
|
/**
|
|
1064
1126
|
* Rewrite JSONPath-based operands from wildcard source to concrete item target.
|
|
@@ -1069,20 +1131,18 @@ export class DefaultPolicyArbiter {
|
|
|
1069
1131
|
* @internal
|
|
1070
1132
|
*/
|
|
1071
1133
|
rewriteOperandForDecisionTarget(operand, sourceTarget, itemTarget) {
|
|
1072
|
-
if (Is.stringValue(operand)) {
|
|
1073
|
-
const prefix = `${DefaultPolicyArbiter._TWIN_PREFIX_OPERATIONS}${DefaultPolicyArbiter._TWIN_PREFIX_JSONPATH}:`;
|
|
1074
|
-
if (operand.startsWith(prefix)) {
|
|
1075
|
-
const valuePath = operand.slice(prefix.length);
|
|
1076
|
-
return `${prefix}${this.rewriteWildcardPath(valuePath, sourceTarget, itemTarget)}`;
|
|
1077
|
-
}
|
|
1078
|
-
return operand;
|
|
1079
|
-
}
|
|
1080
1134
|
if (Is.object(operand)) {
|
|
1081
|
-
const typedOperand = {
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1135
|
+
const typedOperand = {
|
|
1136
|
+
...operand
|
|
1137
|
+
};
|
|
1138
|
+
if (this.isTwinJsonPathOperandType(typedOperand["@type"])) {
|
|
1139
|
+
if (Is.stringValue(typedOperand["@value"])) {
|
|
1140
|
+
typedOperand["@value"] = this.rewriteWildcardPath(typedOperand["@value"], sourceTarget, itemTarget);
|
|
1141
|
+
}
|
|
1142
|
+
const canonicalExpression = typedOperand[DefaultPolicyArbiter._TWIN_JSONPATH_EXPRESSION];
|
|
1143
|
+
if (Is.stringValue(canonicalExpression)) {
|
|
1144
|
+
typedOperand[DefaultPolicyArbiter._TWIN_JSONPATH_EXPRESSION] = this.rewriteWildcardPath(canonicalExpression, sourceTarget, itemTarget);
|
|
1145
|
+
}
|
|
1086
1146
|
}
|
|
1087
1147
|
return typedOperand;
|
|
1088
1148
|
}
|
|
@@ -1150,8 +1210,8 @@ export class DefaultPolicyArbiter {
|
|
|
1150
1210
|
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "constraintStatusNotSupported");
|
|
1151
1211
|
}
|
|
1152
1212
|
// Evaluate the main constraint condition
|
|
1153
|
-
const leftValue = this.calculateOperandValue(regularConstraint.leftOperand, dataSources);
|
|
1154
|
-
const rightValue = this.calculateOperandValue(regularConstraint.rightOperand, dataSources);
|
|
1213
|
+
const leftValue = this.calculateOperandValue(regularConstraint.leftOperand, dataSources, regularConstraint);
|
|
1214
|
+
const rightValue = this.calculateOperandValue(regularConstraint.rightOperand, dataSources, regularConstraint);
|
|
1155
1215
|
const mainSatisfied = this.evaluateOperator(regularConstraint.operator, leftValue, rightValue);
|
|
1156
1216
|
// If main constraint is not satisfied, the overall constraint fails
|
|
1157
1217
|
return mainSatisfied;
|
|
@@ -1276,27 +1336,12 @@ export class DefaultPolicyArbiter {
|
|
|
1276
1336
|
* @internal
|
|
1277
1337
|
*/
|
|
1278
1338
|
tryResolveOperandLookup(operandTypeOrValue, operandValue, dataSources) {
|
|
1279
|
-
|
|
1280
|
-
if (dataSources[
|
|
1281
|
-
if (!Is.stringValue(operandValue)) {
|
|
1282
|
-
return undefined;
|
|
1283
|
-
}
|
|
1284
|
-
lookupTargetId = `${operandTypeOrValue}:${operandValue}`;
|
|
1285
|
-
}
|
|
1286
|
-
else if (operandTypeOrValue.includes(":")) {
|
|
1287
|
-
lookupTargetId = operandTypeOrValue;
|
|
1288
|
-
}
|
|
1289
|
-
else {
|
|
1339
|
+
const sourceKey = this.normalizeTwinJsonPathOperandAlias(operandTypeOrValue);
|
|
1340
|
+
if (!dataSources[sourceKey] || !Is.stringValue(operandValue)) {
|
|
1290
1341
|
return undefined;
|
|
1291
1342
|
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
const resolved = this.tryResolveTargetDataSource(lookupTargetId, dataSources);
|
|
1295
|
-
return {
|
|
1296
|
-
source: resolved.source,
|
|
1297
|
-
jsonPath: resolved.target
|
|
1298
|
-
};
|
|
1299
|
-
}
|
|
1343
|
+
const resolved = this.resolveDataSourceByKey(sourceKey, operandValue, dataSources);
|
|
1344
|
+
return { source: resolved.source, jsonPath: resolved.target };
|
|
1300
1345
|
}
|
|
1301
1346
|
/**
|
|
1302
1347
|
* Calculate an operand value.
|
|
@@ -1305,24 +1350,42 @@ export class DefaultPolicyArbiter {
|
|
|
1305
1350
|
* @returns The resolved operand value.
|
|
1306
1351
|
* @internal
|
|
1307
1352
|
*/
|
|
1308
|
-
calculateOperandValue(operand, dataSources) {
|
|
1353
|
+
calculateOperandValue(operand, dataSources, constraint) {
|
|
1309
1354
|
// Treat prefixed operands as selectors against a namespaced source dictionary.
|
|
1310
1355
|
// Examples: twin:jsonpath:$.field, twin:information:$.credentials.level
|
|
1311
1356
|
let jsonPath;
|
|
1312
1357
|
let operandRoot;
|
|
1313
1358
|
if (Is.stringValue(operand)) {
|
|
1314
|
-
const
|
|
1359
|
+
const expression = this.extractJsonPathExpressionFromConstraint(constraint, operand);
|
|
1360
|
+
let resolvedOperand = operand;
|
|
1361
|
+
if (operand === DefaultPolicyArbiter._TWIN_JSONPATH &&
|
|
1362
|
+
Is.object(constraint)) {
|
|
1363
|
+
const dataSourceOverride = constraint[DefaultPolicyArbiter._TWIN_JSONPATH_DATA_SOURCE];
|
|
1364
|
+
if (Is.stringValue(dataSourceOverride)) {
|
|
1365
|
+
resolvedOperand = dataSourceOverride;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
const lookup = this.tryResolveOperandLookup(resolvedOperand, expression ?? operand, dataSources);
|
|
1315
1369
|
if (lookup) {
|
|
1316
1370
|
jsonPath = lookup.jsonPath;
|
|
1317
1371
|
operandRoot = lookup.source;
|
|
1318
1372
|
}
|
|
1319
1373
|
}
|
|
1320
1374
|
else if (Is.object(operand)) {
|
|
1375
|
+
const typedOperand = operand;
|
|
1321
1376
|
// Is this an object { "@value": "18", "@type": "xsd:integer" } ?
|
|
1322
|
-
const value =
|
|
1323
|
-
|
|
1377
|
+
const value = this.extractJsonPathExpressionFromTypedOperand(typedOperand) ??
|
|
1378
|
+
typedOperand["@value"];
|
|
1379
|
+
const type = typedOperand["@type"];
|
|
1324
1380
|
if (Is.stringValue(type)) {
|
|
1325
|
-
|
|
1381
|
+
let resolvedType = type;
|
|
1382
|
+
if (this.isTwinJsonPathOperandType(type)) {
|
|
1383
|
+
const dataSourceOverride = typedOperand[DefaultPolicyArbiter._TWIN_JSONPATH_DATA_SOURCE];
|
|
1384
|
+
if (Is.stringValue(dataSourceOverride)) {
|
|
1385
|
+
resolvedType = dataSourceOverride;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
const lookup = this.tryResolveOperandLookup(resolvedType, value, dataSources);
|
|
1326
1389
|
if (lookup) {
|
|
1327
1390
|
jsonPath = lookup.jsonPath;
|
|
1328
1391
|
operandRoot = lookup.source;
|
|
@@ -1352,6 +1415,89 @@ export class DefaultPolicyArbiter {
|
|
|
1352
1415
|
// Not JSON Path or object value so return as is
|
|
1353
1416
|
return operand;
|
|
1354
1417
|
}
|
|
1418
|
+
/**
|
|
1419
|
+
* Determine if a target object uses the canonical twin:jsonPath object format.
|
|
1420
|
+
* @param target The target value.
|
|
1421
|
+
* @returns True if the target is a canonical twin:jsonPath object.
|
|
1422
|
+
* @internal
|
|
1423
|
+
*/
|
|
1424
|
+
isTwinJsonPathTarget(target) {
|
|
1425
|
+
return Is.object(target) && this.isTwinJsonPathOperandType(OdrlPolicyHelper.getType(target));
|
|
1426
|
+
}
|
|
1427
|
+
/**
|
|
1428
|
+
* Determine if the operand type is a jsonPath namespace.
|
|
1429
|
+
* @param type The operand type.
|
|
1430
|
+
* @returns True if the type is twin:jsonPath.
|
|
1431
|
+
* @internal
|
|
1432
|
+
*/
|
|
1433
|
+
isTwinJsonPathOperandType(type) {
|
|
1434
|
+
return type === DefaultPolicyArbiter._TWIN_JSONPATH;
|
|
1435
|
+
}
|
|
1436
|
+
/**
|
|
1437
|
+
* Normalize canonical jsonPath alias to the legacy jsonpath namespace key.
|
|
1438
|
+
* @param operandTypeOrValue The raw operand type or value.
|
|
1439
|
+
* @returns The normalized operand type/value.
|
|
1440
|
+
* @internal
|
|
1441
|
+
*/
|
|
1442
|
+
normalizeTwinJsonPathOperandAlias(operandTypeOrValue) {
|
|
1443
|
+
if (operandTypeOrValue === DefaultPolicyArbiter._TWIN_JSONPATH ||
|
|
1444
|
+
operandTypeOrValue.startsWith(`${DefaultPolicyArbiter._TWIN_JSONPATH}:`)) {
|
|
1445
|
+
const suffix = operandTypeOrValue.slice(DefaultPolicyArbiter._TWIN_JSONPATH.length);
|
|
1446
|
+
return `${DefaultPolicyArbiter._DATA_SOURCE_KEY}${suffix}`;
|
|
1447
|
+
}
|
|
1448
|
+
return operandTypeOrValue;
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* Extract canonical jsonPath expression from typed operand object.
|
|
1452
|
+
* @param operand The typed operand.
|
|
1453
|
+
* @returns The jsonPath expression if present.
|
|
1454
|
+
* @internal
|
|
1455
|
+
*/
|
|
1456
|
+
extractJsonPathExpressionFromTypedOperand(operand) {
|
|
1457
|
+
if (!this.isTwinJsonPathOperandType(operand["@type"])) {
|
|
1458
|
+
return undefined;
|
|
1459
|
+
}
|
|
1460
|
+
const expression = operand[DefaultPolicyArbiter._TWIN_JSONPATH_EXPRESSION];
|
|
1461
|
+
if (Is.stringValue(expression)) {
|
|
1462
|
+
return expression;
|
|
1463
|
+
}
|
|
1464
|
+
const type = operand["@type"];
|
|
1465
|
+
if (type === DefaultPolicyArbiter._TWIN_JSONPATH) {
|
|
1466
|
+
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "jsonPathExpressionMissing", {
|
|
1467
|
+
operand: "rightOperand"
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Extract canonical jsonPath expression from constraint for leftOperand aliases.
|
|
1473
|
+
* @param constraint The constraint containing the left operand.
|
|
1474
|
+
* @param leftOperand The left operand.
|
|
1475
|
+
* @returns The expression if canonical form is used.
|
|
1476
|
+
* @internal
|
|
1477
|
+
*/
|
|
1478
|
+
extractJsonPathExpressionFromConstraint(constraint, leftOperand) {
|
|
1479
|
+
if (!Is.object(constraint)) {
|
|
1480
|
+
return undefined;
|
|
1481
|
+
}
|
|
1482
|
+
if (constraint.leftOperand !== leftOperand) {
|
|
1483
|
+
return undefined;
|
|
1484
|
+
}
|
|
1485
|
+
if (leftOperand.startsWith(`${DefaultPolicyArbiter._TWIN_JSONPATH}:`)) {
|
|
1486
|
+
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "jsonPathExpressionMissing", {
|
|
1487
|
+
operand: "leftOperand"
|
|
1488
|
+
});
|
|
1489
|
+
}
|
|
1490
|
+
if (leftOperand !== DefaultPolicyArbiter._TWIN_JSONPATH) {
|
|
1491
|
+
return undefined;
|
|
1492
|
+
}
|
|
1493
|
+
const expression = constraint[DefaultPolicyArbiter._TWIN_JSONPATH_EXPRESSION];
|
|
1494
|
+
if (Is.stringValue(expression)) {
|
|
1495
|
+
return expression;
|
|
1496
|
+
}
|
|
1497
|
+
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "jsonPathExpressionMissing", {
|
|
1498
|
+
operand: "leftOperand"
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1355
1501
|
/**
|
|
1356
1502
|
* Evaluate an ODRL operator against resolved operands.
|
|
1357
1503
|
* @param operator The operator.
|