fix: delete user follows when deleting user

This commit is contained in:
trisua 2025-04-17 21:48:45 -04:00
parent f161e0b176
commit bc57782bfe
5 changed files with 79 additions and 15 deletions

View file

@ -20,7 +20,7 @@ pub async fn follow_request(
if let Ok(userfollow) = data.get_userfollow_by_initiator_receiver(user.id, id).await { if let Ok(userfollow) = data.get_userfollow_by_initiator_receiver(user.id, id).await {
// delete // delete
match data.delete_userfollow(userfollow.id, &user).await { match data.delete_userfollow(userfollow.id, &user, false).await {
Ok(_) => Json(ApiReturn { Ok(_) => Json(ApiReturn {
ok: true, ok: true,
message: "User unfollowed".to_string(), 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 if let Ok(userfollow) = data.get_userfollow_by_initiator_receiver(user.id, id).await
{ {
// automatically unfollow // automatically unfollow
match data.delete_userfollow(userfollow.id, &user).await { match data.delete_userfollow(userfollow.id, &user, false).await {
Ok(_) => Json(ApiReturn { Ok(_) => Json(ApiReturn {
ok: true, ok: true,
message: "User blocked".to_string(), message: "User blocked".to_string(),
@ -176,7 +176,7 @@ pub async fn block_request(
data.get_userfollow_by_receiver_initiator(user.id, id).await data.get_userfollow_by_receiver_initiator(user.id, id).await
{ {
// automatically unfollow // automatically unfollow
match data.delete_userfollow(userfollow.id, &user).await { match data.delete_userfollow(userfollow.id, &user, false).await {
Ok(_) => Json(ApiReturn { Ok(_) => Json(ApiReturn {
ok: true, ok: true,
message: "User blocked".to_string(), message: "User blocked".to_string(),

View file

@ -226,6 +226,39 @@ impl DataManager {
return Err(Error::DatabaseError(e.to_string())); 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 // delete reactions
// reactions counts will remain the same :) // reactions counts will remain the same :)
let res = execute!( let res = execute!(
@ -245,6 +278,15 @@ impl DataManager {
return Err(Error::DatabaseError(e.to_string())); 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 // remove images
let avatar = PathBufD::current().extend(&[ let avatar = PathBufD::current().extend(&[
self.0.dirs.media.as_str(), self.0.dirs.media.as_str(),

View file

@ -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). /// Get all user warnings by user (paginated).
/// ///

View file

@ -196,7 +196,13 @@ impl DataManager {
for userfollow in userfollows { for userfollow in userfollows {
let receiver = userfollow.receiver; 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) Ok(out)
@ -211,7 +217,13 @@ impl DataManager {
for userfollow in userfollows { for userfollow in userfollows {
let initiator = userfollow.initiator; 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) Ok(out)
@ -272,12 +284,18 @@ impl DataManager {
Ok(FollowResult::Followed) 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?; let follow = self.get_userfollow_by_id(id).await?;
if (user.id != follow.initiator) if (user.id != follow.initiator)
&& (user.id != follow.receiver) && (user.id != follow.receiver)
&& !user.permissions.check(FinePermission::MANAGE_FOLLOWS) && !user.permissions.check(FinePermission::MANAGE_FOLLOWS)
&& !is_deleting_user
{ {
return Err(Error::NotAllowed); return Err(Error::NotAllowed);
} }
@ -299,14 +317,18 @@ impl DataManager {
self.2.remove(format!("atto.userfollow:{}", id)).await; self.2.remove(format!("atto.userfollow:{}", id)).await;
// decr counts // 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) self.decr_user_following_count(follow.initiator)
.await .await
.unwrap(); .unwrap();
}
if !is_deleting_user | (follow.receiver != user.id) {
self.decr_user_follower_count(follow.receiver) self.decr_user_follower_count(follow.receiver)
.await .await
.unwrap(); .unwrap();
}
// return // return
Ok(()) Ok(())

View file

@ -299,7 +299,7 @@ impl Notification {
} }
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct UserFollow { pub struct UserFollow {
pub id: usize, pub id: usize,
pub created: usize, pub created: usize,