Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
5a74298
Add key storage toggle to Encryption settings
dbkr Jan 27, 2025
98950de
Keys in the acceptable order
dbkr Jan 27, 2025
4eb07d4
Fix some tests
dbkr Jan 28, 2025
97057de
Fix import
dbkr Jan 28, 2025
4ec09f0
Fix toast showing condition
dbkr Jan 28, 2025
4db196e
Fix import order
dbkr Jan 28, 2025
98114c8
Fix playwright tests
dbkr Jan 28, 2025
6a20703
Merge remote-tracking branch 'origin/develop' into dbkr/key_storage_t…
dbkr Feb 5, 2025
b7b2ea3
Fix bits lost in merge
dbkr Feb 5, 2025
e408715
Add key storage delete confirm screen
dbkr Feb 5, 2025
aa6de76
Fix hardcoded Element string
dbkr Feb 5, 2025
5ac2004
Fix type imports
dbkr Feb 5, 2025
1304587
Fix tests
dbkr Feb 5, 2025
a26efc5
Tests for key storage delete panel
dbkr Feb 5, 2025
1b99071
Fix test
dbkr Feb 5, 2025
6b238d1
Type import
dbkr Feb 5, 2025
87d44a7
Test for the view model
dbkr Feb 6, 2025
4ea6a33
Merge remote-tracking branch 'origin/develop' into dbkr/key_storage_t…
dbkr Feb 6, 2025
df4c23b
Fix type import
dbkr Feb 6, 2025
4a3a373
Actually fix type imports
dbkr Feb 6, 2025
e70afdb
Test updating
dbkr Feb 6, 2025
40f9bd9
Add playwright test & clarify slightly confusing comment
dbkr Feb 6, 2025
16c76cb
Show the advnced section whatever the state of key storage
dbkr Feb 6, 2025
f818d6e
Update screenshots
dbkr Feb 6, 2025
fc9bc09
Copy css to its own file
dbkr Feb 7, 2025
25f8fe2
Add missing doc & merge loading states
dbkr Feb 7, 2025
1178d77
Add tsdoc & loading alt text to spinner
dbkr Feb 7, 2025
7c2d9f4
Turn comments into proper tsdoc
dbkr Feb 7, 2025
cfd55a6
Switch to TypedEventEmitter and remove unnecessary loading state
dbkr Feb 7, 2025
f586c43
Add screenshot
dbkr Feb 7, 2025
e8483e0
Use higher level interface
dbkr Feb 7, 2025
8ca4a8b
Merge the two hooks in EncryptionUserSettingsTab
dbkr Feb 7, 2025
2ef05c5
Remove unused import
dbkr Feb 7, 2025
7149b3d
Don't check key backup enabled state separately
dbkr Feb 7, 2025
64f84cb
Update snapshot
dbkr Feb 7, 2025
0c5f2b0
Merge branch 'develop' into dbkr/key_storage_toggle
dbkr Feb 7, 2025
9c4625d
Use fixed recovery key function
dbkr Feb 7, 2025
f0d9e05
Amalgamate duplicated CSS files
dbkr Feb 10, 2025
de18311
Merge remote-tracking branch 'origin/develop' into dbkr/key_storage_t…
dbkr Feb 10, 2025
c4525b9
Have "key storage disabled" as a separate state
dbkr Feb 10, 2025
d1aef9f
Update snapshot
dbkr Feb 10, 2025
96a70f2
Fix... bad merge?
dbkr Feb 10, 2025
98edffa
Add backup enabled mock to more tests
dbkr Feb 10, 2025
a5cec9e
More snapshots
dbkr Feb 10, 2025
0162c82
Use defer util
dbkr Feb 10, 2025
446fca2
Merge branch 'dbkr/key_storage_toggle' into dbkr/key_storage_toggle_2
dbkr Feb 18, 2025
2c5e81f
Update to use EncryptionCardButtons
dbkr Feb 18, 2025
c0e54d9
Update snapshots
dbkr Feb 18, 2025
8c86402
Merge remote-tracking branch 'origin/develop' into dbkr/key_storage_t…
dbkr Feb 20, 2025
91c0adc
Use EncryptionCardEmphasisedContent
dbkr Feb 20, 2025
d7683e1
Update snapshots
dbkr Feb 20, 2025
2f8fb06
Update snapshot
dbkr Feb 20, 2025
819868c
Try screenshot from CI playwright
dbkr Feb 20, 2025
c83fcfd
Try playwright screenshots again
dbkr Feb 20, 2025
1b8cc7c
More screenshots
dbkr Feb 20, 2025
0108ba6
Rename to match files
dbkr Feb 26, 2025
a015d75
Test that 4S secrets are deleted
dbkr Feb 26, 2025
9d3e419
Make description clearer
dbkr Feb 26, 2025
90b5632
Fix typo & move related states together
dbkr Feb 26, 2025
4eebdb9
Add comment
dbkr Feb 26, 2025
ee925b3
More comments
dbkr Feb 26, 2025
2ff4a7a
Fix hook docs
dbkr Feb 26, 2025
defd1c7
restoreAllMocks
dbkr Feb 26, 2025
10487ea
Merge branch 'develop' into dbkr/key_storage_toggle_2
dbkr Feb 26, 2025
e7f36ed
Update snapshot
dbkr Feb 27, 2025
e6aa2da
Switch icon
dbkr Feb 27, 2025
bf5a22a
Update snapshot
dbkr Feb 27, 2025
fa7ee98
Missing copyright
dbkr Feb 28, 2025
1baaa10
Re-order states
dbkr Feb 28, 2025
b4750ae
Remove phantom space
dbkr Feb 28, 2025
5b0ccf7
Clarify 'button'
dbkr Feb 28, 2025
2c8bff1
Clarify docs more
dbkr Feb 28, 2025
f5d94dc
Explain thinking behind updating
dbkr Feb 28, 2025
dbd8743
Merge branch 'develop' into dbkr/key_storage_toggle_2
dbkr Mar 4, 2025
33a8edb
Switch to getActiveBackupVersion
dbkr Mar 4, 2025
9e6aa26
Add use of Key Storage Panel
dbkr Mar 4, 2025
7b379a6
Change key storage panel to be consistent
dbkr Mar 4, 2025
f68276c
Add tsdoc
dbkr Mar 4, 2025
cf7fe04
Use BACKUP_DISABLED_ACCOUNT_DATA_KEY in more places
dbkr Mar 4, 2025
9cb8a55
Expand doc
dbkr Mar 4, 2025
24c5431
Undo random yarn lock change
dbkr Mar 4, 2025
63d19f1
Use aggregate method for disabling key storage
dbkr Mar 5, 2025
054a6bd
Merge branch 'develop' into dbkr/key_storage_toggle_2
dbkr Mar 6, 2025
5cb8129
Fix tests
dbkr Mar 6, 2025
d803193
Use key backup status event to update
dbkr Mar 12, 2025
19c718c
Comment formatting
dbkr Mar 12, 2025
a03a0e3
Fix comment & put check inside if statement
dbkr Mar 12, 2025
63b0f0e
Add comment
dbkr Mar 12, 2025
5cac058
Prettier
dbkr Mar 12, 2025
75adfa8
Fix comment
dbkr Mar 13, 2025
3be9d0c
Merge branch 'develop' into dbkr/key_storage_toggle_2
dbkr Mar 13, 2025
da5a15f
Update snapshot
dbkr Mar 13, 2025
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
9 changes: 6 additions & 3 deletions src/DeviceListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,12 @@ import { asyncSomeParallel } from "./utils/arrays.ts";

