Loading CHANGES.md +8 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,14 @@ Version 1.3.5 To be released. - Fixed a bug where `CreateFederationOptions.allowPrivateAddress` option had been ignored by the `Context.lookupObject()` method when it had taken a fediverse handle. - The `lookupWebFinger()` function became to silently return `null` when it fails to fetch the WebFinger document due to accessing a private network address, instead of throwing a `UrlError`. Version 1.3.4 ------------- Loading src/federation/middleware.test.ts +56 −0 Original line number Diff line number Diff line Loading @@ -1016,6 +1016,62 @@ test("FederationImpl.sendActivity()", async (t) => { mf.uninstall(); }); test("ContextImpl.lookupObject()", async (t) => { // Note that this test only checks if allowPrivateAddress option affects // the ContextImpl.lookupObject() method. Other aspects of the method are // tested in the lookupObject() tests. mf.install(); mf.mock("GET@/.well-known/webfinger", () => new Response( JSON.stringify({ subject: "acct:test@localhost", links: [ { rel: "self", type: "application/activity+json", href: "https://localhost/actor", }, ], }), { headers: { "Content-Type": "application/jrd+json" } }, )); mf.mock("GET@/actor", () => new Response( JSON.stringify({ "@context": "https://www.w3.org/ns/activitystreams", "type": "Person", "id": "https://localhost/actor", "preferredUsername": "test", }), { headers: { "Content-Type": "application/activity+json" } }, )); await t.step("allowPrivateAddress: true", async () => { const federation = createFederation<void>({ kv: new MemoryKvStore(), allowPrivateAddress: true, }); const ctx = federation.createContext(new URL("https://example.com/")); const result = await ctx.lookupObject("@test@localhost"); assertInstanceOf(result, Person); assertEquals(result.id, new URL("https://localhost/actor")); assertEquals(result.preferredUsername, "test"); }); await t.step("allowPrivateAddress: false", async () => { const federation = createFederation<void>({ kv: new MemoryKvStore(), allowPrivateAddress: false, }); const ctx = federation.createContext(new URL("https://example.com/")); const result = await ctx.lookupObject("@test@localhost"); assertEquals(result, null); }); mf.uninstall(); }); test("ContextImpl.sendActivity()", async (t) => { mf.install(); Loading src/federation/middleware.ts +4 −0 Original line number Diff line number Diff line Loading @@ -372,6 +372,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { documentLoader: DocumentLoader; contextLoader: DocumentLoader; authenticatedDocumentLoaderFactory: AuthenticatedDocumentLoaderFactory; allowPrivateAddress: boolean; userAgent?: GetUserAgentOptions | string; onOutboxError?: OutboxErrorHandler; signatureTimeWindow: Temporal.Duration | Temporal.DurationLike | false; Loading Loading @@ -429,6 +430,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { } } const { allowPrivateAddress, userAgent } = options; this.allowPrivateAddress = allowPrivateAddress ?? false; this.documentLoader = options.documentLoader ?? kvCache({ loader: getDocumentLoader({ allowPrivateAddress, userAgent }), kv: options.kv, Loading Loading @@ -2882,6 +2884,8 @@ export class ContextImpl<TContextData> implements Context<TContextData> { contextLoader: options.contextLoader ?? this.contextLoader, userAgent: options.userAgent ?? this.federation.userAgent, tracerProvider: options.tracerProvider ?? this.tracerProvider, // @ts-ignore: `allowPrivateAddress` is not in the type definition. allowPrivateAddress: this.federation.allowPrivateAddress, }); } Loading src/vocab/lookup.ts +3 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,9 @@ async function lookupObjectInternal( const jrd = await lookupWebFinger(identifier, { userAgent: options.userAgent, tracerProvider: options.tracerProvider, // @ts-ignore: `allowPrivateAddress` is not in the type definition. allowPrivateAddress: "allowPrivateAddress" in options && options.allowPrivateAddress, }); if (jrd?.links == null) return null; for (const l of jrd.links) { Loading src/webfinger/lookup.test.ts +2 −6 Original line number Diff line number Diff line import { assertEquals, assertRejects } from "@std/assert"; import { assertEquals } from "@std/assert"; import { deadline } from "@std/async/deadline"; import * as mf from "mock_fetch"; import { UrlError } from "../runtime/url.ts"; import { test } from "../testing/mod.ts"; import type { ResourceDescriptor } from "./jrd.ts"; import { lookupWebFinger } from "./lookup.ts"; Loading Loading @@ -133,10 +132,7 @@ test("lookupWebFinger()", async (t) => { ); await t.step("redirection to private address", async () => { await assertRejects( () => lookupWebFinger("acct:johndoe@example.com"), UrlError, ); assertEquals(await lookupWebFinger("acct:johndoe@example.com"), null); }); mf.uninstall(); Loading Loading
CHANGES.md +8 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,14 @@ Version 1.3.5 To be released. - Fixed a bug where `CreateFederationOptions.allowPrivateAddress` option had been ignored by the `Context.lookupObject()` method when it had taken a fediverse handle. - The `lookupWebFinger()` function became to silently return `null` when it fails to fetch the WebFinger document due to accessing a private network address, instead of throwing a `UrlError`. Version 1.3.4 ------------- Loading
src/federation/middleware.test.ts +56 −0 Original line number Diff line number Diff line Loading @@ -1016,6 +1016,62 @@ test("FederationImpl.sendActivity()", async (t) => { mf.uninstall(); }); test("ContextImpl.lookupObject()", async (t) => { // Note that this test only checks if allowPrivateAddress option affects // the ContextImpl.lookupObject() method. Other aspects of the method are // tested in the lookupObject() tests. mf.install(); mf.mock("GET@/.well-known/webfinger", () => new Response( JSON.stringify({ subject: "acct:test@localhost", links: [ { rel: "self", type: "application/activity+json", href: "https://localhost/actor", }, ], }), { headers: { "Content-Type": "application/jrd+json" } }, )); mf.mock("GET@/actor", () => new Response( JSON.stringify({ "@context": "https://www.w3.org/ns/activitystreams", "type": "Person", "id": "https://localhost/actor", "preferredUsername": "test", }), { headers: { "Content-Type": "application/activity+json" } }, )); await t.step("allowPrivateAddress: true", async () => { const federation = createFederation<void>({ kv: new MemoryKvStore(), allowPrivateAddress: true, }); const ctx = federation.createContext(new URL("https://example.com/")); const result = await ctx.lookupObject("@test@localhost"); assertInstanceOf(result, Person); assertEquals(result.id, new URL("https://localhost/actor")); assertEquals(result.preferredUsername, "test"); }); await t.step("allowPrivateAddress: false", async () => { const federation = createFederation<void>({ kv: new MemoryKvStore(), allowPrivateAddress: false, }); const ctx = federation.createContext(new URL("https://example.com/")); const result = await ctx.lookupObject("@test@localhost"); assertEquals(result, null); }); mf.uninstall(); }); test("ContextImpl.sendActivity()", async (t) => { mf.install(); Loading
src/federation/middleware.ts +4 −0 Original line number Diff line number Diff line Loading @@ -372,6 +372,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { documentLoader: DocumentLoader; contextLoader: DocumentLoader; authenticatedDocumentLoaderFactory: AuthenticatedDocumentLoaderFactory; allowPrivateAddress: boolean; userAgent?: GetUserAgentOptions | string; onOutboxError?: OutboxErrorHandler; signatureTimeWindow: Temporal.Duration | Temporal.DurationLike | false; Loading Loading @@ -429,6 +430,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { } } const { allowPrivateAddress, userAgent } = options; this.allowPrivateAddress = allowPrivateAddress ?? false; this.documentLoader = options.documentLoader ?? kvCache({ loader: getDocumentLoader({ allowPrivateAddress, userAgent }), kv: options.kv, Loading Loading @@ -2882,6 +2884,8 @@ export class ContextImpl<TContextData> implements Context<TContextData> { contextLoader: options.contextLoader ?? this.contextLoader, userAgent: options.userAgent ?? this.federation.userAgent, tracerProvider: options.tracerProvider ?? this.tracerProvider, // @ts-ignore: `allowPrivateAddress` is not in the type definition. allowPrivateAddress: this.federation.allowPrivateAddress, }); } Loading
src/vocab/lookup.ts +3 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,9 @@ async function lookupObjectInternal( const jrd = await lookupWebFinger(identifier, { userAgent: options.userAgent, tracerProvider: options.tracerProvider, // @ts-ignore: `allowPrivateAddress` is not in the type definition. allowPrivateAddress: "allowPrivateAddress" in options && options.allowPrivateAddress, }); if (jrd?.links == null) return null; for (const l of jrd.links) { Loading
src/webfinger/lookup.test.ts +2 −6 Original line number Diff line number Diff line import { assertEquals, assertRejects } from "@std/assert"; import { assertEquals } from "@std/assert"; import { deadline } from "@std/async/deadline"; import * as mf from "mock_fetch"; import { UrlError } from "../runtime/url.ts"; import { test } from "../testing/mod.ts"; import type { ResourceDescriptor } from "./jrd.ts"; import { lookupWebFinger } from "./lookup.ts"; Loading Loading @@ -133,10 +132,7 @@ test("lookupWebFinger()", async (t) => { ); await t.step("redirection to private address", async () => { await assertRejects( () => lookupWebFinger("acct:johndoe@example.com"), UrlError, ); assertEquals(await lookupWebFinger("acct:johndoe@example.com"), null); }); mf.uninstall(); Loading