diff options
author | Vika <vika@fireburn.ru> | 2024-08-28 14:51:13 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2024-08-28 14:51:13 +0300 |
commit | e03ff3151878851af954aa2e9a17e7578873bbae (patch) | |
tree | 5f09b60194c96794e42599196ae6ad470a62938f /src | |
parent | 60becdedcdf78a7c643ad100bf95799b2d5b9625 (diff) | |
download | kittybox-e03ff3151878851af954aa2e9a17e7578873bbae.tar.zst |
Check validity of Micropub updates
In Kittybox, Micropub updates cannot modify UIDs, since UIDs are used as a primary key. Additional constraints may be added later, and perhaps I'll add a Storage method that would check backend-specific constraints.
Diffstat (limited to 'src')
-rw-r--r-- | src/micropub/mod.rs | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/src/micropub/mod.rs b/src/micropub/mod.rs index 944506d..9838e5a 100644 --- a/src/micropub/mod.rs +++ b/src/micropub/mod.rs @@ -360,6 +360,47 @@ pub struct MicropubUpdate { pub delete: Option<MicropubPropertyDeletion>, } impl MicropubUpdate { + pub fn check_validity(&self) -> Result<(), MicropubError> { + if let Some(add) = &self.add { + if add.iter().map(|(k, _)| k.as_str()).any(|k| { + k.to_lowercase().as_str() == "uid" + }) { + return Err(MicropubError { + error: ErrorKind::InvalidRequest, + error_description: "Update cannot modify the post UID".to_owned() + }); + } + } + if let Some(replace) = &self.replace { + if replace.iter().map(|(k, v)| k.as_str()).any(|k| { + k.to_lowercase().as_str() == "uid" + }) { + return Err(MicropubError { + error: ErrorKind::InvalidRequest, + error_description: "Update cannot modify the post UID".to_owned() + }); + } + } + let iter = match &self.delete { + Some(MicropubPropertyDeletion::Properties(keys)) => { + Some(Box::new(keys.iter().map(|k| k.as_str())) as Box<dyn Iterator<Item = &str>>) + }, + Some(MicropubPropertyDeletion::Values(map)) => { + Some(Box::new(map.iter().map(|(k, _)| k.as_str())) as Box<dyn Iterator<Item = &str>>) + }, + None => None, + }; + if let Some(mut iter) = iter { + if iter.any(|k| k.to_lowercase().as_str() == "uid") { + return Err(MicropubError { + error: ErrorKind::InvalidRequest, + error_description: "Update cannot modify the post UID".to_owned() + }); + } + } + Ok(()) + } + /// 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 { @@ -458,14 +499,17 @@ async fn post_action<D: Storage, A: AuthBackend>( }); } - db.update_post( - &action.url, - action.update.ok_or(MicropubError { + let update = if let Some(update) = action.update { + update + } else { + return Err(MicropubError { error: ErrorKind::InvalidRequest, error_description: "Update request is not set.".to_owned(), - })? - ) - .await? + }) + }; + + update.check_validity()?; + db.update_post(&action.url, update).await?; } } |