Skip to content

Commit 0bb97a8

Browse files
committed
run beforeCreateDirectRoom callback earlier to ensure federated user is created before room setup
1 parent a7f8c73 commit 0bb97a8

File tree

6 files changed

+26
-45
lines changed

6 files changed

+26
-45
lines changed

apps/meteor/app/lib/server/functions/createDirectRoom.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { AppEvents, Apps } from '@rocket.chat/apps';
22
import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions';
33
import type { ISubscriptionExtraData } from '@rocket.chat/core-services';
4-
import type { ICreatedRoom, IRoom, ISubscription, IUser } from '@rocket.chat/core-typings';
4+
import type { ICreatedRoom, IRoom, IRoomNativeFederated, ISubscription, IUser } from '@rocket.chat/core-typings';
55
import { Rooms, Subscriptions, Users } from '@rocket.chat/models';
66
import { Random } from '@rocket.chat/random';
77
import { Meteor } from 'meteor/meteor';
@@ -42,7 +42,7 @@ const getName = (members: IUser[]): string => members.map(({ username }) => user
4242

4343
export async function createDirectRoom(
4444
members: IUser[] | string[],
45-
roomExtraData = {},
45+
roomExtraData: Partial<IRoomNativeFederated | IRoom> = {},
4646
options: {
4747
creator?: string;
4848
subscriptionExtra?: ISubscriptionExtraData;
@@ -69,6 +69,8 @@ export async function createDirectRoom(
6969
})
7070
.filter(isTruthy);
7171

72+
await callbacks.run('beforeCreateDirectRoom', membersUsernames, roomExtraData);
73+
7274
const roomMembers: IUser[] = await Users.findUsersByUsernames(membersUsernames, {
7375
projection: { _id: 1, name: 1, username: 1, settings: 1, customFields: 1 },
7476
}).toArray();
@@ -97,8 +99,6 @@ export async function createDirectRoom(
9799
...roomExtraData,
98100
};
99101

100-
await callbacks.run('beforeCreateDirectRoom', members, roomInfo);
101-
102102
if (isNewRoom) {
103103
const tmpRoom: { _USERNAMES?: (string | undefined)[] } & typeof roomInfo = {
104104
...roomInfo,

apps/meteor/app/lib/server/functions/createRoom.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,16 @@ export const createRoom = async <T extends RoomType>(
134134
> => {
135135
const { teamId, ...optionalExtraData } = roomExtraData || ({} as IRoom);
136136

137+
const hasFederatedMembers = members.some((member) => {
138+
if (typeof member === 'string') {
139+
return member.includes(':') && member.includes('@');
140+
}
141+
return member.username?.includes(':') && member.username?.includes('@');
142+
});
143+
137144
const extraData = {
138145
...optionalExtraData,
139-
...(optionalExtraData.federated && {
146+
...((hasFederatedMembers || optionalExtraData.federated) && {
140147
federated: true,
141148
federation: {
142149
version: 1,

apps/meteor/lib/callbacks.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import type {
2121
ILivechatDepartment,
2222
MessageMention,
2323
IOmnichannelInquiryExtraData,
24+
IRoomNativeFederated,
2425
} from '@rocket.chat/core-typings';
2526
import type { Updater } from '@rocket.chat/models';
2627
import type { FilterOperators } from 'mongodb';
@@ -78,7 +79,7 @@ interface EventLikeCallbackSignatures {
7879
options?: ICreateRoomOptions;
7980
},
8081
) => void;
81-
'beforeCreateDirectRoom': (members: IUser[], room: IRoom) => void;
82+
'beforeCreateDirectRoom': (members: string[], room: Partial<IRoomNativeFederated | IRoom>) => void;
8283
'federation.beforeCreateDirectMessage': (members: IUser[]) => void;
8384
'afterSetReaction': (message: IMessage, params: { user: IUser; reaction: string; shouldReact: boolean; room: IRoom }) => void;
8485
'afterUnsetReaction': (

apps/meteor/server/services/room/hooks/BeforeFederationActions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { IRoomNativeFederated, IRoom } from '@rocket.chat/core-typings';
44
import { throwIfFederationNotEnabled } from '../../federation/utils';
55

66
export class FederationActions {
7-
public static shouldPerformFederationAction(room: IRoom): room is IRoomNativeFederated {
7+
public static shouldPerformFederationAction(room: Partial<IRoom | IRoomNativeFederated>): room is IRoomNativeFederated {
88
if (!isRoomFederated(room)) {
99
return false;
1010
}

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

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -256,47 +256,24 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS
256256
}
257257
}
258258

259-
async ensureFederatedUsersExistLocally(members: (IUser | string)[]): Promise<void> {
259+
async ensureFederatedUsersExistLocally(usernames: string[]): Promise<void> {
260260
try {
261-
this.logger.debug('Ensuring federated users exist locally before DM creation', { memberCount: members.length });
261+
this.logger.debug('Ensuring federated users exist locally before DM creation', { memberCount: usernames.length });
262262

263-
for await (const member of members) {
264-
let username: string;
265-
266-
if (typeof member === 'string') {
267-
username = member;
268-
} else if (typeof member.username === 'string') {
269-
username = member.username;
270-
} else {
271-
continue;
272-
}
273-
274-
if (!username.includes(':') && !username.includes('@')) {
263+
const federatedUsers = usernames.filter((username) => username?.includes(':') && username?.includes('@'));
264+
for await (const username of federatedUsers) {
265+
if (!username) {
275266
continue;
276267
}
277268

278269
const existingUser = await Users.findOneByUsername(username);
279270
if (existingUser) {
280-
// TODO review: DM
281-
// const existingBridge = await MatrixBridgedUser.getExternalUserIdByLocalUserId(existingUser._id); // TODO review: DM
282-
// if (!existingBridge) {
283-
// const remoteDomain = externalUserId.split(':')[1] || this.serverName;
284-
// await MatrixBridgedUser.createOrUpdateByLocalId(existingUser._id, externalUserId, true, remoteDomain);
285-
// }
286271
continue;
287272
}
288273

289-
// TODO: there is not need to check if the username includes ':' or '@', we should just use the username as is
290-
const externalUserId = username.includes(':') ? `@${username}` : `@${username}:${this.serverName}`;
291-
this.logger.debug('Creating federated user locally', { externalUserId, username });
292-
293-
const remoteDomain = externalUserId.split(':')[1];
294-
295-
const localName = username.split(':')[0]?.replace('@', '') || username;
296-
297-
const newUser = {
274+
await Users.create({
298275
username,
299-
name: localName,
276+
name: username,
300277
type: 'user' as const,
301278
status: UserStatus.OFFLINE,
302279
active: true,
@@ -305,16 +282,12 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS
305282
federated: true,
306283
federation: {
307284
version: 1,
308-
mui: externalUserId,
309-
origin: remoteDomain,
285+
mui: username,
286+
origin: username.split(':')[1],
310287
},
311288
createdAt: new Date(),
312289
_updatedAt: new Date(),
313-
};
314-
315-
const { insertedId } = await Users.insertOne(newUser);
316-
317-
this.logger.debug('Successfully created federated user locally', { userId: insertedId, externalUserId });
290+
});
318291
}
319292
} catch (error) {
320293
this.logger.error('Failed to ensure federated users exist locally:', error);

packages/core-services/src/types/IFederationMatrixService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export interface IFederationMatrixService {
77
wellKnown: Router<'/.well-known'>;
88
};
99
createRoom(room: IRoomFederated, owner: IUser, members: string[]): Promise<{ room_id: string; event_id: string }>;
10-
ensureFederatedUsersExistLocally(members: (IUser | string)[]): Promise<void>;
10+
ensureFederatedUsersExistLocally(members: string[]): Promise<void>;
1111
createDirectMessageRoom(room: IRoomFederated, members: IUser[], creatorId: IUser['_id']): Promise<void>;
1212
sendMessage(message: IMessage, room: IRoomFederated, user: IUser): Promise<void>;
1313
deleteMessage(matrixRoomId: string, message: IMessage, uid: string): Promise<void>;

0 commit comments

Comments
 (0)