Settings panels: avoid exceptions with rust crypto (#10962)

* Settings panels: avoid exceptions with rust crypto

If we are using rust crypto, `client.crypto` is undefined. We'll need to fix
these up better in future, but for now, just return early.

* Update tests
pull/28788/head^2
Richard van der Hoff 2023-05-23 13:01:27 +01:00 committed by GitHub
parent 7c34d66bde
commit 161e19dfb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 20 additions and 14 deletions

View File

@ -90,9 +90,12 @@ export default class CrossSigningPanel extends React.PureComponent<{}, IState> {
private async getUpdatedStatus(): Promise<void> { private async getUpdatedStatus(): Promise<void> {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const crypto = cli.crypto;
if (!crypto) return;
const pkCache = cli.getCrossSigningCacheCallbacks(); const pkCache = cli.getCrossSigningCacheCallbacks();
const crossSigning = cli.crypto!.crossSigningInfo; const crossSigning = crypto.crossSigningInfo;
const secretStorage = cli.crypto!.secretStorage; const secretStorage = cli.secretStorage;
const crossSigningPublicKeysOnDevice = Boolean(crossSigning.getId()); const crossSigningPublicKeysOnDevice = Boolean(crossSigning.getId());
const crossSigningPrivateKeysInStorage = Boolean(await crossSigning.isStoredInSecretStorage(secretStorage)); const crossSigningPrivateKeysInStorage = Boolean(await crossSigning.isStoredInSecretStorage(secretStorage));
const masterPrivateKeyCached = !!(await pkCache?.getCrossSigningKeyCache?.("master")); const masterPrivateKeyCached = !!(await pkCache?.getCrossSigningKeyCache?.("master"));

View File

@ -146,14 +146,17 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
private async getUpdatedDiagnostics(): Promise<void> { private async getUpdatedDiagnostics(): Promise<void> {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const secretStorage = cli.crypto!.secretStorage; const crypto = cli.crypto;
if (!crypto) return;
const secretStorage = cli.secretStorage;
const backupKeyStored = !!(await cli.isKeyBackupKeyStored()); const backupKeyStored = !!(await cli.isKeyBackupKeyStored());
const backupKeyFromCache = await cli.crypto!.getSessionBackupPrivateKey(); const backupKeyFromCache = await crypto.getSessionBackupPrivateKey();
const backupKeyCached = !!backupKeyFromCache; const backupKeyCached = !!backupKeyFromCache;
const backupKeyWellFormed = backupKeyFromCache instanceof Uint8Array; const backupKeyWellFormed = backupKeyFromCache instanceof Uint8Array;
const secretStorageKeyInAccount = await secretStorage.hasKey(); const secretStorageKeyInAccount = await secretStorage.hasKey();
const secretStorageReady = await cli.isSecretStorageReady(); const secretStorageReady = await crypto.isSecretStorageReady();
if (this.unmounted) return; if (this.unmounted) return;
this.setState({ this.setState({

View File

@ -79,7 +79,7 @@ describe("<CrossSigningPanel />", () => {
expect(screen.getByTestId("summarised-status").innerHTML).toEqual("✅ Cross-signing is ready for use."); expect(screen.getByTestId("summarised-status").innerHTML).toEqual("✅ Cross-signing is ready for use.");
expect(screen.getByText("Cross-signing private keys:").parentElement!).toMatchSnapshot(); expect(screen.getByText("Cross-signing private keys:").parentElement!).toMatchSnapshot();
expect(mockClient.crypto!.crossSigningInfo.isStoredInSecretStorage).toHaveBeenCalledWith( expect(mockClient.crypto!.crossSigningInfo.isStoredInSecretStorage).toHaveBeenCalledWith(
mockClient.crypto!.secretStorage, mockClient.secretStorage,
); );
}); });
}); });
@ -106,7 +106,7 @@ describe("<CrossSigningPanel />", () => {
); );
expect(screen.getByText("Cross-signing private keys:").parentElement!).toMatchSnapshot(); expect(screen.getByText("Cross-signing private keys:").parentElement!).toMatchSnapshot();
expect(mockClient.crypto!.crossSigningInfo.isStoredInSecretStorage).toHaveBeenCalledWith( expect(mockClient.crypto!.crossSigningInfo.isStoredInSecretStorage).toHaveBeenCalledWith(
mockClient.crypto!.secretStorage, mockClient.secretStorage,
); );
}); });
}); });

View File

