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:
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)
+ }
}