[FIX] E2E messages not decrypting in message threads (#14580)

* fix e2e problems witg threads and message blinking

* fix lint?

* Update RoomManager.js

* ops

* refactor

* Update rocketchat.e2e.js

* fix decryptPendingMessages
rest-set-presence
Guilherme Gazzo 6 years ago committed by Rodrigo Nascimento
parent 4ee7903d38
commit 728e5c14e2
  1. 32
      app/e2e/client/rocketchat.e2e.js
  2. 2
      app/theme/client/imports/components/messages.css
  3. 8
      app/threads/client/flextab/thread.js
  4. 6
      app/threads/client/flextab/threads.js
  5. 22
      app/ui-message/client/message.js
  6. 28
      app/ui-utils/client/lib/RoomHistoryManager.js
  7. 89
      app/ui-utils/client/lib/RoomManager.js
  8. 15
      app/ui-utils/client/lib/openRoom.js

@ -228,13 +228,7 @@ class E2E {
this.decryptSubscription(doc);
});
Messages.after.update((userId, doc) => {
this.decryptMessage(doc);
});
Messages.after.insert((userId, doc) => {
this.decryptMessage(doc);
});
promises.add('onClientMessageReceived', (msg) => this.decryptMessage(msg), promises.priority.HIGH);
}
async changePassword(newPassword) {
@ -408,30 +402,30 @@ class E2E {
async decryptMessage(message) {
if (!this.isEnabled()) {
return;
return message;
}
if (message.t !== 'e2e' || message.e2e === 'done') {
return;
return message;
}
const e2eRoom = await this.getInstanceByRoomId(message.rid);
if (!e2eRoom) {
return;
return message;
}
const data = await e2eRoom.decrypt(message.msg);
if (!data) {
return;
return message;
}
Messages.direct.update({ _id: message._id }, {
$set: {
msg: data.text,
e2e: 'done',
},
});
return {
...message,
msg: data.text,
e2e: 'done',
};
}
async decryptPendingMessages() {
@ -439,8 +433,8 @@ class E2E {
return;
}
return Messages.find({ t: 'e2e', e2e: 'pending' }).forEach(async (item) => {
await this.decryptMessage(item);
return Messages.find({ t: 'e2e', e2e: 'pending' }).forEach(async ({ _id, ...msg }) => {
Messages.direct.update({ _id }, await this.decryptMessage(msg));
});
}

@ -132,6 +132,8 @@
.message-body {
&--unstyled {
vertical-align: sub;
font: inherit;
line-height: initial;

@ -7,11 +7,11 @@ import { Tracker } from 'meteor/tracker';
import { ChatMessages } from '../../../ui';
import { normalizeThreadMessage, call } from '../../../ui-utils/client';
import { messageContext } from '../../../ui-utils/client/lib/messageContext';
import { upsertMessageBulk } from '../../../ui-utils/client/lib/RoomHistoryManager';
import { Messages } from '../../../models';
import { lazyloadtick } from '../../../lazy-load';
import { fileUpload } from '../../../ui/client/lib/fileUpload';
import { dropzoneEvents } from '../../../ui/client/views/app/room';
import { upsert } from '../upsert';
import './thread.html';
const sort = { ts: 1 };
@ -139,11 +139,13 @@ Template.thread.onRendered(function() {
});
});
this.autorun(() => {
const jump = this.state.get('jump');
const loading = this.state.get('loading');
if (jump && loading === false) {
if (jump && this.lastJump !== jump && loading === false) {
this.lastJump = jump;
this.find('.js-scroll-thread').style.scrollBehavior = 'smooth';
this.state.set('jump', null);
Tracker.afterFlush(() => {
@ -179,7 +181,7 @@ Template.thread.onCreated(async function() {
const messages = await call('getThreadMessages', { tmid });
upsert(this.Threads, messages);
upsertMessageBulk({ msgs: messages }, this.Threads);
Tracker.afterFlush(() => {
this.state.set('loading', false);

@ -10,7 +10,7 @@ import { Messages, Subscriptions } from '../../../models';
import { messageContext } from '../../../ui-utils/client/lib/messageContext';
import { messageArgs } from '../../../ui-utils/client/lib/messageArgs';
import { getConfig } from '../../../ui-utils/client/config';
import { upsert } from '../upsert';
import { upsertMessageBulk } from '../../../ui-utils/client/lib/RoomHistoryManager';
import './threads.html';
@ -99,8 +99,8 @@ Template.threads.onCreated(async function() {
this.state.set('loading', rid);
const threads = await call('getThreadsList', { rid, limit: LIST_SIZE, skip: limit - LIST_SIZE });
upsert(this.Threads, threads);
const messages = await call('getThreadsList', { rid, limit: LIST_SIZE, skip: limit - LIST_SIZE });
upsertMessageBulk({ msgs: messages }, this.Threads);
// threads.forEach(({ _id, ...msg }) => this.Threads.upsert({ _id }, msg));
this.state.set('loading', false);
}, 500);

@ -12,6 +12,7 @@ import { RoomRoles, UserRoles, Roles, Messages } from '../../models/client';
import { callbacks } from '../../callbacks/client';
import { Markdown } from '../../markdown/client';
import { t, roomTypes, getURL } from '../../utils';
import { upsertMessage } from '../../ui-utils/client/lib/RoomHistoryManager';
import { messageArgs } from '../../ui-utils/client/lib/messageArgs';
import './message.html';
import './messageThread.html';
@ -406,7 +407,7 @@ Template.message.helpers({
},
isThreadReply() {
const { msg: { tmid, t }, settings: { showreply } } = this;
return !!(tmid && showreply && !t);
return !!(tmid && showreply && (!t || t === 'e2e'));
},
collapsed() {
const { msg: { tmid, collapsed }, settings: { showreply }, shouldCollapseReplies } = this;
@ -433,24 +434,7 @@ const findParentMessage = (() => {
const uid = Tracker.nonreactive(() => Meteor.userId());
const _tmp = [...waiting];
waiting.length = 0;
const messages = await call('getMessages', _tmp);
messages.forEach((message) => {
if (!message) {
return;
}
const { _id, ...msg } = message;
Messages.update({ tmid: _id, repliesCount: { $exists: 0 } }, {
$set: {
following: message.replies && message.replies.indexOf(uid) > -1,
threadMsg: normalizeThreadMessage(msg),
repliesCount: msg.tcount,
},
}, { multi: true });
if (!Messages.findOne({ _id })) {
msg._hidden = true;
Messages.upsert({ _id }, msg);
}
});
(await call('getMessages', _tmp)).map((msg) => upsertMessage({ msg, uid }));
}, 500);
return (tmid) => {

@ -4,6 +4,7 @@ import { Tracker } from 'meteor/tracker';
import { ReactiveVar } from 'meteor/reactive-var';
import { Blaze } from 'meteor/blaze';
import { promises } from '../../../promises/client';
import { RoomManager } from './RoomManager';
import { readMessage } from './readMessages';
import { renderMessageBody } from './renderMessageBody';
@ -28,7 +29,7 @@ export const normalizeThreadMessage = (message) => {
}
};
export const upsertMessage = ({ msg: { _id, ...msg }, subscription }) => {
export const upsertMessage = async ({ msg, subscription, uid = Tracker.nonreactive(() => Meteor.userId()) }, collection = ChatMessage) => {
const userId = msg.u && msg.u._id;
if (subscription && subscription.ignored && subscription.ignored.indexOf(userId) > -1) {
@ -41,32 +42,36 @@ export const upsertMessage = ({ msg: { _id, ...msg }, subscription }) => {
// ].map((e) => e.roles);
// msg.roles = _.union.apply(_.union, roles);
if (msg.t === 'e2e' && !msg.file) {
msg.e2e = 'pending';
}
msg = await promises.run('onClientMessageReceived', msg) || msg;
const { _id, ...messageToUpsert } = msg;
if (msg.tcount) {
const uid = Tracker.nonreactive(() => Meteor.userId());
ChatMessage.update({ tmid: _id }, {
collection.direct.update({ tmid: _id }, {
$set: {
following: msg.replies && msg.replies.indexOf(uid) > -1,
threadMsg: normalizeThreadMessage(msg),
threadMsg: normalizeThreadMessage(messageToUpsert),
repliesCount: msg.tcount,
},
}, { multi: true });
}
return ChatMessage.upsert({ _id }, msg);
return collection.direct.upsert({ _id }, messageToUpsert);
};
function upsertMessageBulk({ msgs, subscription }) {
export function upsertMessageBulk({ msgs, subscription }, collection = ChatMessage) {
const uid = Tracker.nonreactive(() => Meteor.userId());
const { queries } = ChatMessage;
ChatMessage.queries = [];
collection.queries = [];
msgs.forEach((msg, index) => {
if (index === msgs.length - 1) {
ChatMessage.queries = queries;
}
upsertMessage({ msg, subscription });
upsertMessage({ msg, subscription, uid }, collection);
});
}
@ -95,6 +100,7 @@ export const RoomHistoryManager = new class {
getMore(rid, limit = defaultLimit) {
let ts;
const room = this.getRoom(rid);
if (room.hasMore.curValue !== true) {
return;
}
@ -162,10 +168,8 @@ export const RoomHistoryManager = new class {
}
room.isLoading.set(false);
Meteor.defer(() => {
readMessage.refreshUnreadMark(rid, true);
return RoomManager.updateMentionsMarksOfRoom(typeName);
});
readMessage.refreshUnreadMark(rid, true);
return RoomManager.updateMentionsMarksOfRoom(typeName);
});
}

@ -10,7 +10,7 @@ import { fireGlobalEvent } from './fireGlobalEvent';
import { upsertMessage, RoomHistoryManager } from './RoomHistoryManager';
import { mainReady } from './mainReady';
import { roomTypes } from '../../../utils';
import { promises } from '../../../promises/client';
import { call } from '../..';
import { callbacks } from '../../../callbacks';
import { Notifications } from '../../../notifications';
import { CachedChatRoom, ChatMessage, ChatSubscription, CachedChatSubscription } from '../../../models';
@ -50,56 +50,53 @@ export const RoomManager = new function() {
this.prototype.openedRooms = openedRooms;
this.prototype.onlineUsers = onlineUsers;
this.prototype.computation = Tracker.autorun(() => {
Object.keys(openedRooms).forEach((typeName) => {
const record = openedRooms[typeName];
const ready = CachedChatRoom.ready.get() && mainReady.get();
if (ready !== true) { return; }
const user = Meteor.user();
Tracker.nonreactive(() => Object.entries(openedRooms).forEach(([typeName, record]) => {
if (record.active !== true || record.ready === true) { return; }
const ready = CachedChatRoom.ready.get() && mainReady.get();
if (ready !== true) { return; }
const user = Meteor.user();
const type = typeName.substr(0, 1);
const name = typeName.substr(1);
const room = Tracker.nonreactive(() => roomTypes.findRoom(type, name, user));
const room = roomTypes.findRoom(type, name, user);
if (room != null) {
openedRooms[typeName].rid = room._id;
record.rid = room._id;
RoomHistoryManager.getMoreIfIsEmpty(room._id);
if (openedRooms[typeName].streamActive !== true) {
openedRooms[typeName].streamActive = true;
msgStream.on(openedRooms[typeName].rid, (msg) =>
promises.run('onClientMessageReceived', msg).then(function(msg) {
// Should not send message to room if room has not loaded all the current messages
if (RoomHistoryManager.hasMoreNext(openedRooms[typeName].rid) === false) {
// Do not load command messages into channel
if (msg.t !== 'command') {
const subscription = ChatSubscription.findOne({ rid: openedRooms[typeName].rid });
upsertMessage({ msg, subscription });
msg.room = {
type,
name,
};
}
msg.name = room.name;
RoomManager.updateMentionsMarksOfRoom(typeName);
callbacks.run('streamMessage', msg);
return fireGlobalEvent('new-message', msg);
}
})
);
Notifications.onRoom(openedRooms[typeName].rid, 'deleteMessage', onDeleteMessageStream); // eslint-disable-line no-use-before-define
Notifications.onRoom(openedRooms[typeName].rid, 'deleteMessageBulk', onDeleteMessageBulkStream); // eslint-disable-line no-use-before-define
if (record.streamActive !== true) {
record.streamActive = true;
msgStream.on(record.rid, async (msg) => {
// Should not send message to room if room has not loaded all the current messages
if (RoomHistoryManager.hasMoreNext(record.rid) !== false) {
return;
}
// Do not load command messages into channel
if (msg.t !== 'command') {
const subscription = ChatSubscription.findOne({ rid: record.rid }, { reactive: false });
upsertMessage({ msg, subscription });
msg.room = {
type,
name,
};
}
msg.name = room.name;
RoomManager.updateMentionsMarksOfRoom(typeName);
callbacks.run('streamMessage', msg);
return fireGlobalEvent('new-message', msg);
});
Notifications.onRoom(record.rid, 'deleteMessage', onDeleteMessageStream); // eslint-disable-line no-use-before-define
Notifications.onRoom(record.rid, 'deleteMessageBulk', onDeleteMessageBulkStream); // eslint-disable-line no-use-before-define
}
}
record.ready = true;
Dep.changed();
});
}));
Dep.changed();
});
}
@ -255,18 +252,24 @@ export const RoomManager = new function() {
return new Cls();
}();
const loadMissedMessages = function(rid) {
const loadMissedMessages = async function(rid) {
const lastMessage = ChatMessage.findOne({ rid, _hidden: { $ne: true }, temp: { $exists: false } }, { sort: { ts: -1 }, limit: 1 });
if (lastMessage == null) {
return;
}
const subscription = ChatSubscription.findOne({ rid });
return Meteor.call('loadMissedMessages', rid, lastMessage.ts, (err, result) => {
try {
const result = await call('loadMissedMessages', rid, lastMessage.ts);
if (result) {
return Array.from(result).map((item) => promises.run('onClientMessageReceived', item).then((msg) => upsertMessage({ msg, subscription })));
const subscription = ChatSubscription.findOne({ rid });
return Promise.all(Array.from(result).map((msg) => upsertMessage({ msg, subscription })));
}
return [];
});
} catch (error) {
return [];
}
};
let connectionWasOnline = true;

@ -5,6 +5,7 @@ import { Template } from 'meteor/templating';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { BlazeLayout } from 'meteor/kadira:blaze-layout';
import { Session } from 'meteor/session';
import mem from 'mem';
import { RoomManager, fireGlobalEvent, readMessage, RoomHistoryManager } from '..';
@ -17,20 +18,15 @@ import { roomTypes, handleError } from '../../../utils';
window.currentTracker = undefined;
let loadingDom;
function getDomOfLoading() {
if (loadingDom) {
return loadingDom;
}
loadingDom = document.createElement('div');
const getDomOfLoading = mem(function getDomOfLoading() {
const loadingDom = document.createElement('div');
const contentAsFunc = (content) => () => content;
const template = Blaze._TemplateWith({ }, contentAsFunc(Template.loading));
Blaze.render(template, loadingDom);
return loadingDom;
}
});
function replaceCenterDomBy(dom) {
const mainNode = document.querySelector('.main-content');
@ -101,8 +97,7 @@ export const openRoom = function(type, name) {
fireGlobalEvent('room-opened', _.omit(room, 'usernames'));
Session.set('editRoomTitle', false);
RoomManager.updateMentionsMarksOfRoom(type + name);
Meteor.setTimeout(() => readMessage.readNow(), 2000);
setTimeout(() => readMessage.readNow(), 2000);
// KonchatNotification.removeRoomNotification(params._id)
// update user's room subscription
const sub = ChatSubscription.findOne({ rid: room._id });

Loading…
Cancel
Save