@twin.org/rights-management-plugins 0.0.3-next.53 → 0.0.3-next.55
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/models/IStaticPolicyInformationSource.js.map +1 -1
- package/dist/es/policyArbiters/defaultPolicyArbiter.js +126 -8
- package/dist/es/policyArbiters/defaultPolicyArbiter.js.map +1 -1
- package/dist/es/policyArbiters/passThroughPolicyArbiter.js.map +1 -1
- package/dist/es/policyInformationSources/identityPolicyInformationSource.js.map +1 -1
- package/dist/es/policyInformationSources/identityProfilePolicyInformationSource.js +4 -4
- package/dist/es/policyInformationSources/identityProfilePolicyInformationSource.js.map +1 -1
- package/dist/es/policyInformationSources/staticPolicyInformationSource.js.map +1 -1
- package/dist/es/policyNegotiators/passThroughPolicyNegotiator.js.map +1 -1
- package/dist/es/policyObligationEnforcers/passThroughPolicyObligationEnforcer.js.map +1 -1
- package/dist/types/models/IStaticPolicyInformationSource.d.ts +2 -5
- package/dist/types/policyArbiters/defaultPolicyArbiter.d.ts +2 -5
- package/dist/types/policyArbiters/passThroughPolicyArbiter.d.ts +2 -5
- package/dist/types/policyInformationSources/identityPolicyInformationSource.d.ts +2 -5
- package/dist/types/policyInformationSources/identityProfilePolicyInformationSource.d.ts +2 -5
- package/dist/types/policyInformationSources/staticPolicyInformationSource.d.ts +2 -5
- package/dist/types/policyNegotiators/passThroughPolicyNegotiator.d.ts +3 -8
- package/dist/types/policyObligationEnforcers/passThroughPolicyObligationEnforcer.d.ts +2 -5
- package/docs/changelog.md +44 -0
- package/docs/reference/classes/DefaultPolicyArbiter.md +2 -0
- package/docs/reference/classes/IdentityPolicyInformationSource.md +2 -2
- package/docs/reference/classes/IdentityProfilePolicyInformationSource.md +2 -2
- package/docs/reference/classes/PassThroughPolicyArbiter.md +2 -0
- package/docs/reference/classes/PassThroughPolicyNegotiator.md +4 -0
- package/docs/reference/classes/PassThroughPolicyObligationEnforcer.md +2 -0
- package/docs/reference/classes/StaticPolicyInformationSource.md +2 -2
- package/docs/reference/interfaces/IStaticPolicyInformationSource.md +1 -5
- package/locales/en.json +2 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IStaticPolicyInformationSource.js","sourceRoot":"","sources":["../../../src/models/IStaticPolicyInformationSource.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {
|
|
1
|
+
{"version":3,"file":"IStaticPolicyInformationSource.js","sourceRoot":"","sources":["../../../src/models/IStaticPolicyInformationSource.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tIRightsManagementInformation,\n\tPolicyInformationAccessMode\n} from \"@twin.org/rights-management-models\";\n\n/**\n * Configuration for the Static Policy Information Source Component.\n */\nexport interface IStaticPolicyInformationSource {\n\t/**\n\t * Is the information public, if so it will be shared with negotiation requests.\n\t */\n\taccessMode: PolicyInformationAccessMode;\n\n\t/**\n\t * Information is only provided for the specified locator combination.\n\t */\n\tmatchLocators?: {\n\t\tassignee?: string;\n\t\tassigner?: string;\n\t\ttarget?: string;\n\t\taction?: string;\n\t}[];\n\n\t/**\n\t * The objects containing the information.\n\t */\n\tobjects: IRightsManagementInformation;\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Copyright 2025 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
-
import { ArrayHelper, Coerce, ComponentFactory, GeneralError, Guards, Is, ObjectHelper, StringHelper } from "@twin.org/core";
|
|
3
|
+
import { ArrayHelper, Coerce, ComponentFactory, Duration, GeneralError, Guards, Is, ObjectHelper, StringHelper } from "@twin.org/core";
|
|
4
4
|
import { JsonPathHelper } from "@twin.org/data-json-path";
|
|
5
5
|
import { OdrlPolicyHelper, OdrlProfiles, PolicyDecision, PolicyObligationEnforcerFactory } from "@twin.org/rights-management-models";
|
|
6
|
-
import { OdrlConflictStrategyType, OdrlLogicalConstraintType, OdrlOperatorType, OdrlTypes } from "@twin.org/standards-w3c-odrl";
|
|
6
|
+
import { OdrlConflictStrategyType, OdrlLeftOperandType, OdrlLogicalConstraintType, OdrlOperatorType, OdrlTypes } from "@twin.org/standards-w3c-odrl";
|
|
7
7
|
/**
|
|
8
8
|
* Default Policy Arbiter.
|
|
9
9
|
*/
|
|
@@ -1244,8 +1244,8 @@ export class DefaultPolicyArbiter {
|
|
|
1244
1244
|
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "constraintStatusNotSupported");
|
|
1245
1245
|
}
|
|
1246
1246
|
// Evaluate the main constraint condition
|
|
1247
|
-
const leftValue = this.calculateOperandValue(regularConstraint.leftOperand, dataSources, regularConstraint);
|
|
1248
|
-
const rightValue = this.calculateOperandValue(regularConstraint.rightOperand, dataSources, regularConstraint);
|
|
1247
|
+
const leftValue = this.calculateOperandValue(regularConstraint.leftOperand, dataSources, regularConstraint, true);
|
|
1248
|
+
const rightValue = this.calculateOperandValue(regularConstraint.rightOperand, dataSources, regularConstraint, false);
|
|
1249
1249
|
const mainSatisfied = this.evaluateOperator(regularConstraint.operator, leftValue, rightValue);
|
|
1250
1250
|
// If main constraint is not satisfied, the overall constraint fails
|
|
1251
1251
|
return mainSatisfied;
|
|
@@ -1396,10 +1396,12 @@ export class DefaultPolicyArbiter {
|
|
|
1396
1396
|
* @param operand The operand.
|
|
1397
1397
|
* @param dataSources The available prefixed operand sources.
|
|
1398
1398
|
* @param constraint Optional constraint providing additional context for operand resolution.
|
|
1399
|
+
* @param isLeftOperand True when resolving the left operand of the constraint.
|
|
1399
1400
|
* @returns The resolved operand value.
|
|
1401
|
+
* @throws GeneralError When a known ODRL built-in left operand cannot be resolved.
|
|
1400
1402
|
* @internal
|
|
1401
1403
|
*/
|
|
1402
|
-
calculateOperandValue(operand, dataSources, constraint) {
|
|
1404
|
+
calculateOperandValue(operand, dataSources, constraint, isLeftOperand) {
|
|
1403
1405
|
let jsonPath;
|
|
1404
1406
|
let operandRoot;
|
|
1405
1407
|
if (Is.stringValue(operand)) {
|
|
@@ -1417,6 +1419,30 @@ export class DefaultPolicyArbiter {
|
|
|
1417
1419
|
jsonPath = lookup.jsonPath;
|
|
1418
1420
|
operandRoot = lookup.source;
|
|
1419
1421
|
}
|
|
1422
|
+
else {
|
|
1423
|
+
const builtIn = this.resolveOdrlBuiltInLeftOperand(operand);
|
|
1424
|
+
if (!Is.undefined(builtIn)) {
|
|
1425
|
+
return builtIn;
|
|
1426
|
+
}
|
|
1427
|
+
if (isLeftOperand) {
|
|
1428
|
+
if (this.operatorSupportsInformationLookup(constraint?.operator)) {
|
|
1429
|
+
const infoResult = this.resolveInformationKeyOperand(operand, dataSources);
|
|
1430
|
+
if (infoResult.found) {
|
|
1431
|
+
return infoResult.value;
|
|
1432
|
+
}
|
|
1433
|
+
if (this.isKnownOdrlBuiltInOperand(operand)) {
|
|
1434
|
+
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "leftOperandNotSupported", {
|
|
1435
|
+
leftOperand: operand
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
else if (this.isKnownOdrlBuiltInOperand(operand)) {
|
|
1440
|
+
throw new GeneralError(DefaultPolicyArbiter.CLASS_NAME, "leftOperandNotSupported", {
|
|
1441
|
+
leftOperand: operand
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1420
1446
|
}
|
|
1421
1447
|
else if (Is.object(operand)) {
|
|
1422
1448
|
const typedOperand = operand;
|
|
@@ -1560,9 +1586,9 @@ export class DefaultPolicyArbiter {
|
|
|
1560
1586
|
const leftValues = ArrayHelper.fromObjectOrArray(left ?? []);
|
|
1561
1587
|
switch (operator) {
|
|
1562
1588
|
case OdrlOperatorType.Eq:
|
|
1563
|
-
return leftValues.some(v => ObjectHelper.equal(v, right, false));
|
|
1589
|
+
return leftValues.some(v => ObjectHelper.equal(v, right, false) || this.compareDurationEq(v, right));
|
|
1564
1590
|
case OdrlOperatorType.Neq:
|
|
1565
|
-
return leftValues.every(v => !ObjectHelper.equal(v, right, false));
|
|
1591
|
+
return leftValues.every(v => !ObjectHelper.equal(v, right, false) && !this.compareDurationEq(v, right));
|
|
1566
1592
|
case OdrlOperatorType.Gt:
|
|
1567
1593
|
return leftValues.some(v => this.compareOrdered(v, right, (a, b) => a > b));
|
|
1568
1594
|
case OdrlOperatorType.Gteq:
|
|
@@ -1583,7 +1609,10 @@ export class DefaultPolicyArbiter {
|
|
|
1583
1609
|
return ObjectHelper.equal(leftValues, ArrayHelper.fromObjectOrArray(right) ?? [], false);
|
|
1584
1610
|
}
|
|
1585
1611
|
case OdrlOperatorType.IsNoneOf: {
|
|
1586
|
-
return leftValues.every(v =>
|
|
1612
|
+
return leftValues.every(v => {
|
|
1613
|
+
const stringValue = Is.string(v) || Is.number(v) || Is.boolean(v) ? String(v) : JSON.stringify(v);
|
|
1614
|
+
return !(ArrayHelper.fromObjectOrArray(right) ?? []).includes(stringValue);
|
|
1615
|
+
});
|
|
1587
1616
|
}
|
|
1588
1617
|
case OdrlOperatorType.LocTimeEq:
|
|
1589
1618
|
return leftValues.some(v => ObjectHelper.equal(v, right, false));
|
|
@@ -1618,6 +1647,11 @@ export class DefaultPolicyArbiter {
|
|
|
1618
1647
|
if (!Is.undefined(leftDate) && !Is.undefined(rightDate)) {
|
|
1619
1648
|
return compare(leftDate.getTime(), rightDate.getTime());
|
|
1620
1649
|
}
|
|
1650
|
+
const leftDuration = Coerce.duration(left);
|
|
1651
|
+
const rightDuration = Coerce.duration(right);
|
|
1652
|
+
if (!Is.undefined(leftDuration) && !Is.undefined(rightDuration)) {
|
|
1653
|
+
return compare(Duration.toSeconds(leftDuration), Duration.toSeconds(rightDuration));
|
|
1654
|
+
}
|
|
1621
1655
|
// Only use string ordering when both operands are actual strings.
|
|
1622
1656
|
// Avoid coercing other types into strings, as that can cause
|
|
1623
1657
|
// unintended comparisons like 18 >= "$.minAge" evaluating to true.
|
|
@@ -1626,6 +1660,84 @@ export class DefaultPolicyArbiter {
|
|
|
1626
1660
|
}
|
|
1627
1661
|
return false;
|
|
1628
1662
|
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Test whether two values are equal when interpreted as ISO 8601 durations.
|
|
1665
|
+
* Returns false if either side cannot be coerced to a duration.
|
|
1666
|
+
* @param left The left value.
|
|
1667
|
+
* @param right The right value.
|
|
1668
|
+
* @returns True when both sides represent the same duration in seconds.
|
|
1669
|
+
* @internal
|
|
1670
|
+
*/
|
|
1671
|
+
compareDurationEq(left, right) {
|
|
1672
|
+
const leftDuration = Coerce.duration(left);
|
|
1673
|
+
const rightDuration = Coerce.duration(right);
|
|
1674
|
+
if (!Is.undefined(leftDuration) && !Is.undefined(rightDuration)) {
|
|
1675
|
+
return Duration.toSeconds(leftDuration) === Duration.toSeconds(rightDuration);
|
|
1676
|
+
}
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1679
|
+
/**
|
|
1680
|
+
* Resolve an ODRL built-in left operand to its runtime value.
|
|
1681
|
+
* Returns the resolved value for natively-handled operands and undefined for all others.
|
|
1682
|
+
* Callers are responsible for throwing when an unresolved known built-in is unacceptable.
|
|
1683
|
+
* @param operand The left operand string.
|
|
1684
|
+
* @returns The resolved value, or undefined when the operand has no native resolution.
|
|
1685
|
+
* @internal
|
|
1686
|
+
*/
|
|
1687
|
+
resolveOdrlBuiltInLeftOperand(operand) {
|
|
1688
|
+
if (operand === OdrlLeftOperandType.DateTime) {
|
|
1689
|
+
return new Date();
|
|
1690
|
+
}
|
|
1691
|
+
return undefined;
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* Determine whether the operand string is a recognised ODRL built-in left operand.
|
|
1695
|
+
* @param operand The operand string to test.
|
|
1696
|
+
* @returns True when the operand appears in the OdrlLeftOperandType vocabulary.
|
|
1697
|
+
* @internal
|
|
1698
|
+
*/
|
|
1699
|
+
isKnownOdrlBuiltInOperand(operand) {
|
|
1700
|
+
return Object.values(OdrlLeftOperandType).includes(operand);
|
|
1701
|
+
}
|
|
1702
|
+
/**
|
|
1703
|
+
* Determine whether the operator supports resolving left operands from the information object.
|
|
1704
|
+
* Value-comparison and set operators are supported; structural/relationship operators are not.
|
|
1705
|
+
* @param operator The operator to test.
|
|
1706
|
+
* @returns True when information-key lookup is appropriate for this operator.
|
|
1707
|
+
* @internal
|
|
1708
|
+
*/
|
|
1709
|
+
operatorSupportsInformationLookup(operator) {
|
|
1710
|
+
switch (operator) {
|
|
1711
|
+
case OdrlOperatorType.Eq:
|
|
1712
|
+
case OdrlOperatorType.Neq:
|
|
1713
|
+
case OdrlOperatorType.Gt:
|
|
1714
|
+
case OdrlOperatorType.Gteq:
|
|
1715
|
+
case OdrlOperatorType.Lt:
|
|
1716
|
+
case OdrlOperatorType.Lteq:
|
|
1717
|
+
case OdrlOperatorType.IsAnyOf:
|
|
1718
|
+
case OdrlOperatorType.IsAllOf:
|
|
1719
|
+
case OdrlOperatorType.IsNoneOf:
|
|
1720
|
+
case OdrlOperatorType.LocTimeEq:
|
|
1721
|
+
case OdrlOperatorType.LocTimeGteq:
|
|
1722
|
+
return true;
|
|
1723
|
+
default:
|
|
1724
|
+
return false;
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
/**
|
|
1728
|
+
* Attempt to resolve a left operand string as a key in the information object.
|
|
1729
|
+
* @param operand The left operand string.
|
|
1730
|
+
* @param dataSources The available data sources.
|
|
1731
|
+
* @returns An object indicating whether the key was found and its value when present.
|
|
1732
|
+
* @internal
|
|
1733
|
+
*/
|
|
1734
|
+
resolveInformationKeyOperand(operand, dataSources) {
|
|
1735
|
+
const information = dataSources[DefaultPolicyArbiter._INFORMATION_SOURCE_KEY];
|
|
1736
|
+
if (Is.object(information) && !Is.empty(information[operand])) {
|
|
1737
|
+
return { found: true, value: information[operand] };
|
|
1738
|
+
}
|
|
1739
|
+
return { found: false };
|
|
1740
|
+
}
|
|
1629
1741
|
/**
|
|
1630
1742
|
* Coerce a value to a specific XSD type.
|
|
1631
1743
|
* @param value The value to coerce.
|
|
@@ -1666,6 +1778,12 @@ export class DefaultPolicyArbiter {
|
|
|
1666
1778
|
// Handle standard xsd types
|
|
1667
1779
|
return Coerce.dateTime(value);
|
|
1668
1780
|
}
|
|
1781
|
+
else if (type === "xsd:duration") {
|
|
1782
|
+
// Handle standard xsd types - convert to total seconds for ordered comparison.
|
|
1783
|
+
// Falls back to numeric coercion for non-ISO values (e.g. bare seconds as a number).
|
|
1784
|
+
const dur = Coerce.duration(value);
|
|
1785
|
+
return Is.undefined(dur) ? Coerce.number(value) : Duration.toSeconds(dur);
|
|
1786
|
+
}
|
|
1669
1787
|
return undefined;
|
|
1670
1788
|
}
|
|
1671
1789
|
}
|