diff --git a/crates/matrix-sdk-test/src/lib.rs b/crates/matrix-sdk-test/src/lib.rs index 2d968c768..f683f8994 100644 --- a/crates/matrix-sdk-test/src/lib.rs +++ b/crates/matrix-sdk-test/src/lib.rs @@ -24,6 +24,7 @@ pub enum EventsJson { Alias, Aliases, Create, + Encryption, FullyRead, HistoryVisibility, JoinRules, @@ -196,6 +197,7 @@ impl EventBuilder { EventsJson::Name => &test_json::NAME, EventsJson::Member => &test_json::MEMBER, EventsJson::PowerLevels => &test_json::POWER_LEVELS, + EventsJson::Encryption => &test_json::ENCRYPTION, _ => panic!("unknown state event {:?}", json), }; diff --git a/crates/matrix-sdk-test/src/test_json/events.rs b/crates/matrix-sdk-test/src/test_json/events.rs index f6feb37ed..2e3ec4e50 100644 --- a/crates/matrix-sdk-test/src/test_json/events.rs +++ b/crates/matrix-sdk-test/src/test_json/events.rs @@ -337,6 +337,25 @@ lazy_static! { }); } +lazy_static! { + pub static ref ENCRYPTION: JsonValue = json!({ + "content": { + "algorithm": "m.megolm.v1.aes-sha2", + "rotation_period_ms": 604800000, + "rotation_period_msgs": 100 + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1432735824653u64, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "state_key": "", + "type": "m.room.encryption", + "unsigned": { + "age": 1234 + } + }); +} + // TODO: Move `prev_content` into `unsigned` once ruma supports it lazy_static! { pub static ref MEMBER: JsonValue = json!({ diff --git a/crates/matrix-sdk-test/src/test_json/mod.rs b/crates/matrix-sdk-test/src/test_json/mod.rs index 9ccd20cdc..d41ca88d0 100644 --- a/crates/matrix-sdk-test/src/test_json/mod.rs +++ b/crates/matrix-sdk-test/src/test_json/mod.rs @@ -12,11 +12,11 @@ pub mod members; pub mod sync; pub use events::{ - ALIAS, ALIASES, EVENT_ID, KEYS_QUERY, KEYS_UPLOAD, LOGIN, LOGIN_RESPONSE_ERR, LOGIN_TYPES, - LOGIN_WITH_DISCOVERY, LOGOUT, MEMBER, MEMBER_INVITE, MEMBER_NAME_CHANGE, MEMBER_STRIPPED, - MESSAGE_EDIT, MESSAGE_TEXT, NAME, NAME_STRIPPED, POWER_LEVELS, PRESENCE, PUBLIC_ROOMS, - PUSH_RULES, REACTION, READ_RECEIPT, READ_RECEIPT_OTHER, REDACTED, REDACTED_INVALID, - REDACTED_STATE, REDACTION, REGISTRATION_RESPONSE_ERR, ROOM_ID, ROOM_MESSAGES, + ALIAS, ALIASES, ENCRYPTION, EVENT_ID, KEYS_QUERY, KEYS_UPLOAD, LOGIN, LOGIN_RESPONSE_ERR, + LOGIN_TYPES, LOGIN_WITH_DISCOVERY, LOGOUT, MEMBER, MEMBER_INVITE, MEMBER_NAME_CHANGE, + MEMBER_STRIPPED, MESSAGE_EDIT, MESSAGE_TEXT, NAME, NAME_STRIPPED, POWER_LEVELS, PRESENCE, + PUBLIC_ROOMS, PUSH_RULES, REACTION, READ_RECEIPT, READ_RECEIPT_OTHER, REDACTED, + REDACTED_INVALID, REDACTED_STATE, REDACTION, REGISTRATION_RESPONSE_ERR, ROOM_ID, ROOM_MESSAGES, SYNC_ROOM_MESSAGES_BATCH_1, SYNC_ROOM_MESSAGES_BATCH_2, TAG, TOPIC, TYPING, }; pub use members::MEMBERS; diff --git a/crates/matrix-sdk/src/client/mod.rs b/crates/matrix-sdk/src/client/mod.rs index a780ab45e..17d558cf5 100644 --- a/crates/matrix-sdk/src/client/mod.rs +++ b/crates/matrix-sdk/src/client/mod.rs @@ -126,7 +126,7 @@ pub(crate) struct ClientInner { /// The underlying HTTP client. http_client: HttpClient, /// User session data. - base_client: BaseClient, + pub(crate) base_client: BaseClient, /// The Matrix versions the server supports (well-known ones only) server_versions: Mutex>, /// Locks making sure we only have one group session sharing request in diff --git a/crates/matrix-sdk/src/encryption/mod.rs b/crates/matrix-sdk/src/encryption/mod.rs index 681791ea1..55bacff3d 100644 --- a/crates/matrix-sdk/src/encryption/mod.rs +++ b/crates/matrix-sdk/src/encryption/mod.rs @@ -889,3 +889,57 @@ impl Encryption { Ok(olm.import_keys(import, false, |_, _| {}).await?) } } + +#[cfg(all(test, not(target_arch = "wasm32")))] +mod tests { + use matrix_sdk_test::{async_test, EventBuilder, EventsJson}; + use mockito::{mock, Matcher}; + use ruma::{ + event_id, + events::reaction::{ReactionEventContent, Relation}, + room_id, + }; + use serde_json::json; + + use crate::client::tests::logged_in_client; + + #[async_test] + async fn test_reaction_sending() { + let client = logged_in_client().await; + + let event_id = event_id!("$2:example.org"); + let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + + let _m = mock( + "PUT", + Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/send/m%2Ereaction/.*".to_owned()), + ) + .with_status(200) + .with_body( + json!({ + "event_id": event_id, + }) + .to_string(), + ) + .create(); + + let response = EventBuilder::default() + .add_state_event(EventsJson::Member) + .add_state_event(EventsJson::PowerLevels) + .add_state_event(EventsJson::Encryption) + .build_sync_response(); + + client.inner.base_client.receive_sync_response(response).await.unwrap(); + + let room = client.get_joined_room(room_id).expect("Room should exist"); + assert!(room.is_encrypted()); + + let event_id = event_id!("$1:example.org"); + let reaction = ReactionEventContent::new(Relation::new(event_id.into(), "🐈".to_owned())); + room.send(reaction, None).await.expect("Sending the reaction should not fail"); + + room.send_raw(json!({}), "m.reaction", None) + .await + .expect("Sending the reaction should not fail"); + } +} diff --git a/crates/matrix-sdk/src/room/joined.rs b/crates/matrix-sdk/src/room/joined.rs index f7bf778df..58cf6aea1 100644 --- a/crates/matrix-sdk/src/room/joined.rs +++ b/crates/matrix-sdk/src/room/joined.rs @@ -551,26 +551,37 @@ impl Joined { #[cfg(feature = "encryption")] let (content, event_type) = if self.is_encrypted() { - debug!( - room_id = self.room_id().as_str(), - "Sending encrypted event because the room is encrypted.", - ); + // Reactions are currently famously not encrypted, skip encrypting + // them until they are. + if event_type == "m.reaction" { + debug!( + room_id = self.room_id().as_str(), + "Sending plaintext event because the event type is {}", event_type + ); + (Raw::new(&content)?.cast(), event_type) + } else { + debug!( + room_id = self.room_id().as_str(), + "Sending encrypted event because the room is encrypted.", + ); - if !self.are_members_synced() { - self.request_members().await?; - // TODO query keys here? + if !self.are_members_synced() { + self.request_members().await?; + // TODO query keys here? + } + + self.preshare_group_session().await?; + + let olm = self.client.olm_machine().await.expect("Olm machine wasn't started"); + + let encrypted_content = + olm.encrypt_raw(self.inner.room_id(), content, event_type).await?; + let raw_content = Raw::new(&encrypted_content) + .expect("Failed to serialize encrypted event") + .cast(); + + (raw_content, "m.room.encrypted") } - - self.preshare_group_session().await?; - - let olm = self.client.olm_machine().await.expect("Olm machine wasn't started"); - - let encrypted_content = - olm.encrypt_raw(self.inner.room_id(), content, event_type).await?; - let raw_content = - Raw::new(&encrypted_content).expect("Failed to serialize encrypted event").cast(); - - (raw_content, "m.room.encrypted") } else { debug!( room_id = self.room_id().as_str(),