Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

[WIP] Human Edition of Element Web prototype #8228

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
dbc7f50
Wording around microphone and camera device permissions
hughns Apr 4, 2022
de5b9a5
Nasty hack to ignore missing translations without having to rebuild t…
hughns Apr 4, 2022
101c0d5
Wording updates for Verification => Setup secure messaging
hughns Apr 4, 2022
13bf565
Settings refactor
hughns Apr 4, 2022
8dcc40a
Move Discovery settings into Privacy panel
hughns Apr 4, 2022
d1abcab
Only prompt to setup cross-signing when you access an encrypted room
hughns Apr 4, 2022
1430593
Prompt user to setup cross-signing when decryption fails on an event …
hughns Apr 4, 2022
96135f7
Move backup in to Advanced and Search to top level of Secure Messaging
hughns Apr 4, 2022
2ccee9c
Secure Messaging settings layout
hughns Apr 4, 2022
d9248da
Fudge tests to pass
hughns Apr 4, 2022
2226263
Fix i8n + test
hughns Apr 4, 2022
2d59f1b
Lint fixes
hughns Apr 4, 2022
7ad2489
Ignore eslint warnings
hughns Apr 4, 2022
8367f06
Account panel devices wording
hughns Apr 4, 2022
baabe41
Wording for new login popup
hughns Apr 4, 2022
6f77b76
Setup => Set up when used as a verb
hughns Apr 5, 2022
b65d2d8
Merge branch 'develop' into hughns/human-edition
hughns Apr 6, 2022
51f04ee
Additional merge fix
hughns Apr 6, 2022
927406a
More Encrpytion => Secure messaging
hughns Apr 6, 2022
9f23605
Merge branch 'develop' into hughns/human-edition
hughns Apr 8, 2022
ffb4020
Fix merge
hughns Apr 8, 2022
3c43bdb
Setup cross signing and recovery after registration
hughns Apr 10, 2022
80faf81
Don't log recovery key to console
hughns Apr 15, 2022
da6e1a4
Allow insecure passwords for testing
hughns Apr 15, 2022
09bee43
Store 4s recovery key after entered for verification
hughns Apr 15, 2022
19cd361
Prompt for saving recovery key if needed during logout
hughns Apr 15, 2022
5a5251f
Session => Device
hughns Apr 15, 2022
d95de4f
More 4S Security Key => Recovery key
hughns Apr 15, 2022
da283d7
Security key => Recovery key
hughns Apr 15, 2022
ca69917
Trust level slider
hughns Apr 18, 2022
74765d0
Allow device renaming in Account panel
hughns Apr 19, 2022
6406b9a
Secure setup modal title
hughns Apr 19, 2022
c2f404a
Take account of whether user has other devices whilst logging out
hughns Apr 19, 2022
8e2c384
Improve layout of secure messaging devices
hughns Apr 19, 2022
738eb36
More wording on saving recovery key
hughns Apr 19, 2022
b5919fc
Allow removal of recovery key from device
hughns May 4, 2022
b45c336
More "setup"=>"set up"
hughns May 4, 2022
54da80a
"room key" => "message key"
hughns May 4, 2022
27f6e20
Update src/SlashCommands.tsx
hughns May 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn start:build\" \"yarn reskindex:watch\"",
"start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"",
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
"lint:js": "eslint --max-warnings 0 src test",
"lint:js": "eslint src test",
"lint:js-fix": "eslint --fix src test",
"lint:types": "tsc --noEmit --jsx react",
"lint:style": "stylelint \"res/css/**/*.scss\"",
Expand Down
16 changes: 13 additions & 3 deletions src/DeviceListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ export default class DeviceListener {
// The set of device IDs we're currently displaying toasts for
private displayingToastsForDeviceIds = new Set<string>();

private hasViewedEncryptedRoom = false;

public async viewingEncryptedRoom() {
this.hasViewedEncryptedRoom = true;
this.dismissedThisDeviceToast = false;
return this.recheck();
}

static sharedInstance() {
if (!window.mxDeviceListener) window.mxDeviceListener = new DeviceListener();
return window.mxDeviceListener;
Expand Down Expand Up @@ -211,9 +219,11 @@ export default class DeviceListener {
// If we're in the middle of a secret storage operation, we're likely
// modifying the state involved here, so don't add new toasts to setup.
if (isSecretStorageBeingAccessed()) return false;
// Show setup toasts once the user is in at least one encrypted room.
const cli = MatrixClientPeg.get();
return cli && cli.getRooms().some(r => cli.isRoomEncrypted(r.roomId));
// // Show setup toasts once the user is in at least one encrypted room.
// const cli = MatrixClientPeg.get();
// return cli && cli.getRooms().some(r => cli.isRoomEncrypted(r.roomId));
// Show setup toasts once the user tries to view an encrypted room
return this.hasViewedEncryptedRoom;
}

private async recheck() {
Expand Down
27 changes: 14 additions & 13 deletions src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ import { shouldUseLoginForWelcome } from "../../utils/pages";
import { replaceableComponent } from "../../utils/replaceableComponent";
import RoomListStore from "../../stores/room-list/RoomListStore";
import { RoomUpdateCause } from "../../stores/room-list/models";
import SecurityCustomisations from "../../customisations/Security";
import Spinner from "../views/elements/Spinner";
import QuestionDialog from "../views/dialogs/QuestionDialog";
import UserSettingsDialog, { UserTab } from '../views/dialogs/UserSettingsDialog';
Expand Down Expand Up @@ -376,18 +375,20 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
return;
}

const crossSigningIsSetUp = cli.getStoredCrossSigningForUser(cli.getUserId());
if (crossSigningIsSetUp) {
if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) {
this.onLoggedIn();
} else {
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
}
} else if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) {
this.setStateForNewView({ view: Views.E2E_SETUP });
} else {
this.onLoggedIn();
}
// const crossSigningIsSetUp = cli.getStoredCrossSigningForUser(cli.getUserId());
// if (crossSigningIsSetUp) {
// if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) {
// this.onLoggedIn();
// } else {
// this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
// }
// } else if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) {
// this.setStateForNewView({ view: Views.E2E_SETUP });
// } else {
// this.onLoggedIn();
// }
this.onLoggedIn();

