You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-26 17:03:12 +03:00
Merge pull request #1640 from uhoreg/room-history-key-sharing2
Add function to share megolm keys for historical messages.
This commit is contained in:
@@ -2303,6 +2303,39 @@ MatrixClient.prototype.deleteKeysFromBackup = function(roomId, sessionId, versio
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Share shared-history decryption keys with the given users.
|
||||
*
|
||||
* @param {string} roomId the room for which keys should be shared.
|
||||
* @param {array} userIds a list of users to share with. The keys will be sent to
|
||||
* all of the user's current devices.
|
||||
*/
|
||||
MatrixClient.prototype.sendSharedHistoryKeys = async function(roomId, userIds) {
|
||||
if (this._crypto === null) {
|
||||
throw new Error("End-to-end encryption disabled");
|
||||
}
|
||||
|
||||
const roomEncryption = this._roomList.getRoomEncryption(roomId);
|
||||
if (!roomEncryption) {
|
||||
// unknown room, or unencrypted room
|
||||
logger.error("Unknown room. Not sharing decryption keys");
|
||||
return;
|
||||
}
|
||||
|
||||
const deviceInfos = await this._crypto.downloadKeys(userIds);
|
||||
const devicesByUser = {};
|
||||
for (const [userId, devices] of Object.entries(deviceInfos)) {
|
||||
devicesByUser[userId] = Object.values(devices);
|
||||
}
|
||||
|
||||
const alg = this._crypto._getRoomDecryptor(roomId, roomEncryption.algorithm);
|
||||
if (alg.sendSharedHistoryInboundSessions) {
|
||||
await alg.sendSharedHistoryInboundSessions(devicesByUser);
|
||||
} else {
|
||||
logger.warning("Algorithm does not support sharing previous keys", roomEncryption.algorithm);
|
||||
}
|
||||
};
|
||||
|
||||
// Group ops
|
||||
// =========
|
||||
// Operations on groups that come down the sync stream (ie. ones the
|
||||
|
||||
@@ -1048,6 +1048,7 @@ OlmDevice.prototype.addInboundGroupSession = async function(
|
||||
'readwrite', [
|
||||
IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS,
|
||||
IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS_WITHHELD,
|
||||
IndexedDBCryptoStore.STORE_SHARED_HISTORY_INBOUND_GROUP_SESSIONS,
|
||||
], (txn) => {
|
||||
/* if we already have this session, consider updating it */
|
||||
this._getInboundGroupSession(
|
||||
@@ -1104,6 +1105,12 @@ OlmDevice.prototype.addInboundGroupSession = async function(
|
||||
this._cryptoStore.storeEndToEndInboundGroupSession(
|
||||
senderKey, sessionId, sessionData, txn,
|
||||
);
|
||||
|
||||
if (!existingSession && extraSessionData.sharedHistory) {
|
||||
this._cryptoStore.addSharedHistoryInboundGroupSession(
|
||||
roomId, senderKey, sessionId, txn,
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
session.free();
|
||||
}
|
||||
@@ -1383,6 +1390,7 @@ OlmDevice.prototype.getInboundGroupSessionKey = async function(
|
||||
"forwarding_curve25519_key_chain":
|
||||
sessionData.forwardingCurve25519KeyChain || [],
|
||||
"sender_claimed_ed25519_key": senderEd25519Key,
|
||||
"shared_history": sessionData.sharedHistory || false,
|
||||
};
|
||||
},
|
||||
);
|
||||
@@ -1415,10 +1423,24 @@ OlmDevice.prototype.exportInboundGroupSession = function(
|
||||
"session_key": session.export_session(messageIndex),
|
||||
"forwarding_curve25519_key_chain": session.forwardingCurve25519KeyChain || [],
|
||||
"first_known_index": session.first_known_index(),
|
||||
"org.matrix.msc3061.shared_history": sessionData.sharedHistory || false,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
OlmDevice.prototype.getSharedHistoryInboundGroupSessions = async function(roomId) {
|
||||
let result;
|
||||
await this._cryptoStore.doTxn(
|
||||
'readonly', [
|
||||
IndexedDBCryptoStore.STORE_SHARED_HISTORY_INBOUND_GROUP_SESSIONS,
|
||||
], (txn) => {
|
||||
result = this._cryptoStore.getSharedHistoryInboundGroupSessions(roomId, txn);
|
||||
},
|
||||
logger.withPrefix("[getSharedHistoryInboundGroupSessionsForRoom]"),
|
||||
);
|
||||
return result;
|
||||
};
|
||||
|
||||
// Utilities
|
||||
// =========
|
||||
|
||||
|
||||
@@ -36,11 +36,27 @@ import {
|
||||
|
||||
import {WITHHELD_MESSAGES} from '../OlmDevice';
|
||||
|
||||
// determine whether the key can be shared with invitees
|
||||
function isRoomSharedHistory(room) {
|
||||
const visibilityEvent = room.currentState &&
|
||||
room.currentState.getStateEvents("m.room.history_visibility", "");
|
||||
// NOTE: if the room visibility is unset, it would normally default to
|
||||
// "world_readable".
|
||||
// (https://spec.matrix.org/unstable/client-server-api/#server-behaviour-5)
|
||||
// But we will be paranoid here, and treat it as a situation where the room
|
||||
// is not shared-history
|
||||
const visibility = visibilityEvent && visibilityEvent.getContent() &&
|
||||
visibilityEvent.getContent().history_visibility;
|
||||
return ["world_readable", "shared"].includes(visibility);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @constructor
|
||||
*
|
||||
* @param {string} sessionId
|
||||
* @param {boolean} sharedHistory whether the session can be freely shared with
|
||||
* other group members, according to the room history visibility settings
|
||||
*
|
||||
* @property {string} sessionId
|
||||
* @property {Number} useCount number of times this session has been used
|
||||
@@ -50,12 +66,13 @@ import {WITHHELD_MESSAGES} from '../OlmDevice';
|
||||
* devices with which we have shared the session key
|
||||
* userId -> {deviceId -> msgindex}
|
||||
*/
|
||||
function OutboundSessionInfo(sessionId) {
|
||||
function OutboundSessionInfo(sessionId, sharedHistory = false) {
|
||||
this.sessionId = sessionId;
|
||||
this.useCount = 0;
|
||||
this.creationTime = new Date().getTime();
|
||||
this.sharedWithDevices = {};
|
||||
this.blockedDevicesNotified = {};
|
||||
this.sharedHistory = sharedHistory;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +200,7 @@ utils.inherits(MegolmEncryption, EncryptionAlgorithm);
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* @param {module:models/room} room
|
||||
* @param {Object} devicesInRoom The devices in this room, indexed by user ID
|
||||
* @param {Object} blocked The devices that are blocked, indexed by user ID
|
||||
* @param {boolean} [singleOlmCreationPhase] Only perform one round of olm
|
||||
@@ -192,7 +210,7 @@ utils.inherits(MegolmEncryption, EncryptionAlgorithm);
|
||||
* OutboundSessionInfo when setup is complete.
|
||||
*/
|
||||
MegolmEncryption.prototype._ensureOutboundSession = async function(
|
||||
devicesInRoom, blocked, singleOlmCreationPhase,
|
||||
room, devicesInRoom, blocked, singleOlmCreationPhase,
|
||||
) {
|
||||
let session;
|
||||
|
||||
@@ -204,6 +222,13 @@ MegolmEncryption.prototype._ensureOutboundSession = async function(
|
||||
const prepareSession = async (oldSession) => {
|
||||
session = oldSession;
|
||||
|
||||
const sharedHistory = isRoomSharedHistory(room);
|
||||
|
||||
// history visibility changed
|
||||
if (session && sharedHistory !== session.sharedHistory) {
|
||||
session = null;
|
||||
}
|
||||
|
||||
// need to make a brand new session?
|
||||
if (session && session.needsRotation(this._sessionRotationPeriodMsgs,
|
||||
this._sessionRotationPeriodMs)
|
||||
@@ -219,7 +244,7 @@ MegolmEncryption.prototype._ensureOutboundSession = async function(
|
||||
|
||||
if (!session) {
|
||||
logger.log(`Starting new megolm session for room ${this._roomId}`);
|
||||
session = await this._prepareNewSession();
|
||||
session = await this._prepareNewSession(sharedHistory);
|
||||
logger.log(`Started new megolm session ${session.sessionId} ` +
|
||||
`for room ${this._roomId}`);
|
||||
this._outboundSessions[session.sessionId] = session;
|
||||
@@ -250,11 +275,12 @@ MegolmEncryption.prototype._ensureOutboundSession = async function(
|
||||
const payload = {
|
||||
type: "m.room_key",
|
||||
content: {
|
||||
algorithm: olmlib.MEGOLM_ALGORITHM,
|
||||
room_id: this._roomId,
|
||||
session_id: session.sessionId,
|
||||
session_key: key.key,
|
||||
chain_index: key.chain_index,
|
||||
"algorithm": olmlib.MEGOLM_ALGORITHM,
|
||||
"room_id": this._roomId,
|
||||
"session_id": session.sessionId,
|
||||
"session_key": key.key,
|
||||
"chain_index": key.chain_index,
|
||||
"org.matrix.msc3061.shared_history": sharedHistory,
|
||||
},
|
||||
};
|
||||
const [devicesWithoutSession, olmSessions] = await olmlib.getExistingOlmSessions(
|
||||
@@ -374,15 +400,18 @@ MegolmEncryption.prototype._ensureOutboundSession = async function(
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* @param {boolean} sharedHistory
|
||||
*
|
||||
* @return {module:crypto/algorithms/megolm.OutboundSessionInfo} session
|
||||
*/
|
||||
MegolmEncryption.prototype._prepareNewSession = async function() {
|
||||
MegolmEncryption.prototype._prepareNewSession = async function(sharedHistory) {
|
||||
const sessionId = this._olmDevice.createOutboundGroupSession();
|
||||
const key = this._olmDevice.getOutboundGroupSessionKey(sessionId);
|
||||
|
||||
await this._olmDevice.addInboundGroupSession(
|
||||
this._roomId, this._olmDevice.deviceCurve25519Key, [], sessionId,
|
||||
key.key, {ed25519: this._olmDevice.deviceEd25519Key},
|
||||
key.key, {ed25519: this._olmDevice.deviceEd25519Key}, false,
|
||||
{sharedHistory: sharedHistory},
|
||||
);
|
||||
|
||||
// don't wait for it to complete
|
||||
@@ -391,7 +420,7 @@ MegolmEncryption.prototype._prepareNewSession = async function() {
|
||||
sessionId, key.key,
|
||||
);
|
||||
|
||||
return new OutboundSessionInfo(sessionId);
|
||||
return new OutboundSessionInfo(sessionId, sharedHistory);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -672,14 +701,15 @@ MegolmEncryption.prototype.reshareKeyWithDevice = async function(
|
||||
const payload = {
|
||||
type: "m.forwarded_room_key",
|
||||
content: {
|
||||
algorithm: olmlib.MEGOLM_ALGORITHM,
|
||||
room_id: this._roomId,
|
||||
session_id: sessionId,
|
||||
session_key: key.key,
|
||||
chain_index: key.chain_index,
|
||||
sender_key: senderKey,
|
||||
sender_claimed_ed25519_key: key.sender_claimed_ed25519_key,
|
||||
forwarding_curve25519_key_chain: key.forwarding_curve25519_key_chain,
|
||||
"algorithm": olmlib.MEGOLM_ALGORITHM,
|
||||
"room_id": this._roomId,
|
||||
"session_id": sessionId,
|
||||
"session_key": key.key,
|
||||
"chain_index": key.chain_index,
|
||||
"sender_key": senderKey,
|
||||
"sender_claimed_ed25519_key": key.sender_claimed_ed25519_key,
|
||||
"forwarding_curve25519_key_chain": key.forwarding_curve25519_key_chain,
|
||||
"org.matrix.msc3061.shared_history": key.shared_history || false,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -901,7 +931,7 @@ MegolmEncryption.prototype.prepareToEncrypt = function(room) {
|
||||
}
|
||||
|
||||
logger.debug(`Ensuring outbound session in ${this._roomId}`);
|
||||
await this._ensureOutboundSession(devicesInRoom, blocked, true);
|
||||
await this._ensureOutboundSession(room, devicesInRoom, blocked, true);
|
||||
|
||||
logger.debug(`Ready to encrypt events for ${this._roomId}`);
|
||||
} catch (e) {
|
||||
@@ -945,7 +975,7 @@ MegolmEncryption.prototype.encryptMessage = async function(room, eventType, cont
|
||||
this._checkForUnknownDevices(devicesInRoom);
|
||||
}
|
||||
|
||||
const session = await this._ensureOutboundSession(devicesInRoom, blocked);
|
||||
const session = await this._ensureOutboundSession(room, devicesInRoom, blocked);
|
||||
const payloadJson = {
|
||||
room_id: this._roomId,
|
||||
type: eventType,
|
||||
@@ -1370,10 +1400,14 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
|
||||
keysClaimed = event.getKeysClaimed();
|
||||
}
|
||||
|
||||
const extraSessionData = {};
|
||||
if (content["org.matrix.msc3061.shared_history"]) {
|
||||
extraSessionData.sharedHistory = true;
|
||||
}
|
||||
return this._olmDevice.addInboundGroupSession(
|
||||
content.room_id, senderKey, forwardingKeyChain, sessionId,
|
||||
content.session_key, keysClaimed,
|
||||
exportFormat,
|
||||
exportFormat, extraSessionData,
|
||||
).then(() => {
|
||||
// have another go at decrypting events sent with this session.
|
||||
this._retryDecryption(senderKey, sessionId)
|
||||
@@ -1573,14 +1607,15 @@ MegolmDecryption.prototype._buildKeyForwardingMessage = async function(
|
||||
return {
|
||||
type: "m.forwarded_room_key",
|
||||
content: {
|
||||
algorithm: olmlib.MEGOLM_ALGORITHM,
|
||||
room_id: roomId,
|
||||
sender_key: senderKey,
|
||||
sender_claimed_ed25519_key: key.sender_claimed_ed25519_key,
|
||||
session_id: sessionId,
|
||||
session_key: key.key,
|
||||
chain_index: key.chain_index,
|
||||
forwarding_curve25519_key_chain: key.forwarding_curve25519_key_chain,
|
||||
"algorithm": olmlib.MEGOLM_ALGORITHM,
|
||||
"room_id": roomId,
|
||||
"sender_key": senderKey,
|
||||
"sender_claimed_ed25519_key": key.sender_claimed_ed25519_key,
|
||||
"session_id": sessionId,
|
||||
"session_key": key.key,
|
||||
"chain_index": key.chain_index,
|
||||
"forwarding_curve25519_key_chain": key.forwarding_curve25519_key_chain,
|
||||
"org.matrix.msc3061.shared_history": key.shared_history || false,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1594,6 +1629,13 @@ MegolmDecryption.prototype._buildKeyForwardingMessage = async function(
|
||||
* @param {string} [opts.source] where the key came from
|
||||
*/
|
||||
MegolmDecryption.prototype.importRoomKey = function(session, opts = {}) {
|
||||
const extraSessionData = {};
|
||||
if (opts.untrusted) {
|
||||
extraSessionData.untrusted = true;
|
||||
}
|
||||
if (session["org.matrix.msc3061.shared_history"]) {
|
||||
extraSessionData.sharedHistory = true;
|
||||
}
|
||||
return this._olmDevice.addInboundGroupSession(
|
||||
session.room_id,
|
||||
session.sender_key,
|
||||
@@ -1602,7 +1644,7 @@ MegolmDecryption.prototype.importRoomKey = function(session, opts = {}) {
|
||||
session.session_key,
|
||||
session.sender_claimed_keys,
|
||||
true,
|
||||
opts.untrusted ? { untrusted: opts.untrusted } : {},
|
||||
extraSessionData,
|
||||
).then(() => {
|
||||
if (opts.source !== "backup") {
|
||||
// don't wait for it to complete
|
||||
@@ -1681,6 +1723,80 @@ MegolmDecryption.prototype.retryDecryptionFromSender = async function(senderKey)
|
||||
return !this._pendingEvents[senderKey];
|
||||
};
|
||||
|
||||
MegolmDecryption.prototype.sendSharedHistoryInboundSessions = async function(devicesByUser) {
|
||||
await olmlib.ensureOlmSessionsForDevices(
|
||||
this._olmDevice, this._baseApis, devicesByUser,
|
||||
);
|
||||
|
||||
logger.log("sendSharedHistoryInboundSessions to users", Object.keys(devicesByUser));
|
||||
|
||||
const sharedHistorySessions =
|
||||
await this._olmDevice.getSharedHistoryInboundGroupSessions(
|
||||
this._roomId,
|
||||
);
|
||||
logger.log("shared-history sessions", sharedHistorySessions);
|
||||
for (const [senderKey, sessionId] of sharedHistorySessions) {
|
||||
const payload = await this._buildKeyForwardingMessage(
|
||||
this._roomId, senderKey, sessionId,
|
||||
);
|
||||
|
||||
const promises = [];
|
||||
const contentMap = {};
|
||||
for (const [userId, devices] of Object.entries(devicesByUser)) {
|
||||
contentMap[userId] = {};
|
||||
for (const deviceInfo of devices) {
|
||||
const encryptedContent = {
|
||||
algorithm: olmlib.OLM_ALGORITHM,
|
||||
sender_key: this._olmDevice.deviceCurve25519Key,
|
||||
ciphertext: {},
|
||||
};
|
||||
contentMap[userId][deviceInfo.deviceId] = encryptedContent;
|
||||
promises.push(
|
||||
olmlib.encryptMessageForDevice(
|
||||
encryptedContent.ciphertext,
|
||||
this._userId,
|
||||
this._deviceId,
|
||||
this._olmDevice,
|
||||
userId,
|
||||
deviceInfo,
|
||||
payload,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
// prune out any devices that encryptMessageForDevice could not encrypt for,
|
||||
// in which case it will have just not added anything to the ciphertext object.
|
||||
// There's no point sending messages to devices if we couldn't encrypt to them,
|
||||
// since that's effectively a blank message.
|
||||
for (const userId of Object.keys(contentMap)) {
|
||||
for (const deviceId of Object.keys(contentMap[userId])) {
|
||||
if (Object.keys(contentMap[userId][deviceId].ciphertext).length === 0) {
|
||||
logger.log(
|
||||
"No ciphertext for device " +
|
||||
userId + ":" + deviceId + ": pruning",
|
||||
);
|
||||
delete contentMap[userId][deviceId];
|
||||
}
|
||||
}
|
||||
// No devices left for that user? Strip that too.
|
||||
if (Object.keys(contentMap[userId]).length === 0) {
|
||||
logger.log("Pruned all devices for user " + userId);
|
||||
delete contentMap[userId];
|
||||
}
|
||||
}
|
||||
|
||||
// Is there anything left?
|
||||
if (Object.keys(contentMap).length === 0) {
|
||||
logger.log("No users left to send to: aborting");
|
||||
return;
|
||||
}
|
||||
|
||||
await this._baseApis.sendToDevice("m.room.encrypted", contentMap);
|
||||
}
|
||||
};
|
||||
|
||||
registerAlgorithm(
|
||||
olmlib.MEGOLM_ALGORITHM, MegolmEncryption, MegolmDecryption,
|
||||
);
|
||||
|
||||
@@ -19,7 +19,7 @@ limitations under the License.
|
||||
import {logger} from '../../logger';
|
||||
import * as utils from "../../utils";
|
||||
|
||||
export const VERSION = 9;
|
||||
export const VERSION = 10;
|
||||
const PROFILE_TRANSACTIONS = false;
|
||||
|
||||
/**
|
||||
@@ -759,6 +759,38 @@ export class Backend {
|
||||
}));
|
||||
}
|
||||
|
||||
addSharedHistoryInboundGroupSession(roomId, senderKey, sessionId, txn) {
|
||||
if (!txn) {
|
||||
txn = this._db.transaction(
|
||||
"shared_history_inbound_group_sessions", "readwrite",
|
||||
);
|
||||
}
|
||||
const objectStore = txn.objectStore("shared_history_inbound_group_sessions");
|
||||
const req = objectStore.get([roomId]);
|
||||
req.onsuccess = () => {
|
||||
const {sessions} = req.result || {sessions: []};
|
||||
sessions.push([senderKey, sessionId]);
|
||||
objectStore.put({roomId, sessions});
|
||||
};
|
||||
}
|
||||
|
||||
getSharedHistoryInboundGroupSessions(roomId, txn) {
|
||||
if (!txn) {
|
||||
txn = this._db.transaction(
|
||||
"shared_history_inbound_group_sessions", "readonly",
|
||||
);
|
||||
}
|
||||
const objectStore = txn.objectStore("shared_history_inbound_group_sessions");
|
||||
const req = objectStore.get([roomId]);
|
||||
return new Promise((resolve, reject) => {
|
||||
req.onsuccess = () => {
|
||||
const {sessions} = req.result || {sessions: []};
|
||||
resolve(sessions);
|
||||
};
|
||||
req.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
doTxn(mode, stores, func, log = logger) {
|
||||
let startTime;
|
||||
let description;
|
||||
@@ -834,6 +866,11 @@ export function upgradeDatabase(db, oldVersion) {
|
||||
keyPath: ["userId", "deviceId"],
|
||||
});
|
||||
}
|
||||
if (oldVersion < 10) {
|
||||
db.createObjectStore("shared_history_inbound_group_sessions", {
|
||||
keyPath: ["roomId"],
|
||||
});
|
||||
}
|
||||
// Expand as needed.
|
||||
}
|
||||
|
||||
|
||||
@@ -582,6 +582,29 @@ export class IndexedDBCryptoStore {
|
||||
return this._backend.markSessionsNeedingBackup(sessions, txn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a shared-history group session for a room.
|
||||
* @param {string} roomId The room that the key belongs to
|
||||
* @param {string} senderKey The sender's curve 25519 key
|
||||
* @param {string} sessionId The ID of the session
|
||||
* @param {*} txn An active transaction. See doTxn(). (optional)
|
||||
*/
|
||||
addSharedHistoryInboundGroupSession(roomId, senderKey, sessionId, txn) {
|
||||
this._backend.addSharedHistoryInboundGroupSession(
|
||||
roomId, senderKey, sessionId, txn,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the shared-history group session for a room.
|
||||
* @param {string} roomId The room that the key belongs to
|
||||
* @param {*} txn An active transaction. See doTxn(). (optional)
|
||||
* @returns {Promise} Resolves to an array of [senderKey, sessionId]
|
||||
*/
|
||||
getSharedHistoryInboundGroupSessions(roomId, txn) {
|
||||
return this._backend.getSharedHistoryInboundGroupSessions(roomId, txn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a transaction on the crypto store. Any store methods
|
||||
* that require a transaction (txn) object to be passed in may
|
||||
@@ -614,6 +637,8 @@ IndexedDBCryptoStore.STORE_SESSIONS = 'sessions';
|
||||
IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS = 'inbound_group_sessions';
|
||||
IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS_WITHHELD
|
||||
= 'inbound_group_sessions_withheld';
|
||||
IndexedDBCryptoStore.STORE_SHARED_HISTORY_INBOUND_GROUP_SESSIONS
|
||||
= 'shared_history_inbound_group_sessions';
|
||||
IndexedDBCryptoStore.STORE_DEVICE_DATA = 'device_data';
|
||||
IndexedDBCryptoStore.STORE_ROOMS = 'rooms';
|
||||
IndexedDBCryptoStore.STORE_BACKUP = 'sessions_needing_backup';
|
||||
|
||||
@@ -51,6 +51,8 @@ export class MemoryCryptoStore {
|
||||
this._rooms = {};
|
||||
// Set of {senderCurve25519Key+'/'+sessionId}
|
||||
this._sessionsNeedingBackup = {};
|
||||
// roomId -> array of [senderKey, sessionId]
|
||||
this._sharedHistoryInboundGroupSessions = {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -467,6 +469,16 @@ export class MemoryCryptoStore {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
addSharedHistoryInboundGroupSession(roomId, senderKey, sessionId) {
|
||||
const sessions = this._sharedHistoryInboundGroupSessions[roomId] || [];
|
||||
sessions.push([senderKey, sessionId]);
|
||||
this._sharedHistoryInboundGroupSessions[roomId] = sessions;
|
||||
}
|
||||
|
||||
getSharedHistoryInboundGroupSessions(roomId) {
|
||||
return Promise.resolve(this._sharedHistoryInboundGroupSessions[roomId] || []);
|
||||
}
|
||||
|
||||
// Session key backups
|
||||
|
||||
doTxn(mode, stores, func) {
|
||||
|
||||
Reference in New Issue
Block a user