diff --git a/.changeset/lastmessage-e2ee.md b/.changeset/lastmessage-e2ee.md new file mode 100644 index 00000000000..b3c8642dcff --- /dev/null +++ b/.changeset/lastmessage-e2ee.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/model-typings": patch +--- + +Fixed last message preview in Sidebar for E2E Ecrypted channels diff --git a/apps/meteor/app/lib/server/functions/cleanRoomHistory.ts b/apps/meteor/app/lib/server/functions/cleanRoomHistory.ts index f5306199515..2bfb1086c63 100644 --- a/apps/meteor/app/lib/server/functions/cleanRoomHistory.ts +++ b/apps/meteor/app/lib/server/functions/cleanRoomHistory.ts @@ -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); diff --git a/apps/meteor/app/lib/server/functions/deleteMessage.ts b/apps/meteor/app/lib/server/functions/deleteMessage.ts index 4582a88823e..e977874b345 100644 --- a/apps/meteor/app/lib/server/functions/deleteMessage.ts +++ b/apps/meteor/app/lib/server/functions/deleteMessage.ts @@ -81,7 +81,7 @@ export async function deleteMessage(message: IMessage, user: IUser): Promise implements IMessagesModel { return this.findOne(query, options); } - getLastVisibleMessageSentWithNoTypeByRoomId(rid: string, messageId?: string): Promise { - const query = { + getLastVisibleUserMessageSentByRoomId(rid: string, messageId?: string): Promise { + const query: Filter = { 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 implements IMessagesModel { }, }; - return this.findOne(query, options); + return this.findOne(query, options); } async cloneAndSaveAsHistoryByRecord(record: IMessage, user: IMessage['u']): Promise> { diff --git a/apps/meteor/tests/e2e/e2e-encryption.spec.ts b/apps/meteor/tests/e2e/e2e-encryption.spec.ts index bb4d2f47821..c2d1fcc24cb 100644 --- a/apps/meteor/tests/e2e/e2e-encryption.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption.spec.ts @@ -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; diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts index 3d689b27e3f..dfae6c668bb 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts @@ -49,6 +49,12 @@ export class HomeSidenav { return this.page.getByRole('toolbar', { name: 'Sidebar actions' }); } + async setDisplayMode(mode: 'Extended' | 'Medium' | 'Condensed'): Promise { + 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(); diff --git a/packages/model-typings/src/models/IMessagesModel.ts b/packages/model-typings/src/models/IMessagesModel.ts index 14308079967..0fb02a778c9 100644 --- a/packages/model-typings/src/models/IMessagesModel.ts +++ b/packages/model-typings/src/models/IMessagesModel.ts @@ -205,7 +205,7 @@ export interface IMessagesModel extends IBaseModel { updateAllUsernamesByUserId(userId: string, username: string): Promise; setUrlsById(_id: string, urls: NonNullable): Promise; - getLastVisibleMessageSentWithNoTypeByRoomId(rid: string, messageId?: string): Promise; + getLastVisibleUserMessageSentByRoomId(rid: string, messageId?: string): Promise; findOneBySlackTs(slackTs: Date): Promise;