From bc57782bfe07ba17c38754c7ffe1ebb6106379c0 Mon Sep 17 00:00:00 2001 From: trisua Date: Thu, 17 Apr 2025 21:48:45 -0400 Subject: [PATCH] fix: delete user follows when deleting user --- crates/app/src/routes/api/v1/auth/social.rs | 6 +-- crates/core/src/database/auth.rs | 42 +++++++++++++++++++++ crates/core/src/database/user_warnings.rs | 2 +- crates/core/src/database/userfollows.rs | 42 ++++++++++++++++----- crates/core/src/model/auth.rs | 2 +- 5 files changed, 79 insertions(+), 15 deletions(-) diff --git a/crates/app/src/routes/api/v1/auth/social.rs b/crates/app/src/routes/api/v1/auth/social.rs index a951e5e..b9c91b5 100644 --- a/crates/app/src/routes/api/v1/auth/social.rs +++ b/crates/app/src/routes/api/v1/auth/social.rs @@ -20,7 +20,7 @@ pub async fn follow_request( if let Ok(userfollow) = data.get_userfollow_by_initiator_receiver(user.id, id).await { // delete - match data.delete_userfollow(userfollow.id, &user).await { + match data.delete_userfollow(userfollow.id, &user, false).await { Ok(_) => Json(ApiReturn { ok: true, message: "User unfollowed".to_string(), @@ -164,7 +164,7 @@ pub async fn block_request( if let Ok(userfollow) = data.get_userfollow_by_initiator_receiver(user.id, id).await { // automatically unfollow - match data.delete_userfollow(userfollow.id, &user).await { + match data.delete_userfollow(userfollow.id, &user, false).await { Ok(_) => Json(ApiReturn { ok: true, message: "User blocked".to_string(), @@ -176,7 +176,7 @@ pub async fn block_request( data.get_userfollow_by_receiver_initiator(user.id, id).await { // automatically unfollow - match data.delete_userfollow(userfollow.id, &user).await { + match data.delete_userfollow(userfollow.id, &user, false).await { Ok(_) => Json(ApiReturn { ok: true, message: "User blocked".to_string(), diff --git a/crates/core/src/database/auth.rs b/crates/core/src/database/auth.rs index b875e8b..af5c98a 100644 --- a/crates/core/src/database/auth.rs +++ b/crates/core/src/database/auth.rs @@ -226,6 +226,39 @@ impl DataManager { return Err(Error::DatabaseError(e.to_string())); } + // delete requests + let res = execute!( + &conn, + "DELETE FROM requests WHERE owner = $1", + &[&(id as i64)] + ); + + if let Err(e) = res { + return Err(Error::DatabaseError(e.to_string())); + } + + // delete warnings + let res = execute!( + &conn, + "DELETE FROM user_warnings WHERE receiver = $1", + &[&(id as i64)] + ); + + if let Err(e) = res { + return Err(Error::DatabaseError(e.to_string())); + } + + // delete blocks + let res = execute!( + &conn, + "DELETE FROM userblocks WHERE initiator = $1 OR receiver = $1", + &[&(id as i64)] + ); + + if let Err(e) = res { + return Err(Error::DatabaseError(e.to_string())); + } + // delete reactions // reactions counts will remain the same :) let res = execute!( @@ -245,6 +278,15 @@ impl DataManager { return Err(Error::DatabaseError(e.to_string())); } + // delete user follows... individually since it requires updating user counts + for follow in self.get_userfollows_by_receiver_all(id).await? { + self.delete_userfollow(follow.id, &user, true).await?; + } + + for follow in self.get_userfollows_by_initiator_all(id).await? { + self.delete_userfollow(follow.id, &user, true).await?; + } + // remove images let avatar = PathBufD::current().extend(&[ self.0.dirs.media.as_str(), diff --git a/crates/core/src/database/user_warnings.rs b/crates/core/src/database/user_warnings.rs index 4401d3d..73c59ee 100644 --- a/crates/core/src/database/user_warnings.rs +++ b/crates/core/src/database/user_warnings.rs @@ -26,7 +26,7 @@ impl DataManager { } } - auto_method!(get_user_warning_by_ip(&str)@get_user_warning_from_row -> "SELECT * FROM user_warning WHERE ip = $1" --name="user warning" --returns=UserWarning --cache-key-tmpl="atto.user_warning:{}"); + auto_method!(get_user_warning_by_ip(&str)@get_user_warning_from_row -> "SELECT * FROM user_warnings WHERE ip = $1" --name="user warning" --returns=UserWarning --cache-key-tmpl="atto.user_warning:{}"); /// Get all user warnings by user (paginated). /// diff --git a/crates/core/src/database/userfollows.rs b/crates/core/src/database/userfollows.rs index c80a2de..af477c5 100644 --- a/crates/core/src/database/userfollows.rs +++ b/crates/core/src/database/userfollows.rs @@ -196,7 +196,13 @@ impl DataManager { for userfollow in userfollows { let receiver = userfollow.receiver; - out.push((userfollow, self.get_user_by_id(receiver).await?)); + out.push(( + userfollow, + match self.get_user_by_id(receiver).await { + Ok(u) => u, + Err(_) => continue, + }, + )); } Ok(out) @@ -211,7 +217,13 @@ impl DataManager { for userfollow in userfollows { let initiator = userfollow.initiator; - out.push((userfollow, self.get_user_by_id(initiator).await?)); + out.push(( + userfollow, + match self.get_user_by_id(initiator).await { + Ok(u) => u, + Err(_) => continue, + }, + )); } Ok(out) @@ -272,12 +284,18 @@ impl DataManager { Ok(FollowResult::Followed) } - pub async fn delete_userfollow(&self, id: usize, user: &User) -> Result<()> { + pub async fn delete_userfollow( + &self, + id: usize, + user: &User, + is_deleting_user: bool, + ) -> Result<()> { let follow = self.get_userfollow_by_id(id).await?; if (user.id != follow.initiator) && (user.id != follow.receiver) && !user.permissions.check(FinePermission::MANAGE_FOLLOWS) + && !is_deleting_user { return Err(Error::NotAllowed); } @@ -299,14 +317,18 @@ impl DataManager { self.2.remove(format!("atto.userfollow:{}", id)).await; - // decr counts - self.decr_user_following_count(follow.initiator) - .await - .unwrap(); + // decr counts (if we aren't deleting the user OR the user id isn't the deleted user id) + if !is_deleting_user | (follow.initiator != user.id) { + self.decr_user_following_count(follow.initiator) + .await + .unwrap(); + } - self.decr_user_follower_count(follow.receiver) - .await - .unwrap(); + if !is_deleting_user | (follow.receiver != user.id) { + self.decr_user_follower_count(follow.receiver) + .await + .unwrap(); + } // return Ok(()) diff --git a/crates/core/src/model/auth.rs b/crates/core/src/model/auth.rs index 8d411b2..f26bc49 100644 --- a/crates/core/src/model/auth.rs +++ b/crates/core/src/model/auth.rs @@ -299,7 +299,7 @@ impl Notification { } } -#[derive(Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct UserFollow { pub id: usize, pub created: usize,