Skip to content

Commit a4e68ba

Browse files
authored
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>
1 parent e8fb133 commit a4e68ba

File tree

3 files changed

+101
-102
lines changed

3 files changed

+101
-102
lines changed

crates/matrix-sdk/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file.
88

99
### Features
1010

11+
- Allow `Client::get_dm_room()` to be called without the `e2e-encryption` crate feature.
12+
([#5787](https://github.com/matrix-org/matrix-rust-sdk/pull/5787))
1113
- [**breaking**] Add `encryption::secret_storage::SecretStorageError::ImportError` to indicate
1214
an error that occurred when importing a secret from secret storage.
1315
([#5647](https://github.com/matrix-org/matrix-rust-sdk/pull/5647))

crates/matrix-sdk/src/client/mod.rs

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ use ruma::{
7373
federation::discovery::get_server_version,
7474
},
7575
assign,
76+
events::direct::DirectUserIdentifier,
7677
push::Ruleset,
7778
time::Instant,
7879
};
@@ -1800,6 +1801,20 @@ impl Client {
18001801
self.create_room(request).await
18011802
}
18021803

1804+
/// Get the existing DM room with the given user, if any.
1805+
pub fn get_dm_room(&self, user_id: &UserId) -> Option<Room> {
1806+
let rooms = self.joined_rooms();
1807+
1808+
// Find the room we share with the `user_id` and only with `user_id`
1809+
let room = rooms.into_iter().find(|r| {
1810+
let targets = r.direct_targets();
1811+
targets.len() == 1 && targets.contains(<&DirectUserIdentifier>::from(user_id))
1812+
});
1813+
1814+
trace!(?user_id, ?room, "Found DM room with user");
1815+
room
1816+
}
1817+
18031818
/// Search the homeserver's directory for public rooms with a filter.
18041819
///
18051820
/// # Arguments
@@ -3122,7 +3137,7 @@ pub(crate) mod tests {
31223137
ignored_user_list::IgnoredUserListEventContent,
31233138
media_preview_config::{InviteAvatars, MediaPreviewConfigEventContent, MediaPreviews},
31243139
},
3125-
owned_room_id, owned_user_id, room_alias_id, room_id,
3140+
owned_room_id, owned_user_id, room_alias_id, room_id, user_id,
31263141
};
31273142
use serde_json::json;
31283143
use stream_assert::{assert_next_matches, assert_pending};
@@ -4112,4 +4127,83 @@ pub(crate) mod tests {
41124127
.await
41134128
.unwrap();
41144129
}
4130+
4131+
#[async_test]
4132+
async fn test_get_dm_room_returns_the_room_we_have_with_this_user() {
4133+
let server = MatrixMockServer::new().await;
4134+
let client = server.client_builder().build().await;
4135+
// This is the user ID that is inside MemberAdditional.
4136+
// Note the confusing username, so we can share
4137+
// GlobalAccountDataTestEvent::Direct with the invited test.
4138+
let user_id = user_id!("@invited:localhost");
4139+
4140+
// When we receive a sync response saying "invited" is invited to a DM
4141+
let f = EventFactory::new();
4142+
let response = SyncResponseBuilder::default()
4143+
.add_joined_room(
4144+
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberAdditional),
4145+
)
4146+
.add_global_account_data(
4147+
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
4148+
)
4149+
.build_sync_response();
4150+
client.base_client().receive_sync_response(response).await.unwrap();
4151+
4152+
// Then get_dm_room finds this room
4153+
let found_room = client.get_dm_room(user_id).expect("DM not found!");
4154+
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
4155+
}
4156+
4157+
#[async_test]
4158+
async fn test_get_dm_room_still_finds_room_where_participant_is_only_invited() {
4159+
let server = MatrixMockServer::new().await;
4160+
let client = server.client_builder().build().await;
4161+
// This is the user ID that is inside MemberInvite
4162+
let user_id = user_id!("@invited:localhost");
4163+
4164+
// When we receive a sync response saying "invited" is invited to a DM
4165+
let f = EventFactory::new();
4166+
let response = SyncResponseBuilder::default()
4167+
.add_joined_room(
4168+
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberInvite),
4169+
)
4170+
.add_global_account_data(
4171+
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
4172+
)
4173+
.build_sync_response();
4174+
client.base_client().receive_sync_response(response).await.unwrap();
4175+
4176+
// Then get_dm_room finds this room
4177+
let found_room = client.get_dm_room(user_id).expect("DM not found!");
4178+
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
4179+
}
4180+
4181+
#[async_test]
4182+
async fn test_get_dm_room_still_finds_left_room() {
4183+
// See the discussion in https://github.com/matrix-org/matrix-rust-sdk/issues/2017
4184+
// and the high-level issue at https://github.com/vector-im/element-x-ios/issues/1077
4185+
4186+
let server = MatrixMockServer::new().await;
4187+
let client = server.client_builder().build().await;
4188+
// This is the user ID that is inside MemberAdditional.
4189+
// Note the confusing username, so we can share
4190+
// GlobalAccountDataTestEvent::Direct with the invited test.
4191+
let user_id = user_id!("@invited:localhost");
4192+
4193+
// When we receive a sync response saying "invited" is invited to a DM
4194+
let f = EventFactory::new();
4195+
let response = SyncResponseBuilder::default()
4196+
.add_joined_room(
4197+
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberLeave),
4198+
)
4199+
.add_global_account_data(
4200+
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
4201+
)
4202+
.build_sync_response();
4203+
client.base_client().receive_sync_response(response).await.unwrap();
4204+
4205+
// Then get_dm_room finds this room
4206+
let found_room = client.get_dm_room(user_id).expect("DM not found!");
4207+
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
4208+
}
41154209
}

