Skip to content
Snippets Groups Projects
Unverified Commit 2ef71e8e authored by Yash Rajpal's avatar Yash Rajpal Committed by GitHub
Browse files

feat: E2EE room setup header (#32446)

parent 465c8edf
No related branches found
No related tags found
No related merge requests found
---
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---
Added E2EE room setup header, with just limited functionality and room actions.
......@@ -78,3 +78,5 @@ export const quickActionHooks = [
useCloseChatQuickAction,
useOnHoldChatQuickAction,
] satisfies (() => QuickActionsActionConfig | undefined)[];
export const roomActionHooksForE2EESetup = [useChannelSettingsRoomAction, useMembersListRoomAction, useE2EERoomAction];
import type { IRoom } from '@rocket.chat/core-typings';
import { isVoipRoom } from '@rocket.chat/core-typings';
import { isDirectMessageRoom, isVoipRoom } from '@rocket.chat/core-typings';
import { HeaderToolbar } from '@rocket.chat/ui-client';
import { useLayout } from '@rocket.chat/ui-contexts';
import { useLayout, useSetting } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import React, { lazy, memo, useMemo } from 'react';
import SidebarToggler from '../../../components/SidebarToggler';
const DirectRoomHeader = lazy(() => import('./DirectRoomHeader'));
const OmnichannelRoomHeader = lazy(() => import('./Omnichannel/OmnichannelRoomHeader'));
const VoipRoomHeader = lazy(() => import('./Omnichannel/VoipRoomHeader'));
const RoomHeaderE2EESetup = lazy(() => import('./RoomHeaderE2EESetup'));
const DirectRoomHeader = lazy(() => import('./DirectRoomHeader'));
const RoomHeader = lazy(() => import('./RoomHeader'));
type HeaderProps<T> = {
......@@ -18,6 +19,9 @@ type HeaderProps<T> = {
const Header = ({ room }: HeaderProps<IRoom>): ReactElement | null => {
const { isMobile, isEmbedded, showTopNavbarEmbeddedLayout } = useLayout();
const encrypted = Boolean(room.encrypted);
const unencryptedMessagesAllowed = useSetting<boolean>('E2E_Allow_Unencrypted_Messages');
const shouldDisplayE2EESetup = encrypted && !unencryptedMessagesAllowed;
const slots = useMemo(
() => ({
......@@ -34,10 +38,6 @@ const Header = ({ room }: HeaderProps<IRoom>): ReactElement | null => {
return null;
}
if (room.t === 'd' && (room.uids?.length ?? 0) < 3) {
return <DirectRoomHeader slots={slots} room={room} />;
}
if (room.t === 'l') {
return <OmnichannelRoomHeader slots={slots} />;
}
......@@ -46,7 +46,15 @@ const Header = ({ room }: HeaderProps<IRoom>): ReactElement | null => {
return <VoipRoomHeader slots={slots} room={room} />;
}
return <RoomHeader slots={slots} room={room} topic={room.topic} />;
if (shouldDisplayE2EESetup) {
return <RoomHeaderE2EESetup room={room} topic={room.topic} slots={slots} />;
}
if (isDirectMessageRoom(room) && (room.uids?.length ?? 0) < 3) {
return <DirectRoomHeader slots={slots} room={room} />;
}
return <RoomHeader room={room} topic={room.topic} slots={slots} />;
};
export default memo(Header);
......@@ -30,9 +30,10 @@ export type RoomHeaderProps = {
pos?: unknown;
};
};
roomToolbox?: JSX.Element;
};
const RoomHeader = ({ room, topic = '', slots = {} }: RoomHeaderProps) => {
const RoomHeader = ({ room, topic = '', slots = {}, roomToolbox }: RoomHeaderProps) => {
const t = useTranslation();
return (
......@@ -65,7 +66,7 @@ const RoomHeader = ({ room, topic = '', slots = {} }: RoomHeaderProps) => {
<Suspense fallback={null}>
<HeaderToolbar aria-label={t('Toolbox_room_actions')}>
{slots?.toolbox?.pre}
{slots?.toolbox?.content || <RoomToolbox />}
{slots?.toolbox?.content || roomToolbox || <RoomToolbox />}
{slots?.toolbox?.pos}
</HeaderToolbar>
</Suspense>
......
import { isDirectMessageRoom } from '@rocket.chat/core-typings';
import React, { lazy } from 'react';
import { E2EEState } from '../../../../app/e2e/client/E2EEState';
import { E2ERoomState } from '../../../../app/e2e/client/E2ERoomState';
import { useE2EERoomState } from '../hooks/useE2EERoomState';
import { useE2EEState } from '../hooks/useE2EEState';
import DirectRoomHeader from './DirectRoomHeader';
import RoomHeader from './RoomHeader';
import type { RoomHeaderProps } from './RoomHeader';
const RoomToolboxE2EESetup = lazy(() => import('./RoomToolbox/RoomToolboxE2EESetup'));
const RoomHeaderE2EESetup = ({ room, topic = '', slots = {} }: RoomHeaderProps) => {
const e2eeState = useE2EEState();
const e2eRoomState = useE2EERoomState(room._id);
if (e2eeState === E2EEState.SAVE_PASSWORD || e2eeState === E2EEState.ENTER_PASSWORD || e2eRoomState === E2ERoomState.WAITING_KEYS) {
return <RoomHeader room={room} topic={topic} slots={slots} roomToolbox={<RoomToolboxE2EESetup />} />;
}
if (isDirectMessageRoom(room) && (room.uids?.length ?? 0) < 3) {
return <DirectRoomHeader slots={slots} room={room} />;
}
return <RoomHeader room={room} topic={topic} slots={slots} />;
};
export default RoomHeaderE2EESetup;
import { useStableArray } from '@rocket.chat/fuselage-hooks';
import { HeaderToolbarAction } from '@rocket.chat/ui-client';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React from 'react';
import { roomActionHooksForE2EESetup } from '../../../../ui';
import type { RoomToolboxActionConfig } from '../../contexts/RoomToolboxContext';
import { useRoomToolbox } from '../../contexts/RoomToolboxContext';
const RoomToolboxE2EESetup = () => {
const t = useTranslation();
const toolbox = useRoomToolbox();
const { tab } = toolbox;
const actions = useStableArray(
roomActionHooksForE2EESetup
.map((roomActionHook) => roomActionHook())
.filter((roomAction): roomAction is RoomToolboxActionConfig => !!roomAction),
);
return (
<>
{actions.map(({ id, icon, title, action, disabled, tooltip }, index) => (
<HeaderToolbarAction
key={id}
index={index}
id={id}
icon={icon}
title={t(title)}
pressed={id === tab?.id}
action={action ?? (() => toolbox.openTab(id))}
disabled={disabled}
tooltip={tooltip}
/>
))}
</>
);
};
export default RoomToolboxE2EESetup;
......@@ -429,11 +429,17 @@ test.describe.serial('e2ee room setup', () => {
await poHomeChannel.dismissToast();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.encryptedRoomHeaderIcon.first().waitFor();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon.first()).toBeVisible();
await page.locator('role=button[name="Save E2EE password"]').waitFor();
await expect(page.locator('role=button[name="Save E2EE password"]')).toBeVisible();
await poHomeChannel.tabs.btnE2EERoomSetupDisableE2E.waitFor();
await expect(poHomeChannel.tabs.btnE2EERoomSetupDisableE2E).toBeVisible();
await expect(poHomeChannel.tabs.btnTabMembers).toBeVisible();
await expect(poHomeChannel.tabs.btnRoomInfo).toBeVisible();
await expect(poHomeChannel.content.inputMessage).not.toBeVisible();
await page.locator('role=button[name="Save E2EE password"]').click();
......@@ -477,11 +483,17 @@ test.describe.serial('e2ee room setup', () => {
await poHomeChannel.dismissToast();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon.first()).toBeVisible();
await page.locator('role=button[name="Enter your E2E password"]').waitFor();
await expect(page.locator('role=banner >> text="Enter your E2E password"')).toBeVisible();
await poHomeChannel.tabs.btnE2EERoomSetupDisableE2E.waitFor();
await expect(poHomeChannel.tabs.btnE2EERoomSetupDisableE2E).toBeVisible();
await expect(poHomeChannel.tabs.btnTabMembers).toBeVisible();
await expect(poHomeChannel.tabs.btnRoomInfo).toBeVisible();
await expect(poHomeChannel.content.inputMessage).not.toBeVisible();
await page.locator('role=button[name="Enter your E2E password"]').click();
......@@ -518,7 +530,7 @@ test.describe.serial('e2ee room setup', () => {
await poHomeChannel.dismissToast();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon.first()).toBeVisible();
await poHomeChannel.content.sendMessage('hello world');
......@@ -551,5 +563,10 @@ test.describe.serial('e2ee room setup', () => {
await expect(poHomeChannel.content.inputMessage).not.toBeVisible();
await expect(page.locator('.rcx-states__title')).toContainText('Check back later');
await poHomeChannel.tabs.btnE2EERoomSetupDisableE2E.waitFor();
await expect(poHomeChannel.tabs.btnE2EERoomSetupDisableE2E).toBeVisible();
await expect(poHomeChannel.tabs.btnTabMembers).toBeVisible();
await expect(poHomeChannel.tabs.btnRoomInfo).toBeVisible();
});
});
......@@ -44,6 +44,10 @@ export class HomeFlextab {
return this.page.locator('role=menuitem[name="Notifications Preferences"]');
}
get btnE2EERoomSetupDisableE2E(): Locator {
return this.page.locator('[data-qa-id=ToolBoxAction-key]');
}
get btnDisableE2E(): Locator {
return this.page.locator('role=menuitem[name="Disable E2E"]');
}
......
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