Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:RocketChat/Rocket.Chat into brea…
Browse files Browse the repository at this point in the history
…k/blockstack-removal
  • Loading branch information
tassoevan committed Jun 6, 2022
2 parents cc6e19d + 9a4c6cb commit 4466a64
Show file tree
Hide file tree
Showing 205 changed files with 4,221 additions and 1,801 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';

import { FederatedRoom } from '../domain/FederatedRoom';
import { FederatedUser } from '../domain/FederatedUser';
import { EVENT_ORIGIN, IFederationBridge } from '../domain/IFederationBridge';
import { RocketChatMessageAdapter } from '../infrastructure/rocket-chat/adapters/Message';
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 {
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,
) {} // eslint-disable-line no-empty-function

public async createRoom(roomCreateInput: FederationRoomCreateInputDto): Promise<void> {
const {
externalRoomId,
externalInviterId,
normalizedInviterId,
externalRoomName,
normalizedRoomId,
roomType,
wasInternallyProgramaticallyCreated = false,
} = roomCreateInput;

if ((await this.rocketRoomAdapter.getFederatedRoomByExternalId(externalRoomId)) || wasInternallyProgramaticallyCreated) {
return;
}

if (!(await this.rocketUserAdapter.getFederatedUserByExternalId(externalInviterId))) {
const externalUserProfileInformation = await this.bridge.getUserProfileInformation(externalInviterId);
const name = externalUserProfileInformation?.displayname || normalizedInviterId;
const federatedCreatorUser = FederatedUser.createInstance(externalInviterId, {
name,
username: normalizedInviterId,
existsOnlyOnProxyServer: false,
});

await this.rocketUserAdapter.createFederatedUser(federatedCreatorUser);
}
const creator = await this.rocketUserAdapter.getFederatedUserByExternalId(externalInviterId);
const newFederatedRoom = FederatedRoom.createInstance(
externalRoomId,
normalizedRoomId,
creator as FederatedUser,
roomType || RoomType.CHANNEL,
externalRoomName,
);
await this.rocketRoomAdapter.createFederatedRoom(newFederatedRoom);
}

public async changeRoomMembership(roomChangeMembershipInput: FederationRoomChangeMembershipDto): Promise<void> {
const {
externalRoomId,
normalizedInviteeId,
normalizedRoomId,
normalizedInviterId,
externalRoomName,
externalInviteeId,
externalInviterId,
inviteeUsernameOnly,
inviterUsernameOnly,
eventOrigin,
roomType,
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}`);
}
const isInviterFromTheSameHomeServer = await this.bridge.isUserIdFromTheSameHomeserver(
externalInviterId,
this.rocketSettingsAdapter.getHomeServerDomain(),
);
const isInviteeFromTheSameHomeServer = await this.bridge.isUserIdFromTheSameHomeserver(
externalInviteeId,
this.rocketSettingsAdapter.getHomeServerDomain(),
);

if (!(await this.rocketUserAdapter.getFederatedUserByExternalId(externalInviterId))) {
const externalUserProfileInformation = await this.bridge.getUserProfileInformation(externalInviterId);
const name = externalUserProfileInformation.displayname || normalizedInviterId;
const username = isInviterFromTheSameHomeServer ? inviterUsernameOnly : normalizedInviterId;
const federatedInviterUser = FederatedUser.createInstance(externalInviterId, {
name,
username,
existsOnlyOnProxyServer: isInviterFromTheSameHomeServer,
});

await this.rocketUserAdapter.createFederatedUser(federatedInviterUser);
}

if (!(await this.rocketUserAdapter.getFederatedUserByExternalId(externalInviteeId))) {
const externalUserProfileInformation = await this.bridge.getUserProfileInformation(externalInviteeId);
const name = externalUserProfileInformation.displayname || normalizedInviteeId;
const username = isInviteeFromTheSameHomeServer ? inviteeUsernameOnly : normalizedInviteeId;
const federatedInviteeUser = FederatedUser.createInstance(externalInviteeId, {
name,
username,
existsOnlyOnProxyServer: isInviteeFromTheSameHomeServer,
});

await this.rocketUserAdapter.createFederatedUser(federatedInviteeUser);
}

const federatedInviteeUser = await this.rocketUserAdapter.getFederatedUserByExternalId(externalInviteeId);
const federatedInviterUser = await this.rocketUserAdapter.getFederatedUserByExternalId(externalInviterId);

if (!affectedFederatedRoom && eventOrigin === EVENT_ORIGIN.REMOTE) {
const members = [federatedInviterUser, federatedInviteeUser] as any[];
const newFederatedRoom = FederatedRoom.createInstance(
externalRoomId,
normalizedRoomId,
federatedInviterUser as FederatedUser,
roomType,
externalRoomName,
members,
);

await this.rocketRoomAdapter.createFederatedRoom(newFederatedRoom);
await this.bridge.joinRoom(externalRoomId, externalInviteeId);
}
const federatedRoom = affectedFederatedRoom || (await this.rocketRoomAdapter.getFederatedRoomByExternalId(externalRoomId));

if (leave) {
return this.rocketRoomAdapter.removeUserFromRoom(
federatedRoom as FederatedRoom,
federatedInviteeUser as FederatedUser,
federatedInviterUser as FederatedUser,
);
}
await this.rocketRoomAdapter.addUserToRoom(
federatedRoom as FederatedRoom,
federatedInviteeUser as FederatedUser,
federatedInviterUser as FederatedUser,
);
}

public async receiveExternalMessage(roomSendInternalMessageInput: FederationRoomSendInternalMessageDto): Promise<void> {
const { externalRoomId, externalSenderId, text } = roomSendInternalMessageInput;

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

const senderUser = await this.rocketUserAdapter.getFederatedUserByExternalId(externalSenderId);
if (!senderUser) {
return;
}

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);
}
}
128 changes: 128 additions & 0 deletions apps/meteor/app/federation-v2/server/application/RoomServiceSender.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';
import { IMessage, IRoom, 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';

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

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

if (!(await this.rocketUserAdapter.getFederatedUserByInternalId(internalInviterId))) {
const internalUser = (await this.rocketUserAdapter.getInternalUserById(internalInviterId)) as IUser;
const externalInviterId = await this.bridge.createUser(
internalUser.username as string,
internalUser.name as string,
this.rocketSettingsAdapter.getHomeServerDomain(),
);
const federatedInviterUser = FederatedUser.createInstance(externalInviterId, {
name: internalUser.name as string,
username: internalUser.username as string,
existsOnlyOnProxyServer: true,
});
await this.rocketUserAdapter.createFederatedUser(federatedInviterUser);
}

if (!(await this.rocketUserAdapter.getFederatedUserByInternalUsername(normalizedInviteeId))) {
const externalUserProfileInformation = await this.bridge.getUserProfileInformation(rawInviteeId);
const name = externalUserProfileInformation?.displayname || normalizedInviteeId;
const federatedInviteeUser = FederatedUser.createInstance(rawInviteeId, {
name,
username: normalizedInviteeId,
existsOnlyOnProxyServer: false,
});

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(),
);

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 newFederatedRoom = FederatedRoom.createInstance(
externalRoomId,
externalRoomId,
federatedInviterUser,
internalRoom.t as RoomType,
roomName,
);
await this.rocketRoomAdapter.updateFederatedRoomByInternalRoomId(internalRoom._id, newFederatedRoom);
}

const federatedRoom = (await this.rocketRoomAdapter.getFederatedRoomByInternalId(internalRoomId)) as FederatedRoom;
const wasInvitedWhenTheRoomWasCreated = federatedRoom.isDirectMessage();
if (isInviteeFromTheSameHomeServer) {
await this.bridge.createUser(
inviteeUsernameOnly,
federatedInviteeUser.internalReference.name as string,
this.rocketSettingsAdapter.getHomeServerDomain(),
);
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);
}

public async sendMessageFromRocketChat(roomSendExternalMessageInput: FederationRoomSendExternalMessageDto): Promise<IMessage> {
const { internalRoomId, internalSenderId, message } = roomSendExternalMessageInput;

const federatedSender = await this.rocketUserAdapter.getFederatedUserByInternalId(internalSenderId);
const federatedRoom = await this.rocketRoomAdapter.getFederatedRoomByInternalId(internalRoomId);

if (!federatedSender) {
throw new Error(`Could not find user id for ${internalSenderId}`);
}
if (!federatedRoom) {
throw new Error(`Could not find room id for ${internalRoomId}`);
}

await this.bridge.sendMessage(federatedRoom.externalId, federatedSender.externalId, message.msg);

return message;
}

public async isAFederatedRoom(internalRoomId: string): Promise<boolean> {
if (!internalRoomId) {
return false;
}
const federatedRoom = await this.rocketRoomAdapter.getFederatedRoomByInternalId(internalRoomId);

return Boolean(federatedRoom?.isFederated());
}
}
Loading

0 comments on commit 4466a64

Please sign in to comment.