fix: sidebar last message E2EE (#32431)

pull/32507/head^2
Hugo Costa 2 years ago committed by GitHub
parent d3ab41681e
commit eaf2f11a6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      .changeset/lastmessage-e2ee.md
  2. 2
      apps/meteor/app/lib/server/functions/cleanRoomHistory.ts
  3. 2
      apps/meteor/app/lib/server/functions/deleteMessage.ts
  4. 9
      apps/meteor/server/models/raw/Messages.ts
  5. 45
      apps/meteor/tests/e2e/e2e-encryption.spec.ts
  6. 6
      apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts
  7. 2
      packages/model-typings/src/models/IMessagesModel.ts

@ -0,0 +1,6 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/model-typings": patch
---
Fixed last message preview in Sidebar for E2E Ecrypted channels

@ -111,7 +111,7 @@ export async function cleanRoomHistory({
}
if (count) {
const lastMessage = await Messages.getLastVisibleMessageSentWithNoTypeByRoomId(rid);
const lastMessage = await Messages.getLastVisibleUserMessageSentByRoomId(rid);
await Rooms.resetLastMessageById(rid, lastMessage, -count);

@ -81,7 +81,7 @@ export async function deleteMessage(message: IMessage, user: IUser): Promise<voi
// update last message
if (settings.get('Store_Last_Message') && (!room?.lastMessage || room.lastMessage._id === message._id)) {
const lastMessageNotDeleted = await Messages.getLastVisibleMessageSentWithNoTypeByRoomId(message.rid);
const lastMessageNotDeleted = await Messages.getLastVisibleUserMessageSentByRoomId(message.rid);
await Rooms.resetLastMessageById(message.rid, lastMessageNotDeleted, -1);
} else {
// decrease message count

@ -1040,12 +1040,11 @@ export class MessagesRaw extends BaseRaw<IMessage> implements IMessagesModel {
return this.findOne(query, options);
}
getLastVisibleMessageSentWithNoTypeByRoomId(rid: string, messageId?: string): Promise<IMessage | null> {
const query = {
getLastVisibleUserMessageSentByRoomId(rid: string, messageId?: string): Promise<IMessage | null> {
const query: Filter<IMessage> = {
rid,
_hidden: { $ne: true },
t: { $exists: false },
$or: [{ tmid: { $exists: false } }, { tshow: true }],
$or: [{ t: 'e2e' }, { t: { $exists: false }, tmid: { $exists: false } }, { t: { $exists: false }, tshow: true }],
...(messageId && { _id: { $ne: messageId } }),
};
@ -1055,7 +1054,7 @@ export class MessagesRaw extends BaseRaw<IMessage> implements IMessagesModel {
},
};
return this.findOne(query, options);
return this.findOne<IMessage>(query, options);
}
async cloneAndSaveAsHistoryByRecord(record: IMessage, user: IMessage['u']): Promise<InsertOneResult<IMessage>> {

@ -265,6 +265,51 @@ test.describe.serial('e2e-encryption', () => {
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
});
test('expect create a private channel, send unecrypted messages, encrypt the channel and delete the last message and check the last message in the sidebar', async ({
page,
}) => {
const channelName = faker.string.uuid();
// Enable Sidebar Extended display mode
await poHomeChannel.sidenav.setDisplayMode('Extended');
// Create private channel
await poHomeChannel.sidenav.openNewByLabel('Channel');
await poHomeChannel.sidenav.inputChannelName.fill(channelName);
await poHomeChannel.sidenav.btnCreate.click();
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.toastSuccess).toBeVisible();
await poHomeChannel.dismissToast();
// Send Unencrypted Messages
await poHomeChannel.content.sendMessage('first unencrypted message');
await poHomeChannel.content.sendMessage('second unencrypted message');
// Encrypt channel
await poHomeChannel.tabs.kebab.click({ force: true });
await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible();
await poHomeChannel.tabs.btnEnableE2E.click({ force: true });
await page.waitForTimeout(1000);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
// Send Encrypted Messages
const encriptedMessage1 = 'first ENCRYPTED message';
const encriptedMessage2 = 'second ENCRYPTED message';
await poHomeChannel.content.sendMessage(encriptedMessage1);
await poHomeChannel.content.sendMessage(encriptedMessage2);
// Delete last message
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(encriptedMessage2);
await poHomeChannel.content.openLastMessageMenu();
await page.locator('role=menuitem[name="Delete"]').click();
await page.locator('#modal-root .rcx-button-group--align-end .rcx-button--danger').click();
// Check last message in the sidebar
const sidebarChannel = await poHomeChannel.sidenav.getSidebarItemByName(channelName);
await expect(sidebarChannel).toBeVisible();
await expect(sidebarChannel.locator('span')).toContainText(encriptedMessage1);
});
test.describe('reset keys', () => {
let anotherClientPage: Page;

@ -49,6 +49,12 @@ export class HomeSidenav {
return this.page.getByRole('toolbar', { name: 'Sidebar actions' });
}
async setDisplayMode(mode: 'Extended' | 'Medium' | 'Condensed'): Promise<void> {
await this.sidebarToolbar.getByRole('button', { name: 'Display' }).click();
await this.sidebarToolbar.getByRole('menuitemcheckbox', { name: mode }).click();
await this.sidebarToolbar.click();
}
// Note: this is different from openChat because queued chats are not searchable
getQueuedChat(name: string): Locator {
return this.page.locator('[data-qa="sidebar-item-title"]', { hasText: name }).first();

@ -205,7 +205,7 @@ export interface IMessagesModel extends IBaseModel<IMessage> {
updateAllUsernamesByUserId(userId: string, username: string): Promise<UpdateResult | Document>;
setUrlsById(_id: string, urls: NonNullable<IMessage['urls']>): Promise<UpdateResult>;
getLastVisibleMessageSentWithNoTypeByRoomId(rid: string, messageId?: string): Promise<IMessage | null>;
getLastVisibleUserMessageSentByRoomId(rid: string, messageId?: string): Promise<IMessage | null>;
findOneBySlackTs(slackTs: Date): Promise<IMessage | null>;

Loading…
Cancel
Save