@fedify/fedify 2.0.28-dev.1979 → 2.0.28-dev.1982
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{assert_instance_of-C4Ri6VuN.mjs → assert-BhQd8QHP.mjs} +19 -1
- package/dist/{builder-CAAXTNeK.mjs → builder-DG5rS_Zv.mjs} +3 -3
- package/dist/{client-HLLGHiTU.mjs → client-glFHmpn4.mjs} +78 -4
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +3 -4
- package/dist/{context-DJ5oMnte.d.ts → context-B21klrfz.d.ts} +2 -2
- package/dist/{context-zLLwVY_G.d.cts → context-M_MxoQgC.d.cts} +2 -2
- package/dist/{deno-D3gZ1DsB.mjs → deno-eqaJj6JL.mjs} +1 -1
- package/dist/{docloader-DIk3fEXZ.mjs → docloader-BXUqhXNd.mjs} +2 -2
- package/dist/federation/builder.test.mjs +2 -2
- package/dist/federation/collection.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +125 -8
- package/dist/federation/idempotency.test.mjs +4 -4
- package/dist/federation/inbox.test.mjs +1 -1
- package/dist/federation/keycache.test.mjs +44 -10
- package/dist/federation/kv.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +66 -10
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/mq.test.mjs +1 -1
- package/dist/federation/negotiation.test.mjs +2 -2
- package/dist/federation/retry.test.mjs +1 -1
- package/dist/federation/router.test.mjs +1 -1
- package/dist/federation/send.test.mjs +5 -6
- package/dist/federation/temporal.test.mjs +2 -2
- package/dist/federation/webfinger.test.mjs +2 -2
- package/dist/{http-BLqv_3ue.cjs → http-BgOlx4n1.cjs} +163 -3
- package/dist/{http-C4D0ajx0.d.ts → http-Bs6thuCC.d.cts} +2 -2
- package/dist/{http-Bn3-am6C.mjs → http-Bu3NxfGb.mjs} +2 -2
- package/dist/{http-RYvZHWMc.d.cts → http-CDupyfOc.d.ts} +2 -2
- package/dist/{http-Cx5dD1D_.js → http-CwcG2wDs.js} +152 -4
- package/dist/{inbox-DC8NbYIj.mjs → inbox-Hou2ZAjv.mjs} +1 -1
- package/dist/{key-BQUnVMwc.mjs → key-bSphUqhB.mjs} +152 -4
- package/dist/{keycache-DaQ3ndaJ.mjs → keycache-D239uGT9.mjs} +12 -4
- package/dist/{kv-cache-CCEitzFw.cjs → kv-cache-B8GaLaNy.cjs} +1 -1
- package/dist/{kv-cache-DI4m-4xy.js → kv-cache-lbswb9pg.js} +1 -1
- package/dist/{ld-CVbwQ8Fz.mjs → ld-D0uFMLmq.mjs} +2 -2
- package/dist/{middleware-C7Afa66S.cjs → middleware-BKpP3cnZ.cjs} +1 -1
- package/dist/{middleware-D3a1JsO1.mjs → middleware-BuVM1K-J.mjs} +27 -19
- package/dist/{middleware-BqkNe0c6.mjs → middleware-DXPBIbm6.mjs} +1 -1
- package/dist/{middleware-Fcpx7tz6.cjs → middleware-D_7wZH27.cjs} +26 -10
- package/dist/{middleware-2Qp34eTb.js → middleware-DomxFoLd.js} +25 -9
- package/dist/{mod-B2zB0rDg.d.cts → mod-Bt0eg_Lv.d.cts} +1 -1
- package/dist/{mod-Du-UVCX_.d.ts → mod-D24V_w-K.d.ts} +1 -1
- package/dist/{mod-BtvLkCgb.d.cts → mod-Dp5dfH-i.d.cts} +1 -1
- package/dist/{mod-CiQNNAQL.d.ts → mod-E7YM72JZ.d.ts} +1 -1
- package/dist/{mod-CB6pc2pw.d.cts → mod-IOWUF5Yr.d.cts} +1 -1
- package/dist/{mod-CD1youdZ.d.ts → mod-XucBiDNd.d.ts} +1 -1
- package/dist/mod.cjs +5 -5
- package/dist/mod.d.cts +6 -6
- package/dist/mod.d.ts +6 -6
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/client.test.mjs +28 -1
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/nodeinfo/mod.cjs +1 -1
- package/dist/nodeinfo/mod.js +1 -1
- package/dist/nodeinfo/types.test.mjs +1 -1
- package/dist/otel/exporter.test.mjs +1 -1
- package/dist/{owner-CnngXDNJ.d.ts → owner-B3hNQCG8.d.cts} +12 -1
- package/dist/owner-Bzg6w7eA.mjs +175 -0
- package/dist/{owner-DEvZuyOE.d.cts → owner-CiBPcC6F.d.ts} +12 -1
- package/dist/{proof-DZWmoF6Z.mjs → proof-CgLA51pO.mjs} +2 -2
- package/dist/{proof-EY-uItWr.js → proof-DsJHFTkx.js} +112 -58
- package/dist/{proof-liMyPvsb.cjs → proof-xCEe8t7U.cjs} +112 -58
- package/dist/{send-IMhmEkun.mjs → send-D89-FDX-.mjs} +2 -2
- package/dist/sig/http.test.mjs +4 -4
- package/dist/sig/key.test.mjs +169 -2
- package/dist/sig/ld.test.mjs +56 -4
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.d.cts +3 -3
- package/dist/sig/mod.d.ts +3 -3
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +105 -6
- package/dist/sig/proof.test.mjs +72 -3
- package/dist/{temporal-BovRWwqL.mjs → temporal-DPJlkHh3.mjs} +1 -1
- package/dist/{types-m8u9L86X.cjs → types-DWs-qZaY.cjs} +94 -2
- package/dist/{types-DTONwNqL.js → types-sXITXcWa.js} +78 -4
- package/dist/utils/docloader.test.mjs +28 -4
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +5 -5
- package/dist/assert-ddO5KLpe.mjs +0 -23
- package/dist/owner-D9CjMxWb.mjs +0 -120
- /package/dist/{collection-ChgDTHLz.mjs → collection-DI6YzYpd.mjs} +0 -0
- /package/dist/{keys-CtZLJq76.mjs → keys-CCxRJhWa.mjs} +0 -0
- /package/dist/{kv-cache-DqEKe5E0.mjs → kv-cache-BrjuJue8.mjs} +0 -0
- /package/dist/{kv-BrZHNugx.mjs → kv-mI4Ix2EU.mjs} +0 -0
- /package/dist/{negotiation-BehA2uul.mjs → negotiation-TWEs6Cl8.mjs} +0 -0
- /package/dist/{retry-B_E3V_Dx.mjs → retry-Ddbq3AcK.mjs} +0 -0
- /package/dist/{types-C37hquWI.mjs → types-MNlFfxjv.mjs} +0 -0
|
@@ -1,7 +1,81 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { getLogger } from "@logtape/logtape";
|
|
4
|
-
import { UrlError, getUserAgent, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
4
|
+
import { FetchError, UrlError, getUserAgent, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
5
|
+
//#region src/utils/body.ts
|
|
6
|
+
/** Decoded JSON body limit: 16 MiB. @internal */
|
|
7
|
+
const MAX_BODY_SIZE = 16 * 1024 * 1024;
|
|
8
|
+
/** A body exceeded the byte limit. @internal */
|
|
9
|
+
var BodyTooLargeError = class extends FetchError {
|
|
10
|
+
/** Creates an error for a body exceeding the given limit. */
|
|
11
|
+
constructor(url, maxBytes) {
|
|
12
|
+
super(url, `Body exceeds the limit of ${maxBytes} bytes`);
|
|
13
|
+
this.name = "BodyTooLargeError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
/** Validates a finite, positive byte limit. @internal */
|
|
17
|
+
function validateBodySizeLimit(maxBytes) {
|
|
18
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) throw new RangeError("The body size limit must be a positive safe integer.");
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Reads UTF-8 text while limiting bytes received from the body stream.
|
|
22
|
+
* Fetch responses are already decompressed, so the stream count is authoritative.
|
|
23
|
+
* @param message The response or request to read.
|
|
24
|
+
* @param maxBytes The maximum number of decoded bytes to read.
|
|
25
|
+
* @param url The URL to include in errors and logs.
|
|
26
|
+
* @returns The decoded body text.
|
|
27
|
+
* @throws {BodyTooLargeError} If the body exceeds the limit.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
async function readBoundedText(message, maxBytes, url) {
|
|
31
|
+
validateBodySizeLimit(maxBytes);
|
|
32
|
+
const reader = message.body?.getReader();
|
|
33
|
+
const tooLarge = () => {
|
|
34
|
+
getLogger([
|
|
35
|
+
"fedify",
|
|
36
|
+
"runtime",
|
|
37
|
+
"body"
|
|
38
|
+
]).warn("Body from {url} exceeds the limit of {maxBytes} bytes.", {
|
|
39
|
+
url: url.toString(),
|
|
40
|
+
maxBytes
|
|
41
|
+
});
|
|
42
|
+
throw new BodyTooLargeError(url, maxBytes);
|
|
43
|
+
};
|
|
44
|
+
try {
|
|
45
|
+
const length = message.headers.get("Content-Length");
|
|
46
|
+
const encoding = message.headers.get("Content-Encoding");
|
|
47
|
+
if ((encoding == null || encoding.toLowerCase() === "identity") && length != null && /^\d+$/.test(length) && Number(length) > maxBytes) tooLarge();
|
|
48
|
+
if (reader == null) return "";
|
|
49
|
+
let size = 0;
|
|
50
|
+
const textReader = new ReadableStream({ async pull(controller) {
|
|
51
|
+
const { done, value } = await reader.read();
|
|
52
|
+
if (done) {
|
|
53
|
+
controller.close();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
size += value.byteLength;
|
|
57
|
+
if (size > maxBytes) tooLarge();
|
|
58
|
+
controller.enqueue(value);
|
|
59
|
+
} }, { highWaterMark: 0 }).pipeThrough(new TextDecoderStream()).getReader();
|
|
60
|
+
try {
|
|
61
|
+
const chunks = [];
|
|
62
|
+
while (true) {
|
|
63
|
+
const { done, value } = await textReader.read();
|
|
64
|
+
if (done) break;
|
|
65
|
+
chunks.push(value);
|
|
66
|
+
}
|
|
67
|
+
return chunks.join("");
|
|
68
|
+
} finally {
|
|
69
|
+
textReader.releaseLock();
|
|
70
|
+
}
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (reader != null) reader.cancel(error).catch(() => {});
|
|
73
|
+
throw error;
|
|
74
|
+
} finally {
|
|
75
|
+
reader?.releaseLock();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
5
79
|
//#region src/nodeinfo/client.ts
|
|
6
80
|
const logger = getLogger([
|
|
7
81
|
"fedify",
|
|
@@ -82,7 +156,7 @@ async function getNodeInfo(url, options = {}) {
|
|
|
82
156
|
});
|
|
83
157
|
return;
|
|
84
158
|
}
|
|
85
|
-
const wellKnownRd = await wellKnownResponse
|
|
159
|
+
const wellKnownRd = JSON.parse(await readBoundedText(wellKnownResponse, MAX_BODY_SIZE, wellKnownUrl));
|
|
86
160
|
const link = wellKnownRd?.links?.find((link) => link != null && "rel" in link && (link.rel === "http://nodeinfo.diaspora.software/ns/schema/2.0" || link.rel === "http://nodeinfo.diaspora.software/ns/schema/2.1") && "href" in link && link.href != null);
|
|
87
161
|
if (link == null || link.href == null) {
|
|
88
162
|
logger.error("Failed to find a NodeInfo document link from {url}: {resourceDescriptor}", {
|
|
@@ -106,7 +180,7 @@ async function getNodeInfo(url, options = {}) {
|
|
|
106
180
|
});
|
|
107
181
|
return;
|
|
108
182
|
}
|
|
109
|
-
const data = await response
|
|
183
|
+
const data = JSON.parse(await readBoundedText(response, MAX_BODY_SIZE, nodeInfoUrl));
|
|
110
184
|
if (options.parse === "none") return data;
|
|
111
185
|
return parseNodeInfo(data, { tryBestEffort: options.parse === "best-effort" }) ?? void 0;
|
|
112
186
|
} catch (error) {
|
|
@@ -352,4 +426,4 @@ function nodeInfoToJson(nodeInfo) {
|
|
|
352
426
|
};
|
|
353
427
|
}
|
|
354
428
|
//#endregion
|
|
355
|
-
export { getNodeInfo as n, parseNodeInfo as r, nodeInfoToJson as t };
|
|
429
|
+
export { MAX_BODY_SIZE as a, BodyTooLargeError as i, getNodeInfo as n, readBoundedText as o, parseNodeInfo as r, nodeInfoToJson as t };
|
|
@@ -5,11 +5,11 @@ 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-Duiq_YC9.mjs";
|
|
7
7
|
import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
|
|
8
|
-
import { l as verifyRequest } from "../http-
|
|
9
|
-
import { i as rsaPrivateKey2 } from "../keys-
|
|
10
|
-
import { t as getAuthenticatedDocumentLoader } from "../docloader-
|
|
8
|
+
import { l as verifyRequest } from "../http-Bu3NxfGb.mjs";
|
|
9
|
+
import { i as rsaPrivateKey2 } from "../keys-CCxRJhWa.mjs";
|
|
10
|
+
import { t as getAuthenticatedDocumentLoader } from "../docloader-BXUqhXNd.mjs";
|
|
11
11
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
12
|
-
import { UrlError } from "@fedify/vocab-runtime";
|
|
12
|
+
import { FetchError, UrlError } from "@fedify/vocab-runtime";
|
|
13
13
|
//#region src/utils/docloader.test.ts
|
|
14
14
|
test("getAuthenticatedDocumentLoader()", async (t) => {
|
|
15
15
|
esm_default.spyGlobal();
|
|
@@ -120,5 +120,29 @@ test("getAuthenticatedDocumentLoader() cancellation", {
|
|
|
120
120
|
});
|
|
121
121
|
esm_default.hardReset();
|
|
122
122
|
});
|
|
123
|
+
test("getAuthenticatedDocumentLoader() bounds JSON after redirects", async () => {
|
|
124
|
+
esm_default.mockGlobal();
|
|
125
|
+
let oversized = true;
|
|
126
|
+
try {
|
|
127
|
+
const url = "https://example.com/bounded";
|
|
128
|
+
esm_default.get(url, {
|
|
129
|
+
status: 302,
|
|
130
|
+
headers: { Location: `${url}/document` }
|
|
131
|
+
});
|
|
132
|
+
esm_default.get(`${url}/document`, () => new Response("{\"name\":\"hello\"}", { headers: {
|
|
133
|
+
"Content-Type": "application/activity+json",
|
|
134
|
+
...oversized ? { "Content-Length": String(16777217) } : {}
|
|
135
|
+
} }));
|
|
136
|
+
const loader = getAuthenticatedDocumentLoader({
|
|
137
|
+
privateKey: rsaPrivateKey2,
|
|
138
|
+
keyId: new URL("https://example.com/key2")
|
|
139
|
+
}, { allowPrivateAddress: true });
|
|
140
|
+
await assertRejects(() => loader(url), FetchError);
|
|
141
|
+
oversized = false;
|
|
142
|
+
assertEquals((await loader(url)).document, { name: "hello" });
|
|
143
|
+
} finally {
|
|
144
|
+
esm_default.hardReset();
|
|
145
|
+
}
|
|
146
|
+
});
|
|
123
147
|
//#endregion
|
|
124
148
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as kvCache, t as MockKvStore } from "../kv-cache-
|
|
4
|
+
import { n as kvCache, t as MockKvStore } from "../kv-cache-BrjuJue8.mjs";
|
|
5
5
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
6
6
|
import { deepStrictEqual, throws } from "node:assert";
|
|
7
7
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
package/dist/utils/mod.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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_kv_cache = require("../kv-cache-
|
|
4
|
+
const require_kv_cache = require("../kv-cache-B8GaLaNy.cjs");
|
|
5
5
|
exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
|
|
6
6
|
exports.kvCache = require_kv_cache.kvCache;
|
package/dist/utils/mod.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../mod-
|
|
2
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../mod-Bt0eg_Lv.cjs";
|
|
3
3
|
export { getAuthenticatedDocumentLoader, kvCache };
|
package/dist/utils/mod.d.ts
CHANGED
package/dist/utils/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 getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-
|
|
3
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-lbswb9pg.js";
|
|
4
4
|
export { getAuthenticatedDocumentLoader, kvCache };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/fedify",
|
|
3
|
-
"version": "2.0.28-dev.
|
|
3
|
+
"version": "2.0.28-dev.1982+a57dec3f",
|
|
4
4
|
"description": "An ActivityPub server framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ActivityPub",
|
|
@@ -144,9 +144,9 @@
|
|
|
144
144
|
"uri-template-router": "^1.0.0",
|
|
145
145
|
"url-template": "^3.1.1",
|
|
146
146
|
"urlpattern-polyfill": "^10.1.0",
|
|
147
|
-
"@fedify/vocab": "2.0.28-dev.
|
|
148
|
-
"@fedify/vocab-runtime": "2.0.28-dev.
|
|
149
|
-
"@fedify/webfinger": "2.0.28-dev.
|
|
147
|
+
"@fedify/vocab": "2.0.28-dev.1982+a57dec3f",
|
|
148
|
+
"@fedify/vocab-runtime": "2.0.28-dev.1982+a57dec3f",
|
|
149
|
+
"@fedify/webfinger": "2.0.28-dev.1982+a57dec3f"
|
|
150
150
|
},
|
|
151
151
|
"devDependencies": {
|
|
152
152
|
"@std/assert": "npm:@jsr/std__assert@^0.226.0",
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
"typescript": "^6.0.0",
|
|
160
160
|
"wrangler": "^4.17.0",
|
|
161
161
|
"@fedify/fixture": "2.0.0",
|
|
162
|
-
"@fedify/vocab-tools": "^2.0.28-dev.
|
|
162
|
+
"@fedify/vocab-tools": "^2.0.28-dev.1982+a57dec3f"
|
|
163
163
|
},
|
|
164
164
|
"scripts": {
|
|
165
165
|
"build:self": "tsdown",
|
package/dist/assert-ddO5KLpe.mjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import "@js-temporal/polyfill";
|
|
2
|
-
import "urlpattern-polyfill";
|
|
3
|
-
globalThis.addEventListener = () => {};
|
|
4
|
-
import { l as AssertionError } from "./assert_equals-Ew3jOFa3.mjs";
|
|
5
|
-
//#region ../../node_modules/.pnpm/@jsr+std__assert@0.226.0/node_modules/@jsr/std__assert/assert.js
|
|
6
|
-
/**
|
|
7
|
-
* Make an assertion, error will be thrown if `expr` does not have truthy value.
|
|
8
|
-
*
|
|
9
|
-
* @example Usage
|
|
10
|
-
* ```ts no-eval
|
|
11
|
-
* import { assert } from "@std/assert/assert";
|
|
12
|
-
*
|
|
13
|
-
* assert("hello".includes("ello")); // Doesn't throw
|
|
14
|
-
* assert("hello".includes("world")); // Throws
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* @param expr The expression to test.
|
|
18
|
-
* @param msg The optional message to display if the assertion fails.
|
|
19
|
-
*/ function assert(expr, msg = "") {
|
|
20
|
-
if (!expr) throw new AssertionError(msg);
|
|
21
|
-
}
|
|
22
|
-
//#endregion
|
|
23
|
-
export { assert as t };
|
package/dist/owner-D9CjMxWb.mjs
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import "@js-temporal/polyfill";
|
|
2
|
-
import "urlpattern-polyfill";
|
|
3
|
-
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-D3gZ1DsB.mjs";
|
|
5
|
-
import "./key-BQUnVMwc.mjs";
|
|
6
|
-
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
7
|
-
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
8
|
-
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
9
|
-
//#region src/sig/owner.ts
|
|
10
|
-
/**
|
|
11
|
-
* Checks if the actor of the given activity owns the specified key.
|
|
12
|
-
* @param activity The activity to check.
|
|
13
|
-
* @param key The public key to check.
|
|
14
|
-
* @param options Options for checking the key ownership.
|
|
15
|
-
* @returns Whether the actor is the owner of the key.
|
|
16
|
-
*/
|
|
17
|
-
async function doesActorOwnKey(activity, key, options) {
|
|
18
|
-
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("activitypub.verify_key_ownership", {
|
|
19
|
-
kind: SpanKind.INTERNAL,
|
|
20
|
-
attributes: {
|
|
21
|
-
"activitypub.actor.id": activity.actorId?.href ?? "",
|
|
22
|
-
"activitypub.key.id": key.id?.href ?? ""
|
|
23
|
-
}
|
|
24
|
-
}, async (span) => {
|
|
25
|
-
try {
|
|
26
|
-
if (key.ownerId != null) {
|
|
27
|
-
const owns = key.ownerId.href === activity.actorId?.href;
|
|
28
|
-
span.setAttribute("activitypub.key_ownership.verified", owns);
|
|
29
|
-
span.setAttribute("activitypub.key_ownership.method", "owner_id");
|
|
30
|
-
return owns;
|
|
31
|
-
}
|
|
32
|
-
const actor = await activity.getActor(options);
|
|
33
|
-
if (actor == null || !isActor(actor)) {
|
|
34
|
-
span.setAttribute("activitypub.key_ownership.verified", false);
|
|
35
|
-
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
for (const publicKeyId of actor.publicKeyIds) if (key.id != null && publicKeyId.href === key.id.href) {
|
|
39
|
-
span.setAttribute("activitypub.key_ownership.verified", true);
|
|
40
|
-
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
span.setAttribute("activitypub.key_ownership.verified", false);
|
|
44
|
-
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
45
|
-
return false;
|
|
46
|
-
} catch (error) {
|
|
47
|
-
span.recordException(error);
|
|
48
|
-
span.setStatus({
|
|
49
|
-
code: SpanStatusCode.ERROR,
|
|
50
|
-
message: String(error)
|
|
51
|
-
});
|
|
52
|
-
throw error;
|
|
53
|
-
} finally {
|
|
54
|
-
span.end();
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
|
60
|
-
* known owner.
|
|
61
|
-
*
|
|
62
|
-
* @param keyId The ID of the key to check, or the key itself.
|
|
63
|
-
* @param options Options for getting the key owner.
|
|
64
|
-
* @returns The actor that owns the key, or `null` if the key has no known
|
|
65
|
-
* owner.
|
|
66
|
-
* @since 0.7.0
|
|
67
|
-
*/
|
|
68
|
-
async function getKeyOwner(keyId, options) {
|
|
69
|
-
const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
|
|
70
|
-
const documentLoader = options.documentLoader ?? getDocumentLoader();
|
|
71
|
-
const contextLoader = options.contextLoader ?? getDocumentLoader();
|
|
72
|
-
let object;
|
|
73
|
-
if (keyId instanceof CryptographicKey) {
|
|
74
|
-
object = keyId;
|
|
75
|
-
if (object.id == null) return null;
|
|
76
|
-
keyId = object.id;
|
|
77
|
-
} else {
|
|
78
|
-
let keyDoc;
|
|
79
|
-
try {
|
|
80
|
-
const { document } = await documentLoader(keyId.href);
|
|
81
|
-
keyDoc = document;
|
|
82
|
-
} catch (_) {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
try {
|
|
86
|
-
object = await Object$1.fromJsonLd(keyDoc, {
|
|
87
|
-
documentLoader,
|
|
88
|
-
contextLoader,
|
|
89
|
-
tracerProvider
|
|
90
|
-
});
|
|
91
|
-
} catch (e) {
|
|
92
|
-
if (!(e instanceof TypeError)) throw e;
|
|
93
|
-
try {
|
|
94
|
-
object = await CryptographicKey.fromJsonLd(keyDoc, {
|
|
95
|
-
documentLoader,
|
|
96
|
-
contextLoader,
|
|
97
|
-
tracerProvider
|
|
98
|
-
});
|
|
99
|
-
} catch (e) {
|
|
100
|
-
if (e instanceof TypeError) return null;
|
|
101
|
-
throw e;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
let owner = null;
|
|
106
|
-
if (object instanceof CryptographicKey) {
|
|
107
|
-
if (object.ownerId == null) return null;
|
|
108
|
-
owner = await object.getOwner({
|
|
109
|
-
documentLoader,
|
|
110
|
-
contextLoader,
|
|
111
|
-
tracerProvider
|
|
112
|
-
});
|
|
113
|
-
} else if (isActor(object)) owner = object;
|
|
114
|
-
else return null;
|
|
115
|
-
if (owner == null) return null;
|
|
116
|
-
for (const kid of owner.publicKeyIds) if (kid.href === keyId.href) return owner;
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
//#endregion
|
|
120
|
-
export { getKeyOwner as n, doesActorOwnKey as t };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|