Unverified Commit b38fbab5 authored by Hong Minhee's avatar Hong Minhee
Browse files

Fix idempotence check in inbox listeners

... to ensure activities for different origins are processed correctly
parent 76d6c884
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -8,6 +8,9 @@ Version 1.0.12

To be released.

 -  Fixed idempotence check in inbox listeners to ensure activities for
    different origins are processed correctly.


Version 1.0.11
--------------
+5 −3
Original line number Diff line number Diff line
@@ -523,9 +523,11 @@ export async function handleInbox<TContextData>(
    }
    activity = await Activity.fromJsonLd(jsonWithoutSig, context);
  }
  const cacheKey = activity.id == null
    ? null
    : [...kvPrefixes.activityIdempotence, activity.id.href] satisfies KvKey;
  const cacheKey = activity.id == null ? null : [
    ...kvPrefixes.activityIdempotence,
    context.origin,
    activity.id.href,
  ] satisfies KvKey;
  if (cacheKey != null) {
    const cached = await kv.get(cacheKey);
    if (cached === true) {
+33 −1
Original line number Diff line number Diff line
@@ -665,10 +665,11 @@ test("Federation.setInboxListeners()", async (t) => {
    assertEquals(response.status, 401);

    // Personal inbox + HTTP Signatures (RSA)
    const activityPayload = await activity().toJsonLd(options);
    let request = new Request("https://example.com/users/john/inbox", {
      method: "POST",
      headers: { "Content-Type": "application/activity+json" },
      body: JSON.stringify(await activity().toJsonLd(options)),
      body: JSON.stringify(activityPayload),
    });
    request = await signRequest(
      request,
@@ -687,6 +688,37 @@ test("Federation.setInboxListeners()", async (t) => {
      ["https://example.com/person", "https://example.com/users/john#main-key"],
    ]);

    // Idempotence check
    response = await federation.fetch(request, { contextData: undefined });
    assertEquals(inbox.length, 1);

    // Idempotence check with different origin (host)
    inbox.shift();
    request = new Request("https://another.host/users/john/inbox", {
      method: "POST",
      headers: { "Content-Type": "application/activity+json" },
      body: JSON.stringify(activityPayload),
    });
    request = await signRequest(
      request,
      rsaPrivateKey3,
      new URL("https://example.com/person2#key3"),
    );
    response = await federation.fetch(request, { contextData: undefined });
    assertEquals(inbox.length, 1);
    assertEquals(inbox[0][1].actorId, new URL("https://example.com/person2"));
    assertEquals(response.status, 202);

    while (authenticatedRequests.length > 0) authenticatedRequests.shift();
    assertEquals(authenticatedRequests, []);
    await inbox[0][0].documentLoader("https://example.com/person");
    assertEquals(authenticatedRequests, [
      [
        "https://example.com/person",
        "https://another.host/users/john#main-key",
      ],
    ]);

    // Shared inbox + HTTP Signatures (RSA)
    inbox.shift();
    request = new Request("https://example.com/inbox", {
+1 −0
Original line number Diff line number Diff line
@@ -505,6 +505,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> {
    const activity = await Activity.fromJsonLd(message.activity, context);
    const cacheKey = activity.id == null ? null : [
      ...this.kvPrefixes.activityIdempotence,
      context.origin,
      activity.id.href,
    ] satisfies KvKey;
    if (cacheKey != null) {