Skip to content

Commit 1baa03c

Browse files
fix(federation): handle "disinvite" and duplicated messages (#37791)
Co-authored-by: Jéssica Souza <jessica_schelly@hotmail.com>
1 parent b81ae0b commit 1baa03c

File tree

7 files changed

+76
-17
lines changed

7 files changed

+76
-17
lines changed

.changeset/dull-tips-look.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@rocket.chat/meteor": patch
3+
"@rocket.chat/core-services": patch
4+
"@rocket.chat/federation-matrix": patch
5+
---
6+
7+
Fixes an issue where cases of invites that were canceled or disinvited were not being handled.

apps/meteor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
"@rocket.chat/emitter": "~0.31.25",
9999
"@rocket.chat/favicon": "workspace:^",
100100
"@rocket.chat/federation-matrix": "workspace:^",
101-
"@rocket.chat/federation-sdk": "0.3.3",
101+
"@rocket.chat/federation-sdk": "0.3.5",
102102
"@rocket.chat/freeswitch": "workspace:^",
103103
"@rocket.chat/fuselage": "^0.69.0",
104104
"@rocket.chat/fuselage-forms": "~0.1.1",

ee/packages/federation-matrix/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"@rocket.chat/core-services": "workspace:^",
2323
"@rocket.chat/core-typings": "workspace:^",
2424
"@rocket.chat/emitter": "^0.31.25",
25-
"@rocket.chat/federation-sdk": "0.3.3",
25+
"@rocket.chat/federation-sdk": "0.3.5",
2626
"@rocket.chat/http-router": "workspace:^",
2727
"@rocket.chat/license": "workspace:^",
2828
"@rocket.chat/models": "workspace:^",

ee/packages/federation-matrix/src/FederationMatrix.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
UserStatus,
99
} from '@rocket.chat/core-typings';
1010
import type { MessageQuoteAttachment, IMessage, IRoom, IUser, IRoomNativeFederated } from '@rocket.chat/core-typings';
11-
import { eventIdSchema, roomIdSchema, userIdSchema, federationSDK } from '@rocket.chat/federation-sdk';
11+
import { eventIdSchema, roomIdSchema, userIdSchema, federationSDK, FederationRequestError } from '@rocket.chat/federation-sdk';
1212
import type { EventID, UserID, FileMessageType, PresenceState } from '@rocket.chat/federation-sdk';
1313
import { Logger } from '@rocket.chat/logger';
1414
import { Users, Subscriptions, Messages, Rooms, Settings } from '@rocket.chat/models';
@@ -923,7 +923,15 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS
923923
await Room.performAcceptRoomInvite(room, subscription, user);
924924
}
925925
if (action === 'reject') {
926-
await federationSDK.rejectInvite(room.federation.mrid, matrixUserId);
926+
try {
927+
await federationSDK.rejectInvite(room.federation.mrid, matrixUserId);
928+
} catch (error) {
929+
if (error instanceof FederationRequestError && error.response.status === 403) {
930+
return Room.performUserRemoval(room, user);
931+
}
932+
this.logger.error(error, 'Failed to reject invite in Matrix');
933+
throw error;
934+
}
927935
}
928936
}
929937
}

ee/packages/federation-matrix/tests/end-to-end/room.spec.ts

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,18 +1647,62 @@ import { SynapseClient } from '../helper/synapse-client';
16471647
rid = pendingInvitation?.rid!;
16481648
}, 15000);
16491649

1650-
it('It should allow RC user to reject the invite', async () => {
1650+
it('should allow RC user to reject the invite and remove the subscription', async () => {
16511651
const rejectResponse = await rejectRoomInvite(rid, rc1AdminRequestConfig);
16521652
expect(rejectResponse.success).toBe(true);
1653-
});
16541653

1655-
it('It should remove the subscription after rejection', async () => {
16561654
const subscriptions = await getSubscriptions(rc1AdminRequestConfig);
1657-
16581655
const invitedSub = subscriptions.update.find((sub) => sub.fname?.includes(channelName));
1659-
16601656
expect(invitedSub).toBeFalsy();
16611657
});
16621658
});
1659+
1660+
describe('Revoked invitation flow from Synapse', () => {
1661+
describe('Synapse revokes an invitation before the RC user responds', () => {
1662+
let matrixRoomId: string;
1663+
let channelName: string;
1664+
let rid: string;
1665+
1666+
beforeAll(async () => {
1667+
channelName = `federated-channel-revoked-${Date.now()}`;
1668+
matrixRoomId = await hs1AdminApp.createRoom(channelName);
1669+
1670+
// hs1 invites RC user
1671+
await hs1AdminApp.matrixClient.invite(matrixRoomId, federationConfig.rc1.adminMatrixUserId);
1672+
const subscriptions = await getSubscriptions(rc1AdminRequestConfig);
1673+
1674+
const pendingInvitation = subscriptions.update.find(
1675+
(subscription) => subscription.status === 'INVITED' && subscription.fname?.includes(channelName),
1676+
);
1677+
1678+
expect(pendingInvitation).not.toBeUndefined();
1679+
1680+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1681+
rid = pendingInvitation?.rid!;
1682+
1683+
// hs1 revokes the invitation by kicking the invited user
1684+
await hs1AdminApp.matrixClient.kick(matrixRoomId, federationConfig.rc1.adminMatrixUserId, 'Invitation revoked');
1685+
}, 15000);
1686+
1687+
it('should fail when RC user tries to accept the revoked invitation', async () => {
1688+
const acceptResponse = await acceptRoomInvite(rid, rc1AdminRequestConfig);
1689+
expect(acceptResponse.success).toBe(false);
1690+
});
1691+
1692+
it('should allow RC user to reject the revoked invitation and remove the subscription', async () => {
1693+
const rejectResponse = await rejectRoomInvite(rid, rc1AdminRequestConfig);
1694+
expect(rejectResponse.success).toBe(true);
1695+
1696+
const subscriptions = await getSubscriptions(rc1AdminRequestConfig);
1697+
const invitedSub = subscriptions.update.find((sub) => sub.fname?.includes(channelName));
1698+
expect(invitedSub).toBeFalsy();
1699+
});
1700+
1701+
it('should have the RC user with leave membership on Synapse side after revoked invitation', async () => {
1702+
const member = await hs1AdminApp.findRoomMember(channelName, federationConfig.rc1.adminMatrixUserId);
1703+
expect(member?.membership).toBe('leave');
1704+
});
1705+
});
1706+
});
16631707
});
16641708
});

