From 46d13921d087f1b0bc042608107724ec96f2a720 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Mon, 21 Oct 2024 13:53:39 +0200 Subject: [PATCH] First batch: remove deprecated calls on `MatrixClient` (#28207) * Remove `initCrypto` mocking * Remove `MatrixClient.downloadKeys` mocking * Remove `MatrixClient.getStoredDevice` mocking * Replace `MatrixClient.setGlobalBlacklistUnverifiedDevices` by `MatrixClient.CryptoApi.globalBlacklistUnverifiedDevices` * Remove `MatrixClient.getStoredCrossSigningForUser` mocking * Replace `MatrixClient.legacyDeviceVerification` by `MatrixClient.CryptoApi.requestDeviceVerification` * Remove `MatrixClient.isCrossSigningReady` mock * Replace `MatrixClient.bootstrapCrossSigning` by `MatrixClient.getCrypto.bootstrapCrossSigning` * Replace `MatrixClient.getCryptoTrustCrossSignedDevices` by `MatrixClient.getCrypto.getTrustCrossSignedDevices` * Replace `MatrixClient.hasSecretStorageKey` by `MatrixClient.SecretStorage.hasKey` * Replace `MatrixClient.getDefaultSecretStorageKeyId` by `MatrixClient.SecretStorage.getDefaultKeyId` * Remove `MatrixClient.encryptAndSendToDevices` call --- src/SecurityManager.ts | 2 +- .../dialogs/security/CreateKeyBackupDialog.tsx | 2 +- src/components/structures/MatrixChat.tsx | 5 +++-- .../dialogs/security/AccessSecretStorageDialog.tsx | 2 +- .../dialogs/security/CreateCrossSigningDialog.tsx | 2 +- .../dialogs/security/RestoreKeyBackupDialog.tsx | 2 +- .../views/settings/CryptographyPanel.tsx | 3 ++- src/verification.ts | 11 ++++------- test/test-utils/client.ts | 2 -- test/test-utils/test-utils.ts | 7 +------ test/unit-tests/MatrixClientPeg-test.ts | 2 -- .../components/structures/MatrixChat-test.tsx | 8 +++++--- .../security/CreateKeyBackupDialog-test.tsx | 4 ++-- .../components/views/right_panel/UserInfo-test.tsx | 1 - .../views/settings/CrossSigningPanel-test.tsx | 1 - .../settings/tabs/user/SessionManagerTab-test.tsx | 14 -------------- .../toasts/UnverifiedSessionToast-test.tsx | 9 --------- 17 files changed, 22 insertions(+), 55 deletions(-) diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts index 2d103cf25e..4717404222 100644 --- a/src/SecurityManager.ts +++ b/src/SecurityManager.ts @@ -76,7 +76,7 @@ async function getSecretStorageKey({ keys: Record; }): Promise<[string, Uint8Array]> { const cli = MatrixClientPeg.safeGet(); - let keyId = await cli.getDefaultSecretStorageKeyId(); + let keyId = await cli.secretStorage.getDefaultKeyId(); let keyInfo!: SecretStorage.SecretStorageKeyDescription; if (keyId) { // use the default SSSS key if set diff --git a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx index 3ec62c3df5..9608abc4bc 100644 --- a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx +++ b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.tsx @@ -69,7 +69,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { } } - if (cli.getCrypto()) { + const crypto = cli.getCrypto(); + if (crypto) { const blacklistEnabled = SettingsStore.getValueAt(SettingLevel.DEVICE, "blacklistUnverifiedDevices"); - cli.setGlobalBlacklistUnverifiedDevices(blacklistEnabled); + crypto.globalBlacklistUnverifiedDevices = blacklistEnabled; // With cross-signing enabled, we send to unknown devices // without prompting. Any bad-device status the user should diff --git a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx index 50b728f4da..7361e3982d 100644 --- a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx +++ b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx @@ -229,7 +229,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent => { // Now reset cross-signing so everything Just Works™ again. const cli = MatrixClientPeg.safeGet(); - await cli.bootstrapCrossSigning({ + await cli.getCrypto()?.bootstrapCrossSigning({ authUploadDeviceSigningKeys: async (makeRequest): Promise => { const { finished } = Modal.createDialog(InteractiveAuthDialog, { title: _t("encryption|bootstrap_title"), diff --git a/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx b/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx index bc5bc6b21e..69b13a93c9 100644 --- a/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx +++ b/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx @@ -137,7 +137,7 @@ export default class CreateCrossSigningDialog extends React.PureComponent { }; private updateBlacklistDevicesFlag = (checked: boolean): void => { - MatrixClientPeg.safeGet().setGlobalBlacklistUnverifiedDevices(checked); + const crypto = MatrixClientPeg.safeGet().getCrypto(); + if (crypto) crypto.globalBlacklistUnverifiedDevices = checked; }; } diff --git a/src/verification.ts b/src/verification.ts index f043e099d8..e446186f80 100644 --- a/src/verification.ts +++ b/src/verification.ts @@ -7,7 +7,6 @@ Please see LICENSE files in the repository root for full details. */ import { User, MatrixClient, RoomMember } from "matrix-js-sdk/src/matrix"; -import { VerificationMethod } from "matrix-js-sdk/src/types"; import { CrossSigningKey, VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import dis from "./dispatcher/dispatcher"; @@ -39,7 +38,7 @@ export async function verifyDevice(matrixClient: MatrixClient, user: User, devic return; } // if cross-signing is not explicitly disabled, check if it should be enabled first. - if (matrixClient.getCryptoTrustCrossSignedDevices()) { + if (matrixClient.getCrypto()?.getTrustCrossSignedDevices()) { if (!(await enable4SIfNeeded(matrixClient))) { return; } @@ -50,11 +49,9 @@ export async function verifyDevice(matrixClient: MatrixClient, user: User, devic device, onFinished: async (action): Promise => { if (action === "sas") { - const verificationRequestPromise = matrixClient.legacyDeviceVerification( - user.userId, - device.deviceId, - VerificationMethod.Sas, - ); + const verificationRequestPromise = matrixClient + .getCrypto() + ?.requestDeviceVerification(user.userId, device.deviceId); setRightPanel({ member: user, verificationRequestPromise }); } else if (action === "legacy") { Modal.createDialog(ManualDeviceKeyVerificationDialog, { diff --git a/test/test-utils/client.ts b/test/test-utils/client.ts index 7b0e22e70e..0a5798d8a1 100644 --- a/test/test-utils/client.ts +++ b/test/test-utils/client.ts @@ -141,10 +141,8 @@ export const mockClientMethodsDevice = ( export const mockClientMethodsCrypto = (): Partial< Record & PropertyLikeKeys, unknown> > => ({ - isCrossSigningReady: jest.fn(), isKeyBackupKeyStored: jest.fn(), getCrossSigningCacheCallbacks: jest.fn().mockReturnValue({ getCrossSigningKeyCache: jest.fn() }), - getStoredCrossSigningForUser: jest.fn(), getKeyBackupVersion: jest.fn().mockResolvedValue(null), secretStorage: { hasKey: jest.fn() }, getCrypto: jest.fn().mockReturnValue({ diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index e34af523ee..6dc9533ac9 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -95,20 +95,17 @@ export function createTestClient(): MatrixClient { getUser: jest.fn().mockReturnValue({ on: jest.fn(), off: jest.fn() }), getDevice: jest.fn(), getDeviceId: jest.fn().mockReturnValue("ABCDEFGHI"), - getStoredCrossSigningForUser: jest.fn(), - getStoredDevice: jest.fn(), deviceId: "ABCDEFGHI", getDevices: jest.fn().mockResolvedValue({ devices: [{ device_id: "ABCDEFGHI" }] }), getSessionId: jest.fn().mockReturnValue("iaszphgvfku"), credentials: { userId: "@userId:matrix.org" }, - bootstrapCrossSigning: jest.fn(), - hasSecretStorageKey: jest.fn(), getKeyBackupVersion: jest.fn(), secretStorage: { get: jest.fn(), isStored: jest.fn().mockReturnValue(false), checkKey: jest.fn().mockResolvedValue(false), + hasKey: jest.fn().mockReturnValue(false), }, store: { @@ -208,12 +205,10 @@ export function createTestClient(): MatrixClient { }), hasLazyLoadMembersEnabled: jest.fn().mockReturnValue(false), isInitialSyncComplete: jest.fn().mockReturnValue(true), - downloadKeys: jest.fn(), fetchRoomEvent: jest.fn().mockRejectedValue({}), makeTxnId: jest.fn().mockImplementation(() => `t${txnId++}`), sendToDevice: jest.fn().mockResolvedValue(undefined), queueToDevice: jest.fn().mockResolvedValue(undefined), - encryptAndSendToDevices: jest.fn().mockResolvedValue(undefined), cancelPendingEvent: jest.fn(), getMediaHandler: jest.fn().mockReturnValue({ diff --git a/test/unit-tests/MatrixClientPeg-test.ts b/test/unit-tests/MatrixClientPeg-test.ts index efa624349a..5a19b568c0 100644 --- a/test/unit-tests/MatrixClientPeg-test.ts +++ b/test/unit-tests/MatrixClientPeg-test.ts @@ -83,12 +83,10 @@ describe("MatrixClientPeg", () => { it("should initialise the rust crypto library by default", async () => { const mockSetValue = jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined); - const mockInitCrypto = jest.spyOn(testPeg.safeGet(), "initCrypto").mockResolvedValue(undefined); const mockInitRustCrypto = jest.spyOn(testPeg.safeGet(), "initRustCrypto").mockResolvedValue(undefined); const cryptoStoreKey = new Uint8Array([1, 2, 3, 4]); await testPeg.start({ rustCryptoStoreKey: cryptoStoreKey }); - expect(mockInitCrypto).not.toHaveBeenCalled(); expect(mockInitRustCrypto).toHaveBeenCalledWith({ storageKey: cryptoStoreKey }); // we should have stashed the setting in the settings store diff --git a/test/unit-tests/components/structures/MatrixChat-test.tsx b/test/unit-tests/components/structures/MatrixChat-test.tsx index da6e005a23..def72a11f8 100644 --- a/test/unit-tests/components/structures/MatrixChat-test.tsx +++ b/test/unit-tests/components/structures/MatrixChat-test.tsx @@ -125,7 +125,6 @@ describe("", () => { }), getVisibleRooms: jest.fn().mockReturnValue([]), getRooms: jest.fn().mockReturnValue([]), - setGlobalBlacklistUnverifiedDevices: jest.fn(), setGlobalErrorOnUnknownDevices: jest.fn(), getCrypto: jest.fn().mockReturnValue({ getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]), @@ -136,9 +135,10 @@ describe("", () => { setDeviceIsolationMode: jest.fn(), userHasCrossSigningKeys: jest.fn(), getActiveSessionBackupVersion: jest.fn().mockResolvedValue(null), + globalBlacklistUnverifiedDevices: false, + // This needs to not finish immediately because we need to test the screen appears + bootstrapCrossSigning: jest.fn().mockImplementation(() => bootstrapDeferred.promise), }), - // This needs to not finish immediately because we need to test the screen appears - bootstrapCrossSigning: jest.fn().mockImplementation(() => bootstrapDeferred.promise), secretStorage: { isStored: jest.fn().mockReturnValue(null), }, @@ -1011,6 +1011,8 @@ describe("", () => { .mockResolvedValue(new UserVerificationStatus(false, false, false)), setDeviceIsolationMode: jest.fn(), userHasCrossSigningKeys: jest.fn().mockResolvedValue(false), + // This needs to not finish immediately because we need to test the screen appears + bootstrapCrossSigning: jest.fn().mockImplementation(() => bootstrapDeferred.promise), }; loginClient.getCrypto.mockReturnValue(mockCrypto as any); }); diff --git a/test/unit-tests/components/views/dialogs/security/CreateKeyBackupDialog-test.tsx b/test/unit-tests/components/views/dialogs/security/CreateKeyBackupDialog-test.tsx index 183e282d8b..6e0542448b 100644 --- a/test/unit-tests/components/views/dialogs/security/CreateKeyBackupDialog-test.tsx +++ b/test/unit-tests/components/views/dialogs/security/CreateKeyBackupDialog-test.tsx @@ -34,7 +34,7 @@ describe("CreateKeyBackupDialog", () => { it("should display an error message when backup creation failed", async () => { const matrixClient = createTestClient(); - mocked(matrixClient.hasSecretStorageKey).mockResolvedValue(true); + jest.spyOn(matrixClient.secretStorage, "hasKey").mockResolvedValue(true); mocked(matrixClient.getCrypto()!.resetKeyBackup).mockImplementation(() => { throw new Error("failed"); }); @@ -49,7 +49,7 @@ describe("CreateKeyBackupDialog", () => { it("should display an error message when there is no Crypto available", async () => { const matrixClient = createTestClient(); - mocked(matrixClient.hasSecretStorageKey).mockResolvedValue(true); + jest.spyOn(matrixClient.secretStorage, "hasKey").mockResolvedValue(true); mocked(matrixClient.getCrypto).mockReturnValue(undefined); MatrixClientPeg.safeGet = MatrixClientPeg.get = () => matrixClient; diff --git a/test/unit-tests/components/views/right_panel/UserInfo-test.tsx b/test/unit-tests/components/views/right_panel/UserInfo-test.tsx index e0bfe10c86..c9996d7d67 100644 --- a/test/unit-tests/components/views/right_panel/UserInfo-test.tsx +++ b/test/unit-tests/components/views/right_panel/UserInfo-test.tsx @@ -160,7 +160,6 @@ beforeEach(() => { getRoom: jest.fn(), credentials: {}, setPowerLevel: jest.fn(), - downloadKeys: jest.fn(), getCrypto: jest.fn().mockReturnValue(mockCrypto), } as unknown as MatrixClient); diff --git a/test/unit-tests/components/views/settings/CrossSigningPanel-test.tsx b/test/unit-tests/components/views/settings/CrossSigningPanel-test.tsx index 0b7a680093..daa3570ed2 100644 --- a/test/unit-tests/components/views/settings/CrossSigningPanel-test.tsx +++ b/test/unit-tests/components/views/settings/CrossSigningPanel-test.tsx @@ -34,7 +34,6 @@ describe("", () => { }); mockClient.doesServerSupportUnstableFeature.mockResolvedValue(true); - mockClient.isCrossSigningReady.mockResolvedValue(false); }); afterEach(() => { diff --git a/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx b/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx index aec661120f..3ff0084ef9 100644 --- a/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx +++ b/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx @@ -17,7 +17,6 @@ import { waitForElementToBeRemoved, within, } from "jest-matrix-react"; -import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo"; import { logger } from "matrix-js-sdk/src/logger"; import { CryptoApi, DeviceVerificationStatus, VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import { defer, sleep } from "matrix-js-sdk/src/utils"; @@ -205,7 +204,6 @@ describe("", () => { ...mockClientMethodsServer(), getCrypto: jest.fn().mockReturnValue(mockCrypto), getDevices: jest.fn(), - getStoredDevice: jest.fn(), getDeviceId: jest.fn().mockReturnValue(deviceId), deleteMultipleDevices: jest.fn(), generateClientSecret: jest.fn(), @@ -220,10 +218,6 @@ describe("", () => { }); jest.clearAllMocks(); jest.spyOn(logger, "error").mockRestore(); - mockClient.getStoredDevice.mockImplementation((_userId, id) => { - const device = [alicesDevice, alicesMobileDevice].find((device) => device.device_id === id); - return device ? new DeviceInfo(device.device_id) : null; - }); mockCrypto.getDeviceVerificationStatus.mockReset().mockResolvedValue(new DeviceVerificationStatus({})); mockClient.getDevices.mockReset().mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] }); @@ -292,7 +286,6 @@ describe("", () => { mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice, alicesOlderMobileDevice], }); - mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId)); mockCrypto.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => { // alices device is trusted if (deviceId === alicesDevice.device_id) { @@ -464,7 +457,6 @@ describe("", () => { mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice], }); - mockClient.getStoredDevice.mockImplementation(() => new DeviceInfo(alicesDevice.device_id)); mockCrypto.getDeviceVerificationStatus.mockResolvedValue( new DeviceVerificationStatus({ crossSigningVerified: true, localVerified: true }), ); @@ -568,7 +560,6 @@ describe("", () => { mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice], }); - mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId)); mockCrypto.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => { if (deviceId === alicesDevice.device_id) { return new DeviceVerificationStatus({ crossSigningVerified: true, localVerified: true }); @@ -595,7 +586,6 @@ describe("", () => { mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice], }); - mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId)); mockCrypto.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => { // current session verified = able to verify other sessions if (deviceId === alicesDevice.device_id) { @@ -629,7 +619,6 @@ describe("", () => { mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice], }); - mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId)); mockCrypto.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => { if (deviceId === alicesDevice.device_id) { return new DeviceVerificationStatus({ crossSigningVerified: true, localVerified: true }); @@ -667,7 +656,6 @@ describe("", () => { mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice, alicesDehydratedDevice], }); - mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId)); const devicesMap = new Map([ [alicesDeviceObj.deviceId, alicesDeviceObj], @@ -708,7 +696,6 @@ describe("", () => { mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice, alicesDehydratedDevice], }); - mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId)); const devicesMap = new Map([ [alicesDeviceObj.deviceId, alicesDeviceObj], @@ -749,7 +736,6 @@ describe("", () => { mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice, alicesDehydratedDevice, alicesOtherDehydratedDevice], }); - mockClient.getStoredDevice.mockImplementation((_userId, deviceId) => new DeviceInfo(deviceId)); const devicesMap = new Map([ [alicesDeviceObj.deviceId, alicesDeviceObj], diff --git a/test/unit-tests/toasts/UnverifiedSessionToast-test.tsx b/test/unit-tests/toasts/UnverifiedSessionToast-test.tsx index ddb8a6f7b8..c7df2a0e6e 100644 --- a/test/unit-tests/toasts/UnverifiedSessionToast-test.tsx +++ b/test/unit-tests/toasts/UnverifiedSessionToast-test.tsx @@ -11,7 +11,6 @@ import { render, RenderResult, screen } from "jest-matrix-react"; import userEvent from "@testing-library/user-event"; import { mocked, Mocked } from "jest-mock"; import { IMyDevice, MatrixClient } from "matrix-js-sdk/src/matrix"; -import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo"; import { CryptoApi, DeviceVerificationStatus } from "matrix-js-sdk/src/crypto-api"; import dis from "../../../src/dispatcher/dispatcher"; @@ -25,7 +24,6 @@ describe("UnverifiedSessionToast", () => { const otherDevice: IMyDevice = { device_id: "ABC123", }; - const otherDeviceInfo = new DeviceInfo(otherDevice.device_id); let client: Mocked; let renderResult: RenderResult; @@ -40,13 +38,6 @@ describe("UnverifiedSessionToast", () => { throw new Error(`Unknown device ${deviceId}`); }); - client.getStoredDevice.mockImplementation((userId: string, deviceId: string) => { - if (deviceId === otherDevice.device_id) { - return otherDeviceInfo; - } - - return null; - }); client.getCrypto.mockReturnValue({ getDeviceVerificationStatus: jest .fn()