diff --git a/CHANGES.md b/CHANGES.md index db9527ee..ca31f6b0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,21 @@ Version 2.0.2 To be released. +### @fedify/fedify + + - Removed the deprecated third and fourth parameters (`signedKey` and + `signedKeyOwner`) from `AuthorizePredicate` and + `ObjectAuthorizePredicate`. These parameters were deprecated since + Fedify 1.5.0 in favor of `RequestContext.getSignedKey()` and + `RequestContext.getSignedKeyOwner()` methods, but were mistakenly + left in the Fedify 2.0.0 release. The internal handler code that + eagerly called `getSignedKey()` and `getSignedKeyOwner()` before + invoking the predicate has also been removed; predicates should now + call those methods themselves when needed. [[#473], [#590]] + +[#473]: https://github.com/fedify-dev/fedify/issues/473 +[#590]: https://github.com/fedify-dev/fedify/pull/590 + Version 2.0.1 ------------- diff --git a/docs/manual/collections.md b/docs/manual/collections.md index d888a031..6fabf623 100644 --- a/docs/manual/collections.md +++ b/docs/manual/collections.md @@ -1690,8 +1690,9 @@ federation } ) .setFirstCursor(async (ctx, values) => "") - .authorize(async (ctx, values, signedKey, signedKeyOwner) => { + .authorize(async (ctx, values) => { // Only allow access if the viewer is the owner of the bookmarks + const signedKeyOwner = await ctx.getSignedKeyOwner(); if (signedKeyOwner == null) return false; const viewerId = await getActorIdentifier(signedKeyOwner.id); diff --git a/packages/fedify/src/federation/callback.ts b/packages/fedify/src/federation/callback.ts index 6ac9a1a1..94bc12f7 100644 --- a/packages/fedify/src/federation/callback.ts +++ b/packages/fedify/src/federation/callback.ts @@ -1,4 +1,4 @@ -import type { Activity, Actor, CryptographicKey, Object } from "@fedify/vocab"; +import type { Activity, Actor, Object } from "@fedify/vocab"; import type { Link } from "@fedify/webfinger"; import type { NodeInfo } from "../nodeinfo/types.ts"; import type { PageItems } from "./collection.ts"; @@ -273,25 +273,14 @@ export type OutboxPermanentFailureHandler = ( * * @template TContextData The context data to pass to the {@link Context}. * @param context The request context. - * @param identifier The internal identifier of the actor that is being requested. - * @param signedKey *Deprecated in Fedify 1.5.0 in favor of - * {@link RequestContext.getSignedKey} method.* - * The key that was used to sign the request, or `null` if - * the request was not signed or the signature was invalid. - * @param signedKeyOwner *Deprecated in Fedify 1.5.0 in favor of - * {@link RequestContext.getSignedKeyOwner} method.* - * The actor that owns the key that was used to sign the - * request, or `null` if the request was not signed or the - * signature was invalid, or if the key is not associated - * with an actor. + * @param identifier The internal identifier of the actor that is being + * requested. * @returns `true` if the request is authorized, `false` otherwise. * @since 0.7.0 */ export type AuthorizePredicate = ( context: RequestContext, identifier: string, - signedKey: CryptographicKey | null, - signedKeyOwner: Actor | null, ) => boolean | Promise; /** @@ -301,24 +290,12 @@ export type AuthorizePredicate = ( * @template TParam The parameter names of the requested URL. * @param context The request context. * @param values The parameters of the requested URL. - * @param signedKey *Deprecated in Fedify 1.5.0 in favor of - * {@link RequestContext.getSignedKey} method.* - * The key that was used to sign the request, or `null` if - * the request was not signed or the signature was invalid. - * @param signedKeyOwner *Deprecated in Fedify 1.5.0 in favor of - * {@link RequestContext.getSignedKeyOwner} method.* - * The actor that owns the key that was used to sign the - * request, or `null` if the request was not signed or the - * signature was invalid, or if the key is not associated - * with an actor. * @returns `true` if the request is authorized, `false` otherwise. * @since 0.7.0 */ export type ObjectAuthorizePredicate = ( context: RequestContext, values: Record, - signedKey: CryptographicKey | null, - signedKeyOwner: Actor | null, ) => boolean | Promise; /** diff --git a/packages/fedify/src/federation/handler.test.ts b/packages/fedify/src/federation/handler.test.ts index 1dd257c2..1add1f6d 100644 --- a/packages/fedify/src/federation/handler.test.ts +++ b/packages/fedify/src/federation/handler.test.ts @@ -193,8 +193,9 @@ test("handleActor()", async () => { context, identifier: "someone", actorDispatcher, - authorizePredicate: (_ctx, _handle, signedKey, signedKeyOwner) => - signedKey != null && signedKeyOwner != null, + authorizePredicate: async (ctx, _handle) => + await ctx.getSignedKey() != null && + await ctx.getSignedKeyOwner() != null, onNotFound, onUnauthorized, }, @@ -215,8 +216,9 @@ test("handleActor()", async () => { context, identifier: "someone", actorDispatcher, - authorizePredicate: (_ctx, _handle, signedKey, signedKeyOwner) => - signedKey != null && signedKeyOwner != null, + authorizePredicate: async (ctx, _handle) => + await ctx.getSignedKey() != null && + await ctx.getSignedKeyOwner() != null, onNotFound, onUnauthorized, }, @@ -452,8 +454,9 @@ test("handleObject()", async () => { context, values: { identifier: "someone", id: "123" }, objectDispatcher, - authorizePredicate: (_ctx, _values, signedKey, signedKeyOwner) => - signedKey != null && signedKeyOwner != null, + authorizePredicate: async (ctx, _values) => + await ctx.getSignedKey() != null && + await ctx.getSignedKeyOwner() != null, onNotFound, onUnauthorized, }, @@ -474,8 +477,9 @@ test("handleObject()", async () => { context, values: { identifier: "someone", id: "123" }, objectDispatcher, - authorizePredicate: (_ctx, _values, signedKey, signedKeyOwner) => - signedKey != null && signedKeyOwner != null, + authorizePredicate: async (ctx, _values) => + await ctx.getSignedKey() != null && + await ctx.getSignedKeyOwner() != null, onNotFound, onUnauthorized, }, @@ -751,8 +755,9 @@ test("handleCollection()", async () => { }, collectionCallbacks: { dispatcher, - authorizePredicate: (_ctx, _handle, key, keyOwner) => - key != null && keyOwner != null, + authorizePredicate: async (ctx, _handle) => + await ctx.getSignedKey() != null && + await ctx.getSignedKeyOwner() != null, }, onNotFound, onUnauthorized, @@ -779,8 +784,9 @@ test("handleCollection()", async () => { }, collectionCallbacks: { dispatcher, - authorizePredicate: (_ctx, _handle, key, keyOwner) => - key != null && keyOwner != null, + authorizePredicate: async (ctx, _handle) => + await ctx.getSignedKey() != null && + await ctx.getSignedKeyOwner() != null, }, onNotFound, onUnauthorized, @@ -1634,8 +1640,9 @@ test("handleCustomCollection()", async () => { values: { identifier: "someone" }, collectionCallbacks: { dispatcher, - authorizePredicate: (_ctx, _values, key, keyOwner) => - key != null && keyOwner != null, + authorizePredicate: async (ctx, _values) => + await ctx.getSignedKey() != null && + await ctx.getSignedKeyOwner() != null, }, ...errorHandlers, }, @@ -1659,8 +1666,9 @@ test("handleCustomCollection()", async () => { values: { identifier: "someone" }, collectionCallbacks: { dispatcher, - authorizePredicate: (_ctx, _values, key, keyOwner) => - key != null && keyOwner != null, + authorizePredicate: async (ctx, _values) => + await ctx.getSignedKey() != null && + await ctx.getSignedKeyOwner() != null, }, ...errorHandlers, }, diff --git a/packages/fedify/src/federation/handler.ts b/packages/fedify/src/federation/handler.ts index 15331df9..cb09e477 100644 --- a/packages/fedify/src/federation/handler.ts +++ b/packages/fedify/src/federation/handler.ts @@ -92,27 +92,7 @@ export async function handleActor( return await onNotFound(request); } if (authorizePredicate != null) { - let key = await context.getSignedKey(); - key = key?.clone({}, { - // @ts-expect-error: $warning is not part of the type definition - $warning: { - category: ["fedify", "federation", "actor"], - message: "The third parameter of AuthorizePredicate is deprecated " + - "in favor of RequestContext.getSignedKey() method. The third " + - "parameter will be removed in a future release.", - }, - }) ?? null; - let keyOwner = await context.getSignedKeyOwner(); - keyOwner = keyOwner?.clone({}, { - // @ts-expect-error: $warning is not part of the type definition - $warning: { - category: ["fedify", "federation", "actor"], - message: "The fourth parameter of AuthorizePredicate is deprecated " + - "in favor of RequestContext.getSignedKeyOwner() method. The " + - "fourth parameter will be removed in a future release.", - }, - }) ?? null; - if (!await authorizePredicate(context, identifier, key, keyOwner)) { + if (!await authorizePredicate(context, identifier)) { return await onUnauthorized(request); } } @@ -160,27 +140,7 @@ export async function handleObject( const object = await objectDispatcher(context, values); if (object == null) return await onNotFound(request); if (authorizePredicate != null) { - let key = await context.getSignedKey(); - key = key?.clone({}, { - // @ts-expect-error: $warning is not part of the type definition - $warning: { - category: ["fedify", "federation", "object"], - message: "The third parameter of ObjectAuthorizePredicate is " + - "deprecated in favor of RequestContext.getSignedKey() method. " + - "The third parameter will be removed in a future release.", - }, - }) ?? null; - let keyOwner = await context.getSignedKeyOwner(); - keyOwner = keyOwner?.clone({}, { - // @ts-expect-error: $warning is not part of the type definition - $warning: { - category: ["fedify", "federation", "object"], - message: "The fourth parameter of ObjectAuthorizePredicate is " + - "deprecated in favor of RequestContext.getSignedKeyOwner() method. " + - "The fourth parameter will be removed in a future release.", - }, - }) ?? null; - if (!await authorizePredicate(context, values, key, keyOwner)) { + if (!await authorizePredicate(context, values)) { return await onUnauthorized(request); } } @@ -430,34 +390,8 @@ export async function handleCollection< }); } if (collectionCallbacks.authorizePredicate != null) { - let key = await context.getSignedKey(); - key = key?.clone({}, { - // @ts-expect-error: $warning is not part of the type definition - $warning: { - category: ["fedify", "federation", "collection"], - message: "The third parameter of AuthorizePredicate is deprecated in " + - "favor of RequestContext.getSignedKey() method. The third " + - "parameter will be removed in a future release.", - }, - }) ?? null; - let keyOwner = await context.getSignedKeyOwner(); - keyOwner = keyOwner?.clone({}, { - // @ts-expect-error: $warning is not part of the type definition - $warning: { - category: ["fedify", "federation", "collection"], - message: - "The fourth parameter of AuthorizePredicate is deprecated in " + - "favor of RequestContext.getSignedKeyOwner() method. The fourth " + - "parameter will be removed in a future release.", - }, - }) ?? null; if ( - !await collectionCallbacks.authorizePredicate( - context, - identifier, - key, - keyOwner, - ) + !await collectionCallbacks.authorizePredicate(context, identifier) ) { return await onUnauthorized(request); } @@ -1468,38 +1402,11 @@ const authIfNeeded = async ( }, ): Promise => { if (authorize === undefined) return; - const key = (await context.getSignedKey()) - // @ts-expect-error: $warning is not part of the type definition - ?.clone({}, warning.key) ?? null; - const keyOwner = (await context.getSignedKeyOwner()) - // @ts-expect-error: $warning is not part of the type definition - ?.clone({}, warning.keyOwner) ?? null; - if (!await authorize(context, values, key, keyOwner)) { + if (!await authorize(context, values)) { throw new UnauthorizedError(); } }; -/** Warning messages for `authIfNeeded`. */ -const warning = { - key: { - $warning: { - category: ["fedify", "federation", "collection"], - message: - "The third parameter of AuthorizePredicate is deprecated in favor of " + - "RequestContext.getSignedKey() method. The third parameter will be " + - "removed in a future release.", - }, - }, - keyOwner: { - $warning: { - category: ["fedify", "federation", "collection"], - message: "The fourth parameter of AuthorizePredicate is deprecated in " + - "favor of RequestContext.getSignedKeyOwner() method. The fourth " + - "parameter will be removed in a future release.", - }, - }, -} as const; - /** * Appends a cursor parameter to a URL if the cursor exists. * @template Cursor The type of the cursor (string, null, or undefined).