const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000;

// Unfortunately named account data key used by Element X to indicate that the user
// has chosen to disable server side key backups. We need to set and honour this
// to prevent Element X from automatically turning key backup back on.
/**
* Unfortunately-named account data key used by Element X to indicate that the user
* has chosen to disable server side key backups.
*
* We need to set and honour this to prevent Element X from automatically turning key backup back on.
*/
export const BACKUP_DISABLED_ACCOUNT_DATA_KEY = "m.org.matrix.custom.backup_disabled";

const logger = baseLogger.getChild("DeviceListener:");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,16 @@ export function useKeyStoragePanelViewModel(): KeyStoragePanelState {
return;
}
if (enable) {
// If there is no existing key backup on the server, create one.
// `resetKeyBackup` will delete any existing backup, so we only do this if there is no existing backup.
const currentKeyBackup = await crypto.checkKeyBackupAndEnable();
if (currentKeyBackup === null) {
await crypto.resetKeyBackup();
}

// resetKeyBackup fires this off in the background without waiting, so we need to do it
// explicitly and wait for it, otherwise it won't be enabled yet when we check again.
await crypto.checkKeyBackupAndEnable();
// resetKeyBackup fires this off in the background without waiting, so we need to do it
// explicitly and wait for it, otherwise it won't be enabled yet when we check again.
await crypto.checkKeyBackupAndEnable();
}

