@fedify/fedify 2.2.5 → 2.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/{builder-zDJOhWad.mjs → builder-B2wazTqG.mjs} +4 -2
- package/dist/{client-D_1QpnWt.mjs → client-dx126nMS.mjs} +63 -5
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{deno-4Q9ruIMJ.mjs → deno-C-S0PIBP.mjs} +1 -1
- package/dist/{docloader-BHrm7BpO.mjs → docloader-uz9yC9QU.mjs} +2 -2
- package/dist/federation/builder.test.mjs +13 -1
- package/dist/federation/handler.test.mjs +3 -3
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/middleware.test.mjs +6 -6
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.js +1 -1
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +69 -7
- package/dist/{http-CUIxu16z.mjs → http-6X85CU8F.mjs} +2 -2
- package/dist/{http-BTcDrLzD.js → http-CgXWkLVX.js} +17 -7
- package/dist/{http-CK9ElgLS.cjs → http-CpQrMPHt.cjs} +17 -7
- package/dist/{key-CVHsRpwc.mjs → key-CLIL70ZX.mjs} +17 -7
- package/dist/{kv-cache-DI-7Y6VS.cjs → kv-cache-DStmb1rz.cjs} +1 -1
- package/dist/{kv-cache-C_aWsl_r.js → kv-cache-DxK8WCAi.js} +1 -1
- package/dist/{ld-8MkMznIw.mjs → ld-DxefU9PP.mjs} +2 -2
- package/dist/{middleware-DHyZlPpi.mjs → middleware-CG-XVwTH.mjs} +67 -33
- package/dist/{middleware-B373Um8U.cjs → middleware-CfxcGH-c.cjs} +1 -1
- package/dist/{middleware-D7us7Y1k.cjs → middleware-DFvqEsxF.cjs} +63 -27
- package/dist/{middleware-0TW9PJkh.js → middleware-JQfoicJF.js} +62 -26
- package/dist/{middleware-ZavT88mD.mjs → middleware-fOW_Go1o.mjs} +1 -1
- package/dist/mod.cjs +5 -5
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/client.test.mjs +61 -1
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/nodeinfo/mod.cjs +1 -1
- package/dist/nodeinfo/mod.js +1 -1
- package/dist/{owner-BqFf5aUc.mjs → owner-BusoD2MY.mjs} +2 -2
- package/dist/{proof-DkLHCewr.mjs → proof-BfnzsRXs.mjs} +2 -2
- package/dist/{proof-v_hACCAr.js → proof-CDPESdd5.js} +1 -1
- package/dist/{proof-BpBLMdLk.cjs → proof-Z46FMN1e.cjs} +1 -1
- package/dist/{send-Cv34R1iA.mjs → send-mI-UOF8O.mjs} +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +51 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/proof.test.mjs +1 -1
- package/dist/{temporal-DqCyup3d.mjs → temporal-B0fodUhc.mjs} +1 -1
- package/dist/{types-CAY3OdLq.js → types-DTONwNqL.js} +63 -5
- package/dist/{types-KC4QAoxe.cjs → types-m8u9L86X.cjs} +62 -4
- package/dist/utils/docloader.test.mjs +2 -2
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +5 -5
|
@@ -2,25 +2,25 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { n as RouterError } from "./router-CrMLXoOr.mjs";
|
|
5
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
+
import { n as version, t as name } from "./deno-C-S0PIBP.mjs";
|
|
6
6
|
import { t as formatAcceptSignature } from "./accept-CPkZzmGN.mjs";
|
|
7
|
-
import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-
|
|
8
|
-
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-
|
|
9
|
-
import { t as getAuthenticatedDocumentLoader } from "./docloader-
|
|
7
|
+
import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-CLIL70ZX.mjs";
|
|
8
|
+
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-6X85CU8F.mjs";
|
|
9
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-uz9yC9QU.mjs";
|
|
10
10
|
import { n as kvCache } from "./kv-cache-DYsF2MhP.mjs";
|
|
11
|
-
import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-
|
|
12
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-
|
|
11
|
+
import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-DxefU9PP.mjs";
|
|
12
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-BusoD2MY.mjs";
|
|
13
13
|
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-CNmZLixq.mjs";
|
|
14
|
-
import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-
|
|
15
|
-
import { t as getNodeInfo } from "./client-
|
|
14
|
+
import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-BfnzsRXs.mjs";
|
|
15
|
+
import { t as getNodeInfo } from "./client-dx126nMS.mjs";
|
|
16
16
|
import { t as nodeInfoToJson } from "./types-J53Kw7so.mjs";
|
|
17
|
-
import { t as FederationBuilderImpl } from "./builder-
|
|
17
|
+
import { t as FederationBuilderImpl } from "./builder-B2wazTqG.mjs";
|
|
18
18
|
import { t as buildCollectionSynchronizationHeader } from "./collection-D-HqUuA2.mjs";
|
|
19
19
|
import { t as KvKeyCache } from "./keycache-EGATflN-.mjs";
|
|
20
20
|
import { t as acceptsJsonLd } from "./negotiation-SQvQgUqe.mjs";
|
|
21
|
-
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-
|
|
21
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-B0fodUhc.mjs";
|
|
22
22
|
import { t as createExponentialBackoffPolicy } from "./retry-v_sGLH1d.mjs";
|
|
23
|
-
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-
|
|
23
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-mI-UOF8O.mjs";
|
|
24
24
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
25
25
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
26
26
|
import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
|
|
@@ -1697,6 +1697,24 @@ const logger = getLogger([
|
|
|
1697
1697
|
"webfinger",
|
|
1698
1698
|
"server"
|
|
1699
1699
|
]);
|
|
1700
|
+
function getWebFingerSubjectAndAliases({ resourceUrl, actorUri, preferredUsername, acctUsername, host, contextHost }) {
|
|
1701
|
+
const aliases = [];
|
|
1702
|
+
let subject = resourceUrl.href;
|
|
1703
|
+
if (resourceUrl.protocol != "acct:" && preferredUsername != null) {
|
|
1704
|
+
aliases.push(`acct:${preferredUsername}@${host ?? contextHost}`);
|
|
1705
|
+
if (host != null && host !== contextHost) aliases.push(`acct:${preferredUsername}@${contextHost}`);
|
|
1706
|
+
}
|
|
1707
|
+
if (resourceUrl.href !== actorUri.href) aliases.push(actorUri.href);
|
|
1708
|
+
if (resourceUrl.protocol === "acct:" && host != null && host !== contextHost && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
1709
|
+
subject = `acct:${preferredUsername ?? acctUsername}@${host}`;
|
|
1710
|
+
aliases.push(resourceUrl.href);
|
|
1711
|
+
if (preferredUsername != null && preferredUsername !== "" && preferredUsername !== acctUsername) aliases.push(`acct:${preferredUsername}@${contextHost}`);
|
|
1712
|
+
}
|
|
1713
|
+
return {
|
|
1714
|
+
subject,
|
|
1715
|
+
aliases
|
|
1716
|
+
};
|
|
1717
|
+
}
|
|
1700
1718
|
/**
|
|
1701
1719
|
* Handles a WebFinger request. You would not typically call this function
|
|
1702
1720
|
* directly, but instead use {@link Federation.fetch} method.
|
|
@@ -1751,6 +1769,7 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
1751
1769
|
return identifier;
|
|
1752
1770
|
}
|
|
1753
1771
|
let identifier = null;
|
|
1772
|
+
let acctUsername = null;
|
|
1754
1773
|
const uriParsed = context.parseUri(resourceUrl);
|
|
1755
1774
|
if (uriParsed?.type != "actor") {
|
|
1756
1775
|
const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
|
|
@@ -1764,8 +1783,9 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
1764
1783
|
const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
|
|
1765
1784
|
if (normalizedHost != context.url.host && normalizedHost != host) return await onNotFound(request);
|
|
1766
1785
|
else {
|
|
1767
|
-
|
|
1768
|
-
|
|
1786
|
+
acctUsername = match[1];
|
|
1787
|
+
identifier = await mapUsernameToIdentifier(acctUsername);
|
|
1788
|
+
resourceUrl = new URL(`acct:${acctUsername}@${normalizedHost}`);
|
|
1769
1789
|
}
|
|
1770
1790
|
}
|
|
1771
1791
|
} else identifier = uriParsed.identifier;
|
|
@@ -1779,9 +1799,10 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
1779
1799
|
status: 410,
|
|
1780
1800
|
headers: { "Access-Control-Allow-Origin": "*" }
|
|
1781
1801
|
});
|
|
1802
|
+
const actorUri = context.getActorUri(identifier);
|
|
1782
1803
|
const links = [{
|
|
1783
1804
|
rel: "self",
|
|
1784
|
-
href:
|
|
1805
|
+
href: actorUri.href,
|
|
1785
1806
|
type: "application/activity+json"
|
|
1786
1807
|
}];
|
|
1787
1808
|
for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
|
|
@@ -1805,23 +1826,19 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
1805
1826
|
const customLinks = await webFingerLinksDispatcher(context, resourceUrl);
|
|
1806
1827
|
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
1807
1828
|
}
|
|
1808
|
-
const aliases =
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
}
|
|
1819
|
-
const jrd = {
|
|
1820
|
-
subject: resourceUrl.href,
|
|
1829
|
+
const { subject, aliases } = getWebFingerSubjectAndAliases({
|
|
1830
|
+
resourceUrl,
|
|
1831
|
+
actorUri,
|
|
1832
|
+
preferredUsername: actor.preferredUsername,
|
|
1833
|
+
acctUsername,
|
|
1834
|
+
host,
|
|
1835
|
+
contextHost: context.url.host
|
|
1836
|
+
});
|
|
1837
|
+
return new Response(JSON.stringify({
|
|
1838
|
+
subject,
|
|
1821
1839
|
aliases,
|
|
1822
1840
|
links
|
|
1823
|
-
}
|
|
1824
|
-
return new Response(JSON.stringify(jrd), { headers: {
|
|
1841
|
+
}), { headers: {
|
|
1825
1842
|
"Content-Type": "application/jrd+json",
|
|
1826
1843
|
"Access-Control-Allow-Origin": "*"
|
|
1827
1844
|
} });
|
|
@@ -1840,6 +1857,15 @@ function isPermanentRemoteContextError(error) {
|
|
|
1840
1857
|
function isPermanentInboxParseError(error) {
|
|
1841
1858
|
return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || isInvalidUrlTypeError(error));
|
|
1842
1859
|
}
|
|
1860
|
+
function hasLinkedDataSignatureJsonLdProcessingError(error) {
|
|
1861
|
+
if (error.message.startsWith("Maximum deep iterations exceeded")) return true;
|
|
1862
|
+
const cause = error.cause instanceof Error ? error.cause : error.details?.cause;
|
|
1863
|
+
if (error.name === "jsonld.InvalidUrl" && error.details?.code === "loading remote context failed" && cause instanceof Error) return cause.message.startsWith("Maximum deep iterations exceeded") || cause.name.startsWith("jsonld.");
|
|
1864
|
+
return error.name !== "jsonld.InvalidUrl" && error.name.startsWith("jsonld.");
|
|
1865
|
+
}
|
|
1866
|
+
function isLinkedDataSignatureJsonLdProcessingError(error) {
|
|
1867
|
+
return error instanceof Error && hasLinkedDataSignatureJsonLdProcessingError(error);
|
|
1868
|
+
}
|
|
1843
1869
|
/**
|
|
1844
1870
|
* Create a new {@link Federation} instance.
|
|
1845
1871
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -2497,10 +2523,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2497
2523
|
privateKey: pair.privateKey
|
|
2498
2524
|
}))
|
|
2499
2525
|
});
|
|
2500
|
-
else
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2526
|
+
else try {
|
|
2527
|
+
jsonLd = await signJsonLd(jsonLd, rsaKey.privateKey, rsaKey.keyId, {
|
|
2528
|
+
contextLoader,
|
|
2529
|
+
tracerProvider: this.tracerProvider
|
|
2530
|
+
});
|
|
2531
|
+
} catch (error) {
|
|
2532
|
+
if (!isLinkedDataSignatureJsonLdProcessingError(error)) throw error;
|
|
2533
|
+
logger.warn("Failed to create a Linked Data signature for the activity {activityId}. The activity will be sent without a Linked Data signature.", {
|
|
2534
|
+
activityId,
|
|
2535
|
+
error
|
|
2536
|
+
});
|
|
2537
|
+
}
|
|
2504
2538
|
if (!hasProof) logger.warn("No supported key found to create a proof for the activity {activityId}. The activity will be sent without a proof. In order to create a proof, at least one Ed25519 key must be provided.", {
|
|
2505
2539
|
activityId,
|
|
2506
2540
|
keys: keys.map((pair) => ({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
|
-
const require_middleware = require("./middleware-
|
|
3
|
+
const require_middleware = require("./middleware-DFvqEsxF.cjs");
|
|
4
4
|
exports.FederationImpl = require_middleware.FederationImpl;
|
|
@@ -2,10 +2,10 @@ const { Temporal } = require("@js-temporal/polyfill");
|
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
const require_chunk = require("./chunk-DDcVe30Y.cjs");
|
|
4
4
|
const require_transformers = require("./transformers-NeAONrAq.cjs");
|
|
5
|
-
const require_http = require("./http-
|
|
6
|
-
const require_proof = require("./proof-
|
|
7
|
-
const require_types = require("./types-
|
|
8
|
-
const require_kv_cache = require("./kv-cache-
|
|
5
|
+
const require_http = require("./http-CpQrMPHt.cjs");
|
|
6
|
+
const require_proof = require("./proof-Z46FMN1e.cjs");
|
|
7
|
+
const require_types = require("./types-m8u9L86X.cjs");
|
|
8
|
+
const require_kv_cache = require("./kv-cache-DStmb1rz.cjs");
|
|
9
9
|
let _logtape_logtape = require("@logtape/logtape");
|
|
10
10
|
let _fedify_vocab = require("@fedify/vocab");
|
|
11
11
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
@@ -212,7 +212,7 @@ var FederationBuilderImpl = class {
|
|
|
212
212
|
this.collectionTypeIds = {};
|
|
213
213
|
}
|
|
214
214
|
async build(options) {
|
|
215
|
-
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-
|
|
215
|
+
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-CfxcGH-c.cjs"));
|
|
216
216
|
const f = new FederationImpl(options);
|
|
217
217
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
218
218
|
f.router = this.router.clone();
|
|
@@ -223,6 +223,8 @@ var FederationBuilderImpl = class {
|
|
|
223
223
|
f.webFingerLinksDispatcher = this.webFingerLinksDispatcher;
|
|
224
224
|
f.objectCallbacks = { ...this.objectCallbacks };
|
|
225
225
|
f.objectTypeIds = { ...this.objectTypeIds };
|
|
226
|
+
f.collectionCallbacks = { ...this.collectionCallbacks };
|
|
227
|
+
f.collectionTypeIds = { ...this.collectionTypeIds };
|
|
226
228
|
f.inboxPath = this.inboxPath;
|
|
227
229
|
f.outboxPath = this.outboxPath;
|
|
228
230
|
f.inboxCallbacks = this.inboxCallbacks == null ? void 0 : { ...this.inboxCallbacks };
|
|
@@ -2808,6 +2810,24 @@ const logger = (0, _logtape_logtape.getLogger)([
|
|
|
2808
2810
|
"webfinger",
|
|
2809
2811
|
"server"
|
|
2810
2812
|
]);
|
|
2813
|
+
function getWebFingerSubjectAndAliases({ resourceUrl, actorUri, preferredUsername, acctUsername, host, contextHost }) {
|
|
2814
|
+
const aliases = [];
|
|
2815
|
+
let subject = resourceUrl.href;
|
|
2816
|
+
if (resourceUrl.protocol != "acct:" && preferredUsername != null) {
|
|
2817
|
+
aliases.push(`acct:${preferredUsername}@${host ?? contextHost}`);
|
|
2818
|
+
if (host != null && host !== contextHost) aliases.push(`acct:${preferredUsername}@${contextHost}`);
|
|
2819
|
+
}
|
|
2820
|
+
if (resourceUrl.href !== actorUri.href) aliases.push(actorUri.href);
|
|
2821
|
+
if (resourceUrl.protocol === "acct:" && host != null && host !== contextHost && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
2822
|
+
subject = `acct:${preferredUsername ?? acctUsername}@${host}`;
|
|
2823
|
+
aliases.push(resourceUrl.href);
|
|
2824
|
+
if (preferredUsername != null && preferredUsername !== "" && preferredUsername !== acctUsername) aliases.push(`acct:${preferredUsername}@${contextHost}`);
|
|
2825
|
+
}
|
|
2826
|
+
return {
|
|
2827
|
+
subject,
|
|
2828
|
+
aliases
|
|
2829
|
+
};
|
|
2830
|
+
}
|
|
2811
2831
|
/**
|
|
2812
2832
|
* Handles a WebFinger request. You would not typically call this function
|
|
2813
2833
|
* directly, but instead use {@link Federation.fetch} method.
|
|
@@ -2862,6 +2882,7 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2862
2882
|
return identifier;
|
|
2863
2883
|
}
|
|
2864
2884
|
let identifier = null;
|
|
2885
|
+
let acctUsername = null;
|
|
2865
2886
|
const uriParsed = context.parseUri(resourceUrl);
|
|
2866
2887
|
if (uriParsed?.type != "actor") {
|
|
2867
2888
|
const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
|
|
@@ -2875,8 +2896,9 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2875
2896
|
const normalizedHost = portMatch == null ? (0, node_url.domainToASCII)(match[2].toLowerCase()) : (0, node_url.domainToASCII)(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
|
|
2876
2897
|
if (normalizedHost != context.url.host && normalizedHost != host) return await onNotFound(request);
|
|
2877
2898
|
else {
|
|
2878
|
-
|
|
2879
|
-
|
|
2899
|
+
acctUsername = match[1];
|
|
2900
|
+
identifier = await mapUsernameToIdentifier(acctUsername);
|
|
2901
|
+
resourceUrl = new URL(`acct:${acctUsername}@${normalizedHost}`);
|
|
2880
2902
|
}
|
|
2881
2903
|
}
|
|
2882
2904
|
} else identifier = uriParsed.identifier;
|
|
@@ -2890,9 +2912,10 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2890
2912
|
status: 410,
|
|
2891
2913
|
headers: { "Access-Control-Allow-Origin": "*" }
|
|
2892
2914
|
});
|
|
2915
|
+
const actorUri = context.getActorUri(identifier);
|
|
2893
2916
|
const links = [{
|
|
2894
2917
|
rel: "self",
|
|
2895
|
-
href:
|
|
2918
|
+
href: actorUri.href,
|
|
2896
2919
|
type: "application/activity+json"
|
|
2897
2920
|
}];
|
|
2898
2921
|
for (const url of actor.urls) if (url instanceof _fedify_vocab.Link && url.href != null) links.push({
|
|
@@ -2916,23 +2939,19 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2916
2939
|
const customLinks = await webFingerLinksDispatcher(context, resourceUrl);
|
|
2917
2940
|
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
2918
2941
|
}
|
|
2919
|
-
const aliases =
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
}
|
|
2930
|
-
const jrd = {
|
|
2931
|
-
subject: resourceUrl.href,
|
|
2942
|
+
const { subject, aliases } = getWebFingerSubjectAndAliases({
|
|
2943
|
+
resourceUrl,
|
|
2944
|
+
actorUri,
|
|
2945
|
+
preferredUsername: actor.preferredUsername,
|
|
2946
|
+
acctUsername,
|
|
2947
|
+
host,
|
|
2948
|
+
contextHost: context.url.host
|
|
2949
|
+
});
|
|
2950
|
+
return new Response(JSON.stringify({
|
|
2951
|
+
subject,
|
|
2932
2952
|
aliases,
|
|
2933
2953
|
links
|
|
2934
|
-
}
|
|
2935
|
-
return new Response(JSON.stringify(jrd), { headers: {
|
|
2954
|
+
}), { headers: {
|
|
2936
2955
|
"Content-Type": "application/jrd+json",
|
|
2937
2956
|
"Access-Control-Allow-Origin": "*"
|
|
2938
2957
|
} });
|
|
@@ -2951,6 +2970,15 @@ function isPermanentRemoteContextError(error) {
|
|
|
2951
2970
|
function isPermanentInboxParseError(error) {
|
|
2952
2971
|
return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof require_proof.InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || require_proof.isInvalidUrlTypeError(error));
|
|
2953
2972
|
}
|
|
2973
|
+
function hasLinkedDataSignatureJsonLdProcessingError(error) {
|
|
2974
|
+
if (error.message.startsWith("Maximum deep iterations exceeded")) return true;
|
|
2975
|
+
const cause = error.cause instanceof Error ? error.cause : error.details?.cause;
|
|
2976
|
+
if (error.name === "jsonld.InvalidUrl" && error.details?.code === "loading remote context failed" && cause instanceof Error) return cause.message.startsWith("Maximum deep iterations exceeded") || cause.name.startsWith("jsonld.");
|
|
2977
|
+
return error.name !== "jsonld.InvalidUrl" && error.name.startsWith("jsonld.");
|
|
2978
|
+
}
|
|
2979
|
+
function isLinkedDataSignatureJsonLdProcessingError(error) {
|
|
2980
|
+
return error instanceof Error && hasLinkedDataSignatureJsonLdProcessingError(error);
|
|
2981
|
+
}
|
|
2954
2982
|
/**
|
|
2955
2983
|
* Create a new {@link Federation} instance.
|
|
2956
2984
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -3608,10 +3636,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3608
3636
|
privateKey: pair.privateKey
|
|
3609
3637
|
}))
|
|
3610
3638
|
});
|
|
3611
|
-
else
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3639
|
+
else try {
|
|
3640
|
+
jsonLd = await require_proof.signJsonLd(jsonLd, rsaKey.privateKey, rsaKey.keyId, {
|
|
3641
|
+
contextLoader,
|
|
3642
|
+
tracerProvider: this.tracerProvider
|
|
3643
|
+
});
|
|
3644
|
+
} catch (error) {
|
|
3645
|
+
if (!isLinkedDataSignatureJsonLdProcessingError(error)) throw error;
|
|
3646
|
+
logger.warn("Failed to create a Linked Data signature for the activity {activityId}. The activity will be sent without a Linked Data signature.", {
|
|
3647
|
+
activityId,
|
|
3648
|
+
error
|
|
3649
|
+
});
|
|
3650
|
+
}
|
|
3615
3651
|
if (!hasProof) logger.warn("No supported key found to create a proof for the activity {activityId}. The activity will be sent without a proof. In order to create a proof, at least one Ed25519 key must be provided.", {
|
|
3616
3652
|
activityId,
|
|
3617
3653
|
keys: keys.map((pair) => ({
|
|
@@ -2,10 +2,10 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { t as __exportAll } from "./chunk-CRNNMoPX.js";
|
|
4
4
|
import { r as getDefaultActivityTransformers } from "./transformers-BGMIq1cs.js";
|
|
5
|
-
import { _ as version, a as verifyRequestDetailed, d as validateCryptoKey, f as formatAcceptSignature, g as name, i as verifyRequest, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, u as importJwk } from "./http-
|
|
6
|
-
import { _ as hasSignatureLike, b as signJsonLd, c as getKeyOwner, f as compactJsonLd, g as hasSignature, h as getNormalizationContextLoader, i as verifyObject, l as InvalidContextReferenceError, m as detachSignature, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, r as signObject, s as doesActorOwnKey, u as assertSafeJsonLd, v as isClearlyMalformedContextReference, w as wrapContextLoaderForJsonLd, x as verifyCompactJsonLd, y as isInvalidUrlTypeError } from "./proof-
|
|
7
|
-
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
5
|
+
import { _ as version, a as verifyRequestDetailed, d as validateCryptoKey, f as formatAcceptSignature, g as name, i as verifyRequest, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, u as importJwk } from "./http-CgXWkLVX.js";
|
|
6
|
+
import { _ as hasSignatureLike, b as signJsonLd, c as getKeyOwner, f as compactJsonLd, g as hasSignature, h as getNormalizationContextLoader, i as verifyObject, l as InvalidContextReferenceError, m as detachSignature, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, r as signObject, s as doesActorOwnKey, u as assertSafeJsonLd, v as isClearlyMalformedContextReference, w as wrapContextLoaderForJsonLd, x as verifyCompactJsonLd, y as isInvalidUrlTypeError } from "./proof-CDPESdd5.js";
|
|
7
|
+
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-DTONwNqL.js";
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DxK8WCAi.js";
|
|
9
9
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
10
10
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
11
11
|
import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
|
|
@@ -222,6 +222,8 @@ var FederationBuilderImpl = class {
|
|
|
222
222
|
f.webFingerLinksDispatcher = this.webFingerLinksDispatcher;
|
|
223
223
|
f.objectCallbacks = { ...this.objectCallbacks };
|
|
224
224
|
f.objectTypeIds = { ...this.objectTypeIds };
|
|
225
|
+
f.collectionCallbacks = { ...this.collectionCallbacks };
|
|
226
|
+
f.collectionTypeIds = { ...this.collectionTypeIds };
|
|
225
227
|
f.inboxPath = this.inboxPath;
|
|
226
228
|
f.outboxPath = this.outboxPath;
|
|
227
229
|
f.inboxCallbacks = this.inboxCallbacks == null ? void 0 : { ...this.inboxCallbacks };
|
|
@@ -2807,6 +2809,24 @@ const logger = getLogger([
|
|
|
2807
2809
|
"webfinger",
|
|
2808
2810
|
"server"
|
|
2809
2811
|
]);
|
|
2812
|
+
function getWebFingerSubjectAndAliases({ resourceUrl, actorUri, preferredUsername, acctUsername, host, contextHost }) {
|
|
2813
|
+
const aliases = [];
|
|
2814
|
+
let subject = resourceUrl.href;
|
|
2815
|
+
if (resourceUrl.protocol != "acct:" && preferredUsername != null) {
|
|
2816
|
+
aliases.push(`acct:${preferredUsername}@${host ?? contextHost}`);
|
|
2817
|
+
if (host != null && host !== contextHost) aliases.push(`acct:${preferredUsername}@${contextHost}`);
|
|
2818
|
+
}
|
|
2819
|
+
if (resourceUrl.href !== actorUri.href) aliases.push(actorUri.href);
|
|
2820
|
+
if (resourceUrl.protocol === "acct:" && host != null && host !== contextHost && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
2821
|
+
subject = `acct:${preferredUsername ?? acctUsername}@${host}`;
|
|
2822
|
+
aliases.push(resourceUrl.href);
|
|
2823
|
+
if (preferredUsername != null && preferredUsername !== "" && preferredUsername !== acctUsername) aliases.push(`acct:${preferredUsername}@${contextHost}`);
|
|
2824
|
+
}
|
|
2825
|
+
return {
|
|
2826
|
+
subject,
|
|
2827
|
+
aliases
|
|
2828
|
+
};
|
|
2829
|
+
}
|
|
2810
2830
|
/**
|
|
2811
2831
|
* Handles a WebFinger request. You would not typically call this function
|
|
2812
2832
|
* directly, but instead use {@link Federation.fetch} method.
|
|
@@ -2861,6 +2881,7 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2861
2881
|
return identifier;
|
|
2862
2882
|
}
|
|
2863
2883
|
let identifier = null;
|
|
2884
|
+
let acctUsername = null;
|
|
2864
2885
|
const uriParsed = context.parseUri(resourceUrl);
|
|
2865
2886
|
if (uriParsed?.type != "actor") {
|
|
2866
2887
|
const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
|
|
@@ -2874,8 +2895,9 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2874
2895
|
const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
|
|
2875
2896
|
if (normalizedHost != context.url.host && normalizedHost != host) return await onNotFound(request);
|
|
2876
2897
|
else {
|
|
2877
|
-
|
|
2878
|
-
|
|
2898
|
+
acctUsername = match[1];
|
|
2899
|
+
identifier = await mapUsernameToIdentifier(acctUsername);
|
|
2900
|
+
resourceUrl = new URL(`acct:${acctUsername}@${normalizedHost}`);
|
|
2879
2901
|
}
|
|
2880
2902
|
}
|
|
2881
2903
|
} else identifier = uriParsed.identifier;
|
|
@@ -2889,9 +2911,10 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2889
2911
|
status: 410,
|
|
2890
2912
|
headers: { "Access-Control-Allow-Origin": "*" }
|
|
2891
2913
|
});
|
|
2914
|
+
const actorUri = context.getActorUri(identifier);
|
|
2892
2915
|
const links = [{
|
|
2893
2916
|
rel: "self",
|
|
2894
|
-
href:
|
|
2917
|
+
href: actorUri.href,
|
|
2895
2918
|
type: "application/activity+json"
|
|
2896
2919
|
}];
|
|
2897
2920
|
for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
|
|
@@ -2915,23 +2938,19 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2915
2938
|
const customLinks = await webFingerLinksDispatcher(context, resourceUrl);
|
|
2916
2939
|
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
2917
2940
|
}
|
|
2918
|
-
const aliases =
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
}
|
|
2929
|
-
const jrd = {
|
|
2930
|
-
subject: resourceUrl.href,
|
|
2941
|
+
const { subject, aliases } = getWebFingerSubjectAndAliases({
|
|
2942
|
+
resourceUrl,
|
|
2943
|
+
actorUri,
|
|
2944
|
+
preferredUsername: actor.preferredUsername,
|
|
2945
|
+
acctUsername,
|
|
2946
|
+
host,
|
|
2947
|
+
contextHost: context.url.host
|
|
2948
|
+
});
|
|
2949
|
+
return new Response(JSON.stringify({
|
|
2950
|
+
subject,
|
|
2931
2951
|
aliases,
|
|
2932
2952
|
links
|
|
2933
|
-
}
|
|
2934
|
-
return new Response(JSON.stringify(jrd), { headers: {
|
|
2953
|
+
}), { headers: {
|
|
2935
2954
|
"Content-Type": "application/jrd+json",
|
|
2936
2955
|
"Access-Control-Allow-Origin": "*"
|
|
2937
2956
|
} });
|
|
@@ -2958,6 +2977,15 @@ function isPermanentRemoteContextError(error) {
|
|
|
2958
2977
|
function isPermanentInboxParseError(error) {
|
|
2959
2978
|
return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || isInvalidUrlTypeError(error));
|
|
2960
2979
|
}
|
|
2980
|
+
function hasLinkedDataSignatureJsonLdProcessingError(error) {
|
|
2981
|
+
if (error.message.startsWith("Maximum deep iterations exceeded")) return true;
|
|
2982
|
+
const cause = error.cause instanceof Error ? error.cause : error.details?.cause;
|
|
2983
|
+
if (error.name === "jsonld.InvalidUrl" && error.details?.code === "loading remote context failed" && cause instanceof Error) return cause.message.startsWith("Maximum deep iterations exceeded") || cause.name.startsWith("jsonld.");
|
|
2984
|
+
return error.name !== "jsonld.InvalidUrl" && error.name.startsWith("jsonld.");
|
|
2985
|
+
}
|
|
2986
|
+
function isLinkedDataSignatureJsonLdProcessingError(error) {
|
|
2987
|
+
return error instanceof Error && hasLinkedDataSignatureJsonLdProcessingError(error);
|
|
2988
|
+
}
|
|
2961
2989
|
/**
|
|
2962
2990
|
* Create a new {@link Federation} instance.
|
|
2963
2991
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -3615,10 +3643,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3615
3643
|
privateKey: pair.privateKey
|
|
3616
3644
|
}))
|
|
3617
3645
|
});
|
|
3618
|
-
else
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3646
|
+
else try {
|
|
3647
|
+
jsonLd = await signJsonLd(jsonLd, rsaKey.privateKey, rsaKey.keyId, {
|
|
3648
|
+
contextLoader,
|
|
3649
|
+
tracerProvider: this.tracerProvider
|
|
3650
|
+
});
|
|
3651
|
+
} catch (error) {
|
|
3652
|
+
if (!isLinkedDataSignatureJsonLdProcessingError(error)) throw error;
|
|
3653
|
+
logger.warn("Failed to create a Linked Data signature for the activity {activityId}. The activity will be sent without a Linked Data signature.", {
|
|
3654
|
+
activityId,
|
|
3655
|
+
error
|
|
3656
|
+
});
|
|
3657
|
+
}
|
|
3622
3658
|
if (!hasProof) logger.warn("No supported key found to create a proof for the activity {activityId}. The activity will be sent without a proof. In order to create a proof, at least one Ed25519 key must be provided.", {
|
|
3623
3659
|
activityId,
|
|
3624
3660
|
keys: keys.map((pair) => ({
|
package/dist/mod.cjs
CHANGED
|
@@ -4,11 +4,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
4
4
|
require("./chunk-DDcVe30Y.cjs");
|
|
5
5
|
const require_transformers = require("./transformers-NeAONrAq.cjs");
|
|
6
6
|
require("./compat/mod.cjs");
|
|
7
|
-
const require_http = require("./http-
|
|
8
|
-
const require_middleware = require("./middleware-
|
|
9
|
-
const require_proof = require("./proof-
|
|
10
|
-
const require_types = require("./types-
|
|
11
|
-
const require_kv_cache = require("./kv-cache-
|
|
7
|
+
const require_http = require("./http-CpQrMPHt.cjs");
|
|
8
|
+
const require_middleware = require("./middleware-DFvqEsxF.cjs");
|
|
9
|
+
const require_proof = require("./proof-Z46FMN1e.cjs");
|
|
10
|
+
const require_types = require("./types-m8u9L86X.cjs");
|
|
11
|
+
const require_kv_cache = require("./kv-cache-DStmb1rz.cjs");
|
|
12
12
|
const require_federation_mod = require("./federation/mod.cjs");
|
|
13
13
|
require("./nodeinfo/mod.cjs");
|
|
14
14
|
require("./runtime/mod.cjs");
|
package/dist/mod.js
CHANGED
|
@@ -3,11 +3,11 @@ import { URLPattern } from "urlpattern-polyfill";
|
|
|
3
3
|
import "./chunk-CRNNMoPX.js";
|
|
4
4
|
import { n as autoIdAssigner, r as getDefaultActivityTransformers, t as actorDehydrator } from "./transformers-BGMIq1cs.js";
|
|
5
5
|
import "./compat/mod.js";
|
|
6
|
-
import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "./http-
|
|
7
|
-
import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "./middleware-
|
|
8
|
-
import { C as verifySignature, S as verifyJsonLd, _ as hasSignatureLike, a as verifyProof, b as signJsonLd, c as getKeyOwner, d as attachSignature, i as verifyObject, m as detachSignature, n as hasProofLike, p as createSignature, r as signObject, s as doesActorOwnKey, t as createProof } from "./proof-
|
|
9
|
-
import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "./types-
|
|
10
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
6
|
+
import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "./http-CgXWkLVX.js";
|
|
7
|
+
import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "./middleware-JQfoicJF.js";
|
|
8
|
+
import { C as verifySignature, S as verifyJsonLd, _ as hasSignatureLike, a as verifyProof, b as signJsonLd, c as getKeyOwner, d as attachSignature, i as verifyObject, m as detachSignature, n as hasProofLike, p as createSignature, r as signObject, s as doesActorOwnKey, t as createProof } from "./proof-CDPESdd5.js";
|
|
9
|
+
import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "./types-DTONwNqL.js";
|
|
10
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DxK8WCAi.js";
|
|
11
11
|
import { InProcessMessageQueue, MemoryKvStore, ParallelMessageQueue } from "./federation/mod.js";
|
|
12
12
|
import "./nodeinfo/mod.js";
|
|
13
13
|
import "./runtime/mod.js";
|
|
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
|
|
|
4
4
|
import { t as esm_default } from "../esm-DVILvP5e.mjs";
|
|
5
5
|
import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
6
6
|
import "../std__assert-CRDpx_HF.mjs";
|
|
7
|
-
import { a as parseProtocol, c as parseUsage, i as parseOutboundService, n as parseInboundService, o as parseServices, r as parseNodeInfo, s as parseSoftware, t as getNodeInfo } from "../client-
|
|
7
|
+
import { a as parseProtocol, c as parseUsage, i as parseOutboundService, n as parseInboundService, o as parseServices, r as parseNodeInfo, s as parseSoftware, t as getNodeInfo } from "../client-dx126nMS.mjs";
|
|
8
8
|
import { test } from "@fedify/fixture";
|
|
9
9
|
//#region src/nodeinfo/client.test.ts
|
|
10
10
|
test("getNodeInfo()", async (t) => {
|
|
@@ -62,6 +62,66 @@ test("getNodeInfo()", async (t) => {
|
|
|
62
62
|
});
|
|
63
63
|
esm_default.hardReset();
|
|
64
64
|
});
|
|
65
|
+
test("getNodeInfo() blocks SSRF", async (t) => {
|
|
66
|
+
esm_default.spyGlobal();
|
|
67
|
+
await t.step("link href pointing to a loopback address", async () => {
|
|
68
|
+
esm_default.removeRoutes();
|
|
69
|
+
esm_default.get("https://example.com/.well-known/nodeinfo", { body: { links: [{
|
|
70
|
+
rel: "http://nodeinfo.diaspora.software/ns/schema/2.1",
|
|
71
|
+
href: "http://127.0.0.1:8080/internal"
|
|
72
|
+
}] } });
|
|
73
|
+
let internalFetched = false;
|
|
74
|
+
esm_default.get("http://127.0.0.1:8080/internal", () => {
|
|
75
|
+
internalFetched = true;
|
|
76
|
+
return { body: { secret: "INTERNAL_DATA_LEAKED" } };
|
|
77
|
+
});
|
|
78
|
+
assertEquals(await getNodeInfo("https://example.com/", { parse: "none" }), void 0);
|
|
79
|
+
assertEquals(internalFetched, false);
|
|
80
|
+
});
|
|
81
|
+
await t.step("link href using a data: URL", async () => {
|
|
82
|
+
esm_default.removeRoutes();
|
|
83
|
+
esm_default.get("https://example.com/.well-known/nodeinfo", { body: { links: [{
|
|
84
|
+
rel: "http://nodeinfo.diaspora.software/ns/schema/2.0",
|
|
85
|
+
href: "data:application/json,{\"software\":{\"name\":\"x\"}}"
|
|
86
|
+
}] } });
|
|
87
|
+
assertEquals(await getNodeInfo("https://example.com/", { parse: "none" }), void 0);
|
|
88
|
+
});
|
|
89
|
+
await t.step("redirect to a private address", async () => {
|
|
90
|
+
esm_default.removeRoutes();
|
|
91
|
+
esm_default.get("https://example.com/.well-known/nodeinfo", { body: { links: [{
|
|
92
|
+
rel: "http://nodeinfo.diaspora.software/ns/schema/2.1",
|
|
93
|
+
href: "https://example.com/nodeinfo/2.1"
|
|
94
|
+
}] } });
|
|
95
|
+
esm_default.get("https://example.com/nodeinfo/2.1", {
|
|
96
|
+
status: 302,
|
|
97
|
+
headers: { Location: "https://127.0.0.1:8080/internal" }
|
|
98
|
+
});
|
|
99
|
+
let internalFetched = false;
|
|
100
|
+
esm_default.get("https://127.0.0.1:8080/internal", () => {
|
|
101
|
+
internalFetched = true;
|
|
102
|
+
return { body: { secret: "INTERNAL_DATA_LEAKED" } };
|
|
103
|
+
});
|
|
104
|
+
assertEquals(await getNodeInfo("https://example.com/", { parse: "none" }), void 0);
|
|
105
|
+
assertEquals(internalFetched, false);
|
|
106
|
+
});
|
|
107
|
+
await t.step("direct fetch of a private address", async () => {
|
|
108
|
+
esm_default.removeRoutes();
|
|
109
|
+
let internalFetched = false;
|
|
110
|
+
esm_default.get("http://127.0.0.1:8080/nodeinfo", () => {
|
|
111
|
+
internalFetched = true;
|
|
112
|
+
return { body: { software: {
|
|
113
|
+
name: "x",
|
|
114
|
+
version: "1.0.0"
|
|
115
|
+
} } };
|
|
116
|
+
});
|
|
117
|
+
assertEquals(await getNodeInfo("http://127.0.0.1:8080/nodeinfo", {
|
|
118
|
+
direct: true,
|
|
119
|
+
parse: "none"
|
|
120
|
+
}), void 0);
|
|
121
|
+
assertEquals(internalFetched, false);
|
|
122
|
+
});
|
|
123
|
+
esm_default.hardReset();
|
|
124
|
+
});
|
|
65
125
|
test("parseNodeInfo()", () => {
|
|
66
126
|
const input = {
|
|
67
127
|
software: {
|
|
@@ -5,7 +5,7 @@ import { r as createRequestContext } from "../context-Dk_tacqz.mjs";
|
|
|
5
5
|
import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
6
6
|
import "../std__assert-CRDpx_HF.mjs";
|
|
7
7
|
import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
|
|
8
|
-
import { _ as handleNodeInfoJrd, g as handleNodeInfo, o as createFederation } from "../middleware-
|
|
8
|
+
import { _ as handleNodeInfoJrd, g as handleNodeInfo, o as createFederation } from "../middleware-CG-XVwTH.mjs";
|
|
9
9
|
import { test } from "@fedify/fixture";
|
|
10
10
|
//#region src/nodeinfo/handler.test.ts
|
|
11
11
|
test("handleNodeInfo()", async () => {
|
package/dist/nodeinfo/mod.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
-
const require_types = require("../types-
|
|
4
|
+
const require_types = require("../types-m8u9L86X.cjs");
|
|
5
5
|
exports.getNodeInfo = require_types.getNodeInfo;
|
|
6
6
|
exports.nodeInfoToJson = require_types.nodeInfoToJson;
|
|
7
7
|
exports.parseNodeInfo = require_types.parseNodeInfo;
|
package/dist/nodeinfo/mod.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "../types-
|
|
3
|
+
import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "../types-DTONwNqL.js";
|
|
4
4
|
export { getNodeInfo, nodeInfoToJson, parseNodeInfo };
|