From 84f4ce73e511c646a97a12126ebcc96d9b90991b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Fri, 9 Apr 2021 21:38:16 +0200 Subject: [PATCH] fix: membership deserializing --- Cargo.lock | 14 +++++------ Cargo.toml | 7 ++---- src/client_server/membership.rs | 16 ++++++++----- src/client_server/room.rs | 28 ++++++++++++---------- src/database.rs | 2 +- src/database/pusher.rs | 2 +- src/database/rooms.rs | 41 ++++++++++++++++++--------------- src/database/sending.rs | 18 +++++++++------ src/utils.rs | 9 ++++---- 9 files changed, 74 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b960f3..b9b9af7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -877,9 +877,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" [[package]] name = "linked-hash-map" @@ -2125,7 +2125,7 @@ checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483" [[package]] name = "state-res" version = "0.1.0" -source = "git+https://github.com/ruma/state-res?rev=af450d0fe2b0e1c890284d0bc3b9d6d4008ac475#af450d0fe2b0e1c890284d0bc3b9d6d4008ac475" +source = "git+https://github.com/timokoesters/state-res?rev=1ec42ea2fc0b0728bf027a5899839ad94bb3091b#1ec42ea2fc0b0728bf027a5899839ad94bb3091b" dependencies = [ "itertools", "log", @@ -2578,9 +2578,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" dependencies = [ "matches", ] @@ -2760,9 +2760,9 @@ checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" [[package]] name = "wildmatch" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ae7ce410f81ba679081aac1d4874f3b1c328535b630209aa5b4cdaaf895e20" +checksum = "d6c48bd20df7e4ced539c12f570f937c6b4884928a87fee70a479d72f031d4e0" [[package]] name = "winapi" diff --git a/Cargo.toml b/Cargo.toml index caf0bdf..35037ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,11 +23,8 @@ ruma = { git = "https://github.com/ruma/ruma", rev = "a310ccc318a4eb51062923d570 #ruma = { path = "../ruma/ruma", features = ["unstable-exhaustive-types", "rand", "client-api", "federation-api", "push-gateway-api", "unstable-pre-spec", "unstable-synapse-quirks"] } # Used when doing state resolution -state-res = { git = "https://github.com/ruma/state-res", rev = "af450d0fe2b0e1c890284d0bc3b9d6d4008ac475", features = ["unstable-pre-spec"] } -# TODO: remove the gen-eventid feature -#state-res = { git = "https://github.com/ruma/state-res", branch = "main", features = ["unstable-pre-spec", "gen-eventid"] } -#state-res = { git = "https://github.com/ruma/state-res", rev = "1621a491a9e867a1ad4dff9f2f92b0c1e2d44aa0", features = ["unstable-pre-spec", "gen-eventid"] } -#state-res = { path = "../state-res", features = ["unstable-pre-spec", "gen-eventid"] } +state-res = { git = "https://github.com/timokoesters/state-res", rev = "1ec42ea2fc0b0728bf027a5899839ad94bb3091b", features = ["unstable-pre-spec"] } +#state-res = { path = "../state-res", features = ["unstable-pre-spec"] } # Used for long polling and federation sender, should be the same as rocket::tokio tokio = "1.2.0" diff --git a/src/client_server/membership.rs b/src/client_server/membership.rs index 5d630b4..3f4f23f 100644 --- a/src/client_server/membership.rs +++ b/src/client_server/membership.rs @@ -604,12 +604,16 @@ async fn join_room_by_id_helper( db.rooms.update_membership( &pdu.room_id, &target_user_id, - serde_json::from_value::(pdu.content.clone()) - .map_err(|_| { - Error::BadRequest( - ErrorKind::InvalidParam, - "Invalid member event content.", - ) + serde_json::from_value::( + pdu.content + .get("membership") + .ok_or_else(|| { + Error::BadServerResponse("Invalid member event content") + })? + .clone(), + ) + .map_err(|_| { + Error::BadServerResponse("Invalid membership state content.") })?, &pdu.sender, &db.account_data, diff --git a/src/client_server/room.rs b/src/client_server/room.rs index f8d980b..bba7f95 100644 --- a/src/client_server/room.rs +++ b/src/client_server/room.rs @@ -91,10 +91,24 @@ pub async fn create_room_route( )?; // 3. Power levels + + // Figure out preset. We need it for preset specific events + let preset = body + .preset + .clone() + .unwrap_or_else(|| match &body.visibility { + room::Visibility::Private => create_room::RoomPreset::PrivateChat, + room::Visibility::Public => create_room::RoomPreset::PublicChat, + room::Visibility::_Custom(_) => create_room::RoomPreset::PrivateChat, // Room visibility should not be custom + }); + let mut users = BTreeMap::new(); users.insert(sender_user.clone(), 100.into()); - for invite_ in &body.invite { - users.insert(invite_.clone(), 100.into()); + + if preset == create_room::RoomPreset::TrustedPrivateChat { + for invite_ in &body.invite { + users.insert(invite_.clone(), 100.into()); + } } let power_levels_content = if let Some(power_levels) = &body.power_level_content_override { @@ -133,16 +147,6 @@ pub async fn create_room_route( // 4. Events set by preset - // Figure out preset. We need it for preset specific events - let preset = body - .preset - .clone() - .unwrap_or_else(|| match &body.visibility { - room::Visibility::Private => create_room::RoomPreset::PrivateChat, - room::Visibility::Public => create_room::RoomPreset::PublicChat, - room::Visibility::_Custom(s) => create_room::RoomPreset::_Custom(s.into()), - }); - // 4.1 Join Rules db.rooms.build_and_append_pdu( PduBuilder { diff --git a/src/database.rs b/src/database.rs index bacf3b9..cb0df15 100644 --- a/src/database.rs +++ b/src/database.rs @@ -108,7 +108,7 @@ impl Database { pub async fn load_or_create(config: Config) -> Result { let db = sled::Config::default() .path(&config.database_path) - .cache_capacity(config.cache_capacity as u64) + .cache_capacity(config.cache_capacity as usize) .use_compression(true) .open()?; diff --git a/src/database/pusher.rs b/src/database/pusher.rs index 6a88d5e..27e5926 100644 --- a/src/database/pusher.rs +++ b/src/database/pusher.rs @@ -196,7 +196,7 @@ pub async fn send_push_notice( let mut notify = None; let mut tweaks = Vec::new(); - for action in ruleset.get_actions(&pdu.to_sync_state_event(), &ctx) { + for action in ruleset.get_actions(&pdu.to_sync_room_event(), &ctx) { let n = match action { Action::DontNotify => false, // TODO: Implement proper support for coalesce diff --git a/src/database/rooms.rs b/src/database/rooms.rs index b2043d1..81697e3 100644 --- a/src/database/rooms.rs +++ b/src/database/rooms.rs @@ -465,7 +465,7 @@ impl Rooms { /// Returns the pdu. /// /// This does __NOT__ check the outliers `Tree`. - pub fn get_pdu_from_id(&self, pdu_id: &IVec) -> Result> { + pub fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result> { self.pduid_pdu.get(pdu_id)?.map_or(Ok(None), |pdu| { Ok(Some( serde_json::from_slice(&pdu) @@ -671,11 +671,21 @@ impl Rooms { self.update_membership( &pdu.room_id, &target_user_id, - serde_json::from_value::(pdu.content.clone()) - .map_err(|_| { + serde_json::from_value::( + pdu.content + .get("membership") + .ok_or_else(|| { + Error::BadRequest( + ErrorKind::InvalidParam, + "Invalid member event content", + ) + })? + .clone(), + ) + .map_err(|_| { Error::BadRequest( ErrorKind::InvalidParam, - "Invalid member event content.", + "Invalid membership state content.", ) })?, &pdu.sender, @@ -895,19 +905,14 @@ impl Rooms { .scan_prefix(&old_shortstatehash) .filter_map(|pdu| pdu.map_err(|e| error!("{}", e)).ok()) // Chop the old_shortstatehash out leaving behind the short state key - .map(|(k, v)| { - ( - k.subslice(old_shortstatehash.len(), k.len() - old_shortstatehash.len()), - v, - ) - }) - .collect::>() + .map(|(k, v)| (k[old_shortstatehash.len()..].to_vec(), v)) + .collect::, IVec>>() } else { HashMap::new() }; if let Some(state_key) = &new_pdu.state_key { - let mut new_state: HashMap = old_state; + let mut new_state: HashMap, IVec> = old_state; let mut new_state_key = new_pdu.kind.as_ref().as_bytes().to_vec(); new_state_key.push(0xff); @@ -935,7 +940,7 @@ impl Rooms { } }; - new_state.insert(shortstatekey.into(), shorteventid.into()); + new_state.insert(shortstatekey, shorteventid.into()); let new_state_hash = self.calculate_hash( &new_state @@ -1377,13 +1382,11 @@ impl Rooms { &self, room_id: &RoomId, user_id: &UserId, - member_content: member::MemberEventContent, + membership: member::MembershipState, sender: &UserId, account_data: &super::account_data::AccountData, globals: &super::globals::Globals, ) -> Result<()> { - let membership = member_content.membership; - let mut roomserver_id = room_id.as_bytes().to_vec(); roomserver_id.push(0xff); roomserver_id.extend_from_slice(user_id.server_name().as_bytes()); @@ -1633,7 +1636,7 @@ impl Rooms { &'a self, room_id: &RoomId, search_string: &str, - ) -> Result<(impl Iterator + 'a, Vec)> { + ) -> Result<(impl Iterator> + 'a, Vec)> { let mut prefix = room_id.as_bytes().to_vec(); prefix.push(0xff); @@ -1661,7 +1664,7 @@ impl Rooms { .0 + 1; // +1 because the pdu id starts AFTER the separator - let pdu_id = key.subslice(pduid_index, key.len() - pduid_index); + let pdu_id = key[pduid_index..].to_vec(); Ok::<_, Error>(pdu_id) }) @@ -1700,7 +1703,7 @@ impl Rooms { .0 + 1; // +1 because the room id starts AFTER the separator - let room_id = key.subslice(roomid_index, key.len() - roomid_index); + let room_id = key[roomid_index..].to_vec(); Ok::<_, Error>(room_id) }) diff --git a/src/database/sending.rs b/src/database/sending.rs index b0f9c4d..779df06 100644 --- a/src/database/sending.rs +++ b/src/database/sending.rs @@ -47,7 +47,7 @@ impl Sending { let mut futures = FuturesUnordered::new(); // Retry requests we could not finish yet - let mut current_transactions = HashMap::>::new(); + let mut current_transactions = HashMap::>>::new(); for (key, outgoing_kind, pdu) in servercurrentpdus .iter() @@ -55,7 +55,7 @@ impl Sending { .filter_map(|(key, _)| { Self::parse_servercurrentpdus(&key) .ok() - .map(|(k, p)| (key, k, p)) + .map(|(k, p)| (key, k, p.to_vec())) }) { if pdu.is_empty() { @@ -150,7 +150,7 @@ impl Sending { .keys() .filter_map(|r| r.ok()) .map(|k| { - k.subslice(prefix.len(), k.len() - prefix.len()) + k[prefix.len()..].to_vec() }) .take(30) .collect::>(); @@ -211,7 +211,11 @@ impl Sending { }; }, Some(event) = &mut subscriber => { - if let sled::Event::Insert { key, .. } = event { + for (_tree, key, value_opt) in &event { + if value_opt.is_none() { + continue; + } + let servernamepduid = key.clone(); let exponential_backoff = |(tries, instant): &(u32, Instant)| { @@ -265,7 +269,7 @@ impl Sending { futures.push( Self::handle_event( outgoing_kind, - vec![pdu_id], + vec![pdu_id.to_vec()], &db, ) ); @@ -310,7 +314,7 @@ impl Sending { } #[tracing::instrument] - fn calculate_hash(keys: &[IVec]) -> Vec { + fn calculate_hash(keys: &[Vec]) -> Vec { // We only hash the pdu's event ids, not the whole pdu let bytes = keys.join(&0xff); let hash = digest::digest(&digest::SHA256, &bytes); @@ -320,7 +324,7 @@ impl Sending { #[tracing::instrument(skip(db))] async fn handle_event( kind: OutgoingKind, - pdu_ids: Vec, + pdu_ids: Vec>, db: &Database, ) -> std::result::Result { match &kind { diff --git a/src/utils.rs b/src/utils.rs index 0783567..45d9de8 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,7 +2,6 @@ use argon2::{Config, Variant}; use cmp::Ordering; use rand::prelude::*; use ruma::serde::{try_from_json_map, CanonicalJsonError, CanonicalJsonObject}; -use sled::IVec; use std::{ cmp, convert::TryInto, @@ -70,10 +69,10 @@ pub fn calculate_hash(password: &str) -> Result { argon2::hash_encoded(password.as_bytes(), salt.as_bytes(), &hashing_config) } -pub fn common_elements( - mut iterators: impl Iterator>, - check_order: impl Fn(&IVec, &IVec) -> Ordering, -) -> Option> { +pub fn common_elements<'a>( + mut iterators: impl Iterator>>, + check_order: impl Fn(&[u8], &[u8]) -> Ordering, +) -> Option>> { let first_iterator = iterators.next()?; let mut other_iterators = iterators.map(|i| i.peekable()).collect::>();