Skip to content
Draft
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
6 changes: 5 additions & 1 deletion apps/meteor/app/lib/server/functions/setRealName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Users } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
import type { ClientSession } from 'mongodb';

import { callbacks } from '../../../../lib/callbacks';
import { onceTransactionCommitedSuccessfully } from '../../../../server/database/utils';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { settings } from '../../../settings/server';
Expand Down Expand Up @@ -34,6 +35,8 @@ export const _setRealName = async function (
return user;
}

const oldUser = { ...user };

// Set new name
if (name) {
if (updater) {
Expand All @@ -48,7 +51,7 @@ export const _setRealName = async function (
}
user.name = name;

await onceTransactionCommitedSuccessfully(() => {
await onceTransactionCommitedSuccessfully(async () => {
if (settings.get('UI_Use_Real_Name') === true) {
void api.broadcast('user.nameChanged', {
_id: user._id,
Expand All @@ -61,6 +64,7 @@ export const _setRealName = async function (
name,
username: user.username,
});
void callbacks.run('afterSaveUser', { user, oldUser });
}, session);

return user;
Expand Down
53 changes: 50 additions & 3 deletions apps/meteor/ee/server/hooks/federation/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FederationMatrix, Authorization, MeteorError } from '@rocket.chat/core-services';
import { isEditedMessage, type IMessage, type IRoom, type IUser } from '@rocket.chat/core-typings';
import { Rooms } from '@rocket.chat/models';
import { FederationMatrix, Authorization, Message, MeteorError } from '@rocket.chat/core-services';
import { isEditedMessage, isRoomNativeFederated, type IMessage, type IRoom, type IUser } from '@rocket.chat/core-typings';
import { Rooms, Subscriptions } from '@rocket.chat/models';

import { callbacks } from '../../../../lib/callbacks';
import { afterLeaveRoomCallback } from '../../../../lib/callbacks/afterLeaveRoomCallback';
Expand Down Expand Up @@ -218,3 +218,50 @@ callbacks.add(
callbacks.priority.HIGH,
'federation-matrix-after-create-direct-room',
);

callbacks.add(
'afterSaveUser',
async ({ user, oldUser }) => {
if (!oldUser || !user) {
return;
}

const nameChanged = user.name !== oldUser.name;
if (!nameChanged) {
return;
}

const newDisplayName = user.name || user.username;
if (!newDisplayName) {
return;
}

// check if user, even if local, is part of some federated room
// TODO have a method to check if user is part of some federated room
const oldDisplayName = oldUser.name || oldUser.username;
const federatedRoomIds: string[] = [];
const subscriptions = Subscriptions.findByUserId(user._id);
for await (const subscription of subscriptions) {
const room = await Rooms.findOneById(subscription.rid, { fields: { _id: 1, federation: 1, federated: 1 } });
if (!room || !isRoomNativeFederated(room)) {
continue;
}
federatedRoomIds.push(room._id);
}

if (federatedRoomIds.length > 0) {
await FederationMatrix.updateUserProfile(user._id, newDisplayName);

// send system message to each federated room
for await (const roomId of federatedRoomIds) {
try {
await Message.saveSystemMessage('user-display-name-changed', roomId, `${oldDisplayName}|${newDisplayName}`, user);
} catch (error) {
console.error(`Failed to send displayname change system message to room ${roomId}:`, error);
}
}
}
},
callbacks.priority.MEDIUM,
'native-federation-after-user-profile-update',
);
Loading
Loading