// Set the flag so that EX no longer thinks the user wants backup disabled
await matrixClient.setAccountData(BACKUP_DISABLED_ACCOUNT_DATA_KEY, { disabled: false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
import React, { type JSX, useCallback, useEffect, useState } from "react";
import { Button, InlineSpinner, Separator } from "@vector-im/compound-web";
import ComputerIcon from "@vector-im/compound-design-tokens/assets/web/icons/computer";
import { ClientEvent } from "matrix-js-sdk/src/matrix";
import { CryptoEvent } from "matrix-js-sdk/src/crypto-api";

import type { MatrixEvent } from "matrix-js-sdk/src/matrix";
import SettingsTab from "../SettingsTab";
import { RecoveryPanel } from "../../encryption/RecoveryPanel";
import { ChangeRecoveryKey } from "../../encryption/ChangeRecoveryKey";
Expand All @@ -26,7 +25,6 @@ import { RecoveryPanelOutOfSync } from "../../encryption/RecoveryPanelOutOfSync"
import { useTypedEventEmitter } from "../../../../../hooks/useEventEmitter";
import { KeyStoragePanel } from "../../encryption/KeyStoragePanel";
import { DeleteKeyStoragePanel } from "../../encryption/DeleteKeyStoragePanel";
import { BACKUP_DISABLED_ACCOUNT_DATA_KEY } from "../../../../../DeviceListener";

/**
* The state in the encryption settings tab.
Expand Down Expand Up @@ -131,7 +129,7 @@ export function EncryptionUserSettingsTab({ initialState = "loading" }: Encrypti
);
break;
case "key_storage_delete":
content = <DeleteKeyStoragePanel onFinish={() => setState("main")} />;
content = <DeleteKeyStoragePanel onFinish={checkEncryptionState} />;
break;
}

Expand All @@ -146,10 +144,7 @@ export function EncryptionUserSettingsTab({ initialState = "loading" }: Encrypti
* Hook to check if the user needs:
* - to go through the SetupEncryption flow.
* - to enter their recovery key, if the secrets are not cached locally.
* ...and also whether megolm key backup is enabled on this device (which we use to set the state of the 'allow key storage' toggle):
* we don't so much care about the value of the account data, "m.org.matrix.custom.backup_disabled" although we do use it
* as a trigger to update as there's no event emitted for megolm key backup enabled state changing.
* flag here: what's important is whether key backup is actually happening or not).
* ...and also whether megolm key backup is enabled on this device (which we use to set the state of the 'allow key storage' toggle)
*
* If cross signing is set up, key backup is enabled and the secrets are cached, the state will be set to "main".
* If cross signing is not set up, the state will be set to "set_up_encryption".
Expand Down Expand Up @@ -189,18 +184,13 @@ function useCheckEncryptionState(state: State, setState: (state: State) => void)
if (state === "loading") checkEncryptionState();
}, [checkEncryptionState, state]);

useTypedEventEmitter(matrixClient, ClientEvent.AccountData, (event: MatrixEvent): void => {
const type = event.getType();
// Recheck the status if this account data has been updated as this implies the status
// of megolm key backup has changed on the user's account (there's no event emitted for megolm
// key backup enabled state changing, so we use this instead).
useTypedEventEmitter(matrixClient, CryptoEvent.KeyBackupStatus, (): void => {
// Recheck the status if the key backup status has changed so we can keep the page up to date.
// Note that this could potentially update the UI while the user is trying to do something, although
// if their account data is changing then it implies that they're changing encryption related things
// on another device. This code is written with the assumption that it's better for the UI to refresh
// and be up to date with whatever changes they've made.
Comment on lines 189 to 192

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this still talks about account data, which I think is incorrect

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, good catch.

if (type === BACKUP_DISABLED_ACCOUNT_DATA_KEY) {
checkEncryptionState();
}
checkEncryptionState();
});
Comment thread
richvdh marked this conversation as resolved.

// Also return the callback so that the component can re-run the logic.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { act, render, screen } from "jest-matrix-react";
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import { waitFor } from "@testing-library/dom";
import userEvent from "@testing-library/user-event";
import { ClientEvent, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { CryptoEvent } from "matrix-js-sdk/src/crypto-api";

import {
EncryptionUserSettingsTab,
Expand Down Expand Up @@ -163,7 +163,7 @@ describe("<EncryptionUserSettingsTab />", () => {
).toBeVisible();
});

it("should update when backup_disabled account data is changed", async () => {
it("should update when key backup status event is fired", async () => {
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");

renderComponent();
Expand All @@ -173,8 +173,7 @@ describe("<EncryptionUserSettingsTab />", () => {
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue(null);

act(() => {
const accountDataEvent = new MatrixEvent({ type: "m.org.matrix.custom.backup_disabled" });
matrixClient.emit(ClientEvent.AccountData, accountDataEvent);
matrixClient.emit(CryptoEvent.KeyBackupStatus, false);
});

await waitFor(() => {
Expand Down