diff --git a/crates/matrix-sdk-crypto/CHANGELOG.md b/crates/matrix-sdk-crypto/CHANGELOG.md index e4379966c..17ba493dd 100644 --- a/crates/matrix-sdk-crypto/CHANGELOG.md +++ b/crates/matrix-sdk-crypto/CHANGELOG.md @@ -8,11 +8,13 @@ All notable changes to this project will be documented in this file. ### Features -- Add `Store::{store,clear}_room_pending_key_bundle` and - `CryptoStore::get_pending_key_bundle_details_for_room`, which can be used by +- Add `Store::{store,clear}_room_pending_key_bundle`, + `CryptoStore::get_pending_key_bundle_details_for_room` and + `CryptoStore::get_all_rooms_pending_key_bundle`, which can be used by applications to track whether they are expecting an - [MSC4268](https://github.com/matrix-org/matrix-spec-proposals/pull/4268) key bundle. - ([#6199](https://github.com/matrix-org/matrix-rust-sdk/pull/6199)) + [MSC4268](https://github.com/matrix-org/matrix-spec-proposals/pull/4268) key + bundle. + ([#6199](https://github.com/matrix-org/matrix-rust-sdk/pull/6199)), ([#6233](https://github.com/matrix-org/matrix-rust-sdk/pull/6233)), - Add MSC4388 support to the QrcodeData struct. ([#6089](https://github.com/matrix-org/matrix-rust-sdk/pull/6089)) @@ -22,7 +24,7 @@ All notable changes to this project will be documented in this file. ([#6083](https://github.com/matrix-org/matrix-rust-sdk/pull/6083)) - Added a new field `forwarder` to `InboundGroupSession` of type `ForwarderData`, which stores information about the forwarder of a session shared in a room key bundle under [MSC4268](https://github.com/matrix-org/matrix-spec-proposals/pull/4268). ([#5980])(https://github.com/matrix-org/matrix-rust-sdk/pull/5980) -- The `OutboundGroupSession` and `OlmMachine` now return the `EncryptionInfo` +- The `OutboundGroupSession` and `OlmMachine` now return the `EncryptionInfo` used when encrypting raw events. ([#5936](https://github.com/matrix-org/matrix-rust-sdk/pull/5936)) - Expose a new method `CryptoStore::has_downloaded_all_room_keys`, used to track whether the diff --git a/crates/matrix-sdk-crypto/src/store/integration_tests.rs b/crates/matrix-sdk-crypto/src/store/integration_tests.rs index ef3c99cfd..f8c18613d 100644 --- a/crates/matrix-sdk-crypto/src/store/integration_tests.rs +++ b/crates/matrix-sdk-crypto/src/store/integration_tests.rs @@ -1426,10 +1426,17 @@ macro_rules! cryptostore_integration_tests { let details = store.get_pending_key_bundle_details_for_room(test_room).await.unwrap(); assert_matches!(details, Some(details) => { + assert_eq!(details.room_id, test_room); assert_eq!(details.inviter, test_user); assert_eq!(details.invite_accepted_at, timestamp); }); + let all_rooms = store.get_all_rooms_pending_key_bundles().await.unwrap(); + assert_eq!(all_rooms.len(), 1); + assert_eq!(all_rooms[0].room_id, test_room); + assert_eq!(all_rooms[0].inviter, test_user); + assert_eq!(all_rooms[0].invite_accepted_at, timestamp); + // Clear the entry, and check it is blank again store.save_changes(Changes { rooms_pending_key_bundle: HashMap::from([(test_room.to_owned(), None)]), diff --git a/crates/matrix-sdk-crypto/src/store/memorystore.rs b/crates/matrix-sdk-crypto/src/store/memorystore.rs index 9f04a698d..7f113d0f9 100644 --- a/crates/matrix-sdk-crypto/src/store/memorystore.rs +++ b/crates/matrix-sdk-crypto/src/store/memorystore.rs @@ -782,6 +782,10 @@ impl CryptoStore for MemoryStore { Ok(self.rooms_pending_key_bundle.read().get(room_id).cloned()) } + async fn get_all_rooms_pending_key_bundles(&self) -> Result> { + Ok(self.rooms_pending_key_bundle.read().values().cloned().collect()) + } + async fn has_downloaded_all_room_keys(&self, room_id: &RoomId) -> Result { let guard = self.room_key_backups_fully_downloaded.read(); Ok(guard.contains(room_id)) @@ -1629,6 +1633,12 @@ mod integration_tests { self.0.get_pending_key_bundle_details_for_room(room_id).await } + async fn get_all_rooms_pending_key_bundles( + &self, + ) -> Result, Self::Error> { + self.0.get_all_rooms_pending_key_bundles().await + } + async fn get_custom_value(&self, key: &str) -> Result>, Self::Error> { self.0.get_custom_value(key).await } diff --git a/crates/matrix-sdk-crypto/src/store/traits.rs b/crates/matrix-sdk-crypto/src/store/traits.rs index b4987ef34..82dc05a7b 100644 --- a/crates/matrix-sdk-crypto/src/store/traits.rs +++ b/crates/matrix-sdk-crypto/src/store/traits.rs @@ -363,6 +363,12 @@ pub trait CryptoStore: AsyncTraitDeps { room_id: &RoomId, ) -> Result, Self::Error>; + /// Retrieve a list of details for all rooms where we are currently awaiting + /// key bundles to be received. + async fn get_all_rooms_pending_key_bundles( + &self, + ) -> Result, Self::Error>; + /// Get whether we have previously downloaded all room keys for a particular /// room from the key backup in advance of building a room key bundle. async fn has_downloaded_all_room_keys(&self, room_id: &RoomId) -> Result; @@ -649,6 +655,12 @@ impl CryptoStore for EraseCryptoStoreError { self.0.get_pending_key_bundle_details_for_room(room_id).await.map_err(Into::into) } + async fn get_all_rooms_pending_key_bundles( + &self, + ) -> Result, Self::Error> { + self.0.get_all_rooms_pending_key_bundles().await.map_err(Into::into) + } + async fn get_custom_value(&self, key: &str) -> Result>, Self::Error> { self.0.get_custom_value(key).await.map_err(Into::into) } diff --git a/crates/matrix-sdk-indexeddb/CHANGELOG.md b/crates/matrix-sdk-indexeddb/CHANGELOG.md index db9a1a96c..abf734ad5 100644 --- a/crates/matrix-sdk-indexeddb/CHANGELOG.md +++ b/crates/matrix-sdk-indexeddb/CHANGELOG.md @@ -8,9 +8,10 @@ All notable changes to this project will be documented in this file. ### Features -- Implement `CryptoStore::get_pending_key_bundle_details_for_room` and process `rooms_pending_key_bundle` field in - `Changes`. - ([#6199](https://github.com/matrix-org/matrix-rust-sdk/pull/6199)) +- Implement `CryptoStore::get_pending_key_bundle_details_for_room` and + `CryptoStore::get_all_rooms_pending_key_bundle`, and process + `rooms_pending_key_bundle` field in `Changes`. + ([#6199](https://github.com/matrix-org/matrix-rust-sdk/pull/6199)), ([#6233](https://github.com/matrix-org/matrix-rust-sdk/pull/6233)) - Expose implementations of `EventCacheStore` and `MediaStore` and add a composite type for initializing all stores with a single function - i.e., `IndexeddbStores::open`. Additionally, allow feature flags for each of the diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs index 00df131aa..4070558fc 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs @@ -1608,6 +1608,24 @@ impl_crypto_store! { Ok(result) } + async fn get_all_rooms_pending_key_bundles(&self) -> Result> { + let result = self + .inner + .transaction(keys::ROOMS_PENDING_KEY_BUNDLE) + .with_mode(TransactionMode::Readonly) + .build()? + .object_store(keys::ROOMS_PENDING_KEY_BUNDLE)? + .get_all() + .await? + .map(|result| { + result + .map_err(Into::into) + .and_then(|v| self.serializer.deserialize_value(v).map_err(Into::into)) + }) + .collect::>>()?; + Ok(result) + } + async fn get_custom_value(&self, key: &str) -> Result>> { self.inner .transaction(keys::CORE) diff --git a/crates/matrix-sdk-sqlite/CHANGELOG.md b/crates/matrix-sdk-sqlite/CHANGELOG.md index d680eed8c..20272478d 100644 --- a/crates/matrix-sdk-sqlite/CHANGELOG.md +++ b/crates/matrix-sdk-sqlite/CHANGELOG.md @@ -8,9 +8,10 @@ All notable changes to this project will be documented in this file. ### Features -- Implement `CryptoStore::get_pending_key_bundle_details_for_room` and process `rooms_pending_key_bundle` field in - `Changes`. - ([#6199](https://github.com/matrix-org/matrix-rust-sdk/pull/6199)) +- Implement `CryptoStore::get_pending_key_bundle_details_for_room` and + `CryptoStore::get_all_rooms_pending_key_bundle`, and process + `rooms_pending_key_bundle` field in `Changes`. + ([#6199](https://github.com/matrix-org/matrix-rust-sdk/pull/6199)), ([#6233](https://github.com/matrix-org/matrix-rust-sdk/pull/6233)) - Implement new method `CryptoStore::has_downloaded_all_room_keys`, and process `room_key_backups_fully_downloaded` field in `Changes`. ([#6017](https://github.com/matrix-org/matrix-rust-sdk/pull/6017)) diff --git a/crates/matrix-sdk-sqlite/src/crypto_store.rs b/crates/matrix-sdk-sqlite/src/crypto_store.rs index d43fab1c6..f4943c638 100644 --- a/crates/matrix-sdk-sqlite/src/crypto_store.rs +++ b/crates/matrix-sdk-sqlite/src/crypto_store.rs @@ -903,6 +903,12 @@ trait SqliteObjectCryptoStoreExt: SqliteAsyncConnExt { .optional()?) } + async fn get_all_rooms_pending_key_bundle(&self) -> Result>> { + Ok(self + .query_many("SELECT data FROM rooms_pending_key_bundle", (), |row| row.get(0)) + .await?) + } + async fn has_downloaded_all_room_keys(&self, room_id: Key) -> Result { Ok(self .query_row( @@ -1581,6 +1587,15 @@ impl CryptoStore for SqliteCryptoStore { Ok(Some(details)) } + async fn get_all_rooms_pending_key_bundles(&self) -> Result> { + let details = self.read().await?.get_all_rooms_pending_key_bundle().await?; + let room_ids = details + .into_iter() + .map(|value| self.deserialize_value(&value)) + .collect::>()?; + Ok(room_ids) + } + async fn get_custom_value(&self, key: &str) -> Result>> { let Some(serialized) = self.read().await?.get_kv(key).await? else { return Ok(None); diff --git a/crates/matrix-sdk-sqlite/src/utils.rs b/crates/matrix-sdk-sqlite/src/utils.rs index 765e08d2b..80933bab7 100644 --- a/crates/matrix-sdk-sqlite/src/utils.rs +++ b/crates/matrix-sdk-sqlite/src/utils.rs @@ -97,6 +97,17 @@ pub(crate) trait SqliteAsyncConnExt { P: Params + Send + 'static, F: FnOnce(&Row<'_>) -> rusqlite::Result + Send + 'static; + async fn query_many( + &self, + sql: impl AsRef + Send + 'static, + params: P, + f: F, + ) -> rusqlite::Result> + where + T: Send + 'static, + P: Params + Send + 'static, + F: FnMut(&Row<'_>) -> rusqlite::Result + Send + 'static; + async fn with_transaction(&self, f: F) -> Result where T: Send + 'static, @@ -278,6 +289,25 @@ impl SqliteAsyncConnExt for SqliteAsyncConn { .map_err(map_interact_err)? } + async fn query_many( + &self, + sql: impl AsRef + Send + 'static, + params: P, + f: F, + ) -> rusqlite::Result> + where + T: Send + 'static, + P: Params + Send + 'static, + F: FnMut(&Row<'_>) -> rusqlite::Result + Send + 'static, + { + self.interact(move |conn| { + let mut stmt = conn.prepare(sql.as_ref())?; + stmt.query_and_then(params, f)?.collect() + }) + .await + .map_err(map_interact_err)? + } + async fn with_transaction(&self, f: F) -> Result where T: Send + 'static,