Skip to content
Snippets Groups Projects
Unverified Commit 7aefcffe authored by Rodrigo Nascimento's avatar Rodrigo Nascimento Committed by GitHub
Browse files

regression(E2EEncryption): Encrypted quotes of files not working (#32699)

parent 7ee9ca11
No related branches found
No related tags found
No related merge requests found
import { Base64 } from '@rocket.chat/base64';
import { isFileImageAttachment, isFileAttachment, isFileAudioAttachment, isFileVideoAttachment } from '@rocket.chat/core-typings';
import type { IMessage } from '@rocket.chat/core-typings';
import type { IMessage, MessageAttachment } from '@rocket.chat/core-typings';
import {
isFileImageAttachment,
isFileAttachment,
isFileAudioAttachment,
isFileVideoAttachment,
isQuoteAttachment,
} from '@rocket.chat/core-typings';
import type { Options } from '@rocket.chat/message-parser';
import { useSetting } from '@rocket.chat/ui-contexts';
import { useMemo } from 'react';
......@@ -12,6 +18,48 @@ import { useAutoTranslate } from '../../../views/room/MessageList/hooks/useAutoT
import { useKatex } from '../../../views/room/MessageList/hooks/useKatex';
import { useSubscriptionFromMessageQuery } from './useSubscriptionFromMessageQuery';
const normalizeAttachments = (attachments: MessageAttachment[], name?: string, type?: string): MessageAttachment[] => {
if (name) {
name = String.fromCharCode(...new TextEncoder().encode(name));
}
return attachments.map((attachment) => {
if (isQuoteAttachment(attachment) && attachment.attachments) {
attachment.attachments = normalizeAttachments(attachment.attachments);
return attachment;
}
if (!attachment.encryption) {
return attachment;
}
const key = Base64.encode(
JSON.stringify({
...attachment.encryption,
name,
type,
}),
);
if (isFileAttachment(attachment)) {
if (attachment.title_link && !attachment.title_link.startsWith('/file-decrypt/')) {
attachment.title_link = `/file-decrypt${attachment.title_link}?key=${key}`;
}
if (isFileImageAttachment(attachment) && !attachment.image_url.startsWith('/file-decrypt/')) {
attachment.image_url = `/file-decrypt${attachment.image_url}?key=${key}`;
}
if (isFileAudioAttachment(attachment) && !attachment.audio_url.startsWith('/file-decrypt/')) {
attachment.audio_url = `/file-decrypt${attachment.audio_url}?key=${key}`;
}
if (isFileVideoAttachment(attachment) && !attachment.video_url.startsWith('/file-decrypt/')) {
attachment.video_url = `/file-decrypt${attachment.video_url}?key=${key}`;
}
}
return attachment;
});
};
export const useNormalizedMessage = <TMessage extends IMessage>(message: TMessage): MessageWithMdEnforced => {
const { katexEnabled, katexDollarSyntaxEnabled, katexParenthesisSyntaxEnabled } = useKatex();
const customDomains = useAutoLinkDomains();
......@@ -34,35 +82,13 @@ export const useNormalizedMessage = <TMessage extends IMessage>(message: TMessag
const normalizedMessage = parseMessageTextToAstMarkdown(message, parseOptions, autoTranslateOptions);
normalizedMessage.attachments = normalizedMessage.attachments?.map((attachment) => {
if (!attachment.encryption) {
return attachment;
}
const key = Base64.encode(
JSON.stringify({
...attachment.encryption,
name: String.fromCharCode(...new TextEncoder().encode(normalizedMessage.file?.name)),
type: normalizedMessage.file?.type,
}),
if (normalizedMessage.attachments) {
normalizedMessage.attachments = normalizeAttachments(
normalizedMessage.attachments,
normalizedMessage.file?.name,
normalizedMessage.file?.type,
);
if (isFileAttachment(attachment)) {
if (attachment.title_link && !attachment.title_link.startsWith('/file-decrypt/')) {
attachment.title_link = `/file-decrypt${attachment.title_link}?key=${key}`;
}
if (isFileImageAttachment(attachment) && !attachment.image_url.startsWith('/file-decrypt/')) {
attachment.image_url = `/file-decrypt${attachment.image_url}?key=${key}`;
}
if (isFileAudioAttachment(attachment) && !attachment.audio_url.startsWith('/file-decrypt/')) {
attachment.audio_url = `/file-decrypt${attachment.audio_url}?key=${key}`;
}
if (isFileVideoAttachment(attachment) && !attachment.video_url.startsWith('/file-decrypt/')) {
attachment.video_url = `/file-decrypt${attachment.video_url}?key=${key}`;
}
}
return attachment;
});
}
return normalizedMessage;
}, [showColors, customDomains, katexEnabled, katexDollarSyntaxEnabled, katexParenthesisSyntaxEnabled, message, autoTranslateOptions]);
......
import type { IMessage, ITranslatedMessage, MessageAttachment, MessageQuoteAttachment } from '@rocket.chat/core-typings';
import type { IMessage, ITranslatedMessage, MessageAttachment } from '@rocket.chat/core-typings';
import {
isFileAttachment,
isE2EEMessage,
......@@ -56,21 +56,35 @@ export const parseMessageTextToAstMarkdown = <
};
};
export const parseMessageQuoteAttachment = <T extends MessageQuoteAttachment>(
quote: T,
export const parseMessageAttachment = <T extends MessageAttachment>(
attachment: T,
parseOptions: Options,
autoTranslateOptions: { autoTranslateLanguage?: string; translated: boolean },
): T => {
const { translated, autoTranslateLanguage } = autoTranslateOptions;
if (quote.attachments && quote.attachments?.length > 0) {
quote.attachments = quote.attachments.map((attachment) => parseMessageQuoteAttachment(attachment, parseOptions, autoTranslateOptions));
if (!attachment.text && !attachment.description) {
return attachment;
}
const text = (isTranslatedAttachment(quote) && autoTranslateLanguage && quote?.translations?.[autoTranslateLanguage]) || quote.text || '';
if (isQuoteAttachment(attachment) && attachment.attachments) {
attachment.attachments = parseMessageAttachments(attachment.attachments, parseOptions, autoTranslateOptions);
}
const text =
(isTranslatedAttachment(attachment) && autoTranslateLanguage && attachment?.translations?.[autoTranslateLanguage]) ||
attachment.text ||
attachment.description ||
'';
if (isFileAttachment(attachment) && attachment.description) {
attachment.descriptionMd = translated
? textToMessageToken(text, parseOptions)
: attachment.descriptionMd ?? textToMessageToken(text, parseOptions);
}
return {
...quote,
md: translated ? textToMessageToken(text, parseOptions) : quote.md ?? textToMessageToken(text, parseOptions),
...attachment,
md: translated ? textToMessageToken(text, parseOptions) : attachment.md ?? textToMessageToken(text, parseOptions),
};
};
......@@ -78,36 +92,7 @@ export const parseMessageAttachments = <T extends MessageAttachment>(
attachments: T[],
parseOptions: Options,
autoTranslateOptions: { autoTranslateLanguage?: string; translated: boolean },
): T[] =>
attachments.map((attachment) => {
const { translated, autoTranslateLanguage } = autoTranslateOptions;
if (!attachment.text && !attachment.description) {
return attachment;
}
if (isQuoteAttachment(attachment) && attachment.attachments) {
attachment.attachments = attachment.attachments.map((quoteAttachment) =>
parseMessageQuoteAttachment(quoteAttachment, parseOptions, autoTranslateOptions),
);
}
const text =
(isTranslatedAttachment(attachment) && autoTranslateLanguage && attachment?.translations?.[autoTranslateLanguage]) ||
attachment.text ||
attachment.description ||
'';
if (isFileAttachment(attachment) && attachment.description) {
attachment.descriptionMd = translated
? textToMessageToken(text, parseOptions)
: attachment.descriptionMd ?? textToMessageToken(text, parseOptions);
}
return {
...attachment,
md: translated ? textToMessageToken(text, parseOptions) : attachment.md ?? textToMessageToken(text, parseOptions),
};
});
): T[] => attachments.map((attachment) => parseMessageAttachment(attachment, parseOptions, autoTranslateOptions));
const isNotNullOrUndefined = (value: unknown): boolean => value !== null && value !== undefined;
......
......@@ -3,7 +3,7 @@ import type { MessageQuoteAttachment } from '@rocket.chat/core-typings';
import type { Options, Root } from '@rocket.chat/message-parser';
import { expect } from 'chai';
import { parseMessageQuoteAttachment } from '../../../../../../../client/lib/parseMessageTextToAstMarkdown';
import { parseMessageAttachment } from '../../../../../../../client/lib/parseMessageTextToAstMarkdown';
const parseOptions: Options = {
colors: true,
......@@ -70,22 +70,20 @@ const quoteMessage = {
author_name: 'authorName',
author_link: 'link',
author_icon: 'icon',
message_link: 'http://localhost/any_link',
text: 'message **bold** _italic_ and ~strike~',
md: messageParserTokenMessage,
};
describe('parseMessageQuoteAttachment', () => {
describe('parseMessageAttachment', () => {
it('should return md property populated if the quote is parsed', () => {
expect(parseMessageQuoteAttachment(quoteMessage, parseOptions, autoTranslateOptions).md).to.deep.equal(messageParserTokenMessage);
expect(parseMessageAttachment(quoteMessage, parseOptions, autoTranslateOptions).md).to.deep.equal(messageParserTokenMessage);
});
it('should return md property populated if the quote is not parsed', () => {
expect(
parseMessageQuoteAttachment(
{ ...quoteMessage, md: undefined } as unknown as MessageQuoteAttachment,
parseOptions,
autoTranslateOptions,
).md,
parseMessageAttachment({ ...quoteMessage, md: undefined } as unknown as MessageQuoteAttachment, parseOptions, autoTranslateOptions)
.md,
).to.deep.equal(messageParserTokenMessage);
});
......@@ -115,15 +113,12 @@ describe('parseMessageQuoteAttachment', () => {
autoTranslateLanguage: 'en',
};
it('should return correct quote translated parsed md when translate is active', () => {
expect(parseMessageQuoteAttachment(translatedQuote, parseOptions, enabledAutoTranslatedOptions).md).to.deep.equal(
translatedMessageParsed,
);
expect(parseMessageAttachment(translatedQuote, parseOptions, enabledAutoTranslatedOptions).md).to.deep.equal(translatedMessageParsed);
});
it('should return text parsed md when translate is active and autoTranslateLanguage is undefined', () => {
expect(
parseMessageQuoteAttachment(translatedQuote, parseOptions, { ...enabledAutoTranslatedOptions, autoTranslateLanguage: undefined })
.md,
parseMessageAttachment(translatedQuote, parseOptions, { ...enabledAutoTranslatedOptions, autoTranslateLanguage: undefined }).md,
).to.deep.equal([
{
type: 'PARAGRAPH',
......@@ -190,7 +185,7 @@ describe('parseMessageQuoteAttachment', () => {
],
};
expect(parseMessageQuoteAttachment(multipleQuotes, parseOptions, enabledAutoTranslatedOptions)).to.deep.equal(multipleQuotesParsed);
expect(parseMessageAttachment(multipleQuotes, parseOptions, enabledAutoTranslatedOptions)).to.deep.equal(multipleQuotesParsed);
});
});
});
......@@ -10,7 +10,7 @@ export type MessageQuoteAttachment = {
message_link?: string;
text: string;
md?: Root;
attachments?: Array<MessageQuoteAttachment>; // TODO this is cauising issues to define a model, see @ts-expect-error at apps/meteor/app/api/server/v1/channels.ts:274
attachments?: Array<MessageAttachment>; // TODO this is causing issues to define a model, see @ts-expect-error at apps/meteor/app/api/server/v1/channels.ts:274
} & MessageAttachmentBase;
export const isQuoteAttachment = (attachment: MessageAttachment): attachment is MessageQuoteAttachment =>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment