Loading federation/context.ts +8 −1 Original line number Diff line number Diff line import { DocumentLoader } from "../runtime/docloader.ts"; import { Actor } from "../vocab/actor.ts"; import { Activity } from "../vocab/mod.ts"; import { Activity, CryptographicKey } from "../vocab/mod.ts"; /** * A context. Loading Loading @@ -37,6 +37,13 @@ export interface Context<TContextData> { */ getInboxUri(handle: string): URL; /** * Gets a public {@link CryptographicKey} for an actor, if any exists. * @param handle The actor's handle. * @returns The actor's public key, or `null` if the actor has no key. */ getActorKey(handle: string): Promise<CryptographicKey | null>; /** * Sends an activity to recipients' inboxes. * @param sender The sender's handle or sender's key pair. Loading federation/handler.ts +2 −31 Original line number Diff line number Diff line import { accepts } from "https://deno.land/std@0.217.0/http/mod.ts"; import { ActorDispatcher, ActorKeyPairDispatcher, InboxListener, OutboxCounter, OutboxCursor, Loading @@ -16,7 +15,6 @@ import { OrderedCollection, OrderedCollectionPage, } from "../vocab/mod.ts"; import { CryptographicKey } from "../vocab/mod.ts"; function acceptsJsonLd(request: Request): boolean { const types = accepts(request); Loading @@ -28,25 +26,11 @@ function acceptsJsonLd(request: Request): boolean { types.includes("application/json"); } export function getActorKey<TContextData>( context: RequestContext<TContextData>, handle: string, keyPair?: CryptoKeyPair | null, ): CryptographicKey | null { if (keyPair == null) return null; return new CryptographicKey({ id: new URL(`${context.getActorUri(handle)}#main-key`), owner: context.getActorUri(handle), publicKey: keyPair.publicKey, }); } export interface ActorHandlerParameters<TContextData> { handle: string; context: RequestContext<TContextData>; documentLoader: DocumentLoader; actorDispatcher?: ActorDispatcher<TContextData>; actorKeyPairDispatcher?: ActorKeyPairDispatcher<TContextData>; onNotFound(request: Request): Response | Promise<Response>; onNotAcceptable(request: Request): Response | Promise<Response>; } Loading @@ -58,7 +42,6 @@ export async function handleActor<TContextData>( context, documentLoader, actorDispatcher, actorKeyPairDispatcher, onNotFound, onNotAcceptable, }: ActorHandlerParameters<TContextData>, Loading @@ -71,12 +54,7 @@ export async function handleActor<TContextData>( const response = onNotAcceptable(request); return response instanceof Promise ? await response : response; } const keyPair = actorKeyPairDispatcher?.(context.data, handle); const key = getActorKey( context, handle, keyPair instanceof Promise ? await keyPair : keyPair, ); const key = await context.getActorKey(handle); const actor = await actorDispatcher(context, handle, key); if (actor == null) { const response = onNotFound(request); Loading Loading @@ -209,7 +187,6 @@ export interface InboxHandlerParameters<TContextData> { handle: string; context: RequestContext<TContextData>; actorDispatcher?: ActorDispatcher<TContextData>; actorKeyPairDispatcher?: ActorKeyPairDispatcher<TContextData>; inboxListeners: Map< new (...args: unknown[]) => Activity, InboxListener<TContextData, Activity> Loading @@ -225,7 +202,6 @@ export async function handleInbox<TContextData>( handle, context, actorDispatcher, actorKeyPairDispatcher, inboxListeners, inboxErrorHandler, documentLoader, Loading @@ -236,12 +212,7 @@ export async function handleInbox<TContextData>( const response = onNotFound(request); return response instanceof Promise ? await response : response; } else { const keyPair = actorKeyPairDispatcher?.(context.data, handle); const key = getActorKey( context, handle, keyPair instanceof Promise ? await keyPair : keyPair, ); const key = await context.getActorKey(handle); const promise = actorDispatcher(context, handle, key); const actor = promise instanceof Promise ? await promise : promise; if (actor == null) { Loading federation/middleware.ts +14 −3 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import { kvCache, } from "../runtime/docloader.ts"; import { Actor } from "../vocab/actor.ts"; import { Activity } from "../vocab/mod.ts"; import { Activity, CryptographicKey } from "../vocab/mod.ts"; import { handleWebFinger } from "../webfinger/handler.ts"; import { ActorDispatcher, Loading Loading @@ -147,6 +147,19 @@ export class Federation<TContextData> { } return new URL(path, url); }, getActorKey: async (handle: string): Promise<CryptographicKey | null> => { let keyPair = this.#actorCallbacks?.keyPairDispatcher?.( contextData, handle, ); if (keyPair instanceof Promise) keyPair = await keyPair; if (keyPair == null) return null; return new CryptographicKey({ id: new URL(`${context.getActorUri(handle)}#main-key`), owner: context.getActorUri(handle), publicKey: keyPair.publicKey, }); }, sendActivity: async ( sender: { keyId: URL; privateKey: CryptoKey } | { handle: string }, recipients: Actor | Actor[], Loading Loading @@ -368,7 +381,6 @@ export class Federation<TContextData> { context, documentLoader: this.#documentLoader, actorDispatcher: this.#actorCallbacks?.dispatcher, actorKeyPairDispatcher: this.#actorCallbacks?.keyPairDispatcher, onNotFound, onNotAcceptable, }); Loading @@ -390,7 +402,6 @@ export class Federation<TContextData> { context, documentLoader: this.#documentLoader, actorDispatcher: this.#actorCallbacks?.dispatcher, actorKeyPairDispatcher: this.#actorCallbacks?.keyPairDispatcher, inboxListeners: this.#inboxListeners, inboxErrorHandler: this.#inboxErrorHandler, onNotFound, Loading webfinger/handler.ts +2 −13 Original line number Diff line number Diff line import { RequestContext } from "../federation/context.ts"; import { ActorDispatcher, ActorKeyPairDispatcher, } from "../federation/callback.ts"; import { getActorKey } from "../federation/handler.ts"; import { ActorDispatcher } from "../federation/callback.ts"; import { Link as LinkObject } from "../vocab/mod.ts"; import { Link, ResourceDescriptor } from "./jrd.ts"; export interface WebFingerHandlerParameters<TContextData> { context: RequestContext<TContextData>; actorDispatcher?: ActorDispatcher<TContextData>; actorKeyPairDispatcher?: ActorKeyPairDispatcher<TContextData>; onNotFound(request: Request): Response | Promise<Response>; } Loading @@ -19,7 +14,6 @@ export async function handleWebFinger<TContextData>( { context, actorDispatcher, actorKeyPairDispatcher, onNotFound, }: WebFingerHandlerParameters<TContextData>, ): Promise<Response> { Loading @@ -37,12 +31,7 @@ export async function handleWebFinger<TContextData>( return response instanceof Promise ? await response : response; } const handle = match[1]; const keyPair = actorKeyPairDispatcher?.(context.data, handle); const key = getActorKey( context, handle, keyPair instanceof Promise ? await keyPair : keyPair, ); const key = await context.getActorKey(handle); const actor = await actorDispatcher(context, handle, key); if (actor == null) { const response = onNotFound(request); Loading Loading
federation/context.ts +8 −1 Original line number Diff line number Diff line import { DocumentLoader } from "../runtime/docloader.ts"; import { Actor } from "../vocab/actor.ts"; import { Activity } from "../vocab/mod.ts"; import { Activity, CryptographicKey } from "../vocab/mod.ts"; /** * A context. Loading Loading @@ -37,6 +37,13 @@ export interface Context<TContextData> { */ getInboxUri(handle: string): URL; /** * Gets a public {@link CryptographicKey} for an actor, if any exists. * @param handle The actor's handle. * @returns The actor's public key, or `null` if the actor has no key. */ getActorKey(handle: string): Promise<CryptographicKey | null>; /** * Sends an activity to recipients' inboxes. * @param sender The sender's handle or sender's key pair. Loading
federation/handler.ts +2 −31 Original line number Diff line number Diff line import { accepts } from "https://deno.land/std@0.217.0/http/mod.ts"; import { ActorDispatcher, ActorKeyPairDispatcher, InboxListener, OutboxCounter, OutboxCursor, Loading @@ -16,7 +15,6 @@ import { OrderedCollection, OrderedCollectionPage, } from "../vocab/mod.ts"; import { CryptographicKey } from "../vocab/mod.ts"; function acceptsJsonLd(request: Request): boolean { const types = accepts(request); Loading @@ -28,25 +26,11 @@ function acceptsJsonLd(request: Request): boolean { types.includes("application/json"); } export function getActorKey<TContextData>( context: RequestContext<TContextData>, handle: string, keyPair?: CryptoKeyPair | null, ): CryptographicKey | null { if (keyPair == null) return null; return new CryptographicKey({ id: new URL(`${context.getActorUri(handle)}#main-key`), owner: context.getActorUri(handle), publicKey: keyPair.publicKey, }); } export interface ActorHandlerParameters<TContextData> { handle: string; context: RequestContext<TContextData>; documentLoader: DocumentLoader; actorDispatcher?: ActorDispatcher<TContextData>; actorKeyPairDispatcher?: ActorKeyPairDispatcher<TContextData>; onNotFound(request: Request): Response | Promise<Response>; onNotAcceptable(request: Request): Response | Promise<Response>; } Loading @@ -58,7 +42,6 @@ export async function handleActor<TContextData>( context, documentLoader, actorDispatcher, actorKeyPairDispatcher, onNotFound, onNotAcceptable, }: ActorHandlerParameters<TContextData>, Loading @@ -71,12 +54,7 @@ export async function handleActor<TContextData>( const response = onNotAcceptable(request); return response instanceof Promise ? await response : response; } const keyPair = actorKeyPairDispatcher?.(context.data, handle); const key = getActorKey( context, handle, keyPair instanceof Promise ? await keyPair : keyPair, ); const key = await context.getActorKey(handle); const actor = await actorDispatcher(context, handle, key); if (actor == null) { const response = onNotFound(request); Loading Loading @@ -209,7 +187,6 @@ export interface InboxHandlerParameters<TContextData> { handle: string; context: RequestContext<TContextData>; actorDispatcher?: ActorDispatcher<TContextData>; actorKeyPairDispatcher?: ActorKeyPairDispatcher<TContextData>; inboxListeners: Map< new (...args: unknown[]) => Activity, InboxListener<TContextData, Activity> Loading @@ -225,7 +202,6 @@ export async function handleInbox<TContextData>( handle, context, actorDispatcher, actorKeyPairDispatcher, inboxListeners, inboxErrorHandler, documentLoader, Loading @@ -236,12 +212,7 @@ export async function handleInbox<TContextData>( const response = onNotFound(request); return response instanceof Promise ? await response : response; } else { const keyPair = actorKeyPairDispatcher?.(context.data, handle); const key = getActorKey( context, handle, keyPair instanceof Promise ? await keyPair : keyPair, ); const key = await context.getActorKey(handle); const promise = actorDispatcher(context, handle, key); const actor = promise instanceof Promise ? await promise : promise; if (actor == null) { Loading
federation/middleware.ts +14 −3 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import { kvCache, } from "../runtime/docloader.ts"; import { Actor } from "../vocab/actor.ts"; import { Activity } from "../vocab/mod.ts"; import { Activity, CryptographicKey } from "../vocab/mod.ts"; import { handleWebFinger } from "../webfinger/handler.ts"; import { ActorDispatcher, Loading Loading @@ -147,6 +147,19 @@ export class Federation<TContextData> { } return new URL(path, url); }, getActorKey: async (handle: string): Promise<CryptographicKey | null> => { let keyPair = this.#actorCallbacks?.keyPairDispatcher?.( contextData, handle, ); if (keyPair instanceof Promise) keyPair = await keyPair; if (keyPair == null) return null; return new CryptographicKey({ id: new URL(`${context.getActorUri(handle)}#main-key`), owner: context.getActorUri(handle), publicKey: keyPair.publicKey, }); }, sendActivity: async ( sender: { keyId: URL; privateKey: CryptoKey } | { handle: string }, recipients: Actor | Actor[], Loading Loading @@ -368,7 +381,6 @@ export class Federation<TContextData> { context, documentLoader: this.#documentLoader, actorDispatcher: this.#actorCallbacks?.dispatcher, actorKeyPairDispatcher: this.#actorCallbacks?.keyPairDispatcher, onNotFound, onNotAcceptable, }); Loading @@ -390,7 +402,6 @@ export class Federation<TContextData> { context, documentLoader: this.#documentLoader, actorDispatcher: this.#actorCallbacks?.dispatcher, actorKeyPairDispatcher: this.#actorCallbacks?.keyPairDispatcher, inboxListeners: this.#inboxListeners, inboxErrorHandler: this.#inboxErrorHandler, onNotFound, Loading
webfinger/handler.ts +2 −13 Original line number Diff line number Diff line import { RequestContext } from "../federation/context.ts"; import { ActorDispatcher, ActorKeyPairDispatcher, } from "../federation/callback.ts"; import { getActorKey } from "../federation/handler.ts"; import { ActorDispatcher } from "../federation/callback.ts"; import { Link as LinkObject } from "../vocab/mod.ts"; import { Link, ResourceDescriptor } from "./jrd.ts"; export interface WebFingerHandlerParameters<TContextData> { context: RequestContext<TContextData>; actorDispatcher?: ActorDispatcher<TContextData>; actorKeyPairDispatcher?: ActorKeyPairDispatcher<TContextData>; onNotFound(request: Request): Response | Promise<Response>; } Loading @@ -19,7 +14,6 @@ export async function handleWebFinger<TContextData>( { context, actorDispatcher, actorKeyPairDispatcher, onNotFound, }: WebFingerHandlerParameters<TContextData>, ): Promise<Response> { Loading @@ -37,12 +31,7 @@ export async function handleWebFinger<TContextData>( return response instanceof Promise ? await response : response; } const handle = match[1]; const keyPair = actorKeyPairDispatcher?.(context.data, handle); const key = getActorKey( context, handle, keyPair instanceof Promise ? await keyPair : keyPair, ); const key = await context.getActorKey(handle); const actor = await actorDispatcher(context, handle, key); if (actor == null) { const response = onNotFound(request); Loading