From b6d721374f970cca912477a3972bb857758d983d Mon Sep 17 00:00:00 2001 From: Devin Ragotzy Date: Wed, 18 Nov 2020 08:36:12 -0500 Subject: [PATCH] Have Media db return optional content_type, conversion fixes --- src/client_server/media.rs | 8 ++---- src/client_server/membership.rs | 3 +-- src/database/media.rs | 44 +++++++++++++++++++-------------- src/database/rooms.rs | 6 ++--- src/utils.rs | 17 +++++++++++++ 5 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/client_server/media.rs b/src/client_server/media.rs index 0c23488..e6bd182 100644 --- a/src/client_server/media.rs +++ b/src/client_server/media.rs @@ -66,7 +66,7 @@ pub async fn get_content_route( { Ok(get_content::Response { file, - content_type: Some(content_type), + content_type, content_disposition: filename, } .into()) @@ -116,11 +116,7 @@ pub async fn get_content_thumbnail_route( .try_into() .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Width is invalid."))?, )? { - Ok(get_content_thumbnail::Response { - file, - content_type: Some(content_type), - } - .into()) + Ok(get_content_thumbnail::Response { file, content_type }.into()) } else if &*body.server_name != db.globals.server_name() && body.allow_remote { let get_thumbnail_response = server_server::send_request( &db.globals, diff --git a/src/client_server/membership.rs b/src/client_server/membership.rs index 849fb7e..47fcde1 100644 --- a/src/client_server/membership.rs +++ b/src/client_server/membership.rs @@ -510,8 +510,7 @@ async fn join_room_by_id_helper( .expect("event is valid, we just created it"), ); - // TODO fixup CanonicalJsonValue - // use that instead of serde_json::Map... maybe? + // Convert `serde_json;:Value` to `CanonicalJsonObj` for hashing/signing let mut canon_json_stub: BTreeMap<_, ruma::signatures::CanonicalJsonValue> = serde_json::from_value(join_event_stub_value).expect("json Value is canonical JSON"); diff --git a/src/database/media.rs b/src/database/media.rs index bfc6207..89d48e1 100644 --- a/src/database/media.rs +++ b/src/database/media.rs @@ -5,7 +5,7 @@ use std::mem; pub struct FileMeta { pub filename: Option, - pub content_type: String, + pub content_type: Option, pub file: Vec, } @@ -83,12 +83,14 @@ impl Media { let (key, file) = r?; let mut parts = key.rsplit(|&b| b == 0xff); - let content_type = utils::string_from_bytes( - parts - .next() - .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?, - ) - .map_err(|_| Error::bad_database("Content type in mediaid_file is invalid unicode."))?; + let content_type = parts + .next() + .map(|bytes| { + Ok::<_, Error>(utils::string_from_bytes(bytes).map_err(|_| { + Error::bad_database("Content type in mediaid_file is invalid unicode.") + })?) + }) + .transpose()?; let filename_bytes = parts .next() @@ -158,12 +160,14 @@ impl Media { let (key, file) = r?; let mut parts = key.rsplit(|&b| b == 0xff); - let content_type = utils::string_from_bytes( - parts - .next() - .ok_or_else(|| Error::bad_database("Invalid Media ID in db"))?, - ) - .map_err(|_| Error::bad_database("Content type in mediaid_file is invalid unicode."))?; + let content_type = parts + .next() + .map(|bytes| { + Ok::<_, Error>(utils::string_from_bytes(bytes).map_err(|_| { + Error::bad_database("Content type in mediaid_file is invalid unicode.") + })?) + }) + .transpose()?; let filename_bytes = parts .next() @@ -189,12 +193,14 @@ impl Media { let (key, file) = r?; let mut parts = key.rsplit(|&b| b == 0xff); - let content_type = utils::string_from_bytes( - parts - .next() - .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?, - ) - .map_err(|_| Error::bad_database("Content type in mediaid_file is invalid unicode."))?; + let content_type = parts + .next() + .map(|bytes| { + Ok::<_, Error>(utils::string_from_bytes(bytes).map_err(|_| { + Error::bad_database("Content type in mediaid_file is invalid unicode.") + })?) + }) + .transpose()?; let filename_bytes = parts .next() diff --git a/src/database/rooms.rs b/src/database/rooms.rs index 3d5b890..a95587c 100644 --- a/src/database/rooms.rs +++ b/src/database/rooms.rs @@ -499,7 +499,6 @@ impl Rooms { Ok(()) } - #[allow(clippy::too_many_arguments)] /// Creates a new persisted data unit and adds it to a room. /// /// By this point the incoming event should be fully authenticated, no auth happens @@ -856,9 +855,8 @@ impl Rooms { }; // Hash and sign - let mut pdu_json: BTreeMap = - serde_json::from_value(serde_json::json!(&pdu)) - .expect("event is valid, we just created it"); + let mut pdu_json = + utils::to_canonical_object(&pdu).expect("event is valid, we just created it"); pdu_json.remove("event_id"); diff --git a/src/utils.rs b/src/utils.rs index edcf48a..c82e6fe 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,7 @@ 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, @@ -94,3 +95,19 @@ pub fn common_elements( .all(|b| b) })) } + +/// Fallible conversion from any value that implements `Serialize` to a `CanonicalJsonObject`. +/// +/// `value` must serialize to an `serde_json::Value::Object`. +pub fn to_canonical_object( + value: T, +) -> Result { + use serde::ser::Error; + + match serde_json::to_value(value).map_err(CanonicalJsonError::SerDe)? { + serde_json::Value::Object(map) => try_from_json_map(map), + _ => Err(CanonicalJsonError::SerDe(serde_json::Error::custom( + "Value must be an object", + ))), + } +}