crates/matrix-sdk/src/encryption/mod.rs

Lines changed: 4 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,15 @@ use ruma::{
6464
uiaa::{AuthData, UiaaInfo},
6565
},
6666
assign,
67-
events::{
68-
direct::DirectUserIdentifier,
69-
room::{MediaSource, ThumbnailInfo},
70-
},
67+
events::room::{MediaSource, ThumbnailInfo},
7168
};
7269
#[cfg(feature = "experimental-send-custom-to-device")]
7370
use ruma::{events::AnyToDeviceEventContent, serde::Raw, to_device::DeviceIdOrAllDevices};
7471
use serde::{Deserialize, de::Error as _};
7572
use tasks::BundleReceiverTask;
7673
use tokio::sync::{Mutex, RwLockReadGuard};
7774
use tokio_stream::wrappers::errors::BroadcastStreamRecvError;
78-
use tracing::{debug, error, instrument, trace, warn};
75+
use tracing::{debug, error, instrument, warn};
7976
use url::Url;
8077
use vodozemac::Curve25519PublicKey;
8178

@@ -89,7 +86,7 @@ use self::{
8986
verification::{SasVerification, Verification, VerificationRequest},
9087
};
9188
use crate::{
92-
Client, Error, HttpError, Result, Room, RumaApiError, TransmissionProgress,
89+
Client, Error, HttpError, Result, RumaApiError, TransmissionProgress,
9390
attachment::Thumbnail,
9491
client::{ClientInner, WeakClient},
9592
cross_process_lock::CrossProcessLockGuard,
@@ -669,20 +666,6 @@ impl Client {
669666
Ok(())
670667
}
671668

672-
/// Get the existing DM room with the given user, if any.
673-
pub fn get_dm_room(&self, user_id: &UserId) -> Option<Room> {
674-
let rooms = self.joined_rooms();
675-
676-
// Find the room we share with the `user_id` and only with `user_id`
677-
let room = rooms.into_iter().find(|r| {
678-
let targets = r.direct_targets();
679-
targets.len() == 1 && targets.contains(<&DirectUserIdentifier>::from(user_id))
680-
});
681-
682-
trace!(?room, "Found room");
683-
room
684-
}
685-
686669
async fn send_outgoing_request(&self, r: OutgoingRequest) -> Result<()> {
687670
use matrix_sdk_base::crypto::types::requests::AnyOutgoingRequest;
688671

@@ -2034,12 +2017,11 @@ mod tests {
20342017

20352018
use matrix_sdk_test::{
20362019
DEFAULT_TEST_ROOM_ID, JoinedRoomBuilder, StateTestEvent, SyncResponseBuilder, async_test,
2037-
event_factory::EventFactory, test_json,
2020+
test_json,
20382021
};
20392022
use ruma::{
20402023
event_id,
20412024
events::{reaction::ReactionEventContent, relation::Annotation},
2042-
user_id,
20432025
};
20442026
use serde_json::json;
20452027
use wiremock::{
@@ -2106,85 +2088,6 @@ mod tests {
21062088
room.send_raw("m.reaction", json!({})).await.expect("Sending the reaction should not fail");
21072089
}
21082090

2109-
#[async_test]
2110-
async fn test_get_dm_room_returns_the_room_we_have_with_this_user() {
2111-
let server = MockServer::start().await;
2112-
let client = logged_in_client(Some(server.uri())).await;
2113-
// This is the user ID that is inside MemberAdditional.
2114-
// Note the confusing username, so we can share
2115-
// GlobalAccountDataTestEvent::Direct with the invited test.
2116-
let user_id = user_id!("@invited:localhost");
2117-
2118-
// When we receive a sync response saying "invited" is invited to a DM
2119-
let f = EventFactory::new();
2120-
let response = SyncResponseBuilder::default()
2121-
.add_joined_room(
2122-
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberAdditional),
2123-
)
2124-
.add_global_account_data(
2125-
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
2126-
)
2127-
.build_sync_response();
2128-
client.base_client().receive_sync_response(response).await.unwrap();
2129-
2130-
// Then get_dm_room finds this room
2131-
let found_room = client.get_dm_room(user_id).expect("DM not found!");
2132-
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
2133-
}
2134-
2135-
#[async_test]
2136-
async fn test_get_dm_room_still_finds_room_where_participant_is_only_invited() {
2137-
let server = MockServer::start().await;
2138-
let client = logged_in_client(Some(server.uri())).await;
2139-
// This is the user ID that is inside MemberInvite
2140-
let user_id = user_id!("@invited:localhost");
2141-
2142-
// When we receive a sync response saying "invited" is invited to a DM
2143-
let f = EventFactory::new();
2144-
let response = SyncResponseBuilder::default()
2145-
.add_joined_room(
2146-
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberInvite),
2147-
)
2148-
.add_global_account_data(
2149-
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
2150-
)
2151-
.build_sync_response();
2152-
client.base_client().receive_sync_response(response).await.unwrap();
2153-
2154-
// Then get_dm_room finds this room
2155-
let found_room = client.get_dm_room(user_id).expect("DM not found!");
2156-
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
2157-
}
2158-
2159-
#[async_test]
2160-
async fn test_get_dm_room_still_finds_left_room() {
2161-
// See the discussion in https://github.com/matrix-org/matrix-rust-sdk/issues/2017
2162-
// and the high-level issue at https://github.com/vector-im/element-x-ios/issues/1077
2163-
2164-
let server = MockServer::start().await;
2165-
let client = logged_in_client(Some(server.uri())).await;
2166-
// This is the user ID that is inside MemberAdditional.
2167-
// Note the confusing username, so we can share
2168-
// GlobalAccountDataTestEvent::Direct with the invited test.
2169-
let user_id = user_id!("@invited:localhost");
2170-
2171-
// When we receive a sync response saying "invited" is invited to a DM
2172-
let f = EventFactory::new();
2173-
let response = SyncResponseBuilder::default()
2174-
.add_joined_room(
2175-
JoinedRoomBuilder::default().add_state_event(StateTestEvent::MemberLeave),
2176-
)
2177-
.add_global_account_data(
2178-
f.direct().add_user(user_id.to_owned().into(), *DEFAULT_TEST_ROOM_ID),
2179-
)
2180-
.build_sync_response();
2181-
client.base_client().receive_sync_response(response).await.unwrap();
2182-
2183-
// Then get_dm_room finds this room
2184-
let found_room = client.get_dm_room(user_id).expect("DM not found!");
2185-
assert!(found_room.get_member_no_sync(user_id).await.unwrap().is_some());
2186-
}
2187-
21882091
#[cfg(feature = "sqlite")]
21892092
#[async_test]
21902093
async fn test_generation_counter_invalidates_olm_machine() {

0 commit comments

Comments
 (0)