mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-06 15:04:11 -04:00
feat(matrix-sdk): Expose method to decrypt room events
Merge pull request #614 from jsparber/fix_decrypt_timeline
This commit is contained in:
@@ -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<AnyRoomEvent>) -> 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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -4,13 +4,15 @@ use std::{collections::BTreeMap, ops::Deref, sync::Arc};
|
||||
use futures_core::stream::Stream;
|
||||
use matrix_sdk_base::deserialized_responses::{MembersResponse, RoomEvent};
|
||||
#[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::{
|
||||
room::encrypted::OriginalSyncRoomEncryptedEvent, AnySyncMessageLikeEvent, AnySyncRoomEvent,
|
||||
SyncMessageLikeEvent,
|
||||
};
|
||||
use ruma::{
|
||||
api::client::{
|
||||
config::set_global_account_data,
|
||||
@@ -178,24 +180,47 @@ impl Common {
|
||||
/// # });
|
||||
/// ```
|
||||
pub async fn messages(&self, options: MessagesOptions<'_>) -> Result<Messages> {
|
||||
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(machine) = self.client.olm_machine().await {
|
||||
for event in http_response.chunk {
|
||||
let decrypted_event =
|
||||
if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted(
|
||||
SyncMessageLikeEvent::Original(encrypted_event),
|
||||
)) = event.deserialize_as::<AnySyncRoomEvent>()?
|
||||
{
|
||||
machine.decrypt_room_event(&encrypted_event, room_id).await?
|
||||
} 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(decrypted_event);
|
||||
}
|
||||
} else {
|
||||
response.chunk.extend(
|
||||
http_response
|
||||
.chunk
|
||||
.into_iter()
|
||||
.map(|event| RoomEvent { event, encryption_info: None }),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
@@ -450,10 +475,17 @@ impl Common {
|
||||
let event = self.client.send(request, None).await?.event;
|
||||
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
return Ok(self.client.decrypt_room_event(event).await);
|
||||
if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted(
|
||||
SyncMessageLikeEvent::Original(encrypted_event),
|
||||
)) = event.deserialize_as::<AnySyncRoomEvent>()?
|
||||
{
|
||||
Ok(self.decrypt_event(&encrypted_event).await?)
|
||||
} else {
|
||||
Ok(RoomEvent { event, encryption_info: None })
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "e2e-encryption"))]
|
||||
return Ok(RoomEvent { event, encryption_info: None });
|
||||
Ok(RoomEvent { event, encryption_info: None })
|
||||
}
|
||||
|
||||
pub(crate) async fn request_members(&self) -> Result<Option<MembersResponse>> {
|
||||
@@ -876,6 +908,21 @@ impl Common {
|
||||
self.client.send(request, None).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tries to decrypt a room event.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `event` - The room event to be decrypted.
|
||||
///
|
||||
/// Returns the decrypted event.
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
pub async fn decrypt_event(&self, event: &OriginalSyncRoomEncryptedEvent) -> Result<RoomEvent> {
|
||||
if let Some(machine) = self.client.olm_machine().await {
|
||||
Ok(machine.decrypt_room_event(event, self.inner.room_id()).await?)
|
||||
} else {
|
||||
Err(Error::NoOlmMachine)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Options for [`messages`][Common::messages].
|
||||
|
||||
Reference in New Issue
Block a user