diff options
-rw-r--r-- | src/database/memory.rs | 25 | ||||
-rw-r--r-- | src/database/mod.rs | 11 | ||||
-rw-r--r-- | src/frontend/mod.rs | 6 |
3 files changed, 20 insertions, 22 deletions
diff --git a/src/database/memory.rs b/src/database/memory.rs index 5e2ad52..786466c 100644 --- a/src/database/memory.rs +++ b/src/database/memory.rs @@ -43,11 +43,10 @@ impl Storage for MemoryStorage { async fn put_post(&self, post: &'_ serde_json::Value, _user: &'_ str) -> Result<()> { let mapping = &mut self.mapping.write().await; - let key: &str; - match post["properties"]["uid"][0].as_str() { - Some(uid) => key = uid, + let key: &str = match post["properties"]["uid"][0].as_str() { + Some(uid) => uid, None => return Err(StorageError::new(ErrorKind::Other, "post doesn't have a UID")) - } + }; mapping.insert(key.to_string(), post.clone()); if post["properties"]["url"].is_array() { for url in post["properties"]["url"].as_array().unwrap().iter().map(|i| i.as_str().unwrap().to_string()) { @@ -110,12 +109,11 @@ impl Storage for MemoryStorage { } for (k, v) in remove_values { let k = &k; - let props; - if k == "children" { - props = &mut post; + let props = if k == "children" { + &mut post } else { - props = &mut post["properties"]; - } + &mut post["properties"] + }; v.iter().for_each(|v| { if let Some(vec) = props[k].as_array_mut() { if let Some(index) = vec.iter().position(|w| w == v) { @@ -125,12 +123,11 @@ impl Storage for MemoryStorage { }); } for (k, v) in add_keys { - let props; - if k == "children" { - props = &mut post; + let props = if k == "children" { + &mut post } else { - props = &mut post["properties"]; - } + &mut post["properties"] + }; let k = &k; if let Some(prop) = props[k].as_array_mut() { if k == "children" { diff --git a/src/database/mod.rs b/src/database/mod.rs index b9a8652..6bf5409 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -209,11 +209,11 @@ pub trait Storage: std::fmt::Debug + Clone + Send + Sync { /// Modify a post using an update object as defined in the Micropub spec. /// - /// Note to implementors: the update operation MUST be atomic OR MUST lock the database - /// to prevent two clients overwriting each other's changes. - /// - /// You can assume concurrent updates will never contradict each other, since that will be dumb. - /// The last update always wins. + /// Note to implementors: the update operation MUST be atomic and + /// SHOULD lock the database to prevent two clients overwriting + /// each other's changes or simply corrupting something. Rejecting + /// is allowed in case of concurrent updates if waiting for a lock + /// cannot be done. async fn update_post(&self, url: &'_ str, update: serde_json::Value) -> Result<()>; /// Get a list of channels available for the user represented by the URL `user` to write to. @@ -323,6 +323,7 @@ mod tests { } /// Note: this is merely a smoke check and is in no way comprehensive. + // TODO updates for feeds must update children using special logic async fn test_update<Backend: Storage>(backend: Backend) { let post: serde_json::Value = json!({ "type": ["h-entry"], diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 106d839..3c3072d 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -1,6 +1,6 @@ use std::convert::TryInto; use crate::database::Storage; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use futures_util::TryFutureExt; use warp::{http::StatusCode, Filter, host::Authority, path::FullPath}; @@ -234,8 +234,8 @@ pub fn homepage<D: Storage>(db: D, endpoints: IndiewebEndpoints) -> impl Filter< .and(crate::util::require_host()) .and(warp::query()) .and_then(|db: D, host: Authority, q: QueryParams| async move { - let path = format!("https://{}/", host.to_string()); - let feed_path = format!("https://{}/feeds/main", host.to_string()); + let path = format!("https://{}/", host); + let feed_path = format!("https://{}/feeds/main", host); match tokio::try_join!( get_post_from_database(&db, &path, None, &None), |