Skip to content

Commit aeaefd4

Browse files
authored
regression(federation): fix group DM name (#37957)
1 parent a868db6 commit aeaefd4

File tree

5 files changed

+86
-88
lines changed

5 files changed

+86
-88
lines changed

apps/meteor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
"@rocket.chat/emitter": "~0.31.25",
100100
"@rocket.chat/favicon": "workspace:^",
101101
"@rocket.chat/federation-matrix": "workspace:^",
102-
"@rocket.chat/federation-sdk": "0.3.5",
102+
"@rocket.chat/federation-sdk": "0.3.7",
103103
"@rocket.chat/fuselage": "^0.70.0",
104104
"@rocket.chat/fuselage-forms": "~0.1.1",
105105
"@rocket.chat/fuselage-hooks": "~0.38.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.5",
25+
"@rocket.chat/federation-sdk": "0.3.7",
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: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -260,53 +260,23 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS
260260
try {
261261
this.logger.debug('Creating direct message room in Matrix', { roomId: room._id, memberCount: members.length });
262262

263-
const creator = await Users.findOneById(creatorId);
263+
const creator = await Users.findOneById<Pick<IUser, 'username'>>(creatorId, { projection: { username: 1 } });
264264
if (!creator) {
265265
throw new Error('Creator not found in members list');
266266
}
267267

268-
const actualMatrixUserId = `@${creator.username}:${this.serverName}`;
269-
270-
let matrixRoomResult: { room_id: string; event_id?: string };
271-
if (members.length === 2) {
272-
const otherMember = members.find((member) => member._id !== creatorId);
273-
if (!otherMember) {
274-
throw new Error('Other member not found for 1-on-1 DM');
275-
}
276-
if (!isUserNativeFederated(otherMember)) {
277-
throw new Error('Other member is not federated');
278-
}
279-
const roomId = await federationSDK.createDirectMessageRoom(
280-
userIdSchema.parse(actualMatrixUserId),
281-
userIdSchema.parse(otherMember.username),
282-
);
283-
matrixRoomResult = { room_id: roomId };
284-
} else {
285-
// For group DMs (more than 2 members), create a private room
286-
const roomName = room.name || room.fname || `Group chat with ${members.length} members`;
287-
matrixRoomResult = await federationSDK.createRoom(userIdSchema.parse(actualMatrixUserId), roomName, 'invite');
288-
289-
for await (const member of members) {
290-
if (member._id === creatorId) {
291-
continue;
292-
}
293-
294-
try {
295-
await federationSDK.inviteUserToRoom(
296-
isUserNativeFederated(member) ? userIdSchema.parse(member.username) : `@${member.username}:${this.serverName}`,
297-
roomIdSchema.parse(matrixRoomResult.room_id),
298-
userIdSchema.parse(actualMatrixUserId),
299-
);
300-
} catch (error) {
301-
this.logger.error(error, 'Error creating or updating bridged user for DM');
302-
}
303-
}
304-
}
268+
const roomId = await federationSDK.createDirectMessage({
269+
creatorUserId: userIdSchema.parse(`@${creator.username}:${this.serverName}`),
270+
members: members
271+
.filter((member) => member._id !== creatorId)
272+
.map((member) => userIdSchema.parse(isUserNativeFederated(member) ? member.username : `@${member.username}:${this.serverName}`)),
273+
});
305274

306275
await Rooms.setAsFederated(room._id, {
307-
mrid: matrixRoomResult.room_id,
276+
mrid: roomId,
308277
origin: this.serverName,
309278
});
279+
310280
this.logger.debug({ roomId: room._id, msg: 'Direct message room creation completed successfully' });
311281
} catch (error) {
312282
this.logger.error(error, 'Failed to create direct message room');

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

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,10 @@ const waitForRoomEvent = async (
937937
});
938938
});
939939

