From 67e4e83d1cbf984f4a801e7245a2aeec66efe522 Mon Sep 17 00:00:00 2001 From: Vika Date: Wed, 28 Aug 2024 14:17:24 +0300 Subject: Make Micropub update logic self-contained This allows for a separation of concerns between database backends and Micropub, unless such backend have special requirements, like the file backend storing children of a feed in an array. --- src/database/file/mod.rs | 4 +++- src/database/postgres/mod.rs | 34 +--------------------------------- src/micropub/mod.rs | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/database/file/mod.rs b/src/database/file/mod.rs index 10d6079..cf7380f 100644 --- a/src/database/file/mod.rs +++ b/src/database/file/mod.rs @@ -466,7 +466,9 @@ impl Storage for FileStorage { file.read_to_string(&mut content).await?; let json: serde_json::Value = serde_json::from_str(&content)?; drop(file); - // Apply the editing algorithms + // Apply the editing algorithms. We can't use the stock + // `update.apply` function due to special requirements of + // the file backend, so we're implementing our own. let new_json = modify_post(&json, update)?; temp.write_all(new_json.to_string().as_bytes()).await?; diff --git a/src/database/postgres/mod.rs b/src/database/postgres/mod.rs index 83e04c7..27ec51c 100644 --- a/src/database/postgres/mod.rs +++ b/src/database/postgres/mod.rs @@ -202,39 +202,7 @@ WHERE "The specified post wasn't found in the database." ))?; - if let Some(MicropubPropertyDeletion::Properties(ref delete)) = update.delete { - if let Some(props) = post["properties"].as_object_mut() { - for key in delete { - props.remove(key); - } - } - } else if let Some(MicropubPropertyDeletion::Values(ref delete)) = update.delete { - if let Some(props) = post["properties"].as_object_mut() { - for (key, values) in delete { - if let Some(prop) = props.get_mut(key).and_then(serde_json::Value::as_array_mut) { - prop.retain(|v| { values.iter().all(|i| i != v) }) - } - } - } - } - if let Some(replace) = update.replace { - if let Some(props) = post["properties"].as_object_mut() { - for (key, value) in replace { - props.insert(key, serde_json::Value::Array(value)); - } - } - } - if let Some(add) = update.add { - if let Some(props) = post["properties"].as_object_mut() { - for (key, value) in add { - if let Some(prop) = props.get_mut(&key).and_then(serde_json::Value::as_array_mut) { - prop.extend_from_slice(value.as_slice()); - } else { - props.insert(key, serde_json::Value::Array(value)); - } - } - } - } + update.apply(&mut post); sqlx::query("UPDATE kittybox.mf2_json SET mf2 = $2 WHERE uid = $1") .bind(uid) diff --git a/src/micropub/mod.rs b/src/micropub/mod.rs index 8f95085..944506d 100644 --- a/src/micropub/mod.rs +++ b/src/micropub/mod.rs @@ -358,7 +358,44 @@ pub struct MicropubUpdate { pub add: Option>>, #[serde(skip_serializing_if = "Option::is_none")] pub delete: Option, - +} +impl MicropubUpdate { + /// Update a specified MF2-JSON document with this update. + pub fn apply(self, post: &mut serde_json::Value) { + if let Some(MicropubPropertyDeletion::Properties(ref delete)) = self.delete { + if let Some(props) = post["properties"].as_object_mut() { + for key in delete { + props.remove(key); + } + } + } else if let Some(MicropubPropertyDeletion::Values(ref delete)) = self.delete { + if let Some(props) = post["properties"].as_object_mut() { + for (key, values) in delete { + if let Some(prop) = props.get_mut(key).and_then(serde_json::Value::as_array_mut) { + prop.retain(|v| { values.iter().all(|i| i != v) }) + } + } + } + } + if let Some(replace) = self.replace { + if let Some(props) = post["properties"].as_object_mut() { + for (key, value) in replace { + props.insert(key, serde_json::Value::Array(value)); + } + } + } + if let Some(add) = self.add { + if let Some(props) = post["properties"].as_object_mut() { + for (key, value) in add { + if let Some(prop) = props.get_mut(&key).and_then(serde_json::Value::as_array_mut) { + prop.extend_from_slice(value.as_slice()); + } else { + props.insert(key, serde_json::Value::Array(value)); + } + } + } + } + } } impl From for MicropubAction { -- cgit 1.4.1