You've already forked element-web
mirror of
https://github.com/element-hq/element-web.git
synced 2025-08-06 16:22:46 +03:00
Prompt the user when key storage is unexpectedly off (#29912)
* Assert that we set backup_disabled when turning off key storage * Prompt the user when key storage is unexpectedly off * Playwright tests for the Turn on key storage toast
This commit is contained in:
@@ -24,7 +24,7 @@ import {
|
||||
} from "matrix-js-sdk/src/crypto-api";
|
||||
import { type CryptoSessionStateChange } from "@matrix-org/analytics-events/types/typescript/CryptoSessionStateChange";
|
||||
|
||||
import DeviceListener from "../../src/DeviceListener";
|
||||
import DeviceListener, { BACKUP_DISABLED_ACCOUNT_DATA_KEY } from "../../src/DeviceListener";
|
||||
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
||||
import * as SetupEncryptionToast from "../../src/toasts/SetupEncryptionToast";
|
||||
import * as UnverifiedSessionToast from "../../src/toasts/UnverifiedSessionToast";
|
||||
@@ -118,6 +118,7 @@ describe("DeviceListener", () => {
|
||||
getDeviceId: jest.fn().mockReturnValue(deviceId),
|
||||
setAccountData: jest.fn(),
|
||||
getAccountData: jest.fn(),
|
||||
getAccountDataFromServer: jest.fn(),
|
||||
deleteAccountData: jest.fn(),
|
||||
getCrypto: jest.fn().mockReturnValue(mockCrypto),
|
||||
secretStorage: {
|
||||
@@ -309,6 +310,8 @@ describe("DeviceListener", () => {
|
||||
it("hides setup encryption toast when cross signing and secret storage are ready", async () => {
|
||||
mockCrypto!.isCrossSigningReady.mockResolvedValue(true);
|
||||
mockCrypto!.isSecretStorageReady.mockResolvedValue(true);
|
||||
mockCrypto!.getActiveSessionBackupVersion.mockResolvedValue("1");
|
||||
|
||||
await createAndStart();
|
||||
expect(SetupEncryptionToast.hideToast).toHaveBeenCalled();
|
||||
});
|
||||
@@ -377,6 +380,7 @@ describe("DeviceListener", () => {
|
||||
|
||||
it("hides the out-of-sync toast when one of the secrets is missing", async () => {
|
||||
mockCrypto!.isSecretStorageReady.mockResolvedValue(true);
|
||||
mockCrypto!.getActiveSessionBackupVersion.mockResolvedValue("1");
|
||||
|
||||
// First show the toast
|
||||
mockCrypto!.getCrossSigningStatus.mockResolvedValue({
|
||||
@@ -414,6 +418,7 @@ describe("DeviceListener", () => {
|
||||
it("shows set up recovery toast when user has a key backup available", async () => {
|
||||
// non falsy response
|
||||
mockCrypto.getKeyBackupInfo.mockResolvedValue({} as unknown as KeyBackupInfo);
|
||||
mockCrypto.getActiveSessionBackupVersion.mockResolvedValue("1");
|
||||
mockClient.secretStorage.getDefaultKeyId.mockResolvedValue(null);
|
||||
|
||||
await createAndStart();
|
||||
@@ -444,6 +449,9 @@ describe("DeviceListener", () => {
|
||||
|
||||
it("dispatches keybackup event when key backup is not enabled", async () => {
|
||||
mockCrypto.getActiveSessionBackupVersion.mockResolvedValue(null);
|
||||
mockClient.getAccountDataFromServer.mockImplementation((eventType) =>
|
||||
eventType === BACKUP_DISABLED_ACCOUNT_DATA_KEY ? ({ disabled: true } as any) : null,
|
||||
);
|
||||
await createAndStart();
|
||||
expect(mockDispatcher.dispatch).toHaveBeenCalledWith({
|
||||
action: Action.ReportKeyBackupNotEnabled,
|
||||
@@ -463,6 +471,137 @@ describe("DeviceListener", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("sets backup_disabled account data when we call recordKeyBackupDisabled", async () => {
|
||||
const instance = await createAndStart();
|
||||
await instance.recordKeyBackupDisabled();
|
||||
|
||||
expect(mockClient.setAccountData).toHaveBeenCalledWith("m.org.matrix.custom.backup_disabled", {
|
||||
disabled: true,
|
||||
});
|
||||
});
|
||||
|
||||
describe("when crypto is in use and set up", () => {
|
||||
beforeEach(() => {
|
||||
// Encryption is in use
|
||||
mockClient.getRooms.mockReturnValue([{ roomId: "!room1" }, { roomId: "!room2" }] as unknown as Room[]);
|
||||
jest.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
|
||||
|
||||
// The device is verified
|
||||
mockCrypto.getDeviceVerificationStatus.mockResolvedValue(
|
||||
new DeviceVerificationStatus({ crossSigningVerified: true }),
|
||||
);
|
||||
});
|
||||
|
||||
describe("but key storage is off", () => {
|
||||
beforeEach(() => {
|
||||
// There is no active key backup/storage
|
||||
mockCrypto.getActiveSessionBackupVersion.mockResolvedValue(null);
|
||||
});
|
||||
|
||||
it("shows the 'Turn on key storage' toast if we never explicitly turned off key storage", async () => {
|
||||
// Given key backup is off but the account data saying we turned it off is not set
|
||||
// (m.org.matrix.custom.backup_disabled)
|
||||
mockClient.getAccountData.mockReturnValue(undefined);
|
||||
|
||||
// When we launch the DeviceListener
|
||||
await createAndStart();
|
||||
|
||||
// Then the toast is displayed
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith(
|
||||
SetupEncryptionToast.Kind.TURN_ON_KEY_STORAGE,
|
||||
);
|
||||
});
|
||||
|
||||
it("shows the 'Turn on key storage' toast if we turned on key storage", async () => {
|
||||
// Given key backup is off but the account data says we turned it on (this should not happen - the
|
||||
// account data should only be updated if we turn on key storage)
|
||||
mockClient.getAccountData.mockImplementation((eventType) =>
|
||||
eventType === BACKUP_DISABLED_ACCOUNT_DATA_KEY
|
||||
? new MatrixEvent({ content: { disabled: false } })
|
||||
: undefined,
|
||||
);
|
||||
|
||||
// When we launch the DeviceListener
|
||||
await createAndStart();
|
||||
|
||||
// Then the toast is displayed
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith(
|
||||
SetupEncryptionToast.Kind.TURN_ON_KEY_STORAGE,
|
||||
);
|
||||
});
|
||||
|
||||
it("does not show the 'Turn on key storage' toast if we turned off key storage", async () => {
|
||||
// Given key backup is off but the account data saying we turned it off is set
|
||||
mockClient.getAccountDataFromServer.mockImplementation((eventType) =>
|
||||
eventType === BACKUP_DISABLED_ACCOUNT_DATA_KEY ? ({ disabled: true } as any) : null,
|
||||
);
|
||||
|
||||
// When we launch the DeviceListener
|
||||
await createAndStart();
|
||||
|
||||
// Then the toast is not displayed
|
||||
expect(SetupEncryptionToast.showToast).not.toHaveBeenCalledWith(
|
||||
SetupEncryptionToast.Kind.TURN_ON_KEY_STORAGE,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("and key storage is on", () => {
|
||||
beforeEach(() => {
|
||||
// There is an active key backup/storage
|
||||
mockCrypto.getActiveSessionBackupVersion.mockResolvedValue("1");
|
||||
});
|
||||
|
||||
it("does not show the 'Turn on key storage' toast if we never explicitly turned off key storage", async () => {
|
||||
// Given key backup is on and the account data saying we turned it off is not set
|
||||
mockClient.getAccountData.mockReturnValue(undefined);
|
||||
|
||||
// When we launch the DeviceListener
|
||||
await createAndStart();
|
||||
|
||||
// Then the toast is not displayed
|
||||
expect(SetupEncryptionToast.showToast).not.toHaveBeenCalledWith(
|
||||
SetupEncryptionToast.Kind.TURN_ON_KEY_STORAGE,
|
||||
);
|
||||
});
|
||||
|
||||
it("does not show the 'Turn on key storage' toast if we turned on key storage", async () => {
|
||||
// Given key backup is on and the account data says we turned it on
|
||||
mockClient.getAccountData.mockImplementation((eventType) =>
|
||||
eventType === BACKUP_DISABLED_ACCOUNT_DATA_KEY
|
||||
? new MatrixEvent({ content: { disabled: false } })
|
||||
: undefined,
|
||||
);
|
||||
|
||||
// When we launch the DeviceListener
|
||||
await createAndStart();
|
||||
|
||||
// Then the toast is not displayed
|
||||
expect(SetupEncryptionToast.showToast).not.toHaveBeenCalledWith(
|
||||
SetupEncryptionToast.Kind.TURN_ON_KEY_STORAGE,
|
||||
);
|
||||
});
|
||||
|
||||
it("does not show the 'Turn on key storage' toast if we turned off key storage", async () => {
|
||||
// Given key backup is on but the account data saying we turned it off is set (this should never
|
||||
// happen - it should only be set when we turn off key storage or dismiss the toast)
|
||||
mockClient.getAccountData.mockImplementation((eventType) =>
|
||||
eventType === BACKUP_DISABLED_ACCOUNT_DATA_KEY
|
||||
? new MatrixEvent({ content: { disabled: true } })
|
||||
: undefined,
|
||||
);
|
||||
|
||||
// When we launch the DeviceListener
|
||||
await createAndStart();
|
||||
|
||||
// Then the toast is not displayed
|
||||
expect(SetupEncryptionToast.showToast).not.toHaveBeenCalledWith(
|
||||
SetupEncryptionToast.Kind.TURN_ON_KEY_STORAGE,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("unverified sessions toasts", () => {
|
||||
const currentDevice = new Device({ deviceId, userId: userId, algorithms: [], keys: new Map() });
|
||||
const device2 = new Device({ deviceId: "d2", userId: userId, algorithms: [], keys: new Map() });
|
||||
@@ -997,6 +1136,8 @@ describe("DeviceListener", () => {
|
||||
});
|
||||
|
||||
it("shows the 'set up recovery' toast if user has not set up 4S", async () => {
|
||||
mockCrypto!.getActiveSessionBackupVersion.mockResolvedValue("1");
|
||||
|
||||
await createAndStart();
|
||||
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith(SetupEncryptionToast.Kind.SET_UP_RECOVERY);
|
||||
|
Reference in New Issue
Block a user