this.setState({ pendingInitialSync: false });
}

Expand Down
3 changes: 3 additions & 0 deletions src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ import { DoAfterSyncPreparedPayload } from '../../dispatcher/payloads/DoAfterSyn
import FileDropTarget from './FileDropTarget';
import Measured from '../views/elements/Measured';
import { FocusComposerPayload } from '../../dispatcher/payloads/FocusComposerPayload';
import DeviceListener from '../../DeviceListener';

const DEBUG = false;
let debuglog = function(msg: string) {};
Expand Down Expand Up @@ -1140,6 +1141,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
e2eStatus = await shieldStatusForRoom(this.context, room);
}

await DeviceListener.sharedInstance().viewingEncryptedRoom();

if (this.unmounted) return;
this.setState({ e2eStatus });
}
Expand Down
14 changes: 12 additions & 2 deletions src/components/structures/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,18 @@ export default class UserMenu extends React.Component<IProps, IState> {
/>
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconLock"
label={_t("Security & Privacy")}
onClick={(e) => this.onSettingsOpen(e, UserTab.Security)}
label={_t("Account")}
onClick={(e) => this.onSettingsOpen(e, UserTab.Account)}
/>
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconLock"
label={_t("Secure Messaging")}
onClick={(e) => this.onSettingsOpen(e, UserTab.SecureMessaging)}
/>
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconLock"
label={_t("Privacy")}
onClick={(e) => this.onSettingsOpen(e, UserTab.Privacy)}
/>
<IconizedContextMenuOption
iconClassName="mx_UserMenu_iconSettings"
Expand Down
8 changes: 4 additions & 4 deletions src/components/structures/auth/CompleteSecurity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
title = _t("Unable to verify this device");
} else {
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
title = _t("Verify this device");
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_normal" />;
title = _t("Secure messaging setup");
}
} else if (phase === Phase.Done) {
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_verified" />;
Expand All @@ -81,11 +81,11 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
title = _t("Are you sure?");
} else if (phase === Phase.Busy) {
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_normal" />;
title = _t("Verify this device");
} else if (phase === Phase.ConfirmReset) {
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
title = _t("Really reset verification keys?");
title = _t("Are you sure?");
} else if (phase === Phase.Finished) {
// SetupEncryptionBody will take care of calling onFinished, we don't need to do anything
} else {
Expand Down
45 changes: 23 additions & 22 deletions src/components/structures/auth/SetupEncryptionBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,15 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
return (
<div>
<p>{ _t(
"It looks like you don't have a Security Key or any other devices you can " +
"verify against. This device will not be able to access old encrypted messages. " +
"It looks like you don't have a recovery key or any other devices you can use to complete " +
"the setup of secure messaging. As a result, this device won't be able to access past encrypted messages. " +
"In order to verify your identity on this device, you'll need to reset " +
"your verification keys.",
"secure messaging completely.",
) }</p>

<div className="mx_CompleteSecurity_actionRow">
<AccessibleButton kind="primary" onClick={this.onResetConfirmClick}>
{ _t("Proceed with reset") }
{ _t("Reset secure messaging") }
</AccessibleButton>
</div>
</div>
Expand All @@ -183,9 +183,9 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
const store = SetupEncryptionStore.sharedInstance();
let recoveryKeyPrompt;
if (store.keyInfo && keyHasPassphrase(store.keyInfo)) {
recoveryKeyPrompt = _t("Verify with Security Key or Phrase");
recoveryKeyPrompt = _t("Use recovery key or passphrase");
} else if (store.keyInfo) {
recoveryKeyPrompt = _t("Verify with Security Key");
recoveryKeyPrompt = _t("Use recovery key");
}

let useRecoveryKeyButton;
Expand All @@ -198,22 +198,25 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
let verifyButton;
if (store.hasDevicesToVerifyAgainst) {
verifyButton = <AccessibleButton kind="primary" onClick={this.onVerifyClick}>
{ _t("Verify with another device") }
{ _t("Use another device") }
</AccessibleButton>;
}

return (
<div>
<p>{ _t(
"Verify your identity to access encrypted messages and prove your identity to others.",
"Setup secure messaging on this device to access past encrypted messages and allow others to trust it.",
) }</p>
<p>{ _t(
"Please select how you would like to do the setup.",
) }</p>

<div className="mx_CompleteSecurity_actionRow">
{ verifyButton }
{ useRecoveryKeyButton }
</div>
<div className="mx_SetupEncryptionBody_reset">
{ _t("Forgotten or lost all recovery methods? <a>Reset all</a>", null, {
{ _t("Forgotten or lost all setup methods? <a>Reset secure messaging</a>", null, {
a: (sub) => <button
onClick={this.onResetClick}
className="mx_SetupEncryptionBody_reset_link mx_Dialog_nonDialogButton">
Expand All @@ -228,12 +231,12 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
let message;
if (this.state.backupInfo) {
message = <p>{ _t(
"Your new device is now verified. It has access to your " +
"encrypted messages, and other users will see it as trusted.",
"Secure messaging is now setup on this device and you can access your past encrypted message. " +
"Others will see this device as trusted.",
) }</p>;
} else {
message = <p>{ _t(
"Your new device is now verified. Other users will see it as trusted.",
"Secure messaging is now setup on this device and others will see it as trusted.",
) }</p>;
}
return (
Expand All @@ -254,21 +257,21 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
return (
<div>
<p>{ _t(
"Without verifying, you won't have access to all your messages " +
"and may appear as untrusted to others.",
"Without setting up secure messaging you won't have access to past encrypted messages. " +
"This device may also appear as untrusted to others.",
) }</p>
<div className="mx_CompleteSecurity_actionRow">
<AccessibleButton
kind="danger_outline"
onClick={this.onSkipConfirmClick}
>
{ _t("I'll verify later") }
{ _t("Setup later") }
</AccessibleButton>
<AccessibleButton
kind="primary"
onClick={this.onSkipBackClick}
>
{ _t("Go Back") }
{ _t("Go back") }
</AccessibleButton>
</div>
</div>
Expand All @@ -277,14 +280,12 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
return (
<div>
<p>{ _t(
"Resetting your verification keys cannot be undone. After resetting, " +
"you won't have access to old encrypted messages, and any friends who " +
"have previously verified you will see security warnings until you " +
"re-verify with them.",
"By resetting secure messaging you will lose access to your past encrypted messages. " +
"Also, any contact who has previously verified you will see this device as untrusted.",
) }</p>
<p>{ _t(
"Please only proceed if you're sure you've lost all of your other " +
"devices and your security key.",
"You should only proceed if you are certain that you cannot access your other devices and have lost " +
"your recovery key.",
) }</p>

<div className="mx_CompleteSecurity_actionRow">
Expand Down
Loading