mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-06-10 02:21:19 +03:00
Element R: emit events when devices have changed (#4019)
* emit events when Rust crypto wasm tells us devices have changed * lint * add missing stub function * apply workaround for queueMicrotask
This commit is contained in:
parent
f81036346f
commit
d178fbf9cd
@ -94,6 +94,7 @@ describe("initRustCrypto", () => {
|
||||
getSecretsFromInbox: jest.fn().mockResolvedValue([]),
|
||||
deleteSecretsFromInbox: jest.fn(),
|
||||
registerReceiveSecretCallback: jest.fn(),
|
||||
registerDevicesUpdatedCallback: jest.fn(),
|
||||
outgoingRequests: jest.fn(),
|
||||
isBackupEnabled: jest.fn().mockResolvedValue(false),
|
||||
verifyBackup: jest.fn().mockResolvedValue({ trusted: jest.fn().mockReturnValue(false) }),
|
||||
@ -1132,6 +1133,33 @@ describe("RustCrypto", () => {
|
||||
rustCrypto.stop();
|
||||
});
|
||||
|
||||
it("should emit events on device changes", async () => {
|
||||
jest.useFakeTimers({ doNotFake: ["queueMicrotask"] });
|
||||
|
||||
fetchMock.post("path:/_matrix/client/v3/keys/upload", { one_time_key_counts: {} });
|
||||
fetchMock.post("path:/_matrix/client/v3/keys/query", {
|
||||
device_keys: {
|
||||
[testData.TEST_USER_ID]: {
|
||||
[testData.TEST_DEVICE_ID]: testData.SIGNED_TEST_DEVICE_DATA,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const rustCrypto = await makeTestRustCrypto(makeMatrixHttpApi(), testData.TEST_USER_ID);
|
||||
const willUpdateCallback = jest.fn();
|
||||
rustCrypto.on(CryptoEvent.WillUpdateDevices, willUpdateCallback);
|
||||
const devicesUpdatedCallback = jest.fn();
|
||||
rustCrypto.on(CryptoEvent.DevicesUpdated, devicesUpdatedCallback);
|
||||
|
||||
rustCrypto.onSyncCompleted({});
|
||||
|
||||
// wait for the devices to be updated
|
||||
await rustCrypto.getUserDeviceInfo([testData.TEST_USER_ID]);
|
||||
expect(willUpdateCallback).toHaveBeenCalledWith([testData.TEST_USER_ID], false);
|
||||
expect(devicesUpdatedCallback).toHaveBeenCalledWith([testData.TEST_USER_ID], false);
|
||||
rustCrypto.stop();
|
||||
});
|
||||
|
||||
describe("requestDeviceVerification", () => {
|
||||
it("throws an error if the device is unknown", async () => {
|
||||
const rustCrypto = await makeTestRustCrypto();
|
||||
|
@ -2360,6 +2360,9 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
CryptoEvent.KeyBackupSessionsRemaining,
|
||||
CryptoEvent.KeyBackupFailed,
|
||||
CryptoEvent.KeyBackupDecryptionKeyCached,
|
||||
CryptoEvent.KeysChanged,
|
||||
CryptoEvent.DevicesUpdated,
|
||||
CryptoEvent.WillUpdateDevices,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -158,6 +158,7 @@ async function initOlmMachine(
|
||||
await olmMachine.registerUserIdentityUpdatedCallback((userId: RustSdkCryptoJs.UserId) =>
|
||||
rustCrypto.onUserIdentityUpdated(userId),
|
||||
);
|
||||
await olmMachine.registerDevicesUpdatedCallback((userIds: string[]) => rustCrypto.onDevicesUpdated(userIds));
|
||||
|
||||
// Check if there are any key backup secrets pending processing. There may be multiple secrets to process if several devices have gossiped them.
|
||||
// The `registerReceiveSecretCallback` function will only be triggered for new secrets. If the client is restarted before processing them, the secrets will need to be manually handled.
|
||||
|
@ -1441,7 +1441,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
* Callback for `OlmMachine.registerUserIdentityUpdatedCallback`
|
||||
*
|
||||
* Called by the rust-sdk whenever there is an update to any user's cross-signing status. We re-check their trust
|
||||
* status and emit a `UserTrustStatusChanged` event.
|
||||
* status and emit a `UserTrustStatusChanged` event, as well as a `KeysChanged` if it is our own identity that changed.
|
||||
*
|
||||
* @param userId - the user with the updated identity
|
||||
*/
|
||||
@ -1452,10 +1452,26 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
||||
// If our own user identity has changed, we may now trust the key backup where we did not before.
|
||||
// So, re-check the key backup status and enable it if available.
|
||||
if (userId.toString() === this.userId) {
|
||||
this.emit(CryptoEvent.KeysChanged, {});
|
||||
await this.checkKeyBackupAndEnable();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for `OlmMachine.registerDevicesUpdatedCallback`
|
||||
*
|
||||
* Called when users' devices have updated. Emits `WillUpdateDevices` and `DevicesUpdated`. In the JavaScript
|
||||
* crypto backend, these events are called at separate times, with `WillUpdateDevices` being emitted just before
|
||||
* the devices are saved, and `DevicesUpdated` being emitted just after. But the OlmMachine only gives us
|
||||
* one event, so we emit both events here.
|
||||
*
|
||||
* @param userIds - an array of user IDs of users whose devices have updated.
|
||||
*/
|
||||
public async onDevicesUpdated(userIds: string[]): Promise<void> {
|
||||
this.emit(CryptoEvent.WillUpdateDevices, userIds, false);
|
||||
this.emit(CryptoEvent.DevicesUpdated, userIds, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles secret received from the rust secret inbox.
|
||||
*
|
||||
@ -1828,6 +1844,9 @@ function rustEncryptionInfoToJsEncryptionInfo(
|
||||
type RustCryptoEvents =
|
||||
| CryptoEvent.VerificationRequestReceived
|
||||
| CryptoEvent.UserTrustStatusChanged
|
||||
| CryptoEvent.KeysChanged
|
||||
| CryptoEvent.WillUpdateDevices
|
||||
| CryptoEvent.DevicesUpdated
|
||||
| RustBackupCryptoEvents;
|
||||
|
||||
type RustCryptoEventMap = {
|
||||
@ -1842,4 +1861,31 @@ type RustCryptoEventMap = {
|
||||
[CryptoEvent.UserTrustStatusChanged]: (userId: string, userTrustLevel: UserVerificationStatus) => void;
|
||||
|
||||
[CryptoEvent.KeyBackupDecryptionKeyCached]: (version: string) => void;
|
||||
/**
|
||||
* Fires when the user's cross-signing keys have changed or cross-signing
|
||||
* has been enabled/disabled. The client can use getStoredCrossSigningForUser
|
||||
* with the user ID of the logged in user to check if cross-signing is
|
||||
* enabled on the account. If enabled, it can test whether the current key
|
||||
* is trusted using with checkUserTrust with the user ID of the logged
|
||||
* in user. The checkOwnCrossSigningTrust function may be used to reconcile
|
||||
* the trust in the account key.
|
||||
*
|
||||
* The cross-signing API is currently UNSTABLE and may change without notice.
|
||||
* @experimental
|
||||
*/
|
||||
[CryptoEvent.KeysChanged]: (data: {}) => void;
|
||||
/**
|
||||
* Fires whenever the stored devices for a user will be updated
|
||||
* @param users - A list of user IDs that will be updated
|
||||
* @param initialFetch - If true, the store is empty (apart
|
||||
* from our own device) and is being seeded.
|
||||
*/
|
||||
[CryptoEvent.WillUpdateDevices]: (users: string[], initialFetch: boolean) => void;
|
||||
/**
|
||||
* Fires whenever the stored devices for a user have changed
|
||||
* @param users - A list of user IDs that were updated
|
||||
* @param initialFetch - If true, the store was empty (apart
|
||||
* from our own device) and has been seeded.
|
||||
*/
|
||||
[CryptoEvent.DevicesUpdated]: (users: string[], initialFetch: boolean) => void;
|
||||
} & RustBackupCryptoEventMap;
|
||||
|
Loading…
x
Reference in New Issue
Block a user