You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-28 05:03:59 +03:00
Expose function to force-reset outgoing room key requests
This commit is contained in:
87
spec/unit/crypto/outgoing-room-key-requests.spec.js
Normal file
87
spec/unit/crypto/outgoing-room-key-requests.spec.js
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
IndexedDBCryptoStore,
|
||||||
|
} from '../../../src/crypto/store/indexeddb-crypto-store';
|
||||||
|
import {MemoryCryptoStore} from '../../../src/crypto/store/memory-crypto-store';
|
||||||
|
import 'fake-indexeddb/auto';
|
||||||
|
import 'jest-localstorage-mock';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ROOM_KEY_REQUEST_STATES,
|
||||||
|
} from '../../../src/crypto/OutgoingRoomKeyRequestManager';
|
||||||
|
|
||||||
|
const requests = [
|
||||||
|
{
|
||||||
|
requestId: "A",
|
||||||
|
requestBody: { session_id: "A", room_id: "A" },
|
||||||
|
state: ROOM_KEY_REQUEST_STATES.SENT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
requestId: "B",
|
||||||
|
requestBody: { session_id: "B", room_id: "B" },
|
||||||
|
state: ROOM_KEY_REQUEST_STATES.SENT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
requestId: "C",
|
||||||
|
requestBody: { session_id: "C", room_id: "C" },
|
||||||
|
state: ROOM_KEY_REQUEST_STATES.UNSENT,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
describe.each([
|
||||||
|
["IndexedDBCryptoStore",
|
||||||
|
() => new IndexedDBCryptoStore(global.indexedDB, "tests")],
|
||||||
|
["LocalStorageCryptoStore",
|
||||||
|
() => new IndexedDBCryptoStore(undefined, "tests")],
|
||||||
|
["MemoryCryptoStore", () => {
|
||||||
|
const store = new IndexedDBCryptoStore(undefined, "tests");
|
||||||
|
store._backend = new MemoryCryptoStore();
|
||||||
|
store._backendPromise = Promise.resolve(store._backend);
|
||||||
|
return store;
|
||||||
|
}],
|
||||||
|
])("Outgoing room key requests [%s]", function(name, dbFactory) {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
store = dbFactory();
|
||||||
|
await store.startup();
|
||||||
|
await Promise.all(requests.map((request) =>
|
||||||
|
store.getOrAddOutgoingRoomKeyRequest(request),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("getAllOutgoingRoomKeyRequestsByState retrieves all entries in a given state",
|
||||||
|
async () => {
|
||||||
|
const r = await
|
||||||
|
store.getAllOutgoingRoomKeyRequestsByState(ROOM_KEY_REQUEST_STATES.SENT);
|
||||||
|
expect(r).toHaveLength(2);
|
||||||
|
requests.filter((e) => e.state == ROOM_KEY_REQUEST_STATES.SENT).forEach((e) => {
|
||||||
|
expect(r).toContainEqual(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getOutgoingRoomKeyRequestByState retrieves any entry in a given state",
|
||||||
|
async () => {
|
||||||
|
const r =
|
||||||
|
await store.getOutgoingRoomKeyRequestByState([ROOM_KEY_REQUEST_STATES.SENT]);
|
||||||
|
expect(r).not.toBeNull();
|
||||||
|
expect(r).not.toBeUndefined();
|
||||||
|
expect(r.state).toEqual(ROOM_KEY_REQUEST_STATES.SENT);
|
||||||
|
expect(requests).toContainEqual(r);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -58,7 +58,7 @@ const SEND_KEY_REQUESTS_DELAY_MS = 500;
|
|||||||
*
|
*
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
*/
|
*/
|
||||||
const ROOM_KEY_REQUEST_STATES = {
|
export const ROOM_KEY_REQUEST_STATES = {
|
||||||
/** request not yet sent */
|
/** request not yet sent */
|
||||||
UNSENT: 0,
|
UNSENT: 0,
|
||||||
|
|
||||||
@@ -327,6 +327,21 @@ export class OutgoingRoomKeyRequestManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find anything in `sent` state, and kick it around the loop again.
|
||||||
|
* This is intended for situations where something substantial has changed, and we
|
||||||
|
* don't really expect the other end to even care about the cancellation.
|
||||||
|
* For example, after initialization or self-verification.
|
||||||
|
* @return {Promise} An array of `sendRoomKeyRequest` outputs.
|
||||||
|
*/
|
||||||
|
async cancelAndResendAllOutgoingRequests() {
|
||||||
|
const outgoings = await this._cryptoStore.getAllOutgoingRoomKeyRequestsByState(
|
||||||
|
ROOM_KEY_REQUEST_STATES.SENT,
|
||||||
|
);
|
||||||
|
return Promise.all(outgoings.map(({ requestBody, recipients }) =>
|
||||||
|
this.sendRoomKeyRequest(requestBody, recipients, true)));
|
||||||
|
}
|
||||||
|
|
||||||
// start the background timer to send queued requests, if the timer isn't
|
// start the background timer to send queued requests, if the timer isn't
|
||||||
// already running
|
// already running
|
||||||
_startTimer() {
|
_startTimer() {
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ export class Backend {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const txn = this._db.transaction("outgoingRoomKeyRequests", "readwrite");
|
const txn = this._db.transaction("outgoingRoomKeyRequests", "readwrite");
|
||||||
txn.onerror = reject;
|
txn.onerror = reject;
|
||||||
|
txn.onabort = (ev) => reject(ev.target.error);
|
||||||
|
|
||||||
// first see if we already have an entry for this request.
|
// first see if we already have an entry for this request.
|
||||||
this._getOutgoingRoomKeyRequest(txn, requestBody, (existing) => {
|
this._getOutgoingRoomKeyRequest(txn, requestBody, (existing) => {
|
||||||
@@ -203,6 +204,24 @@ export class Backend {
|
|||||||
return promiseifyTxn(txn).then(() => result);
|
return promiseifyTxn(txn).then(() => result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Number} wantedState
|
||||||
|
* @return {Promise<Array<*>>} All elements in a given state
|
||||||
|
*/
|
||||||
|
getAllOutgoingRoomKeyRequestsByState(wantedState) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const txn = this._db.transaction("outgoingRoomKeyRequests", "readonly");
|
||||||
|
const store = txn.objectStore("outgoingRoomKeyRequests");
|
||||||
|
const index = store.index("state");
|
||||||
|
const request = index.getAll(wantedState);
|
||||||
|
|
||||||
|
request.onsuccess = (ev) => resolve(ev.target.result);
|
||||||
|
request.onerror = (ev) => reject(ev.target.error);
|
||||||
|
request.onabort = (ev) => reject(ev.target.error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getOutgoingRoomKeyRequestsByTarget(userId, deviceId, wantedStates) {
|
getOutgoingRoomKeyRequestsByTarget(userId, deviceId, wantedStates) {
|
||||||
let stateIndex = 0;
|
let stateIndex = 0;
|
||||||
const results = [];
|
const results = [];
|
||||||
|
|||||||
@@ -225,6 +225,17 @@ export class IndexedDBCryptoStore {
|
|||||||
return this._backend.getOutgoingRoomKeyRequestByState(wantedStates);
|
return this._backend.getOutgoingRoomKeyRequestByState(wantedStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look for room key requests by state –
|
||||||
|
* unlike above, return a list of all entries in one state.
|
||||||
|
*
|
||||||
|
* @param {Number} wantedState
|
||||||
|
* @return {Promise<Array<*>>} Returns an array of requests in the given state
|
||||||
|
*/
|
||||||
|
getAllOutgoingRoomKeyRequestsByState(wantedState) {
|
||||||
|
return this._backend.getAllOutgoingRoomKeyRequestsByState(wantedState);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look for room key requests by target device and state
|
* Look for room key requests by target device and state
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -166,6 +166,19 @@ export class MemoryCryptoStore {
|
|||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Number} wantedState
|
||||||
|
* @return {Promise<Array<*>>} All OutgoingRoomKeyRequests in state
|
||||||
|
*/
|
||||||
|
getAllOutgoingRoomKeyRequestsByState(wantedState) {
|
||||||
|
return Promise.resolve(
|
||||||
|
this._outgoingRoomKeyRequests.filter(
|
||||||
|
(r) => r.state == wantedState,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
getOutgoingRoomKeyRequestsByTarget(userId, deviceId, wantedStates) {
|
getOutgoingRoomKeyRequestsByTarget(userId, deviceId, wantedStates) {
|
||||||
const results = [];
|
const results = [];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user