You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-28 05:03:59 +03:00
Fix device tracking with initial /sync
* Check whether we share an e2e room with user IDs in the 'left' field of /keys/changes: there's no guarantee we no longer share any e2e rooms with these users * Reset everyone's tracking status on an initial sync - just re-fetching device lists for all users we're currently tracking isn't good enough since room memberships may have changed. * Fix typo in test
This commit is contained in:
@@ -366,9 +366,9 @@ describe("DeviceList management:", function() {
|
|||||||
anotherTestClient.httpBackend.when('GET', '/sync').respond(
|
anotherTestClient.httpBackend.when('GET', '/sync').respond(
|
||||||
200, getSyncResponse([]));
|
200, getSyncResponse([]));
|
||||||
await anotherTestClient.flushSync();
|
await anotherTestClient.flushSync();
|
||||||
await aliceTestClient.client._crypto._deviceList.saveIfDirty();
|
await anotherTestClient.client._crypto._deviceList.saveIfDirty();
|
||||||
|
|
||||||
aliceTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
|
anotherTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
|
||||||
const bobStat = data.trackingStatus['@bob:xyz'];
|
const bobStat = data.trackingStatus['@bob:xyz'];
|
||||||
|
|
||||||
expect(bobStat).toEqual(
|
expect(bobStat).toEqual(
|
||||||
|
|||||||
@@ -417,6 +417,19 @@ export default class DeviceList {
|
|||||||
this._dirty = true;
|
this._dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all users we're currently tracking to untracked
|
||||||
|
*
|
||||||
|
* This will flag each user whose devices we are tracking as in need of an
|
||||||
|
* update.
|
||||||
|
*/
|
||||||
|
stopTrackingAllDeviceLists() {
|
||||||
|
for (const userId of Object.keys(this._deviceTrackingStatus)) {
|
||||||
|
this._deviceTrackingStatus[userId] = TRACKING_STATUS_NOT_TRACKED;
|
||||||
|
}
|
||||||
|
console.log("stopped tracking all: "+JSON.stringify(this._deviceTrackingStatus));
|
||||||
|
this._dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark the cached device list for the given user outdated.
|
* Mark the cached device list for the given user outdated.
|
||||||
@@ -440,18 +453,6 @@ export default class DeviceList {
|
|||||||
this._dirty = true;
|
this._dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark all tracked device lists as outdated.
|
|
||||||
*
|
|
||||||
* This will flag each user whose devices we are tracking as in need of an
|
|
||||||
* update.
|
|
||||||
*/
|
|
||||||
invalidateAllDeviceLists() {
|
|
||||||
for (const userId of Object.keys(this._deviceTrackingStatus)) {
|
|
||||||
this.invalidateUserDeviceList(userId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we have users who have outdated device lists, start key downloads for them
|
* If we have users who have outdated device lists, start key downloads for them
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -894,6 +894,22 @@ Crypto.prototype.onCryptoEvent = async function(event) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before the result of a sync is procesed
|
||||||
|
*
|
||||||
|
* @param {Object} syncData the data from the 'MatrixClient.sync' event
|
||||||
|
*/
|
||||||
|
Crypto.prototype.onSyncWillProcess = async function(syncData) {
|
||||||
|
if (!syncData.oldSyncToken) {
|
||||||
|
// If there is no old sync token, we start all our tracking from
|
||||||
|
// scratch, so mark everything as untracked. onCryptoEvent will
|
||||||
|
// be called for all e2e rooms during the processing of the sync,
|
||||||
|
// at which point we'll start tracking all the users of that room.
|
||||||
|
console.log("Initial sync performed - resetting device tracking state");
|
||||||
|
this._deviceList.stopTrackingAllDeviceLists();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* handle the completion of a /sync
|
* handle the completion of a /sync
|
||||||
*
|
*
|
||||||
@@ -905,14 +921,6 @@ Crypto.prototype.onCryptoEvent = async function(event) {
|
|||||||
Crypto.prototype.onSyncCompleted = async function(syncData) {
|
Crypto.prototype.onSyncCompleted = async function(syncData) {
|
||||||
const nextSyncToken = syncData.nextSyncToken;
|
const nextSyncToken = syncData.nextSyncToken;
|
||||||
|
|
||||||
if (!syncData.oldSyncToken) {
|
|
||||||
// If we have a stored device sync token, we could request the complete
|
|
||||||
// list of device changes from the server here to get our device list up
|
|
||||||
// to date. This case should be relatively rare though (only when you hit
|
|
||||||
// 'clear cache and reload' in practice) so we just invalidate everything.
|
|
||||||
console.log("invalidating all device list caches after inital sync");
|
|
||||||
this._deviceList.invalidateAllDeviceLists();
|
|
||||||
}
|
|
||||||
this._deviceList.setSyncToken(syncData.nextSyncToken);
|
this._deviceList.setSyncToken(syncData.nextSyncToken);
|
||||||
this._deviceList.saveIfDirty();
|
this._deviceList.saveIfDirty();
|
||||||
|
|
||||||
@@ -945,12 +953,32 @@ Crypto.prototype._evalDeviceListChanges = async function(deviceLists) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (deviceLists.left && Array.isArray(deviceLists.left)) {
|
if (deviceLists.left && Array.isArray(deviceLists.left)) {
|
||||||
|
const e2eUserIds = new Set(this._getE2eUsers());
|
||||||
|
|
||||||
deviceLists.left.forEach((u) => {
|
deviceLists.left.forEach((u) => {
|
||||||
this._deviceList.stopTrackingDeviceList(u);
|
if (!e2eUserIds.has(u)) {
|
||||||
|
this._deviceList.stopTrackingDeviceList(u);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of all the IDs of users we share an e2e room with
|
||||||
|
*
|
||||||
|
* @returns {string[]} List of user IDs
|
||||||
|
*/
|
||||||
|
Crypto.prototype._getE2eUsers = function() {
|
||||||
|
const e2eUserIds = [];
|
||||||
|
for (const room of this._getE2eRooms()) {
|
||||||
|
const members = room.getJoinedMembers();
|
||||||
|
for (const member of members) {
|
||||||
|
e2eUserIds.push(member.userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return e2eUserIds;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of the e2e-enabled rooms we are members of
|
* Get a list of the e2e-enabled rooms we are members of
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -627,6 +627,12 @@ SyncApi.prototype._sync = async function(syncOptions) {
|
|||||||
catchingUp: this._catchingUp,
|
catchingUp: this._catchingUp,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.opts.crypto && !isCachedResponse) {
|
||||||
|
// tell the crypto module we're about to process a sync
|
||||||
|
// response
|
||||||
|
await this.opts.crypto.onSyncWillProcess(syncEventData);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this._processSyncResponse(syncEventData, data, isCachedResponse);
|
await this._processSyncResponse(syncEventData, data, isCachedResponse);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user