Skip to content

Commit d204ec6

Browse files
ggazzoricardogarimMarcos Spessatto Defendidebdutdebsampaiodiego
authored
feat: native federation (#36970)
Co-authored-by: Ricardo Garim <rswarovsky@gmail.com> Co-authored-by: Marcos Spessatto Defendi <marcos.defendi@rocket.chat> Co-authored-by: Debdut Chakraborty <debdutdeb@outlook.com> Co-authored-by: Debdut Chakraborty <debdut.chakraborty@rocket.chat> Co-authored-by: Diego Sampaio <chinello@gmail.com> Co-authored-by: Marcos Spessatto Defendi <marcos.defendicc@rede.ulbra.br> Co-authored-by: Rodrigo Nascimento <rodrigoknascimento@gmail.com>
1 parent 630b4f6 commit d204ec6

File tree

150 files changed

+7934
-413
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

150 files changed

+7934
-413
lines changed

.github/workflows/ci-test-storybook.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ jobs:
2222
runs-on: ubuntu-24.04
2323

2424
name: Test Storybook
25-
25+
2626
steps:
2727
- uses: actions/checkout@v4
28+
2829
- name: Setup NodeJS
2930
uses: ./.github/actions/setup-node
3031
with:
@@ -54,4 +55,3 @@ jobs:
5455
flags: unit
5556
verbose: true
5657
token: ${{ secrets.CODECOV_TOKEN }}
57-

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,5 @@ registration.yaml
5959

6060
storybook-static
6161
development/tempo-data/
62+
63+
.env

apps/meteor/app/channel-settings/server/functions/saveRoomName.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,6 @@ export async function saveRoomName(
9696
await Message.saveSystemMessage('r', rid, displayName, user);
9797
}
9898

99-
await callbacks.run('afterRoomNameChange', { room, name: displayName, oldName: room.name, userId: user._id });
99+
await callbacks.run('afterRoomNameChange', { room, name: displayName, oldName: room.name, user });
100100
return displayName;
101101
}

apps/meteor/app/channel-settings/server/functions/saveRoomTopic.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import { Meteor } from 'meteor/meteor';
55

66
import { callbacks } from '../../../../lib/callbacks';
77

