From faad410e1c339c7785f178ffe7e591fe93b80bca Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 4 Jun 2024 01:25:09 +0530 Subject: [PATCH 01/10] disable slash commands in e2ee rooms --- .../client/views/room/composer/ComposerBoxPopup.tsx | 12 +++++++++++- .../room/composer/ComposerBoxPopupSlashCommand.tsx | 8 ++++++-- .../views/room/contexts/ComposerPopupContext.ts | 1 + .../views/room/providers/ComposerPopupProvider.tsx | 6 ++++-- packages/i18n/src/locales/en.i18n.json | 1 + 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx b/apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx index dd7b19797530..3e36f454f9f4 100644 --- a/apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx +++ b/apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx @@ -9,6 +9,7 @@ export type ComposerBoxPopupProps< T extends { _id: string; sort?: number; + disabled?: boolean; }, > = { title?: string; @@ -22,6 +23,7 @@ function ComposerBoxPopup< T extends { _id: string; sort?: number; + disabled?: boolean; }, >({ title, @@ -37,7 +39,10 @@ function ComposerBoxPopup< const variant = popupSizes && popupSizes.inlineSize < 480 ? 'small' : 'large'; - const getOptionTitle = (item: T) => { + const getOptionTitle = ( + item: T, + ) => { + console.log({ item }); if (variant !== 'small') { return undefined; } @@ -49,6 +54,10 @@ function ComposerBoxPopup< if (item.suggestion) { return t('Suggestion_from_recent_messages'); } + + if (item.disabled) { + return t('Unavailable_in_encrypted_channels'); + } }; const itemsFlat = useMemo( @@ -96,6 +105,7 @@ function ComposerBoxPopup< id={`popup-item-${item._id}`} tabIndex={item === focused ? 0 : -1} aria-selected={item === focused} + disabled={item.disabled} > {renderItem({ item: { ...item, variant } })} diff --git a/apps/meteor/client/views/room/composer/ComposerBoxPopupSlashCommand.tsx b/apps/meteor/client/views/room/composer/ComposerBoxPopupSlashCommand.tsx index 24dd07d067b3..fe69136c3d26 100644 --- a/apps/meteor/client/views/room/composer/ComposerBoxPopupSlashCommand.tsx +++ b/apps/meteor/client/views/room/composer/ComposerBoxPopupSlashCommand.tsx @@ -1,20 +1,24 @@ import { OptionColumn, OptionContent, OptionDescription, OptionInput } from '@rocket.chat/fuselage'; +import { useTranslation } from '@rocket.chat/ui-contexts'; import React from 'react'; export type ComposerBoxPopupSlashCommandProps = { _id: string; description?: string; params?: string; + disabled?: boolean; }; -function ComposerBoxPopupSlashCommand({ _id, description, params }: ComposerBoxPopupSlashCommandProps) { +function ComposerBoxPopupSlashCommand({ _id, description, params, disabled }: ComposerBoxPopupSlashCommandProps) { + const t = useTranslation(); + return ( <> {_id} {params} - {description} + {disabled ? t('Unavailable_in_encrypted_channels') : description} ); diff --git a/apps/meteor/client/views/room/contexts/ComposerPopupContext.ts b/apps/meteor/client/views/room/contexts/ComposerPopupContext.ts index 21d239ee6bd7..e42bbe5e38fe 100644 --- a/apps/meteor/client/views/room/contexts/ComposerPopupContext.ts +++ b/apps/meteor/client/views/room/contexts/ComposerPopupContext.ts @@ -21,6 +21,7 @@ export type ComposerPopupOption string; renderItem?: ({ item }: { item: T }) => ReactElement; + disabled?: boolean; }; export type ComposerPopupContextValue = ComposerPopupOption[]; diff --git a/apps/meteor/client/views/room/providers/ComposerPopupProvider.tsx b/apps/meteor/client/views/room/providers/ComposerPopupProvider.tsx index cb8e74fbe142..3b0c68f2f991 100644 --- a/apps/meteor/client/views/room/providers/ComposerPopupProvider.tsx +++ b/apps/meteor/client/views/room/providers/ComposerPopupProvider.tsx @@ -25,7 +25,7 @@ import type { ComposerPopupContextValue } from '../contexts/ComposerPopupContext import { ComposerPopupContext, createMessageBoxPopupConfig } from '../contexts/ComposerPopupContext'; const ComposerPopupProvider = ({ children, room }: { children: ReactNode; room: IRoom }) => { - const { _id: rid } = room; + const { _id: rid, encrypted } = room; const userSpotlight = useMethod('spotlight'); const suggestionsCount = useSetting('Number_of_users_autocomplete_suggestions'); const cannedResponseEnabled = useSetting('Canned_Responses_Enable'); @@ -278,6 +278,7 @@ const ComposerPopupProvider = ({ children, room }: { children: ReactNode; room: trigger: '/', suffix: ' ', triggerAnywhere: false, + disabled: Boolean(encrypted), renderItem: ({ item }) => , getItemsFromLocal: async (filter: string) => { return Object.keys(slashCommands.commands) @@ -288,6 +289,7 @@ const ComposerPopupProvider = ({ children, room }: { children: ReactNode; room: params: item.params && t.has(item.params) ? t(item.params) : item.params ?? '', description: item.description && t.has(item.description) ? t(item.description) : item.description, permission: item.permission, + ...(encrypted && { disabled: Boolean(encrypted) }), }; }) .filter((command) => { @@ -360,7 +362,7 @@ const ComposerPopupProvider = ({ children, room }: { children: ReactNode; room: }, }), ].filter(Boolean); - }, [t, cannedResponseEnabled, isOmnichannel, recentEmojis, suggestionsCount, userSpotlight, rid, call, useEmoji]); + }, [t, cannedResponseEnabled, isOmnichannel, recentEmojis, suggestionsCount, userSpotlight, rid, call, useEmoji, encrypted]); return ; }; diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 8e5c80ab1043..7c4663285644 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -5464,6 +5464,7 @@ "Unassigned": "Unassigned", "unauthorized": "Not authorized", "Unavailable": "Unavailable", + "Unavailable_in_encrypted_channels": "Unavailable in encrypted channels", "Unblock": "Unblock", "Unblock_User": "Unblock User", "Uncheck_All": "Uncheck All", From 7e4240fa895ee94925ca891eddd07f6be5326307 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 4 Jun 2024 01:26:19 +0530 Subject: [PATCH 02/10] add cs --- .changeset/popular-bulldogs-accept.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/popular-bulldogs-accept.md diff --git a/.changeset/popular-bulldogs-accept.md b/.changeset/popular-bulldogs-accept.md new file mode 100644 index 000000000000..b18e3382148b --- /dev/null +++ b/.changeset/popular-bulldogs-accept.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/i18n': patch +'@rocket.chat/meteor': patch +--- + +Disable slash commands in encrypted rooms and show a disabled warning. From 7f1f70acbcb2fa11085fe6f4415cd7a3ccc989fd Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 4 Jun 2024 01:39:51 +0530 Subject: [PATCH 03/10] remove logs --- apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx b/apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx index 3e36f454f9f4..523c0e44af86 100644 --- a/apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx +++ b/apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx @@ -42,7 +42,6 @@ function ComposerBoxPopup< const getOptionTitle = ( item: T, ) => { - console.log({ item }); if (variant !== 'small') { return undefined; } From 2fc1e29dea5d25cd1d3f2c86462001c6a5efd988 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Fri, 7 Jun 2024 20:00:34 +0530 Subject: [PATCH 04/10] check for e2ee enable settings --- .../views/room/providers/ComposerPopupProvider.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/meteor/client/views/room/providers/ComposerPopupProvider.tsx b/apps/meteor/client/views/room/providers/ComposerPopupProvider.tsx index 3b0c68f2f991..245a2a0112f3 100644 --- a/apps/meteor/client/views/room/providers/ComposerPopupProvider.tsx +++ b/apps/meteor/client/views/room/providers/ComposerPopupProvider.tsx @@ -25,7 +25,7 @@ import type { ComposerPopupContextValue } from '../contexts/ComposerPopupContext import { ComposerPopupContext, createMessageBoxPopupConfig } from '../contexts/ComposerPopupContext'; const ComposerPopupProvider = ({ children, room }: { children: ReactNode; room: IRoom }) => { - const { _id: rid, encrypted } = room; + const { _id: rid, encrypted: isRoomEncrypted } = room; const userSpotlight = useMethod('spotlight'); const suggestionsCount = useSetting('Number_of_users_autocomplete_suggestions'); const cannedResponseEnabled = useSetting('Canned_Responses_Enable'); @@ -33,6 +33,9 @@ const ComposerPopupProvider = ({ children, room }: { children: ReactNode; room: const isOmnichannel = isOmnichannelRoom(room); const useEmoji = useUserPreference('useEmojis'); const t = useTranslation(); + const e2eEnabled = useSetting('E2E_Enable'); + const unencryptedMessagesAllowed = useSetting('E2E_Allow_Unencrypted_Messages'); + const encrypted = isRoomEncrypted && e2eEnabled && !unencryptedMessagesAllowed; const call = useMethod('getSlashCommandPreviews'); const value: ComposerPopupContextValue = useMemo(() => { @@ -278,7 +281,7 @@ const ComposerPopupProvider = ({ children, room }: { children: ReactNode; room: trigger: '/', suffix: ' ', triggerAnywhere: false, - disabled: Boolean(encrypted), + disabled: encrypted, renderItem: ({ item }) => , getItemsFromLocal: async (filter: string) => { return Object.keys(slashCommands.commands) @@ -289,7 +292,7 @@ const ComposerPopupProvider = ({ children, room }: { children: ReactNode; room: params: item.params && t.has(item.params) ? t(item.params) : item.params ?? '', description: item.description && t.has(item.description) ? t(item.description) : item.description, permission: item.permission, - ...(encrypted && { disabled: Boolean(encrypted) }), + ...(encrypted && { disabled: encrypted }), }; }) .filter((command) => { From b5cec389d212883e24b717ab1132d5781997bf03 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 11 Jun 2024 12:09:27 +0530 Subject: [PATCH 05/10] stop executing slash commands --- apps/meteor/client/lib/chats/ChatAPI.ts | 10 +++++++++- apps/meteor/client/lib/chats/flows/sendMessage.ts | 13 +++++++++---- .../client/views/room/composer/ComposerMessage.tsx | 6 +++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/apps/meteor/client/lib/chats/ChatAPI.ts b/apps/meteor/client/lib/chats/ChatAPI.ts index ceffab987a64..10589b8b7c97 100644 --- a/apps/meteor/client/lib/chats/ChatAPI.ts +++ b/apps/meteor/client/lib/chats/ChatAPI.ts @@ -140,7 +140,15 @@ export type ChatAPI = { readonly flows: { readonly uploadFiles: (files: readonly File[], resetFileInput?: () => void) => Promise; - readonly sendMessage: ({ text, tshow }: { text: string; tshow?: boolean; previewUrls?: string[] }) => Promise; + readonly sendMessage: ({ + text, + tshow, + }: { + text: string; + tshow?: boolean; + previewUrls?: string[]; + isSlashCommandAllowed?: boolean; + }) => Promise; readonly processSlashCommand: (message: IMessage, userId: string | null) => Promise; readonly processTooLongMessage: (message: IMessage) => Promise; readonly processMessageEditing: ( diff --git a/apps/meteor/client/lib/chats/flows/sendMessage.ts b/apps/meteor/client/lib/chats/flows/sendMessage.ts index 62adbd80eb3e..c691c40b3faf 100644 --- a/apps/meteor/client/lib/chats/flows/sendMessage.ts +++ b/apps/meteor/client/lib/chats/flows/sendMessage.ts @@ -10,7 +10,7 @@ import { processSetReaction } from './processSetReaction'; import { processSlashCommand } from './processSlashCommand'; import { processTooLongMessage } from './processTooLongMessage'; -const process = async (chat: ChatAPI, message: IMessage, previewUrls?: string[]): Promise => { +const process = async (chat: ChatAPI, message: IMessage, previewUrls?: string[], isSlashCommandAllowed?: boolean): Promise => { KonchatNotification.removeRoomNotification(message.rid); if (await processSetReaction(chat, message)) { @@ -25,7 +25,7 @@ const process = async (chat: ChatAPI, message: IMessage, previewUrls?: string[]) return; } - if (await processSlashCommand(chat, message)) { + if (isSlashCommandAllowed && (await processSlashCommand(chat, message))) { return; } @@ -34,7 +34,12 @@ const process = async (chat: ChatAPI, message: IMessage, previewUrls?: string[]) export const sendMessage = async ( chat: ChatAPI, - { text, tshow, previewUrls }: { text: string; tshow?: boolean; previewUrls?: string[] }, + { + text, + tshow, + previewUrls, + isSlashCommandAllowed, + }: { text: string; tshow?: boolean; previewUrls?: string[]; isSlashCommandAllowed?: boolean }, ): Promise => { if (!(await chat.data.isSubscribedToRoom())) { try { @@ -63,7 +68,7 @@ export const sendMessage = async ( }); try { - await process(chat, message, previewUrls); + await process(chat, message, previewUrls, isSlashCommandAllowed); chat.composer?.dismissAllQuotedMessages(); } catch (error) { dispatchToastMessage({ type: 'error', message: error }); diff --git a/apps/meteor/client/views/room/composer/ComposerMessage.tsx b/apps/meteor/client/views/room/composer/ComposerMessage.tsx index 28824acab05a..8aed7d1d244e 100644 --- a/apps/meteor/client/views/room/composer/ComposerMessage.tsx +++ b/apps/meteor/client/views/room/composer/ComposerMessage.tsx @@ -1,5 +1,5 @@ import type { IMessage, ISubscription } from '@rocket.chat/core-typings'; -import { useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useSetting, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; import type { ReactElement, ReactNode } from 'react'; import React, { memo, useCallback, useMemo } from 'react'; @@ -29,6 +29,9 @@ const ComposerMessage = ({ tmid, readOnly, onSend, ...props }: ComposerMessagePr const chat = useChat(); const room = useRoom(); const dispatchToastMessage = useToastMessageDispatch(); + const e2eEnabled = useSetting('E2E_Enable'); + const unencryptedMessagesAllowed = useSetting('E2E_Allow_Unencrypted_Messages'); + const isSlashCommandAllowed = room.encrypted && e2eEnabled && unencryptedMessagesAllowed; const composerProps = useMemo( () => ({ @@ -48,6 +51,7 @@ const ComposerMessage = ({ tmid, readOnly, onSend, ...props }: ComposerMessagePr text, tshow, previewUrls, + isSlashCommandAllowed, }); if (newMessageSent) onSend?.(); } catch (error) { From 9844a7c08e86f2593354e342945d7be77384931f Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 11 Jun 2024 12:11:06 +0530 Subject: [PATCH 06/10] add e2e tests --- apps/meteor/tests/e2e/e2e-encryption.spec.ts | 38 ++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/apps/meteor/tests/e2e/e2e-encryption.spec.ts b/apps/meteor/tests/e2e/e2e-encryption.spec.ts index 55de92ef8bad..00f3a601a79a 100644 --- a/apps/meteor/tests/e2e/e2e-encryption.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption.spec.ts @@ -239,6 +239,44 @@ test.describe.serial('e2e-encryption', () => { await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); }); + test.describe('un-encrypted messages not allowed in e2ee rooms', () => { + let poHomeChannel: HomeChannel; + + test.beforeEach(async ({ page }) => { + poHomeChannel = new HomeChannel(page); + await page.goto('/home'); + }); + test.beforeAll(async ({ api }) => { + expect((await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: false })).status()).toBe(200); + }); + + test.afterAll(async ({ api }) => { + expect((await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: false })).status()).toBe(200); + }); + + test('expect slash commands to be disabled in an e2ee room', async ({ page }) => { + await restoreState(page, Users.admin); + const channelName = faker.string.uuid(); + + await poHomeChannel.sidenav.createEncryptedChannel(channelName); + + await expect(page).toHaveURL(`/group/${channelName}`); + + await poHomeChannel.dismissToast(); + + await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible(); + + await poHomeChannel.content.sendMessage('This is an encrypted message.'); + + await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is an encrypted message.'); + await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + + await page.locator('[name="msg"]').type('/'); + await expect(page.locator('#popup-item-contextualbar')).toHaveClass(/disabled/) + + }); + }); + test.describe('reset keys', () => { let anotherClientPage: Page; From 0f0672114ba6c5dedb1c101c28615cdeb755c856 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Tue, 11 Jun 2024 20:25:01 +0530 Subject: [PATCH 07/10] lint --- apps/meteor/tests/e2e/e2e-encryption.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/meteor/tests/e2e/e2e-encryption.spec.ts b/apps/meteor/tests/e2e/e2e-encryption.spec.ts index 00f3a601a79a..7ddc9908f8f6 100644 --- a/apps/meteor/tests/e2e/e2e-encryption.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption.spec.ts @@ -272,8 +272,7 @@ test.describe.serial('e2e-encryption', () => { await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); await page.locator('[name="msg"]').type('/'); - await expect(page.locator('#popup-item-contextualbar')).toHaveClass(/disabled/) - + await expect(page.locator('#popup-item-contextualbar')).toHaveClass(/disabled/); }); }); From de3c8d64f757b67e0264d88746b7d17650eaf16e Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Wed, 12 Jun 2024 15:08:47 +0530 Subject: [PATCH 08/10] slash commands allowed condition --- .../client/views/room/composer/ComposerMessage.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/meteor/client/views/room/composer/ComposerMessage.tsx b/apps/meteor/client/views/room/composer/ComposerMessage.tsx index 8aed7d1d244e..e51e6d83bc07 100644 --- a/apps/meteor/client/views/room/composer/ComposerMessage.tsx +++ b/apps/meteor/client/views/room/composer/ComposerMessage.tsx @@ -31,7 +31,7 @@ const ComposerMessage = ({ tmid, readOnly, onSend, ...props }: ComposerMessagePr const dispatchToastMessage = useToastMessageDispatch(); const e2eEnabled = useSetting('E2E_Enable'); const unencryptedMessagesAllowed = useSetting('E2E_Allow_Unencrypted_Messages'); - const isSlashCommandAllowed = room.encrypted && e2eEnabled && unencryptedMessagesAllowed; + const isSlashCommandAllowed = !e2eEnabled || !room.encrypted || unencryptedMessagesAllowed; const composerProps = useMemo( () => ({ @@ -71,7 +71,16 @@ const ComposerMessage = ({ tmid, readOnly, onSend, ...props }: ComposerMessagePr return chat?.flows.uploadFiles(files); }, }), - [chat?.data, chat?.flows, chat?.action, chat?.composer?.text, chat?.messageEditing, dispatchToastMessage, onSend], + [ + chat?.data, + chat?.flows, + chat?.action, + chat?.composer?.text, + chat?.messageEditing, + dispatchToastMessage, + onSend, + isSlashCommandAllowed, + ], ); const publicationReady = useReactiveValue( From e94590ee8e6c297f11e80657d62f2438df2e976c Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Wed, 12 Jun 2024 15:21:45 +0530 Subject: [PATCH 09/10] refactor --- .../views/room/composer/ComposerMessage.tsx | 28 +++++++++---------- .../room/composer/messageBox/MessageBox.tsx | 8 ++++-- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/apps/meteor/client/views/room/composer/ComposerMessage.tsx b/apps/meteor/client/views/room/composer/ComposerMessage.tsx index e51e6d83bc07..790b1739bde7 100644 --- a/apps/meteor/client/views/room/composer/ComposerMessage.tsx +++ b/apps/meteor/client/views/room/composer/ComposerMessage.tsx @@ -1,5 +1,5 @@ import type { IMessage, ISubscription } from '@rocket.chat/core-typings'; -import { useSetting, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; +import { useToastMessageDispatch } from '@rocket.chat/ui-contexts'; import type { ReactElement, ReactNode } from 'react'; import React, { memo, useCallback, useMemo } from 'react'; @@ -29,9 +29,6 @@ const ComposerMessage = ({ tmid, readOnly, onSend, ...props }: ComposerMessagePr const chat = useChat(); const room = useRoom(); const dispatchToastMessage = useToastMessageDispatch(); - const e2eEnabled = useSetting('E2E_Enable'); - const unencryptedMessagesAllowed = useSetting('E2E_Allow_Unencrypted_Messages'); - const isSlashCommandAllowed = !e2eEnabled || !room.encrypted || unencryptedMessagesAllowed; const composerProps = useMemo( () => ({ @@ -44,7 +41,17 @@ const ComposerMessage = ({ tmid, readOnly, onSend, ...props }: ComposerMessagePr } }, - onSend: async ({ value: text, tshow, previewUrls }: { value: string; tshow?: boolean; previewUrls?: string[] }): Promise => { + onSend: async ({ + value: text, + tshow, + previewUrls, + isSlashCommandAllowed, + }: { + value: string; + tshow?: boolean; + previewUrls?: string[]; + isSlashCommandAllowed?: boolean; + }): Promise => { try { await chat?.action.stop('typing'); const newMessageSent = await chat?.flows.sendMessage({ @@ -71,16 +78,7 @@ const ComposerMessage = ({ tmid, readOnly, onSend, ...props }: ComposerMessagePr return chat?.flows.uploadFiles(files); }, }), - [ - chat?.data, - chat?.flows, - chat?.action, - chat?.composer?.text, - chat?.messageEditing, - dispatchToastMessage, - onSend, - isSlashCommandAllowed, - ], + [chat?.data, chat?.flows, chat?.action, chat?.composer?.text, chat?.messageEditing, dispatchToastMessage, onSend], ); const publicationReady = useReactiveValue( diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx index 043837f8c8c6..4b7a466d6de0 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx @@ -12,7 +12,7 @@ import { MessageComposerHint, MessageComposerButton, } from '@rocket.chat/ui-composer'; -import { useTranslation, useUserPreference, useLayout } from '@rocket.chat/ui-contexts'; +import { useTranslation, useUserPreference, useLayout, useSetting } from '@rocket.chat/ui-contexts'; import { useMutation } from '@tanstack/react-query'; import type { ReactElement, @@ -92,7 +92,7 @@ const getEmptyArray = () => a; type MessageBoxProps = { tmid?: IMessage['_id']; readOnly: boolean; - onSend?: (params: { value: string; tshow?: boolean; previewUrls?: string[] }) => Promise; + onSend?: (params: { value: string; tshow?: boolean; previewUrls?: string[]; isSlashCommandAllowed?: boolean }) => Promise; onJoin?: () => Promise; onResize?: () => void; onTyping?: () => void; @@ -123,6 +123,9 @@ const MessageBox = ({ const chat = useChat(); const room = useRoom(); const t = useTranslation(); + const e2eEnabled = useSetting('E2E_Enable'); + const unencryptedMessagesAllowed = useSetting('E2E_Allow_Unencrypted_Messages'); + const isSlashCommandAllowed = !e2eEnabled || !room.encrypted || unencryptedMessagesAllowed; const composerPlaceholder = useMessageBoxPlaceholder(t('Message'), room); const [typing, setTyping] = useReducer(reducer, false); @@ -176,6 +179,7 @@ const MessageBox = ({ value: text, tshow, previewUrls, + isSlashCommandAllowed, }); }); From 3adba9bab321a382e1c236220325a6311addbf74 Mon Sep 17 00:00:00 2001 From: yash-rajpal Date: Wed, 12 Jun 2024 15:46:13 +0530 Subject: [PATCH 10/10] add more tests --- apps/meteor/tests/e2e/e2e-encryption.spec.ts | 30 ++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/meteor/tests/e2e/e2e-encryption.spec.ts b/apps/meteor/tests/e2e/e2e-encryption.spec.ts index 8c6a08cb07e1..2dbcb5110a3e 100644 --- a/apps/meteor/tests/e2e/e2e-encryption.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption.spec.ts @@ -239,6 +239,33 @@ test.describe.serial('e2e-encryption', () => { await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); }); + test('expect slash commands to be enabled in an e2ee room', async ({ page }) => { + const channelName = faker.string.uuid(); + + await poHomeChannel.sidenav.createEncryptedChannel(channelName); + + await expect(page).toHaveURL(`/group/${channelName}`); + + await poHomeChannel.dismissToast(); + + await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible(); + + await poHomeChannel.content.sendMessage('This is an encrypted message.'); + + await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is an encrypted message.'); + await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + + await page.locator('[name="msg"]').type('/'); + await expect(page.locator('#popup-item-contextualbar')).not.toHaveClass(/disabled/); + await page.locator('[name="msg"]').clear(); + + await poHomeChannel.content.dispatchSlashCommand('/contextualbar'); + await expect(poHomeChannel.btnContextualbarClose).toBeVisible(); + + await poHomeChannel.btnContextualbarClose.click(); + await expect(poHomeChannel.btnContextualbarClose).toBeHidden(); + }); + test.describe('un-encrypted messages not allowed in e2ee rooms', () => { let poHomeChannel: HomeChannel; @@ -251,11 +278,10 @@ test.describe.serial('e2e-encryption', () => { }); test.afterAll(async ({ api }) => { - expect((await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: false })).status()).toBe(200); + expect((await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: true })).status()).toBe(200); }); test('expect slash commands to be disabled in an e2ee room', async ({ page }) => { - await restoreState(page, Users.admin); const channelName = faker.string.uuid(); await poHomeChannel.sidenav.createEncryptedChannel(channelName);