-
Notifications
You must be signed in to change notification settings - Fork 10.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' of github.com:RocketChat/Rocket.Chat into brea…
…k/blockstack-removal
- Loading branch information
Showing
205 changed files
with
4,221 additions
and
1,801 deletions.
There are no files selected for viewing
217 changes: 217 additions & 0 deletions
217
apps/meteor/app/federation-v2/server/application/RoomServiceReceiver.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
128
apps/meteor/app/federation-v2/server/application/RoomServiceSender.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | ||
} | ||
} |
Oops, something went wrong.