From 62df9ca5803d049e5b255474220da77fb49b954e Mon Sep 17 00:00:00 2001 From: Devin Ragotzy Date: Sat, 25 Jul 2020 23:56:50 -0400 Subject: [PATCH 1/5] Fix all clippy warnings, shorten line len in client_server --- src/client_server.rs | 185 ++++++++++++++++++++++++++++-------------- src/database/media.rs | 11 +-- src/database/rooms.rs | 55 ++++++------- src/database/uiaa.rs | 2 +- src/database/users.rs | 2 +- 5 files changed, 155 insertions(+), 100 deletions(-) diff --git a/src/client_server.rs b/src/client_server.rs index 4a2f33b3..6f9688ff 100644 --- a/src/client_server.rs +++ b/src/client_server.rs @@ -230,7 +230,7 @@ pub fn register_route( Ok(register::Response { access_token: Some(token), user_id, - device_id: Some(device_id.into()), + device_id: Some(device_id), } .into()) } @@ -257,11 +257,22 @@ pub fn login_route( if let (login::UserInfo::MatrixId(username), login::LoginInfo::Password { password }) = (body.user.clone(), body.login_info.clone()) { - let user_id = UserId::parse_with_server_name(username, db.globals.server_name()).map_err(|_| Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid."))?; - let hash = db.users.password_hash(&user_id)?.ok_or(Error::BadRequest(ErrorKind::Forbidden, "Wrong username or password."))?; + let user_id = UserId::parse_with_server_name(username, db.globals.server_name()) + .map_err(|_| Error::BadRequest( + ErrorKind::InvalidUsername, + "Username is invalid." + ))?; + let hash = db.users.password_hash(&user_id)? + .ok_or(Error::BadRequest( + ErrorKind::Forbidden, + "Wrong username or password." + ))?; if hash.is_empty() { - return Err(Error::BadRequest(ErrorKind::UserDeactivated, "The user has been deactivated")); + return Err(Error::BadRequest( + ErrorKind::UserDeactivated, + "The user has been deactivated" + )); } let hash_matches = @@ -298,7 +309,7 @@ pub fn login_route( user_id, access_token: token, home_server: Some(db.globals.server_name().to_owned()), - device_id: device_id.into(), + device_id, well_known: None, } .into()) @@ -1702,8 +1713,7 @@ pub fn leave_room_route( ErrorKind::BadState, "Cannot leave a room you are not a member of.", ))? - .content - .clone(), + .content, ) .map_err(|_| Error::bad_database("Invalid member event in database."))? .deserialize() @@ -1746,8 +1756,7 @@ pub fn kick_user_route( ErrorKind::BadState, "Cannot kick member that's not in the room.", ))? - .content - .clone(), + .content, ) .expect("Raw::from_value always works") .deserialize() @@ -1882,8 +1891,7 @@ pub fn unban_user_route( ErrorKind::BadState, "Cannot unban a user who is not banned.", ))? - .content - .clone(), + .content, ) .map_err(|_| Error::bad_database("Invalid member event in database."))? .deserialize() @@ -2049,6 +2057,8 @@ pub async fn get_public_rooms_filtered_route( db: State<'_, Database>, _body: Ruma, ) -> ConduitResult { + use ruma::events::room; + let mut chunk = db .rooms .public_rooms() @@ -2060,63 +2070,110 @@ pub async fn get_public_rooms_filtered_route( let chunk = directory::PublicRoomsChunk { aliases: Vec::new(), - canonical_alias: state.get(&(EventType::RoomCanonicalAlias, "".to_owned())).map_or(Ok::<_, Error>(None), |s| { - Ok(serde_json::from_value::< - Raw, + canonical_alias: state + .get(&(EventType::RoomCanonicalAlias, "".to_owned())) + .map_or(Ok::<_, Error>(None), |s| { + Ok(serde_json::from_value::< + Raw, >(s.content.clone()) - .map_err(|_| Error::bad_database("Invalid canonical alias event in database."))? + .map_err(|_| { + Error::bad_database("Invalid canonical alias event in database.") + })? .deserialize() - .map_err(|_| Error::bad_database("Invalid canonical alias event in database."))? + .map_err(|_| { + Error::bad_database("Invalid canonical alias event in database.") + })? .alias) - })?, - name: state.get(&(EventType::RoomName, "".to_owned())).map_or(Ok::<_, Error>(None), |s| { - Ok(serde_json::from_value::>( - s.content.clone(), - ) - .map_err(|_| Error::bad_database("Invalid room name event in database."))? - .deserialize() - .map_err(|_| Error::bad_database("Invalid room name event in database."))? - .name() - .map(|n| n.to_owned())) - })?, + })?, + name: state.get(&(EventType::RoomName, "".to_owned())).map_or( + Ok::<_, Error>(None), + |s| { + Ok(serde_json::from_value::>( + s.content.clone(), + ) + .map_err(|_| Error::bad_database("Invalid room name event in database."))? + .deserialize() + .map_err(|_| Error::bad_database("Invalid room name event in database."))? + .name() + .map(|n| n.to_owned())) + }, + )?, num_joined_members: (db.rooms.room_members(&room_id).count() as u32).into(), room_id, - topic: state.get(&(EventType::RoomTopic, "".to_owned())).map_or(Ok::<_, Error>(None), |s| { - Ok(Some(serde_json::from_value::< - Raw, + topic: state.get(&(EventType::RoomTopic, "".to_owned())).map_or( + Ok::<_, Error>(None), + |s| { + Ok(Some( + serde_json::from_value::>( + s.content.clone(), + ) + .map_err(|_| { + Error::bad_database("Invalid room topic event in database.") + })? + .deserialize() + .map_err(|_| { + Error::bad_database("Invalid room topic event in database.") + })? + .topic, + )) + }, + )?, + world_readable: state + .get(&(EventType::RoomHistoryVisibility, "".to_owned())) + .map_or(Ok::<_, Error>(false), |s| { + Ok(serde_json::from_value::< + Raw, >(s.content.clone()) - .map_err(|_| Error::bad_database("Invalid room topic event in database."))? + .map_err(|_| { + Error::bad_database( + "Invalid room history visibility event in database.", + ) + })? .deserialize() - .map_err(|_| Error::bad_database("Invalid room topic event in database."))? - .topic)) - })?, - world_readable: state.get(&(EventType::RoomHistoryVisibility, "".to_owned())).map_or(Ok::<_, Error>(false), |s| { - Ok(serde_json::from_value::< - Raw, - >(s.content.clone()) - .map_err(|_| Error::bad_database("Invalid room history visibility event in database."))? - .deserialize() - .map_err(|_| Error::bad_database("Invalid room history visibility event in database."))? - .history_visibility == history_visibility::HistoryVisibility::WorldReadable) - })?, - guest_can_join: state.get(&(EventType::RoomGuestAccess, "".to_owned())).map_or(Ok::<_, Error>(false), |s| { - Ok(serde_json::from_value::< - Raw, - >(s.content.clone()) - .map_err(|_| Error::bad_database("Invalid room guest access event in database."))? - .deserialize() - .map_err(|_| Error::bad_database("Invalid room guest access event in database."))? - .guest_access == guest_access::GuestAccess::CanJoin) - })?, - avatar_url: state.get(&(EventType::RoomAvatar, "".to_owned())).map_or( Ok::<_, Error>(None),|s| { - Ok(Some(serde_json::from_value::< - Raw, - >(s.content.clone()) - .map_err(|_| Error::bad_database("Invalid room avatar event in database."))? - .deserialize() - .map_err(|_| Error::bad_database("Invalid room avatar event in database."))? - .url)) - })?, + .map_err(|_| { + Error::bad_database( + "Invalid room history visibility event in database.", + ) + })? + .history_visibility + == history_visibility::HistoryVisibility::WorldReadable) + })?, + guest_can_join: state + .get(&(EventType::RoomGuestAccess, "".to_owned())) + .map_or(Ok::<_, Error>(false), |s| { + Ok( + serde_json::from_value::< + Raw, + >(s.content.clone()) + .map_err(|_| { + Error::bad_database("Invalid room guest access event in database.") + })? + .deserialize() + .map_err(|_| { + Error::bad_database("Invalid room guest access event in database.") + })? + .guest_access + == guest_access::GuestAccess::CanJoin, + ) + })?, + avatar_url: state.get(&(EventType::RoomAvatar, "".to_owned())).map_or( + Ok::<_, Error>(None), + |s| { + Ok(Some( + serde_json::from_value::>( + s.content.clone(), + ) + .map_err(|_| { + Error::bad_database("Invalid room avatar event in database.") + })? + .deserialize() + .map_err(|_| { + Error::bad_database("Invalid room avatar event in database.") + })? + .url, + )) + }, + )?, }; Ok::<_, Error>(chunk) }) @@ -2338,7 +2395,11 @@ pub fn create_state_event_for_key_route( .filter(|room| room == &body.room_id) // Make sure it's the right room .is_none() { - return Err(Error::BadRequest(ErrorKind::Forbidden, "You are only allowed to send canonical_alias events when it's aliases already exists")); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "You are only allowed to send canonical_alias \ + events when it's aliases already exists", + )); } } } diff --git a/src/database/media.rs b/src/database/media.rs index 0d0820d3..cec74a62 100644 --- a/src/database/media.rs +++ b/src/database/media.rs @@ -1,6 +1,8 @@ use crate::{utils, Error, Result}; use std::mem; +pub type FileMeta = (Option, String, Vec); + pub struct Media { pub(super) mediaid_file: sled::Tree, // MediaId = MXC + WidthHeight + Filename + ContentType } @@ -29,7 +31,7 @@ impl Media { } /// Downloads a file. - pub fn get(&self, mxc: String) -> Result, String, Vec)>> { + pub fn get(&self, mxc: String) -> Result> { let mut prefix = mxc.as_bytes().to_vec(); prefix.push(0xff); prefix.extend_from_slice(&0_u32.to_be_bytes()); // Width = 0 if it's not a thumbnail @@ -66,12 +68,7 @@ impl Media { } /// Downloads a file's thumbnail. - pub fn get_thumbnail( - &self, - mxc: String, - width: u32, - height: u32, - ) -> Result, String, Vec)>> { + pub fn get_thumbnail(&self, mxc: String, width: u32, height: u32) -> Result> { let mut main_prefix = mxc.as_bytes().to_vec(); main_prefix.push(0xff); diff --git a/src/database/rooms.rs b/src/database/rooms.rs index 7895f025..ae0d0849 100644 --- a/src/database/rooms.rs +++ b/src/database/rooms.rs @@ -250,6 +250,7 @@ impl Rooms { } /// Creates a new persisted data unit and adds it to a room. + #[allow(clippy::too_many_arguments, clippy::blocks_in_if_conditions)] pub fn append_pdu( &self, room_id: RoomId, @@ -288,7 +289,7 @@ impl Rooms { }, |power_levels| { Ok(serde_json::from_value::>( - power_levels.content.clone(), + power_levels.content, ) .expect("Raw::from_value always works.") .deserialize() @@ -298,13 +299,13 @@ impl Rooms { let sender_membership = self .room_state_get(&room_id, &EventType::RoomMember, &sender.to_string())? .map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| { - Ok(serde_json::from_value::>( - pdu.content.clone(), + Ok( + serde_json::from_value::>(pdu.content) + .expect("Raw::from_value always works.") + .deserialize() + .map_err(|_| Error::bad_database("Invalid Member event in db."))? + .membership, ) - .expect("Raw::from_value always works.") - .deserialize() - .map_err(|_| Error::bad_database("Invalid Member event in db."))? - .membership) })?; let sender_power = power_levels.users.get(&sender).map_or_else( @@ -341,7 +342,7 @@ impl Rooms { )? .map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| { Ok(serde_json::from_value::>( - pdu.content.clone(), + pdu.content, ) .expect("Raw::from_value always works.") .deserialize() @@ -373,7 +374,7 @@ impl Rooms { .map_or(Ok::<_, Error>(join_rules::JoinRule::Public), |pdu| { Ok(serde_json::from_value::< Raw, - >(pdu.content.clone()) + >(pdu.content) .expect("Raw::from_value always works.") .deserialize() .map_err(|_| { @@ -501,7 +502,7 @@ impl Rooms { let mut unsigned = unsigned.unwrap_or_default(); if let Some(state_key) = &state_key { if let Some(prev_pdu) = self.room_state_get(&room_id, &event_type, &state_key)? { - unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone()); + unsigned.insert("prev_content".to_owned(), prev_pdu.content); unsigned.insert( "prev_sender".to_owned(), serde_json::to_value(prev_pdu.sender).expect("UserId::to_value always works"), @@ -575,28 +576,24 @@ impl Rooms { self.roomstateid_pdu.insert(key, &*pdu_json.to_string())?; } - match event_type { - EventType::RoomRedaction => { - if let Some(redact_id) = &redacts { - // TODO: Reason - let _reason = - serde_json::from_value::>(content) - .expect("Raw::from_value always works.") - .deserialize() - .map_err(|_| { - Error::BadRequest( - ErrorKind::InvalidParam, - "Invalid redaction event content.", - ) - })? - .reason; + if let EventType::RoomRedaction = event_type { + if let Some(redact_id) = &redacts { + // TODO: Reason + let _reason = + serde_json::from_value::>(content) + .expect("Raw::from_value always works.") + .deserialize() + .map_err(|_| { + Error::BadRequest( + ErrorKind::InvalidParam, + "Invalid redaction event content.", + ) + })? + .reason; - self.redact_pdu(&redact_id)?; - } + self.redact_pdu(&redact_id)?; } - _ => {} } - self.edus.room_read_set(&room_id, &sender, index)?; Ok(pdu.event_id) diff --git a/src/database/uiaa.rs b/src/database/uiaa.rs index 4366eb2c..cece8dbe 100644 --- a/src/database/uiaa.rs +++ b/src/database/uiaa.rs @@ -42,7 +42,7 @@ impl Uiaa { .map(|session| { Ok::<_, Error>(self.get_uiaa_session(&user_id, &device_id, session)?) }) - .unwrap_or(Ok(uiaainfo.clone()))?; + .unwrap_or_else(|| Ok(uiaainfo.clone()))?; // Find out what the user completed match &**kind { diff --git a/src/database/users.rs b/src/database/users.rs index c7927677..1ec677ca 100644 --- a/src/database/users.rs +++ b/src/database/users.rs @@ -502,7 +502,7 @@ impl Users { )); } - let mut user_signing_key_key = prefix.clone(); + let mut user_signing_key_key = prefix; user_signing_key_key.extend_from_slice(user_signing_key_id.as_bytes()); self.keyid_key.insert( From 2da48b941d9fbf013b807bfcfbe2f101d34ecfb7 Mon Sep 17 00:00:00 2001 From: Devin Ragotzy Date: Mon, 27 Jul 2020 19:46:38 -0400 Subject: [PATCH 2/5] Convert all map_err -> expect when deserializing to Raw --- src/client_server.rs | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/src/client_server.rs b/src/client_server.rs index 6f9688ff..bac4b259 100644 --- a/src/client_server.rs +++ b/src/client_server.rs @@ -676,7 +676,7 @@ pub fn set_displayname_route( .content .clone(), ) - .map_err(|_| Error::bad_database("Database contains invalid PDU."))? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| Error::bad_database("Database contains invalid PDU."))? }) @@ -772,7 +772,7 @@ pub fn set_avatar_url_route( .content .clone(), ) - .map_err(|_| Error::bad_database("Database contains invalid PDU."))? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| Error::bad_database("Database contains invalid PDU."))? }) @@ -1715,7 +1715,7 @@ pub fn leave_room_route( ))? .content, ) - .map_err(|_| Error::bad_database("Invalid member event in database."))? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| Error::bad_database("Invalid member event in database."))?; @@ -1846,7 +1846,7 @@ pub fn ban_user_route( }), |event| { let mut event = serde_json::from_value::>( - event.content.clone(), + event.content, ) .expect("Raw::from_value always works") .deserialize() @@ -1893,7 +1893,7 @@ pub fn unban_user_route( ))? .content, ) - .map_err(|_| Error::bad_database("Invalid member event in database."))? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| Error::bad_database("Invalid member event in database."))?; @@ -2076,9 +2076,7 @@ pub async fn get_public_rooms_filtered_route( Ok(serde_json::from_value::< Raw, >(s.content.clone()) - .map_err(|_| { - Error::bad_database("Invalid canonical alias event in database.") - })? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| { Error::bad_database("Invalid canonical alias event in database.") @@ -2091,7 +2089,7 @@ pub async fn get_public_rooms_filtered_route( Ok(serde_json::from_value::>( s.content.clone(), ) - .map_err(|_| Error::bad_database("Invalid room name event in database."))? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| Error::bad_database("Invalid room name event in database."))? .name() @@ -2107,9 +2105,7 @@ pub async fn get_public_rooms_filtered_route( serde_json::from_value::>( s.content.clone(), ) - .map_err(|_| { - Error::bad_database("Invalid room topic event in database.") - })? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| { Error::bad_database("Invalid room topic event in database.") @@ -2124,11 +2120,7 @@ pub async fn get_public_rooms_filtered_route( Ok(serde_json::from_value::< Raw, >(s.content.clone()) - .map_err(|_| { - Error::bad_database( - "Invalid room history visibility event in database.", - ) - })? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| { Error::bad_database( @@ -2145,9 +2137,7 @@ pub async fn get_public_rooms_filtered_route( serde_json::from_value::< Raw, >(s.content.clone()) - .map_err(|_| { - Error::bad_database("Invalid room guest access event in database.") - })? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| { Error::bad_database("Invalid room guest access event in database.") @@ -2163,9 +2153,7 @@ pub async fn get_public_rooms_filtered_route( serde_json::from_value::>( s.content.clone(), ) - .map_err(|_| { - Error::bad_database("Invalid room avatar event in database.") - })? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| { Error::bad_database("Invalid room avatar event in database.") @@ -2377,7 +2365,7 @@ pub fn create_state_event_for_key_route( let canonical_alias = serde_json::from_value::< Raw, >(content.clone()) - .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid canonical alias."))? + .expect("from_value::> can never fail") .deserialize() .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid canonical alias."))?; From 1c6f2119334e68b467ee4b8e4e4fabedea1f8131 Mon Sep 17 00:00:00 2001 From: Devin Ragotzy Date: Tue, 28 Jul 2020 08:59:30 -0400 Subject: [PATCH 3/5] Create media::FileMeta to represent a file and meta data --- src/client_server.rs | 14 +++++++++++--- src/database.rs | 2 +- src/database/media.rs | 24 ++++++++++++++++++++---- src/lib.rs | 2 +- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/client_server.rs b/src/client_server.rs index bac4b259..e5a6df8d 100644 --- a/src/client_server.rs +++ b/src/client_server.rs @@ -4,7 +4,9 @@ use std::{ time::{Duration, SystemTime}, }; -use crate::{utils, ConduitResult, Database, Error, Ruma}; +use crate::{ + database::media::FileMeta, pdu::PduBuilder, utils, ConduitResult, Database, Error, Ruma, +}; use keys::{upload_signatures, upload_signing_keys}; use log::warn; @@ -3273,7 +3275,11 @@ pub fn get_content_route( _server_name: String, _media_id: String, ) -> ConduitResult { - if let Some((filename, content_type, file)) = db + if let Some(FileMeta { + filename, + content_type, + file, + }) = db .media .get(format!("mxc://{}/{}", body.server_name, body.media_id))? { @@ -3301,7 +3307,9 @@ pub fn get_content_thumbnail_route( _server_name: String, _media_id: String, ) -> ConduitResult { - if let Some((_, content_type, file)) = db.media.get_thumbnail( + if let Some(FileMeta { + content_type, file, .. + }) = db.media.get_thumbnail( format!("mxc://{}/{}", body.server_name, body.media_id), body.width .try_into() diff --git a/src/database.rs b/src/database.rs index 5a1ed0f6..536978ef 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,7 +1,7 @@ pub(self) mod account_data; pub(self) mod globals; pub(self) mod key_backups; -pub(self) mod media; +pub(crate) mod media; pub(self) mod rooms; pub(self) mod uiaa; pub(self) mod users; diff --git a/src/database/media.rs b/src/database/media.rs index cec74a62..e9dcb4a0 100644 --- a/src/database/media.rs +++ b/src/database/media.rs @@ -1,7 +1,11 @@ use crate::{utils, Error, Result}; use std::mem; -pub type FileMeta = (Option, String, Vec); +pub struct FileMeta { + pub filename: Option, + pub content_type: String, + pub file: Vec, +} pub struct Media { pub(super) mediaid_file: sled::Tree, // MediaId = MXC + WidthHeight + Filename + ContentType @@ -61,7 +65,11 @@ impl Media { })?) }; - Ok(Some((filename, content_type, file.to_vec()))) + Ok(Some(FileMeta { + filename, + content_type, + file: file.to_vec(), + })) } else { Ok(None) } @@ -107,7 +115,11 @@ impl Media { ) }; - Ok(Some((filename, content_type, file.to_vec()))) + Ok(Some(FileMeta { + filename, + content_type, + file: file.to_vec(), + })) } else if let Some(r) = self.mediaid_file.scan_prefix(&original_prefix).next() { // Generate a thumbnail let (key, file) = r?; @@ -154,7 +166,11 @@ impl Media { self.mediaid_file.insert(thumbnail_key, &*thumbnail_bytes)?; - Ok(Some((filename, content_type, thumbnail_bytes))) + Ok(Some(FileMeta { + filename, + content_type, + file: thumbnail_bytes.to_vec(), + })) } else { Ok(None) } diff --git a/src/lib.rs b/src/lib.rs index cd5029c1..5cd8d480 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ pub mod push_rules; mod ruma_wrapper; mod utils; -pub use database::Database; +pub use database::{media::FileMeta, Database}; pub use error::{Error, Result}; pub use pdu::PduEvent; pub use ruma_wrapper::{ConduitResult, Ruma, RumaResponse}; From d948f896c0e3e9ccb436015c8dbfe4cc9911156d Mon Sep 17 00:00:00 2001 From: Devin Ragotzy Date: Tue, 28 Jul 2020 09:00:23 -0400 Subject: [PATCH 4/5] Turn append_pdu args into struct PduBuilder --- src/client_server.rs | 545 +++++++++++++++++++++++------------------- src/database.rs | 2 +- src/database/rooms.rs | 23 +- src/pdu.rs | 12 + 4 files changed, 322 insertions(+), 260 deletions(-) diff --git a/src/client_server.rs b/src/client_server.rs index e5a6df8d..16bf73d5 100644 --- a/src/client_server.rs +++ b/src/client_server.rs @@ -477,13 +477,15 @@ pub fn deactivate_route( }; db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(event).expect("event is valid, we just created it"), - None, - Some(sender_id.to_string()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(event).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(sender_id.to_string()), + redacts: None, + }, &db.globals, )?; } @@ -662,30 +664,32 @@ pub fn set_displayname_route( for room_id in db.rooms.rooms_joined(&sender_id) { let room_id = room_id?; db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(ruma::events::room::member::MemberEventContent { - displayname: body.displayname.clone(), - ..serde_json::from_value::>( - db.rooms - .room_state_get(&room_id, &EventType::RoomMember, &sender_id.to_string())? - .ok_or_else(|| { - Error::bad_database( - "Tried to send displayname update for user not in the room.", - ) - })? - .content - .clone(), - ) - .expect("from_value::> can never fail") - .deserialize() - .map_err(|_| Error::bad_database("Database contains invalid PDU."))? - }) - .expect("event is valid, we just created it"), - None, - Some(sender_id.to_string()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(ruma::events::room::member::MemberEventContent { + displayname: body.displayname.clone(), + ..serde_json::from_value::>( + db.rooms + .room_state_get(&room_id, &EventType::RoomMember, &sender_id.to_string())? + .ok_or_else(|| { + Error::bad_database( + "Tried to send displayname update for user not in the room.", + ) + })? + .content + .clone(), + ) + .expect("from_value::> can never fail") + .deserialize() + .map_err(|_| Error::bad_database("Database contains invalid PDU."))? + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(sender_id.to_string()), + redacts: None, + }, &db.globals, )?; @@ -758,30 +762,32 @@ pub fn set_avatar_url_route( for room_id in db.rooms.rooms_joined(&sender_id) { let room_id = room_id?; db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(ruma::events::room::member::MemberEventContent { - avatar_url: body.avatar_url.clone(), - ..serde_json::from_value::>( - db.rooms - .room_state_get(&room_id, &EventType::RoomMember, &sender_id.to_string())? - .ok_or_else(|| { - Error::bad_database( - "Tried to send avatar url update for user not in the room.", - ) - })? - .content - .clone(), - ) - .expect("from_value::> can never fail") - .deserialize() - .map_err(|_| Error::bad_database("Database contains invalid PDU."))? - }) - .expect("event is valid, we just created it"), - None, - Some(sender_id.to_string()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(ruma::events::room::member::MemberEventContent { + avatar_url: body.avatar_url.clone(), + ..serde_json::from_value::>( + db.rooms + .room_state_get(&room_id, &EventType::RoomMember, &sender_id.to_string())? + .ok_or_else(|| { + Error::bad_database( + "Tried to send avatar url update for user not in the room.", + ) + })? + .content + .clone(), + ) + .expect("from_value::> can never fail") + .deserialize() + .map_err(|_| Error::bad_database("Database contains invalid PDU."))? + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(sender_id.to_string()), + redacts: None, + }, &db.globals, )?; @@ -1294,32 +1300,36 @@ pub fn create_room_route( // 1. The room create event db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomCreate, - serde_json::to_value(content).expect("event is valid, we just created it"), - None, - Some("".to_owned()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomCreate, + content: serde_json::to_value(content).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, &db.globals, )?; // 2. Let the room creator join db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(member::MemberEventContent { - membership: member::MembershipState::Join, - displayname: db.users.displayname(&sender_id)?, - avatar_url: db.users.avatar_url(&sender_id)?, - is_direct: body.is_direct, - third_party_invite: None, - }) - .expect("event is valid, we just created it"), - None, - Some(sender_id.to_string()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(member::MemberEventContent { + membership: member::MembershipState::Join, + displayname: db.users.displayname(&sender_id)?, + avatar_url: db.users.avatar_url(&sender_id)?, + is_direct: body.is_direct, + third_party_invite: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(sender_id.to_string()), + redacts: None, + }, &db.globals, )?; @@ -1359,72 +1369,82 @@ pub fn create_room_route( .expect("event is valid, we just created it") }; db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomPowerLevels, - power_levels_content, - None, - Some("".to_owned()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomPowerLevels, + content: power_levels_content, + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, &db.globals, )?; // 4. Events set by preset // 4.1 Join Rules db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomJoinRules, - match preset { - create_room::RoomPreset::PublicChat => serde_json::to_value( - join_rules::JoinRulesEventContent::new(join_rules::JoinRule::Public), - ) - .expect("event is valid, we just created it"), - // according to spec "invite" is the default - _ => serde_json::to_value(join_rules::JoinRulesEventContent::new( - join_rules::JoinRule::Invite, - )) - .expect("event is valid, we just created it"), + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomJoinRules, + content: match preset { + create_room::RoomPreset::PublicChat => serde_json::to_value( + join_rules::JoinRulesEventContent::new(join_rules::JoinRule::Public), + ) + .expect("event is valid, we just created it"), + // according to spec "invite" is the default + _ => serde_json::to_value(join_rules::JoinRulesEventContent::new( + join_rules::JoinRule::Invite, + )) + .expect("event is valid, we just created it"), + }, + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, }, - None, - Some("".to_owned()), - None, &db.globals, )?; // 4.2 History Visibility db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomHistoryVisibility, - serde_json::to_value(history_visibility::HistoryVisibilityEventContent::new( - history_visibility::HistoryVisibility::Shared, - )) - .expect("event is valid, we just created it"), - None, - Some("".to_owned()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomHistoryVisibility, + content: serde_json::to_value(history_visibility::HistoryVisibilityEventContent::new( + history_visibility::HistoryVisibility::Shared, + )) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, &db.globals, )?; // 4.3 Guest Access db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomGuestAccess, - match preset { - create_room::RoomPreset::PublicChat => serde_json::to_value( - guest_access::GuestAccessEventContent::new(guest_access::GuestAccess::Forbidden), - ) - .expect("event is valid, we just created it"), - _ => serde_json::to_value(guest_access::GuestAccessEventContent::new( - guest_access::GuestAccess::CanJoin, - )) - .expect("event is valid, we just created it"), + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomGuestAccess, + content: match preset { + create_room::RoomPreset::PublicChat => { + serde_json::to_value(guest_access::GuestAccessEventContent::new( + guest_access::GuestAccess::Forbidden, + )) + .expect("event is valid, we just created it") + } + _ => serde_json::to_value(guest_access::GuestAccessEventContent::new( + guest_access::GuestAccess::CanJoin, + )) + .expect("event is valid, we just created it"), + }, + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, }, - None, - Some("".to_owned()), - None, &db.globals, )?; @@ -1441,15 +1461,17 @@ pub fn create_room_route( } db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - event_type.clone(), - serde_json::from_str(content.get()).map_err(|_| { - Error::BadRequest(ErrorKind::BadJson, "Invalid initial_state content.") - })?, - None, - state_key.clone(), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: event_type.clone(), + content: serde_json::from_str(content.get()).map_err(|_| { + Error::BadRequest(ErrorKind::BadJson, "Invalid initial_state content.") + })?, + unsigned: None, + state_key: state_key.clone(), + redacts: None, + }, &db.globals, )?; } @@ -1457,33 +1479,38 @@ pub fn create_room_route( // 6. Events implied by name and topic if let Some(name) = &body.name { db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomName, - serde_json::to_value( - name::NameEventContent::new(name.clone()) - .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Name is invalid."))?, - ) - .expect("event is valid, we just created it"), - None, - Some("".to_owned()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomName, + content: serde_json::to_value( + name::NameEventContent::new(name.clone()).map_err(|_| { + Error::BadRequest(ErrorKind::InvalidParam, "Name is invalid.") + })?, + ) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, &db.globals, )?; } if let Some(topic) = &body.topic { db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomTopic, - serde_json::to_value(topic::TopicEventContent { - topic: topic.clone(), - }) - .expect("event is valid, we just created it"), - None, - Some("".to_owned()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomTopic, + content: serde_json::to_value(topic::TopicEventContent { + topic: topic.clone(), + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, &db.globals, )?; } @@ -1491,20 +1518,22 @@ pub fn create_room_route( // 7. Events implied by invite (and TODO: invite_3pid) for user in &body.invite { db.rooms.append_pdu( - room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(member::MemberEventContent { - membership: member::MembershipState::Invite, - displayname: db.users.displayname(&user)?, - avatar_url: db.users.avatar_url(&user)?, - is_direct: body.is_direct, - third_party_invite: None, - }) - .expect("event is valid, we just created it"), - None, - Some(user.to_string()), - None, + PduBuilder { + room_id: room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(member::MemberEventContent { + membership: member::MembershipState::Invite, + displayname: db.users.displayname(&user)?, + avatar_url: db.users.avatar_url(&user)?, + is_direct: body.is_direct, + third_party_invite: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(user.to_string()), + redacts: None, + }, &db.globals, )?; } @@ -1552,16 +1581,18 @@ pub fn redact_event_route( let sender_id = body.sender_id.as_ref().expect("user is authenticated"); let event_id = db.rooms.append_pdu( - body.room_id.clone(), - sender_id.clone(), - EventType::RoomRedaction, - serde_json::to_value(redaction::RedactionEventContent { - reason: body.reason.clone(), - }) - .expect("event is valid, we just created it"), - None, - None, - Some(body.event_id.clone()), + PduBuilder { + room_id: body.room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomRedaction, + content: serde_json::to_value(redaction::RedactionEventContent { + reason: body.reason.clone(), + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: None, + redacts: Some(body.event_id.clone()), + }, &db.globals, )?; @@ -1647,13 +1678,15 @@ pub fn join_room_by_id_route( }; db.rooms.append_pdu( - body.room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(event).expect("event is valid, we just created it"), - None, - Some(sender_id.to_string()), - None, + PduBuilder { + room_id: body.room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(event).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(sender_id.to_string()), + redacts: None, + }, &db.globals, )?; @@ -1724,13 +1757,15 @@ pub fn leave_room_route( event.membership = member::MembershipState::Leave; db.rooms.append_pdu( - body.room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(event).expect("event is valid, we just created it"), - None, - Some(sender_id.to_string()), - None, + PduBuilder { + room_id: body.room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(event).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(sender_id.to_string()), + redacts: None, + }, &db.globals, )?; @@ -1768,13 +1803,15 @@ pub fn kick_user_route( // TODO: reason db.rooms.append_pdu( - body.room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(event).expect("event is valid, we just created it"), - None, - Some(body.user_id.to_string()), - None, + PduBuilder { + room_id: body.room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(event).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(body.user_id.to_string()), + redacts: None, + }, &db.globals, )?; @@ -1859,13 +1896,15 @@ pub fn ban_user_route( )?; db.rooms.append_pdu( - body.room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(event).expect("event is valid, we just created it"), - None, - Some(body.user_id.to_string()), - None, + PduBuilder { + room_id: body.room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(event).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(body.user_id.to_string()), + redacts: None, + }, &db.globals, )?; @@ -1902,13 +1941,15 @@ pub fn unban_user_route( event.membership = ruma::events::room::member::MembershipState::Leave; db.rooms.append_pdu( - body.room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(event).expect("event is valid, we just created it"), - None, - Some(body.user_id.to_string()), - None, + PduBuilder { + room_id: body.room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(event).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(body.user_id.to_string()), + redacts: None, + }, &db.globals, )?; @@ -1942,20 +1983,22 @@ pub fn invite_user_route( if let invite_user::InvitationRecipient::UserId { user_id } = &body.recipient { db.rooms.append_pdu( - body.room_id.clone(), - sender_id.clone(), - EventType::RoomMember, - serde_json::to_value(member::MemberEventContent { - membership: member::MembershipState::Invite, - displayname: db.users.displayname(&user_id)?, - avatar_url: db.users.avatar_url(&user_id)?, - is_direct: None, - third_party_invite: None, - }) - .expect("event is valid, we just created it"), - None, - Some(user_id.to_string()), - None, + PduBuilder { + room_id: body.room_id.clone(), + sender: sender_id.clone(), + event_type: EventType::RoomMember, + content: serde_json::to_value(member::MemberEventContent { + membership: member::MembershipState::Invite, + displayname: db.users.displayname(&user_id)?, + avatar_url: db.users.avatar_url(&user_id)?, + is_direct: None, + third_party_invite: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(user_id.to_string()), + redacts: None, + }, &db.globals, )?; @@ -2327,18 +2370,20 @@ pub fn create_message_event_route( unsigned.insert("transaction_id".to_owned(), body.txn_id.clone().into()); let event_id = db.rooms.append_pdu( - body.room_id.clone(), - sender_id.clone(), - body.event_type.clone(), - serde_json::from_str( - body.json_body - .ok_or(Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))? - .get(), - ) - .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))?, - Some(unsigned), - None, - None, + PduBuilder { + room_id: body.room_id.clone(), + sender: sender_id.clone(), + event_type: body.event_type.clone(), + content: serde_json::from_str( + body.json_body + .ok_or(Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))? + .get(), + ) + .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))?, + unsigned: Some(unsigned), + state_key: None, + redacts: None, + }, &db.globals, )?; @@ -2395,13 +2440,15 @@ pub fn create_state_event_for_key_route( } let event_id = db.rooms.append_pdu( - body.room_id.clone(), - sender_id.clone(), - body.event_type.clone(), - content, - None, - Some(body.state_key.clone()), - None, + PduBuilder { + room_id: body.room_id.clone(), + sender: sender_id.clone(), + event_type: body.event_type.clone(), + content, + unsigned: None, + state_key: Some(body.state_key.clone()), + redacts: None, + }, &db.globals, )?; @@ -2696,7 +2743,7 @@ pub async fn sync_events_route( // Filter for possible heroes .filter_map(|u| u) { - if heroes.contains(&hero) || hero == sender_id.to_string() { + if heroes.contains(&hero) || hero == sender_id.as_str() { continue; } @@ -2796,7 +2843,7 @@ pub async fn sync_events_route( notification_count, }, timeline: sync_events::Timeline { - limited: false || joined_since_last_sync, + limited: joined_since_last_sync, prev_batch, events: room_events, }, @@ -2984,7 +3031,7 @@ pub async fn sync_events_route( { // Hang a few seconds so requests are not spammed // Stop hanging if new info arrives - let mut duration = body.timeout.unwrap_or(Duration::default()); + let mut duration = body.timeout.unwrap_or_default(); if duration.as_secs() > 30 { duration = Duration::from_secs(30); } diff --git a/src/database.rs b/src/database.rs index 536978ef..e3d003c3 100644 --- a/src/database.rs +++ b/src/database.rs @@ -125,7 +125,7 @@ impl Database { }) } - pub async fn watch(&self, user_id: &UserId, device_id: &DeviceId) -> () { + pub async fn watch(&self, user_id: &UserId, device_id: &DeviceId) { let mut userid_prefix = user_id.to_string().as_bytes().to_vec(); userid_prefix.push(0xff); let mut userdeviceid_prefix = userid_prefix.clone(); diff --git a/src/database/rooms.rs b/src/database/rooms.rs index ae0d0849..9ff11b89 100644 --- a/src/database/rooms.rs +++ b/src/database/rooms.rs @@ -2,7 +2,7 @@ mod edus; pub use edus::RoomEdus; -use crate::{utils, Error, PduEvent, Result}; +use crate::{pdu::PduBuilder, utils, Error, PduEvent, Result}; use log::error; use ruma::{ api::client::error::ErrorKind, @@ -250,18 +250,21 @@ impl Rooms { } /// Creates a new persisted data unit and adds it to a room. - #[allow(clippy::too_many_arguments, clippy::blocks_in_if_conditions)] + #[allow(clippy::blocks_in_if_conditions)] pub fn append_pdu( &self, - room_id: RoomId, - sender: UserId, - event_type: EventType, - content: serde_json::Value, - unsigned: Option>, - state_key: Option, - redacts: Option, + pdu_builder: PduBuilder, globals: &super::globals::Globals, ) -> Result { + let PduBuilder { + room_id, + sender, + event_type, + content, + unsigned, + state_key, + redacts, + } = pdu_builder; // TODO: Make sure this isn't called twice in parallel let prev_events = self.get_pdu_leaves(&room_id)?; @@ -623,7 +626,7 @@ impl Rooms { let mut first_pdu_id = prefix.clone(); first_pdu_id.extend_from_slice(&(since + 1).to_be_bytes()); - let mut last_pdu_id = prefix.clone(); + let mut last_pdu_id = prefix; last_pdu_id.extend_from_slice(&u64::MAX.to_be_bytes()); let user_id = user_id.clone(); diff --git a/src/pdu.rs b/src/pdu.rs index c1492970..b689a3ee 100644 --- a/src/pdu.rs +++ b/src/pdu.rs @@ -175,3 +175,15 @@ impl PduEvent { serde_json::from_value(json).expect("Raw::from_value always works") } } + +/// Build the start of a PDU in order to add it to the `Database`. +#[derive(Debug)] +pub struct PduBuilder { + pub room_id: RoomId, + pub sender: UserId, + pub event_type: EventType, + pub content: serde_json::Value, + pub unsigned: Option>, + pub state_key: Option, + pub redacts: Option, +} From b67372b11bb7e10a7150a444e4ec3dd4b8f385a2 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 29 Jul 2020 21:27:49 +0200 Subject: [PATCH 5/5] refactor: make all mods in database pub Now they can easily export their own structs --- src/database.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/database.rs b/src/database.rs index e3d003c3..47876695 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,10 +1,10 @@ -pub(self) mod account_data; -pub(self) mod globals; -pub(self) mod key_backups; -pub(crate) mod media; -pub(self) mod rooms; -pub(self) mod uiaa; -pub(self) mod users; +pub mod account_data; +pub mod globals; +pub mod key_backups; +pub mod media; +pub mod rooms; +pub mod uiaa; +pub mod users; use crate::{Error, Result}; use directories::ProjectDirs;