From dd4f8b6d58f523663502886fbc82df7b0115e33d Mon Sep 17 00:00:00 2001 From: trisua Date: Fri, 16 May 2025 16:20:24 -0400 Subject: [PATCH] add: purge/restore post api --- crates/app/src/langs/en-US.toml | 2 + crates/app/src/public/html/components.html | 19 ++++++++- crates/app/src/public/js/me.js | 42 +++++++++++++++++++ .../src/routes/api/v1/communities/posts.rs | 27 +++++++++++- crates/app/src/routes/api/v1/mod.rs | 8 +++- crates/core/src/database/posts.rs | 8 ++++ 6 files changed, 102 insertions(+), 4 deletions(-) diff --git a/crates/app/src/langs/en-US.toml b/crates/app/src/langs/en-US.toml index cfb4088..28ee298 100644 --- a/crates/app/src/langs/en-US.toml +++ b/crates/app/src/langs/en-US.toml @@ -17,6 +17,8 @@ version = "1.0.0" "general:link.stats" = "Stats" "general:action.save" = "Save" "general:action.delete" = "Delete" +"general:action.purge" = "Purge" +"general:action.restore" = "Restore" "general:action.accept" = "Accept" "general:action.back" = "Back" "general:action.report" = "Report" diff --git a/crates/app/src/public/html/components.html b/crates/app/src/public/html/components.html index 73cba83..472f1f6 100644 --- a/crates/app/src/public/html/components.html +++ b/crates/app/src/public/html/components.html @@ -382,6 +382,7 @@ and show_community and community.id != config.town_square or question %} > + {% if not post.is_deleted %} - {% endif %} + {% endif %} {% if is_helper and post.is_deleted %} + + + + {% endif %} {% endif %} {% endif %} diff --git a/crates/app/src/public/js/me.js b/crates/app/src/public/js/me.js index 9dc4578..12b06e7 100644 --- a/crates/app/src/public/js/me.js +++ b/crates/app/src/public/js/me.js @@ -62,6 +62,48 @@ }); }); + self.define("purge_post", async (_, id) => { + if ( + !(await trigger("atto::confirm", [ + "Are you sure you want to do this? This cannot be undone.", + ])) + ) { + return; + } + + fetch(`/api/v1/posts/${id}/purge`, { + method: "DELETE", + }) + .then((res) => res.json()) + .then((res) => { + trigger("atto::toast", [ + res.ok ? "success" : "error", + res.message, + ]); + }); + }); + + self.define("restore_post", async (_, id) => { + if ( + !(await trigger("atto::confirm", [ + "Are you sure you want to do this?", + ])) + ) { + return; + } + + fetch(`/api/v1/posts/${id}/restore`, { + method: "POST", + }) + .then((res) => res.json()) + .then((res) => { + trigger("atto::toast", [ + res.ok ? "success" : "error", + res.message, + ]); + }); + }); + self.define("react", async (_, element, asset, asset_type, is_like) => { await trigger("atto::debounce", ["reactions::toggle"]); fetch("/api/v1/reactions", { diff --git a/crates/app/src/routes/api/v1/communities/posts.rs b/crates/app/src/routes/api/v1/communities/posts.rs index b278adf..76bae9e 100644 --- a/crates/app/src/routes/api/v1/communities/posts.rs +++ b/crates/app/src/routes/api/v1/communities/posts.rs @@ -183,7 +183,7 @@ pub async fn delete_request( } } -pub async fn real_delete_request( +pub async fn purge_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, @@ -208,6 +208,31 @@ pub async fn real_delete_request( } } +pub async fn restore_request( + jar: CookieJar, + Extension(data): Extension, + Path(id): Path, +) -> impl IntoResponse { + let data = &(data.read().await).0; + let user = match get_user_from_token!(jar, data) { + Some(ua) => ua, + None => return Json(Error::NotAllowed.into()), + }; + + if !user.permissions.check(FinePermission::MANAGE_POSTS) { + return Json(Error::NotAllowed.into()); + } + + match data.fake_delete_post(id, user, false).await { + Ok(_) => Json(ApiReturn { + ok: true, + message: "Post restored".to_string(), + payload: (), + }), + Err(e) => Json(e.into()), + } +} + pub async fn update_content_request( jar: CookieJar, Extension(data): Extension, diff --git a/crates/app/src/routes/api/v1/mod.rs b/crates/app/src/routes/api/v1/mod.rs index 9d35aa8..51e0119 100644 --- a/crates/app/src/routes/api/v1/mod.rs +++ b/crates/app/src/routes/api/v1/mod.rs @@ -94,8 +94,12 @@ pub fn routes() -> Router { .route("/posts", post(communities::posts::create_request)) .route("/posts/{id}", delete(communities::posts::delete_request)) .route( - "/posts/{id}/real_delete", - delete(communities::posts::real_delete_request), + "/posts/{id}/purge", + delete(communities::posts::purge_request), + ) + .route( + "/posts/{id}/restore", + post(communities::posts::restore_request), ) .route( "/posts/{id}/repost", diff --git a/crates/core/src/database/posts.rs b/crates/core/src/database/posts.rs index 99bb4b8..3835797 100644 --- a/crates/core/src/database/posts.rs +++ b/crates/core/src/database/posts.rs @@ -178,6 +178,10 @@ impl DataManager { let mut seen_user_follow_statuses: HashMap<(usize, usize), bool> = HashMap::new(); for post in posts { + if post.is_deleted { + continue; + } + let owner = post.owner; if ignore_users.contains(&owner) { @@ -274,6 +278,10 @@ impl DataManager { let mut seen_user_follow_statuses: HashMap<(usize, usize), bool> = HashMap::new(); for post in posts { + if post.is_deleted { + continue; + } + let owner = post.owner; if ignore_users.contains(&owner) {