send room keys to newly joined members in afterSyncCompleted stage

This commit is contained in:
Bruno Windels 2020-09-08 14:38:27 +02:00
parent c158e3da77
commit 31d4b6f75d
5 changed files with 53 additions and 1 deletions

View file

@ -125,6 +125,7 @@ export class Session {
olmEncryption: this._olmEncryption,
megolmEncryption: this._megolmEncryption,
megolmDecryption: this._megolmDecryption,
storage: this._storage,
encryptionParams
});
}

View file

@ -128,6 +128,22 @@ export class RoomEncryption {
};
}
needsToShareKeys(memberChanges) {
for (const m of memberChanges.values()) {
if (m.member.needsRoomKey) {
return true;
}
}
return false;
}
async shareRoomKeyToPendingMembers(hsApi) {
// sucks to call this for all encrypted rooms on startup?
const txn = await this._storage.readTxn([this._storage.storeNames.roomMembers]);
const pendingUserIds = await txn.roomMembers.getUserIdsNeedingRoomKey(this._room.id);
return await this._shareRoomKey(pendingUserIds, hsApi);
}
async shareRoomKeyForMemberChanges(memberChanges, hsApi) {
const pendingUserIds = [];
for (const m of memberChanges.values()) {

View file

@ -157,7 +157,8 @@ export class Room extends EventEmitter {
newLiveKey,
removedPendingEvents,
memberChanges,
heroChanges
heroChanges,
needsAfterSyncCompleted: this._roomEncryption?.needsToShareKeys(memberChanges)
};
}
@ -204,6 +205,17 @@ export class Room extends EventEmitter {
}
}
/**
* Only called if the result of writeSync had `needsAfterSyncCompleted` set.
* Can be used to do longer running operations that resulted from the last sync,
* like network operations.
*/
async afterSyncCompleted({memberChanges}) {
if (this._roomEncryption) {
await this._roomEncryption.shareRoomKeyForMemberChanges(memberChanges, this._hsApi);
}
}
/** @package */
resumeSending() {
this._sendQueue.resumeSending();

View file

@ -187,6 +187,14 @@ export class QueryTarget {
return results;
}
async iterateWhile(range, predicate) {
const cursor = this._openCursor(range, "next");
await iterateCursor(cursor, (value) => {
const passesPredicate = predicate(value);
return {done: !passesPredicate};
});
}
async _find(range, predicate, direction) {
const cursor = this._openCursor(range, direction);
let result;

View file

@ -60,4 +60,19 @@ export class RoomMemberStore {
});
return userIds;
}
async getUserIdsNeedingRoomKey(roomId) {
const userIds = [];
const range = IDBKeyRange.lowerBound(encodeKey(roomId, ""));
await this._roomMembersStore.iterateWhile(range, member => {
if (member.roomId !== roomId) {
return false;
}
if (member.needsRoomKey) {
userIds.push(member.userId);
}
return true;
});
return userIds;
}
}