@fedify/fedify 2.2.6 → 2.2.8
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-C-al99Vs.mjs → builder-Hr1c39Ha.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-B0LcALOm.mjs → deno-B_vGx2Ji.mjs} +1 -1
- package/dist/{docloader-DLAjdiZt.mjs → docloader-DixiMoIZ.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-BkivuOe4.mjs → http-BlHW6_Oi.mjs} +2 -2
- package/dist/{http-C-9duWvR.js → http-C-FdpmAl.js} +1 -1
- package/dist/{http-NEN2KDMb.cjs → http-DLRpF855.cjs} +1 -1
- package/dist/{key-BcpJR7wT.mjs → key-6U1u5H_H.mjs} +1 -1
- package/dist/{kv-cache-8o7zAqEi.js → kv-cache-BjlL4Zk0.js} +1 -1
- package/dist/{kv-cache-9K6uVGgd.cjs → kv-cache-DKprbYof.cjs} +1 -1
- package/dist/{ld-DAZQsoKN.mjs → ld-DDBxn1rq.mjs} +2 -2
- package/dist/{middleware-C3JAusAj.mjs → middleware-BJM6vrlT.mjs} +46 -29
- package/dist/{middleware-BUiHyCQ9.cjs → middleware-Bj5UFOaT.cjs} +42 -23
- package/dist/{middleware-CeqmkLh1.cjs → middleware-DNJYfRV4.cjs} +1 -1
- package/dist/{middleware-Bk-ge16h.js → middleware-DOkcTiZ-.js} +41 -22
- package/dist/{middleware-BysI6Pqz.mjs → middleware-Ds3ujCKo.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-CwVIBwY0.mjs → owner-vuyMTd_f.mjs} +2 -2
- package/dist/{proof-wrxzZi_u.mjs → proof-BGrdGhcb.mjs} +2 -2
- package/dist/{proof-C2en2Cmb.cjs → proof-BNGY2IU6.cjs} +1 -1
- package/dist/{proof-IyDe0jjt.js → proof-DA_wkPds.js} +1 -1
- package/dist/{send-DOlXF7S8.mjs → send-BvazsIXC.mjs} +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -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-B13wkvUP.mjs → temporal-MdUFasAg.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 +6 -6
package/README.md
CHANGED
|
@@ -193,7 +193,7 @@ This project exists thanks to all the people who contribute, donate, and sponsor
|
|
|
193
193
|
it. We are grateful for their support. We would like to thank the following
|
|
194
194
|
financial contributors:[^2]
|
|
195
195
|
|
|
196
|
-
[^2]: Those lists are automatically updated
|
|
196
|
+
[^2]: Those lists are automatically updated twice a day.
|
|
197
197
|
|
|
198
198
|
<!-- hongdown-disable -->
|
|
199
199
|
|
|
@@ -204,21 +204,22 @@ financial contributors:[^2]
|
|
|
204
204
|
### Corporate sponsors
|
|
205
205
|
|
|
206
206
|
- [<img src="https://images.opencollective.com/ghost/avatar/128.png" width="64" height="64"> Ghost](https://ghost.org)
|
|
207
|
+
- [<img src="https://images.opencollective.com/altstore/avatar/128.png" width="64" height="64"> AltStore](https://altstore.io)
|
|
207
208
|
|
|
208
209
|
### Supporters
|
|
209
210
|
|
|
210
|
-
- [Daniel Supernault](https://pixelfed.org/)
|
|
211
211
|
- [tkgka](https://opencollective.com/tkgka)
|
|
212
212
|
- [Blaine](https://opencollective.com/blaine)
|
|
213
213
|
- [Erick González Aguilar](https://opencollective.com/erick-gonzalez-aguilar)
|
|
214
|
+
- [Daniel Supernault](https://pixelfed.org/)
|
|
214
215
|
|
|
215
216
|
### Backers
|
|
216
217
|
|
|
217
|
-
Robin Riley,
|
|
218
|
+
Robin Riley, Encyclia, taye, box464, Evan Prodromou, okin, yamanoku, malte, Rafael Goulart, Andy Piper
|
|
218
219
|
|
|
219
220
|
### One-time donations
|
|
220
221
|
|
|
221
|
-
Robin Riley,
|
|
222
|
+
Robin Riley, malte, Nils Bergmann, Markus P, Rameez
|
|
222
223
|
|
|
223
224
|
<!-- /DO NOT EDIT -->
|
|
224
225
|
|
|
@@ -2,7 +2,7 @@ import "@js-temporal/polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { n as RouterError, t as Router } from "./router-CrMLXoOr.mjs";
|
|
5
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
+
import { n as version, t as name } from "./deno-B_vGx2Ji.mjs";
|
|
6
6
|
import { t as ActivityListenerSet } from "./activity-listener-ell7W1s9.mjs";
|
|
7
7
|
import { Tombstone, getTypeId } from "@fedify/vocab";
|
|
8
8
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -58,7 +58,7 @@ var FederationBuilderImpl = class {
|
|
|
58
58
|
this.collectionTypeIds = {};
|
|
59
59
|
}
|
|
60
60
|
async build(options) {
|
|
61
|
-
const { FederationImpl } = await import("./middleware-
|
|
61
|
+
const { FederationImpl } = await import("./middleware-Ds3ujCKo.mjs");
|
|
62
62
|
const f = new FederationImpl(options);
|
|
63
63
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
64
64
|
f.router = this.router.clone();
|
|
@@ -69,6 +69,8 @@ var FederationBuilderImpl = class {
|
|
|
69
69
|
f.webFingerLinksDispatcher = this.webFingerLinksDispatcher;
|
|
70
70
|
f.objectCallbacks = { ...this.objectCallbacks };
|
|
71
71
|
f.objectTypeIds = { ...this.objectTypeIds };
|
|
72
|
+
f.collectionCallbacks = { ...this.collectionCallbacks };
|
|
73
|
+
f.collectionTypeIds = { ...this.collectionTypeIds };
|
|
72
74
|
f.inboxPath = this.inboxPath;
|
|
73
75
|
f.outboxPath = this.outboxPath;
|
|
74
76
|
f.inboxCallbacks = this.inboxCallbacks == null ? void 0 : { ...this.inboxCallbacks };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { getUserAgent } from "@fedify/vocab-runtime";
|
|
4
|
+
import { UrlError, getUserAgent, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
5
5
|
import { getLogger } from "@logtape/logtape";
|
|
6
6
|
//#region src/nodeinfo/client.ts
|
|
7
7
|
const logger = getLogger([
|
|
@@ -9,15 +9,72 @@ const logger = getLogger([
|
|
|
9
9
|
"nodeinfo",
|
|
10
10
|
"client"
|
|
11
11
|
]);
|
|
12
|
+
const DEFAULT_MAX_REDIRECTION = 5;
|
|
13
|
+
/**
|
|
14
|
+
* Fetches a URL while guarding against SSRF. Before every request—including
|
|
15
|
+
* each redirect hop—the destination is validated with
|
|
16
|
+
* {@link validatePublicUrl}, so that loopback, link-local, and private
|
|
17
|
+
* addresses, as well as non-HTTP(S) schemes such as `data:`, are rejected.
|
|
18
|
+
* Redirects are followed manually with a cap, so that a public URL cannot
|
|
19
|
+
* bounce the request to an internal address.
|
|
20
|
+
* @param url The URL to fetch.
|
|
21
|
+
* @param headers The request headers.
|
|
22
|
+
* @returns The final response, or `null` if the URL is disallowed or there
|
|
23
|
+
* are too many redirects.
|
|
24
|
+
*/
|
|
25
|
+
async function fetchPublicUrl(url, headers) {
|
|
26
|
+
let current = url instanceof URL ? url : new URL(url);
|
|
27
|
+
let redirected = 0;
|
|
28
|
+
while (true) {
|
|
29
|
+
try {
|
|
30
|
+
await validatePublicUrl(current.href);
|
|
31
|
+
} catch (e) {
|
|
32
|
+
if (e instanceof UrlError) {
|
|
33
|
+
logger.error("Refused to fetch a private or invalid URL {url}: {error}", {
|
|
34
|
+
url: current.href,
|
|
35
|
+
error: e
|
|
36
|
+
});
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
throw e;
|
|
40
|
+
}
|
|
41
|
+
const response = await fetch(current, {
|
|
42
|
+
headers,
|
|
43
|
+
redirect: "manual"
|
|
44
|
+
});
|
|
45
|
+
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
46
|
+
redirected++;
|
|
47
|
+
if (redirected >= DEFAULT_MAX_REDIRECTION) {
|
|
48
|
+
logger.error("Too many redirections ({redirections}) while fetching {url}.", {
|
|
49
|
+
redirections: redirected,
|
|
50
|
+
url: current.href
|
|
51
|
+
});
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const next = new URL(response.headers.get("Location"), response.url == null || response.url === "" ? current : response.url);
|
|
55
|
+
if (next.protocol !== current.protocol) {
|
|
56
|
+
logger.error("Refused a redirect to a different protocol ({protocol} to {redirectedProtocol}) while fetching NodeInfo.", {
|
|
57
|
+
protocol: current.protocol,
|
|
58
|
+
redirectedProtocol: next.protocol
|
|
59
|
+
});
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
current = next;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
return response;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
12
68
|
async function getNodeInfo(url, options = {}) {
|
|
13
69
|
try {
|
|
14
70
|
let nodeInfoUrl = url;
|
|
15
71
|
if (!options.direct) {
|
|
16
72
|
const wellKnownUrl = new URL("/.well-known/nodeinfo", url);
|
|
17
|
-
const wellKnownResponse = await
|
|
73
|
+
const wellKnownResponse = await fetchPublicUrl(wellKnownUrl, {
|
|
18
74
|
Accept: "application/json",
|
|
19
75
|
"User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
|
|
20
|
-
}
|
|
76
|
+
});
|
|
77
|
+
if (wellKnownResponse == null) return void 0;
|
|
21
78
|
if (!wellKnownResponse.ok) {
|
|
22
79
|
logger.error("Failed to fetch {url}: {status} {statusText}", {
|
|
23
80
|
url: wellKnownUrl.href,
|
|
@@ -37,10 +94,11 @@ async function getNodeInfo(url, options = {}) {
|
|
|
37
94
|
}
|
|
38
95
|
nodeInfoUrl = link.href;
|
|
39
96
|
}
|
|
40
|
-
const response = await
|
|
97
|
+
const response = await fetchPublicUrl(nodeInfoUrl, {
|
|
41
98
|
Accept: "application/json",
|
|
42
99
|
"User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
|
|
43
|
-
}
|
|
100
|
+
});
|
|
101
|
+
if (response == null) return void 0;
|
|
44
102
|
if (!response.ok) {
|
|
45
103
|
logger.error("Failed to fetch NodeInfo document from {url}: {status} {statusText}", {
|
|
46
104
|
url: nodeInfoUrl.toString(),
|
|
@@ -5,7 +5,7 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
|
5
5
|
import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
|
|
6
6
|
import { t as assert } from "../assert-DikXweDx.mjs";
|
|
7
7
|
import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
|
|
8
|
-
import { n as FederationImpl, v as actorDehydrator, y as autoIdAssigner } from "../middleware-
|
|
8
|
+
import { n as FederationImpl, v as actorDehydrator, y as autoIdAssigner } from "../middleware-BJM6vrlT.mjs";
|
|
9
9
|
import { test } from "@fedify/fixture";
|
|
10
10
|
import { Follow, Person } from "@fedify/vocab";
|
|
11
11
|
//#region src/compat/transformers.test.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { o as validateCryptoKey } from "./key-
|
|
5
|
-
import { n as doubleKnock } from "./http-
|
|
4
|
+
import { o as validateCryptoKey } from "./key-6U1u5H_H.mjs";
|
|
5
|
+
import { n as doubleKnock } from "./http-BlHW6_Oi.mjs";
|
|
6
6
|
import { curry } from "es-toolkit";
|
|
7
7
|
import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
8
8
|
import { getLogger } from "@logtape/logtape";
|
|
@@ -6,7 +6,7 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
|
6
6
|
import { i as assertExists } from "../std__assert-CRDpx_HF.mjs";
|
|
7
7
|
import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
|
|
8
8
|
import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
|
|
9
|
-
import { n as createFederationBuilder } from "../builder-
|
|
9
|
+
import { n as createFederationBuilder } from "../builder-Hr1c39Ha.mjs";
|
|
10
10
|
import { test } from "@fedify/fixture";
|
|
11
11
|
import { Activity, Note, Person } from "@fedify/vocab";
|
|
12
12
|
//#region src/federation/builder.test.ts
|
|
@@ -180,6 +180,18 @@ test("FederationBuilder", async (t) => {
|
|
|
180
180
|
});
|
|
181
181
|
builder.setCollectionDispatcher(strId, Note, "/string-id/{id}", dispatcher);
|
|
182
182
|
});
|
|
183
|
+
await t.step("propagates custom collection dispatchers to the built federation", async () => {
|
|
184
|
+
const kv = new MemoryKvStore();
|
|
185
|
+
const builder = createFederationBuilder();
|
|
186
|
+
builder.setCollectionDispatcher("test", Note, "/c/{id}", () => ({ items: [] }));
|
|
187
|
+
const impl = await builder.build({
|
|
188
|
+
kv,
|
|
189
|
+
origin: "https://example.com"
|
|
190
|
+
});
|
|
191
|
+
assertExists(impl.collectionCallbacks["test"]);
|
|
192
|
+
assertEquals(impl.collectionTypeIds["test"], Note);
|
|
193
|
+
assertEquals((await impl.fetch(new Request("https://example.com/c/x", { headers: { accept: "application/activity+json" } }), { contextData: void 0 })).status, 200);
|
|
194
|
+
});
|
|
183
195
|
});
|
|
184
196
|
//#endregion
|
|
185
197
|
export {};
|
|
@@ -8,11 +8,11 @@ import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
|
|
|
8
8
|
import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
|
|
9
9
|
import { t as assert } from "../assert-DikXweDx.mjs";
|
|
10
10
|
import { r as parseAcceptSignature } from "../accept-CPkZzmGN.mjs";
|
|
11
|
-
import { s as signRequest } from "../http-
|
|
11
|
+
import { s as signRequest } from "../http-BlHW6_Oi.mjs";
|
|
12
12
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-DGu1NFwu.mjs";
|
|
13
|
-
import { a as compactJsonLd, p as signJsonLd } from "../ld-
|
|
13
|
+
import { a as compactJsonLd, p as signJsonLd } from "../ld-DDBxn1rq.mjs";
|
|
14
14
|
import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
|
|
15
|
-
import { c as handleActor, d as handleInbox, f as handleObject, h as respondWithObjectIfAcceptable, l as handleCollection, m as respondWithObject, o as createFederation, p as handleOutbox, u as handleCustomCollection } from "../middleware-
|
|
15
|
+
import { c as handleActor, d as handleInbox, f as handleObject, h as respondWithObjectIfAcceptable, l as handleCollection, m as respondWithObject, o as createFederation, p as handleOutbox, u as handleCustomCollection } from "../middleware-BJM6vrlT.mjs";
|
|
16
16
|
import { t as ActivityListenerSet } from "../activity-listener-ell7W1s9.mjs";
|
|
17
17
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
18
18
|
import { Activity, Create, Note, Person, Tombstone } from "@fedify/vocab";
|
|
@@ -4,9 +4,9 @@ globalThis.addEventListener = () => {};
|
|
|
4
4
|
import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
5
5
|
import "../std__assert-CRDpx_HF.mjs";
|
|
6
6
|
import { n as ed25519PrivateKey, r as ed25519PublicKey, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
|
|
7
|
-
import { r as signObject } from "../proof-
|
|
7
|
+
import { r as signObject } from "../proof-BGrdGhcb.mjs";
|
|
8
8
|
import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
|
|
9
|
-
import { o as createFederation } from "../middleware-
|
|
9
|
+
import { o as createFederation } from "../middleware-BJM6vrlT.mjs";
|
|
10
10
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
11
11
|
import { Create, Follow, Person } from "@fedify/vocab";
|
|
12
12
|
//#region src/federation/idempotency.test.ts
|
|
@@ -11,14 +11,14 @@ import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
|
|
|
11
11
|
import { t as assertNotEquals } from "../assert_not_equals--wG9hV7u.mjs";
|
|
12
12
|
import { t as assertStrictEquals } from "../assert_strict_equals-Dmjbg-bA.mjs";
|
|
13
13
|
import { t as assert } from "../assert-DikXweDx.mjs";
|
|
14
|
-
import { l as verifyRequest, s as signRequest } from "../http-
|
|
14
|
+
import { l as verifyRequest, s as signRequest } from "../http-BlHW6_Oi.mjs";
|
|
15
15
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
|
|
16
|
-
import { t as getAuthenticatedDocumentLoader } from "../docloader-
|
|
17
|
-
import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-
|
|
18
|
-
import { t as doesActorOwnKey } from "../owner-
|
|
19
|
-
import { i as verifyObject, r as signObject } from "../proof-
|
|
16
|
+
import { t as getAuthenticatedDocumentLoader } from "../docloader-DixiMoIZ.mjs";
|
|
17
|
+
import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-DDBxn1rq.mjs";
|
|
18
|
+
import { t as doesActorOwnKey } from "../owner-vuyMTd_f.mjs";
|
|
19
|
+
import { i as verifyObject, r as signObject } from "../proof-BGrdGhcb.mjs";
|
|
20
20
|
import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
|
|
21
|
-
import { i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-
|
|
21
|
+
import { i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-BJM6vrlT.mjs";
|
|
22
22
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
23
23
|
import * as vocab from "@fedify/vocab";
|
|
24
24
|
import { Create, Offer, Person, getTypeId, lookupObject } from "@fedify/vocab";
|
package/dist/federation/mod.cjs
CHANGED
|
@@ -2,7 +2,7 @@ const { Temporal } = require("@js-temporal/polyfill");
|
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
4
|
require("../chunk-DDcVe30Y.cjs");
|
|
5
|
-
const require_middleware = require("../middleware-
|
|
5
|
+
const require_middleware = require("../middleware-Bj5UFOaT.cjs");
|
|
6
6
|
let es_toolkit = require("es-toolkit");
|
|
7
7
|
//#region src/federation/kv.ts
|
|
8
8
|
/**
|
package/dist/federation/mod.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
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-
|
|
3
|
+
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-DOkcTiZ-.js";
|
|
4
4
|
import { isEqual } from "es-toolkit";
|
|
5
5
|
//#region src/federation/kv.ts
|
|
6
6
|
/**
|
|
@@ -8,10 +8,10 @@ import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z
|
|
|
8
8
|
import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
|
|
9
9
|
import { t as assertNotEquals } from "../assert_not_equals--wG9hV7u.mjs";
|
|
10
10
|
import { t as assert } from "../assert-DikXweDx.mjs";
|
|
11
|
-
import { l as verifyRequest } from "../http-
|
|
11
|
+
import { l as verifyRequest } from "../http-BlHW6_Oi.mjs";
|
|
12
12
|
import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
|
|
13
|
-
import { t as doesActorOwnKey } from "../owner-
|
|
14
|
-
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-
|
|
13
|
+
import { t as doesActorOwnKey } from "../owner-vuyMTd_f.mjs";
|
|
14
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-BvazsIXC.mjs";
|
|
15
15
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
16
16
|
import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
|
|
17
17
|
//#region src/federation/send.test.ts
|
|
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
|
|
|
4
4
|
import "../std__assert-CRDpx_HF.mjs";
|
|
5
5
|
import { n as assertFalse } from "../assert_rejects-B-qJtC9Z.mjs";
|
|
6
6
|
import { t as assert } from "../assert-DikXweDx.mjs";
|
|
7
|
-
import { t as hasMalformedKnownTemporalLiteral } from "../temporal-
|
|
7
|
+
import { t as hasMalformedKnownTemporalLiteral } from "../temporal-MdUFasAg.mjs";
|
|
8
8
|
import { test } from "@fedify/fixture";
|
|
9
9
|
//#region src/federation/temporal.test.ts
|
|
10
10
|
test("hasMalformedKnownTemporalLiteral() detects expanded proof timestamps", async () => {
|
|
@@ -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 { o as createFederation, s as handleWebFinger } from "../middleware-
|
|
8
|
+
import { o as createFederation, s as handleWebFinger } from "../middleware-BJM6vrlT.mjs";
|
|
9
9
|
import { test } from "@fedify/fixture";
|
|
10
10
|
import { Image, Link, Person, Tombstone } from "@fedify/vocab";
|
|
11
11
|
//#region src/federation/webfinger.test.ts
|
|
@@ -257,7 +257,7 @@ test("handleWebFinger()", async (t) => {
|
|
|
257
257
|
});
|
|
258
258
|
onNotFoundCalled = null;
|
|
259
259
|
const actorHandleMapper = (_ctx, username) => {
|
|
260
|
-
return username === "foo" ? "someone" : username === "bar" ? "someone2" : null;
|
|
260
|
+
return username === "foo" ? "someone" : username === "bar" ? "someone2" : username === "qux" ? "someone2" : null;
|
|
261
261
|
};
|
|
262
262
|
await t.step("handle mapper", async () => {
|
|
263
263
|
const u = new URL(url);
|
|
@@ -380,21 +380,83 @@ test("handleWebFinger()", async (t) => {
|
|
|
380
380
|
assertEquals(response.status, 404);
|
|
381
381
|
});
|
|
382
382
|
await t.step("handleHost", async () => {
|
|
383
|
-
|
|
384
|
-
u.searchParams.set("resource", "acct:someone@example.com");
|
|
383
|
+
let u = new URL("https://ap.example.com/.well-known/webfinger");
|
|
384
|
+
u.searchParams.set("resource", "acct:someone@ap.example.com");
|
|
385
385
|
let context = createContext(u);
|
|
386
386
|
let request = context.request;
|
|
387
387
|
let response = await handleWebFinger(request, {
|
|
388
388
|
context,
|
|
389
|
-
host: "
|
|
389
|
+
host: "example.com",
|
|
390
390
|
actorDispatcher,
|
|
391
391
|
onNotFound
|
|
392
392
|
});
|
|
393
393
|
assertEquals(response.status, 200);
|
|
394
394
|
assertEquals(await response.json(), {
|
|
395
|
-
|
|
396
|
-
aliases: [
|
|
395
|
+
subject: "acct:someone@example.com",
|
|
396
|
+
aliases: ["https://ap.example.com/users/someone", "acct:someone@ap.example.com"],
|
|
397
|
+
links: [
|
|
398
|
+
{
|
|
399
|
+
href: "https://ap.example.com/users/someone",
|
|
400
|
+
rel: "self",
|
|
401
|
+
type: "application/activity+json"
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
href: "https://ap.example.com/@someone",
|
|
405
|
+
rel: "http://webfinger.net/rel/profile-page"
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
href: "https://ap.example.com/@someone",
|
|
409
|
+
rel: "alternate",
|
|
410
|
+
type: "text/html"
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
href: "https://ap.example.com/icon.jpg",
|
|
414
|
+
rel: "http://webfinger.net/rel/avatar",
|
|
415
|
+
type: "image/jpeg"
|
|
416
|
+
}
|
|
417
|
+
]
|
|
418
|
+
});
|
|
419
|
+
u.searchParams.set("resource", "acct:qux@ap.example.com");
|
|
420
|
+
context = createContext(u);
|
|
421
|
+
request = context.request;
|
|
422
|
+
response = await handleWebFinger(request, {
|
|
423
|
+
context,
|
|
424
|
+
host: "example.com",
|
|
425
|
+
actorDispatcher,
|
|
426
|
+
actorHandleMapper,
|
|
427
|
+
onNotFound
|
|
397
428
|
});
|
|
429
|
+
assertEquals(response.status, 200);
|
|
430
|
+
assertEquals(await response.json(), {
|
|
431
|
+
subject: "acct:bar@example.com",
|
|
432
|
+
aliases: [
|
|
433
|
+
"https://ap.example.com/users/someone2",
|
|
434
|
+
"acct:qux@ap.example.com",
|
|
435
|
+
"acct:bar@ap.example.com"
|
|
436
|
+
],
|
|
437
|
+
links: [
|
|
438
|
+
{
|
|
439
|
+
href: "https://ap.example.com/users/someone2",
|
|
440
|
+
rel: "self",
|
|
441
|
+
type: "application/activity+json"
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
href: "https://ap.example.com/@someone2",
|
|
445
|
+
rel: "http://webfinger.net/rel/profile-page"
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
href: "https://ap.example.com/@someone2",
|
|
449
|
+
rel: "alternate",
|
|
450
|
+
type: "text/html"
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
href: "https://ap.example.com/icon.jpg",
|
|
454
|
+
rel: "http://webfinger.net/rel/avatar",
|
|
455
|
+
type: "image/jpeg"
|
|
456
|
+
}
|
|
457
|
+
]
|
|
458
|
+
});
|
|
459
|
+
u = new URL(url);
|
|
398
460
|
u.searchParams.set("resource", "acct:someone@handle.example.com");
|
|
399
461
|
context = createContext(u);
|
|
400
462
|
request = context.request;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
4
|
+
import { n as version, t as name } from "./deno-B_vGx2Ji.mjs";
|
|
5
5
|
import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CPkZzmGN.mjs";
|
|
6
|
-
import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-
|
|
6
|
+
import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-6U1u5H_H.mjs";
|
|
7
7
|
import { CryptographicKey } from "@fedify/vocab";
|
|
8
8
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
9
9
|
import { FetchError } from "@fedify/vocab-runtime";
|
|
@@ -10,7 +10,7 @@ import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } fro
|
|
|
10
10
|
import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
|
|
11
11
|
//#region deno.json
|
|
12
12
|
var name = "@fedify/fedify";
|
|
13
|
-
var version = "2.2.
|
|
13
|
+
var version = "2.2.8";
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region src/sig/accept.ts
|
|
16
16
|
/**
|
|
@@ -11,7 +11,7 @@ let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conve
|
|
|
11
11
|
let byte_encodings_base64 = require("byte-encodings/base64");
|
|
12
12
|
//#region deno.json
|
|
13
13
|
var name = "@fedify/fedify";
|
|
14
|
-
var version = "2.2.
|
|
14
|
+
var version = "2.2.8";
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/sig/accept.ts
|
|
17
17
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
4
|
+
import { n as version, t as name } from "./deno-B_vGx2Ji.mjs";
|
|
5
5
|
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
6
6
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
7
7
|
import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { d as validateCryptoKey, t as doubleKnock } from "./http-C-
|
|
3
|
+
import { d as validateCryptoKey, t as doubleKnock } from "./http-C-FdpmAl.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
5
|
import { curry } from "es-toolkit";
|
|
6
6
|
import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
require("./chunk-DDcVe30Y.cjs");
|
|
4
|
-
const require_http = require("./http-
|
|
4
|
+
const require_http = require("./http-DLRpF855.cjs");
|
|
5
5
|
let _logtape_logtape = require("@logtape/logtape");
|
|
6
6
|
let es_toolkit = require("es-toolkit");
|
|
7
7
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as fetchKey, o as validateCryptoKey } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-B_vGx2Ji.mjs";
|
|
5
|
+
import { n as fetchKey, o as validateCryptoKey } from "./key-6U1u5H_H.mjs";
|
|
6
6
|
import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
|
|
7
7
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
8
8
|
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
@@ -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-B_vGx2Ji.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-6U1u5H_H.mjs";
|
|
8
|
+
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-BlHW6_Oi.mjs";
|
|
9
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-DixiMoIZ.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-DDBxn1rq.mjs";
|
|
12
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-vuyMTd_f.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-BGrdGhcb.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-Hr1c39Ha.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-MdUFasAg.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-BvazsIXC.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
|
} });
|