diff --git a/apps/meteor/app/lib/server/functions/sendMessage.js b/apps/meteor/app/lib/server/functions/sendMessage.js
index e80b527573f..f067a3ad78a 100644
--- a/apps/meteor/app/lib/server/functions/sendMessage.js
+++ b/apps/meteor/app/lib/server/functions/sendMessage.js
@@ -10,6 +10,7 @@ import { hasPermission } from '../../../authorization/server';
import { SystemLogger } from '../../../../server/lib/logger/system';
import { parseUrlsInMessage } from './parseUrlsInMessage';
import { isRelativeURL } from '../../../../lib/utils/isRelativeURL';
+import notifications from '../../../notifications/server/lib/Notifications';
/**
* IMPORTANT
@@ -244,7 +245,10 @@ export const sendMessage = function (user, message, room, upsert = false) {
message = callbacks.run('beforeSaveMessage', message, room);
if (message) {
- if (message._id && upsert) {
+ if (message.t === 'otr') {
+ const otrStreamer = notifications.streamRoomMessage;
+ otrStreamer.emit(message.rid, message, user, room);
+ } else if (message._id && upsert) {
const { _id } = message;
delete message._id;
Messages.upsert(
diff --git a/apps/meteor/app/otr/client/OTRRoom.ts b/apps/meteor/app/otr/client/OTRRoom.ts
index f722a6191cc..57c4097c844 100644
--- a/apps/meteor/app/otr/client/OTRRoom.ts
+++ b/apps/meteor/app/otr/client/OTRRoom.ts
@@ -66,8 +66,7 @@ export class OTRRoom implements IOTRRoom {
}
setState(nextState: OtrRoomState): void {
- const currentState = this.state.get();
- if (currentState === nextState) {
+ if (this.getState() === nextState) {
return;
}
@@ -141,7 +140,7 @@ export class OTRRoom implements IOTRRoom {
this._userOnlineComputation = Tracker.autorun(() => {
const $room = $(`#chat-window-${this._roomId}`);
const $title = $('.rc-header__title', $room);
- if (this.state.get() === OtrRoomState.ESTABLISHED) {
+ if (this.getState() === OtrRoomState.ESTABLISHED) {
if ($room.length && $title.length && !$('.otr-icon', $title).length) {
$title.prepend("");
}
@@ -252,8 +251,8 @@ export class OTRRoom implements IOTRRoom {
const establishConnection = async (): Promise => {
this.setState(OtrRoomState.ESTABLISHING);
Meteor.clearTimeout(timeout);
-
try {
+ if (!data.publicKey) throw new Error('Public key is not generated');
await this.generateKeyPair();
await this.importPublicKey(data.publicKey);
await goToRoomById(data.roomId);
@@ -283,11 +282,11 @@ export class OTRRoom implements IOTRRoom {
throw new Meteor.Error('user-not-defined', 'User not defined.');
}
- if (data.refresh && this.state.get() === OtrRoomState.ESTABLISHED) {
+ if (data.refresh && this.getState() === OtrRoomState.ESTABLISHED) {
this.reset();
await establishConnection();
} else {
- if (this.state.get() === OtrRoomState.ESTABLISHED) {
+ if (this.getState() === OtrRoomState.ESTABLISHED) {
this.reset();
}
imperativeModal.open({
@@ -308,11 +307,11 @@ export class OTRRoom implements IOTRRoom {
},
},
});
+ timeout = Meteor.setTimeout(() => {
+ this.setState(OtrRoomState.TIMEOUT);
+ imperativeModal.close();
+ }, 10000);
}
- timeout = Meteor.setTimeout(() => {
- this.setState(OtrRoomState.TIMEOUT);
- imperativeModal.close();
- }, 10000);
} catch (e) {
dispatchToastMessage({ type: 'error', message: e });
}
@@ -320,6 +319,7 @@ export class OTRRoom implements IOTRRoom {
case 'acknowledge':
try {
+ if (!data.publicKey) throw new Error('Public key is not generated');
await this.importPublicKey(data.publicKey);
this.setState(OtrRoomState.ESTABLISHED);
@@ -334,7 +334,7 @@ export class OTRRoom implements IOTRRoom {
break;
case 'deny':
- if (this.state.get() === OtrRoomState.ESTABLISHING) {
+ if (this.getState() === OtrRoomState.ESTABLISHING) {
this.reset();
this.setState(OtrRoomState.DECLINED);
}
@@ -347,7 +347,7 @@ export class OTRRoom implements IOTRRoom {
throw new Meteor.Error('user-not-defined', 'User not defined.');
}
- if (this.state.get() === OtrRoomState.ESTABLISHED) {
+ if (this.getState() === OtrRoomState.ESTABLISHED) {
this.reset();
this.setState(OtrRoomState.NOT_STARTED);
imperativeModal.open({
diff --git a/apps/meteor/app/otr/lib/IOTR.ts b/apps/meteor/app/otr/lib/IOTR.ts
index 33548be6a43..da595114a9d 100644
--- a/apps/meteor/app/otr/lib/IOTR.ts
+++ b/apps/meteor/app/otr/lib/IOTR.ts
@@ -5,8 +5,8 @@ import type { OTRRoom } from '../client/OTRRoom';
export interface IOnUserStreamData {
roomId: IRoom['_id'];
- publicKey: string;
userId: IUser['_id'];
+ publicKey?: string;
refresh?: boolean;
}
diff --git a/apps/meteor/app/otr/server/index.ts b/apps/meteor/app/otr/server/index.ts
index 8d489ec9c16..3657e7d2393 100644
--- a/apps/meteor/app/otr/server/index.ts
+++ b/apps/meteor/app/otr/server/index.ts
@@ -1,4 +1,4 @@
import './settings';
-import './methods/deleteOldOTRMessages';
import './methods/updateOTRAck';
import './methods/sendSystemMessages';
+import './methods/deleteOldOTRMessages';
diff --git a/apps/meteor/app/otr/server/methods/updateOTRAck.ts b/apps/meteor/app/otr/server/methods/updateOTRAck.ts
index b4444ac5656..1eff9d8638e 100644
--- a/apps/meteor/app/otr/server/methods/updateOTRAck.ts
+++ b/apps/meteor/app/otr/server/methods/updateOTRAck.ts
@@ -1,13 +1,13 @@
-import type { IMessage } from '@rocket.chat/core-typings';
import { Meteor } from 'meteor/meteor';
-import { Messages } from '../../../models/server';
+import notifications from '../../../notifications/server/lib/Notifications';
Meteor.methods({
- updateOTRAck(_id: IMessage['_id'], ack: IMessage['otrAck']): void {
+ updateOTRAck({ message, ack }) {
if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'updateOTRAck' });
}
- Messages.updateOTRAck(_id, ack);
+ const otrStreamer = notifications.streamRoomMessage;
+ otrStreamer.emit(message.rid, { ...message, otr: { ack } });
},
});
diff --git a/apps/meteor/app/ui-utils/client/lib/RoomManager.ts b/apps/meteor/app/ui-utils/client/lib/RoomManager.ts
index 85f281f9440..3ba6756212c 100644
--- a/apps/meteor/app/ui-utils/client/lib/RoomManager.ts
+++ b/apps/meteor/app/ui-utils/client/lib/RoomManager.ts
@@ -193,7 +193,7 @@ const computation = Tracker.autorun(() => {
}
}
- msg.name = room.name;
+ msg.name = room.name || '';
handleTrackSettingsChange(msg);
diff --git a/apps/meteor/client/startup/otr.ts b/apps/meteor/client/startup/otr.ts
index f10d1a298dd..e63b76275d5 100644
--- a/apps/meteor/client/startup/otr.ts
+++ b/apps/meteor/client/startup/otr.ts
@@ -1,23 +1,32 @@
-import { AtLeast, IMessage } from '@rocket.chat/core-typings';
+import { IMessage, IRoom, IUser, AtLeast } from '@rocket.chat/core-typings';
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import { Notifications } from '../../app/notifications/client';
import OTR from '../../app/otr/client/OTR';
-import { IOnUserStreamData, IOTRDecrypt } from '../../app/otr/lib/IOTR';
import { OtrRoomState } from '../../app/otr/lib/OtrRoomState';
import { t } from '../../app/utils/client';
import { onClientBeforeSendMessage } from '../lib/onClientBeforeSendMessage';
import { onClientMessageReceived } from '../lib/onClientMessageReceived';
+type NotifyUserData = {
+ roomId: IRoom['_id'];
+ userId: IUser['_id'];
+};
+
Meteor.startup(() => {
Tracker.autorun(() => {
if (Meteor.userId()) {
- Notifications.onUser('otr', (type: string, data: IOnUserStreamData) => {
+ Notifications.onUser('otr', (type: string, data: NotifyUserData) => {
+ if (!data.roomId || !data.userId || data.userId === Meteor.userId()) {
+ return;
+ }
const instanceByRoomId = OTR.getInstanceByRoomId(data.roomId);
- if (!data.roomId || !data.userId || data.userId === Meteor.userId() || !instanceByRoomId) {
+
+ if (!instanceByRoomId) {
return;
}
+
instanceByRoomId.onUserStream(type, data);
});
}
@@ -37,33 +46,32 @@ Meteor.startup(() => {
const instanceByRoomId = OTR.getInstanceByRoomId(message.rid);
if (message.rid && instanceByRoomId && instanceByRoomId.getState() === OtrRoomState.ESTABLISHED) {
- if (message.notification) {
+ if (message?.notification) {
message.msg = t('Encrypted_message');
return message;
}
- if (message?.t !== 'otr') {
+ if (message.t !== 'otr') {
return message;
}
- const otrRoom = instanceByRoomId;
- const decrypted = await otrRoom.decrypt(message.msg);
+
+ const decrypted = await instanceByRoomId.decrypt(message.msg);
if (typeof decrypted === 'string') {
return { ...message, msg: decrypted };
}
- const { _id, text: msg, ack, ts, userId }: IOTRDecrypt = decrypted;
+ const { _id, text: msg, ack, ts, userId } = decrypted;
if (ts) message.ts = ts;
if (message.otrAck) {
- const otrAck = await otrRoom.decrypt(message.otrAck);
+ const otrAck = await instanceByRoomId.decrypt(message.otrAck);
if (typeof otrAck === 'string') {
return { ...message, msg: otrAck };
}
-
if (ack === otrAck.text) message.t = 'otr-ack';
} else if (userId !== Meteor.userId()) {
- const encryptedAck = await otrRoom.encryptText(ack);
+ const encryptedAck = await instanceByRoomId.encryptText(ack);
- Meteor.call('updateOTRAck', _id, encryptedAck);
+ Meteor.call('updateOTRAck', { message, ack: encryptedAck });
}
return { ...message, _id, msg };
diff --git a/apps/meteor/server/modules/notifications/notifications.module.ts b/apps/meteor/server/modules/notifications/notifications.module.ts
index 5da8d00d757..e2243c0fccb 100644
--- a/apps/meteor/server/modules/notifications/notifications.module.ts
+++ b/apps/meteor/server/modules/notifications/notifications.module.ts
@@ -282,6 +282,10 @@ export class NotificationsModule {
this.streamUser.allowWrite(async function (eventName: string, data: unknown) {
const [, e] = eventName.split('/');
+ if (e === 'otr' && (data === 'handshake' || data === 'acknowledge')) {
+ const isEnable = await Settings.getValueById('OTR_Enable');
+ return Boolean(this.userId) && (isEnable === 'true' || isEnable === true);
+ }
if (e === 'webrtc') {
return true;
}
@@ -308,11 +312,15 @@ export class NotificationsModule {
this.streamUser.allowRead(async function (eventName) {
const [userId, e] = eventName.split('/');
+ if (e === 'otr') {
+ const isEnable = await Settings.getValueById('OTR_Enable');
+ return Boolean(this.userId) && this.userId === userId && (isEnable === 'true' || isEnable === true);
+ }
if (e === 'webrtc') {
return true;
}
- return this.userId != null && this.userId === userId;
+ return Boolean(this.userId) && this.userId === userId;
});
this.streamImporters.allowRead('all');
diff --git a/packages/core-typings/src/IMessage/IMessage.ts b/packages/core-typings/src/IMessage/IMessage.ts
index 6b12e428b5d..44bc4f48600 100644
--- a/packages/core-typings/src/IMessage/IMessage.ts
+++ b/packages/core-typings/src/IMessage/IMessage.ts
@@ -57,12 +57,11 @@ type OmnichannelTypesValues =
| 'omnichannel_on_hold_chat_resumed';
type OtrMessageTypeValues = 'otr' | 'otr-ack';
+
type OtrSystemMessages = 'user_joined_otr' | 'user_requested_otr_key_refresh' | 'user_key_refreshed_successfully';
export type MessageTypesValues =
| 'e2e'
- | 'otr'
- | 'otr-ack'
| 'uj'
| 'ul'
| 'ru'