From d415fd29a3b0fb7f337423fff8318ec393928875 Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sat, 6 Jan 2024 09:07:48 +0900 Subject: [PATCH] =?UTF-8?q?enhance(backend):=20ActivityPub=20Deliver=20que?= =?UTF-8?q?ue=E3=81=A7Body=E3=82=92=E4=BA=8B=E5=89=8D=E5=87=A6=E7=90=86?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20(#12916)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Pre-processing deliver body * CHANGELOG * ループ内で計算されると意味がないので * 同じ処理を同じ形に --------- Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com> --- CHANGELOG.md | 3 +++ packages/backend/src/core/QueueService.ts | 12 ++++++++++-- .../src/core/activitypub/ApRequestService.ts | 13 +++++++++---- .../src/queue/processors/DeliverProcessorService.ts | 2 +- packages/backend/src/queue/types.ts | 4 +++- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54fbb04120..f4fe8de755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ - Fix: v2023.12.0で追加された「モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能」が管理画面上で正しく表示されていない問題を修正 - Enhance: チャンネルノートのピン留めをノートのメニューからできるよ +### Server +- Enhance: ActivityPub Deliver queueでBodyを事前処理するように (#12916) + ## 2023.12.2 ### General diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index be378a899b..4f99dee64e 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -16,6 +16,7 @@ import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, Obj import type { DbJobData, DeliverJobData, RelationshipJobData, ThinUser } from '../queue/types.js'; import type httpSignature from '@peertube/http-signature'; import type * as Bull from 'bullmq'; +import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js'; @Injectable() export class QueueService { @@ -74,11 +75,15 @@ export class QueueService { if (content == null) return null; if (to == null) return null; + const contentBody = JSON.stringify(content); + const digest = ApRequestCreator.createDigest(contentBody); + const data: DeliverJobData = { user: { id: user.id, }, - content, + content: contentBody, + digest, to, isSharedInbox, }; @@ -103,6 +108,8 @@ export class QueueService { @bindThis public async deliverMany(user: ThinUser, content: IActivity | null, inboxes: Map) { if (content == null) return null; + const contentBody = JSON.stringify(content); + const digest = ApRequestCreator.createDigest(contentBody); const opts = { attempts: this.config.deliverJobMaxAttempts ?? 12, @@ -117,7 +124,8 @@ export class QueueService { name: d[0], data: { user, - content, + content: contentBody, + digest, to: d[0], isSharedInbox: d[1], } as DeliverJobData, diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts index b59ce5241f..e165c5e960 100644 --- a/packages/backend/src/core/activitypub/ApRequestService.ts +++ b/packages/backend/src/core/activitypub/ApRequestService.ts @@ -34,9 +34,9 @@ type PrivateKey = { }; export class ApRequestCreator { - static createSignedPost(args: { key: PrivateKey, url: string, body: string, additionalHeaders: Record }): Signed { + static createSignedPost(args: { key: PrivateKey, url: string, body: string, digest?: string, additionalHeaders: Record }): Signed { const u = new URL(args.url); - const digestHeader = `SHA-256=${crypto.createHash('sha256').update(args.body).digest('base64')}`; + const digestHeader = args.digest ?? this.createDigest(args.body); const request: Request = { url: u.href, @@ -59,6 +59,10 @@ export class ApRequestCreator { }; } + static createDigest(body: string) { + return `SHA-256=${crypto.createHash('sha256').update(body).digest('base64')}`; + } + static createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record }): Signed { const u = new URL(args.url); @@ -145,8 +149,8 @@ export class ApRequestService { } @bindThis - public async signedPost(user: { id: MiUser['id'] }, url: string, object: unknown): Promise { - const body = JSON.stringify(object); + public async signedPost(user: { id: MiUser['id'] }, url: string, object: unknown, digest?: string): Promise { + const body = typeof object === 'string' ? object : JSON.stringify(object); const keypair = await this.userKeypairService.getUserKeypair(user.id); @@ -157,6 +161,7 @@ export class ApRequestService { }, url, body, + digest, additionalHeaders: { }, }); diff --git a/packages/backend/src/queue/processors/DeliverProcessorService.ts b/packages/backend/src/queue/processors/DeliverProcessorService.ts index 4a1d9f28b4..675eccbe34 100644 --- a/packages/backend/src/queue/processors/DeliverProcessorService.ts +++ b/packages/backend/src/queue/processors/DeliverProcessorService.ts @@ -72,7 +72,7 @@ export class DeliverProcessorService { } try { - await this.apRequestService.signedPost(job.data.user, job.data.to, job.data.content); + await this.apRequestService.signedPost(job.data.user, job.data.to, job.data.content, job.data.digest); // Update stats this.federatedInstanceService.fetch(host).then(i => { diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts index 9330c01528..5a9952e807 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -15,7 +15,9 @@ export type DeliverJobData = { /** Actor */ user: ThinUser; /** Activity */ - content: unknown; + content: string; + /** Digest header */ + digest: string; /** inbox URL to deliver */ to: string; /** whether it is sharedInbox */