mirror of
https://github.com/Skylar-Tech/node-red-contrib-matrix-chat.git
synced 2026-05-25 08:33:38 -06:00
Compare commits
1 Commits
v1.0.0-beta.2
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| bc97c564d3 |
@@ -17,6 +17,13 @@ const v8 = require('v8');
|
|||||||
|
|
||||||
let shimInstalled = false;
|
let shimInstalled = false;
|
||||||
|
|
||||||
|
// Mirrors matrix-js-sdk's localStorage-crypto-store.js: olm sessions live under
|
||||||
|
// "crypto.sessions/<deviceKey>" and migration batches are capped at 50.
|
||||||
|
const E2E_PREFIX = 'crypto.';
|
||||||
|
const SESSION_KEY_PREFIX = E2E_PREFIX + 'sessions/';
|
||||||
|
const SESSION_BATCH_SIZE = 50;
|
||||||
|
const OLM_BATCH_PATCH_MARKER = Symbol.for('node-red-contrib-matrix-chat.olmSessionBatchPatched');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install the in-memory IndexedDB shim onto globalThis. Idempotent. Must be
|
* Install the in-memory IndexedDB shim onto globalThis. Idempotent. Must be
|
||||||
* called before MatrixClient.initRustCrypto().
|
* called before MatrixClient.initRustCrypto().
|
||||||
@@ -172,4 +179,70 @@ async function snapshotCryptoStore(filePath, dbNamePrefix) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { ensureIndexedDBShim, restoreCryptoStore, snapshotCryptoStore };
|
/**
|
||||||
|
* Patch a LocalStorageCryptoStore instance so its getEndToEndSessionsBatch()
|
||||||
|
* returns olm sessions with deviceKey/sessionId attached.
|
||||||
|
*
|
||||||
|
* Why: matrix-js-sdk's LocalStorageCryptoStore stores olm sessions as
|
||||||
|
* `{ session, lastReceivedMessageTs }` with the curve25519 deviceKey encoded
|
||||||
|
* only in the localStorage key ("crypto.sessions/<deviceKey>"). On read,
|
||||||
|
* getEndToEndSessionsBatch() returns the bare session value without injecting
|
||||||
|
* the deviceKey or sessionId, so initRustCrypto()'s libolm-to-rust migration
|
||||||
|
* crashes at PickledSession.senderKey = session.deviceKey (undefined). The
|
||||||
|
* IndexedDB backend stores those fields in the record and is unaffected.
|
||||||
|
*
|
||||||
|
* Idempotent and safe to call on a store with no legacy sessions.
|
||||||
|
*/
|
||||||
|
function patchLocalStorageCryptoStoreForRustMigration(cryptoStore) {
|
||||||
|
if (!cryptoStore || cryptoStore[OLM_BATCH_PATCH_MARKER]) {
|
||||||
|
return cryptoStore;
|
||||||
|
}
|
||||||
|
const store = cryptoStore.store;
|
||||||
|
if (!store || typeof store.length !== 'number' || typeof store.key !== 'function') {
|
||||||
|
return cryptoStore;
|
||||||
|
}
|
||||||
|
cryptoStore.getEndToEndSessionsBatch = async function() {
|
||||||
|
const result = [];
|
||||||
|
for (let i = 0; i < store.length; i++) {
|
||||||
|
const key = store.key(i);
|
||||||
|
if (!key || !key.startsWith(SESSION_KEY_PREFIX)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const deviceKey = key.slice(SESSION_KEY_PREFIX.length);
|
||||||
|
let sessions;
|
||||||
|
try {
|
||||||
|
const raw = store.getItem(key);
|
||||||
|
sessions = raw ? JSON.parse(raw) : null;
|
||||||
|
} catch (e) {
|
||||||
|
sessions = null;
|
||||||
|
}
|
||||||
|
if (!sessions || typeof sessions !== 'object') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const [sessionId, val] of Object.entries(sessions)) {
|
||||||
|
if (val === null || val === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Mirrors LocalStorageCryptoStore._getEndToEndSessions: very old
|
||||||
|
// entries were stored as bare base64 pickle strings.
|
||||||
|
const sessionInfo = (typeof val === 'string')
|
||||||
|
? { session: val, lastReceivedMessageTs: 0 }
|
||||||
|
: val;
|
||||||
|
result.push({ ...sessionInfo, deviceKey, sessionId });
|
||||||
|
if (result.length >= SESSION_BATCH_SIZE) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.length === 0 ? null : result;
|
||||||
|
};
|
||||||
|
cryptoStore[OLM_BATCH_PATCH_MARKER] = true;
|
||||||
|
return cryptoStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
ensureIndexedDBShim,
|
||||||
|
restoreCryptoStore,
|
||||||
|
snapshotCryptoStore,
|
||||||
|
patchLocalStorageCryptoStoreForRustMigration,
|
||||||
|
};
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ const cryptoApiPromise = import("matrix-js-sdk/lib/crypto-api/index.js");
|
|||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const { resolve } = require('path');
|
const { resolve } = require('path');
|
||||||
const { LocalStorage } = require('node-localstorage');
|
const { LocalStorage } = require('node-localstorage');
|
||||||
const { ensureIndexedDBShim, restoreCryptoStore, snapshotCryptoStore } = require('./matrix-crypto-store');
|
const {
|
||||||
|
ensureIndexedDBShim,
|
||||||
|
restoreCryptoStore,
|
||||||
|
snapshotCryptoStore,
|
||||||
|
patchLocalStorageCryptoStoreForRustMigration,
|
||||||
|
} = require('./matrix-crypto-store');
|
||||||
require("abort-controller/polyfill"); // polyfill abort-controller if we don't have it
|
require("abort-controller/polyfill"); // polyfill abort-controller if we don't have it
|
||||||
if (!globalThis.fetch) {
|
if (!globalThis.fetch) {
|
||||||
// polyfill fetch if we don't have it
|
// polyfill fetch if we don't have it
|
||||||
@@ -453,8 +458,13 @@ module.exports = function(RED) {
|
|||||||
if(node.e2ee) {
|
if(node.e2ee) {
|
||||||
// Provide the legacy (pre-v37 libolm) crypto store so that
|
// Provide the legacy (pre-v37 libolm) crypto store so that
|
||||||
// initRustCrypto() can perform a one-time migration of any
|
// initRustCrypto() can perform a one-time migration of any
|
||||||
// existing crypto state into the Rust crypto store.
|
// existing crypto state into the Rust crypto store. Patch
|
||||||
clientOpts.cryptoStore = new LocalStorageCryptoStore(localStorage);
|
// the store because matrix-js-sdk's LocalStorageCryptoStore
|
||||||
|
// omits deviceKey/sessionId from getEndToEndSessionsBatch(),
|
||||||
|
// which breaks the libolm->rust olm-session migration.
|
||||||
|
clientOpts.cryptoStore = patchLocalStorageCryptoStoreForRustMigration(
|
||||||
|
new LocalStorageCryptoStore(localStorage)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
node.matrixClient = sdk.createClient(clientOpts);
|
node.matrixClient = sdk.createClient(clientOpts);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user