1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-25 05:23:13 +03:00

Make Room.getEncryptionTargetMembers async, as members might be loading

This commit is contained in:
Bruno Windels
2018-08-06 17:18:36 +02:00
parent 3616a07dbb
commit a8bf66d8af
4 changed files with 70 additions and 65 deletions

View File

@@ -535,8 +535,9 @@ MegolmEncryption.prototype._checkForUnknownDevices = function(devicesInRoom) {
* @return {module:client.Promise} Promise which resolves to a map * @return {module:client.Promise} Promise which resolves to a map
* from userId to deviceId to deviceInfo * from userId to deviceId to deviceInfo
*/ */
MegolmEncryption.prototype._getDevicesInRoom = function(room) { MegolmEncryption.prototype._getDevicesInRoom = async function(room) {
const roomMembers = utils.map(room.getEncryptionTargetMembers(), function(u) { const members = await room.getEncryptionTargetMembers();
const roomMembers = utils.map(members, function(u) {
return u.userId; return u.userId;
}); });
@@ -555,29 +556,28 @@ MegolmEncryption.prototype._getDevicesInRoom = function(room) {
// common and then added new devices before joining this one? --Matthew // common and then added new devices before joining this one? --Matthew
// //
// yup, see https://github.com/vector-im/riot-web/issues/2305 --richvdh // yup, see https://github.com/vector-im/riot-web/issues/2305 --richvdh
return this._crypto.downloadKeys(roomMembers, false).then((devices) => { const devices = await this._crypto.downloadKeys(roomMembers, false);
// remove any blocked devices // remove any blocked devices
for (const userId in devices) { for (const userId in devices) {
if (!devices.hasOwnProperty(userId)) { if (!devices.hasOwnProperty(userId)) {
continue;
}
const userDevices = devices[userId];
for (const deviceId in userDevices) {
if (!userDevices.hasOwnProperty(deviceId)) {
continue; continue;
} }
const userDevices = devices[userId]; if (userDevices[deviceId].isBlocked() ||
for (const deviceId in userDevices) { (userDevices[deviceId].isUnverified() && isBlacklisting)
if (!userDevices.hasOwnProperty(deviceId)) { ) {
continue; delete userDevices[deviceId];
}
if (userDevices[deviceId].isBlocked() ||
(userDevices[deviceId].isUnverified() && isBlacklisting)
) {
delete userDevices[deviceId];
}
} }
} }
}
return devices; return devices;
});
}; };
/** /**

View File

@@ -83,60 +83,62 @@ OlmEncryption.prototype._ensureSession = function(roomMembers) {
* *
* @return {module:client.Promise} Promise which resolves to the new event body * @return {module:client.Promise} Promise which resolves to the new event body
*/ */
OlmEncryption.prototype.encryptMessage = function(room, eventType, content) { OlmEncryption.prototype.encryptMessage = async function(room, eventType, content) {
// pick the list of recipients based on the membership list. // pick the list of recipients based on the membership list.
// //
// TODO: there is a race condition here! What if a new user turns up // TODO: there is a race condition here! What if a new user turns up
// just as you are sending a secret message? // just as you are sending a secret message?
const users = utils.map(room.getEncryptionTargetMembers(), function(u) { const members = await room.getEncryptionTargetMembers();
const users = utils.map(members, function(u) {
return u.userId; return u.userId;
}); });
const self = this; const self = this;
return this._ensureSession(users).then(function() { await this._ensureSession(users);
const payloadFields = {
room_id: room.roomId,
type: eventType,
content: content,
};
const encryptedContent = { const payloadFields = {
algorithm: olmlib.OLM_ALGORITHM, room_id: room.roomId,
sender_key: self._olmDevice.deviceCurve25519Key, type: eventType,
ciphertext: {}, content: content,
}; };
const promises = []; const encryptedContent = {
algorithm: olmlib.OLM_ALGORITHM,
sender_key: self._olmDevice.deviceCurve25519Key,
ciphertext: {},
};
for (let i = 0; i < users.length; ++i) { const promises = [];
const userId = users[i];
const devices = self._crypto.getStoredDevicesForUser(userId);
for (let j = 0; j < devices.length; ++j) { for (let i = 0; i < users.length; ++i) {
const deviceInfo = devices[j]; const userId = users[i];
const key = deviceInfo.getIdentityKey(); const devices = self._crypto.getStoredDevicesForUser(userId);
if (key == self._olmDevice.deviceCurve25519Key) {
// don't bother sending to ourself
continue;
}
if (deviceInfo.verified == DeviceVerification.BLOCKED) {
// don't bother setting up sessions with blocked users
continue;
}
promises.push( for (let j = 0; j < devices.length; ++j) {
olmlib.encryptMessageForDevice( const deviceInfo = devices[j];
encryptedContent.ciphertext, const key = deviceInfo.getIdentityKey();
self._userId, self._deviceId, self._olmDevice, if (key == self._olmDevice.deviceCurve25519Key) {
userId, deviceInfo, payloadFields, // don't bother sending to ourself
), continue;
); }
if (deviceInfo.verified == DeviceVerification.BLOCKED) {
// don't bother setting up sessions with blocked users
continue;
} }
}
return Promise.all(promises).return(encryptedContent); promises.push(
}); olmlib.encryptMessageForDevice(
encryptedContent.ciphertext,
self._userId, self._deviceId, self._olmDevice,
userId, deviceInfo, payloadFields,
),
);
}
}
return await Promise.all(promises).return(encryptedContent);
}; };
/** /**

View File

@@ -652,7 +652,7 @@ Crypto.prototype.setRoomEncryption = async function(roomId, config, inhibitDevic
throw new Error(`Unable to enable encryption in unknown room ${roomId}`); throw new Error(`Unable to enable encryption in unknown room ${roomId}`);
} }
const members = room.getEncryptionTargetMembers(); const members = await room.getEncryptionTargetMembers();
members.forEach((m) => { members.forEach((m) => {
this._deviceList.startTrackingDeviceList(m.userId); this._deviceList.startTrackingDeviceList(m.userId);
}); });
@@ -852,7 +852,7 @@ Crypto.prototype.handleDeviceListChanges = async function(syncData, syncDeviceLi
// 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.
this._evalDeviceListChanges(syncDeviceLists); await this._evalDeviceListChanges(syncDeviceLists);
}; };
/** /**
@@ -968,7 +968,7 @@ Crypto.prototype._evalDeviceListChanges = async function(deviceLists) {
// Check we really don't share any rooms with these users // Check we really don't share any rooms with these users
// any more: the server isn't required to give us the // any more: the server isn't required to give us the
// exact correct set. // exact correct set.
const e2eUserIds = new Set(this._getE2eUsers()); const e2eUserIds = new Set(await this._getE2eUsers());
deviceLists.left.forEach((u) => { deviceLists.left.forEach((u) => {
if (!e2eUserIds.has(u)) { if (!e2eUserIds.has(u)) {
@@ -983,10 +983,10 @@ Crypto.prototype._evalDeviceListChanges = async function(deviceLists) {
* *
* @returns {string[]} List of user IDs * @returns {string[]} List of user IDs
*/ */
Crypto.prototype._getE2eUsers = function() { Crypto.prototype._getE2eUsers = async function() {
const e2eUserIds = []; const e2eUserIds = [];
for (const room of this._getE2eRooms()) { for (const room of this._getE2eRooms()) {
const members = room.getEncryptionTargetMembers(); const members = await room.getEncryptionTargetMembers();
for (const member of members) { for (const member of members) {
e2eUserIds.push(member.userId); e2eUserIds.push(member.userId);
} }

View File

@@ -569,10 +569,13 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline,
/** /**
* Get a list of members we should be encrypting for in this room * Get a list of members we should be encrypting for in this room
* @return {RoomMember[]} A list of members who we should encrypt messages for * @return {Promise<RoomMember[]>} A list of members who
* in this room. * we should encrypt messages for in this room.
*/ */
Room.prototype.getEncryptionTargetMembers = function() { Room.prototype.getEncryptionTargetMembers = async function() {
if (this._oobMembersPromise) {
await _oobMembersPromise;
}
let members = this.getMembersWithMembership("join"); let members = this.getMembersWithMembership("join");
if (this.shouldEncryptForInvitedMembers()) { if (this.shouldEncryptForInvitedMembers()) {
members = members.concat(this.getMembersWithMembership("invite")); members = members.concat(this.getMembersWithMembership("invite"));