Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/nice-baboons-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@rocket.chat/federation-matrix': patch
'@rocket.chat/meteor': patch
---

Fixes an issue where editing or deleting a message in a federated room caused subsequent messages to stop syncing between servers

Note: this prevents the issue from happening, but does not restore rooms that are already affected. Recovering those requires a separate, one-time repair.
26 changes: 18 additions & 8 deletions apps/meteor/ee/server/hooks/federation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,16 @@ callbacks.add(

callbacks.add(
'afterDeleteMessage',
async (message: IMessage, { room }) => {
async (message: IMessage, { room, user }) => {
if (!message.federation?.eventId) {
return;
}

// deletion came from federation — don't echo
if (isUserNativeFederated(user)) {
Comment on lines +86 to +87

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove inline implementation comments in these hook paths.

Line 86 and Line 270 add code comments inside implementation code; this conflicts with the repository guideline for TS/JS files. Please remove these comments and keep the guard logic self-descriptive through code structure/naming only.

Suggested diff
-		// deletion came from federation — don't echo
 		if (isUserNativeFederated(user)) {
 			return;
 		}
@@
-		// editor is remote -> edit came from federation, don't echo
 		if (isUserNativeFederated(user)) {
 			return;
 		}

As per coding guidelines, "Avoid code comments in the implementation".

Also applies to: 270-271

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/ee/server/hooks/federation/index.ts` around lines 86 - 87, Remove
the inline implementation comment `// deletion came from federation — don't
echo` that appears before the `isUserNativeFederated(user)` guard check, as well
as the similar inline comment at line 270-271 in the same file. The code should
be self-descriptive through function naming and logic structure alone, following
the repository's guideline to avoid code comments in implementation.

Source: Coding guidelines

return;
}

if (FederationActions.shouldPerformFederationAction(room)) {
await FederationMatrix.deleteMessage(room.federation.mrid, message);
}
Expand Down Expand Up @@ -255,14 +260,19 @@ callbacks.add(

callbacks.add(
'afterSaveMessage',
async (message: IMessage, { room }) => {
if (FederationActions.shouldPerformFederationAction(room)) {
if (!isEditedMessage(message)) {
return;
}

await FederationMatrix.updateMessage(room, message);
async (message: IMessage, { room, user }) => {
if (!FederationActions.shouldPerformFederationAction(room)) {
return;
}
if (!isEditedMessage(message)) {
return;
}
// editor is remote -> edit came from federation, don't echo
if (isUserNativeFederated(user)) {
return;
}

await FederationMatrix.updateMessage(room, message);
},
callbacks.priority.HIGH,
'federation-matrix-after-room-message-updated',
Expand Down
5 changes: 5 additions & 0 deletions ee/packages/federation-matrix/src/FederationMatrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,11 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS
return;
}

if (isUserNativeFederated(user)) {
this.logger.debug('Edit originated from a federated user; not re-sending to Matrix');
return;
}

const userMui = isUserNativeFederated(user) ? user.federation.mui : `@${user.username}:${this.serverName}`;

const parsedMessage = await toExternalMessageFormat({
Expand Down
Loading