@fedify/vocab-tools 2.4.0-dev.2063 → 2.4.0-dev.2071
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/deno.json +1 -1
- package/dist/mod.cjs +132 -66
- package/dist/mod.js +132 -66
- package/package.json +1 -1
- package/src/__snapshots__/class.test.ts.deno.snap +16928 -8905
- package/src/__snapshots__/class.test.ts.node.snap +16928 -8905
- package/src/__snapshots__/class.test.ts.snap +16928 -8905
- package/src/class.ts +9 -3
- package/src/property.ts +122 -62
package/deno.json
CHANGED
package/dist/mod.cjs
CHANGED
|
@@ -8,7 +8,7 @@ let yaml = require("yaml");
|
|
|
8
8
|
let es_toolkit = require("es-toolkit");
|
|
9
9
|
//#region deno.json
|
|
10
10
|
var name = "@fedify/vocab-tools";
|
|
11
|
-
var version = "2.4.0-dev.
|
|
11
|
+
var version = "2.4.0-dev.2071+8b9dccb9";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/type.ts
|
|
14
14
|
const HEURISTICS_CONTEXTS = [
|
|
@@ -1673,13 +1673,22 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1673
1673
|
${JSON.stringify(version)},
|
|
1674
1674
|
);
|
|
1675
1675
|
return await tracer.startActiveSpan("activitypub.lookup_object", async (span) => {
|
|
1676
|
-
|
|
1676
|
+
const dereferencePortable = async (
|
|
1677
|
+
portableUrl: URL,
|
|
1678
|
+
extra: {
|
|
1679
|
+
inferredGateways?: readonly URL[];
|
|
1680
|
+
response?: RemoteDocument;
|
|
1681
|
+
contextLoader?: DocumentLoader;
|
|
1682
|
+
} = {},
|
|
1683
|
+
) => {
|
|
1677
1684
|
try {
|
|
1678
|
-
const obj = await dereferencePortableIri(
|
|
1685
|
+
const obj = await dereferencePortableIri(portableUrl, {
|
|
1679
1686
|
documentLoader,
|
|
1680
|
-
contextLoader,
|
|
1687
|
+
contextLoader: extra.contextLoader ?? contextLoader,
|
|
1681
1688
|
tracerProvider,
|
|
1682
1689
|
gateways: options.gateways,
|
|
1690
|
+
inferredGateways: extra.inferredGateways,
|
|
1691
|
+
response: extra.response,
|
|
1683
1692
|
verifyPortableObject: options.verifyPortableObject,
|
|
1684
1693
|
referrer: {
|
|
1685
1694
|
object: this,
|
|
@@ -1697,7 +1706,10 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1697
1706
|
}),
|
|
1698
1707
|
});
|
|
1699
1708
|
if (obj != null) {
|
|
1700
|
-
span.setAttribute(
|
|
1709
|
+
span.setAttribute(
|
|
1710
|
+
"activitypub.object.id",
|
|
1711
|
+
(obj.id ?? portableUrl).href,
|
|
1712
|
+
);
|
|
1701
1713
|
span.setAttribute(
|
|
1702
1714
|
"activitypub.object.type",
|
|
1703
1715
|
// @ts-ignore: obj.constructor always has a typeId.
|
|
@@ -1714,12 +1726,20 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1714
1726
|
} finally {
|
|
1715
1727
|
span.end();
|
|
1716
1728
|
}
|
|
1717
|
-
}
|
|
1729
|
+
};
|
|
1730
|
+
if (isPortableIri(url)) return await dereferencePortable(url);
|
|
1718
1731
|
const lookupUrl = formatIri(url);
|
|
1719
|
-
const
|
|
1720
|
-
if (
|
|
1721
|
-
|
|
1722
|
-
|
|
1732
|
+
const portableMode = isPortableMode(this, options);
|
|
1733
|
+
if (portableMode) {
|
|
1734
|
+
const compatible = parseCompatibleEf61Reference(url);
|
|
1735
|
+
if (compatible === null) {
|
|
1736
|
+
span.end();
|
|
1737
|
+
return rejectMalformedCompatibleReference(lookupUrl, options);
|
|
1738
|
+
} else if (compatible != null) {
|
|
1739
|
+
return await dereferencePortable(compatible.id, {
|
|
1740
|
+
inferredGateways: [compatible.gateway],
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1723
1743
|
}
|
|
1724
1744
|
let fetchResult: RemoteDocument;
|
|
1725
1745
|
try {
|
|
@@ -1740,63 +1760,90 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1740
1760
|
throw error;
|
|
1741
1761
|
}
|
|
1742
1762
|
const { document, documentUrl } = fetchResult;
|
|
1743
|
-
|
|
1763
|
+
// In portable mode, the document may turn out to be a portable object,
|
|
1764
|
+
// which has to be verified with the same context documents:
|
|
1765
|
+
const snapshot = portableMode
|
|
1766
|
+
? createSnapshotContextLoader(contextLoader)
|
|
1767
|
+
: null;
|
|
1744
1768
|
try {
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
documentUrl,
|
|
1757
|
-
options.crossOrigin,
|
|
1769
|
+
let claim: PortableResponseClaim | null | undefined;
|
|
1770
|
+
try {
|
|
1771
|
+
const baseUrl = parseIri(documentUrl);
|
|
1772
|
+
const obj = await this.#${property.singularName}_fromJsonLd(
|
|
1773
|
+
document,
|
|
1774
|
+
{
|
|
1775
|
+
documentLoader,
|
|
1776
|
+
contextLoader: snapshot?.loader ?? contextLoader,
|
|
1777
|
+
tracerProvider,
|
|
1778
|
+
baseUrl,
|
|
1779
|
+
}
|
|
1758
1780
|
);
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1781
|
+
if (snapshot == null) {
|
|
1782
|
+
markUnverifiedPortableClaim(obj, url, documentUrl);
|
|
1783
|
+
} else {
|
|
1784
|
+
claim = getPortableResponseClaim(documentUrl, obj.id);
|
|
1785
|
+
}
|
|
1786
|
+
if (claim === undefined) {
|
|
1787
|
+
if (
|
|
1788
|
+
obj?.id != null &&
|
|
1789
|
+
!isTrustedIriOrigin(options, obj.id, baseUrl)
|
|
1790
|
+
) {
|
|
1791
|
+
if (options.crossOrigin === "throw") {
|
|
1792
|
+
throw new Error(
|
|
1793
|
+
"The object's @id (" + obj.id.href + ") has a different origin " +
|
|
1794
|
+
"than the document URL (" + baseUrl.href + "); refusing to return " +
|
|
1795
|
+
"the object. If you want to bypass this check and are aware of" +
|
|
1796
|
+
'the security implications, set the crossOrigin option to "trust".'
|
|
1797
|
+
);
|
|
1798
|
+
}
|
|
1799
|
+
getLogger(["fedify", "vocab"]).warn(
|
|
1800
|
+
"The object's @id ({objectId}) has a different origin than the document " +
|
|
1801
|
+
"URL ({documentUrl}); refusing to return the object. If you want to " +
|
|
1802
|
+
"bypass this check and are aware of the security implications, " +
|
|
1803
|
+
'set the crossOrigin option to "trust".',
|
|
1804
|
+
{ ...fetchResult, objectId: obj.id.href },
|
|
1805
|
+
);
|
|
1806
|
+
span.end();
|
|
1807
|
+
return null;
|
|
1808
|
+
}
|
|
1809
|
+
span.setAttribute("activitypub.object.id", (obj.id ?? url).href);
|
|
1810
|
+
span.setAttribute(
|
|
1811
|
+
"activitypub.object.type",
|
|
1812
|
+
// @ts-ignore: obj.constructor always has a typeId.
|
|
1813
|
+
obj.constructor.typeId.href
|
|
1767
1814
|
);
|
|
1815
|
+
span.end();
|
|
1816
|
+
return obj;
|
|
1768
1817
|
}
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
"
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1818
|
+
} catch (e) {
|
|
1819
|
+
if (options.suppressError) {
|
|
1820
|
+
getLogger(["fedify", "vocab"]).error(
|
|
1821
|
+
"Failed to parse {url}: {error}",
|
|
1822
|
+
{ error: e, url: lookupUrl }
|
|
1823
|
+
);
|
|
1824
|
+
span.end();
|
|
1825
|
+
return null;
|
|
1826
|
+
}
|
|
1827
|
+
span.setStatus({
|
|
1828
|
+
code: SpanStatusCode.ERROR,
|
|
1829
|
+
message: String(e),
|
|
1830
|
+
});
|
|
1831
|
+
span.end();
|
|
1832
|
+
throw e;
|
|
1777
1833
|
}
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
);
|
|
1784
|
-
return obj;
|
|
1785
|
-
} catch (e) {
|
|
1786
|
-
if (options.suppressError) {
|
|
1787
|
-
getLogger(["fedify", "vocab"]).error(
|
|
1788
|
-
"Failed to parse {url}: {error}",
|
|
1789
|
-
{ error: e, url: lookupUrl }
|
|
1790
|
-
);
|
|
1791
|
-
return null;
|
|
1834
|
+
// The document stands for a portable object, so it is verified as
|
|
1835
|
+
// one instead of being trusted because of where it came from:
|
|
1836
|
+
if (claim === null) {
|
|
1837
|
+
span.end();
|
|
1838
|
+
return rejectMalformedCompatibleReference(documentUrl, options);
|
|
1792
1839
|
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1840
|
+
return await dereferencePortable(claim.id, {
|
|
1841
|
+
inferredGateways: claim.inferredGateways,
|
|
1842
|
+
response: fetchResult,
|
|
1843
|
+
contextLoader: snapshot?.loader,
|
|
1796
1844
|
});
|
|
1797
|
-
throw e;
|
|
1798
1845
|
} finally {
|
|
1799
|
-
|
|
1846
|
+
snapshot?.release();
|
|
1800
1847
|
}
|
|
1801
1848
|
});
|
|
1802
1849
|
}
|
|
@@ -1918,7 +1965,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1918
1965
|
} else if (
|
|
1919
1966
|
!isTrustedIriOrigin(options, v.id, ${trustOwner}) ||
|
|
1920
1967
|
isUnsecuredPortableObject(this) ||
|
|
1921
|
-
(
|
|
1968
|
+
mustDereferencePortableObject(this, ${trustOwner}, v.id, options)
|
|
1922
1969
|
) {
|
|
1923
1970
|
v = v.id;
|
|
1924
1971
|
}
|
|
@@ -1927,6 +1974,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1927
1974
|
const fetched =
|
|
1928
1975
|
await this.#fetch${(0, es_toolkit.pascalCase)(property.singularName)}(v, options);
|
|
1929
1976
|
if (fetched == null) return null;
|
|
1977
|
+
// Not cached, so that it is verified when the portable object
|
|
1978
|
+
// policy applies later:
|
|
1979
|
+
if (isUnverifiedPortableClaim(fetched)) return fetched;
|
|
1930
1980
|
this.${await getFieldName(property.uri)}[0] = fetched;
|
|
1931
1981
|
this.${await getFieldName(property.uri, "#_trust")}.add(0);
|
|
1932
1982
|
this._cachedJsonLd = undefined;
|
|
@@ -1962,7 +2012,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1962
2012
|
if (v?.id != null &&
|
|
1963
2013
|
((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
|
|
1964
2014
|
isUnsecuredPortableObject(this) ||
|
|
1965
|
-
(
|
|
2015
|
+
mustDereferencePortableObject(
|
|
2016
|
+
this, ${trustOwner}, v.id, options,
|
|
2017
|
+
)) &&
|
|
1966
2018
|
!this.${await getFieldName(property.uri, "#_trust")}.has(0)) {
|
|
1967
2019
|
if (options.crossOrigin === "throw") {
|
|
1968
2020
|
throw new Error(
|
|
@@ -2039,7 +2091,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
2039
2091
|
} else if (
|
|
2040
2092
|
!isTrustedIriOrigin(options, v.id, ${trustOwner}) ||
|
|
2041
2093
|
isUnsecuredPortableObject(this) ||
|
|
2042
|
-
(
|
|
2094
|
+
mustDereferencePortableObject(this, ${trustOwner}, v.id, options)
|
|
2043
2095
|
) {
|
|
2044
2096
|
v = v.id;
|
|
2045
2097
|
}
|
|
@@ -2048,6 +2100,12 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
2048
2100
|
const fetched =
|
|
2049
2101
|
await this.#fetch${(0, es_toolkit.pascalCase)(property.singularName)}(v, options);
|
|
2050
2102
|
if (fetched == null) continue;
|
|
2103
|
+
// Not cached, so that it is verified when the portable object
|
|
2104
|
+
// policy applies later:
|
|
2105
|
+
if (isUnverifiedPortableClaim(fetched)) {
|
|
2106
|
+
yield fetched;
|
|
2107
|
+
continue;
|
|
2108
|
+
}
|
|
2051
2109
|
vs[i] = fetched;
|
|
2052
2110
|
this.${await getFieldName(property.uri, "#_trust")}.add(i);
|
|
2053
2111
|
this._cachedJsonLd = undefined;
|
|
@@ -2084,7 +2142,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
2084
2142
|
if (v?.id != null &&
|
|
2085
2143
|
((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
|
|
2086
2144
|
isUnsecuredPortableObject(this) ||
|
|
2087
|
-
(
|
|
2145
|
+
mustDereferencePortableObject(
|
|
2146
|
+
this, ${trustOwner}, v.id, options,
|
|
2147
|
+
)) &&
|
|
2088
2148
|
!this.${await getFieldName(property.uri, "#_trust")}.has(i)) {
|
|
2089
2149
|
if (options.crossOrigin === "throw") {
|
|
2090
2150
|
throw new Error(
|
|
@@ -2129,13 +2189,19 @@ const INTERNAL_RUNTIME_IMPORTS = [
|
|
|
2129
2189
|
].join(",\n ");
|
|
2130
2190
|
const PORTABLE_DEREFERENCE_IMPORTS = [
|
|
2131
2191
|
"copyPortableProvenance",
|
|
2192
|
+
"createSnapshotContextLoader",
|
|
2132
2193
|
"dereferencePortableIri",
|
|
2133
|
-
"
|
|
2134
|
-
"isInPortableChain",
|
|
2194
|
+
"getPortableResponseClaim",
|
|
2135
2195
|
"isPortableIri",
|
|
2196
|
+
"isPortableMode",
|
|
2136
2197
|
"isUnsecuredPortableObject",
|
|
2198
|
+
"isUnverifiedPortableClaim",
|
|
2199
|
+
"markUnverifiedPortableClaim",
|
|
2200
|
+
"mustDereferencePortableObject",
|
|
2201
|
+
"parseCompatibleEf61Reference",
|
|
2202
|
+
"type PortableResponseClaim",
|
|
2137
2203
|
"recordPortableReferrer",
|
|
2138
|
-
"
|
|
2204
|
+
"rejectMalformedCompatibleReference",
|
|
2139
2205
|
"warnUnverifiableEmbeddedObject"
|
|
2140
2206
|
].join(",\n ");
|
|
2141
2207
|
const SIGNED_REPRESENTATION_IMPORTS = [
|
package/dist/mod.js
CHANGED
|
@@ -7,7 +7,7 @@ import { parse } from "yaml";
|
|
|
7
7
|
import { pascalCase } from "es-toolkit";
|
|
8
8
|
//#region deno.json
|
|
9
9
|
var name = "@fedify/vocab-tools";
|
|
10
|
-
var version = "2.4.0-dev.
|
|
10
|
+
var version = "2.4.0-dev.2071+8b9dccb9";
|
|
11
11
|
//#endregion
|
|
12
12
|
//#region src/type.ts
|
|
13
13
|
const HEURISTICS_CONTEXTS = [
|
|
@@ -1672,13 +1672,22 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1672
1672
|
${JSON.stringify(version)},
|
|
1673
1673
|
);
|
|
1674
1674
|
return await tracer.startActiveSpan("activitypub.lookup_object", async (span) => {
|
|
1675
|
-
|
|
1675
|
+
const dereferencePortable = async (
|
|
1676
|
+
portableUrl: URL,
|
|
1677
|
+
extra: {
|
|
1678
|
+
inferredGateways?: readonly URL[];
|
|
1679
|
+
response?: RemoteDocument;
|
|
1680
|
+
contextLoader?: DocumentLoader;
|
|
1681
|
+
} = {},
|
|
1682
|
+
) => {
|
|
1676
1683
|
try {
|
|
1677
|
-
const obj = await dereferencePortableIri(
|
|
1684
|
+
const obj = await dereferencePortableIri(portableUrl, {
|
|
1678
1685
|
documentLoader,
|
|
1679
|
-
contextLoader,
|
|
1686
|
+
contextLoader: extra.contextLoader ?? contextLoader,
|
|
1680
1687
|
tracerProvider,
|
|
1681
1688
|
gateways: options.gateways,
|
|
1689
|
+
inferredGateways: extra.inferredGateways,
|
|
1690
|
+
response: extra.response,
|
|
1682
1691
|
verifyPortableObject: options.verifyPortableObject,
|
|
1683
1692
|
referrer: {
|
|
1684
1693
|
object: this,
|
|
@@ -1696,7 +1705,10 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1696
1705
|
}),
|
|
1697
1706
|
});
|
|
1698
1707
|
if (obj != null) {
|
|
1699
|
-
span.setAttribute(
|
|
1708
|
+
span.setAttribute(
|
|
1709
|
+
"activitypub.object.id",
|
|
1710
|
+
(obj.id ?? portableUrl).href,
|
|
1711
|
+
);
|
|
1700
1712
|
span.setAttribute(
|
|
1701
1713
|
"activitypub.object.type",
|
|
1702
1714
|
// @ts-ignore: obj.constructor always has a typeId.
|
|
@@ -1713,12 +1725,20 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1713
1725
|
} finally {
|
|
1714
1726
|
span.end();
|
|
1715
1727
|
}
|
|
1716
|
-
}
|
|
1728
|
+
};
|
|
1729
|
+
if (isPortableIri(url)) return await dereferencePortable(url);
|
|
1717
1730
|
const lookupUrl = formatIri(url);
|
|
1718
|
-
const
|
|
1719
|
-
if (
|
|
1720
|
-
|
|
1721
|
-
|
|
1731
|
+
const portableMode = isPortableMode(this, options);
|
|
1732
|
+
if (portableMode) {
|
|
1733
|
+
const compatible = parseCompatibleEf61Reference(url);
|
|
1734
|
+
if (compatible === null) {
|
|
1735
|
+
span.end();
|
|
1736
|
+
return rejectMalformedCompatibleReference(lookupUrl, options);
|
|
1737
|
+
} else if (compatible != null) {
|
|
1738
|
+
return await dereferencePortable(compatible.id, {
|
|
1739
|
+
inferredGateways: [compatible.gateway],
|
|
1740
|
+
});
|
|
1741
|
+
}
|
|
1722
1742
|
}
|
|
1723
1743
|
let fetchResult: RemoteDocument;
|
|
1724
1744
|
try {
|
|
@@ -1739,63 +1759,90 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1739
1759
|
throw error;
|
|
1740
1760
|
}
|
|
1741
1761
|
const { document, documentUrl } = fetchResult;
|
|
1742
|
-
|
|
1762
|
+
// In portable mode, the document may turn out to be a portable object,
|
|
1763
|
+
// which has to be verified with the same context documents:
|
|
1764
|
+
const snapshot = portableMode
|
|
1765
|
+
? createSnapshotContextLoader(contextLoader)
|
|
1766
|
+
: null;
|
|
1743
1767
|
try {
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
documentUrl,
|
|
1756
|
-
options.crossOrigin,
|
|
1768
|
+
let claim: PortableResponseClaim | null | undefined;
|
|
1769
|
+
try {
|
|
1770
|
+
const baseUrl = parseIri(documentUrl);
|
|
1771
|
+
const obj = await this.#${property.singularName}_fromJsonLd(
|
|
1772
|
+
document,
|
|
1773
|
+
{
|
|
1774
|
+
documentLoader,
|
|
1775
|
+
contextLoader: snapshot?.loader ?? contextLoader,
|
|
1776
|
+
tracerProvider,
|
|
1777
|
+
baseUrl,
|
|
1778
|
+
}
|
|
1757
1779
|
);
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1780
|
+
if (snapshot == null) {
|
|
1781
|
+
markUnverifiedPortableClaim(obj, url, documentUrl);
|
|
1782
|
+
} else {
|
|
1783
|
+
claim = getPortableResponseClaim(documentUrl, obj.id);
|
|
1784
|
+
}
|
|
1785
|
+
if (claim === undefined) {
|
|
1786
|
+
if (
|
|
1787
|
+
obj?.id != null &&
|
|
1788
|
+
!isTrustedIriOrigin(options, obj.id, baseUrl)
|
|
1789
|
+
) {
|
|
1790
|
+
if (options.crossOrigin === "throw") {
|
|
1791
|
+
throw new Error(
|
|
1792
|
+
"The object's @id (" + obj.id.href + ") has a different origin " +
|
|
1793
|
+
"than the document URL (" + baseUrl.href + "); refusing to return " +
|
|
1794
|
+
"the object. If you want to bypass this check and are aware of" +
|
|
1795
|
+
'the security implications, set the crossOrigin option to "trust".'
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
getLogger(["fedify", "vocab"]).warn(
|
|
1799
|
+
"The object's @id ({objectId}) has a different origin than the document " +
|
|
1800
|
+
"URL ({documentUrl}); refusing to return the object. If you want to " +
|
|
1801
|
+
"bypass this check and are aware of the security implications, " +
|
|
1802
|
+
'set the crossOrigin option to "trust".',
|
|
1803
|
+
{ ...fetchResult, objectId: obj.id.href },
|
|
1804
|
+
);
|
|
1805
|
+
span.end();
|
|
1806
|
+
return null;
|
|
1807
|
+
}
|
|
1808
|
+
span.setAttribute("activitypub.object.id", (obj.id ?? url).href);
|
|
1809
|
+
span.setAttribute(
|
|
1810
|
+
"activitypub.object.type",
|
|
1811
|
+
// @ts-ignore: obj.constructor always has a typeId.
|
|
1812
|
+
obj.constructor.typeId.href
|
|
1766
1813
|
);
|
|
1814
|
+
span.end();
|
|
1815
|
+
return obj;
|
|
1767
1816
|
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
"
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1817
|
+
} catch (e) {
|
|
1818
|
+
if (options.suppressError) {
|
|
1819
|
+
getLogger(["fedify", "vocab"]).error(
|
|
1820
|
+
"Failed to parse {url}: {error}",
|
|
1821
|
+
{ error: e, url: lookupUrl }
|
|
1822
|
+
);
|
|
1823
|
+
span.end();
|
|
1824
|
+
return null;
|
|
1825
|
+
}
|
|
1826
|
+
span.setStatus({
|
|
1827
|
+
code: SpanStatusCode.ERROR,
|
|
1828
|
+
message: String(e),
|
|
1829
|
+
});
|
|
1830
|
+
span.end();
|
|
1831
|
+
throw e;
|
|
1776
1832
|
}
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
);
|
|
1783
|
-
return obj;
|
|
1784
|
-
} catch (e) {
|
|
1785
|
-
if (options.suppressError) {
|
|
1786
|
-
getLogger(["fedify", "vocab"]).error(
|
|
1787
|
-
"Failed to parse {url}: {error}",
|
|
1788
|
-
{ error: e, url: lookupUrl }
|
|
1789
|
-
);
|
|
1790
|
-
return null;
|
|
1833
|
+
// The document stands for a portable object, so it is verified as
|
|
1834
|
+
// one instead of being trusted because of where it came from:
|
|
1835
|
+
if (claim === null) {
|
|
1836
|
+
span.end();
|
|
1837
|
+
return rejectMalformedCompatibleReference(documentUrl, options);
|
|
1791
1838
|
}
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1839
|
+
return await dereferencePortable(claim.id, {
|
|
1840
|
+
inferredGateways: claim.inferredGateways,
|
|
1841
|
+
response: fetchResult,
|
|
1842
|
+
contextLoader: snapshot?.loader,
|
|
1795
1843
|
});
|
|
1796
|
-
throw e;
|
|
1797
1844
|
} finally {
|
|
1798
|
-
|
|
1845
|
+
snapshot?.release();
|
|
1799
1846
|
}
|
|
1800
1847
|
});
|
|
1801
1848
|
}
|
|
@@ -1917,7 +1964,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1917
1964
|
} else if (
|
|
1918
1965
|
!isTrustedIriOrigin(options, v.id, ${trustOwner}) ||
|
|
1919
1966
|
isUnsecuredPortableObject(this) ||
|
|
1920
|
-
(
|
|
1967
|
+
mustDereferencePortableObject(this, ${trustOwner}, v.id, options)
|
|
1921
1968
|
) {
|
|
1922
1969
|
v = v.id;
|
|
1923
1970
|
}
|
|
@@ -1926,6 +1973,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1926
1973
|
const fetched =
|
|
1927
1974
|
await this.#fetch${pascalCase(property.singularName)}(v, options);
|
|
1928
1975
|
if (fetched == null) return null;
|
|
1976
|
+
// Not cached, so that it is verified when the portable object
|
|
1977
|
+
// policy applies later:
|
|
1978
|
+
if (isUnverifiedPortableClaim(fetched)) return fetched;
|
|
1929
1979
|
this.${await getFieldName(property.uri)}[0] = fetched;
|
|
1930
1980
|
this.${await getFieldName(property.uri, "#_trust")}.add(0);
|
|
1931
1981
|
this._cachedJsonLd = undefined;
|
|
@@ -1961,7 +2011,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
1961
2011
|
if (v?.id != null &&
|
|
1962
2012
|
((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
|
|
1963
2013
|
isUnsecuredPortableObject(this) ||
|
|
1964
|
-
(
|
|
2014
|
+
mustDereferencePortableObject(
|
|
2015
|
+
this, ${trustOwner}, v.id, options,
|
|
2016
|
+
)) &&
|
|
1965
2017
|
!this.${await getFieldName(property.uri, "#_trust")}.has(0)) {
|
|
1966
2018
|
if (options.crossOrigin === "throw") {
|
|
1967
2019
|
throw new Error(
|
|
@@ -2038,7 +2090,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
2038
2090
|
} else if (
|
|
2039
2091
|
!isTrustedIriOrigin(options, v.id, ${trustOwner}) ||
|
|
2040
2092
|
isUnsecuredPortableObject(this) ||
|
|
2041
|
-
(
|
|
2093
|
+
mustDereferencePortableObject(this, ${trustOwner}, v.id, options)
|
|
2042
2094
|
) {
|
|
2043
2095
|
v = v.id;
|
|
2044
2096
|
}
|
|
@@ -2047,6 +2099,12 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
2047
2099
|
const fetched =
|
|
2048
2100
|
await this.#fetch${pascalCase(property.singularName)}(v, options);
|
|
2049
2101
|
if (fetched == null) continue;
|
|
2102
|
+
// Not cached, so that it is verified when the portable object
|
|
2103
|
+
// policy applies later:
|
|
2104
|
+
if (isUnverifiedPortableClaim(fetched)) {
|
|
2105
|
+
yield fetched;
|
|
2106
|
+
continue;
|
|
2107
|
+
}
|
|
2050
2108
|
vs[i] = fetched;
|
|
2051
2109
|
this.${await getFieldName(property.uri, "#_trust")}.add(i);
|
|
2052
2110
|
this._cachedJsonLd = undefined;
|
|
@@ -2083,7 +2141,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
|
|
|
2083
2141
|
if (v?.id != null &&
|
|
2084
2142
|
((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
|
|
2085
2143
|
isUnsecuredPortableObject(this) ||
|
|
2086
|
-
(
|
|
2144
|
+
mustDereferencePortableObject(
|
|
2145
|
+
this, ${trustOwner}, v.id, options,
|
|
2146
|
+
)) &&
|
|
2087
2147
|
!this.${await getFieldName(property.uri, "#_trust")}.has(i)) {
|
|
2088
2148
|
if (options.crossOrigin === "throw") {
|
|
2089
2149
|
throw new Error(
|
|
@@ -2128,13 +2188,19 @@ const INTERNAL_RUNTIME_IMPORTS = [
|
|
|
2128
2188
|
].join(",\n ");
|
|
2129
2189
|
const PORTABLE_DEREFERENCE_IMPORTS = [
|
|
2130
2190
|
"copyPortableProvenance",
|
|
2191
|
+
"createSnapshotContextLoader",
|
|
2131
2192
|
"dereferencePortableIri",
|
|
2132
|
-
"
|
|
2133
|
-
"isInPortableChain",
|
|
2193
|
+
"getPortableResponseClaim",
|
|
2134
2194
|
"isPortableIri",
|
|
2195
|
+
"isPortableMode",
|
|
2135
2196
|
"isUnsecuredPortableObject",
|
|
2197
|
+
"isUnverifiedPortableClaim",
|
|
2198
|
+
"markUnverifiedPortableClaim",
|
|
2199
|
+
"mustDereferencePortableObject",
|
|
2200
|
+
"parseCompatibleEf61Reference",
|
|
2201
|
+
"type PortableResponseClaim",
|
|
2136
2202
|
"recordPortableReferrer",
|
|
2137
|
-
"
|
|
2203
|
+
"rejectMalformedCompatibleReference",
|
|
2138
2204
|
"warnUnverifiableEmbeddedObject"
|
|
2139
2205
|
].join(",\n ");
|
|
2140
2206
|
const SIGNED_REPRESENTATION_IMPORTS = [
|