940+
it('should show the room name as the inviter name on Synapse before join', async () => {
941+
expect(hs1Room1.name).toBe(rcUser1.username);
942+
});
943+
940944
it('should display the fname containing the two invited users for the inviter', async () => {
941945
// Check the subscription for the inviter
942946
const sub = await getSubscriptionByRoomId(rcRoom._id, rcUserConfig1.credentials, rcUserConfig1.request);
@@ -954,16 +958,23 @@ const waitForRoomEvent = async (
954958
expect(sub).toHaveProperty('fname', rcUser1.username);
955959
});
956960

957-
it.failing('should keep the fname to the RC invited user when the Synapse invited user accepts the DM', async () => {
958-
const waitForRoomEventPromise1 = waitForRoomEvent(hs1Room1, RoomStateEvent.Members, ({ event }) => {
959-
expect(event).toHaveProperty('content.membership', 'join');
960-
expect(event).toHaveProperty('state_key', federationConfig.hs1.adminMatrixUserId);
961-
});
962-
961+
it('should accept the invitation on Synapse', async () => {
963962
await hs1AdminApp.matrixClient.joinRoom(rcRoom.federation.mrid);
964963

965-
await waitForRoomEventPromise1;
964+
await retry(
965+
'wait for the join to be processed',
966+
async () => {
967+
expect(hs1Room1.getMyMembership()).toBe('join');
968+
},
969+
{ delayMs: 100 },
970+
);
971+
});
966972

973+
it('should show the room name with all members on Synapse after join', async () => {
974+
expect(hs1Room1.name).toBe(`${rcUser1.username} and ${rcUser2.username}`);
975+
});
976+
977+
it.failing('should keep the fname to the RC invited user when the Synapse invited user accepts the DM', async () => {
967978
await retry(
968979
'this is an async operation, so we need to wait for the event to be processed',
969980
async () => {
@@ -991,11 +1002,6 @@ const waitForRoomEvent = async (
9911002
{ delayMs: 100 },
9921003
);
9931004
});
994-
995-
it('should validate the room name for group DMs on Synapse', async () => {
996-
// TODO this should probably change
997-
expect(hs1Room1.name).toBe('Group chat with 3 members');
998-
});
9991005
});
10001006

10011007
describe('Permission validations', () => {
@@ -1103,12 +1109,11 @@ const waitForRoomEvent = async (
11031109
});
11041110

11051111
// TODO maybe we should allow it
1106-
// is this working now?
1107-
it.failing('should fail if a user from rc try to add another user to the group DM', async () => {
1112+
it('should fail if a user from rc try to add another user to the group DM', async () => {
11081113
const response = await addUserToRoom({
11091114
usernames: [rcUser3.username],
11101115
rid: rcRoom._id,
1111-
config: rcUserConfig1,
1116+
config: rcUserConfig2,
11121117
});
11131118

11141119
expect(response.body).toHaveProperty('success', true);
@@ -1120,23 +1125,32 @@ const waitForRoomEvent = async (
11201125
expect(messageData).toHaveProperty('error.error', 'error-not-allowed');
11211126
});
11221127

1123-
// TODO we're creating DMs with powerlevel 50 for invites, so this is not working
1124-
it.failing('should add another user by another user than the initial inviter', async () => {
1128+
it('should add another user by another user than the initial inviter', async () => {
11251129
await hs1AdminApp.matrixClient.joinRoom(rcRoom.federation.mrid);
11261130

1127-
await retry('waiting for join', async () => {
1128-
const members = await hs1Room1.getMembers();
1129-
expect(members.length).toBe(3);
1130-
});
1131+
await retry(
1132+
'waiting for join',
1133+
async () => {
1134+
expect(hs1Room1.getMyMembership()).toBe('join');
1135+
1136+
const members = await hs1Room1.getMembers();
1137+
expect(members.length).toBe(3);
1138+
},
1139+
{ delayMs: 100 },
1140+
);
11311141

11321142
await hs1AdminApp.inviteUserToRoom(hs1Room1.roomId, userDmId3);
11331143

1134-
await retry('waiting for user4 to receive invitation', async () => {
1135-
const members = await hs1Room1.getMembers();
1136-
const user4Member = members.find((m) => m.userId === userDmId3);
1137-
expect(user4Member).toBeDefined();
1138-
expect(user4Member?.membership).toBe('invite');
1139-
});
1144+
await retry(
1145+
'waiting for user4 to receive invitation',
1146+
async () => {
1147+
const members = await hs1Room1.getMembers();
1148+
const user4Member = members.find((m) => m.userId === userDmId3);
1149+
expect(user4Member).toBeDefined();
1150+
expect(user4Member?.membership).toBe('invite');
1151+
},
1152+
{ delayMs: 100 },
1153+
);
11401154
});
11411155
});
11421156

@@ -1662,7 +1676,7 @@ const waitForRoomEvent = async (
16621676
expect(messageData).toHaveProperty('error.error', 'error-cant-invite-for-direct-room');
16631677
});
16641678

1665-
it('should create a 1:1 a federated DM between', async () => {
1679+
it('should create a 1:1 federated DM', async () => {
16661680
// Create 1:1 DM from RC user to another RC user
16671681
const response = await rcUser1.config.request
16681682
.post(api('dm.create'))
@@ -1696,7 +1710,7 @@ const waitForRoomEvent = async (
16961710
expect(sub).toHaveProperty('fname', federationConfig.hs1.adminMatrixUserId);
16971711
});
16981712

1699-
it('should show the invite to the third user', async () => {
1713+
it('should send an invite to another Synapse user', async () => {
17001714
// invite from rocket.chat
17011715
const response = await addUserToRoom({
17021716
usernames: [federationConfig.hs1.additionalUser1.matrixUserId],
@@ -1744,19 +1758,33 @@ const waitForRoomEvent = async (
17441758
expect(roomInfo.room).toHaveProperty('usersCount', 3);
17451759
});
17461760

1747-
// TODO we're creating DMs with powerlevel 50 for invites, so this is not working
1748-
it.failing('should invite a fourth user from Rocket.Chat by a Synapse user', async () => {
1761+
it('should invite a fourth Rocket.Chat user by the invited Synapse user', async () => {
17491762
await hs1User1.inviteUserToRoom(hs1Room1.roomId, rcUser2.matrixId);
17501763

1751-
await retry('waiting for fourth user to receive invitation', async () => {
1752-
const subscriptionInvite = await getSubscriptionByRoomId(rcRoom._id, rcUser2.config.credentials, rcUser2.config.request);
1764+
await retry(
1765+
'waiting for user4 to receive invitation',
1766+
async () => {
1767+
const members = await hs1Room1.getMembers();
17531768

1754-
expect(subscriptionInvite).toHaveProperty('status', 'INVITED');
1755-
expect(subscriptionInvite).toHaveProperty(
1756-
'fname',
1757-
`${federationConfig.hs1.adminMatrixUserId}, ${federationConfig.hs1.additionalUser1.matrixUserId}, ${rcUser1.matrixId}`,
1758-
);
1759-
});
1769+
const user4Member = members.find((m) => m.userId === rcUser2.matrixId);
1770+
1771+
expect(user4Member).toBeDefined();
1772+
expect(user4Member?.membership).toBe('invite');
1773+
},
1774+
{ delayMs: 100 },
1775+
);
1776+
1777+
await retry(
1778+
'waiting for fourth user to receive invitation',
1779+
async () => {
1780+
const sub = await getSubscriptionByRoomId(rcRoom._id, rcUser2.config.credentials, rcUser2.config.request);
1781+
1782+
expect(sub).toHaveProperty('status', 'INVITED');
1783+
expect(sub).toHaveProperty('name', federationConfig.hs1.additionalUser1.matrixUserId);
1784+
expect(sub).toHaveProperty('fname', federationConfig.hs1.additionalUser1.matrixUserId);
1785+
},
1786+
{ delayMs: 100 },
1787+
);
17601788
});
17611789
});
17621790
});

yarn.lock

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8467,7 +8467,7 @@ __metadata:
84678467
"@rocket.chat/apps-engine": "workspace:^"
84688468
"@rocket.chat/core-typings": "workspace:^"
84698469
"@rocket.chat/eslint-config": "workspace:^"
8470-
"@rocket.chat/federation-sdk": "npm:0.3.5"
8470+
"@rocket.chat/federation-sdk": "npm:0.3.7"
84718471
"@rocket.chat/http-router": "workspace:^"
84728472
"@rocket.chat/icons": "npm:~0.46.0"
84738473
"@rocket.chat/jest-presets": "workspace:~"
@@ -8674,7 +8674,7 @@ __metadata:
86748674
"@rocket.chat/ddp-client": "workspace:^"
86758675
"@rocket.chat/emitter": "npm:^0.31.25"
86768676
"@rocket.chat/eslint-config": "workspace:^"
8677-
"@rocket.chat/federation-sdk": "npm:0.3.5"
8677+
"@rocket.chat/federation-sdk": "npm:0.3.7"
86788678
"@rocket.chat/http-router": "workspace:^"
86798679
"@rocket.chat/license": "workspace:^"
86808680
"@rocket.chat/models": "workspace:^"
@@ -8700,9 +8700,9 @@ __metadata:
87008700
languageName: unknown
87018701
linkType: soft
87028702

8703-
"@rocket.chat/federation-sdk@npm:0.3.5":
8704-
version: 0.3.5
8705-
resolution: "@rocket.chat/federation-sdk@npm:0.3.5"
8703+
"@rocket.chat/federation-sdk@npm:0.3.7":
8704+
version: 0.3.7
8705+
resolution: "@rocket.chat/federation-sdk@npm:0.3.7"
87068706
dependencies:
87078707
"@datastructures-js/priority-queue": "npm:^6.3.5"
87088708
"@noble/ed25519": "npm:^3.0.0"
@@ -8715,7 +8715,7 @@ __metadata:
87158715
zod: "npm:^3.24.1"
87168716
peerDependencies:
87178717
typescript: ~5.9.2
8718-
checksum: 10/47de2265555649b375620c7a90cf84134b14f3e38d171d84276dee9196b7b303a2d8c6f693223d63ba1c464ce12c128c5f6a795c0bb42c0e5339587b2429d034
8718+
checksum: 10/fd3bce12146ad906970ebe88ddc54f118362a52fe600d90d39a99a684aa7c637922b39791b671f1b9de8fb160076468de5034286673da443dfad6a68924fed91
87198719
languageName: node
87208720
linkType: hard
87218721

@@ -9342,7 +9342,7 @@ __metadata:
93429342
"@rocket.chat/eslint-config": "workspace:^"
93439343
"@rocket.chat/favicon": "workspace:^"
93449344
"@rocket.chat/federation-matrix": "workspace:^"
9345-
"@rocket.chat/federation-sdk": "npm:0.3.5"
9345+
"@rocket.chat/federation-sdk": "npm:0.3.7"
93469346
"@rocket.chat/fuselage": "npm:^0.70.0"
93479347
"@rocket.chat/fuselage-forms": "npm:~0.1.1"
93489348
"@rocket.chat/fuselage-hooks": "npm:~0.38.1"
@@ -10797,7 +10797,7 @@ __metadata:
1079710797
peerDependencies:
1079810798
"@rocket.chat/layout": "*"
1079910799
"@rocket.chat/tools": 0.2.4-rc.0
10800-
"@rocket.chat/ui-contexts": 26.0.0-rc.0
10800+
"@rocket.chat/ui-contexts": 26.0.0-rc.1
1080110801
"@tanstack/react-query": "*"
1080210802
react: "*"
1080310803
react-hook-form: "*"

0 commit comments

Comments
 (0)