@ -32,17 +32,17 @@ describe("<SecureBackupPanel />", () => {
...mockClientMethodsUser(userId), ...mockClientMethodsUser(userId),
checkKeyBackup: jest.fn(), checkKeyBackup: jest.fn(),
isKeyBackupKeyStored: jest.fn(), isKeyBackupKeyStored: jest.fn(),
isSecretStorageReady: jest.fn(),
getKeyBackupEnabled: jest.fn(), getKeyBackupEnabled: jest.fn(),
getKeyBackupVersion: jest.fn().mockReturnValue("1"), getKeyBackupVersion: jest.fn().mockReturnValue("1"),
isKeyBackupTrusted: jest.fn().mockResolvedValue(true), isKeyBackupTrusted: jest.fn().mockResolvedValue(true),
getClientWellKnown: jest.fn(), getClientWellKnown: jest.fn(),
deleteKeyBackupVersion: jest.fn(), deleteKeyBackupVersion: jest.fn(),
secretStorage: { hasKey: jest.fn() },
}); });
// @ts-ignore allow it // @ts-ignore allow it
client.crypto = { client.crypto = {
secretStorage: { hasKey: jest.fn() },
getSessionBackupPrivateKey: jest.fn(), getSessionBackupPrivateKey: jest.fn(),
isSecretStorageReady: jest.fn(),
} as unknown as Crypto; } as unknown as Crypto;
const getComponent = () => render(<SecureBackupPanel />); const getComponent = () => render(<SecureBackupPanel />);
@ -62,7 +62,7 @@ describe("<SecureBackupPanel />", () => {
}, },
}); });
mocked(client.crypto!.secretStorage.hasKey).mockClear().mockResolvedValue(false); mocked(client.secretStorage.hasKey).mockClear().mockResolvedValue(false);
client.deleteKeyBackupVersion.mockClear().mockResolvedValue(); client.deleteKeyBackupVersion.mockClear().mockResolvedValue();
client.getKeyBackupVersion.mockClear(); client.getKeyBackupVersion.mockClear();
client.isKeyBackupTrusted.mockClear(); client.isKeyBackupTrusted.mockClear();
@ -166,7 +166,7 @@ describe("<SecureBackupPanel />", () => {
}); });
it("resets secret storage", async () => { it("resets secret storage", async () => {
mocked(client.crypto!.secretStorage.hasKey).mockClear().mockResolvedValue(true); mocked(client.secretStorage.hasKey).mockClear().mockResolvedValue(true);
getComponent(); getComponent();
// flush checkKeyBackup promise // flush checkKeyBackup promise
await flushPromises(); await flushPromises();

View File

@ -66,7 +66,7 @@ export class MockClientWithEventEmitter extends EventEmitter {
* ``` * ```
*/ */
export const getMockClientWithEventEmitter = ( export const getMockClientWithEventEmitter = (
mockProperties: Partial<Record<MethodLikeKeys<MatrixClient>, unknown>>, mockProperties: Partial<Record<keyof MatrixClient, unknown>>,
): MockedObject<MatrixClient> => { ): MockedObject<MatrixClient> => {
const mock = mocked(new MockClientWithEventEmitter(mockProperties) as unknown as MatrixClient); const mock = mocked(new MockClientWithEventEmitter(mockProperties) as unknown as MatrixClient);
@ -143,15 +143,15 @@ export const mockClientMethodsCrypto = (): Partial<
Record<MethodLikeKeys<MatrixClient> & PropertyLikeKeys<MatrixClient>, unknown> Record<MethodLikeKeys<MatrixClient> & PropertyLikeKeys<MatrixClient>, unknown>
> => ({ > => ({
isCryptoEnabled: jest.fn(), isCryptoEnabled: jest.fn(),
isSecretStorageReady: jest.fn(),
isCrossSigningReady: jest.fn(), isCrossSigningReady: jest.fn(),
isKeyBackupKeyStored: jest.fn(), isKeyBackupKeyStored: jest.fn(),
getCrossSigningCacheCallbacks: jest.fn().mockReturnValue({ getCrossSigningKeyCache: jest.fn() }), getCrossSigningCacheCallbacks: jest.fn().mockReturnValue({ getCrossSigningKeyCache: jest.fn() }),
getStoredCrossSigningForUser: jest.fn(), getStoredCrossSigningForUser: jest.fn(),
checkKeyBackup: jest.fn().mockReturnValue({}), checkKeyBackup: jest.fn().mockReturnValue({}),
secretStorage: { hasKey: jest.fn() },
crypto: { crypto: {
isSecretStorageReady: jest.fn(),
getSessionBackupPrivateKey: jest.fn(), getSessionBackupPrivateKey: jest.fn(),
secretStorage: { hasKey: jest.fn() },
crossSigningInfo: { crossSigningInfo: {
getId: jest.fn(), getId: jest.fn(),
isStoredInSecretStorage: jest.fn(), isStoredInSecretStorage: jest.fn(),