Skip to content

Commit 752e6d4

Browse files
authored
feat: Improve E2E encryption UI texts (RocketChat#36923)
1 parent feba290 commit 752e6d4

70 files changed

Lines changed: 81 additions & 440 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/cold-colts-hear.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@rocket.chat/i18n': minor
3+
'@rocket.chat/meteor': minor
4+
---
5+
6+
Replaces some texts in order to improve the E2E encryption communication on the UI

apps/meteor/client/hooks/roomActions/useE2EERoomAction.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export const useE2EERoomAction = () => {
115115
return {
116116
id: 'e2e',
117117
groups: ['direct', 'direct_multiple', 'group', 'team'],
118-
title: enabledOnRoom ? 'E2E_disable' : 'E2E_enable',
118+
title: enabledOnRoom ? 'Disable_E2E_encryption' : 'Enable_E2E_encryption',
119119
icon: 'key',
120120
order: 13,
121121
action,

apps/meteor/client/lib/e2ee/rocketchat.e2e.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ class E2E extends Emitter {
349349
onConfirm: () => {
350350
Accounts.storageLocation.removeItem('e2e.randomPassword');
351351
this.setState(E2EEState.READY);
352-
dispatchToastMessage({ type: 'success', message: t('End_To_End_Encryption_Enabled') });
352+
dispatchToastMessage({ type: 'success', message: t('E2E_encryption_enabled') });
353353
this.closeAlert();
354354
imperativeModal.close();
355355
},
@@ -413,8 +413,8 @@ class E2E extends Emitter {
413413
if (randomPassword) {
414414
this.setState(E2EEState.SAVE_PASSWORD);
415415
this.openAlert({
416-
title: () => t('Save_your_encryption_password'),
417-
html: () => t('Click_here_to_view_and_copy_your_password'),
416+
title: () => t('Save_your_new_E2EE_password'),
417+
html: () => t('Click_here_to_view_and_save_your_new_E2EE_password'),
418418
modifiers: ['large'],
419419
closable: false,
420420
icon: 'key',
@@ -587,7 +587,7 @@ class E2E extends Emitter {
587587
const showAlert = () => {
588588
this.openAlert({
589589
title: () => t('Enter_your_E2E_password'),
590-
html: () => t('Click_here_to_enter_your_encryption_password'),
590+
html: () => t('Click_here_to_enter_your_password'),
591591
modifiers: ['large'],
592592
closable: false,
593593
icon: 'key',
@@ -633,7 +633,7 @@ class E2E extends Emitter {
633633
await this.createAndLoadKeys();
634634
this.setState(E2EEState.READY);
635635
}
636-
dispatchToastMessage({ type: 'success', message: t('End_To_End_Encryption_Enabled') });
636+
dispatchToastMessage({ type: 'success', message: t('E2E_encryption_enabled') });
637637
} catch (error) {
638638
this.setState(E2EEState.ENTER_PASSWORD);
639639
dispatchToastMessage({ type: 'error', message: t('Your_E2EE_password_is_incorrect') });

apps/meteor/client/views/account/security/EndToEnd.tsx

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import { Box, PasswordInput, Field, FieldGroup, FieldLabel, FieldRow, FieldError, FieldHint, Button, Divider } from '@rocket.chat/fuselage';
2-
import { useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts';
2+
import { useToastMessageDispatch } from '@rocket.chat/ui-contexts';
33
import DOMPurify from 'dompurify';
44
import { Accounts } from 'meteor/accounts-base';
55
import type { ComponentProps, ReactElement } from 'react';
66
import { useId, useEffect } from 'react';
77
import { Controller, useForm } from 'react-hook-form';
8+
import { Trans, useTranslation } from 'react-i18next';
89

910
import { e2e } from '../../../lib/e2ee/rocketchat.e2e';
1011
import { useResetE2EPasswordMutation } from '../../hooks/useResetE2EPasswordMutation';
1112

1213
const EndToEnd = (props: ComponentProps<typeof Box>): ReactElement => {
13-
const t = useTranslation();
14+
const { t } = useTranslation();
1415
const dispatchToastMessage = useToastMessageDispatch();
1516

1617
const publicKey = Accounts.storageLocation.getItem('public_key');
@@ -29,11 +30,14 @@ const EndToEnd = (props: ComponentProps<typeof Box>): ReactElement => {
2930
password: '',
3031
passwordConfirm: '',
3132
},
32-
mode: 'all',
3333
});
3434

3535
const { password } = watch();
3636

37+
/**
38+
* TODO: We need to figure out a way to make this reactive,
39+
* so the form will allow change password as soon the user enter the current E2EE password
40+
*/
3741
const keysExist = Boolean(publicKey && privateKey);
3842

3943
const hasTypedPassword = Boolean(password?.trim().length);
@@ -66,65 +70,77 @@ const EndToEnd = (props: ComponentProps<typeof Box>): ReactElement => {
6670
id={e2ePasswordExplanationId}
6771
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(t('E2E_Encryption_Password_Explanation')) }}
6872
/>
69-
7073
<Box mbs={36} w='full'>
7174
<Box is='h4' fontScale='h4' mbe={12}>
72-
{t('E2E_Encryption_Password_Change')}
75+
{t('Change_E2EE_password')}
7376
</Box>
74-
7577
<FieldGroup w='full'>
7678
<Field>
77-
<FieldLabel htmlFor={passwordId}>{t('New_encryption_password')}</FieldLabel>
79+
<FieldLabel htmlFor={passwordId}>{t('New_E2EE_password')}</FieldLabel>
7880
<FieldRow>
7981
<Controller
8082
control={control}
8183
name='password'
82-
rules={{ required: t('Required_field', { field: t('New_encryption_password') }) }}
84+
rules={{ required: t('Required_field', { field: t('New_E2EE_password') }) }}
8385
render={({ field }) => (
8486
<PasswordInput
8587
{...field}
8688
id={passwordId}
8789
error={errors.password?.message}
88-
placeholder={t('New_Password_Placeholder')}
8990
disabled={!keysExist}
9091
aria-describedby={`${e2ePasswordExplanationId} ${passwordId}-hint ${passwordId}-error`}
9192
aria-invalid={errors.password ? 'true' : 'false'}
9293
/>
9394
)}
9495
/>
9596
</FieldRow>
96-
{!keysExist && <FieldHint id={`${passwordId}-hint`}>{t('EncryptionKey_Change_Disabled')}</FieldHint>}
97+
{!keysExist && (
98+
<FieldHint id={`${passwordId}-hint`}>
99+
<Trans i18nKey='Enter_current_E2EE_password_to_set_new'>
100+
To set a new password, first
101+
<Box
102+
is='a'
103+
href='#'
104+
onClick={async (e) => {
105+
e.preventDefault();
106+
await e2e.decodePrivateKeyFlow();
107+
}}
108+
>
109+
enter your current E2EE password.
110+
</Box>
111+
</Trans>
112+
</FieldHint>
113+
)}
97114
{errors?.password && (
98-
<FieldError aria-live='assertive' id={`${passwordId}-error`}>
115+
<FieldError role='alert' id={`${passwordId}-error`}>
99116
{errors.password.message}
100117
</FieldError>
101118
)}
102119
</Field>
103120
{hasTypedPassword && (
104121
<Field>
105-
<FieldLabel htmlFor={passwordConfirmId}>{t('Confirm_new_encryption_password')}</FieldLabel>
122+
<FieldLabel htmlFor={passwordConfirmId}>{t('Confirm_new_E2EE_password')}</FieldLabel>
106123
<FieldRow>
107124
<Controller
108125
control={control}
109126
name='passwordConfirm'
110127
rules={{
111-
required: t('Required_field', { field: t('Confirm_new_encryption_password') }),
112-
validate: (value: string) => (password !== value ? 'Your passwords do no match' : true),
128+
required: t('Required_field', { field: t('Confirm_new_E2EE_password') }),
129+
validate: (value: string) => (password !== value ? t('Passwords_do_not_match') : true),
113130
}}
114131
render={({ field }) => (
115132
<PasswordInput
116133
{...field}
117134
id={passwordConfirmId}
118135
error={errors.passwordConfirm?.message}
119-
placeholder={t('Confirm_New_Password_Placeholder')}
120136
aria-describedby={`${passwordConfirmId}-error`}
121-
aria-invalid={errors.password ? 'true' : 'false'}
137+
aria-invalid={errors.passwordConfirm ? 'true' : 'false'}
122138
/>
123139
)}
124140
/>
125141
</FieldRow>
126142
{errors.passwordConfirm && (
127-
<FieldError aria-live='assertive' id={`${passwordConfirmId}-error`}>
143+
<FieldError role='alert' id={`${passwordConfirmId}-error`}>
128144
{errors.passwordConfirm.message}
129145
</FieldError>
130146
)}
@@ -141,16 +157,16 @@ const EndToEnd = (props: ComponentProps<typeof Box>): ReactElement => {
141157
{t('Save_changes')}
142158
</Button>
143159
</Box>
144-
145160
<Divider mb={36} width='full' />
146-
147161
<Box>
148162
<Box is='h4' fontScale='h4' mbe={12}>
149-
{t('Reset_E2E_Key')}
163+
{t('Reset_E2EE_password')}
164+
</Box>
165+
<Box is='p' fontScale='p1' mbe={12}>
166+
{t('Reset_E2EE_password_description')}
150167
</Box>
151-
<Box is='p' fontScale='p1' mbe={12} dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(t('E2E_Reset_Key_Explanation')) }} />
152168
<Button onClick={() => resetE2EPassword.mutate()} data-qa-type='e2e-encryption-reset-key-button'>
153-
{t('Reset_E2E_Key')}
169+
{t('Reset_E2EE_password')}
154170
</Button>
155171
</Box>
156172
</Box>

apps/meteor/client/views/admin/users/hooks/useResetE2EEKeyAction.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const useResetE2EEKeyAction = (userId: IUser['_id']): AdminUserAction | u
3434
return canResetE2EEKey
3535
? {
3636
icon: 'key',
37-
content: t('Reset_E2E_Key'),
37+
content: t('Reset_E2EE_password'),
3838
onClick: confirmResetE2EEKey,
3939
}
4040
: undefined;

apps/meteor/client/views/e2e/SaveE2EPasswordModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const SaveE2EPasswordModal = ({ randomPassword, onClose, onCancel, onConfirm }:
2727
cancelText={t('Do_It_Later')}
2828
confirmText={t('I_Saved_My_Password')}
2929
variant='warning'
30-
title={t('Save_your_encryption_password')}
30+
title={t('Save_your_new_E2EE_password')}
3131
annotation={t('You_can_do_from_account_preferences')}
3232
>
3333
<p>

apps/meteor/client/views/hooks/useResetE2EPasswordMutation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const useResetE2EPasswordMutation = ({ options }: { options?: MutationOpt
1313
return useMutation({
1414
mutationFn: async () => resetE2eKey(),
1515
onSuccess: () => {
16-
dispatchToastMessage({ type: 'success', message: t('User_e2e_key_was_reset') });
16+
dispatchToastMessage({ type: 'success', message: t('E2EE_password_reset') });
1717
logout();
1818
},
1919
onError: (error) => {

apps/meteor/client/views/room/modals/E2EEModals/DisableE2EEModal.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const DisableE2EEModal = ({ onConfirm, onCancel, roomType, canResetRoomKey, onRe
2323
onConfirm={onConfirm}
2424
onCancel={onCancel}
2525
onDismiss={() => undefined}
26+
annotation={t('Proceed_with_caution')}
2627
>
2728
<Box mbe={16} is='p'>
2829
<Trans i18nKey='E2E_disable_encryption_description' tOptions={{ roomType }} />

apps/meteor/tests/e2e/page-objects/account-profile.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,7 @@ export class AccountProfile {
118118
}
119119

120120
get securityE2EEncryptionResetKeyButton(): Locator {
121-
return this.page.locator("role=button[name='Reset E2EE key']");
122-
}
123-
124-
get securityE2EEncryptionPassword(): Locator {
125-
return this.page.locator('role=textbox[name="New encryption password"]');
126-
}
127-
128-
get securityE2EEncryptionPasswordConfirmation(): Locator {
129-
return this.page.locator('role=textbox[name="Confirm new encryption password"]');
121+
return this.page.locator("role=button[name='Reset E2EE password']");
130122
}
131123

132124
get securityE2EEncryptionSavePasswordButton(): Locator {

apps/meteor/tests/e2e/page-objects/account-security.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ export class AccountSecurityPage {
1818
}
1919

2020
private get resetE2EEPasswordButton() {
21-
return this.page.getByRole('button', { name: 'Reset E2EE key' });
21+
return this.page.getByRole('button', { name: 'Reset E2EE password' });
2222
}
2323

2424
private get newE2EEPasswordInput() {
25-
return this.page.getByRole('textbox', { name: 'New encryption password' });
25+
return this.page.getByRole('textbox', { name: 'New E2EE password' });
2626
}
2727

2828
private get confirmNewE2EEPasswordInput() {
29-
return this.page.getByRole('textbox', { name: 'Confirm new encryption password' });
29+
return this.page.getByRole('textbox', { name: 'Confirm new E2EE password' });
3030
}
3131

3232
private get saveChangesButton() {

0 commit comments

Comments
 (0)