Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEW] Rename slash command from bridge to federation #25846

Merged
merged 5 commits into from
Jun 13, 2022
Merged
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
1 change: 1 addition & 0 deletions apps/meteor/.mocharc.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module.exports = {
exit: true,
spec: [
'ee/tests/**/*.tests.ts',
'ee/tests/**/*.spec.ts',
'tests/unit/app/**/*.spec.ts',
'tests/unit/app/**/*.tests.js',
'tests/unit/app/**/*.tests.ts',
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/app/federation-v2/client/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './slash-commands';
20 changes: 20 additions & 0 deletions apps/meteor/app/federation-v2/client/slash-commands/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { slashCommands } from '../../../utils/lib/slashCommand';

const callback = undefined;
const result = undefined;
const providesPreview = false;
const previewer = undefined;
const previewCallback = undefined;

slashCommands.add(
'federation',
callback,
{
description: 'Federation_slash_commands',
params: '#command (dm) #user',
},
result,
providesPreview,
previewer,
previewCallback,
);
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,15 @@ import {
FederationRoomCreateInputDto,
FederationRoomChangeMembershipDto,
FederationRoomSendInternalMessageDto,
FederationRoomChangeJoinRulesDto,
FederationRoomChangeNameDto,
FederationRoomChangeTopicDto,
} from './input/RoomReceiverDto';

export class FederationRoomServiceReceiver {
constructor(
private rocketRoomAdapter: RocketChatRoomAdapter,
private rocketUserAdapter: RocketChatUserAdapter,
private rocketMessageAdapter: RocketChatMessageAdapter,
private rocketSettingsAdapter: RocketChatSettingsAdapter,
private bridge: IFederationBridge,
protected rocketRoomAdapter: RocketChatRoomAdapter,
protected rocketUserAdapter: RocketChatUserAdapter,
protected rocketMessageAdapter: RocketChatMessageAdapter,
protected rocketSettingsAdapter: RocketChatSettingsAdapter,
protected bridge: IFederationBridge,
) {} // eslint-disable-line no-empty-function

public async createRoom(roomCreateInput: FederationRoomCreateInputDto): Promise<void> {
Expand Down Expand Up @@ -78,6 +75,7 @@ export class FederationRoomServiceReceiver {
leave,
} = roomChangeMembershipInput;
const affectedFederatedRoom = await this.rocketRoomAdapter.getFederatedRoomByExternalId(externalRoomId);

if (!affectedFederatedRoom && eventOrigin === EVENT_ORIGIN.LOCAL) {
throw new Error(`Could not find room with external room id: ${externalRoomId}`);
}
Expand Down Expand Up @@ -120,7 +118,7 @@ export class FederationRoomServiceReceiver {
const federatedInviterUser = await this.rocketUserAdapter.getFederatedUserByExternalId(externalInviterId);

if (!affectedFederatedRoom && eventOrigin === EVENT_ORIGIN.REMOTE) {
const members = [federatedInviterUser, federatedInviteeUser] as any[];
const members = [federatedInviterUser, federatedInviteeUser] as FederatedUser[];
const newFederatedRoom = FederatedRoom.createInstance(
externalRoomId,
normalizedRoomId,
Expand Down Expand Up @@ -164,54 +162,4 @@ export class FederationRoomServiceReceiver {

await this.rocketMessageAdapter.sendMessage(senderUser, text, federatedRoom);
}

public async changeJoinRules(roomJoinRulesChangeInput: FederationRoomChangeJoinRulesDto): Promise<void> {
const { externalRoomId, roomType } = roomJoinRulesChangeInput;

const federatedRoom = await this.rocketRoomAdapter.getFederatedRoomByExternalId(externalRoomId);
if (!federatedRoom) {
return;
}

if (federatedRoom.isDirectMessage()) {
return;
}

federatedRoom.setRoomType(roomType);
await this.rocketRoomAdapter.updateRoomType(federatedRoom);
}

public async changeRoomName(roomChangeNameInput: FederationRoomChangeNameDto): Promise<void> {
const { externalRoomId, normalizedRoomName } = roomChangeNameInput;

const federatedRoom = await this.rocketRoomAdapter.getFederatedRoomByExternalId(externalRoomId);
if (!federatedRoom) {
return;
}

if (federatedRoom.isDirectMessage()) {
return;
}

federatedRoom.changeRoomName(normalizedRoomName);

await this.rocketRoomAdapter.updateRoomName(federatedRoom);
}

public async changeRoomTopic(roomChangeTopicInput: FederationRoomChangeTopicDto): Promise<void> {
const { externalRoomId, roomTopic } = roomChangeTopicInput;

const federatedRoom = await this.rocketRoomAdapter.getFederatedRoomByExternalId(externalRoomId);
if (!federatedRoom) {
return;
}

if (federatedRoom.isDirectMessage()) {
return;
}

federatedRoom.changeRoomTopic(roomTopic);

await this.rocketRoomAdapter.updateRoomTopic(federatedRoom);
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';
import { IMessage, IRoom, IUser } from '@rocket.chat/core-typings';
import { IMessage, IUser } from '@rocket.chat/core-typings';

import { FederatedRoom } from '../domain/FederatedRoom';
import { FederatedUser } from '../domain/FederatedUser';
import { IFederationBridge } from '../domain/IFederationBridge';
import { RocketChatNotificationAdapter } from '../infrastructure/rocket-chat/adapters/Notification';
import { RocketChatRoomAdapter } from '../infrastructure/rocket-chat/adapters/Room';
import { RocketChatSettingsAdapter } from '../infrastructure/rocket-chat/adapters/Settings';
import { RocketChatUserAdapter } from '../infrastructure/rocket-chat/adapters/User';
import { FederationRoomInviteUserDto, FederationRoomSendExternalMessageDto } from './input/RoomSenderDto';
import { FederationCreateDMAndInviteUserDto, FederationRoomSendExternalMessageDto } from './input/RoomSenderDto';

export class FederationRoomServiceSender {
constructor(
private rocketRoomAdapter: RocketChatRoomAdapter,
private rocketUserAdapter: RocketChatUserAdapter,
private rocketSettingsAdapter: RocketChatSettingsAdapter,
private rocketNotificationAdapter: RocketChatNotificationAdapter,
private bridge: IFederationBridge,
protected rocketRoomAdapter: RocketChatRoomAdapter,
protected rocketUserAdapter: RocketChatUserAdapter,
protected rocketSettingsAdapter: RocketChatSettingsAdapter,
protected bridge: IFederationBridge,
) {} // eslint-disable-line no-empty-function

public async inviteUserToAFederatedRoom(roomInviteUserInput: FederationRoomInviteUserDto): Promise<void> {
const { normalizedInviteeId, rawInviteeId, internalInviterId, inviteeUsernameOnly, internalRoomId } = roomInviteUserInput;
public async createDirectMessageRoomAndInviteUser(roomCreateDMAndInviteUserInput: FederationCreateDMAndInviteUserDto): Promise<void> {
const { normalizedInviteeId, rawInviteeId, internalInviterId, inviteeUsernameOnly } = roomCreateDMAndInviteUserInput;

if (!(await this.rocketUserAdapter.getFederatedUserByInternalId(internalInviterId))) {
const internalUser = (await this.rocketUserAdapter.getInternalUserById(internalInviterId)) as IUser;
Expand Down Expand Up @@ -48,36 +46,28 @@ export class FederationRoomServiceSender {

await this.rocketUserAdapter.createFederatedUser(federatedInviteeUser);
}

const federatedInviterUser = (await this.rocketUserAdapter.getFederatedUserByInternalId(internalInviterId)) as FederatedUser;
const federatedInviteeUser = (await this.rocketUserAdapter.getFederatedUserByInternalUsername(normalizedInviteeId)) as FederatedUser;
const isInviteeFromTheSameHomeServer = await this.bridge.isUserIdFromTheSameHomeserver(
rawInviteeId,
this.rocketSettingsAdapter.getHomeServerDomain(),
);
const internalRoomId = FederatedRoom.buildRoomIdForDirectMessages(federatedInviterUser, federatedInviteeUser);

if (!(await this.rocketRoomAdapter.getFederatedRoomByInternalId(internalRoomId))) {
const internalRoom = (await this.rocketRoomAdapter.getInternalRoomById(internalRoomId)) as IRoom;
const roomName = (internalRoom.fname || internalRoom.name) as string;
const externalRoomId = await this.bridge.createRoom(
federatedInviterUser.externalId,
federatedInviteeUser.externalId,
internalRoom.t as RoomType,
roomName,
internalRoom.topic,
);
const externalRoomId = await this.bridge.createDirectMessageRoom(federatedInviterUser.externalId, federatedInviteeUser.externalId);
const newFederatedRoom = FederatedRoom.createInstance(
externalRoomId,
externalRoomId,
federatedInviterUser,
internalRoom.t as RoomType,
roomName,
RoomType.DIRECT_MESSAGE,
'',
[federatedInviterUser, federatedInviteeUser] as any[],
);
await this.rocketRoomAdapter.updateFederatedRoomByInternalRoomId(internalRoom._id, newFederatedRoom);
await this.rocketRoomAdapter.createFederatedRoomForDirectMessage(newFederatedRoom);
}

const federatedRoom = (await this.rocketRoomAdapter.getFederatedRoomByInternalId(internalRoomId)) as FederatedRoom;
const wasInvitedWhenTheRoomWasCreated = federatedRoom.isDirectMessage();
if (isInviteeFromTheSameHomeServer) {
await this.bridge.createUser(
inviteeUsernameOnly,
Expand All @@ -86,15 +76,6 @@ export class FederationRoomServiceSender {
);
await this.bridge.inviteToRoom(federatedRoom.externalId, federatedInviterUser.externalId, federatedInviteeUser.externalId);
await this.bridge.joinRoom(federatedRoom.externalId, federatedInviteeUser.externalId);
} else if (!wasInvitedWhenTheRoomWasCreated) {
this.bridge.inviteToRoom(federatedRoom.externalId, federatedInviterUser.externalId, federatedInviteeUser.externalId).catch(() => {
this.rocketNotificationAdapter.notifyWithEphemeralMessage(
'Federation_Matrix_only_owners_can_invite_users',
federatedInviterUser?.internalReference?._id,
internalRoomId,
federatedInviterUser?.internalReference?.language,
);
});
}
await this.rocketRoomAdapter.addUserToRoom(federatedRoom, federatedInviteeUser, federatedInviterUser);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,3 @@ export class FederationRoomSendInternalMessageDto extends BaseRoom {

text: string;
}

export class FederationRoomChangeJoinRulesDto extends BaseRoom {
roomType: RoomType;
}

export class FederationRoomChangeNameDto extends BaseRoom {
normalizedRoomName: string;
}

export class FederationRoomChangeTopicDto extends BaseRoom {
roomTopic: string;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IMessage } from '@rocket.chat/core-typings';

export class FederationRoomInviteUserDto {
export class FederationCreateDMAndInviteUserDto {
internalInviterId: string;

internalRoomId: string;
Expand Down
40 changes: 9 additions & 31 deletions apps/meteor/app/federation-v2/server/domain/FederatedRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export class FederatedRoom {
public internalReference: IRoom;

// eslint-disable-next-line
private constructor() {}
protected constructor() {}

private static generateTemporaryName(normalizedExternalId: string): string {
protected static generateTemporaryName(normalizedExternalId: string): string {
return `Federation-${normalizedExternalId}`;
}

Expand All @@ -23,12 +23,12 @@ export class FederatedRoom {
creator: FederatedUser,
type: RoomType,
name?: string,
members?: IUser[],
members?: FederatedUser[],
): FederatedRoom {
const roomName = name || FederatedRoom.generateTemporaryName(normalizedExternalId);
return Object.assign(new FederatedRoom(), {
externalId,
...(type === RoomType.DIRECT_MESSAGE ? { members } : {}),
members,
internalReference: {
t: type,
name: roomName,
Expand All @@ -42,37 +42,15 @@ export class FederatedRoom {
return new FederatedRoom();
}

public isDirectMessage(): boolean {
return this.internalReference?.t === RoomType.DIRECT_MESSAGE;
}

public setRoomType(type: RoomType): void {
if (this.isDirectMessage()) {
throw new Error('Its not possible to change a direct message type');
}
this.internalReference.t = type;
}

public changeRoomName(name: string): void {
if (this.isDirectMessage()) {
throw new Error('Its not possible to change a direct message name');
}
this.internalReference.name = name;
this.internalReference.fname = name;
}

public changeRoomTopic(topic: string): void {
if (this.isDirectMessage()) {
throw new Error('Its not possible to change a direct message topic');
}
this.internalReference.description = topic;
}

public getMembers(): IUser[] {
return this.isDirectMessage() && this.members && this.members.length > 0 ? this.members.map((user) => user.internalReference) : [];
return this.members && this.members.length > 0 ? this.members.map((user) => user.internalReference) : [];
}

public isFederated(): boolean {
return this.internalReference?.federated === true;
}

public static buildRoomIdForDirectMessages(inviter: FederatedUser, invitee: FederatedUser): string {
return inviter.internalReference?._id + invitee.internalReference?._id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class FederatedUser {
public existsOnlyOnProxyServer: boolean;

// eslint-disable-next-line
private constructor() {}
protected constructor() {}

public static createInstance(externalId: string, params: IFederatedUserCreationParams): FederatedUser {
return Object.assign(new FederatedUser(), {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';

export interface IFederationBridge {
start(): Promise<void>;
stop(): Promise<void>;
onFederationAvailabilityChanged(enabled: boolean): Promise<void>;
getUserProfileInformation(externalUserId: string): Promise<any>;
joinRoom(externalRoomId: string, externalUserId: string): Promise<void>;
createRoom(
externalCreatorId: string,
externalInviteeId: string,
roomType: RoomType,
roomName: string,
roomTopic?: string,
): Promise<string>;
createDirectMessageRoom(externalCreatorId: string, externalInviteeId: string): Promise<string>;
inviteToRoom(externalRoomId: string, externalInviterId: string, externalInviteeId: string): Promise<void>;
sendMessage(externalRoomId: string, externaSenderId: string, text: string): Promise<void>;
createUser(username: string, name: string, domain: string): Promise<string>;
Expand Down
23 changes: 15 additions & 8 deletions apps/meteor/app/federation-v2/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { FederationFactoryEE } from '../../../ee/app/federation-v2/server/infrastructure/Factory';
import { FederationFactory } from './infrastructure/Factory';
import './infrastructure/rocket-chat/slash-commands';

const PROCESSING_CONCURRENCY = 1;
export const FEDERATION_PROCESSING_CONCURRENCY = 1;

const rocketSettingsAdapter = FederationFactory.buildRocketSettingsAdapter();
rocketSettingsAdapter.initialize();
const queueInstance = FederationFactory.buildQueue();
const federation = FederationFactory.buildBridge(rocketSettingsAdapter, queueInstance);
const rocketRoomAdapter = FederationFactory.buildRocketRoomAdapter();
const federation = FederationFactoryEE.buildBridge(rocketSettingsAdapter, queueInstance);
const rocketRoomAdapter = FederationFactoryEE.buildRocketRoomAdapter();
const rocketUserAdapter = FederationFactory.buildRocketUserAdapter();
const rocketMessageAdapter = FederationFactory.buildRocketMessageAdapter();
const rocketNotificationAdapter = FederationFactory.buildRocketNotificationdapter();

const federationRoomServiceReceiver = FederationFactory.buildRoomServiceReceiver(
rocketRoomAdapter,
Expand All @@ -24,12 +24,19 @@ export const federationRoomServiceSender = FederationFactory.buildRoomServiceSen
rocketRoomAdapter,
rocketUserAdapter,
rocketSettingsAdapter,
rocketNotificationAdapter,
federation,
);

(async (): Promise<void> => {
queueInstance.setHandler(federationEventsHandler.handleEvent.bind(federationEventsHandler), PROCESSING_CONCURRENCY);
export const runFederation = async (): Promise<void> => {
queueInstance.setHandler(federationEventsHandler.handleEvent.bind(federationEventsHandler), FEDERATION_PROCESSING_CONCURRENCY);
await federation.start();
await rocketSettingsAdapter.onFederationEnabledStatusChanged(federation.onFederationAvailabilityChanged.bind(federation));
};

export const stopFederation = async (): Promise<void> => {
await federation.stop();
};

(async (): Promise<void> => {
await runFederation();
})();
Loading