mirror of
https://github.com/RocketChat/Rocket.Chat.git
synced 2025-12-28 06:47:25 +00:00
fix(federation): handle "disinvite" and duplicated messages (#37791)
Co-authored-by: Jéssica Souza <jessica_schelly@hotmail.com>
This commit is contained in:
parent
b81ae0b6d8
commit
1baa03cced
7
.changeset/dull-tips-look.md
Normal file
7
.changeset/dull-tips-look.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@rocket.chat/meteor": patch
|
||||||
|
"@rocket.chat/core-services": patch
|
||||||
|
"@rocket.chat/federation-matrix": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes an issue where cases of invites that were canceled or disinvited were not being handled.
|
||||||
@ -98,7 +98,7 @@
|
|||||||
"@rocket.chat/emitter": "~0.31.25",
|
"@rocket.chat/emitter": "~0.31.25",
|
||||||
"@rocket.chat/favicon": "workspace:^",
|
"@rocket.chat/favicon": "workspace:^",
|
||||||
"@rocket.chat/federation-matrix": "workspace:^",
|
"@rocket.chat/federation-matrix": "workspace:^",
|
||||||
"@rocket.chat/federation-sdk": "0.3.3",
|
"@rocket.chat/federation-sdk": "0.3.5",
|
||||||
"@rocket.chat/freeswitch": "workspace:^",
|
"@rocket.chat/freeswitch": "workspace:^",
|
||||||
"@rocket.chat/fuselage": "^0.69.0",
|
"@rocket.chat/fuselage": "^0.69.0",
|
||||||
"@rocket.chat/fuselage-forms": "~0.1.1",
|
"@rocket.chat/fuselage-forms": "~0.1.1",
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
"@rocket.chat/core-services": "workspace:^",
|
"@rocket.chat/core-services": "workspace:^",
|
||||||
"@rocket.chat/core-typings": "workspace:^",
|
"@rocket.chat/core-typings": "workspace:^",
|
||||||
"@rocket.chat/emitter": "^0.31.25",
|
"@rocket.chat/emitter": "^0.31.25",
|
||||||
"@rocket.chat/federation-sdk": "0.3.3",
|
"@rocket.chat/federation-sdk": "0.3.5",
|
||||||
"@rocket.chat/http-router": "workspace:^",
|
"@rocket.chat/http-router": "workspace:^",
|
||||||
"@rocket.chat/license": "workspace:^",
|
"@rocket.chat/license": "workspace:^",
|
||||||
"@rocket.chat/models": "workspace:^",
|
"@rocket.chat/models": "workspace:^",
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
UserStatus,
|
UserStatus,
|
||||||
} from '@rocket.chat/core-typings';
|
} from '@rocket.chat/core-typings';
|
||||||
import type { MessageQuoteAttachment, IMessage, IRoom, IUser, IRoomNativeFederated } from '@rocket.chat/core-typings';
|
import type { MessageQuoteAttachment, IMessage, IRoom, IUser, IRoomNativeFederated } from '@rocket.chat/core-typings';
|
||||||
import { eventIdSchema, roomIdSchema, userIdSchema, federationSDK } from '@rocket.chat/federation-sdk';
|
import { eventIdSchema, roomIdSchema, userIdSchema, federationSDK, FederationRequestError } from '@rocket.chat/federation-sdk';
|
||||||
import type { EventID, UserID, FileMessageType, PresenceState } from '@rocket.chat/federation-sdk';
|
import type { EventID, UserID, FileMessageType, PresenceState } from '@rocket.chat/federation-sdk';
|
||||||
import { Logger } from '@rocket.chat/logger';
|
import { Logger } from '@rocket.chat/logger';
|
||||||
import { Users, Subscriptions, Messages, Rooms, Settings } from '@rocket.chat/models';
|
import { Users, Subscriptions, Messages, Rooms, Settings } from '@rocket.chat/models';
|
||||||
@ -923,7 +923,15 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS
|
|||||||
await Room.performAcceptRoomInvite(room, subscription, user);
|
await Room.performAcceptRoomInvite(room, subscription, user);
|
||||||
}
|
}
|
||||||
if (action === 'reject') {
|
if (action === 'reject') {
|
||||||
await federationSDK.rejectInvite(room.federation.mrid, matrixUserId);
|
try {
|
||||||
|
await federationSDK.rejectInvite(room.federation.mrid, matrixUserId);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof FederationRequestError && error.response.status === 403) {
|
||||||
|
return Room.performUserRemoval(room, user);
|
||||||
|
}
|
||||||
|
this.logger.error(error, 'Failed to reject invite in Matrix');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1647,18 +1647,62 @@ import { SynapseClient } from '../helper/synapse-client';
|
|||||||
rid = pendingInvitation?.rid!;
|
rid = pendingInvitation?.rid!;
|
||||||
}, 15000);
|
}, 15000);
|
||||||
|
|
||||||
it('It should allow RC user to reject the invite', async () => {
|
it('should allow RC user to reject the invite and remove the subscription', async () => {
|
||||||
const rejectResponse = await rejectRoomInvite(rid, rc1AdminRequestConfig);
|
const rejectResponse = await rejectRoomInvite(rid, rc1AdminRequestConfig);
|
||||||
expect(rejectResponse.success).toBe(true);
|
expect(rejectResponse.success).toBe(true);
|
||||||
});
|
|
||||||
|
|
||||||
it('It should remove the subscription after rejection', async () => {
|
|
||||||
const subscriptions = await getSubscriptions(rc1AdminRequestConfig);
|
const subscriptions = await getSubscriptions(rc1AdminRequestConfig);
|
||||||
|
|
||||||
const invitedSub = subscriptions.update.find((sub) => sub.fname?.includes(channelName));
|
const invitedSub = subscriptions.update.find((sub) => sub.fname?.includes(channelName));
|
||||||
|
|
||||||
expect(invitedSub).toBeFalsy();
|
expect(invitedSub).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Revoked invitation flow from Synapse', () => {
|
||||||
|
describe('Synapse revokes an invitation before the RC user responds', () => {
|
||||||
|
let matrixRoomId: string;
|
||||||
|
let channelName: string;
|
||||||
|
let rid: string;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
channelName = `federated-channel-revoked-${Date.now()}`;
|
||||||
|
matrixRoomId = await hs1AdminApp.createRoom(channelName);
|
||||||
|
|
||||||
|
// hs1 invites RC user
|
||||||
|
await hs1AdminApp.matrixClient.invite(matrixRoomId, federationConfig.rc1.adminMatrixUserId);
|
||||||
|
const subscriptions = await getSubscriptions(rc1AdminRequestConfig);
|
||||||
|
|
||||||
|
const pendingInvitation = subscriptions.update.find(
|
||||||
|
(subscription) => subscription.status === 'INVITED' && subscription.fname?.includes(channelName),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(pendingInvitation).not.toBeUndefined();
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
rid = pendingInvitation?.rid!;
|
||||||
|
|
||||||
|
// hs1 revokes the invitation by kicking the invited user
|
||||||
|
await hs1AdminApp.matrixClient.kick(matrixRoomId, federationConfig.rc1.adminMatrixUserId, 'Invitation revoked');
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
it('should fail when RC user tries to accept the revoked invitation', async () => {
|
||||||
|
const acceptResponse = await acceptRoomInvite(rid, rc1AdminRequestConfig);
|
||||||
|
expect(acceptResponse.success).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow RC user to reject the revoked invitation and remove the subscription', async () => {
|
||||||
|
const rejectResponse = await rejectRoomInvite(rid, rc1AdminRequestConfig);
|
||||||
|
expect(rejectResponse.success).toBe(true);
|
||||||
|
|
||||||
|
const subscriptions = await getSubscriptions(rc1AdminRequestConfig);
|
||||||
|
const invitedSub = subscriptions.update.find((sub) => sub.fname?.includes(channelName));
|
||||||
|
expect(invitedSub).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have the RC user with leave membership on Synapse side after revoked invitation', async () => {
|
||||||
|
const member = await hs1AdminApp.findRoomMember(channelName, federationConfig.rc1.adminMatrixUserId);
|
||||||
|
expect(member?.membership).toBe('leave');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rocket.chat/core-typings": "workspace:^",
|
"@rocket.chat/core-typings": "workspace:^",
|
||||||
"@rocket.chat/federation-sdk": "0.3.3",
|
"@rocket.chat/federation-sdk": "0.3.5",
|
||||||
"@rocket.chat/http-router": "workspace:^",
|
"@rocket.chat/http-router": "workspace:^",
|
||||||
"@rocket.chat/icons": "~0.45.0",
|
"@rocket.chat/icons": "~0.45.0",
|
||||||
"@rocket.chat/media-signaling": "workspace:^",
|
"@rocket.chat/media-signaling": "workspace:^",
|
||||||
|
|||||||
14
yarn.lock
14
yarn.lock
@ -8284,7 +8284,7 @@ __metadata:
|
|||||||
"@rocket.chat/apps-engine": "workspace:^"
|
"@rocket.chat/apps-engine": "workspace:^"
|
||||||
"@rocket.chat/core-typings": "workspace:^"
|
"@rocket.chat/core-typings": "workspace:^"
|
||||||
"@rocket.chat/eslint-config": "workspace:^"
|
"@rocket.chat/eslint-config": "workspace:^"
|
||||||
"@rocket.chat/federation-sdk": "npm:0.3.3"
|
"@rocket.chat/federation-sdk": "npm:0.3.5"
|
||||||
"@rocket.chat/http-router": "workspace:^"
|
"@rocket.chat/http-router": "workspace:^"
|
||||||
"@rocket.chat/icons": "npm:~0.45.0"
|
"@rocket.chat/icons": "npm:~0.45.0"
|
||||||
"@rocket.chat/jest-presets": "workspace:~"
|
"@rocket.chat/jest-presets": "workspace:~"
|
||||||
@ -8495,7 +8495,7 @@ __metadata:
|
|||||||
"@rocket.chat/ddp-client": "workspace:^"
|
"@rocket.chat/ddp-client": "workspace:^"
|
||||||
"@rocket.chat/emitter": "npm:^0.31.25"
|
"@rocket.chat/emitter": "npm:^0.31.25"
|
||||||
"@rocket.chat/eslint-config": "workspace:^"
|
"@rocket.chat/eslint-config": "workspace:^"
|
||||||
"@rocket.chat/federation-sdk": "npm:0.3.3"
|
"@rocket.chat/federation-sdk": "npm:0.3.5"
|
||||||
"@rocket.chat/http-router": "workspace:^"
|
"@rocket.chat/http-router": "workspace:^"
|
||||||
"@rocket.chat/license": "workspace:^"
|
"@rocket.chat/license": "workspace:^"
|
||||||
"@rocket.chat/models": "workspace:^"
|
"@rocket.chat/models": "workspace:^"
|
||||||
@ -8521,9 +8521,9 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@rocket.chat/federation-sdk@npm:0.3.3":
|
"@rocket.chat/federation-sdk@npm:0.3.5":
|
||||||
version: 0.3.3
|
version: 0.3.5
|
||||||
resolution: "@rocket.chat/federation-sdk@npm:0.3.3"
|
resolution: "@rocket.chat/federation-sdk@npm:0.3.5"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@datastructures-js/priority-queue": "npm:^6.3.5"
|
"@datastructures-js/priority-queue": "npm:^6.3.5"
|
||||||
"@noble/ed25519": "npm:^3.0.0"
|
"@noble/ed25519": "npm:^3.0.0"
|
||||||
@ -8536,7 +8536,7 @@ __metadata:
|
|||||||
zod: "npm:^3.24.1"
|
zod: "npm:^3.24.1"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: ~5.9.2
|
typescript: ~5.9.2
|
||||||
checksum: 10/e93f0d59da8508ee0ecfb53f6d599f93130ab4b9f651d87da77615355261e4852d6f4659aae9f4c8881cf4b26a628512e6363ecc407d6e01a31a27d20b9d7684
|
checksum: 10/47de2265555649b375620c7a90cf84134b14f3e38d171d84276dee9196b7b303a2d8c6f693223d63ba1c464ce12c128c5f6a795c0bb42c0e5339587b2429d034
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -9179,7 +9179,7 @@ __metadata:
|
|||||||
"@rocket.chat/eslint-config": "workspace:^"
|
"@rocket.chat/eslint-config": "workspace:^"
|
||||||
"@rocket.chat/favicon": "workspace:^"
|
"@rocket.chat/favicon": "workspace:^"
|
||||||
"@rocket.chat/federation-matrix": "workspace:^"
|
"@rocket.chat/federation-matrix": "workspace:^"
|
||||||
"@rocket.chat/federation-sdk": "npm:0.3.3"
|
"@rocket.chat/federation-sdk": "npm:0.3.5"
|
||||||
"@rocket.chat/freeswitch": "workspace:^"
|
"@rocket.chat/freeswitch": "workspace:^"
|
||||||
"@rocket.chat/fuselage": "npm:^0.69.0"
|
"@rocket.chat/fuselage": "npm:^0.69.0"
|
||||||
"@rocket.chat/fuselage-forms": "npm:~0.1.1"
|
"@rocket.chat/fuselage-forms": "npm:~0.1.1"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user