You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-07 23:02:56 +03:00
Element-R: pass device list change notifications into rust crypto-sdk (#3254)
This commit is contained in:
@@ -662,13 +662,17 @@ describe("SlidingSyncSdk", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("can update device lists", () => {
|
it("can update device lists", () => {
|
||||||
|
client!.crypto!.processDeviceLists = jest.fn();
|
||||||
ext.onResponse({
|
ext.onResponse({
|
||||||
device_lists: {
|
device_lists: {
|
||||||
changed: ["@alice:localhost"],
|
changed: ["@alice:localhost"],
|
||||||
left: ["@bob:localhost"],
|
left: ["@bob:localhost"],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// TODO: more assertions?
|
expect(client!.crypto!.processDeviceLists).toHaveBeenCalledWith({
|
||||||
|
changed: ["@alice:localhost"],
|
||||||
|
left: ["@bob:localhost"],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can update OTK counts and unused fallback keys", () => {
|
it("can update OTK counts and unused fallback keys", () => {
|
||||||
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { IToDeviceEvent } from "../sync-accumulator";
|
import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator";
|
||||||
import { MatrixEvent } from "../models/event";
|
import { MatrixEvent } from "../models/event";
|
||||||
import { Room } from "../models/room";
|
import { Room } from "../models/room";
|
||||||
import { CryptoApi } from "../crypto-api";
|
import { CryptoApi } from "../crypto-api";
|
||||||
@@ -113,6 +113,14 @@ export interface SyncCryptoCallbacks {
|
|||||||
*/
|
*/
|
||||||
processKeyCounts(oneTimeKeysCounts?: Record<string, number>, unusedFallbackKeys?: string[]): Promise<void>;
|
processKeyCounts(oneTimeKeysCounts?: Record<string, number>, unusedFallbackKeys?: string[]): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the notification from /sync that device lists have
|
||||||
|
* been changed.
|
||||||
|
*
|
||||||
|
* @param deviceLists - device_lists field from /sync
|
||||||
|
*/
|
||||||
|
processDeviceLists(deviceLists: IDeviceLists): Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the /sync loop whenever an m.room.encryption event is received.
|
* Called by the /sync loop whenever an m.room.encryption event is received.
|
||||||
*
|
*
|
||||||
|
@@ -71,7 +71,7 @@ import { CryptoStore } from "./store/base";
|
|||||||
import { IVerificationChannel } from "./verification/request/Channel";
|
import { IVerificationChannel } from "./verification/request/Channel";
|
||||||
import { TypedEventEmitter } from "../models/typed-event-emitter";
|
import { TypedEventEmitter } from "../models/typed-event-emitter";
|
||||||
import { IContent } from "../models/event";
|
import { IContent } from "../models/event";
|
||||||
import { ISyncResponse, IToDeviceEvent } from "../sync-accumulator";
|
import { IDeviceLists, ISyncResponse, IToDeviceEvent } from "../sync-accumulator";
|
||||||
import { ISignatures } from "../@types/signed";
|
import { ISignatures } from "../@types/signed";
|
||||||
import { IMessage } from "./algorithms/olm";
|
import { IMessage } from "./algorithms/olm";
|
||||||
import { CryptoBackend, OnSyncCompletedData } from "../common-crypto/CryptoBackend";
|
import { CryptoBackend, OnSyncCompletedData } from "../common-crypto/CryptoBackend";
|
||||||
@@ -2893,21 +2893,12 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the notification from /sync or /keys/changes that device lists have
|
* Handle the notification from /sync that device lists have
|
||||||
* been changed.
|
* been changed.
|
||||||
*
|
*
|
||||||
* @param syncData - Object containing sync tokens associated with this sync
|
* @param deviceLists - device_lists field from /sync
|
||||||
* @param syncDeviceLists - device_lists field from /sync, or response from
|
|
||||||
* /keys/changes
|
|
||||||
*/
|
*/
|
||||||
public async handleDeviceListChanges(
|
public async processDeviceLists(deviceLists: IDeviceLists): Promise<void> {
|
||||||
syncData: ISyncStateData,
|
|
||||||
syncDeviceLists: Required<ISyncResponse>["device_lists"],
|
|
||||||
): Promise<void> {
|
|
||||||
// Initial syncs don't have device change lists. We'll either get the complete list
|
|
||||||
// of changes for the interval or will have invalidated everything in willProcessSync
|
|
||||||
if (!syncData.oldSyncToken) return;
|
|
||||||
|
|
||||||
// Here, we're relying on the fact that we only ever save the sync data after
|
// Here, we're relying on the fact that we only ever save the sync data after
|
||||||
// sucessfully saving the device list data, so we're guaranteed that the device
|
// sucessfully saving the device list data, so we're guaranteed that the device
|
||||||
// list store is at least as fresh as the sync token from the sync store, ie.
|
// list store is at least as fresh as the sync token from the sync store, ie.
|
||||||
@@ -2916,7 +2907,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
// If we didn't make this assumption, we'd have to use the /keys/changes API
|
// If we didn't make this assumption, we'd have to use the /keys/changes API
|
||||||
// to get key changes between the sync token in the device list and the 'old'
|
// to get key changes between the sync token in the device list and the 'old'
|
||||||
// sync token used here to make sure we didn't miss any.
|
// sync token used here to make sure we didn't miss any.
|
||||||
await this.evalDeviceListChanges(syncDeviceLists);
|
await this.evalDeviceListChanges(deviceLists);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-js";
|
import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-js";
|
||||||
|
|
||||||
import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto";
|
import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto";
|
||||||
import type { IToDeviceEvent } from "../sync-accumulator";
|
import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator";
|
||||||
import type { IEncryptedEventInfo } from "../crypto/api";
|
import type { IEncryptedEventInfo } from "../crypto/api";
|
||||||
import { MatrixEvent } from "../models/event";
|
import { MatrixEvent } from "../models/event";
|
||||||
import { Room } from "../models/room";
|
import { Room } from "../models/room";
|
||||||
@@ -176,20 +176,23 @@ export class RustCrypto implements CryptoBackend {
|
|||||||
* @param events - the received to-device messages
|
* @param events - the received to-device messages
|
||||||
* @param oneTimeKeysCounts - the received one time key counts
|
* @param oneTimeKeysCounts - the received one time key counts
|
||||||
* @param unusedFallbackKeys - the received unused fallback keys
|
* @param unusedFallbackKeys - the received unused fallback keys
|
||||||
|
* @param devices - the received device list updates
|
||||||
* @returns A list of preprocessed to-device messages.
|
* @returns A list of preprocessed to-device messages.
|
||||||
*/
|
*/
|
||||||
private async receiveSyncChanges({
|
private async receiveSyncChanges({
|
||||||
events,
|
events,
|
||||||
oneTimeKeysCounts = new Map<string, number>(),
|
oneTimeKeysCounts = new Map<string, number>(),
|
||||||
unusedFallbackKeys = new Set<string>(),
|
unusedFallbackKeys = new Set<string>(),
|
||||||
|
devices = new RustSdkCryptoJs.DeviceLists(),
|
||||||
}: {
|
}: {
|
||||||
events?: IToDeviceEvent[];
|
events?: IToDeviceEvent[];
|
||||||
oneTimeKeysCounts?: Map<string, number>;
|
oneTimeKeysCounts?: Map<string, number>;
|
||||||
unusedFallbackKeys?: Set<string>;
|
unusedFallbackKeys?: Set<string>;
|
||||||
|
devices?: RustSdkCryptoJs.DeviceLists;
|
||||||
}): Promise<IToDeviceEvent[]> {
|
}): Promise<IToDeviceEvent[]> {
|
||||||
const result = await this.olmMachine.receiveSyncChanges(
|
const result = await this.olmMachine.receiveSyncChanges(
|
||||||
events ? JSON.stringify(events) : "[]",
|
events ? JSON.stringify(events) : "[]",
|
||||||
new RustSdkCryptoJs.DeviceLists(),
|
devices,
|
||||||
oneTimeKeysCounts,
|
oneTimeKeysCounts,
|
||||||
unusedFallbackKeys,
|
unusedFallbackKeys,
|
||||||
);
|
);
|
||||||
@@ -229,6 +232,16 @@ export class RustCrypto implements CryptoBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** called by the sync loop to process the notification that device lists have
|
||||||
|
* been changed.
|
||||||
|
*
|
||||||
|
* @param deviceLists - device_lists field from /sync
|
||||||
|
*/
|
||||||
|
public async processDeviceLists(deviceLists: IDeviceLists): Promise<void> {
|
||||||
|
const devices = new RustSdkCryptoJs.DeviceLists(deviceLists.changed, deviceLists.left);
|
||||||
|
await this.receiveSyncChanges({ devices });
|
||||||
|
}
|
||||||
|
|
||||||
/** called by the sync loop on m.room.encrypted events
|
/** called by the sync loop on m.room.encrypted events
|
||||||
*
|
*
|
||||||
* @param room - in which the event was received
|
* @param room - in which the event was received
|
||||||
|
@@ -85,13 +85,8 @@ class ExtensionE2EE implements Extension<ExtensionE2EERequest, ExtensionE2EEResp
|
|||||||
|
|
||||||
public async onResponse(data: ExtensionE2EEResponse): Promise<void> {
|
public async onResponse(data: ExtensionE2EEResponse): Promise<void> {
|
||||||
// Handle device list updates
|
// Handle device list updates
|
||||||
if (data["device_lists"]) {
|
if (data.device_lists) {
|
||||||
await this.crypto.handleDeviceListChanges(
|
await this.crypto.processDeviceLists(data.device_lists);
|
||||||
{
|
|
||||||
oldSyncToken: "yep", // XXX need to do this so the device list changes get processed :(
|
|
||||||
},
|
|
||||||
data["device_lists"],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle one_time_keys_count and unused_fallback_key_types
|
// Handle one_time_keys_count and unused_fallback_key_types
|
||||||
|
@@ -132,7 +132,7 @@ interface IToDevice {
|
|||||||
events: IToDeviceEvent[];
|
events: IToDeviceEvent[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IDeviceLists {
|
export interface IDeviceLists {
|
||||||
changed?: string[];
|
changed?: string[];
|
||||||
left?: string[];
|
left?: string[];
|
||||||
}
|
}
|
||||||
|
@@ -1515,8 +1515,8 @@ export class SyncApi {
|
|||||||
|
|
||||||
// Handle device list updates
|
// Handle device list updates
|
||||||
if (data.device_lists) {
|
if (data.device_lists) {
|
||||||
if (this.syncOpts.crypto) {
|
if (this.syncOpts.cryptoCallbacks) {
|
||||||
await this.syncOpts.crypto.handleDeviceListChanges(syncEventData, data.device_lists);
|
await this.syncOpts.cryptoCallbacks.processDeviceLists(data.device_lists);
|
||||||
} else {
|
} else {
|
||||||
// FIXME if we *don't* have a crypto module, we still need to
|
// FIXME if we *don't* have a crypto module, we still need to
|
||||||
// invalidate the device lists. But that would require a
|
// invalidate the device lists. But that would require a
|
||||||
|
Reference in New Issue
Block a user