Merge pull request #275 from vector-im/bwindels/retryeventidsforkeybackup
Extract retry event ids for key before overwriting key on key backup
This commit is contained in:
commit
a9027e1fee
3 changed files with 34 additions and 20 deletions
|
@ -210,11 +210,14 @@ export class RoomEncryption {
|
||||||
}
|
}
|
||||||
let roomKey = this._megolmDecryption.roomKeyFromBackup(this._room.id, sessionId, session);
|
let roomKey = this._megolmDecryption.roomKeyFromBackup(this._room.id, sessionId, session);
|
||||||
if (roomKey) {
|
if (roomKey) {
|
||||||
let keyIsBestOne = false;
|
let retryEventIds;
|
||||||
try {
|
try {
|
||||||
const txn = await this._storage.readWriteTxn([this._storage.storeNames.inboundGroupSessions]);
|
const txn = await this._storage.readWriteTxn([this._storage.storeNames.inboundGroupSessions]);
|
||||||
try {
|
try {
|
||||||
keyIsBestOne = await this._megolmDecryption.writeRoomKey(roomKey, txn);
|
const keyIsBestOne = await this._megolmDecryption.writeRoomKey(roomKey, txn);
|
||||||
|
if (keyIsBestOne) {
|
||||||
|
retryEventIds = roomKey.eventIds;
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
txn.abort();
|
txn.abort();
|
||||||
throw err;
|
throw err;
|
||||||
|
@ -225,9 +228,8 @@ export class RoomEncryption {
|
||||||
// this is just clearing the internal sessionInfo
|
// this is just clearing the internal sessionInfo
|
||||||
roomKey.dispose();
|
roomKey.dispose();
|
||||||
}
|
}
|
||||||
if (keyIsBestOne) {
|
if (retryEventIds?.length) {
|
||||||
// wrote the key, meaning we didn't have a better one, go ahead and reattempt decryption
|
await this._room.retryDecryption(retryEventIds);
|
||||||
await this._room.notifyRoomKey(roomKey);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (session?.algorithm) {
|
} else if (session?.algorithm) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ export class BaseRoomKey {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._sessionInfo = null;
|
this._sessionInfo = null;
|
||||||
this._isBetter = null;
|
this._isBetter = null;
|
||||||
|
this._eventIds = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async createSessionInfo(olm, pickleKey, txn) {
|
async createSessionInfo(olm, pickleKey, txn) {
|
||||||
|
@ -44,6 +45,11 @@ export class BaseRoomKey {
|
||||||
existingSession.free();
|
existingSession.free();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// store the event ids that can be decrypted with this key
|
||||||
|
// before we overwrite them if called from `write`.
|
||||||
|
if (existingSessionEntry?.eventIds) {
|
||||||
|
this._eventIds = existingSessionEntry.eventIds;
|
||||||
|
}
|
||||||
return isBetter;
|
return isBetter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +77,10 @@ export class BaseRoomKey {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get eventIds() {
|
||||||
|
return this._eventIds;
|
||||||
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
if (this._sessionInfo) {
|
if (this._sessionInfo) {
|
||||||
this._sessionInfo.release();
|
this._sessionInfo.release();
|
||||||
|
|
|
@ -55,27 +55,24 @@ export class Room extends EventEmitter {
|
||||||
this._observedEvents = null;
|
this._observedEvents = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getRetryDecryptEntriesForKey(roomKey, roomEncryption, txn) {
|
async _eventIdsToEntries(eventIds, txn) {
|
||||||
const retryEventIds = await roomEncryption.getEventIdsForMissingKey(roomKey, txn);
|
|
||||||
const retryEntries = [];
|
const retryEntries = [];
|
||||||
if (retryEventIds) {
|
await Promise.all(eventIds.map(async eventId => {
|
||||||
for (const eventId of retryEventIds) {
|
const storageEntry = await txn.timelineEvents.getByEventId(this._roomId, eventId);
|
||||||
const storageEntry = await txn.timelineEvents.getByEventId(this._roomId, eventId);
|
if (storageEntry) {
|
||||||
if (storageEntry) {
|
retryEntries.push(new EventEntry(storageEntry, this._fragmentIdComparer));
|
||||||
retryEntries.push(new EventEntry(storageEntry, this._fragmentIdComparer));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
return retryEntries;
|
return retryEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for keys received from other sources than sync, like key backup.
|
* Used for retrying decryption from other sources than sync, like key backup.
|
||||||
* @internal
|
* @internal
|
||||||
* @param {RoomKey} roomKey
|
* @param {Array<string>} eventIds
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
async notifyRoomKey(roomKey) {
|
async retryDecryption(eventIds) {
|
||||||
if (!this._roomEncryption) {
|
if (!this._roomEncryption) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +80,7 @@ export class Room extends EventEmitter {
|
||||||
this._storage.storeNames.timelineEvents,
|
this._storage.storeNames.timelineEvents,
|
||||||
this._storage.storeNames.inboundGroupSessions,
|
this._storage.storeNames.inboundGroupSessions,
|
||||||
]);
|
]);
|
||||||
const retryEntries = await this._getRetryDecryptEntriesForKey(roomKey, this._roomEncryption, txn);
|
const retryEntries = await this._eventIdsToEntries(eventIds, txn);
|
||||||
if (retryEntries.length) {
|
if (retryEntries.length) {
|
||||||
const decryptRequest = this._decryptEntries(DecryptionSource.Retry, retryEntries, txn);
|
const decryptRequest = this._decryptEntries(DecryptionSource.Retry, retryEntries, txn);
|
||||||
// this will close txn while awaiting decryption
|
// this will close txn while awaiting decryption
|
||||||
|
@ -157,8 +154,13 @@ export class Room extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getSyncRetryDecryptEntries(newKeys, roomEncryption, txn) {
|
async _getSyncRetryDecryptEntries(newKeys, roomEncryption, txn) {
|
||||||
const entriesPerKey = await Promise.all(newKeys.map(key => this._getRetryDecryptEntriesForKey(key, roomEncryption, txn)));
|
const entriesPerKey = await Promise.all(newKeys.map(async key => {
|
||||||
let retryEntries = entriesPerKey.reduce((allEntries, entries) => allEntries.concat(entries), []);
|
const retryEventIds = await roomEncryption.getEventIdsForMissingKey(key, txn);
|
||||||
|
if (retryEventIds) {
|
||||||
|
return this._eventIdsToEntries(retryEventIds, txn);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
let retryEntries = entriesPerKey.reduce((allEntries, entries) => entries ? allEntries.concat(entries) : allEntries, []);
|
||||||
// If we have the timeline open, see if there are more entries for the new keys
|
// If we have the timeline open, see if there are more entries for the new keys
|
||||||
// as we only store missing session information for synced events, not backfilled.
|
// as we only store missing session information for synced events, not backfilled.
|
||||||
// We want to decrypt all events we can though if the user is looking
|
// We want to decrypt all events we can though if the user is looking
|
||||||
|
|
Reference in a new issue