You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-12 08:42:46 +03:00
Refresh device list on startup
On initialsync, call the /keys/changes api to see which users have updated their devices. (On failure, invalidate all of them).
This commit is contained in:
@@ -1082,6 +1082,28 @@ MatrixBaseApis.prototype.claimOneTimeKeys = function(devices, key_algorithm) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask the server for a list of users who have changed their device lists
|
||||||
|
* between a pair of sync tokens
|
||||||
|
*
|
||||||
|
* @param {string} oldToken
|
||||||
|
* @param {string} newToken
|
||||||
|
*
|
||||||
|
* @return {module:client.Promise} Resolves: result object. Rejects: with
|
||||||
|
* an error response ({@link module:http-api.MatrixError}).
|
||||||
|
*/
|
||||||
|
MatrixBaseApis.prototype.getKeyChanges = function(oldToken, newToken) {
|
||||||
|
const qps = {
|
||||||
|
from: oldToken,
|
||||||
|
to: newToken,
|
||||||
|
};
|
||||||
|
|
||||||
|
return this._http.authedRequestWithPrefix(
|
||||||
|
undefined, "GET", "/keys/changes", qps, undefined,
|
||||||
|
httpApi.PREFIX_UNSTABLE,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Identity Server Operations
|
// Identity Server Operations
|
||||||
// ==========================
|
// ==========================
|
||||||
|
@@ -732,6 +732,22 @@ Crypto.prototype._onSyncCompleted = function(syncData) {
|
|||||||
if (!syncData.oldSyncToken) {
|
if (!syncData.oldSyncToken) {
|
||||||
// an initialsync.
|
// an initialsync.
|
||||||
this._sendNewDeviceEvents();
|
this._sendNewDeviceEvents();
|
||||||
|
|
||||||
|
// if we have a deviceSyncToken, we can tell the deviceList to
|
||||||
|
// invalidate devices which have changed since then.
|
||||||
|
const oldSyncToken = this._sessionStore.getEndToEndDeviceSyncToken();
|
||||||
|
if (oldSyncToken) {
|
||||||
|
this._invalidateDeviceListsSince(oldSyncToken).catch((e) => {
|
||||||
|
// if that failed, we fall back to invalidating everyone.
|
||||||
|
console.warn("Error fetching changed device list", e);
|
||||||
|
this._invalidateDeviceListForAllActiveUsers();
|
||||||
|
return this._deviceList.flushNewDeviceRequests();
|
||||||
|
}).done();
|
||||||
|
} else {
|
||||||
|
// otherwise, we have to invalidate all devices for all users we
|
||||||
|
// share a room with.
|
||||||
|
this._invalidateDeviceListForAllActiveUsers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// catch up on any new devices we got told about during the sync.
|
// catch up on any new devices we got told about during the sync.
|
||||||
@@ -754,25 +770,8 @@ Crypto.prototype._sendNewDeviceEvents = function() {
|
|||||||
// we need to tell all the devices in all the rooms we are members of that
|
// we need to tell all the devices in all the rooms we are members of that
|
||||||
// we have arrived.
|
// we have arrived.
|
||||||
// build a list of rooms for each user.
|
// build a list of rooms for each user.
|
||||||
const rooms = this._clientStore.getRooms();
|
|
||||||
const roomsByUser = {};
|
const roomsByUser = {};
|
||||||
for (let i = 0; i < rooms.length; i++) {
|
for (const room of this._getE2eRooms()) {
|
||||||
const room = rooms[i];
|
|
||||||
|
|
||||||
// check for rooms with encryption enabled
|
|
||||||
const alg = this._roomEncryptors[room.roomId];
|
|
||||||
if (!alg) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore any rooms which we have left
|
|
||||||
const me = room.getMember(this._userId);
|
|
||||||
if (!me || (
|
|
||||||
me.membership !== "join" && me.membership !== "invite"
|
|
||||||
)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const members = room.getJoinedMembers();
|
const members = room.getJoinedMembers();
|
||||||
for (let j = 0; j < members.length; j++) {
|
for (let j = 0; j < members.length; j++) {
|
||||||
const m = members[j];
|
const m = members[j];
|
||||||
@@ -806,6 +805,88 @@ Crypto.prototype._sendNewDeviceEvents = function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask the server which users have new devices since a given token,
|
||||||
|
* invalidate them, and start an update query.
|
||||||
|
*
|
||||||
|
* @param {String} oldSyncToken
|
||||||
|
*
|
||||||
|
* @returns {Promise} resolves once the query is complete. Rejects if the
|
||||||
|
* keyChange query fails.
|
||||||
|
*/
|
||||||
|
Crypto.prototype._invalidateDeviceListsSince = function(oldSyncToken) {
|
||||||
|
return this._baseApis.getKeyChanges(
|
||||||
|
oldSyncToken, this.lastKnownSyncToken,
|
||||||
|
).then((r) => {
|
||||||
|
if (!r.changed || !Array.isArray(r.changed)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only invalidate users we share an e2e room with - we don't
|
||||||
|
// care about users in non-e2e rooms.
|
||||||
|
const filteredUserIds = this._getE2eRoomMembers();
|
||||||
|
r.changed.forEach((u) => {
|
||||||
|
if (u in filteredUserIds) {
|
||||||
|
this._deviceList.invalidateUserDeviceList(u);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return this._deviceList.flushNewDeviceRequests();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate any stored device list for any users we share an e2e room with
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
Crypto.prototype._invalidateDeviceListForAllActiveUsers = function() {
|
||||||
|
Object.keys(this._getE2eRoomMembers()).forEach((m) => {
|
||||||
|
this._deviceList.invalidateUserDeviceList(m);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the users we share an e2e-enabled room with
|
||||||
|
*
|
||||||
|
* @returns {Object<string>} userid->userid map (should be a Set but argh ES6)
|
||||||
|
*/
|
||||||
|
Crypto.prototype._getE2eRoomMembers = function() {
|
||||||
|
const userIds = Object.create(null);
|
||||||
|
|
||||||
|
const rooms = this._getE2eRooms();
|
||||||
|
for (const r of rooms) {
|
||||||
|
const members = r.getJoinedMembers();
|
||||||
|
members.forEach((m) => { userIds[m.userId] = m.userId; });
|
||||||
|
}
|
||||||
|
|
||||||
|
return userIds;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of the e2e-enabled rooms we are members of
|
||||||
|
*
|
||||||
|
* @returns {module:models.Room[]}
|
||||||
|
*/
|
||||||
|
Crypto.prototype._getE2eRooms = function() {
|
||||||
|
return this._clientStore.getRooms().filter((room) => {
|
||||||
|
// check for rooms with encryption enabled
|
||||||
|
const alg = this._roomEncryptors[room.roomId];
|
||||||
|
if (!alg) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore any rooms which we have left
|
||||||
|
const me = room.getMember(this._userId);
|
||||||
|
if (!me || (
|
||||||
|
me.membership !== "join" && me.membership !== "invite"
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a key event
|
* Handle a key event
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user