Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Handle encrypted pinned messages #32380

Merged
merged 13 commits into from
Jun 22, 2024
6 changes: 6 additions & 0 deletions .changeset/forty-bikes-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/core-typings': patch
'@rocket.chat/meteor': patch
---

Decrypt pinned encrypted message
yash-rajpal marked this conversation as resolved.
Show resolved Hide resolved
26 changes: 25 additions & 1 deletion apps/meteor/app/e2e/client/rocketchat.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import QueryString from 'querystring';
import URL from 'url';

import type { IE2EEMessage, IMessage, IRoom, ISubscription } from '@rocket.chat/core-typings';
import type { IE2EEMessage, IMessage, IRoom, ISubscription, MessageAttachment } from '@rocket.chat/core-typings';
import { isE2EEMessage, isFileAttachment } from '@rocket.chat/core-typings';
import { Emitter } from '@rocket.chat/emitter';
import EJSON from 'ejson';
Expand Down Expand Up @@ -437,10 +437,34 @@
return decryptedMessageWithAttachments;
}

async decryptPinnedMessage(message: IMessage) {
yash-rajpal marked this conversation as resolved.
Show resolved Hide resolved
if (!message?.attachments || !message.attachments[0]?.text) {
yash-rajpal marked this conversation as resolved.
Show resolved Hide resolved
return message;
}

const e2eRoom = await this.getInstanceByRoomId(message.rid);
const pinnedMessage = message.attachments[0]?.text;
yash-rajpal marked this conversation as resolved.
Show resolved Hide resolved

if (!e2eRoom || !pinnedMessage) {
return message;
}

const data = await e2eRoom.decrypt(pinnedMessage);

if (!data) {
return message;
}

const decryptedPinnedMessage = { ...message } as IMessage & { attachments: MessageAttachment[] };
decryptedPinnedMessage.attachments[0].text = data.text;
yash-rajpal marked this conversation as resolved.
Show resolved Hide resolved

return decryptedPinnedMessage;
}

async decryptMessageAttachments(message: IMessage): Promise<IMessage> {
const { attachments } = message;

if (!attachments || !attachments.length) {

Check warning on line 467 in apps/meteor/app/e2e/client/rocketchat.e2e.ts

View workflow job for this annotation

GitHub Actions / 🔎 Code Check / Code Lint

Prefer using an optional chain expression instead, as it's more concise and easier to read
return message;
}

Expand Down
4 changes: 3 additions & 1 deletion apps/meteor/app/message-pin/server/pinMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ Meteor.methods<ServerMethods>({
// App IPostMessagePinned event hook
await Apps.self?.triggerEvent(AppEvents.IPostMessagePinned, originalMessage, await Meteor.userAsync(), originalMessage.pinned);

const msgId = await Message.saveSystemMessage('message_pinned', originalMessage.rid, '', me, {
const pinMessageType = originalMessage.t === 'e2e' ? 'message_pinned_e2e' : 'message_pinned';

const msgId = await Message.saveSystemMessage(pinMessageType, originalMessage.rid, '', me, {
attachments: [
{
text: originalMessage.msg,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const StatusIndicators = ({ message }: StatusIndicatorsProps): ReactElement => {
const starred = useShowStarred({ message });
const following = useShowFollowing({ message });

const isEncryptedMessage = isE2EEMessage(message);
const isEncryptedMessage = isE2EEMessage(message) || message.t === 'message_pinned_e2e';
yash-rajpal marked this conversation as resolved.
Show resolved Hide resolved
const isOtrMessage = isOTRMessage(message) || isOTRAckMessage(message);

const uid = useUserId();
Expand Down
5 changes: 5 additions & 0 deletions apps/meteor/client/startup/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ Meteor.startup(() => {
if (!e2eRoom?.shouldConvertReceivedMessages()) {
return msg;
}

if (msg.t === 'message_pinned_e2e') {
yash-rajpal marked this conversation as resolved.
Show resolved Hide resolved
return e2e.decryptPinnedMessage(msg);
}

return e2e.decryptMessage(msg);
});

Expand Down
6 changes: 6 additions & 0 deletions apps/meteor/client/startup/messageTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,10 @@ Meteor.startup(() => {
system: true,
message: 'Pinned_a_message',
});

MessageTypes.registerType({
id: 'message_pinned_e2e',
system: true,
message: 'Pinned_a_message',
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useQuery } from '@tanstack/react-query';
import type { ReactElement } from 'react';
import React from 'react';

import { onClientMessageReceived } from '../../../lib/onClientMessageReceived';
import { mapMessageFromApi } from '../../../lib/utils/mapMessageFromApi';
import { useRoom } from '../contexts/RoomContext';
import MessageListTab from './MessageListTab';
Expand All @@ -25,7 +26,7 @@ const PinnedMessagesTab = (): ReactElement => {
messages.push(...result.messages.map(mapMessageFromApi));
}

return messages;
return Promise.all(messages.map(onClientMessageReceived));
});

const t = useTranslation();
Expand Down
1 change: 1 addition & 0 deletions packages/core-typings/src/IMessage/IMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export type MessageTypesValues =
| 'command'
| 'videoconf'
| 'message_pinned'
| 'message_pinned_e2e'
| 'new-moderator'
| 'moderator-removed'
| 'new-owner'
Expand Down
Loading