From 2919c2d5d1dfc3a29a3374ef88a1f44b1501697e Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Tue, 26 Apr 2022 18:31:24 +0200 Subject: [PATCH 1/6] matrix-sdk: Expose method to decrypt room events The also adds an enum so that the user can give many different rust types to the decryption method. --- crates/matrix-sdk/src/encryption/mod.rs | 44 +----- crates/matrix-sdk/src/room/common.rs | 186 ++++++++++++++++++++++-- 2 files changed, 178 insertions(+), 52 deletions(-) diff --git a/crates/matrix-sdk/src/encryption/mod.rs b/crates/matrix-sdk/src/encryption/mod.rs index 6b50c2a49..16cbfddd6 100644 --- a/crates/matrix-sdk/src/encryption/mod.rs +++ b/crates/matrix-sdk/src/encryption/mod.rs @@ -26,19 +26,15 @@ use std::{ }; use futures_util::stream::{self, StreamExt}; -pub use matrix_sdk_base::crypto::{LocalTrust, MediaEncryptionInfo, RoomKeyImportResult}; -use matrix_sdk_base::{ - crypto::{ - store::CryptoStoreError, CrossSigningStatus, OutgoingRequest, RoomMessageRequest, - ToDeviceRequest, - }, - deserialized_responses::RoomEvent, +use matrix_sdk_base::crypto::{ + store::CryptoStoreError, CrossSigningStatus, OutgoingRequest, RoomMessageRequest, + ToDeviceRequest, }; +pub use matrix_sdk_base::crypto::{LocalTrust, MediaEncryptionInfo, RoomKeyImportResult}; use matrix_sdk_common::instant::Duration; #[cfg(feature = "e2e-encryption")] use ruma::{ - api::client::config::set_global_account_data, - events::{GlobalAccountDataEventContent, MessageLikeEvent}, + api::client::config::set_global_account_data, events::GlobalAccountDataEventContent, OwnedDeviceId, }; use ruma::{ @@ -54,8 +50,7 @@ use ruma::{ uiaa::AuthData, }, assign, - events::{AnyMessageLikeEvent, AnyRoomEvent, GlobalAccountDataEventType}, - serde::Raw, + events::GlobalAccountDataEventType, DeviceId, OwnedUserId, TransactionId, UserId, }; use tracing::{debug, instrument, trace, warn}; @@ -71,33 +66,6 @@ use crate::{ }; impl Client { - /// Tries to decrypt a `AnyRoomEvent`. Returns undecrypted room event when - /// decryption fails. - #[cfg(feature = "e2e-encryption")] - pub(crate) async fn decrypt_room_event(&self, event: Raw) -> RoomEvent { - if let Some(machine) = self.olm_machine().await { - if let Ok(AnyRoomEvent::MessageLike(event)) = event.deserialize() { - if let AnyMessageLikeEvent::RoomEncrypted(_) = event { - let room_id = event.room_id(); - - if let AnyMessageLikeEvent::RoomEncrypted(MessageLikeEvent::Original(ev)) = - &event - { - // Turn the OriginalMessageLikeEvent into a OriginalSyncMessageLikeEvent - let ev = ev.clone().into(); - if let Ok(decrypted) = machine.decrypt_room_event(&ev, room_id).await { - return decrypted; - } - } - } - } - } - - // Fallback to still-encrypted room event - - RoomEvent { event, encryption_info: None } - } - /// Query the server for users device keys. /// /// # Panics diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index b6ea52a4c..69ed97c6d 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -3,14 +3,18 @@ use std::{collections::BTreeMap, ops::Deref, sync::Arc}; #[cfg(feature = "experimental-timeline")] use futures_core::stream::Stream; use matrix_sdk_base::deserialized_responses::{MembersResponse, RoomEvent}; +#[cfg(feature = "e2e-encryption")] +use matrix_sdk_base::{crypto::OlmMachine, deserialized_responses::SyncRoomEvent}; #[cfg(feature = "experimental-timeline")] -use matrix_sdk_base::{ - deserialized_responses::{SyncRoomEvent, TimelineSlice}, - TimelineStreamError, -}; +use matrix_sdk_base::{deserialized_responses::TimelineSlice, TimelineStreamError}; use matrix_sdk_common::locks::Mutex; #[cfg(feature = "experimental-timeline")] use ruma::api::client::filter::LazyLoadOptions; +#[cfg(feature = "e2e-encryption")] +use ruma::events::{ + AnyMessageLikeEvent, AnyRoomEvent, AnySyncMessageLikeEvent, AnySyncRoomEvent, MessageLikeEvent, + SyncMessageLikeEvent, +}; use ruma::{ api::client::{ config::set_global_account_data, @@ -178,24 +182,44 @@ impl Common { /// # }); /// ``` pub async fn messages(&self, options: MessagesOptions<'_>) -> Result { - let request = options.into_request(self.inner.room_id()); + let room_id = self.inner.room_id(); + let request = options.into_request(room_id); let http_response = self.client.send(request, None).await?; + #[allow(unused_mut)] let mut response = Messages { start: http_response.start, end: http_response.end, + #[cfg(not(feature = "e2e-encryption"))] + chunk: http_response + .chunk + .into_iter() + .map(|event| RoomEvent { event, encryption_info: None }) + .collect(), + #[cfg(feature = "e2e-encryption")] chunk: Vec::with_capacity(http_response.chunk.len()), state: http_response.state, }; - for event in http_response.chunk { - #[cfg(feature = "e2e-encryption")] - let event = self.client.decrypt_room_event(event).await; + #[cfg(feature = "e2e-encryption")] + if let Some(ref machine) = self.client.olm_machine().await { + for event in http_response.chunk { + let event = + if let Some(event) = EventEnum::from(&event).decrypt(room_id, machine).await { + event + } else { + RoomEvent { event, encryption_info: None } + }; - #[cfg(not(feature = "e2e-encryption"))] - let event = RoomEvent { event, encryption_info: None }; - - response.chunk.push(event); + response.chunk.push(event); + } + } else { + response.chunk.extend( + http_response + .chunk + .into_iter() + .map(|event| RoomEvent { event, encryption_info: None }), + ); } Ok(response) @@ -450,10 +474,16 @@ impl Common { let event = self.client.send(request, None).await?.event; #[cfg(feature = "e2e-encryption")] - return Ok(self.client.decrypt_room_event(event).await); + let decrypted = if let Some(event) = self.decrypt_event(&event).await { + Ok(event) + } else { + Ok(RoomEvent { event, encryption_info: None }) + }; #[cfg(not(feature = "e2e-encryption"))] - return Ok(RoomEvent { event, encryption_info: None }); + let decrypted = Ok(RoomEvent { event, encryption_info: None }); + + decrypted } pub(crate) async fn request_members(&self) -> Result> { @@ -876,6 +906,19 @@ impl Common { self.client.send(request, None).await?; Ok(()) } + + /// Tries to decrypt a room event. + /// + /// # Arguments + /// * `event` - The room event to be decrypted. + #[cfg(feature = "e2e-encryption")] + pub async fn decrypt_event(&self, event: impl Into>) -> Option { + if let Some(machine) = self.client.olm_machine().await { + event.into().decrypt(self.inner.room_id(), &machine).await + } else { + None + } + } } /// Options for [`messages`][Common::messages]. @@ -938,3 +981,118 @@ impl<'a> MessagesOptions<'a> { }) } } + +/// An enum to abstract over different rust types for events that can be given +/// to [`decrypt_event`][Common::decrypt_event]. +#[cfg(feature = "e2e-encryption")] +#[derive(Debug)] +pub enum EventEnum<'a> { + Event(&'a RoomEvent), + RawEvent(&'a Raw), + DeserializedEvent(&'a AnyRoomEvent), + SyncEvent(&'a SyncRoomEvent), + RawSyncEvent(&'a Raw), + DeserializedSyncEvent(&'a AnySyncRoomEvent), +} + +#[cfg(feature = "e2e-encryption")] +impl<'a> From<&'a RoomEvent> for EventEnum<'a> { + fn from(event: &'a RoomEvent) -> Self { + Self::Event(event) + } +} + +#[cfg(feature = "e2e-encryption")] +impl<'a> From<&'a Raw> for EventEnum<'a> { + fn from(event: &'a Raw) -> Self { + Self::RawEvent(event) + } +} + +#[cfg(feature = "e2e-encryption")] +impl<'a> From<&'a AnyRoomEvent> for EventEnum<'a> { + fn from(event: &'a AnyRoomEvent) -> Self { + Self::DeserializedEvent(event) + } +} + +#[cfg(feature = "e2e-encryption")] +impl<'a> From<&'a SyncRoomEvent> for EventEnum<'a> { + fn from(event: &'a SyncRoomEvent) -> Self { + Self::SyncEvent(event) + } +} + +#[cfg(feature = "e2e-encryption")] +impl<'a> From<&'a Raw> for EventEnum<'a> { + fn from(event: &'a Raw) -> Self { + Self::RawSyncEvent(event) + } +} + +#[cfg(feature = "e2e-encryption")] +impl<'a> From<&'a AnySyncRoomEvent> for EventEnum<'a> { + fn from(event: &'a AnySyncRoomEvent) -> Self { + Self::DeserializedSyncEvent(event) + } +} + +#[cfg(feature = "e2e-encryption")] +impl<'a> EventEnum<'a> { + async fn decrypt(&self, room_id: &RoomId, olm_machine: &OlmMachine) -> Option { + match self { + EventEnum::Event(event) => { + if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + ))) = event.event.deserialize_as::() + { + return olm_machine.decrypt_room_event(&event, room_id).await.ok(); + } + } + EventEnum::RawEvent(event) => { + if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + ))) = event.deserialize_as::() + { + return olm_machine.decrypt_room_event(&event, room_id).await.ok(); + } + } + EventEnum::DeserializedEvent(event) => { + if let AnyRoomEvent::MessageLike(AnyMessageLikeEvent::RoomEncrypted( + MessageLikeEvent::Original(event), + )) = event + { + return olm_machine + .decrypt_room_event(&event.clone().into(), room_id) + .await + .ok(); + } + } + EventEnum::SyncEvent(event) => { + if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + ))) = event.event.deserialize() + { + return olm_machine.decrypt_room_event(&event, room_id).await.ok(); + } + } + EventEnum::RawSyncEvent(event) => { + if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + ))) = event.deserialize() + { + return olm_machine.decrypt_room_event(&event, room_id).await.ok(); + } + } + EventEnum::DeserializedSyncEvent(event) => { + if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + )) = event + { + return olm_machine.decrypt_room_event(event, room_id).await.ok(); + } + } + } + None + } +} From 3910122fd56ef341110f47e8cbe8a673d63f8724 Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Mon, 9 May 2022 13:51:03 +0200 Subject: [PATCH 2/6] Remove uneeded ref Co-authored-by: Jonas Platte --- crates/matrix-sdk/src/room/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index 69ed97c6d..513d24916 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -202,7 +202,7 @@ impl Common { }; #[cfg(feature = "e2e-encryption")] - if let Some(ref machine) = self.client.olm_machine().await { + if let Some(machine) = self.client.olm_machine().await { for event in http_response.chunk { let event = if let Some(event) = EventEnum::from(&event).decrypt(room_id, machine).await { From fa37a2dea2ecf4f9ab12142e630f762dce4f45a5 Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Mon, 9 May 2022 13:58:04 +0200 Subject: [PATCH 3/6] Fix missing referance --- crates/matrix-sdk/src/room/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index 513d24916..8c00a90b0 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -205,7 +205,7 @@ impl Common { if let Some(machine) = self.client.olm_machine().await { for event in http_response.chunk { let event = - if let Some(event) = EventEnum::from(&event).decrypt(room_id, machine).await { + if let Some(event) = EventEnum::from(&event).decrypt(room_id, &machine).await { event } else { RoomEvent { event, encryption_info: None } From b586f1690b095e6f836d9b528e7fc5c59f6ef97c Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Tue, 10 May 2022 14:54:13 +0200 Subject: [PATCH 4/6] use trait as argument for room::Common::decrypt_event --- crates/matrix-sdk/src/error.rs | 5 + crates/matrix-sdk/src/room/common.rs | 248 ++++++++++++++------------- 2 files changed, 130 insertions(+), 123 deletions(-) diff --git a/crates/matrix-sdk/src/error.rs b/crates/matrix-sdk/src/error.rs index 5c533aea8..5e1b678b9 100644 --- a/crates/matrix-sdk/src/error.rs +++ b/crates/matrix-sdk/src/error.rs @@ -122,6 +122,11 @@ pub enum Error { #[error("The olm machine has already been initialized")] BadCryptoStoreState, + /// Attempting to access the olm-machine but it is not yet available. + #[cfg(feature = "e2e-encryption")] + #[error("The olm machine isn't yet available")] + NoOlmMachine, + /// An error de/serializing type for the `StateStore` #[error(transparent)] SerdeJson(#[from] JsonError), diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index 8c00a90b0..dd35960be 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -2,9 +2,9 @@ use std::{collections::BTreeMap, ops::Deref, sync::Arc}; #[cfg(feature = "experimental-timeline")] use futures_core::stream::Stream; -use matrix_sdk_base::deserialized_responses::{MembersResponse, RoomEvent}; #[cfg(feature = "e2e-encryption")] -use matrix_sdk_base::{crypto::OlmMachine, deserialized_responses::SyncRoomEvent}; +use matrix_sdk_base::deserialized_responses::SyncRoomEvent; +use matrix_sdk_base::deserialized_responses::{MembersResponse, RoomEvent}; #[cfg(feature = "experimental-timeline")] use matrix_sdk_base::{deserialized_responses::TimelineSlice, TimelineStreamError}; use matrix_sdk_common::locks::Mutex; @@ -12,8 +12,8 @@ use matrix_sdk_common::locks::Mutex; use ruma::api::client::filter::LazyLoadOptions; #[cfg(feature = "e2e-encryption")] use ruma::events::{ - AnyMessageLikeEvent, AnyRoomEvent, AnySyncMessageLikeEvent, AnySyncRoomEvent, MessageLikeEvent, - SyncMessageLikeEvent, + room::encrypted::OriginalSyncRoomEncryptedEvent, AnyMessageLikeEvent, AnyRoomEvent, + AnySyncMessageLikeEvent, AnySyncRoomEvent, MessageLikeEvent, SyncMessageLikeEvent, }; use ruma::{ api::client::{ @@ -204,14 +204,13 @@ impl Common { #[cfg(feature = "e2e-encryption")] if let Some(machine) = self.client.olm_machine().await { for event in http_response.chunk { - let event = - if let Some(event) = EventEnum::from(&event).decrypt(room_id, &machine).await { - event - } else { - RoomEvent { event, encryption_info: None } - }; + let decrypted_event = if let Some(encrypted_event) = event.to_encrypted_event()? { + machine.decrypt_room_event(&encrypted_event, room_id).await? + } else { + RoomEvent { event, encryption_info: None } + }; - response.chunk.push(event); + response.chunk.push(decrypted_event); } } else { response.chunk.extend( @@ -474,7 +473,7 @@ impl Common { let event = self.client.send(request, None).await?.event; #[cfg(feature = "e2e-encryption")] - let decrypted = if let Some(event) = self.decrypt_event(&event).await { + let decrypted = if let Some(event) = self.decrypt_event(&event).await? { Ok(event) } else { Ok(RoomEvent { event, encryption_info: None }) @@ -911,12 +910,23 @@ impl Common { /// /// # Arguments /// * `event` - The room event to be decrypted. + /// + /// Returns: #[cfg(feature = "e2e-encryption")] - pub async fn decrypt_event(&self, event: impl Into>) -> Option { - if let Some(machine) = self.client.olm_machine().await { - event.into().decrypt(self.inner.room_id(), &machine).await + pub async fn decrypt_event(&self, event: &E) -> Result> + where + E: ToEncryptedEvent, + { + let encrypted_event = if let Some(event) = event.to_encrypted_event()? { + event } else { - None + return Ok(None); + }; + + if let Some(machine) = self.client.olm_machine().await { + Ok(Some(machine.decrypt_room_event(&encrypted_event, self.inner.room_id()).await?)) + } else { + Err(Error::NoOlmMachine) } } } @@ -982,117 +992,109 @@ impl<'a> MessagesOptions<'a> { } } -/// An enum to abstract over different rust types for events that can be given -/// to [`decrypt_event`][Common::decrypt_event]. +/// A trait that is implemented for different rust event types so that +/// [`decrypt_event`][`crate::room::Common::decrpyt_event`] can take any of them +/// as input. #[cfg(feature = "e2e-encryption")] -#[derive(Debug)] -pub enum EventEnum<'a> { - Event(&'a RoomEvent), - RawEvent(&'a Raw), - DeserializedEvent(&'a AnyRoomEvent), - SyncEvent(&'a SyncRoomEvent), - RawSyncEvent(&'a Raw), - DeserializedSyncEvent(&'a AnySyncRoomEvent), +pub trait ToEncryptedEvent { + #[doc(hidden)] + fn to_encrypted_event( + &self, + ) -> Result, serde_json::Error>; } #[cfg(feature = "e2e-encryption")] -impl<'a> From<&'a RoomEvent> for EventEnum<'a> { - fn from(event: &'a RoomEvent) -> Self { - Self::Event(event) - } -} - -#[cfg(feature = "e2e-encryption")] -impl<'a> From<&'a Raw> for EventEnum<'a> { - fn from(event: &'a Raw) -> Self { - Self::RawEvent(event) - } -} - -#[cfg(feature = "e2e-encryption")] -impl<'a> From<&'a AnyRoomEvent> for EventEnum<'a> { - fn from(event: &'a AnyRoomEvent) -> Self { - Self::DeserializedEvent(event) - } -} - -#[cfg(feature = "e2e-encryption")] -impl<'a> From<&'a SyncRoomEvent> for EventEnum<'a> { - fn from(event: &'a SyncRoomEvent) -> Self { - Self::SyncEvent(event) - } -} - -#[cfg(feature = "e2e-encryption")] -impl<'a> From<&'a Raw> for EventEnum<'a> { - fn from(event: &'a Raw) -> Self { - Self::RawSyncEvent(event) - } -} - -#[cfg(feature = "e2e-encryption")] -impl<'a> From<&'a AnySyncRoomEvent> for EventEnum<'a> { - fn from(event: &'a AnySyncRoomEvent) -> Self { - Self::DeserializedSyncEvent(event) - } -} - -#[cfg(feature = "e2e-encryption")] -impl<'a> EventEnum<'a> { - async fn decrypt(&self, room_id: &RoomId, olm_machine: &OlmMachine) -> Option { - match self { - EventEnum::Event(event) => { - if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - ))) = event.event.deserialize_as::() - { - return olm_machine.decrypt_room_event(&event, room_id).await.ok(); - } - } - EventEnum::RawEvent(event) => { - if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - ))) = event.deserialize_as::() - { - return olm_machine.decrypt_room_event(&event, room_id).await.ok(); - } - } - EventEnum::DeserializedEvent(event) => { - if let AnyRoomEvent::MessageLike(AnyMessageLikeEvent::RoomEncrypted( - MessageLikeEvent::Original(event), - )) = event - { - return olm_machine - .decrypt_room_event(&event.clone().into(), room_id) - .await - .ok(); - } - } - EventEnum::SyncEvent(event) => { - if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - ))) = event.event.deserialize() - { - return olm_machine.decrypt_room_event(&event, room_id).await.ok(); - } - } - EventEnum::RawSyncEvent(event) => { - if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - ))) = event.deserialize() - { - return olm_machine.decrypt_room_event(&event, room_id).await.ok(); - } - } - EventEnum::DeserializedSyncEvent(event) => { - if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - )) = event - { - return olm_machine.decrypt_room_event(event, room_id).await.ok(); - } - } +impl ToEncryptedEvent for Raw { + fn to_encrypted_event( + &self, + ) -> Result, serde_json::Error> { + if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + )) = self.deserialize()? + { + Ok(Some(event)) + } else { + Ok(None) + } + } +} + +#[cfg(feature = "e2e-encryption")] +impl ToEncryptedEvent for SyncRoomEvent { + fn to_encrypted_event( + &self, + ) -> Result, serde_json::Error> { + if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + )) = self.event.deserialize()? + { + Ok(Some(event)) + } else { + Ok(None) + } + } +} + +#[cfg(feature = "e2e-encryption")] +impl ToEncryptedEvent for Raw { + fn to_encrypted_event( + &self, + ) -> Result, serde_json::Error> { + if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + )) = self.deserialize_as::()? + { + Ok(Some(event)) + } else { + Ok(None) + } + } +} + +#[cfg(feature = "e2e-encryption")] +impl ToEncryptedEvent for RoomEvent { + fn to_encrypted_event( + &self, + ) -> Result, serde_json::Error> { + if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + )) = self.event.deserialize_as::()? + { + Ok(Some(event)) + } else { + Ok(None) + } + } +} + +#[cfg(feature = "e2e-encryption")] +impl ToEncryptedEvent for AnySyncRoomEvent { + fn to_encrypted_event( + &self, + ) -> Result, serde_json::Error> { + if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(event), + )) = self + { + Ok(Some(event.clone())) + } else { + Ok(None) + } + } +} + +#[cfg(feature = "e2e-encryption")] +impl ToEncryptedEvent for AnyRoomEvent { + fn to_encrypted_event( + &self, + ) -> Result, serde_json::Error> { + if let AnyRoomEvent::MessageLike(AnyMessageLikeEvent::RoomEncrypted( + MessageLikeEvent::Original(event), + )) = self + { + Ok(Some(event.clone().into())) + } else { + Ok(None) } - None } } From af01c64712730862b375f67ddab091a1bd4845e4 Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Wed, 11 May 2022 11:01:54 +0200 Subject: [PATCH 5/6] Fix doc ofr room::Common::decrypt_event() --- crates/matrix-sdk/src/room/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index dd35960be..d94f3a8bb 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -911,7 +911,7 @@ impl Common { /// # Arguments /// * `event` - The room event to be decrypted. /// - /// Returns: + /// Returns the decrypted event if it was encrypted else `None` #[cfg(feature = "e2e-encryption")] pub async fn decrypt_event(&self, event: &E) -> Result> where From 89e0af97af55bd74f433c92cb38008e9b3954ec1 Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Wed, 11 May 2022 12:28:20 +0200 Subject: [PATCH 6/6] Drop trait used in room::Common::decrypt_event --- crates/matrix-sdk/src/room/common.rs | 155 ++++----------------------- 1 file changed, 21 insertions(+), 134 deletions(-) diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index d94f3a8bb..a08c138ad 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -2,8 +2,6 @@ use std::{collections::BTreeMap, ops::Deref, sync::Arc}; #[cfg(feature = "experimental-timeline")] use futures_core::stream::Stream; -#[cfg(feature = "e2e-encryption")] -use matrix_sdk_base::deserialized_responses::SyncRoomEvent; use matrix_sdk_base::deserialized_responses::{MembersResponse, RoomEvent}; #[cfg(feature = "experimental-timeline")] use matrix_sdk_base::{deserialized_responses::TimelineSlice, TimelineStreamError}; @@ -12,8 +10,8 @@ use matrix_sdk_common::locks::Mutex; use ruma::api::client::filter::LazyLoadOptions; #[cfg(feature = "e2e-encryption")] use ruma::events::{ - room::encrypted::OriginalSyncRoomEncryptedEvent, AnyMessageLikeEvent, AnyRoomEvent, - AnySyncMessageLikeEvent, AnySyncRoomEvent, MessageLikeEvent, SyncMessageLikeEvent, + room::encrypted::OriginalSyncRoomEncryptedEvent, AnySyncMessageLikeEvent, AnySyncRoomEvent, + SyncMessageLikeEvent, }; use ruma::{ api::client::{ @@ -204,11 +202,15 @@ impl Common { #[cfg(feature = "e2e-encryption")] if let Some(machine) = self.client.olm_machine().await { for event in http_response.chunk { - let decrypted_event = if let Some(encrypted_event) = event.to_encrypted_event()? { - machine.decrypt_room_event(&encrypted_event, room_id).await? - } else { - RoomEvent { event, encryption_info: None } - }; + let decrypted_event = + if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(encrypted_event), + )) = event.deserialize_as::()? + { + machine.decrypt_room_event(&encrypted_event, room_id).await? + } else { + RoomEvent { event, encryption_info: None } + }; response.chunk.push(decrypted_event); } @@ -473,16 +475,17 @@ impl Common { let event = self.client.send(request, None).await?.event; #[cfg(feature = "e2e-encryption")] - let decrypted = if let Some(event) = self.decrypt_event(&event).await? { - Ok(event) + if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(encrypted_event), + )) = event.deserialize_as::()? + { + Ok(self.decrypt_event(&encrypted_event).await?) } else { Ok(RoomEvent { event, encryption_info: None }) - }; + } #[cfg(not(feature = "e2e-encryption"))] - let decrypted = Ok(RoomEvent { event, encryption_info: None }); - - decrypted + Ok(RoomEvent { event, encryption_info: None }) } pub(crate) async fn request_members(&self) -> Result> { @@ -911,20 +914,11 @@ impl Common { /// # Arguments /// * `event` - The room event to be decrypted. /// - /// Returns the decrypted event if it was encrypted else `None` + /// Returns the decrypted event. #[cfg(feature = "e2e-encryption")] - pub async fn decrypt_event(&self, event: &E) -> Result> - where - E: ToEncryptedEvent, - { - let encrypted_event = if let Some(event) = event.to_encrypted_event()? { - event - } else { - return Ok(None); - }; - + pub async fn decrypt_event(&self, event: &OriginalSyncRoomEncryptedEvent) -> Result { if let Some(machine) = self.client.olm_machine().await { - Ok(Some(machine.decrypt_room_event(&encrypted_event, self.inner.room_id()).await?)) + Ok(machine.decrypt_room_event(event, self.inner.room_id()).await?) } else { Err(Error::NoOlmMachine) } @@ -991,110 +985,3 @@ impl<'a> MessagesOptions<'a> { }) } } - -/// A trait that is implemented for different rust event types so that -/// [`decrypt_event`][`crate::room::Common::decrpyt_event`] can take any of them -/// as input. -#[cfg(feature = "e2e-encryption")] -pub trait ToEncryptedEvent { - #[doc(hidden)] - fn to_encrypted_event( - &self, - ) -> Result, serde_json::Error>; -} - -#[cfg(feature = "e2e-encryption")] -impl ToEncryptedEvent for Raw { - fn to_encrypted_event( - &self, - ) -> Result, serde_json::Error> { - if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - )) = self.deserialize()? - { - Ok(Some(event)) - } else { - Ok(None) - } - } -} - -#[cfg(feature = "e2e-encryption")] -impl ToEncryptedEvent for SyncRoomEvent { - fn to_encrypted_event( - &self, - ) -> Result, serde_json::Error> { - if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - )) = self.event.deserialize()? - { - Ok(Some(event)) - } else { - Ok(None) - } - } -} - -#[cfg(feature = "e2e-encryption")] -impl ToEncryptedEvent for Raw { - fn to_encrypted_event( - &self, - ) -> Result, serde_json::Error> { - if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - )) = self.deserialize_as::()? - { - Ok(Some(event)) - } else { - Ok(None) - } - } -} - -#[cfg(feature = "e2e-encryption")] -impl ToEncryptedEvent for RoomEvent { - fn to_encrypted_event( - &self, - ) -> Result, serde_json::Error> { - if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - )) = self.event.deserialize_as::()? - { - Ok(Some(event)) - } else { - Ok(None) - } - } -} - -#[cfg(feature = "e2e-encryption")] -impl ToEncryptedEvent for AnySyncRoomEvent { - fn to_encrypted_event( - &self, - ) -> Result, serde_json::Error> { - if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(event), - )) = self - { - Ok(Some(event.clone())) - } else { - Ok(None) - } - } -} - -#[cfg(feature = "e2e-encryption")] -impl ToEncryptedEvent for AnyRoomEvent { - fn to_encrypted_event( - &self, - ) -> Result, serde_json::Error> { - if let AnyRoomEvent::MessageLike(AnyMessageLikeEvent::RoomEncrypted( - MessageLikeEvent::Original(event), - )) = self - { - Ok(Some(event.clone().into())) - } else { - Ok(None) - } - } -}