feat: Move Client::get_dm_room into the main impl Client block
This patch moves the `Client::get_dm_room` helper function and its tests from `src/encryption/mod.rs` to `src/client/mod.rs`, so it may be used without the `e2e-encryption` crate feature enabled. - [x] Public API changes documented in changelogs (optional) Signed-off-by: Ginger <ginger@gingershaped.computer>
This commit is contained in:
@@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
### Features
|
||||
|
||||
- Allow `Client::get_dm_room()` to be called without the `e2e-encryption` crate feature.
|
||||
([#5787](https://github.com/matrix-org/matrix-rust-sdk/pull/5787))
|
||||
- [**breaking**] Add `encryption::secret_storage::SecretStorageError::ImportError` to indicate
|
||||
an error that occurred when importing a secret from secret storage.
|
||||
([#5647](https://github.com/matrix-org/matrix-rust-sdk/pull/5647))
|
||||
|
||||
@@ -73,6 +73,7 @@ use ruma::{
|
||||
federation::discovery::get_server_version,
|
||||
},
|
||||
assign,
|
||||
events::direct::DirectUserIdentifier,
|
||||
push::Ruleset,
|
||||
time::Instant,
|
||||
};
|
||||
@@ -1800,6 +1801,20 @@ impl Client {
|
||||
self.create_room(request).await
|
||||
}
|
||||
|
||||
/// Get the existing DM room with the given user, if any.
|
||||
pub fn get_dm_room(&self, user_id: &UserId) -> Option<Room> {
|
||||
let rooms = self.joined_rooms();
|
||||
|
||||
// Find the room we share with the `user_id` and only with `user_id`
|
||||
let room = rooms.into_iter().find(|r| {
|
||||
let targets = r.direct_targets();
|
||||
targets.len() == 1 && targets.contains(<&DirectUserIdentifier>::from(user_id))
|
||||
});
|
||||
|
||||
trace!(?user_id, ?room, "Found DM room with user");
|
||||
room
|
||||
}
|
||||
|
||||
/// Search the homeserver's directory for public rooms with a filter.
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -3122,7 +3137,7 @@ pub(crate) mod tests {
|
||||
ignored_user_list::IgnoredUserListEventContent,
|
||||
media_preview_config::{InviteAvatars, MediaPreviewConfigEventContent, MediaPreviews},
|
||||
},
|
||||
owned_room_id, owned_user_id, room_alias_id, room_id,
|
||||
owned_room_id, owned_user_id, room_alias_id, room_id, user_id,
|
||||
};
|
||||
use serde_json::json;
|
||||
use stream_assert::{assert_next_matches, assert_pending};
|
||||
@@ -4112,4 +4127,83 @@ pub(crate) mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_get_dm_room_returns_the_room_we_have_with_this_user() {
|
||||
let server = MatrixMockServer::new().await;
|
||||
let client = server.client_builder().build().await;
|
||||
// This is the user ID that is inside MemberAdditional.
|
||||
// Note the confusing username, so we can share
|
||||
// GlobalAccountDataTestEvent::Direct with the invited test.
|
||||
let user_id = user_id!("@invited:localhost");
|
||||
|
||||
// When we receive a sync response saying "invited" is invited to a DM
|
||||
let f = EventFactory::new();
|
||||
let response = SyncResponseBuilder::default()
|
||||
.add_joined_room(
|
||||
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberAdditional),
|
||||
)
|
||||
.add_global_account_data(
|
||||
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
|
||||
)
|
||||
.build_sync_response();
|
||||
client.base_client().receive_sync_response(response).await.unwrap();
|
||||
|
||||
// Then get_dm_room finds this room
|
||||
let found_room = client.get_dm_room(user_id).expect("DM not found!");
|
||||
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_get_dm_room_still_finds_room_where_participant_is_only_invited() {
|
||||
let server = MatrixMockServer::new().await;
|
||||
let client = server.client_builder().build().await;
|
||||
// This is the user ID that is inside MemberInvite
|
||||
let user_id = user_id!("@invited:localhost");
|
||||
|
||||
// When we receive a sync response saying "invited" is invited to a DM
|
||||
let f = EventFactory::new();
|
||||
let response = SyncResponseBuilder::default()
|
||||
.add_joined_room(
|
||||
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberInvite),
|
||||
)
|
||||
.add_global_account_data(
|
||||
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
|
||||
)
|
||||
.build_sync_response();
|
||||
client.base_client().receive_sync_response(response).await.unwrap();
|
||||
|
||||
// Then get_dm_room finds this room
|
||||
let found_room = client.get_dm_room(user_id).expect("DM not found!");
|
||||
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_get_dm_room_still_finds_left_room() {
|
||||
// See the discussion in https://github.com/matrix-org/matrix-rust-sdk/issues/2017
|
||||
// and the high-level issue at https://github.com/vector-im/element-x-ios/issues/1077
|
||||
|
||||
let server = MatrixMockServer::new().await;
|
||||
let client = server.client_builder().build().await;
|
||||
// This is the user ID that is inside MemberAdditional.
|
||||
// Note the confusing username, so we can share
|
||||
// GlobalAccountDataTestEvent::Direct with the invited test.
|
||||
let user_id = user_id!("@invited:localhost");
|
||||
|
||||
// When we receive a sync response saying "invited" is invited to a DM
|
||||
let f = EventFactory::new();
|
||||
let response = SyncResponseBuilder::default()
|
||||
.add_joined_room(
|
||||
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberLeave),
|
||||
)
|
||||
.add_global_account_data(
|
||||
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
|
||||
)
|
||||
.build_sync_response();
|
||||
client.base_client().receive_sync_response(response).await.unwrap();
|
||||
|
||||
// Then get_dm_room finds this room
|
||||
let found_room = client.get_dm_room(user_id).expect("DM not found!");
|
||||
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,10 +64,7 @@ use ruma::{
|
||||
uiaa::{AuthData, UiaaInfo},
|
||||
},
|
||||
assign,
|
||||
events::{
|
||||
direct::DirectUserIdentifier,
|
||||
room::{MediaSource, ThumbnailInfo},
|
||||
},
|
||||
events::room::{MediaSource, ThumbnailInfo},
|
||||
};
|
||||
#[cfg(feature = "experimental-send-custom-to-device")]
|
||||
use ruma::{events::AnyToDeviceEventContent, serde::Raw, to_device::DeviceIdOrAllDevices};
|
||||
@@ -75,7 +72,7 @@ use serde::{Deserialize, de::Error as _};
|
||||
use tasks::BundleReceiverTask;
|
||||
use tokio::sync::{Mutex, RwLockReadGuard};
|
||||
use tokio_stream::wrappers::errors::BroadcastStreamRecvError;
|
||||
use tracing::{debug, error, instrument, trace, warn};
|
||||
use tracing::{debug, error, instrument, warn};
|
||||
use url::Url;
|
||||
use vodozemac::Curve25519PublicKey;
|
||||
|
||||
@@ -89,7 +86,7 @@ use self::{
|
||||
verification::{SasVerification, Verification, VerificationRequest},
|
||||
};
|
||||
use crate::{
|
||||
Client, Error, HttpError, Result, Room, RumaApiError, TransmissionProgress,
|
||||
Client, Error, HttpError, Result, RumaApiError, TransmissionProgress,
|
||||
attachment::Thumbnail,
|
||||
client::{ClientInner, WeakClient},
|
||||
cross_process_lock::CrossProcessLockGuard,
|
||||
@@ -669,20 +666,6 @@ impl Client {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the existing DM room with the given user, if any.
|
||||
pub fn get_dm_room(&self, user_id: &UserId) -> Option<Room> {
|
||||
let rooms = self.joined_rooms();
|
||||
|
||||
// Find the room we share with the `user_id` and only with `user_id`
|
||||
let room = rooms.into_iter().find(|r| {
|
||||
let targets = r.direct_targets();
|
||||
targets.len() == 1 && targets.contains(<&DirectUserIdentifier>::from(user_id))
|
||||
});
|
||||
|
||||
trace!(?room, "Found room");
|
||||
room
|
||||
}
|
||||
|
||||
async fn send_outgoing_request(&self, r: OutgoingRequest) -> Result<()> {
|
||||
use matrix_sdk_base::crypto::types::requests::AnyOutgoingRequest;
|
||||
|
||||
@@ -2034,12 +2017,11 @@ mod tests {
|
||||
|
||||
use matrix_sdk_test::{
|
||||
DEFAULT_TEST_ROOM_ID, JoinedRoomBuilder, StateTestEvent, SyncResponseBuilder, async_test,
|
||||
event_factory::EventFactory, test_json,
|
||||
test_json,
|
||||
};
|
||||
use ruma::{
|
||||
event_id,
|
||||
events::{reaction::ReactionEventContent, relation::Annotation},
|
||||
user_id,
|
||||
};
|
||||
use serde_json::json;
|
||||
use wiremock::{
|
||||
@@ -2106,85 +2088,6 @@ mod tests {
|
||||
room.send_raw("m.reaction", json!({})).await.expect("Sending the reaction should not fail");
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_get_dm_room_returns_the_room_we_have_with_this_user() {
|
||||
let server = MockServer::start().await;
|
||||
let client = logged_in_client(Some(server.uri())).await;
|
||||
// This is the user ID that is inside MemberAdditional.
|
||||
// Note the confusing username, so we can share
|
||||
// GlobalAccountDataTestEvent::Direct with the invited test.
|
||||
let user_id = user_id!("@invited:localhost");
|
||||
|
||||
// When we receive a sync response saying "invited" is invited to a DM
|
||||
let f = EventFactory::new();
|
||||
let response = SyncResponseBuilder::default()
|
||||
.add_joined_room(
|
||||
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberAdditional),
|
||||
)
|
||||
.add_global_account_data(
|
||||
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
|
||||
)
|
||||
.build_sync_response();
|
||||
client.base_client().receive_sync_response(response).await.unwrap();
|
||||
|
||||
// Then get_dm_room finds this room
|
||||
let found_room = client.get_dm_room(user_id).expect("DM not found!");
|
||||
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_get_dm_room_still_finds_room_where_participant_is_only_invited() {
|
||||
let server = MockServer::start().await;
|
||||
let client = logged_in_client(Some(server.uri())).await;
|
||||
// This is the user ID that is inside MemberInvite
|
||||
let user_id = user_id!("@invited:localhost");
|
||||
|
||||
// When we receive a sync response saying "invited" is invited to a DM
|
||||
let f = EventFactory::new();
|
||||
let response = SyncResponseBuilder::default()
|
||||
.add_joined_room(
|
||||
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberInvite),
|
||||
)
|
||||
.add_global_account_data(
|
||||
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
|
||||
)
|
||||
.build_sync_response();
|
||||
client.base_client().receive_sync_response(response).await.unwrap();
|
||||
|
||||
// Then get_dm_room finds this room
|
||||
let found_room = client.get_dm_room(user_id).expect("DM not found!");
|
||||
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_get_dm_room_still_finds_left_room() {
|
||||
// See the discussion in https://github.com/matrix-org/matrix-rust-sdk/issues/2017
|
||||
// and the high-level issue at https://github.com/vector-im/element-x-ios/issues/1077
|
||||
|
||||
let server = MockServer::start().await;
|
||||
let client = logged_in_client(Some(server.uri())).await;
|
||||
// This is the user ID that is inside MemberAdditional.
|
||||
// Note the confusing username, so we can share
|
||||
// GlobalAccountDataTestEvent::Direct with the invited test.
|
||||
let user_id = user_id!("@invited:localhost");
|
||||
|
||||
// When we receive a sync response saying "invited" is invited to a DM
|
||||
let f = EventFactory::new();
|
||||
let response = SyncResponseBuilder::default()
|
||||
.add_joined_room(
|
||||
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberLeave),
|
||||
)
|
||||
.add_global_account_data(
|
||||
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
|
||||
)
|
||||
.build_sync_response();
|
||||
client.base_client().receive_sync_response(response).await.unwrap();
|
||||
|
||||
// Then get_dm_room finds this room
|
||||
let found_room = client.get_dm_room(user_id).expect("DM not found!");
|
||||
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[async_test]
|
||||
async fn test_generation_counter_invalidates_olm_machine() {
|
||||
|
||||
Reference in New Issue
Block a user