From ceb0c9812dbed61efc9326b7e1343aa6acd3b996 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Fri, 27 Mar 2026 04:51:30 +0100 Subject: [PATCH] fix(federation): resolve code review issues in upload size mismatch - Fix critical: outbox worker now copies file_rejected payload fields (attachmentId, sourceFilename, rejectionReason, rejectionLimit, affectedUserIds) so the reverse relay actually delivers them - Fix: add sourceFilename to file_rejected event for reliable multi-attachment matching on the sender side - Fix: change text-accent-warning to text-accent-amber (valid class) - Add Array.isArray guard on federationMeta parse --- packages/server/src/routes/federation.ts | 16 ++++++++-------- packages/server/src/utils/federationWorker.ts | 10 ++++++++++ packages/shared/src/types.ts | 1 + .../src/components/chat/AttachmentRenderer.tsx | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/packages/server/src/routes/federation.ts b/packages/server/src/routes/federation.ts index 62962ec7..fe94a046 100644 --- a/packages/server/src/routes/federation.ts +++ b/packages/server/src/routes/federation.ts @@ -2312,14 +2312,13 @@ function processFileRejectedEvent( .where(eq(schema.attachments.dmMessageId, localMsg.id)) .all(); - // The attachmentId from the remote is their local attachment ID, not ours. - // Match by sourceUrl instead — the remote's sourceUrl points to our upload endpoint. - const ourOrigin = getOurOrigin(); - let matchedAttachment = messageAttachments.find(a => - a.sourceUrl && a.sourceUrl.startsWith(ourOrigin), - ); + // Match by filename from the sourceUrl — the remote sends the filename portion + // (e.g., "12345.png") which matches our local attachment's filename. + let matchedAttachment = event.sourceFilename + ? messageAttachments.find(a => a.filename === event.sourceFilename) + : undefined; - // If only one attachment, use it directly + // Fallback: if only one attachment, use it directly if (!matchedAttachment && messageAttachments.length === 1) { matchedAttachment = messageAttachments[0]; } @@ -2357,7 +2356,8 @@ function processFileRejectedEvent( let existingMeta: Array<{ userId: string; username: string; limit: number }> = []; if (matchedAttachment.federationMeta) { try { - existingMeta = JSON.parse(matchedAttachment.federationMeta); + const parsed = JSON.parse(matchedAttachment.federationMeta); + existingMeta = Array.isArray(parsed) ? parsed : []; } catch { /* ignore parse errors */ } } diff --git a/packages/server/src/utils/federationWorker.ts b/packages/server/src/utils/federationWorker.ts index 40e60d02..67990aaf 100644 --- a/packages/server/src/utils/federationWorker.ts +++ b/packages/server/src/utils/federationWorker.ts @@ -179,6 +179,12 @@ async function processOutboxTick(): Promise { if (parsed.ownership) evt.ownership = parsed.ownership; if (parsed.group) evt.group = parsed.group; if (parsed.friendship) evt.friendship = parsed.friendship; + // file_rejected event fields + if (parsed.attachmentId) evt.attachmentId = parsed.attachmentId; + if (parsed.sourceFilename) evt.sourceFilename = parsed.sourceFilename; + if (parsed.rejectionReason) evt.rejectionReason = parsed.rejectionReason; + if (parsed.rejectionLimit != null) evt.rejectionLimit = parsed.rejectionLimit; + if (parsed.affectedUserIds) evt.affectedUserIds = parsed.affectedUserIds; return evt; }); @@ -420,12 +426,16 @@ function handleSizeRejection( } // Queue a file_rejected reverse relay event to the sender's instance + // Extract the filename from the sourceUrl (e.g., "https://sender/api/uploads/12345.png" → "12345.png") + const sourceFilename = entry.sourceUrl.split('/').pop() ?? entry.sourceUrl; + const event: FederationRelayEvent = { eventType: 'file_rejected', messageId: localMsg.sourceMessageId, encryptionVersion: 0, timestamp: now, attachmentId: att?.id ?? entry.sourceUrl, + sourceFilename, rejectionReason: 'size_limit_exceeded', rejectionLimit: maxUploadSize, affectedUserIds, diff --git a/packages/shared/src/types.ts b/packages/shared/src/types.ts index 2791f20d..a77f707b 100644 --- a/packages/shared/src/types.ts +++ b/packages/shared/src/types.ts @@ -770,6 +770,7 @@ export interface FederationRelayEvent { friendship?: FederationFriendshipPayload; // file_rejected event fields attachmentId?: string; + sourceFilename?: string; rejectionReason?: string; rejectionLimit?: number; affectedUserIds?: string[]; diff --git a/packages/web/src/components/chat/AttachmentRenderer.tsx b/packages/web/src/components/chat/AttachmentRenderer.tsx index de132636..1361fcf5 100644 --- a/packages/web/src/components/chat/AttachmentRenderer.tsx +++ b/packages/web/src/components/chat/AttachmentRenderer.tsx @@ -70,7 +70,7 @@ export function AttachmentRenderer({ attachment }: AttachmentRendererProps) { } return ( -
+