Skip to content

Commit ede91bf

Browse files
Use CryptoApi.getKeyBackupInfo instead of deprecated MatrixClient.getKeyBackupVersion (#28450)
* Use `CryptoApi.getKeyBackupInfo` instead of deprecated `MatrixClient.getKeyBackupVersion` * Review changes --------- Co-authored-by: Michael Telatynski <[email protected]>
1 parent fd7c50f commit ede91bf

17 files changed

+37
-40
lines changed

src/DeviceListener.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,15 @@ export default class DeviceListener {
230230
private async getKeyBackupInfo(): Promise<KeyBackupInfo | null> {
231231
if (!this.client) return null;
232232
const now = new Date().getTime();
233+
const crypto = this.client.getCrypto();
234+
if (!crypto) return null;
235+
233236
if (
234237
!this.keyBackupInfo ||
235238
!this.keyBackupFetchedAt ||
236239
this.keyBackupFetchedAt < now - KEY_BACKUP_POLL_INTERVAL
237240
) {
238-
this.keyBackupInfo = await this.client.getKeyBackupVersion();
241+
this.keyBackupInfo = await crypto.getKeyBackupInfo();
239242
this.keyBackupFetchedAt = now;
240243
}
241244
return this.keyBackupInfo;

src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
279279
if (!forceReset) {
280280
try {
281281
this.setState({ phase: Phase.Loading });
282-
backupInfo = await cli.getKeyBackupVersion();
282+
backupInfo = await crypto.getKeyBackupInfo();
283283
} catch (e) {
284284
logger.error("Error fetching backup data from server", e);
285285
this.setState({ phase: Phase.LoadError });

src/components/structures/MatrixChat.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1638,7 +1638,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
16381638
} else {
16391639
// otherwise check the server to see if there's a new one
16401640
try {
1641-
newVersionInfo = await cli.getKeyBackupVersion();
1641+
newVersionInfo = (await cli.getCrypto()?.getKeyBackupInfo()) ?? null;
16421642
if (newVersionInfo !== null) haveNewVersion = true;
16431643
} catch (e) {
16441644
logger.error("Saw key backup error but failed to check backup version!", e);

src/components/views/dialogs/LogoutDialog.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export default class LogoutDialog extends React.Component<IProps, IState> {
109109
}
110110

111111
// backup is not active. see if there is a backup version on the server we ought to back up to.
112-
const backupInfo = await client.getKeyBackupVersion();
112+
const backupInfo = await crypto.getKeyBackupInfo();
113113
this.setState({ backupStatus: backupInfo ? BackupStatus.SERVER_BACKUP_BUT_DISABLED : BackupStatus.NO_BACKUP });
114114
}
115115

src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
258258
});
259259
try {
260260
const cli = MatrixClientPeg.safeGet();
261-
const backupInfo = await cli.getKeyBackupVersion();
261+
const backupInfo = (await cli.getCrypto()?.getKeyBackupInfo()) ?? null;
262262
const has4S = await cli.secretStorage.hasKey();
263263
const backupKeyStored = has4S ? await cli.isKeyBackupKeyStored() : null;
264264
this.setState({

src/components/views/settings/SecureBackupPanel.tsx

+4-7
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
118118
this.getUpdatedDiagnostics();
119119
try {
120120
const cli = MatrixClientPeg.safeGet();
121-
const backupInfo = await cli.getKeyBackupVersion();
121+
const backupInfo = (await cli.getCrypto()?.getKeyBackupInfo()) ?? null;
122122
const backupTrustInfo = backupInfo ? await cli.getCrypto()?.isKeyBackupTrusted(backupInfo) : undefined;
123123

124124
const activeBackupVersion = (await cli.getCrypto()?.getActiveSessionBackupVersion()) ?? null;
@@ -192,12 +192,9 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
192192
if (!proceed) return;
193193
this.setState({ loading: true });
194194
const versionToDelete = this.state.backupInfo!.version!;
195-
MatrixClientPeg.safeGet()
196-
.getCrypto()
197-
?.deleteKeyBackupVersion(versionToDelete)
198-
.then(() => {
199-
this.loadBackupStatus();
200-
});
195+
// deleteKeyBackupVersion fires a key backup status event
196+
// which will update the UI
197+
MatrixClientPeg.safeGet().getCrypto()?.deleteKeyBackupVersion(versionToDelete);
201198
},
202199
});
203200
};

src/stores/SetupEncryptionStore.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export class SetupEncryptionStore extends EventEmitter {
125125
this.emit("update");
126126
try {
127127
const cli = MatrixClientPeg.safeGet();
128-
const backupInfo = await cli.getKeyBackupVersion();
128+
const backupInfo = (await cli.getCrypto()?.getKeyBackupInfo()) ?? null;
129129
this.backupInfo = backupInfo;
130130
this.emit("update");
131131

test/test-utils/client.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ export const mockClientMethodsCrypto = (): Partial<
143143
> => ({
144144
isKeyBackupKeyStored: jest.fn(),
145145
getCrossSigningCacheCallbacks: jest.fn().mockReturnValue({ getCrossSigningKeyCache: jest.fn() }),
146-
getKeyBackupVersion: jest.fn().mockResolvedValue(null),
147146
secretStorage: { hasKey: jest.fn() },
148147
getCrypto: jest.fn().mockReturnValue({
149148
getUserDeviceInfo: jest.fn(),
@@ -163,6 +162,7 @@ export const mockClientMethodsCrypto = (): Partial<
163162
getOwnDeviceKeys: jest.fn().mockReturnValue(new Promise(() => {})),
164163
getCrossSigningKeyId: jest.fn(),
165164
isEncryptionEnabledInRoom: jest.fn().mockResolvedValue(false),
165+
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
166166
}),
167167
});
168168

test/test-utils/test-utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ export function createTestClient(): MatrixClient {
9999
getDevices: jest.fn().mockResolvedValue({ devices: [{ device_id: "ABCDEFGHI" }] }),
100100
getSessionId: jest.fn().mockReturnValue("iaszphgvfku"),
101101
credentials: { userId: "@userId:matrix.org" },
102-
getKeyBackupVersion: jest.fn(),
103102

104103
secretStorage: {
105104
get: jest.fn(),
@@ -135,6 +134,7 @@ export function createTestClient(): MatrixClient {
135134
restoreKeyBackupWithPassphrase: jest.fn(),
136135
loadSessionBackupPrivateKeyFromSecretStorage: jest.fn(),
137136
storeSessionBackupPrivateKey: jest.fn(),
137+
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
138138
}),
139139

140140
getPushActionsForEvent: jest.fn(),

test/unit-tests/DeviceListener-test.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,12 @@ describe("DeviceListener", () => {
9696
}),
9797
getSessionBackupPrivateKey: jest.fn(),
9898
isEncryptionEnabledInRoom: jest.fn(),
99+
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
99100
} as unknown as Mocked<CryptoApi>;
100101
mockClient = getMockClientWithEventEmitter({
101102
isGuest: jest.fn(),
102103
getUserId: jest.fn().mockReturnValue(userId),
103104
getSafeUserId: jest.fn().mockReturnValue(userId),
104-
getKeyBackupVersion: jest.fn().mockResolvedValue(undefined),
105105
getRooms: jest.fn().mockReturnValue([]),
106106
isVersionSupported: jest.fn().mockResolvedValue(true),
107107
isInitialSyncComplete: jest.fn().mockReturnValue(true),
@@ -354,7 +354,7 @@ describe("DeviceListener", () => {
354354

355355
it("shows set up encryption toast when user has a key backup available", async () => {
356356
// non falsy response
357-
mockClient!.getKeyBackupVersion.mockResolvedValue({} as unknown as KeyBackupInfo);
357+
mockCrypto.getKeyBackupInfo.mockResolvedValue({} as unknown as KeyBackupInfo);
358358
await createAndStart();
359359

360360
expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith(
@@ -673,7 +673,7 @@ describe("DeviceListener", () => {
673673
describe("When Room Key Backup is not enabled", () => {
674674
beforeEach(() => {
675675
// no backup
676-
mockClient.getKeyBackupVersion.mockResolvedValue(null);
676+
mockCrypto.getKeyBackupInfo.mockResolvedValue(null);
677677
});
678678

679679
it("Should report recovery state as Enabled", async () => {
@@ -722,7 +722,7 @@ describe("DeviceListener", () => {
722722
});
723723

724724
// no backup
725-
mockClient.getKeyBackupVersion.mockResolvedValue(null);
725+
mockCrypto.getKeyBackupInfo.mockResolvedValue(null);
726726

727727
await createAndStart();
728728

@@ -872,7 +872,7 @@ describe("DeviceListener", () => {
872872
describe("When Room Key Backup is enabled", () => {
873873
beforeEach(() => {
874874
// backup enabled - just need a mock object
875-
mockClient.getKeyBackupVersion.mockResolvedValue({} as KeyBackupInfo);
875+
mockCrypto.getKeyBackupInfo.mockResolvedValue({} as KeyBackupInfo);
876876
});
877877

878878
const testCases = [

test/unit-tests/components/structures/MatrixChat-test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ describe("<MatrixChat />", () => {
139139
globalBlacklistUnverifiedDevices: false,
140140
// This needs to not finish immediately because we need to test the screen appears
141141
bootstrapCrossSigning: jest.fn().mockImplementation(() => bootstrapDeferred.promise),
142+
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
142143
}),
143144
secretStorage: {
144145
isStored: jest.fn().mockReturnValue(null),
@@ -148,7 +149,6 @@ describe("<MatrixChat />", () => {
148149
whoami: jest.fn(),
149150
logout: jest.fn(),
150151
getDeviceId: jest.fn(),
151-
getKeyBackupVersion: jest.fn().mockResolvedValue(null),
152152
});
153153
let mockClient: Mocked<MatrixClient>;
154154
const serverConfig = {

test/unit-tests/components/views/dialogs/LogoutDialog-test.tsx

+3-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ describe("LogoutDialog", () => {
2222
beforeEach(() => {
2323
mockClient = getMockClientWithEventEmitter({
2424
...mockClientMethodsCrypto(),
25-
getKeyBackupVersion: jest.fn(),
2625
});
2726

2827
mockCrypto = mocked(mockClient.getCrypto()!);
@@ -50,14 +49,14 @@ describe("LogoutDialog", () => {
5049
});
5150

5251
it("Prompts user to connect backup if there is a backup on the server", async () => {
53-
mockClient.getKeyBackupVersion.mockResolvedValue({} as KeyBackupInfo);
52+
mockCrypto.getKeyBackupInfo.mockResolvedValue({} as KeyBackupInfo);
5453
const rendered = renderComponent();
5554
await rendered.findByText("Connect this session to Key Backup");
5655
expect(rendered.container).toMatchSnapshot();
5756
});
5857

5958
it("Prompts user to set up backup if there is no backup on the server", async () => {
60-
mockClient.getKeyBackupVersion.mockResolvedValue(null);
59+
mockCrypto.getKeyBackupInfo.mockResolvedValue(null);
6160
const rendered = renderComponent();
6261
await rendered.findByText("Start using Key Backup");
6362
expect(rendered.container).toMatchSnapshot();
@@ -69,7 +68,7 @@ describe("LogoutDialog", () => {
6968
describe("when there is an error fetching backups", () => {
7069
filterConsole("Unable to fetch key backup status");
7170
it("prompts user to set up backup", async () => {
72-
mockClient.getKeyBackupVersion.mockImplementation(async () => {
71+
mockCrypto.getKeyBackupInfo.mockImplementation(async () => {
7372
throw new Error("beep");
7473
});
7574
const rendered = renderComponent();

test/unit-tests/components/views/dialogs/security/CreateSecretStorageDialog-test.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ describe("CreateSecretStorageDialog", () => {
7777
filterConsole("Error fetching backup data from server");
7878

7979
it("shows an error", async () => {
80-
mockClient.getKeyBackupVersion.mockImplementation(async () => {
80+
jest.spyOn(mockClient.getCrypto()!, "getKeyBackupInfo").mockImplementation(async () => {
8181
throw new Error("bleh bleh");
8282
});
8383

@@ -92,7 +92,7 @@ describe("CreateSecretStorageDialog", () => {
9292
expect(result.container).toMatchSnapshot();
9393

9494
// Now we can get the backup and we retry
95-
mockClient.getKeyBackupVersion.mockRestore();
95+
jest.spyOn(mockClient.getCrypto()!, "getKeyBackupInfo").mockRestore();
9696
await userEvent.click(screen.getByRole("button", { name: "Retry" }));
9797
await screen.findByText("Your keys are now being backed up from this device.");
9898
});

test/unit-tests/components/views/dialogs/security/RestoreKeyBackupDialog-test.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ describe("<RestoreKeyBackupDialog />", () => {
2828
beforeEach(() => {
2929
matrixClient = stubClient();
3030
jest.spyOn(recoveryKeyModule, "decodeRecoveryKey").mockReturnValue(new Uint8Array(32));
31-
jest.spyOn(matrixClient, "getKeyBackupVersion").mockResolvedValue({ version: "1" } as KeyBackupInfo);
31+
jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockResolvedValue({ version: "1" } as KeyBackupInfo);
3232
});
3333

3434
it("should render", async () => {
@@ -99,7 +99,7 @@ describe("<RestoreKeyBackupDialog />", () => {
9999

100100
test("should restore key backup when passphrase is filled", async () => {
101101
// Determine that the passphrase is required
102-
jest.spyOn(matrixClient, "getKeyBackupVersion").mockResolvedValue({
102+
jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockResolvedValue({
103103
version: "1",
104104
auth_data: {
105105
private_key_salt: "salt",

test/unit-tests/components/views/settings/SecureBackupPanel-test.tsx

+8-10
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,13 @@ describe("<SecureBackupPanel />", () => {
2828
const client = getMockClientWithEventEmitter({
2929
...mockClientMethodsUser(userId),
3030
...mockClientMethodsCrypto(),
31-
getKeyBackupVersion: jest.fn().mockReturnValue("1"),
3231
getClientWellKnown: jest.fn(),
3332
});
3433

3534
const getComponent = () => render(<SecureBackupPanel />);
3635

3736
beforeEach(() => {
38-
client.getKeyBackupVersion.mockResolvedValue({
37+
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockResolvedValue({
3938
version: "1",
4039
algorithm: "test",
4140
auth_data: {
@@ -52,7 +51,6 @@ describe("<SecureBackupPanel />", () => {
5251
});
5352

5453
mocked(client.secretStorage.hasKey).mockClear().mockResolvedValue(false);
55-
client.getKeyBackupVersion.mockClear();
5654

5755
mocked(accessSecretStorage).mockClear().mockResolvedValue();
5856
});
@@ -65,8 +63,8 @@ describe("<SecureBackupPanel />", () => {
6563
});
6664

6765
it("handles error fetching backup", async () => {
68-
// getKeyBackupVersion can fail for various reasons
69-
client.getKeyBackupVersion.mockImplementation(async () => {
66+
// getKeyBackupInfo can fail for various reasons
67+
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockImplementation(async () => {
7068
throw new Error("beep beep");
7169
});
7270
const renderResult = getComponent();
@@ -75,9 +73,9 @@ describe("<SecureBackupPanel />", () => {
7573
});
7674

7775
it("handles absence of backup", async () => {
78-
client.getKeyBackupVersion.mockResolvedValue(null);
76+
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockResolvedValue(null);
7977
getComponent();
80-
// flush getKeyBackupVersion promise
78+
// flush getKeyBackupInfo promise
8179
await flushPromises();
8280
expect(screen.getByText("Back up your keys before signing out to avoid losing them.")).toBeInTheDocument();
8381
});
@@ -120,7 +118,7 @@ describe("<SecureBackupPanel />", () => {
120118
});
121119

122120
it("deletes backup after confirmation", async () => {
123-
client.getKeyBackupVersion
121+
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo")
124122
.mockResolvedValueOnce({
125123
version: "1",
126124
algorithm: "test",
@@ -157,7 +155,7 @@ describe("<SecureBackupPanel />", () => {
157155
// flush checkKeyBackup promise
158156
await flushPromises();
159157

160-
client.getKeyBackupVersion.mockClear();
158+
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockClear();
161159
mocked(client.getCrypto()!).isKeyBackupTrusted.mockClear();
162160

163161
fireEvent.click(screen.getByText("Reset"));
@@ -167,7 +165,7 @@ describe("<SecureBackupPanel />", () => {
167165
await flushPromises();
168166

169167
// backup status refreshed
170-
expect(client.getKeyBackupVersion).toHaveBeenCalled();
168+
expect(client.getCrypto()!.getKeyBackupInfo).toHaveBeenCalled();
171169
expect(client.getCrypto()!.isKeyBackupTrusted).toHaveBeenCalled();
172170
});
173171
});

test/unit-tests/components/views/settings/tabs/user/SecurityUserSettingsTab-test.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ describe("<SecurityUserSettingsTab />", () => {
3434
...mockClientMethodsCrypto(),
3535
getRooms: jest.fn().mockReturnValue([]),
3636
getIgnoredUsers: jest.fn(),
37-
getKeyBackupVersion: jest.fn(),
3837
});
3938

4039
const sdkContext = new SdkContextClass();

test/unit-tests/stores/SetupEncryptionStore-test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ describe("SetupEncryptionStore", () => {
3737
getDeviceVerificationStatus: jest.fn(),
3838
isDehydrationSupported: jest.fn().mockResolvedValue(false),
3939
startDehydration: jest.fn(),
40+
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
4041
} as unknown as Mocked<CryptoApi>;
4142
client.getCrypto.mockReturnValue(mockCrypto);
4243

0 commit comments

Comments
 (0)