vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit 410ee9f1f7a9ad814fac94af8f2bb87fdc016f89
parent 538dc00234c9e6e27026b30ce13f19a14369aa95
Author: Daniel GarcĂ­a <dani-garcia@users.noreply.github.com>
Date:   Tue, 12 Jun 2018 23:01:14 +0200

Fixed case problems, hopefully this time for real

Diffstat:
Msrc/api/core/accounts.rs | 3---
Msrc/api/core/ciphers.rs | 1-
Msrc/util.rs | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 74 insertions(+), 14 deletions(-)

diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs @@ -6,8 +6,6 @@ use db::models::*; use api::{PasswordData, JsonResult, EmptyResult, JsonUpcase}; use auth::Headers; -use util; - use CONFIG; #[derive(Deserialize, Debug)] @@ -15,7 +13,6 @@ use CONFIG; struct RegisterData { Email: String, Key: String, - #[serde(deserialize_with = "util::upcase_deserialize")] Keys: Option<KeysData>, MasterPasswordHash: String, MasterPasswordHint: Option<String>, diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs @@ -363,7 +363,6 @@ fn post_collections_admin(uuid: String, data: JsonUpcase<CollectionsAdminData>, #[derive(Deserialize)] #[allow(non_snake_case)] struct ShareCipherData { - #[serde(deserialize_with = "util::upcase_deserialize")] Cipher: CipherData, CollectionIds: Vec<String>, } diff --git a/src/util.rs b/src/util.rs @@ -129,24 +129,88 @@ pub fn format_date(date: &NaiveDateTime) -> String { /// Deserialization methods /// -use std::collections::BTreeMap as Map; +use std::fmt; -use serde::de::{self, Deserialize, DeserializeOwned, Deserializer}; +use serde::de::{self, DeserializeOwned, Deserializer, MapAccess, SeqAccess, Visitor}; use serde_json::Value; +#[derive(PartialEq, Serialize, Deserialize)] +pub struct UpCase<T: DeserializeOwned> { + #[serde(deserialize_with = "upcase_deserialize")] + #[serde(flatten)] + pub data: T, +} + /// https://github.com/serde-rs/serde/issues/586 pub fn upcase_deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error> where T: DeserializeOwned, D: Deserializer<'de> { - let map = Map::<String, Value>::deserialize(deserializer)?; - let lower = map.into_iter().map(|(k, v)| (upcase_first(&k), v)).collect(); - T::deserialize(Value::Object(lower)).map_err(de::Error::custom) + let d = deserializer.deserialize_any(UpCaseVisitor)?; + T::deserialize(d).map_err(de::Error::custom) } -#[derive(PartialEq, Serialize, Deserialize)] -pub struct UpCase<T: DeserializeOwned> { - #[serde(deserialize_with = "upcase_deserialize")] - #[serde(flatten)] - pub data: T, +struct UpCaseVisitor; + +impl<'de> Visitor<'de> for UpCaseVisitor { + type Value = Value; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an object or an array") + } + + fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> + where A: MapAccess<'de> + { + use serde_json::Map; + let mut result_map = Map::<String, Value>::new(); + + while let Some((key, value)) = map.next_entry()? { + result_map.insert(upcase_first(key), upcase_value(&value)); + } + + Ok(Value::Object(result_map)) + } + + fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> + where A: SeqAccess<'de> { + let mut result_seq = Vec::<Value>::new(); + + while let Some(value) = seq.next_element()? { + result_seq.push(upcase_value(&value)); + } + + Ok(Value::Array(result_seq)) + } +} + +fn upcase_value(value: &Value) -> Value { + if let Some(map) = value.as_object() { + let mut new_value = json!({}); + + for (key, val) in map { + let processed_key = _process_key(key); + new_value[processed_key] = upcase_value(val); + } + new_value + + } else if let Some(array) = value.as_array() { + // Initialize array with null values + let mut new_value = json!(vec![Value::Null; array.len()]); + + for (index, val) in array.iter().enumerate() { + new_value[index] = upcase_value(val); + } + new_value + + } else { + value.clone() + } +} + +fn _process_key(key: &str) -> String { + match key.to_lowercase().as_ref() { + "ssn" => "SSN".into(), + _ => self::upcase_first(key) + } }