diff --git a/src/blog.rs b/src/blog.rs index 6acd57d..6ee1c43 100644 --- a/src/blog.rs +++ b/src/blog.rs @@ -118,6 +118,10 @@ impl Post { Self::create_url_mapping(&self.url, &self.uuid).await?; store::put_obj(&Self::uuid_to_post_key(&self.uuid), self).await } + + pub async fn delete_by_uuid(uuid: &str) -> MyResult<()> { + store::delete(&Self::uuid_to_post_key(uuid)).await + } } lazy_static! { @@ -342,4 +346,8 @@ impl PostContentCache { pub async fn save(&self) -> MyResult<()> { store::put_obj(&Self::uuid_to_cache_key(&self.uuid), self).await } + + pub async fn delete_by_uuid(uuid: &str) -> MyResult<()> { + store::delete(&Self::uuid_to_cache_key(uuid)).await + } } \ No newline at end of file diff --git a/src/sn.rs b/src/sn.rs index 39b4c64..8fef95f 100644 --- a/src/sn.rs +++ b/src/sn.rs @@ -11,6 +11,7 @@ use web_sys::*; pub fn build_routes(router: &mut Router) { router.add_route("/actions", &get_actions); router.add_route("/post", &create_or_update_post); + router.add_route("/delete", &delete_post); } macro_rules! verify_secret { @@ -54,6 +55,15 @@ async fn get_actions(_req: Request, url: Url) -> MyResult { }); if post_exists { + actions.push(Action { + label: "Delete".into(), + url: format!("{}/delete?secret={}", origin, CONFIG.secret.clone()), + verb: Verb::Post, + context: Context::Item, + content_types: vec![ContentType::Note], + access_type: Some(AccessType::Decrypted) + }); + actions.push(Action { label: "Open Post".into(), url: format!("{}/{}/", origin, post.unwrap().url), @@ -61,7 +71,7 @@ async fn get_actions(_req: Request, url: Url) -> MyResult { context: Context::Item, content_types: vec![ContentType::Note], access_type: None - }) + }); } let info = ActionsExtension { @@ -173,6 +183,19 @@ fn build_metadata(custom: Option, uuid: &str, title: &str) -> Me ret } +macro_rules! load_post_body { + ($data:ident, $req:expr) => { + let $data: ActionsPostData = serde_json::from_str( + &JsFuture::from($req.text().internal_err()?) + .await.internal_err()? + .as_string().ok_or(Error::BadRequest("Unable to parse POST body".into()))? + ).internal_err()?; + if $data.items.len() == 0 { + return Err(Error::BadRequest("At least one item must be supplied".into())); + } + }; +} + async fn create_or_update_post(req: Request, url: Url) -> MyResult { verify_secret!(url, params); if req.method() != "POST" { @@ -180,14 +203,7 @@ async fn create_or_update_post(req: Request, url: Url) -> MyResult { } // Load the information sent as POST body - let data: ActionsPostData = serde_json::from_str( - &JsFuture::from(req.text().internal_err()?) - .await.internal_err()? - .as_string().ok_or(Error::BadRequest("Unable to parse POST body".into()))? - ).internal_err()?; - if data.items.len() == 0 { - return Err(Error::BadRequest("At least one item must be supplied".into())); - } + load_post_body!(data, req); let uuid = data.items[0].uuid.clone(); let text = data.items[0].content.text.clone(); @@ -247,6 +263,28 @@ async fn create_or_update_post(req: Request, url: Url) -> MyResult { ).internal_err() } +async fn delete_post(req: Request, url: Url) -> MyResult { + verify_secret!(url, params); + if req.method() != "POST" { + return Err(Error::BadRequest("Unsupported method".into())); + } + + // Load the information sent as POST body + load_post_body!(data, req); + + let uuid = &data.items[0].uuid; + blog::PostsList::load().await.remove_post(uuid).await?; + blog::Post::delete_by_uuid(uuid).await?; + blog::PostContentCache::delete_by_uuid(uuid).await?; + + Response::new_with_opt_str_and_init( + None, + ResponseInit::new() + .status(200) + .headers(headers!().add_cors().as_ref()) + ).internal_err() +} + pub enum Verb { Show, Post, diff --git a/src/store.rs b/src/store.rs index 5878464..a5615de 100644 --- a/src/store.rs +++ b/src/store.rs @@ -12,6 +12,8 @@ extern "C" { fn kv_get(key: &str) -> Promise; #[wasm_bindgen(js_namespace = PAPRIKA, js_name = "put")] fn kv_put_str(key: &str, value: &str) -> Promise; + #[wasm_bindgen(js_namespace = PAPRIKA, js_name = "delete")] + fn kv_delete(key: &str) -> Promise; } // Returns empty string ("") if the key is not found @@ -37,4 +39,9 @@ pub async fn put_obj(key: &str, value: T) -> MyResult<()> { // For example, the user may want to manually edit the order in which posts appear pub async fn put_obj_pretty(key: &str, value: T) -> MyResult<()> { put_str(key, &serde_json::to_string_pretty(&value).internal_err()?).await +} + +pub async fn delete(key: &str) -> MyResult<()> { + JsFuture::from(kv_delete(key)).await.internal_err()?; + Ok(()) } \ No newline at end of file