You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-25 05:23:13 +03:00
RustCrypto.getCrossSigningStatus: check the client is not stopped (#3682)
* `RustCrypto.getCrossSigningStatus`: check the client is not stopped Better error handling for the case that a call to `MatrixClient.stop` happens while the call to `getCrossSigningStatus` (or `isCrossSigningReady`) is in flight. * fix up tsdoc
This commit is contained in:
committed by
GitHub
parent
dec4650d3d
commit
f406ffd3dd
@@ -150,6 +150,44 @@ describe("RustCrypto", () => {
|
|||||||
await expect(rustCrypto.getCrossSigningKeyId()).resolves.toBe(null);
|
await expect(rustCrypto.getCrossSigningKeyId()).resolves.toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("getCrossSigningStatus", () => {
|
||||||
|
it("returns sensible values on a default client", async () => {
|
||||||
|
const secretStorage = {
|
||||||
|
isStored: jest.fn().mockResolvedValue(null),
|
||||||
|
} as unknown as Mocked<ServerSideSecretStorage>;
|
||||||
|
const rustCrypto = await makeTestRustCrypto(undefined, undefined, undefined, secretStorage);
|
||||||
|
|
||||||
|
const result = await rustCrypto.getCrossSigningStatus();
|
||||||
|
|
||||||
|
expect(secretStorage.isStored).toHaveBeenCalledWith("m.cross_signing.master");
|
||||||
|
expect(result).toEqual({
|
||||||
|
privateKeysCachedLocally: {
|
||||||
|
masterKey: false,
|
||||||
|
selfSigningKey: false,
|
||||||
|
userSigningKey: false,
|
||||||
|
},
|
||||||
|
privateKeysInSecretStorage: false,
|
||||||
|
publicKeysOnDevice: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws if `stop` is called mid-call", async () => {
|
||||||
|
const secretStorage = {
|
||||||
|
isStored: jest.fn().mockResolvedValue(null),
|
||||||
|
} as unknown as Mocked<ServerSideSecretStorage>;
|
||||||
|
const rustCrypto = await makeTestRustCrypto(undefined, undefined, undefined, secretStorage);
|
||||||
|
|
||||||
|
// start the call off
|
||||||
|
const result = rustCrypto.getCrossSigningStatus();
|
||||||
|
|
||||||
|
// call `.stop`
|
||||||
|
rustCrypto.stop();
|
||||||
|
|
||||||
|
// getCrossSigningStatus should abort
|
||||||
|
await expect(result).rejects.toEqual(new Error("MatrixClient has been stopped"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("bootstrapCrossSigning delegates to CrossSigningIdentity", async () => {
|
it("bootstrapCrossSigning delegates to CrossSigningIdentity", async () => {
|
||||||
const rustCrypto = await makeTestRustCrypto();
|
const rustCrypto = await makeTestRustCrypto();
|
||||||
const mockCrossSigningIdentity = {
|
const mockCrossSigningIdentity = {
|
||||||
|
|||||||
@@ -170,6 +170,8 @@ export interface CryptoApi {
|
|||||||
* return true.
|
* return true.
|
||||||
*
|
*
|
||||||
* @returns True if cross-signing is ready to be used on this device
|
* @returns True if cross-signing is ready to be used on this device
|
||||||
|
*
|
||||||
|
* @throws May throw {@link ClientStoppedError} if the `MatrixClient` is stopped before or during the call.
|
||||||
*/
|
*/
|
||||||
isCrossSigningReady(): Promise<boolean>;
|
isCrossSigningReady(): Promise<boolean>;
|
||||||
|
|
||||||
@@ -234,7 +236,10 @@ export interface CryptoApi {
|
|||||||
/**
|
/**
|
||||||
* Get the status of our cross-signing keys.
|
* Get the status of our cross-signing keys.
|
||||||
*
|
*
|
||||||
* @returns The current status of cross-signing keys: whether we have public and private keys cached locally, and whether the private keys are in secret storage.
|
* @returns The current status of cross-signing keys: whether we have public and private keys cached locally, and
|
||||||
|
* whether the private keys are in secret storage.
|
||||||
|
*
|
||||||
|
* @throws May throw {@link ClientStoppedError} if the `MatrixClient` is stopped before or during the call.
|
||||||
*/
|
*/
|
||||||
getCrossSigningStatus(): Promise<CrossSigningStatus>;
|
getCrossSigningStatus(): Promise<CrossSigningStatus>;
|
||||||
|
|
||||||
|
|||||||
@@ -51,3 +51,17 @@ export class KeySignatureUploadError extends Error {
|
|||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It is invalid to call most methods once {@link MatrixClient#stopClient} has been called.
|
||||||
|
*
|
||||||
|
* This error will be thrown if you attempt to do so.
|
||||||
|
*
|
||||||
|
* {@link MatrixClient#stopClient} itself is an exception to this: it may safely be called multiple times on the same
|
||||||
|
* instance.
|
||||||
|
*/
|
||||||
|
export class ClientStoppedError extends Error {
|
||||||
|
public constructor() {
|
||||||
|
super("MatrixClient has been stopped");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ import { TypedEventEmitter } from "../models/typed-event-emitter";
|
|||||||
import { RustBackupCryptoEventMap, RustBackupCryptoEvents, RustBackupManager } from "./backup";
|
import { RustBackupCryptoEventMap, RustBackupCryptoEvents, RustBackupManager } from "./backup";
|
||||||
import { TypedReEmitter } from "../ReEmitter";
|
import { TypedReEmitter } from "../ReEmitter";
|
||||||
import { randomString } from "../randomstring";
|
import { randomString } from "../randomstring";
|
||||||
|
import { ClientStoppedError } from "../errors";
|
||||||
|
|
||||||
const ALL_VERIFICATION_METHODS = ["m.sas.v1", "m.qr_code.scan.v1", "m.qr_code.show.v1", "m.reciprocate.v1"];
|
const ALL_VERIFICATION_METHODS = ["m.sas.v1", "m.qr_code.scan.v1", "m.qr_code.show.v1", "m.reciprocate.v1"];
|
||||||
|
|
||||||
@@ -138,6 +139,20 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the OlmMachine only if {@link RustCrypto#stop} has not been called.
|
||||||
|
*
|
||||||
|
* This allows us to better handle race conditions where the client is stopped before or during a crypto API call.
|
||||||
|
*
|
||||||
|
* @throws ClientStoppedError if {@link RustCrypto#stop} has been called.
|
||||||
|
*/
|
||||||
|
private getOlmMachineOrThrow(): RustSdkCryptoJs.OlmMachine {
|
||||||
|
if (this.stopped) {
|
||||||
|
throw new ClientStoppedError();
|
||||||
|
}
|
||||||
|
return this.olmMachine;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// CryptoBackend implementation
|
// CryptoBackend implementation
|
||||||
@@ -635,16 +650,17 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
|||||||
* Implementation of {@link CryptoApi#getCrossSigningStatus}
|
* Implementation of {@link CryptoApi#getCrossSigningStatus}
|
||||||
*/
|
*/
|
||||||
public async getCrossSigningStatus(): Promise<CrossSigningStatus> {
|
public async getCrossSigningStatus(): Promise<CrossSigningStatus> {
|
||||||
const userIdentity: RustSdkCryptoJs.OwnUserIdentity | null = await this.olmMachine.getIdentity(
|
const userIdentity: RustSdkCryptoJs.OwnUserIdentity | null = await this.getOlmMachineOrThrow().getIdentity(
|
||||||
new RustSdkCryptoJs.UserId(this.userId),
|
new RustSdkCryptoJs.UserId(this.userId),
|
||||||
);
|
);
|
||||||
|
|
||||||
const publicKeysOnDevice =
|
const publicKeysOnDevice =
|
||||||
Boolean(userIdentity?.masterKey) &&
|
Boolean(userIdentity?.masterKey) &&
|
||||||
Boolean(userIdentity?.selfSigningKey) &&
|
Boolean(userIdentity?.selfSigningKey) &&
|
||||||
Boolean(userIdentity?.userSigningKey);
|
Boolean(userIdentity?.userSigningKey);
|
||||||
const privateKeysInSecretStorage = await secretStorageContainsCrossSigningKeys(this.secretStorage);
|
const privateKeysInSecretStorage = await secretStorageContainsCrossSigningKeys(this.secretStorage);
|
||||||
const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus | null =
|
const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus | null =
|
||||||
await this.olmMachine.crossSigningStatus();
|
await this.getOlmMachineOrThrow().crossSigningStatus();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
publicKeysOnDevice,
|
publicKeysOnDevice,
|
||||||
|
|||||||
Reference in New Issue
Block a user