packages/core-services/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
},
1818
"dependencies": {
1919
"@rocket.chat/core-typings": "workspace:^",
20-
"@rocket.chat/federation-sdk": "0.3.3",
20+
"@rocket.chat/federation-sdk": "0.3.5",
2121
"@rocket.chat/http-router": "workspace:^",
2222
"@rocket.chat/icons": "~0.45.0",
2323
"@rocket.chat/media-signaling": "workspace:^",

yarn.lock

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8284,7 +8284,7 @@ __metadata:
82848284
"@rocket.chat/apps-engine": "workspace:^"
82858285
"@rocket.chat/core-typings": "workspace:^"
82868286
"@rocket.chat/eslint-config": "workspace:^"
8287-
"@rocket.chat/federation-sdk": "npm:0.3.3"
8287+
"@rocket.chat/federation-sdk": "npm:0.3.5"
82888288
"@rocket.chat/http-router": "workspace:^"
82898289
"@rocket.chat/icons": "npm:~0.45.0"
82908290
"@rocket.chat/jest-presets": "workspace:~"
@@ -8495,7 +8495,7 @@ __metadata:
84958495
"@rocket.chat/ddp-client": "workspace:^"
84968496
"@rocket.chat/emitter": "npm:^0.31.25"
84978497
"@rocket.chat/eslint-config": "workspace:^"
8498-
"@rocket.chat/federation-sdk": "npm:0.3.3"
8498+
"@rocket.chat/federation-sdk": "npm:0.3.5"
84998499
"@rocket.chat/http-router": "workspace:^"
85008500
"@rocket.chat/license": "workspace:^"
85018501
"@rocket.chat/models": "workspace:^"
@@ -8521,9 +8521,9 @@ __metadata:
85218521
languageName: unknown
85228522
linkType: soft
85238523

8524-
"@rocket.chat/federation-sdk@npm:0.3.3":
8525-
version: 0.3.3
8526-
resolution: "@rocket.chat/federation-sdk@npm:0.3.3"
8524+
"@rocket.chat/federation-sdk@npm:0.3.5":
8525+
version: 0.3.5
8526+
resolution: "@rocket.chat/federation-sdk@npm:0.3.5"
85278527
dependencies:
85288528
"@datastructures-js/priority-queue": "npm:^6.3.5"
85298529
"@noble/ed25519": "npm:^3.0.0"
@@ -8536,7 +8536,7 @@ __metadata:
85368536
zod: "npm:^3.24.1"
85378537
peerDependencies:
85388538
typescript: ~5.9.2
8539-
checksum: 10/e93f0d59da8508ee0ecfb53f6d599f93130ab4b9f651d87da77615355261e4852d6f4659aae9f4c8881cf4b26a628512e6363ecc407d6e01a31a27d20b9d7684
8539+
checksum: 10/47de2265555649b375620c7a90cf84134b14f3e38d171d84276dee9196b7b303a2d8c6f693223d63ba1c464ce12c128c5f6a795c0bb42c0e5339587b2429d034
85408540
languageName: node
85418541
linkType: hard
85428542

@@ -9179,7 +9179,7 @@ __metadata:
91799179
"@rocket.chat/eslint-config": "workspace:^"
91809180
"@rocket.chat/favicon": "workspace:^"
91819181
"@rocket.chat/federation-matrix": "workspace:^"
9182-
"@rocket.chat/federation-sdk": "npm:0.3.3"
9182+
"@rocket.chat/federation-sdk": "npm:0.3.5"
91839183
"@rocket.chat/freeswitch": "workspace:^"
91849184
"@rocket.chat/fuselage": "npm:^0.69.0"
91859185
"@rocket.chat/fuselage-forms": "npm:~0.1.1"

0 commit comments

Comments
 (0)