From 0bdcc0fbf90286b7555fda48403151f02dde6717 Mon Sep 17 00:00:00 2001 From: Johannes Becker Date: Thu, 13 May 2021 17:42:06 +0200 Subject: [PATCH 1/7] appservice: Refactor API --- .../examples/actix_autojoin.rs | 6 +- matrix_sdk_appservice/src/actix.rs | 8 +- matrix_sdk_appservice/src/lib.rs | 213 ++++++++++-------- matrix_sdk_appservice/tests/tests.rs | 8 +- 4 files changed, 135 insertions(+), 100 deletions(-) diff --git a/matrix_sdk_appservice/examples/actix_autojoin.rs b/matrix_sdk_appservice/examples/actix_autojoin.rs index cc798966..ad385180 100644 --- a/matrix_sdk_appservice/examples/actix_autojoin.rs +++ b/matrix_sdk_appservice/examples/actix_autojoin.rs @@ -34,7 +34,9 @@ impl EventHandler for AppserviceEventHandler { if let MembershipState::Invite = event.content.membership { let user_id = UserId::try_from(event.state_key.clone()).unwrap(); - let client = self.appservice.client_with_localpart(user_id.localpart()).await.unwrap(); + self.appservice.register(user_id.localpart()).await.unwrap(); + + let client = self.appservice.client(Some(user_id.localpart())).await.unwrap(); client.join_room_by_id(room.room_id()).await.unwrap(); } @@ -55,7 +57,7 @@ pub async fn main() -> std::io::Result<()> { let event_handler = AppserviceEventHandler::new(appservice.clone()); - appservice.client().set_event_handler(Box::new(event_handler)).await; + appservice.set_event_handler(Box::new(event_handler)).await.unwrap(); HttpServer::new(move || App::new().service(appservice.actix_service())) .bind(("0.0.0.0", 8090))? diff --git a/matrix_sdk_appservice/src/actix.rs b/matrix_sdk_appservice/src/actix.rs index c0114440..bf5d2800 100644 --- a/matrix_sdk_appservice/src/actix.rs +++ b/matrix_sdk_appservice/src/actix.rs @@ -61,11 +61,11 @@ async fn push_transactions( request: IncomingRequest, appservice: Data, ) -> Result { - if !appservice.hs_token_matches(request.access_token) { + if !appservice.compare_hs_token(request.access_token) { return Ok(HttpResponse::Unauthorized().finish()); } - appservice.client().receive_transaction(request.incoming).await.unwrap(); + appservice.client(None).await?.receive_transaction(request.incoming).await?; Ok(HttpResponse::Ok().json("{}")) } @@ -76,7 +76,7 @@ async fn query_user_id( request: IncomingRequest, appservice: Data, ) -> Result { - if !appservice.hs_token_matches(request.access_token) { + if !appservice.compare_hs_token(request.access_token) { return Ok(HttpResponse::Unauthorized().finish()); } @@ -89,7 +89,7 @@ async fn query_room_alias( request: IncomingRequest, appservice: Data, ) -> Result { - if !appservice.hs_token_matches(request.access_token) { + if !appservice.compare_hs_token(request.access_token) { return Ok(HttpResponse::Unauthorized().finish()); } diff --git a/matrix_sdk_appservice/src/lib.rs b/matrix_sdk_appservice/src/lib.rs index 67b89385..819380a4 100644 --- a/matrix_sdk_appservice/src/lib.rs +++ b/matrix_sdk_appservice/src/lib.rs @@ -20,13 +20,26 @@ //! the webserver for you //! * receive and validate requests from the homeserver correctly //! * allow calling the homeserver with proper virtual user identity assertion -//! * have the goal to have a consistent room state available by leveraging the -//! stores that the matrix-sdk provides +//! * have consistent room state by leveraging matrix-sdk's state store +//! * provide E2EE support by leveraging matrix-sdk's crypto store +//! +//! # Status +//! +//! The crate is in an experimental state. Follow +//! [matrix-org/matrix-rust-sdk#228] for progress. //! //! # Quickstart //! //! ```no_run //! # async { +//! # +//! # use matrix_sdk::{async_trait, EventHandler}; +//! # +//! # struct AppserviceEventHandler; +//! # +//! # #[async_trait] +//! # impl EventHandler for AppserviceEventHandler {} +//! # //! use matrix_sdk_appservice::{Appservice, AppserviceRegistration}; //! //! let homeserver_url = "http://127.0.0.1:8008"; @@ -42,17 +55,23 @@ //! users: //! - exclusive: true //! regex: '@_appservice_.*' -//! ") -//! .unwrap(); +//! ")?; //! -//! let appservice = Appservice::new(homeserver_url, server_name, registration).await.unwrap(); -//! // set event handler with `appservice.client().set_event_handler()` here -//! let (host, port) = appservice.get_host_and_port_from_registration().unwrap(); -//! appservice.run(host, port).await.unwrap(); +//! let appservice = Appservice::new(homeserver_url, server_name, registration).await?; +//! appservice.set_event_handler(Box::new(AppserviceEventHandler)).await?; +//! +//! let (host, port) = appservice.registration().get_host_and_port()?; +//! appservice.run(host, port).await?; +//! # +//! # Ok::<(), Box>(()) //! # }; //! ``` //! +//! Check the [examples directory] for fully working examples. +//! //! [Application Service]: https://matrix.org/docs/spec/application_service/r0.1.2 +//! [matrix-org/matrix-rust-sdk#228]: https://github.com/matrix-org/matrix-rust-sdk/issues/228 +//! [examples directory]: https://github.com/matrix-org/matrix-rust-sdk/tree/master/matrix_sdk_appservice/examples #[cfg(not(any(feature = "actix",)))] compile_error!("one webserver feature must be enabled. available ones: `actix`"); @@ -79,7 +98,8 @@ use matrix_sdk::{ assign, identifiers::{self, DeviceId, ServerNameBox, UserId}, reqwest::Url, - Client, ClientConfig, FromHttpResponseError, HttpError, RequestConfig, ServerError, Session, + Client, ClientConfig, EventHandler, FromHttpResponseError, HttpError, RequestConfig, + ServerError, Session, }; use regex::Regex; #[cfg(not(feature = "actix"))] @@ -96,6 +116,8 @@ pub type Host = String; pub type Port = u16; /// Appservice Registration +/// +/// Wrapper around [`Registration`] #[derive(Debug, Clone)] pub struct AppserviceRegistration { inner: Registration, @@ -117,6 +139,26 @@ impl AppserviceRegistration { Ok(Self { inner: serde_yaml::from_reader(file)? }) } + + /// Get the host and port from the registration URL + /// + /// If no port is found it falls back to scheme defaults: 80 for http and + /// 443 for https + pub fn get_host_and_port(&self) -> Result<(Host, Port)> { + let uri = Uri::try_from(&self.inner.url)?; + + let host = uri.host().ok_or(Error::MissingRegistrationHost)?.to_owned(); + let port = match uri.port() { + Some(port) => Ok(port.as_u16()), + None => match uri.scheme_str() { + Some("http") => Ok(80), + Some("https") => Ok(443), + _ => Err(Error::MissingRegistrationPort), + }, + }?; + + Ok((host, port)) + } } impl From for AppserviceRegistration { @@ -133,31 +175,20 @@ impl Deref for AppserviceRegistration { } } -async fn create_client( - homeserver_url: &Url, - server_name: &ServerNameBox, +async fn client_session_with_login_restore( + client: &Client, registration: &AppserviceRegistration, - localpart: Option<&str>, -) -> Result { - let client = if localpart.is_some() { - let request_config = RequestConfig::default().assert_identity(); - let config = ClientConfig::default().request_config(request_config); - Client::new_with_config(homeserver_url.clone(), config)? - } else { - Client::new(homeserver_url.clone())? - }; - + localpart: impl AsRef + Into>, + server_name: &ServerNameBox, +) -> Result<()> { let session = Session { access_token: registration.as_token.clone(), - user_id: UserId::parse_with_server_name( - localpart.unwrap_or(®istration.sender_localpart), - &server_name, - )?, + user_id: UserId::parse_with_server_name(localpart, server_name)?, device_id: DeviceId::new(), }; client.restore_login(session).await?; - Ok(client) + Ok(()) } /// Appservice @@ -189,60 +220,82 @@ impl Appservice { let homeserver_url = homeserver_url.try_into()?; let server_name = server_name.try_into()?; - let client = create_client(&homeserver_url, &server_name, ®istration, None).await?; + let client_sender_localpart = Client::new(homeserver_url.clone())?; - Ok(Appservice { - homeserver_url, - server_name, - registration, - client_sender_localpart: client, - }) - } - - /// Get `Client` for the user associated with the application service - /// (`sender_localpart` of the [registration]) - /// - /// [registration]: https://matrix.org/docs/spec/application_service/r0.1.2#registration - pub fn client(&self) -> Client { - self.client_sender_localpart.clone() - } - - /// Get `Client` for the given `localpart` - /// - /// If the `localpart` is covered by the `namespaces` in the [registration] - /// all requests to the homeserver will [assert the identity] to the - /// according virtual user. - /// - /// [registration]: https://matrix.org/docs/spec/application_service/r0.1.2#registration - /// [assert the identity]: - /// https://matrix.org/docs/spec/application_service/r0.1.2#identity-assertion - pub async fn client_with_localpart( - &self, - localpart: impl AsRef + Into>, - ) -> Result { - let user_id = UserId::parse_with_server_name(localpart, &self.server_name)?; - let localpart = user_id.localpart().to_owned(); - - let client = create_client( - &self.homeserver_url, - &self.server_name, - &self.registration, - Some(&localpart), + client_session_with_login_restore( + &client_sender_localpart, + ®istration, + registration.sender_localpart.as_ref(), + &server_name, ) .await?; - self.ensure_registered(localpart).await?; + Ok(Appservice { homeserver_url, server_name, registration, client_sender_localpart }) + } + + /// Get a [`Client`] + /// + /// Will return a `Client` that's configured to [assert the identity] on all + /// outgoing homeserver requests if `localpart` is given. If not given + /// the `Client` will use the main user associated with this appservice, + /// that is the `sender_localpart` in the [`AppserviceRegistration`] + /// + /// # Arguments + /// + /// * `localpart` - The localpart of the user we want assert our identity to + /// + /// [registration]: https://matrix.org/docs/spec/application_service/r0.1.2#registration + /// [assert the identity]: https://matrix.org/docs/spec/application_service/r0.1.2#identity-assertion + pub async fn client(&self, localpart: Option<&str>) -> Result { + let localpart = localpart.unwrap_or_else(|| self.registration.sender_localpart.as_ref()); + + // The `as_token` in the `Session` maps to the main appservice user + // (`sender_localpart`) by default, so we don't need to assert identity + // in that case + let client = if localpart == self.registration.sender_localpart { + self.client_sender_localpart.clone() + } else { + let request_config = RequestConfig::default().assert_identity(); + let config = ClientConfig::default().request_config(request_config); + let client = Client::new_with_config(self.homeserver_url.clone(), config)?; + + client_session_with_login_restore( + &client, + &self.registration, + localpart, + &self.server_name, + ) + .await?; + + client + }; Ok(client) } - async fn ensure_registered(&self, localpart: impl AsRef) -> Result<()> { + /// Convenience wrapper around [`Client::set_event_handler()`] + pub async fn set_event_handler(&self, handler: Box) -> Result<()> { + let client = self.client(None).await?; + client.set_event_handler(handler).await; + + Ok(()) + } + + /// Register a virtual user by sending a [`RegistrationRequest`] to the + /// homeserver + /// + /// # Arguments + /// + /// * `localpart` - The localpart of the user to register. Must be covered + /// by the namespaces in the [`Registration`] in order to succeed. + pub async fn register(&self, localpart: impl AsRef) -> Result<()> { let request = assign!(RegistrationRequest::new(), { username: Some(localpart.as_ref()), login_type: Some(&LoginType::ApplicationService), }); - match self.client().register(request).await { + let client = self.client(None).await?; + match client.register(request).await { Ok(_) => (), Err(error) => match error { matrix_sdk::Error::Http(HttpError::UiaaError(FromHttpResponseError::Http( @@ -266,14 +319,14 @@ impl Appservice { /// Get the Appservice [registration] /// /// [registration]: https://matrix.org/docs/spec/application_service/r0.1.2#registration - pub fn registration(&self) -> &Registration { + pub fn registration(&self) -> &AppserviceRegistration { &self.registration } /// Compare the given `hs_token` against `registration.hs_token` /// /// Returns `true` if the tokens match, `false` otherwise. - pub fn hs_token_matches(&self, hs_token: impl AsRef) -> bool { + pub fn compare_hs_token(&self, hs_token: impl AsRef) -> bool { self.registration.hs_token == hs_token.as_ref() } @@ -290,26 +343,6 @@ impl Appservice { Ok(false) } - /// Get the host and port from the registration URL - /// - /// If no port is found it falls back to scheme defaults: 80 for http and - /// 443 for https - pub fn get_host_and_port_from_registration(&self) -> Result<(Host, Port)> { - let uri = Uri::try_from(&self.registration.url)?; - - let host = uri.host().ok_or(Error::MissingRegistrationHost)?.to_owned(); - let port = match uri.port() { - Some(port) => Ok(port.as_u16()), - None => match uri.scheme_str() { - Some("http") => Ok(80), - Some("https") => Ok(443), - _ => Err(Error::MissingRegistrationPort), - }, - }?; - - Ok((host, port)) - } - /// Service to register on an Actix `App` #[cfg(feature = "actix")] #[cfg_attr(docs, doc(cfg(feature = "actix")))] diff --git a/matrix_sdk_appservice/tests/tests.rs b/matrix_sdk_appservice/tests/tests.rs index 30cdf2b7..61fe0ee4 100644 --- a/matrix_sdk_appservice/tests/tests.rs +++ b/matrix_sdk_appservice/tests/tests.rs @@ -76,7 +76,7 @@ async fn test_event_handler() -> Result<()> { } } - appservice.client().set_event_handler(Box::new(Example::new())).await; + appservice.set_event_handler(Box::new(Example::new())).await?; let event = serde_json::from_value::(member_json()).unwrap(); let event: Raw = AnyRoomEvent::State(event).into(); @@ -87,7 +87,7 @@ async fn test_event_handler() -> Result<()> { events, ); - appservice.client().receive_transaction(incoming).await?; + appservice.client(None).await?.receive_transaction(incoming).await?; Ok(()) } @@ -105,7 +105,7 @@ async fn test_transaction() -> Result<()> { events, ); - appservice.client().receive_transaction(incoming).await?; + appservice.client(None).await?.receive_transaction(incoming).await?; Ok(()) } @@ -116,7 +116,7 @@ async fn test_verify_hs_token() -> Result<()> { let registration = appservice.registration(); - assert!(appservice.hs_token_matches(®istration.hs_token)); + assert!(appservice.compare_hs_token(®istration.hs_token)); Ok(()) } From 15540e84e3feb4a1e681861de489cb98b39b40f4 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Sat, 15 May 2021 16:03:22 +0200 Subject: [PATCH 2/7] Upgrade ruma --- matrix_sdk_base/src/client.rs | 14 ++++++-------- matrix_sdk_base/src/store/sled_store/mod.rs | 6 +++--- matrix_sdk_common/Cargo.toml | 2 +- matrix_sdk_common/src/deserialized_responses.rs | 5 +++-- matrix_sdk_common/src/lib.rs | 2 +- matrix_sdk_crypto/src/machine.rs | 5 ++--- .../src/olm/group_sessions/inbound.rs | 15 ++------------- matrix_sdk_crypto/src/verification/requests.rs | 5 +++-- 8 files changed, 21 insertions(+), 33 deletions(-) diff --git a/matrix_sdk_base/src/client.rs b/matrix_sdk_base/src/client.rs index e3555ea4..d24a2f1c 100644 --- a/matrix_sdk_base/src/client.rs +++ b/matrix_sdk_base/src/client.rs @@ -20,7 +20,6 @@ use std::{ path::{Path, PathBuf}, result::Result as StdResult, sync::Arc, - time::SystemTime, }; #[cfg(feature = "encryption")] @@ -49,7 +48,7 @@ use matrix_sdk_common::{ instant::Instant, locks::RwLock, push::{Action, PushConditionRoomCtx, Ruleset}, - Raw, UInt, + MilliSecondsSinceUnixEpoch, Raw, UInt, }; #[cfg(feature = "encryption")] use matrix_sdk_crypto::{ @@ -100,8 +99,7 @@ pub struct AdditionalUnsignedData { pub fn hoist_and_deserialize_state_event( event: &Raw, ) -> StdResult { - let prev_content = - serde_json::from_str::(event.json().get())?.unsigned.prev_content; + let prev_content = event.deserialize_as::()?.unsigned.prev_content; let mut ev = event.deserialize()?; @@ -117,8 +115,7 @@ pub fn hoist_and_deserialize_state_event( fn hoist_member_event( event: &Raw>, ) -> StdResult, serde_json::Error> { - let prev_content = - serde_json::from_str::(event.json().get())?.unsigned.prev_content; + let prev_content = event.deserialize_as::()?.unsigned.prev_content; let mut e = event.deserialize()?; @@ -132,7 +129,8 @@ fn hoist_member_event( fn hoist_room_event_prev_content( event: &Raw, ) -> StdResult { - let prev_content = serde_json::from_str::(event.json().get()) + let prev_content = event + .deserialize_as::() .map(|more_unsigned| more_unsigned.unsigned) .map(|additional| additional.prev_content)? .and_then(|p| p.deserialize().ok()); @@ -515,7 +513,7 @@ impl BaseClient { event.event.clone(), false, room_id.clone(), - SystemTime::now(), + MilliSecondsSinceUnixEpoch::now(), ), ); } diff --git a/matrix_sdk_base/src/store/sled_store/mod.rs b/matrix_sdk_base/src/store/sled_store/mod.rs index 74ad0175..cace1128 100644 --- a/matrix_sdk_base/src/store/sled_store/mod.rs +++ b/matrix_sdk_base/src/store/sled_store/mod.rs @@ -681,7 +681,7 @@ impl StateStore for SledStore { #[cfg(test)] mod test { - use std::{convert::TryFrom, time::SystemTime}; + use std::convert::TryFrom; use matrix_sdk_common::{ events::{ @@ -692,7 +692,7 @@ mod test { AnySyncStateEvent, EventType, Unsigned, }, identifiers::{room_id, user_id, EventId, UserId}, - Raw, + MilliSecondsSinceUnixEpoch, Raw, }; use matrix_sdk_test::async_test; use serde_json::json; @@ -733,7 +733,7 @@ mod test { event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(), content, sender: user_id(), - origin_server_ts: SystemTime::now(), + origin_server_ts: MilliSecondsSinceUnixEpoch::now(), state_key: user_id(), prev_content: None, unsigned: Unsigned::default(), diff --git a/matrix_sdk_common/Cargo.toml b/matrix_sdk_common/Cargo.toml index 5206e11d..f2169f20 100644 --- a/matrix_sdk_common/Cargo.toml +++ b/matrix_sdk_common/Cargo.toml @@ -22,7 +22,7 @@ async-trait = "0.1.42" [dependencies.ruma] version = "0.0.3" git = "https://github.com/ruma/ruma" -rev = "3bdead1cf207e3ab9c8fcbfc454c054c726ba6f5" +rev = "e1ab817e0bef78cb8241d6d3c1ced7d6b414c7f6" features = ["client-api-c", "compat", "unstable-pre-spec"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/matrix_sdk_common/src/deserialized_responses.rs b/matrix_sdk_common/src/deserialized_responses.rs index 3acc4b4d..6582b0d2 100644 --- a/matrix_sdk_common/src/deserialized_responses.rs +++ b/matrix_sdk_common/src/deserialized_responses.rs @@ -1,4 +1,4 @@ -use std::{collections::BTreeMap, convert::TryFrom, time::SystemTime}; +use std::{collections::BTreeMap, convert::TryFrom}; use ruma::{ api::client::r0::sync::sync_events::{ @@ -22,6 +22,7 @@ use super::{ SyncStateEvent, Unsigned, }, identifiers::{DeviceKeyAlgorithm, EventId, RoomId, UserId}, + MilliSecondsSinceUnixEpoch, }; /// A change in ambiguity of room members that an `m.room.member` event @@ -249,7 +250,7 @@ impl Timeline { pub struct MemberEvent { pub content: MemberEventContent, pub event_id: EventId, - pub origin_server_ts: SystemTime, + pub origin_server_ts: MilliSecondsSinceUnixEpoch, pub prev_content: Option, pub sender: UserId, pub state_key: UserId, diff --git a/matrix_sdk_common/src/lib.rs b/matrix_sdk_common/src/lib.rs index 5c91e21f..c45a082d 100644 --- a/matrix_sdk_common/src/lib.rs +++ b/matrix_sdk_common/src/lib.rs @@ -15,7 +15,7 @@ pub use ruma::{ }, assign, directory, encryption, events, identifiers, int, presence, push, receipt, serde::{CanonicalJsonValue, Raw}, - thirdparty, uint, Int, Outgoing, UInt, + thirdparty, uint, Int, MilliSecondsSinceUnixEpoch, Outgoing, SecondsSinceUnixEpoch, UInt, }; pub use uuid; diff --git a/matrix_sdk_crypto/src/machine.rs b/matrix_sdk_crypto/src/machine.rs index 869bafbd..59e70b13 100644 --- a/matrix_sdk_crypto/src/machine.rs +++ b/matrix_sdk_crypto/src/machine.rs @@ -1204,7 +1204,6 @@ pub(crate) mod test { collections::BTreeMap, convert::{TryFrom, TryInto}, sync::Arc, - time::SystemTime, }; use http::Response; @@ -1221,7 +1220,7 @@ pub(crate) mod test { identifiers::{ event_id, room_id, user_id, DeviceId, DeviceKeyAlgorithm, DeviceKeyId, UserId, }, - IncomingResponse, Raw, + IncomingResponse, MilliSecondsSinceUnixEpoch, Raw, }; use matrix_sdk_test::test_json; use serde_json::json; @@ -1668,7 +1667,7 @@ pub(crate) mod test { let event = SyncMessageEvent { event_id: event_id!("$xxxxx:example.org"), - origin_server_ts: SystemTime::now(), + origin_server_ts: MilliSecondsSinceUnixEpoch::now(), sender: alice.user_id().clone(), content: encrypted_content, unsigned: Unsigned::default(), diff --git a/matrix_sdk_crypto/src/olm/group_sessions/inbound.rs b/matrix_sdk_crypto/src/olm/group_sessions/inbound.rs index cb81ad73..957fbed8 100644 --- a/matrix_sdk_crypto/src/olm/group_sessions/inbound.rs +++ b/matrix_sdk_crypto/src/olm/group_sessions/inbound.rs @@ -12,12 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{ - collections::BTreeMap, - convert::{TryFrom, TryInto}, - fmt, mem, - sync::Arc, -}; +use std::{collections::BTreeMap, convert::TryFrom, fmt, mem, sync::Arc}; use matrix_sdk_common::{ events::{ @@ -310,13 +305,7 @@ impl InboundGroupSession { let mut decrypted_value = serde_json::from_str::(&plaintext)?; let decrypted_object = decrypted_value.as_object_mut().ok_or(EventError::NotAnObject)?; - // TODO better number conversion here. - let server_ts = event - .origin_server_ts - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_millis(); - let server_ts: i64 = server_ts.try_into().unwrap_or_default(); + let server_ts: i64 = event.origin_server_ts.0.into(); decrypted_object.insert("sender".to_owned(), event.sender.to_string().into()); decrypted_object.insert("event_id".to_owned(), event.event_id.to_string().into()); diff --git a/matrix_sdk_crypto/src/verification/requests.rs b/matrix_sdk_crypto/src/verification/requests.rs index 7f3ffcb4..097279d8 100644 --- a/matrix_sdk_crypto/src/verification/requests.rs +++ b/matrix_sdk_crypto/src/verification/requests.rs @@ -436,12 +436,13 @@ struct Passive { #[cfg(test)] mod test { - use std::{convert::TryFrom, time::SystemTime}; + use std::convert::TryFrom; use matrix_sdk_common::{ api::r0::message::send_message_event::Response as RoomMessageResponse, events::{SyncMessageEvent, Unsigned}, identifiers::{event_id, room_id, DeviceIdBox, UserId}, + MilliSecondsSinceUnixEpoch, }; use matrix_sdk_test::async_test; @@ -566,7 +567,7 @@ mod test { content: c, event_id: event_id.clone(), sender: bob_id(), - origin_server_ts: SystemTime::now(), + origin_server_ts: MilliSecondsSinceUnixEpoch::now(), unsigned: Unsigned::default(), } } else { From ffea84b64aa172b9b153a76588f4f609bf15c441 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Sat, 15 May 2021 17:23:31 +0200 Subject: [PATCH 3/7] Use Instant instead of SystemTime to measure elapsed time --- matrix_sdk_base/src/store/sled_store/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix_sdk_base/src/store/sled_store/mod.rs b/matrix_sdk_base/src/store/sled_store/mod.rs index cace1128..973360cc 100644 --- a/matrix_sdk_base/src/store/sled_store/mod.rs +++ b/matrix_sdk_base/src/store/sled_store/mod.rs @@ -19,7 +19,7 @@ use std::{ convert::TryFrom, path::{Path, PathBuf}, sync::Arc, - time::SystemTime, + time::Instant, }; use futures::{ @@ -286,7 +286,7 @@ impl SledStore { } pub async fn save_changes(&self, changes: &StateChanges) -> Result<()> { - let now = SystemTime::now(); + let now = Instant::now(); let ret: Result<(), TransactionError> = ( &self.session, From 5059d8b2c6e759e197c2b251cf894b6e9656c2d9 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Mon, 17 May 2021 02:21:18 +0200 Subject: [PATCH 4/7] Remove unused import --- matrix_sdk_appservice/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/matrix_sdk_appservice/src/lib.rs b/matrix_sdk_appservice/src/lib.rs index 819380a4..11c9710d 100644 --- a/matrix_sdk_appservice/src/lib.rs +++ b/matrix_sdk_appservice/src/lib.rs @@ -102,8 +102,6 @@ use matrix_sdk::{ ServerError, Session, }; use regex::Regex; -#[cfg(not(feature = "actix"))] -use tracing::error; use tracing::warn; #[cfg(feature = "actix")] From cd77441d1bf8318ecf4cc9e1886696558ea6ed7b Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Mon, 17 May 2021 02:21:30 +0200 Subject: [PATCH 5/7] Upgrade ruma to 0.1.0 (crates.io release) --- matrix_sdk/src/client.rs | 27 +++--- matrix_sdk/src/room/joined.rs | 73 +++++++-------- matrix_sdk_base/src/store/sled_store/mod.rs | 10 +-- matrix_sdk_common/Cargo.toml | 4 +- .../src/file_encryption/attachments.rs | 6 +- matrix_sdk_crypto/src/key_request.rs | 60 ++++++------- matrix_sdk_crypto/src/store/sled.rs | 12 +-- .../src/verification/requests.rs | 22 ++--- .../src/verification/sas/helpers.rs | 7 +- .../src/verification/sas/sas_state.rs | 88 +++++++++---------- 10 files changed, 141 insertions(+), 168 deletions(-) diff --git a/matrix_sdk/src/client.rs b/matrix_sdk/src/client.rs index fff469c8..d0bd4445 100644 --- a/matrix_sdk/src/client.rs +++ b/matrix_sdk/src/client.rs @@ -2394,7 +2394,7 @@ mod test { api::r0::{ account::register::Request as RegistrationRequest, directory::get_public_rooms_filtered::Request as PublicRoomsFilterRequest, - membership::Invite3pid, session::get_login_types::LoginType, uiaa::AuthData, + membership::Invite3pidInit, session::get_login_types::LoginType, uiaa::AuthData, }, assign, directory::Filter, @@ -2792,12 +2792,15 @@ mod test { let room = client.get_joined_room(&room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); - room.invite_user_by_3pid(Invite3pid { - id_server: "example.org", - id_access_token: "IdToken", - medium: thirdparty::Medium::Email, - address: "address", - }) + room.invite_user_by_3pid( + Invite3pidInit { + id_server: "example.org", + id_access_token: "IdToken", + medium: thirdparty::Medium::Email, + address: "address", + } + .into(), + ) .await .unwrap(); } @@ -3053,13 +3056,9 @@ mod test { let room = client.get_joined_room(&room_id).unwrap(); let avatar_url = mxc_uri!("mxc://example.org/avA7ar"); - let member_event = MemberEventContent { - avatar_url: Some(avatar_url), - membership: MembershipState::Join, - is_direct: None, - displayname: None, - third_party_invite: None, - }; + let member_event = assign!(MemberEventContent::new(MembershipState::Join), { + avatar_url: Some(avatar_url) + }); let content = AnyStateEventContent::RoomMember(member_event); let response = room.send_state_event(content, "").await.unwrap(); assert_eq!(event_id!("$h29iv0s8:example.com"), response.event_id); diff --git a/matrix_sdk/src/room/joined.rs b/matrix_sdk/src/room/joined.rs index f28778e4..db10e91c 100644 --- a/matrix_sdk/src/room/joined.rs +++ b/matrix_sdk/src/room/joined.rs @@ -4,8 +4,6 @@ use std::{io::Read, ops::Deref}; #[cfg(feature = "encryption")] use matrix_sdk_base::crypto::AttachmentEncryptor; -#[cfg(feature = "encryption")] -use matrix_sdk_common::locks::Mutex; use matrix_sdk_common::{ api::r0::{ membership::{ @@ -36,6 +34,8 @@ use matrix_sdk_common::{ receipt::ReceiptType, uuid::Uuid, }; +#[cfg(feature = "encryption")] +use matrix_sdk_common::{events::room::EncryptedFileInit, locks::Mutex}; use mime::{self, Mime}; #[cfg(feature = "encryption")] use tracing::instrument; @@ -462,15 +462,18 @@ impl Joined { let response = self.client.upload(&content_type, &mut reader).await?; #[cfg(feature = "encryption")] - let keys = { + let keys: Option> = { let keys = reader.finish(); - Some(Box::new(EncryptedFile { - url: response.content_uri.clone(), - key: keys.web_key, - iv: keys.iv, - hashes: keys.hashes, - v: keys.version, - })) + Some(Box::new( + EncryptedFileInit { + url: response.content_uri.clone(), + key: keys.web_key, + iv: keys.iv, + hashes: keys.hashes, + v: keys.version, + } + .into(), + )) }; #[cfg(not(feature = "encryption"))] let keys: Option> = None; @@ -486,32 +489,23 @@ impl Joined { let content = match content_type.type_() { mime::IMAGE => { // TODO create a thumbnail using the image crate?. - MessageType::Image(ImageMessageEventContent { - body: body.to_owned(), - info: None, - url: Some(url), - file: encrypted_file, - }) + MessageType::Image(assign!( + ImageMessageEventContent::plain(body.to_owned(), url, None), + { file: encrypted_file } + )) } - mime::AUDIO => MessageType::Audio(AudioMessageEventContent { - body: body.to_owned(), - info: None, - url: Some(url), - file: encrypted_file, - }), - mime::VIDEO => MessageType::Video(VideoMessageEventContent { - body: body.to_owned(), - info: None, - url: Some(url), - file: encrypted_file, - }), - _ => MessageType::File(FileMessageEventContent { - filename: None, - body: body.to_owned(), - info: None, - url: Some(url), - file: encrypted_file, - }), + mime::AUDIO => MessageType::Audio(assign!( + AudioMessageEventContent::plain(body.to_owned(), url, None), + { file: encrypted_file } + )), + mime::VIDEO => MessageType::Video(assign!( + VideoMessageEventContent::plain(body.to_owned(), url, None), + { file: encrypted_file } + )), + _ => MessageType::File(assign!( + FileMessageEventContent::plain(body.to_owned(), url, None), + { file: encrypted_file } + )), }; self.send(AnyMessageEventContent::RoomMessage(MessageEventContent::new(content)), txn_id) @@ -540,6 +534,7 @@ impl Joined { /// room::member::{MemberEventContent, MembershipState}, /// }, /// identifiers::mxc_uri, + /// assign, /// }; /// # futures::executor::block_on(async { /// # let homeserver = url::Url::parse("http://localhost:8080").unwrap(); @@ -547,13 +542,9 @@ impl Joined { /// # let room_id = matrix_sdk::identifiers::room_id!("!test:localhost"); /// /// let avatar_url = mxc_uri!("mxc://example.org/avatar"); - /// let member_event = MemberEventContent { + /// let member_event = assign!(MemberEventContent::new(MembershipState::Join), { /// avatar_url: Some(avatar_url), - /// membership: MembershipState::Join, - /// is_direct: None, - /// displayname: None, - /// third_party_invite: None, - /// }; + /// }); /// # let room = client /// # .get_joined_room(&room_id) /// # .unwrap(); diff --git a/matrix_sdk_base/src/store/sled_store/mod.rs b/matrix_sdk_base/src/store/sled_store/mod.rs index 973360cc..1991c610 100644 --- a/matrix_sdk_base/src/store/sled_store/mod.rs +++ b/matrix_sdk_base/src/store/sled_store/mod.rs @@ -721,17 +721,9 @@ mod test { } fn membership_event() -> MemberEvent { - let content = MemberEventContent { - avatar_url: None, - displayname: None, - is_direct: None, - third_party_invite: None, - membership: MembershipState::Join, - }; - MemberEvent { event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(), - content, + content: MemberEventContent::new(MembershipState::Join), sender: user_id(), origin_server_ts: MilliSecondsSinceUnixEpoch::now(), state_key: user_id(), diff --git a/matrix_sdk_common/Cargo.toml b/matrix_sdk_common/Cargo.toml index f2169f20..901d2724 100644 --- a/matrix_sdk_common/Cargo.toml +++ b/matrix_sdk_common/Cargo.toml @@ -20,9 +20,7 @@ serde = "1.0.122" async-trait = "0.1.42" [dependencies.ruma] -version = "0.0.3" -git = "https://github.com/ruma/ruma" -rev = "e1ab817e0bef78cb8241d6d3c1ced7d6b414c7f6" +version = "0.1.0" features = ["client-api-c", "compat", "unstable-pre-spec"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/matrix_sdk_crypto/src/file_encryption/attachments.rs b/matrix_sdk_crypto/src/file_encryption/attachments.rs index 8b83aa08..81c3cf23 100644 --- a/matrix_sdk_crypto/src/file_encryption/attachments.rs +++ b/matrix_sdk_crypto/src/file_encryption/attachments.rs @@ -23,7 +23,7 @@ use aes_ctr::{ }; use base64::DecodeError; use getrandom::getrandom; -use matrix_sdk_common::events::room::JsonWebKey; +use matrix_sdk_common::events::room::{JsonWebKey, JsonWebKeyInit}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use thiserror::Error; @@ -201,13 +201,13 @@ impl<'a, R: Read + 'a> AttachmentEncryptor<'a, R> { // initialized. getrandom(&mut iv[0..8]).expect("Can't generate randomness"); - let web_key = JsonWebKey { + let web_key = JsonWebKey::from(JsonWebKeyInit { kty: "oct".to_owned(), key_ops: vec!["encrypt".to_owned(), "decrypt".to_owned()], alg: "A256CTR".to_owned(), k: encode_url_safe(&*key), ext: true, - }; + }); let encoded_iv = encode(&*iv); let aes = Aes256Ctr::new_var(&*key, &*iv).expect("Cannot create AES encryption object."); diff --git a/matrix_sdk_crypto/src/key_request.rs b/matrix_sdk_crypto/src/key_request.rs index 67a3a494..f1dbb43a 100644 --- a/matrix_sdk_crypto/src/key_request.rs +++ b/matrix_sdk_crypto/src/key_request.rs @@ -151,12 +151,12 @@ pub struct OutgoingKeyRequest { impl OutgoingKeyRequest { fn to_request(&self, own_device_id: &DeviceId) -> Result { - let content = RoomKeyRequestToDeviceEventContent { - action: Action::Request, - request_id: self.request_id.to_string(), - requesting_device_id: own_device_id.to_owned(), - body: Some(self.info.clone()), - }; + let content = RoomKeyRequestToDeviceEventContent::new( + Action::Request, + Some(self.info.clone()), + own_device_id.to_owned(), + self.request_id.to_string(), + ); wrap_key_request_content(self.request_recipient.clone(), self.request_id, &content) } @@ -165,12 +165,12 @@ impl OutgoingKeyRequest { &self, own_device_id: &DeviceId, ) -> Result { - let content = RoomKeyRequestToDeviceEventContent { - action: Action::CancelRequest, - request_id: self.request_id.to_string(), - requesting_device_id: own_device_id.to_owned(), - body: None, - }; + let content = RoomKeyRequestToDeviceEventContent::new( + Action::CancelRequest, + None, + own_device_id.to_owned(), + self.request_id.to_string(), + ); let id = Uuid::new_v4(); wrap_key_request_content(self.request_recipient.clone(), id, &content) @@ -584,12 +584,12 @@ impl KeyRequestMachine { sender_key: &str, session_id: &str, ) -> Result<(Option, OutgoingRequest), CryptoStoreError> { - let key_info = RequestedKeyInfo { - algorithm: EventEncryptionAlgorithm::MegolmV1AesSha2, - room_id: room_id.to_owned(), - sender_key: sender_key.to_owned(), - session_id: session_id.to_owned(), - }; + let key_info = RequestedKeyInfo::new( + EventEncryptionAlgorithm::MegolmV1AesSha2, + room_id.to_owned(), + sender_key.to_owned(), + session_id.to_owned(), + ); let request = self.store.get_key_request_by_info(&key_info).await?; @@ -644,12 +644,12 @@ impl KeyRequestMachine { sender_key: &str, session_id: &str, ) -> Result<(), CryptoStoreError> { - let key_info = RequestedKeyInfo { - algorithm: EventEncryptionAlgorithm::MegolmV1AesSha2, - room_id: room_id.to_owned(), - sender_key: sender_key.to_owned(), - session_id: session_id.to_owned(), - }; + let key_info = RequestedKeyInfo::new( + EventEncryptionAlgorithm::MegolmV1AesSha2, + room_id.to_owned(), + sender_key.to_owned(), + session_id.to_owned(), + ); if self.should_request_key(&key_info).await? { self.request_key_helper(key_info).await?; @@ -675,12 +675,12 @@ impl KeyRequestMachine { &self, content: &ForwardedRoomKeyToDeviceEventContent, ) -> Result, CryptoStoreError> { - let info = RequestedKeyInfo { - algorithm: content.algorithm.clone(), - room_id: content.room_id.clone(), - sender_key: content.sender_key.clone(), - session_id: content.session_id.clone(), - }; + let info = RequestedKeyInfo::new( + content.algorithm.clone(), + content.room_id.clone(), + content.sender_key.clone(), + content.session_id.clone(), + ); self.store.get_key_request_by_info(&info).await } diff --git a/matrix_sdk_crypto/src/store/sled.rs b/matrix_sdk_crypto/src/store/sled.rs index 3bca87ab..2a40b083 100644 --- a/matrix_sdk_crypto/src/store/sled.rs +++ b/matrix_sdk_crypto/src/store/sled.rs @@ -1205,12 +1205,12 @@ mod test { let (account, store, _dir) = get_loaded_store().await; let id = Uuid::new_v4(); - let info = RequestedKeyInfo { - algorithm: EventEncryptionAlgorithm::MegolmV1AesSha2, - room_id: room_id!("!test:localhost"), - sender_key: "test_sender_key".to_string(), - session_id: "test_session_id".to_string(), - }; + let info = RequestedKeyInfo::new( + EventEncryptionAlgorithm::MegolmV1AesSha2, + room_id!("!test:localhost"), + "test_sender_key".to_string(), + "test_session_id".to_string(), + ); let request = OutgoingKeyRequest { request_recipient: account.user_id().to_owned(), diff --git a/matrix_sdk_crypto/src/verification/requests.rs b/matrix_sdk_crypto/src/verification/requests.rs index 097279d8..e74925d6 100644 --- a/matrix_sdk_crypto/src/verification/requests.rs +++ b/matrix_sdk_crypto/src/verification/requests.rs @@ -265,17 +265,17 @@ impl RequestState { } fn as_content(&self) -> KeyVerificationRequestEventContent { - KeyVerificationRequestEventContent { - body: format!( + KeyVerificationRequestEventContent::new( + format!( "{} is requesting to verify your key, but your client does not \ support in-chat key verification. You will need to use legacy \ key verification to verify keys.", self.own_user_id ), - methods: SUPPORTED_METHODS.to_vec(), - from_device: self.own_device_id.clone(), - to: self.other_user_id.clone(), - } + SUPPORTED_METHODS.to_vec(), + self.own_device_id.clone(), + self.other_user_id.clone(), + ) } fn into_sent(self, response: &RoomMessageResponse) -> RequestState { @@ -360,11 +360,11 @@ impl RequestState { }, }; - let content = ReadyEventContent { - from_device: self.own_device_id, - methods: self.state.methods, - relation: Relation { event_id: self.state.flow_id }, - }; + let content = ReadyEventContent::new( + self.own_device_id, + self.state.methods, + Relation::new(self.state.flow_id), + ); (state, content) } diff --git a/matrix_sdk_crypto/src/verification/sas/helpers.rs b/matrix_sdk_crypto/src/verification/sas/helpers.rs index 312231af..1a682fe8 100644 --- a/matrix_sdk_crypto/src/verification/sas/helpers.rs +++ b/matrix_sdk_crypto/src/verification/sas/helpers.rs @@ -315,12 +315,9 @@ pub fn get_mac_content(sas: &OlmSas, ids: &SasIds, flow_id: &FlowId) -> MacConte .expect("Can't calculate SAS MAC"); match flow_id { - FlowId::ToDevice(s) => { - MacToDeviceEventContent { transaction_id: s.to_string(), keys, mac }.into() - } + FlowId::ToDevice(s) => MacToDeviceEventContent::new(s.to_string(), mac, keys).into(), FlowId::InRoom(r, e) => { - (r.clone(), MacEventContent { mac, keys, relation: Relation { event_id: e.clone() } }) - .into() + (r.clone(), MacEventContent::new(mac, keys, Relation::new(e.clone()))).into() } } } diff --git a/matrix_sdk_crypto/src/verification/sas/sas_state.rs b/matrix_sdk_crypto/src/verification/sas/sas_state.rs index 1fbd5e38..bd789bef 100644 --- a/matrix_sdk_crypto/src/verification/sas/sas_state.rs +++ b/matrix_sdk_crypto/src/verification/sas/sas_state.rs @@ -23,13 +23,13 @@ use matrix_sdk_common::{ events::key::verification::{ accept::{ AcceptEventContent, AcceptMethod, AcceptToDeviceEventContent, - MSasV1Content as AcceptV1Content, MSasV1ContentInit as AcceptV1ContentInit, + SasV1Content as AcceptV1Content, SasV1ContentInit as AcceptV1ContentInit, }, cancel::{CancelCode, CancelEventContent, CancelToDeviceEventContent}, done::DoneEventContent, key::{KeyEventContent, KeyToDeviceEventContent}, start::{ - MSasV1Content, MSasV1ContentInit, StartEventContent, StartMethod, + SasV1Content, SasV1ContentInit, StartEventContent, StartMethod, StartToDeviceEventContent, }, HashAlgorithm, KeyAgreementProtocol, MessageAuthenticationCode, Relation, @@ -187,14 +187,14 @@ impl std::fmt::Debug for SasState { /// The initial SAS state. #[derive(Clone, Debug)] pub struct Created { - protocol_definitions: MSasV1ContentInit, + protocol_definitions: SasV1ContentInit, } /// The initial SAS state if the other side started the SAS verification. #[derive(Clone, Debug)] pub struct Started { commitment: String, - protocol_definitions: MSasV1Content, + protocol_definitions: SasV1Content, } /// The SAS state we're going to be in after the other side accepted our @@ -375,7 +375,7 @@ impl SasState { last_event_time: Arc::new(Instant::now()), state: Arc::new(Created { - protocol_definitions: MSasV1ContentInit { + protocol_definitions: SasV1ContentInit { short_authentication_string: STRINGS.to_vec(), key_agreement_protocols: KEY_AGREEMENT_PROTOCOLS.to_vec(), message_authentication_codes: MACS.to_vec(), @@ -387,24 +387,24 @@ impl SasState { pub fn as_content(&self) -> StartContent { match self.verification_flow_id.as_ref() { - FlowId::ToDevice(s) => StartContent::ToDevice(StartToDeviceEventContent { - transaction_id: s.to_string(), - from_device: self.device_id().into(), - method: StartMethod::MSasV1( - MSasV1Content::new(self.state.protocol_definitions.clone()) + FlowId::ToDevice(s) => StartContent::ToDevice(StartToDeviceEventContent::new( + self.device_id().into(), + s.to_string(), + StartMethod::SasV1( + SasV1Content::new(self.state.protocol_definitions.clone()) .expect("Invalid initial protocol definitions."), ), - }), + )), FlowId::InRoom(r, e) => StartContent::Room( r.clone(), - StartEventContent { - from_device: self.device_id().into(), - method: StartMethod::MSasV1( - MSasV1Content::new(self.state.protocol_definitions.clone()) + StartEventContent::new( + self.device_id().into(), + StartMethod::SasV1( + SasV1Content::new(self.state.protocol_definitions.clone()) .expect("Invalid initial protocol definitions."), ), - relation: Relation { event_id: e.clone() }, - }, + Relation::new(e.clone()), + ), ), } } @@ -478,7 +478,7 @@ impl SasState { other_identity: Option, content: &StartContent, ) -> Result, SasState> { - if let StartMethod::MSasV1(method_content) = content.method() { + if let StartMethod::SasV1(method_content) = content.method() { let sas = OlmSas::new(); let pubkey = sas.public_key(); @@ -564,14 +564,10 @@ impl SasState { ); match self.verification_flow_id.as_ref() { - FlowId::ToDevice(s) => { - AcceptToDeviceEventContent { transaction_id: s.to_string(), method }.into() + FlowId::ToDevice(s) => AcceptToDeviceEventContent::new(s.to_string(), method).into(), + FlowId::InRoom(r, e) => { + (r.clone(), AcceptEventContent::new(method, Relation::new(e.clone()))).into() } - FlowId::InRoom(r, e) => ( - r.clone(), - AcceptEventContent { method, relation: Relation { event_id: e.clone() } }, - ) - .into(), } } @@ -678,10 +674,10 @@ impl SasState { .into(), FlowId::InRoom(r, e) => ( r.clone(), - KeyEventContent { - key: self.inner.lock().unwrap().public_key(), - relation: Relation { event_id: e.clone() }, - }, + KeyEventContent::new( + self.inner.lock().unwrap().public_key(), + Relation::new(e.clone()), + ), ) .into(), } @@ -702,10 +698,10 @@ impl SasState { .into(), FlowId::InRoom(r, e) => ( r.clone(), - KeyEventContent { - key: self.inner.lock().unwrap().public_key(), - relation: Relation { event_id: e.clone() }, - }, + KeyEventContent::new( + self.inner.lock().unwrap().public_key(), + Relation::new(e.clone()), + ), ) .into(), } @@ -1000,7 +996,7 @@ impl SasState { unreachable!("The done content isn't supported yet for to-device verifications") } FlowId::InRoom(r, e) => { - (r.clone(), DoneEventContent { relation: Relation { event_id: e.clone() } }).into() + (r.clone(), DoneEventContent::new(Relation::new(e.clone()))).into() } } } @@ -1052,7 +1048,7 @@ impl SasState { unreachable!("The done content isn't supported yet for to-device verifications") } FlowId::InRoom(r, e) => { - (r.clone(), DoneEventContent { relation: Relation { event_id: e.clone() } }).into() + (r.clone(), DoneEventContent::new(Relation::new(e.clone()))).into() } } } @@ -1096,20 +1092,20 @@ impl Canceled { impl SasState { pub fn as_content(&self) -> CancelContent { match self.verification_flow_id.as_ref() { - FlowId::ToDevice(s) => CancelToDeviceEventContent { - transaction_id: s.clone(), - reason: self.state.reason.to_string(), - code: self.state.cancel_code.clone(), - } + FlowId::ToDevice(s) => CancelToDeviceEventContent::new( + s.clone(), + self.state.reason.to_string(), + self.state.cancel_code.clone(), + ) .into(), FlowId::InRoom(r, e) => ( r.clone(), - CancelEventContent { - reason: self.state.reason.to_string(), - code: self.state.cancel_code.clone(), - relation: Relation { event_id: e.clone() }, - }, + CancelEventContent::new( + self.state.reason.to_string(), + self.state.cancel_code.clone(), + Relation::new(e.clone()), + ), ) .into(), } @@ -1336,7 +1332,7 @@ mod test { }; match method { - StartMethod::MSasV1(ref mut c) => { + StartMethod::SasV1(ref mut c) => { c.message_authentication_codes = vec![]; } _ => panic!("Unknown SAS start method"), From bb69901d947c11dd772e0ac4f40fd54cb56f8cf4 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Mon, 17 May 2021 22:28:30 +0000 Subject: [PATCH 6/7] Return joined members in a room from the correct Sled tree. --- matrix_sdk/src/room/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix_sdk/src/room/common.rs b/matrix_sdk/src/room/common.rs index 80526bf2..82647506 100644 --- a/matrix_sdk/src/room/common.rs +++ b/matrix_sdk/src/room/common.rs @@ -245,7 +245,7 @@ impl Common { pub async fn joined_members_no_sync(&self) -> Result> { Ok(self .inner - .members() + .joined_members() .await? .into_iter() .map(|member| RoomMember::new(self.client.clone(), member)) From c122549e0d587f1297f81ad5f432deda7d139913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Tue, 18 May 2021 08:29:10 +0200 Subject: [PATCH 7/7] base: Correctly get the user ids of all room members --- matrix_sdk_base/src/store/sled_store/mod.rs | 41 ++++++++++++++------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/matrix_sdk_base/src/store/sled_store/mod.rs b/matrix_sdk_base/src/store/sled_store/mod.rs index 1991c610..c60534bc 100644 --- a/matrix_sdk_base/src/store/sled_store/mod.rs +++ b/matrix_sdk_base/src/store/sled_store/mod.rs @@ -83,8 +83,9 @@ impl From for StoreError { } } +const ENCODE_SEPARATOR: u8 = 0xff; + trait EncodeKey { - const SEPARATOR: u8 = 0xff; fn encode(&self) -> Vec; } @@ -102,13 +103,13 @@ impl EncodeKey for &RoomId { impl EncodeKey for &str { fn encode(&self) -> Vec { - [self.as_bytes(), &[Self::SEPARATOR]].concat() + [self.as_bytes(), &[ENCODE_SEPARATOR]].concat() } } impl EncodeKey for (&str, &str) { fn encode(&self) -> Vec { - [self.0.as_bytes(), &[Self::SEPARATOR], self.1.as_bytes(), &[Self::SEPARATOR]].concat() + [self.0.as_bytes(), &[ENCODE_SEPARATOR], self.1.as_bytes(), &[ENCODE_SEPARATOR]].concat() } } @@ -116,11 +117,11 @@ impl EncodeKey for (&str, &str, &str) { fn encode(&self) -> Vec { [ self.0.as_bytes(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], self.1.as_bytes(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], self.2.as_bytes(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], ] .concat() } @@ -506,11 +507,22 @@ impl SledStore { .transpose()?) } - pub async fn get_user_ids(&self, room_id: &RoomId) -> impl Stream> { - stream::iter(self.members.scan_prefix(room_id.encode()).map(|u| { - UserId::try_from(String::from_utf8_lossy(&u?.1).to_string()) - .map_err(StoreError::Identifier) - })) + pub async fn get_user_ids_stream( + &self, + room_id: &RoomId, + ) -> impl Stream> { + let decode = |key: &[u8]| -> Result { + let mut iter = key.split(|c| c == &ENCODE_SEPARATOR); + // Our key is a the room id separated from the user id by a null + // byte, discard the first value of the split. + iter.next(); + + let user_id = iter.next().expect("User ids weren't properly encoded"); + + Ok(UserId::try_from(String::from_utf8_lossy(user_id).to_string())?) + }; + + stream::iter(self.members.scan_prefix(room_id.encode()).map(move |u| decode(&u?.0))) } pub async fn get_invited_user_ids( @@ -636,7 +648,7 @@ impl StateStore for SledStore { } async fn get_user_ids(&self, room_id: &RoomId) -> Result> { - self.get_user_ids(room_id).await.try_collect().await + self.get_user_ids_stream(room_id).await.try_collect().await } async fn get_invited_user_ids(&self, room_id: &RoomId) -> Result> { @@ -698,7 +710,7 @@ mod test { use serde_json::json; use super::{SledStore, StateChanges}; - use crate::deserialized_responses::MemberEvent; + use crate::{deserialized_responses::MemberEvent, StateStore}; fn user_id() -> UserId { user_id!("@example:localhost") @@ -748,6 +760,9 @@ mod test { store.save_changes(&changes).await.unwrap(); assert!(store.get_member_event(&room_id, &user_id).await.unwrap().is_some()); + + let members = store.get_user_ids(&room_id).await.unwrap(); + assert!(!members.is_empty()) } #[async_test]