diff --git a/crates/matrix-sdk-base/Changelog.md b/crates/matrix-sdk-base/Changelog.md index 99964cb77..9e3b784e8 100644 --- a/crates/matrix-sdk-base/Changelog.md +++ b/crates/matrix-sdk-base/Changelog.md @@ -6,6 +6,8 @@ - Add `RoomInfo::state` accessor - Remove `members` and `stripped_members` fields in `StateChanges`. Room member events are now with other state events in `state` and `stripped_state`. +- `StateStore::get_user_ids` takes a `RoomMemberships` to be able to filter the results by any + membership state. ## 0.5.1 diff --git a/crates/matrix-sdk-base/src/rooms/normal.rs b/crates/matrix-sdk-base/src/rooms/normal.rs index 2b8a38dff..7b340e69a 100644 --- a/crates/matrix-sdk-base/src/rooms/normal.rs +++ b/crates/matrix-sdk-base/src/rooms/normal.rs @@ -44,7 +44,7 @@ use crate::{ deserialized_responses::MemberEvent, store::{DynStateStore, Result as StoreResult, StateStoreExt}, sync::UnreadNotificationsCount, - MinimalStateEvent, + MinimalStateEvent, RoomMemberships, }; /// The underlying room data structure collecting state for joined, left and @@ -323,7 +323,7 @@ impl Room { /// Get the all `RoomMember`s of this room that are known to the store. pub async fn members(&self) -> StoreResult> { - let user_ids = self.store.get_user_ids(self.room_id()).await?; + let user_ids = self.store.get_user_ids(self.room_id(), RoomMemberships::empty()).await?; let mut members = Vec::new(); for u in user_ids { diff --git a/crates/matrix-sdk-base/src/store/integration_tests.rs b/crates/matrix-sdk-base/src/store/integration_tests.rs index 8cd37af4c..bb7bc0a4e 100644 --- a/crates/matrix-sdk-base/src/store/integration_tests.rs +++ b/crates/matrix-sdk-base/src/store/integration_tests.rs @@ -35,7 +35,7 @@ use crate::{ deserialized_responses::MemberEvent, media::{MediaFormat, MediaRequest, MediaThumbnailSize}, store::{Result, StateStoreExt}, - RoomInfo, RoomState, StateChanges, StateStoreDataKey, StateStoreDataValue, + RoomInfo, RoomMemberships, RoomState, StateChanges, StateStoreDataKey, StateStoreDataValue, }; /// `StateStore` integration tests. @@ -330,7 +330,7 @@ impl StateStoreIntegrationTests for DynStateStore { assert!(self.get_profile(room_id, user_id).await?.is_some()); assert!(self.get_member_event(room_id, user_id).await?.is_some()); assert_eq!( - self.get_user_ids(room_id).await?.len(), + self.get_user_ids(room_id, RoomMemberships::empty()).await?.len(), 2, "Expected to find 2 members for room" ); @@ -394,7 +394,7 @@ impl StateStoreIntegrationTests for DynStateStore { self.save_changes(&changes).await.unwrap(); assert!(self.get_member_event(room_id, user_id).await.unwrap().is_some()); - let members = self.get_user_ids(room_id).await.unwrap(); + let members = self.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); assert!(!members.is_empty(), "We expected to find members for the room") } @@ -466,7 +466,7 @@ impl StateStoreIntegrationTests for DynStateStore { self.save_changes(&changes).await.unwrap(); assert!(self.get_member_event(room_id, user_id).await.unwrap().is_some()); - let members = self.get_user_ids(room_id).await.unwrap(); + let members = self.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); assert!(!members.is_empty(), "We expected to find members for the room") } @@ -774,7 +774,7 @@ impl StateStoreIntegrationTests for DynStateStore { assert_eq!(self.get_room_infos().await.unwrap().len(), 1); assert_eq!(self.get_stripped_room_infos().await.unwrap().len(), 0); - let members = self.get_user_ids(room_id).await.unwrap(); + let members = self.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); assert_eq!(members, vec![user_id.to_owned()]); let mut changes = StateChanges::default(); @@ -788,7 +788,7 @@ impl StateStoreIntegrationTests for DynStateStore { assert_eq!(self.get_room_infos().await.unwrap().len(), 0); assert_eq!(self.get_stripped_room_infos().await.unwrap().len(), 1); - let members = self.get_user_ids(room_id).await.unwrap(); + let members = self.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); assert_eq!(members, vec![user_id.to_owned()]); Ok(()) @@ -813,7 +813,10 @@ impl StateStoreIntegrationTests for DynStateStore { ); assert!(self.get_profile(room_id, user_id).await?.is_none()); assert!(self.get_member_event(room_id, user_id).await?.is_none()); - assert!(self.get_user_ids(room_id).await?.is_empty(), "still user ids found"); + assert!( + self.get_user_ids(room_id, RoomMemberships::empty()).await?.is_empty(), + "still user ids found" + ); assert!( self.get_invited_user_ids(room_id).await?.is_empty(), "still invited user ids found" diff --git a/crates/matrix-sdk-base/src/store/memory_store.rs b/crates/matrix-sdk-base/src/store/memory_store.rs index 3a96c35d3..5ba6ce519 100644 --- a/crates/matrix-sdk-base/src/store/memory_store.rs +++ b/crates/matrix-sdk-base/src/store/memory_store.rs @@ -456,30 +456,6 @@ impl MemoryStore { .unwrap_or_default() } - fn get_user_ids(&self, room_id: &RoomId) -> Vec { - let v = self.get_user_ids_inner(room_id, RoomMemberships::empty(), true); - if !v.is_empty() { - return v; - } - self.get_user_ids_inner(room_id, RoomMemberships::empty(), false) - } - - fn get_invited_user_ids(&self, room_id: &RoomId) -> Vec { - self.get_user_ids_inner(room_id, RoomMemberships::INVITE, false) - } - - fn get_joined_user_ids(&self, room_id: &RoomId) -> Vec { - self.get_user_ids_inner(room_id, RoomMemberships::JOIN, false) - } - - fn get_stripped_invited_user_ids(&self, room_id: &RoomId) -> Vec { - self.get_user_ids_inner(room_id, RoomMemberships::INVITE, true) - } - - fn get_stripped_joined_user_ids(&self, room_id: &RoomId) -> Vec { - self.get_user_ids_inner(room_id, RoomMemberships::JOIN, true) - } - fn get_room_infos(&self) -> Vec { self.room_info.iter().map(|r| r.clone()).collect() } @@ -643,24 +619,24 @@ impl StateStore for MemoryStore { self.get_member_event(room_id, state_key).await } - async fn get_user_ids(&self, room_id: &RoomId) -> Result> { - Ok(self.get_user_ids(room_id)) + async fn get_user_ids( + &self, + room_id: &RoomId, + memberships: RoomMemberships, + ) -> Result> { + let v = self.get_user_ids_inner(room_id, memberships, true); + if !v.is_empty() { + return Ok(v); + } + Ok(self.get_user_ids_inner(room_id, memberships, false)) } async fn get_invited_user_ids(&self, room_id: &RoomId) -> Result> { - let v = self.get_stripped_invited_user_ids(room_id); - if !v.is_empty() { - return Ok(v); - } - Ok(self.get_invited_user_ids(room_id)) + StateStore::get_user_ids(self, room_id, RoomMemberships::INVITE).await } async fn get_joined_user_ids(&self, room_id: &RoomId) -> Result> { - let v = self.get_stripped_joined_user_ids(room_id); - if !v.is_empty() { - return Ok(v); - } - Ok(self.get_joined_user_ids(room_id)) + StateStore::get_user_ids(self, room_id, RoomMemberships::JOIN).await } async fn get_room_infos(&self) -> Result> { diff --git a/crates/matrix-sdk-base/src/store/traits.rs b/crates/matrix-sdk-base/src/store/traits.rs index 972dc0e2b..da6561fe6 100644 --- a/crates/matrix-sdk-base/src/store/traits.rs +++ b/crates/matrix-sdk-base/src/store/traits.rs @@ -33,6 +33,7 @@ use ruma::{ use super::{StateChanges, StoreError}; use crate::{ deserialized_responses::RawMemberEvent, media::MediaRequest, MinimalRoomMemberEvent, RoomInfo, + RoomMemberships, }; /// An abstract state store trait that can be used to implement different stores @@ -142,9 +143,13 @@ pub trait StateStore: AsyncTraitDeps { state_key: &UserId, ) -> Result, Self::Error>; - /// Get all the user ids of members for a given room, for stripped and - /// regular rooms alike. - async fn get_user_ids(&self, room_id: &RoomId) -> Result, Self::Error>; + /// Get the user ids of members for a given room with the given memberships, + /// for stripped and regular rooms alike. + async fn get_user_ids( + &self, + room_id: &RoomId, + memberships: RoomMemberships, + ) -> Result, Self::Error>; /// Get all the user ids of members that are in the invited state for a /// given room, for stripped and regular rooms alike. @@ -391,8 +396,12 @@ impl StateStore for EraseStateStoreError { self.0.get_member_event(room_id, state_key).await.map_err(Into::into) } - async fn get_user_ids(&self, room_id: &RoomId) -> Result, Self::Error> { - self.0.get_user_ids(room_id).await.map_err(Into::into) + async fn get_user_ids( + &self, + room_id: &RoomId, + memberships: RoomMemberships, + ) -> Result, Self::Error> { + self.0.get_user_ids(room_id, memberships).await.map_err(Into::into) } async fn get_invited_user_ids( diff --git a/crates/matrix-sdk-indexeddb/src/state_store/migrations.rs b/crates/matrix-sdk-indexeddb/src/state_store/migrations.rs index 1efa72fcc..49b7a2ee8 100644 --- a/crates/matrix-sdk-indexeddb/src/state_store/migrations.rs +++ b/crates/matrix-sdk-indexeddb/src/state_store/migrations.rs @@ -605,8 +605,8 @@ mod tests { use assert_matches::assert_matches; use indexed_db_futures::prelude::*; use matrix_sdk_base::{ - deserialized_responses::RawMemberEvent, RoomInfo, RoomState, StateStore, StateStoreDataKey, - StoreError, + deserialized_responses::RawMemberEvent, RoomInfo, RoomMemberships, RoomState, StateStore, + StateStoreDataKey, StoreError, }; use matrix_sdk_test::{async_test, test_json}; use ruma::{ @@ -1166,23 +1166,30 @@ mod tests { // this transparently migrates to the latest version let store = IndexeddbStateStore::builder().name(name).build().await?; - assert_eq!(store.get_joined_user_ids(room_id).await.unwrap().len(), 0); + assert_eq!(store.get_user_ids(room_id, RoomMemberships::JOIN).await.unwrap().len(), 0); assert_eq!( - store.get_invited_user_ids(room_id).await.unwrap().as_slice(), + store.get_user_ids(room_id, RoomMemberships::INVITE).await.unwrap().as_slice(), [invite_user_id.to_owned()] ); - let user_ids = store.get_user_ids(room_id).await.unwrap(); + let user_ids = store.get_user_ids(room_id, RoomMemberships::empty()).await.unwrap(); assert_eq!(user_ids.len(), 2); assert!(user_ids.contains(&invite_user_id.to_owned())); assert!(user_ids.contains(&ban_user_id.to_owned())); assert_eq!( - store.get_stripped_joined_user_ids(stripped_room_id).await.unwrap().as_slice(), + store.get_user_ids(stripped_room_id, RoomMemberships::JOIN).await.unwrap().as_slice(), [stripped_user_id.to_owned()] ); - assert_eq!(store.get_stripped_invited_user_ids(stripped_room_id).await.unwrap().len(), 0); assert_eq!( - store.get_user_ids(stripped_room_id).await.unwrap().as_slice(), + store.get_user_ids(stripped_room_id, RoomMemberships::INVITE).await.unwrap().len(), + 0 + ); + assert_eq!( + store + .get_user_ids(stripped_room_id, RoomMemberships::empty()) + .await + .unwrap() + .as_slice(), [stripped_user_id.to_owned()] ); diff --git a/crates/matrix-sdk-indexeddb/src/state_store/mod.rs b/crates/matrix-sdk-indexeddb/src/state_store/mod.rs index af4b69cd0..b80509ccd 100644 --- a/crates/matrix-sdk-indexeddb/src/state_store/mod.rs +++ b/crates/matrix-sdk-indexeddb/src/state_store/mod.rs @@ -312,9 +312,6 @@ impl IndexeddbStateStore { /// Get user IDs for the given room with the given memberships and stripped /// state. - /// - /// If `memberships` is empty, returns all user IDs in the room with the - /// given stripped state. pub async fn get_user_ids_inner( &self, room_id: &RoomId, @@ -364,17 +361,6 @@ impl IndexeddbStateStore { Ok(user_ids) } - pub async fn get_stripped_invited_user_ids( - &self, - room_id: &RoomId, - ) -> Result> { - self.get_user_ids_inner(room_id, RoomMemberships::INVITE, true).await - } - - pub async fn get_stripped_joined_user_ids(&self, room_id: &RoomId) -> Result> { - self.get_user_ids_inner(room_id, RoomMemberships::JOIN, true).await - } - async fn get_custom_value_for_js(&self, jskey: &JsValue) -> Result>> { self.inner .transaction_on_one_with_mode(keys::CUSTOM, IdbTransactionMode::Readonly)? @@ -1146,28 +1132,20 @@ impl_state_store! { tx.await.into_result().map_err(|e| e.into()) } - async fn get_user_ids(&self, room_id: &RoomId) -> Result> { - let ids = self.get_user_ids_inner(room_id, RoomMemberships::empty(), true).await?; + async fn get_user_ids(&self, room_id: &RoomId, memberships: RoomMemberships) -> Result> { + let ids = self.get_user_ids_inner(room_id, memberships, true).await?; if !ids.is_empty() { return Ok(ids); } - self.get_user_ids_inner(room_id, RoomMemberships::empty(), false).await + self.get_user_ids_inner(room_id, memberships, false).await } async fn get_invited_user_ids(&self, room_id: &RoomId) -> Result> { - let ids: Vec = self.get_stripped_invited_user_ids(room_id).await?; - if !ids.is_empty() { - return Ok(ids); - } - self.get_user_ids_inner(room_id, RoomMemberships::INVITE, false).await + self.get_user_ids(room_id, RoomMemberships::INVITE).await } async fn get_joined_user_ids(&self, room_id: &RoomId) -> Result> { - let ids: Vec = self.get_stripped_joined_user_ids(room_id).await?; - if !ids.is_empty() { - return Ok(ids); - } - self.get_user_ids_inner(room_id, RoomMemberships::JOIN, false).await + self.get_user_ids(room_id, RoomMemberships::JOIN).await } } diff --git a/crates/matrix-sdk-sled/src/state_store/migrations.rs b/crates/matrix-sdk-sled/src/state_store/migrations.rs index da33b5d83..7e11f56f1 100644 --- a/crates/matrix-sdk-sled/src/state_store/migrations.rs +++ b/crates/matrix-sdk-sled/src/state_store/migrations.rs @@ -390,7 +390,8 @@ pub const V1_DB_STORES: &[&str] = &[ mod test { use assert_matches::assert_matches; use matrix_sdk_base::{ - deserialized_responses::RawMemberEvent, RoomInfo, RoomState, StateStoreDataKey, + deserialized_responses::RawMemberEvent, RoomInfo, RoomMemberships, RoomState, + StateStoreDataKey, }; use matrix_sdk_test::{async_test, test_json}; use ruma::{ @@ -774,23 +775,41 @@ mod test { .build() .unwrap(); - assert_eq!(store.get_joined_user_ids(room_id).await.unwrap().len(), 0); assert_eq!( - store.get_invited_user_ids(room_id).await.unwrap().as_slice(), + store.get_user_ids(room_id, RoomMemberships::JOIN, false).await.unwrap().len(), + 0 + ); + assert_eq!( + store.get_user_ids(room_id, RoomMemberships::INVITE, false).await.unwrap().as_slice(), [invite_user_id.to_owned()] ); - let user_ids = store.get_user_ids(room_id).await.unwrap(); + let user_ids = store.get_user_ids(room_id, RoomMemberships::empty(), false).await.unwrap(); assert_eq!(user_ids.len(), 2); assert!(user_ids.contains(&invite_user_id.to_owned())); assert!(user_ids.contains(&ban_user_id.to_owned())); assert_eq!( - store.get_stripped_joined_user_ids(stripped_room_id).await.unwrap().as_slice(), + store + .get_user_ids(stripped_room_id, RoomMemberships::JOIN, true) + .await + .unwrap() + .as_slice(), [stripped_user_id.to_owned()] ); - assert_eq!(store.get_stripped_invited_user_ids(stripped_room_id).await.unwrap().len(), 0); assert_eq!( - store.get_stripped_user_ids(stripped_room_id).await.unwrap().as_slice(), + store + .get_user_ids(stripped_room_id, RoomMemberships::INVITE, true) + .await + .unwrap() + .len(), + 0 + ); + assert_eq!( + store + .get_user_ids(stripped_room_id, RoomMemberships::empty(), true) + .await + .unwrap() + .as_slice(), [stripped_user_id.to_owned()] ); } diff --git a/crates/matrix-sdk-sled/src/state_store/mod.rs b/crates/matrix-sdk-sled/src/state_store/mod.rs index 142a6f7bc..e315ba568 100644 --- a/crates/matrix-sdk-sled/src/state_store/mod.rs +++ b/crates/matrix-sdk-sled/src/state_store/mod.rs @@ -852,12 +852,9 @@ impl SledStateStore { .await? } - /// Get a stream of user IDs for the given room with the given memberships - /// and stripped state. - /// - /// If `memberships` is empty, returns all user IDs in the room with the - /// given stripped state. - pub async fn get_user_ids_inner( + /// Get the user IDs for the given room with the given memberships and + /// stripped state. + pub async fn get_user_ids( &self, room_id: &RoomId, memberships: RoomMemberships, @@ -888,36 +885,6 @@ impl SledStateStore { .map_err(StoreError::backend)? } - pub async fn get_user_ids(&self, room_id: &RoomId) -> StoreResult> { - self.get_user_ids_inner(room_id, RoomMemberships::empty(), false).await - } - - pub async fn get_stripped_user_ids(&self, room_id: &RoomId) -> StoreResult> { - self.get_user_ids_inner(room_id, RoomMemberships::empty(), true).await - } - - pub async fn get_invited_user_ids(&self, room_id: &RoomId) -> StoreResult> { - self.get_user_ids_inner(room_id, RoomMemberships::INVITE, false).await - } - - pub async fn get_joined_user_ids(&self, room_id: &RoomId) -> StoreResult> { - self.get_user_ids_inner(room_id, RoomMemberships::JOIN, false).await - } - - pub async fn get_stripped_invited_user_ids( - &self, - room_id: &RoomId, - ) -> StoreResult> { - self.get_user_ids_inner(room_id, RoomMemberships::INVITE, true).await - } - - pub async fn get_stripped_joined_user_ids( - &self, - room_id: &RoomId, - ) -> StoreResult> { - self.get_user_ids_inner(room_id, RoomMemberships::JOIN, true).await - } - pub async fn get_room_infos(&self) -> Result>> { let db = self.clone(); spawn_blocking(move || { @@ -1292,28 +1259,24 @@ impl StateStore for SledStateStore { self.get_member_event(room_id, state_key).await.map_err(Into::into) } - async fn get_user_ids(&self, room_id: &RoomId) -> StoreResult> { - let v = self.get_stripped_user_ids(room_id).await?; + async fn get_user_ids( + &self, + room_id: &RoomId, + memberships: RoomMemberships, + ) -> StoreResult> { + let v = self.get_user_ids(room_id, memberships, true).await?; if !v.is_empty() { return Ok(v); } - self.get_user_ids(room_id).await + self.get_user_ids(room_id, memberships, false).await } async fn get_invited_user_ids(&self, room_id: &RoomId) -> StoreResult> { - let v = self.get_stripped_invited_user_ids(room_id).await?; - if !v.is_empty() { - return Ok(v); - } - self.get_invited_user_ids(room_id).await + StateStore::get_user_ids(self, room_id, RoomMemberships::INVITE).await } async fn get_joined_user_ids(&self, room_id: &RoomId) -> StoreResult> { - let v = self.get_stripped_joined_user_ids(room_id).await?; - if !v.is_empty() { - return Ok(v); - } - self.get_joined_user_ids(room_id).await + StateStore::get_user_ids(self, room_id, RoomMemberships::JOIN).await } async fn get_room_infos(&self) -> StoreResult> { diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index bbd10b19d..452fa53e6 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -701,7 +701,10 @@ impl Common { /// Returns true if all devices in the room are verified, otherwise false. #[cfg(feature = "e2e-encryption")] pub async fn contains_only_verified_devices(&self) -> Result { - let user_ids = self.client.store().get_user_ids(self.room_id()).await?; + use matrix_sdk_base::RoomMemberships; + + let user_ids = + self.client.store().get_user_ids(self.room_id(), RoomMemberships::empty()).await?; for user_id in user_ids { let devices = self.client.encryption().get_user_devices(&user_id).await?;