Skip to content

Commit

Permalink
Use CryptoApi.getKeyBackupInfo instead of deprecated `MatrixClient.…
Browse files Browse the repository at this point in the history
…getKeyBackupVersion`
  • Loading branch information
florianduros committed Nov 12, 2024
1 parent 6bc8080 commit 4bfe8e2
Show file tree
Hide file tree
Showing 14 changed files with 32 additions and 34 deletions.
10 changes: 6 additions & 4 deletions src/DeviceListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,14 @@ export default class DeviceListener {
private async getKeyBackupInfo(): Promise<KeyBackupInfo | null> {
if (!this.client) return null;
const now = new Date().getTime();
const crypto = this.client.getCrypto();
if (
!this.keyBackupInfo ||
!this.keyBackupFetchedAt ||
this.keyBackupFetchedAt < now - KEY_BACKUP_POLL_INTERVAL
crypto &&
(!this.keyBackupInfo ||
!this.keyBackupFetchedAt ||
this.keyBackupFetchedAt < now - KEY_BACKUP_POLL_INTERVAL)
) {
this.keyBackupInfo = await this.client.getKeyBackupVersion();
this.keyBackupInfo = await crypto.getKeyBackupInfo();

Check failure on line 239 in src/DeviceListener.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'CryptoApi'.
this.keyBackupFetchedAt = now;
}
return this.keyBackupInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
if (!forceReset) {
try {
this.setState({ phase: Phase.Loading });
backupInfo = await cli.getKeyBackupVersion();
backupInfo = await crypto.getKeyBackupInfo();

Check failure on line 280 in src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'CryptoApi'.
} catch (e) {
logger.error("Error fetching backup data from server", e);
this.setState({ phase: Phase.LoadError });
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} else {
// otherwise check the server to see if there's a new one
try {
newVersionInfo = await cli.getKeyBackupVersion();
newVersionInfo = (await cli.getCrypto()?.getKeyBackupInfo()) || null;

Check failure on line 1643 in src/components/structures/MatrixChat.tsx

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'CryptoApi'.
if (newVersionInfo !== null) haveNewVersion = true;
} catch (e) {
logger.error("Saw key backup error but failed to check backup version!", e);
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/dialogs/LogoutDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default class LogoutDialog extends React.Component<IProps, IState> {
}

// backup is not active. see if there is a backup version on the server we ought to back up to.
const backupInfo = await client.getKeyBackupVersion();
const backupInfo = await crypto.getKeyBackupInfo();

Check failure on line 114 in src/components/views/dialogs/LogoutDialog.tsx

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'CryptoApi'.
this.setState({ backupStatus: backupInfo ? BackupStatus.SERVER_BACKUP_BUT_DISABLED : BackupStatus.NO_BACKUP });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
});
try {
const cli = MatrixClientPeg.safeGet();
const backupInfo = await cli.getKeyBackupVersion();
const backupInfo = (await cli.getCrypto()?.getKeyBackupInfo()) || null;

Check failure on line 268 in src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'CryptoApi'.
const has4S = await cli.secretStorage.hasKey();
const backupKeyStored = has4S ? await cli.isKeyBackupKeyStored() : null;
this.setState({
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/settings/SecureBackupPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
this.getUpdatedDiagnostics();
try {
const cli = MatrixClientPeg.safeGet();
const backupInfo = await cli.getKeyBackupVersion();
const backupInfo = (await cli.getCrypto()?.getKeyBackupInfo()) || null;

Check failure on line 122 in src/components/views/settings/SecureBackupPanel.tsx

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'CryptoApi'.
const backupTrustInfo = backupInfo ? await cli.getCrypto()?.isKeyBackupTrusted(backupInfo) : undefined;

const activeBackupVersion = (await cli.getCrypto()?.getActiveSessionBackupVersion()) ?? null;
Expand Down
2 changes: 1 addition & 1 deletion src/stores/SetupEncryptionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export class SetupEncryptionStore extends EventEmitter {
this.emit("update");
try {
const cli = MatrixClientPeg.safeGet();
const backupInfo = await cli.getKeyBackupVersion();
const backupInfo = (await cli.getCrypto()?.getKeyBackupInfo()) || null;

Check failure on line 131 in src/stores/SetupEncryptionStore.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'CryptoApi'.
this.backupInfo = backupInfo;
this.emit("update");

Expand Down
2 changes: 1 addition & 1 deletion test/test-utils/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ export const mockClientMethodsCrypto = (): Partial<
> => ({
isKeyBackupKeyStored: jest.fn(),
getCrossSigningCacheCallbacks: jest.fn().mockReturnValue({ getCrossSigningKeyCache: jest.fn() }),
getKeyBackupVersion: jest.fn().mockResolvedValue(null),
secretStorage: { hasKey: jest.fn() },
getCrypto: jest.fn().mockReturnValue({
getUserDeviceInfo: jest.fn(),
Expand All @@ -162,6 +161,7 @@ export const mockClientMethodsCrypto = (): Partial<
getVersion: jest.fn().mockReturnValue("Version 0"),
getOwnDeviceKeys: jest.fn().mockReturnValue(new Promise(() => {})),
getCrossSigningKeyId: jest.fn(),
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
}),
});

Expand Down
2 changes: 1 addition & 1 deletion test/test-utils/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ export function createTestClient(): MatrixClient {
getDevices: jest.fn().mockResolvedValue({ devices: [{ device_id: "ABCDEFGHI" }] }),
getSessionId: jest.fn().mockReturnValue("iaszphgvfku"),
credentials: { userId: "@userId:matrix.org" },
getKeyBackupVersion: jest.fn(),

secretStorage: {
get: jest.fn(),
Expand Down Expand Up @@ -131,6 +130,7 @@ export function createTestClient(): MatrixClient {
createRecoveryKeyFromPassphrase: jest.fn().mockResolvedValue({}),
bootstrapSecretStorage: jest.fn(),
isDehydrationSupported: jest.fn().mockResolvedValue(false),
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
}),

getPushActionsForEvent: jest.fn(),
Expand Down
10 changes: 5 additions & 5 deletions test/unit-tests/DeviceListener-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,12 @@ describe("DeviceListener", () => {
},
}),
getSessionBackupPrivateKey: jest.fn(),
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
} as unknown as Mocked<CryptoApi>;
mockClient = getMockClientWithEventEmitter({
isGuest: jest.fn(),
getUserId: jest.fn().mockReturnValue(userId),
getSafeUserId: jest.fn().mockReturnValue(userId),
getKeyBackupVersion: jest.fn().mockResolvedValue(undefined),
getRooms: jest.fn().mockReturnValue([]),
isVersionSupported: jest.fn().mockResolvedValue(true),
isInitialSyncComplete: jest.fn().mockReturnValue(true),
Expand Down Expand Up @@ -354,7 +354,7 @@ describe("DeviceListener", () => {

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

Check failure on line 357 in test/unit-tests/DeviceListener-test.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'MockedObject<CryptoApi>'.
await createAndStart();

expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith(
Expand Down Expand Up @@ -673,7 +673,7 @@ describe("DeviceListener", () => {
describe("When Room Key Backup is not enabled", () => {
beforeEach(() => {
// no backup
mockClient.getKeyBackupVersion.mockResolvedValue(null);
mockCrypto.getKeyBackupInfo.mockResolvedValue(null);

Check failure on line 676 in test/unit-tests/DeviceListener-test.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'MockedObject<CryptoApi>'.
});

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

// no backup
mockClient.getKeyBackupVersion.mockResolvedValue(null);
mockCrypto.getKeyBackupInfo.mockResolvedValue(null);

Check failure on line 725 in test/unit-tests/DeviceListener-test.ts

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

Property 'getKeyBackupInfo' does not exist on type 'MockedObject<CryptoApi>'.

await createAndStart();

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

const testCases = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ describe("LogoutDialog", () => {
beforeEach(() => {
mockClient = getMockClientWithEventEmitter({
...mockClientMethodsCrypto(),
getKeyBackupVersion: jest.fn(),
});

mockCrypto = mocked(mockClient.getCrypto()!);
Expand Down Expand Up @@ -50,14 +49,14 @@ describe("LogoutDialog", () => {
});

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

it("Prompts user to set up backup if there is no backup on the server", async () => {
mockClient.getKeyBackupVersion.mockResolvedValue(null);
mockCrypto.getKeyBackupInfo.mockResolvedValue(null);
const rendered = renderComponent();
await rendered.findByText("Start using Key Backup");
expect(rendered.container).toMatchSnapshot();
Expand All @@ -66,7 +65,7 @@ describe("LogoutDialog", () => {
describe("when there is an error fetching backups", () => {
filterConsole("Unable to fetch key backup status");
it("prompts user to set up backup", async () => {
mockClient.getKeyBackupVersion.mockImplementation(async () => {
mockCrypto.getKeyBackupInfo.mockImplementation(async () => {
throw new Error("beep");
});
const rendered = renderComponent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ describe("CreateSecretStorageDialog", () => {
filterConsole("Error fetching backup data from server");

it("shows an error", async () => {
mockClient.getKeyBackupVersion.mockImplementation(async () => {
jest.spyOn(mockClient.getCrypto()!, "getKeyBackupInfo").mockImplementation(async () => {
throw new Error("bleh bleh");
});

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

// Now we can get the backup and we retry
mockClient.getKeyBackupVersion.mockRestore();
jest.spyOn(mockClient.getCrypto()!, "getKeyBackupInfo").mockRestore();
await userEvent.click(screen.getByRole("button", { name: "Retry" }));
await screen.findByText("Your keys are now being backed up from this device.");
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@ describe("<SecureBackupPanel />", () => {
const client = getMockClientWithEventEmitter({
...mockClientMethodsUser(userId),
...mockClientMethodsCrypto(),
getKeyBackupVersion: jest.fn().mockReturnValue("1"),
getClientWellKnown: jest.fn(),
});

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

beforeEach(() => {
client.getKeyBackupVersion.mockResolvedValue({
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockResolvedValue({
version: "1",
algorithm: "test",
auth_data: {
Expand All @@ -52,7 +51,6 @@ describe("<SecureBackupPanel />", () => {
});

mocked(client.secretStorage.hasKey).mockClear().mockResolvedValue(false);
client.getKeyBackupVersion.mockClear();

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

it("handles error fetching backup", async () => {
// getKeyBackupVersion can fail for various reasons
client.getKeyBackupVersion.mockImplementation(async () => {
// getKeyBackupInfo can fail for various reasons
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockImplementation(async () => {
throw new Error("beep beep");
});
const renderResult = getComponent();
Expand All @@ -75,9 +73,9 @@ describe("<SecureBackupPanel />", () => {
});

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

it("deletes backup after confirmation", async () => {
client.getKeyBackupVersion
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo")
.mockResolvedValueOnce({
version: "1",
algorithm: "test",
Expand Down Expand Up @@ -157,7 +155,7 @@ describe("<SecureBackupPanel />", () => {
// flush checkKeyBackup promise
await flushPromises();

client.getKeyBackupVersion.mockClear();
jest.spyOn(client.getCrypto()!, "getKeyBackupInfo").mockClear();
mocked(client.getCrypto()!).isKeyBackupTrusted.mockClear();

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

// backup status refreshed
expect(client.getKeyBackupVersion).toHaveBeenCalled();
expect(client.getCrypto()!.getKeyBackupInfo).toHaveBeenCalled();
expect(client.getCrypto()!.isKeyBackupTrusted).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ describe("<SecurityUserSettingsTab />", () => {
...mockClientMethodsCrypto(),
getRooms: jest.fn().mockReturnValue([]),
getIgnoredUsers: jest.fn(),
getKeyBackupVersion: jest.fn(),
});

const sdkContext = new SdkContextClass();
Expand Down

0 comments on commit 4bfe8e2

Please sign in to comment.