matrix-js-sdk 41.3.0 → 41.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/lib/@types/event.d.ts +9 -0
- package/lib/@types/event.d.ts.map +1 -1
- package/lib/@types/event.js.map +1 -1
- package/lib/crypto-api/index.d.ts +27 -5
- package/lib/crypto-api/index.d.ts.map +1 -1
- package/lib/crypto-api/index.js +22 -3
- package/lib/crypto-api/index.js.map +1 -1
- package/lib/embedded.js +1 -1
- package/lib/embedded.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.js +2 -1
- package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
- package/lib/matrixrtc/membershipData/rtc.d.ts.map +1 -1
- package/lib/matrixrtc/membershipData/rtc.js +5 -4
- package/lib/matrixrtc/membershipData/rtc.js.map +1 -1
- package/lib/oidc/authorize.d.ts +8 -4
- package/lib/oidc/authorize.d.ts.map +1 -1
- package/lib/oidc/authorize.js +18 -6
- package/lib/oidc/authorize.js.map +1 -1
- package/lib/oidc/discovery.js +1 -1
- package/lib/oidc/discovery.js.map +1 -1
- package/lib/rust-crypto/backup.d.ts +6 -2
- package/lib/rust-crypto/backup.d.ts.map +1 -1
- package/lib/rust-crypto/backup.js +30 -10
- package/lib/rust-crypto/backup.js.map +1 -1
- package/lib/rust-crypto/rust-crypto.d.ts +16 -11
- package/lib/rust-crypto/rust-crypto.d.ts.map +1 -1
- package/lib/rust-crypto/rust-crypto.js +38 -21
- package/lib/rust-crypto/rust-crypto.js.map +1 -1
- package/lib/store/indexeddb-local-backend.d.ts.map +1 -1
- package/lib/store/indexeddb-local-backend.js +4 -2
- package/lib/store/indexeddb-local-backend.js.map +1 -1
- package/package.json +14 -10
- package/src/@types/event.ts +14 -2
- package/src/crypto-api/index.ts +30 -5
- package/src/embedded.ts +1 -1
- package/src/matrixrtc/MatrixRTCSession.ts +2 -1
- package/src/matrixrtc/membershipData/rtc.ts +5 -4
- package/src/oidc/authorize.ts +25 -6
- package/src/oidc/discovery.ts +1 -1
- package/src/rust-crypto/backup.ts +31 -10
- package/src/rust-crypto/rust-crypto.ts +28 -13
- package/src/store/indexeddb-local-backend.ts +2 -1
|
@@ -161,7 +161,7 @@ export class RustBackupManager extends TypedEventEmitter<RustBackupCryptoEvents,
|
|
|
161
161
|
/**
|
|
162
162
|
* Handles a backup secret received event and store it if it matches the current backup version.
|
|
163
163
|
*
|
|
164
|
-
* @param secret - The secret as received from a `m.secret.send` event for secret `m.megolm_backup.v1`.
|
|
164
|
+
* @param secret - The secret as received from a `m.secret.send` or `io.element.msc4385.secret.push` event for secret `m.megolm_backup.v1`.
|
|
165
165
|
* @returns true if the secret is valid and has been stored, false otherwise.
|
|
166
166
|
*/
|
|
167
167
|
public async handleBackupSecretReceived(secret: string): Promise<boolean> {
|
|
@@ -180,28 +180,44 @@ export class RustBackupManager extends TypedEventEmitter<RustBackupCryptoEvents,
|
|
|
180
180
|
// There is no server-side key backup.
|
|
181
181
|
// This decryption key is useless to us.
|
|
182
182
|
this.logger.warn(
|
|
183
|
-
"handleBackupSecretReceived: Received a backup decryption key, but there is no
|
|
183
|
+
"handleBackupSecretReceived: Received a backup decryption key, but there is no server-side key backup",
|
|
184
184
|
);
|
|
185
185
|
return false;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
let backupDecryptionKey: RustSdkCryptoJs.BackupDecryptionKey;
|
|
189
|
+
try {
|
|
190
|
+
backupDecryptionKey = RustSdkCryptoJs.BackupDecryptionKey.fromBase64(secret);
|
|
191
|
+
} catch (e) {
|
|
192
|
+
this.logger.warn("handleBackupSecretReceived: Invalid backup decryption key", e);
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
188
196
|
try {
|
|
189
|
-
const backupDecryptionKey = RustSdkCryptoJs.BackupDecryptionKey.fromBase64(secret);
|
|
190
197
|
const privateKeyMatches = this.backupInfoMatchesBackupDecryptionKey(latestBackupInfo, backupDecryptionKey);
|
|
191
198
|
if (!privateKeyMatches) {
|
|
192
199
|
this.logger.warn(
|
|
193
|
-
`handleBackupSecretReceived: Private decryption key does not match the public key of the current
|
|
200
|
+
`handleBackupSecretReceived: Private decryption key does not match the public key of the current server-side backup version (${latestBackupInfo.version})`,
|
|
194
201
|
);
|
|
195
202
|
// just ignore the secret
|
|
196
203
|
return false;
|
|
197
204
|
}
|
|
198
205
|
this.logger.info(
|
|
199
|
-
`handleBackupSecretReceived:
|
|
206
|
+
`handleBackupSecretReceived: Valid decryption key for the current server-side backup version (${latestBackupInfo.version}) received`,
|
|
200
207
|
);
|
|
201
208
|
await this.saveBackupDecryptionKey(backupDecryptionKey, latestBackupInfo.version);
|
|
209
|
+
// Check if the backup should be enabled (e.g. if it's properly
|
|
210
|
+
// signed), and enable it if it should
|
|
211
|
+
if (this.keyBackupCheckInProgress) {
|
|
212
|
+
await this.keyBackupCheckInProgress;
|
|
213
|
+
}
|
|
214
|
+
this.keyBackupCheckInProgress = this.doCheckKeyBackup(latestBackupInfo).finally(() => {
|
|
215
|
+
this.keyBackupCheckInProgress = null;
|
|
216
|
+
});
|
|
217
|
+
await this.keyBackupCheckInProgress;
|
|
202
218
|
return true;
|
|
203
219
|
} catch (e) {
|
|
204
|
-
this.logger.warn("handleBackupSecretReceived:
|
|
220
|
+
this.logger.warn("handleBackupSecretReceived: Unable to validate backup decryption key", e);
|
|
205
221
|
}
|
|
206
222
|
|
|
207
223
|
return false;
|
|
@@ -281,12 +297,17 @@ export class RustBackupManager extends TypedEventEmitter<RustBackupCryptoEvents,
|
|
|
281
297
|
|
|
282
298
|
private keyBackupCheckInProgress: Promise<KeyBackupCheck | null> | null = null;
|
|
283
299
|
|
|
284
|
-
/** Helper
|
|
285
|
-
|
|
300
|
+
/** Helper to check the key backup status, and enable/disable it as appropriate
|
|
301
|
+
*
|
|
302
|
+
* A KeyBackupInfo can be passed if it was fetched recently, to avoid trying to
|
|
303
|
+
* re-fetch it from the server.
|
|
304
|
+
*/
|
|
305
|
+
private async doCheckKeyBackup(backupInfo?: KeyBackupInfo | null | undefined): Promise<KeyBackupCheck | null> {
|
|
286
306
|
this.logger.debug("Checking key backup status...");
|
|
287
|
-
let backupInfo: KeyBackupInfo | null | undefined;
|
|
288
307
|
try {
|
|
289
|
-
|
|
308
|
+
if (!backupInfo) {
|
|
309
|
+
backupInfo = await this.requestKeyBackupVersion();
|
|
310
|
+
}
|
|
290
311
|
} catch (e) {
|
|
291
312
|
this.logger.warn("Error checking for active key backup", e);
|
|
292
313
|
this.serverBackupInfo = undefined;
|
|
@@ -736,7 +736,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
736
736
|
? userIdentity.identityNeedsUserApproval()
|
|
737
737
|
: false;
|
|
738
738
|
userIdentity.free();
|
|
739
|
-
return new UserVerificationStatus(verified, wasVerified,
|
|
739
|
+
return new UserVerificationStatus(verified, wasVerified, true, needsUserApproval);
|
|
740
740
|
}
|
|
741
741
|
|
|
742
742
|
/**
|
|
@@ -1376,6 +1376,8 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
1376
1376
|
public async resetKeyBackup(): Promise<void> {
|
|
1377
1377
|
const backupInfo = await this.backupManager.setupKeyBackup((o) => this.signObject(o));
|
|
1378
1378
|
|
|
1379
|
+
await this.pushSecretToVerifiedDevices("m.megolm_backup.v1");
|
|
1380
|
+
|
|
1379
1381
|
// we want to store the private key in 4S
|
|
1380
1382
|
// need to check if 4S is set up?
|
|
1381
1383
|
if (await this.secretStorageHasAESKey()) {
|
|
@@ -1971,14 +1973,15 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
1971
1973
|
* the event.
|
|
1972
1974
|
*
|
|
1973
1975
|
* To counter this, we proactively discard any active outgoing Megolm
|
|
1974
|
-
* session when we see
|
|
1975
|
-
*
|
|
1976
|
-
*
|
|
1977
|
-
*
|
|
1978
|
-
*
|
|
1979
|
-
*
|
|
1980
|
-
|
|
1981
|
-
|
|
1976
|
+
* session when we see an event indicating the user left.
|
|
1977
|
+
*
|
|
1978
|
+
* Note that we have to do this in `onRoomStateEvent` rather than
|
|
1979
|
+
* `onRoomMembership`, because `onRoomMembership` is only called when we see
|
|
1980
|
+
* a *change* in membership. In the case of a gappy sync, we might miss
|
|
1981
|
+
* Charlie's invite and join, and only see the final `leave` event (so his
|
|
1982
|
+
* membership goes from `leave` to `leave`).
|
|
1983
|
+
*/
|
|
1984
|
+
public onRoomStateEvent(event: MatrixEvent, _state: RoomState, _prevEvent: MatrixEvent | null): void {
|
|
1982
1985
|
if (event.getType() != EventType.RoomMember) {
|
|
1983
1986
|
// Ignore all events that aren't member updates.
|
|
1984
1987
|
return;
|
|
@@ -1986,7 +1989,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
1986
1989
|
|
|
1987
1990
|
if (
|
|
1988
1991
|
event.getStateKey()! !== this.olmMachine.userId.toString() &&
|
|
1989
|
-
event.getContent().membership
|
|
1992
|
+
event.getContent().membership !== KnownMembership.Join
|
|
1990
1993
|
) {
|
|
1991
1994
|
this.logger.info(`Rotating session for room ${event.getRoomId()} due to member leaving the room`);
|
|
1992
1995
|
this.forceDiscardSession(event.getRoomId()!);
|
|
@@ -2103,9 +2106,9 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
2103
2106
|
/**
|
|
2104
2107
|
* Handles secret received from the rust secret inbox.
|
|
2105
2108
|
*
|
|
2106
|
-
* The gossipped secrets are received using the `m.secret.send`
|
|
2107
|
-
* and are guaranteed to have
|
|
2108
|
-
* Session from a verified device.
|
|
2109
|
+
* The gossipped secrets are received using the `m.secret.send` or
|
|
2110
|
+
* `io.element.msc4385.secret.push` event types and are guaranteed to have
|
|
2111
|
+
* been received over a 1-to-1 Olm Session from a verified device.
|
|
2109
2112
|
*
|
|
2110
2113
|
* The only secret currently handled in this way is `m.megolm_backup.v1`.
|
|
2111
2114
|
*
|
|
@@ -2253,6 +2256,18 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
2253
2256
|
| undefined;
|
|
2254
2257
|
return identity;
|
|
2255
2258
|
}
|
|
2259
|
+
|
|
2260
|
+
/**
|
|
2261
|
+
* Push a secret to all of the current user's verified devices.
|
|
2262
|
+
*/
|
|
2263
|
+
public async pushSecretToVerifiedDevices(name: string): Promise<void> {
|
|
2264
|
+
const logger = new LogSpan(this.logger, "pushSecretToVerifiedDevices");
|
|
2265
|
+
await this.keyClaimManager.ensureSessionsForUsers(logger, [new RustSdkCryptoJs.UserId(this.userId)]);
|
|
2266
|
+
await this.olmMachine.pushSecretToVerifiedDevices(name);
|
|
2267
|
+
this.outgoingRequestsManager.doProcessOutgoingRequests().catch((e) => {
|
|
2268
|
+
logger.warn("pushSecretToVerifiedDevices: Error processing outgoing requests", e);
|
|
2269
|
+
});
|
|
2270
|
+
}
|
|
2256
2271
|
}
|
|
2257
2272
|
|
|
2258
2273
|
class EventDecryptor {
|
|
@@ -61,6 +61,7 @@ const VERSION = DB_MIGRATIONS.length;
|
|
|
61
61
|
* Return the data you want to keep.
|
|
62
62
|
* @returns Promise which resolves to an array of whatever you returned from
|
|
63
63
|
* resultMapper.
|
|
64
|
+
* @throws If there was an error completing the query.
|
|
64
65
|
*/
|
|
65
66
|
function selectQuery<T>(
|
|
66
67
|
store: IDBObjectStore,
|
|
@@ -71,7 +72,7 @@ function selectQuery<T>(
|
|
|
71
72
|
return new Promise((resolve, reject) => {
|
|
72
73
|
const results: T[] = [];
|
|
73
74
|
query.onerror = (): void => {
|
|
74
|
-
reject(new Error(
|
|
75
|
+
reject(new Error(`selectQuery failed for ${store.name}`, { cause: query.error }));
|
|
75
76
|
};
|
|
76
77
|
// collect results
|
|
77
78
|
query.onsuccess = (): void => {
|