8-
export const saveRoomTopic = async function (
8+
export const saveRoomTopic = async (
99
rid: string,
1010
roomTopic: string | undefined,
1111
user: {
1212
username: string;
1313
_id: string;
1414
},
1515
sendMessage = true,
16-
) {
16+
) => {
1717
if (!Match.test(rid, String)) {
1818
throw new Meteor.Error('invalid-room', 'Invalid room', {
1919
function: 'RocketChat.saveRoomTopic',
@@ -28,6 +28,6 @@ export const saveRoomTopic = async function (
2828
if (update && sendMessage) {
2929
await Message.saveSystemMessage('room_changed_topic', rid, roomTopic || '', user);
3030
}
31-
await callbacks.run('afterRoomTopicChange', { rid, topic: roomTopic });
31+
await callbacks.run('afterRoomTopicChange', undefined, { room, topic: roomTopic, user });
3232
return update;
3333
};

apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ callbacks.add(
4848

4949
callbacks.add(
5050
'afterDeleteMessage',
51-
async (message, { _id, prid }) => {
51+
async (message, { room: { _id, prid } }) => {
5252
if (prid) {
5353
const room = await Rooms.findOneById(_id, {
5454
projection: {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Apps, AppEvents } from '@rocket.chat/apps';
22
import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions';
33
import { Message, Team } from '@rocket.chat/core-services';
4-
import type { IUser } from '@rocket.chat/core-typings';
4+
import { type IUser } from '@rocket.chat/core-typings';
55
import { Subscriptions, Users, Rooms } from '@rocket.chat/models';
66
import { Meteor } from 'meteor/meteor';
77

@@ -19,7 +19,7 @@ import { notifyOnRoomChangedById, notifyOnSubscriptionChangedById } from '../lib
1919
* Caution - It does not validates if the user has permission to join room
2020
*/
2121

22-
export const addUserToRoom = async function (
22+
export const addUserToRoom = async (
2323
rid: string,
2424
user: Pick<IUser, '_id' | 'username'> | string,
2525
inviter?: Pick<IUser, '_id' | 'username'>,
@@ -32,7 +32,7 @@ export const addUserToRoom = async function (
3232
skipAlertSound?: boolean;
3333
createAsHidden?: boolean;
3434
} = {},
35-
): Promise<boolean | undefined> {
35+
): Promise<boolean | undefined> => {
3636
const now = new Date();
3737
const room = await Rooms.findOneById(rid);
3838

@@ -57,7 +57,7 @@ export const addUserToRoom = async function (
5757
}
5858

5959
try {
60-
await beforeAddUserToRoom.run({ user: userToBeAdded, inviter }, room);
60+
await beforeAddUserToRoom.run({ user: userToBeAdded, inviter: (inviter && (await Users.findOneById(inviter._id))) || undefined }, room);
6161
} catch (error) {
6262
throw new Meteor.Error((error as any)?.message);
6363
}

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ const getName = (members: IUser[]): string => members.map(({ username }) => user
4242

4343
export async function createDirectRoom(
4444
members: IUser[] | string[],
45-
roomExtraData = {},
45+
roomExtraData: Partial<IRoom> = {},
4646
options: {
4747
creator?: string;
4848
subscriptionExtra?: ISubscriptionExtraData;
49+
federatedRoomId?: string;
4950
},
5051
): Promise<ICreatedRoom> {
5152
const maxUsers = settings.get<number>('DirectMesssage_maxUsers') || 1;
@@ -59,17 +60,17 @@ export async function createDirectRoom(
5960
);
6061
}
6162

62-
await callbacks.run('beforeCreateDirectRoom', members);
63-
6463
const membersUsernames: string[] = members
6564
.map((member) => {
6665
if (typeof member === 'string') {
67-
return member.replace('@', '');
66+
return member;
6867
}
6968
return member.username;
7069
})
7170
.filter(isTruthy);
7271

72+
await callbacks.run('beforeCreateDirectRoom', membersUsernames, roomExtraData);
73+
7374
const roomMembers: IUser[] = await Users.findUsersByUsernames(membersUsernames, {
7475
projection: { _id: 1, name: 1, username: 1, settings: 1, customFields: 1 },
7576
}).toArray();
@@ -179,7 +180,11 @@ export async function createDirectRoom(
179180
if (isNewRoom) {
180181
const insertedRoom = await Rooms.findOneById(rid);
181182

182-
await callbacks.run('afterCreateDirectRoom', insertedRoom, { members: roomMembers, creatorId: options?.creator });
183+
await callbacks.run('afterCreateDirectRoom', insertedRoom, {
184+
members: roomMembers,
185+
creatorId: options?.creator,
186+
mrid: options?.federatedRoomId,
187+
});
183188

184189
void Apps.self?.triggerEvent(AppEvents.IPostRoomCreate, insertedRoom);
185190
}

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ async function createUsersSubscriptions({
6868

6969
const membersCursor = Users.findUsersByUsernames(members);
7070

71+
// TODO: Check re new federation-service - should we add them here or keep on createRoom inside of homeserver?!
7172
for await (const member of membersCursor) {
7273
try {
7374
await beforeAddUserToRoom.run({ user: member, inviter: owner }, room);
@@ -131,7 +132,25 @@ export const createRoom = async <T extends RoomType>(
131132
rid: string;
132133
}
133134
> => {
134-
const { teamId, ...extraData } = roomExtraData || ({} as IRoom);
135+
const { teamId, ...optionalExtraData } = roomExtraData || ({} as IRoom);
136+
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+
144+
const extraData = {
145+
...optionalExtraData,
146+
...((hasFederatedMembers || optionalExtraData.federated) && {
147+
federated: true,
148+
federation: {
149+
version: 1,
150+
// TODO we should be able to provide all values from here, currently we update on callback afterCreateRoom
151+
},
152+
}),
153+
};
135154

136155
await prepareCreateRoomCallback.run({
137156
type,
@@ -265,6 +284,7 @@ export const createRoom = async <T extends RoomType>(
265284
callbacks.runAsync('afterCreatePrivateGroup', owner, room);
266285
}
267286
callbacks.runAsync('afterCreateRoom', owner, room);
287+
268288
if (shouldBeHandledByFederation) {
269289
callbacks.runAsync('federation.afterCreateFederatedRoom', room, { owner, originalMemberList: members, options });
270290
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export async function deleteMessage(message: IMessage, user: IUser): Promise<voi
9393
await Rooms.decreaseMessageCountById(message.rid, 1);
9494
}
9595

96-
await callbacks.run('afterDeleteMessage', deletedMsg, room);
96+
await callbacks.run('afterDeleteMessage', deletedMsg, { room, user });
9797

9898
void notifyOnRoomChangedById(message.rid);
9999

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

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { Federation, FederationEE, License } from '@rocket.chat/core-services';
21
import type { IUser, IUserEmail } from '@rocket.chat/core-typings';
32
import { isUserFederated, isDirectMessageRoom } from '@rocket.chat/core-typings';
4-
import { Rooms, Users, Subscriptions, MatrixBridgedUser } from '@rocket.chat/models';
3+
import { Rooms, Users, Subscriptions } from '@rocket.chat/models';
54
import { Accounts } from 'meteor/accounts-base';
65
import { check } from 'meteor/check';
76
import { Meteor } from 'meteor/meteor';
@@ -71,22 +70,6 @@ export async function setUserActiveStatus(
7170
});
7271
}
7372

74-
if (user.active !== active) {
75-
const remoteUser = await MatrixBridgedUser.getExternalUserIdByLocalUserId(userId);
76-
77-
if (remoteUser) {
78-
if (active) {
79-
throw new Meteor.Error('error-not-allowed', 'Deactivated federated users can not be re-activated', {
80-
method: 'setUserActiveStatus',
81-
});
82-
}
83-
84-
const federation = (await License.hasValidLicense()) ? FederationEE : Federation;
85-
86-
await federation.deactivateRemoteUser(remoteUser);
87-
}
88-
}
89-
9073
// Users without username can't do anything, so there is no need to check for owned rooms
9174
if (user.username != null && !active) {
9275
const userAdmin = await Users.findOneAdmin(userId || '');

0 commit comments

Comments
 (0)