From f3620e707217c29a00e0d258ce3573fed35b0d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20H=C3=A4cker?= Date: Sun, 25 Jul 2021 20:51:46 +0200 Subject: [PATCH 1/2] room: Add event() method to retrieve a room event --- matrix_sdk/src/room/common.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/matrix_sdk/src/room/common.rs b/matrix_sdk/src/room/common.rs index 2b29f1bc..92ed5933 100644 --- a/matrix_sdk/src/room/common.rs +++ b/matrix_sdk/src/room/common.rs @@ -6,6 +6,7 @@ use ruma::{ api::client::r0::{ membership::{get_member_events, join_room_by_id, leave_room}, message::get_message_events, + room::get_room_event, }, events::room::history_visibility::HistoryVisibility, UserId, @@ -146,6 +147,17 @@ impl Common { self.client.send(request, None).await } + /// Sends a request to `/_matrix/client/r0/rooms/{roomId}/event/{eventId}` + /// and returns a `get_room_event::Response` that contains a event + /// (`AnyRoomEvent`). + pub async fn event( + &self, + request: impl Into>, + ) -> Result { + let request = request.into(); + self.client.send(request, None).await + } + pub(crate) async fn request_members(&self) -> Result> { #[allow(clippy::map_clone)] if let Some(mutex) = From 91e9a5f9f3a9e228b7c80ed78277cce7617ecde9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20H=C3=A4cker?= Date: Wed, 28 Jul 2021 19:49:41 +0200 Subject: [PATCH 2/2] Add new RoomEvent type, try to decrypt event --- matrix_sdk/src/client.rs | 38 +++++++++++++++++++ matrix_sdk/src/room/common.rs | 12 ++++-- .../src/deserialized_responses.rs | 8 ++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/matrix_sdk/src/client.rs b/matrix_sdk/src/client.rs index f2105751..f582cbc4 100644 --- a/matrix_sdk/src/client.rs +++ b/matrix_sdk/src/client.rs @@ -47,6 +47,8 @@ use matrix_sdk_base::crypto::{ store::CryptoStoreError, AttachmentDecryptor, OutgoingRequests, RoomMessageRequest, ToDeviceRequest, }; +#[cfg(feature = "encryption")] +use matrix_sdk_base::deserialized_responses::RoomEvent; use matrix_sdk_base::{ deserialized_responses::SyncResponse, media::{MediaEventContent, MediaFormat, MediaRequest, MediaThumbnailSize, MediaType}, @@ -56,6 +58,8 @@ use mime::{self, Mime}; #[cfg(feature = "sso_login")] use rand::{thread_rng, Rng}; use reqwest::header::InvalidHeaderValue; +#[cfg(feature = "encryption")] +use ruma::events::{AnyMessageEvent, AnyRoomEvent, AnySyncMessageEvent}; use ruma::{api::SendAccessToken, events::AnyMessageEventContent, MxcUri}; #[cfg(feature = "sso_login")] use tokio::{net::TcpListener, sync::oneshot}; @@ -946,6 +950,40 @@ impl Client { self.store().get_room(room_id).and_then(|room| room::Left::new(self.clone(), room)) } + /// Tries to decrypt a `AnyRoomEvent`. Returns unencrypted room event when + /// decryption fails. + #[cfg(feature = "encryption")] + #[cfg_attr(feature = "docs", doc(cfg(encryption)))] + pub(crate) async fn decrypt_room_event(&self, event: &AnyRoomEvent) -> RoomEvent { + if let Some(machine) = self.base_client.olm_machine().await { + if let AnyRoomEvent::Message(event) = event { + if let AnyMessageEvent::RoomEncrypted(_) = event { + let room_id = event.room_id(); + // Turn the AnyMessageEvent into a AnySyncMessageEvent + let event = event.clone().into(); + + if let AnySyncMessageEvent::RoomEncrypted(e) = event { + if let Ok(decrypted) = machine.decrypt_room_event(&e, &room_id).await { + let event = decrypted + .event + .deserialize() + .unwrap() + .into_full_event(room_id.clone()) + .into(); + let encryption_info = decrypted.encryption_info; + + // Return decrytped room event + return RoomEvent { event, encryption_info }; + } + } + } + } + } + + // Fallback to unencrypted room event + RoomEvent { event: event.into(), encryption_info: None } + } + /// Gets the homeserver’s supported login types. /// /// This should be the first step when trying to login so you can call the diff --git a/matrix_sdk/src/room/common.rs b/matrix_sdk/src/room/common.rs index 92ed5933..4082e5bc 100644 --- a/matrix_sdk/src/room/common.rs +++ b/matrix_sdk/src/room/common.rs @@ -1,6 +1,6 @@ use std::{ops::Deref, sync::Arc}; -use matrix_sdk_base::deserialized_responses::MembersResponse; +use matrix_sdk_base::deserialized_responses::{MembersResponse, RoomEvent}; use matrix_sdk_common::locks::Mutex; use ruma::{ api::client::r0::{ @@ -153,9 +153,15 @@ impl Common { pub async fn event( &self, request: impl Into>, - ) -> Result { + ) -> Result { let request = request.into(); - self.client.send(request, None).await + let event = self.client.send(request, None).await?.event.deserialize()?; + + #[cfg(feature = "encryption")] + return Ok(self.client.decrypt_room_event(&event).await); + + #[cfg(not(feature = "encryption"))] + return Ok(RoomEvent { event: event.into(), encryption_info: None }); } pub(crate) async fn request_members(&self) -> Result> { diff --git a/matrix_sdk_common/src/deserialized_responses.rs b/matrix_sdk_common/src/deserialized_responses.rs index 24b07dd8..e581af12 100644 --- a/matrix_sdk_common/src/deserialized_responses.rs +++ b/matrix_sdk_common/src/deserialized_responses.rs @@ -133,6 +133,14 @@ impl SyncResponse { } } +pub struct RoomEvent { + /// The actual event. + pub event: Raw, + /// The encryption info about the event. Will be `None` if the event was not + /// encrypted. + pub encryption_info: Option, +} + #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Rooms { /// The rooms that the user has left or been banned from.