Fix user deletion to update more tables (#5351)

* wip: fix user delete

* add wrap_errs

* delete more rows in user deletion

* sqlx prepare
This commit is contained in:
aecsocket
2026-02-12 11:37:40 +00:00
committed by GitHub
parent 76ba11d966
commit e7eb4899a1
14 changed files with 334 additions and 102 deletions

View File

@@ -7,6 +7,7 @@ use crate::database::redis::RedisPool;
use crate::database::{PgTransaction, models};
use crate::models::billing::ChargeStatus;
use crate::models::users::Badges;
use crate::util::error::Context;
use ariadne::ids::base62_impl::{parse_base62, to_base62};
use chrono::{DateTime, Utc};
use dashmap::DashMap;
@@ -504,12 +505,15 @@ impl DBUser {
id: DBUserId,
transaction: &mut PgTransaction<'_>,
redis: &RedisPool,
) -> Result<Option<()>, DatabaseError> {
let user = Self::get_id(id, &mut *transaction, redis).await?;
) -> Result<Option<()>, eyre::Report> {
let user = Self::get_id(id, &mut *transaction, redis)
.await
.wrap_err("failed to get user by ID")?;
if let Some(delete_user) = user {
DBUser::clear_caches(&[(id, Some(delete_user.username))], redis)
.await?;
.await
.wrap_err("failed to clear caches")?;
let deleted_user: DBUserId =
crate::models::users::DELETED_USER.into();
@@ -524,7 +528,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update team_members owner")?;
sqlx::query!(
"
@@ -536,7 +541,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update versions author_id")?;
sqlx::query!(
"
@@ -548,7 +554,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update shared_instances owner_id")?;
use futures::TryStreamExt;
let notifications: Vec<i64> = sqlx::query!(
@@ -561,7 +568,8 @@ impl DBUser {
.fetch(&mut *transaction)
.map_ok(|m| m.id)
.try_collect::<Vec<i64>>()
.await?;
.await
.wrap_err("failed to fetch notifications")?;
sqlx::query!(
"
@@ -571,7 +579,8 @@ impl DBUser {
&notifications
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete notifications_actions")?;
sqlx::query!(
"
@@ -581,7 +590,8 @@ impl DBUser {
id as DBUserId
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete notifications_deliveries")?;
sqlx::query!(
"
@@ -591,7 +601,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete notifications")?;
let user_collections = sqlx::query!(
"
@@ -604,11 +615,13 @@ impl DBUser {
.fetch(&mut *transaction)
.map_ok(|x| DBCollectionId(x.id))
.try_collect::<Vec<_>>()
.await?;
.await
.wrap_err("failed to fetch user collections")?;
for collection_id in user_collections {
models::DBCollection::remove(collection_id, transaction, redis)
.await?;
.await
.wrap_err("failed to remove collection")?;
}
let report_threads = sqlx::query!(
@@ -623,10 +636,13 @@ impl DBUser {
.fetch(&mut *transaction)
.map_ok(|x| DBThreadId(x.id))
.try_collect::<Vec<_>>()
.await?;
.await
.wrap_err("failed to fetch report threads")?;
for thread_id in report_threads {
models::DBThread::remove_full(thread_id, transaction).await?;
models::DBThread::remove_full(thread_id, transaction)
.await
.wrap_err("failed to remove thread")?;
}
sqlx::query!(
@@ -637,7 +653,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete reports")?;
sqlx::query!(
"
@@ -649,7 +666,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update reports user_id")?;
sqlx::query!(
"
@@ -659,7 +677,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete mod_follows")?;
sqlx::query!(
"
@@ -669,29 +688,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
sqlx::query!(
"
DELETE FROM payouts_values
WHERE user_id = $1
",
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
sqlx::query!(
"
UPDATE payouts
SET user_id = $1
WHERE user_id = $2
",
deleted_user as DBUserId,
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete team_members")?;
sqlx::query!(
r#"
@@ -703,7 +701,8 @@ impl DBUser {
deleted_user as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update threads_messages")?;
sqlx::query!(
"
@@ -713,7 +712,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete threads_members")?;
sqlx::query!(
"
@@ -725,7 +725,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update uploaded_images owner_id")?;
sqlx::query!(
"
@@ -735,7 +736,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete sessions")?;
sqlx::query!(
"
@@ -745,7 +747,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete pats")?;
sqlx::query!(
"
@@ -755,7 +758,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete friends")?;
sqlx::query!(
"
@@ -766,7 +770,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update affiliate_codes created_by")?;
sqlx::query!(
"
@@ -775,7 +780,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete affiliate_codes")?;
sqlx::query!(
"
@@ -786,7 +792,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update payouts_values user_id")?;
sqlx::query!(
"
@@ -795,7 +802,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete payouts_values_notifications")?;
sqlx::query!(
"
@@ -807,21 +815,28 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update charges user_id")?;
let open_subscriptions =
DBUserSubscription::get_all_user(id, &mut *transaction).await?;
DBUserSubscription::get_all_user(id, &mut *transaction)
.await
.wrap_err("failed to get user subscriptions")?;
for x in open_subscriptions {
let charge =
DBCharge::get_open_subscription(x.id, &mut *transaction)
.await?;
.await
.wrap_err("failed to get open subscription charge")?;
if let Some(mut charge) = charge {
charge.status = ChargeStatus::Cancelled;
charge.due = Utc::now();
charge.user_id = deleted_user;
charge.upsert(transaction).await?;
charge
.upsert(transaction)
.await
.wrap_err("failed to upsert charge")?;
}
}
@@ -835,7 +850,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to update users_subscriptions user_id")?;
sqlx::query!(
"
@@ -845,7 +861,8 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete user_backup_codes")?;
sqlx::query!(
"
@@ -855,7 +872,113 @@ impl DBUser {
id as DBUserId,
)
.execute(&mut *transaction)
.await?;
.await
.wrap_err("failed to delete user")?;
sqlx::query!(
"
DELETE FROM oauth_client_authorizations
WHERE user_id = $1
",
id as DBUserId,
)
.execute(&mut *transaction)
.await
.wrap_err("failed to delete oauth_client_authorizations")?;
sqlx::query!(
"
DELETE FROM shared_instance_users
WHERE user_id = $1
",
id as DBUserId,
)
.execute(&mut *transaction)
.await
.wrap_err("failed to delete shared_instance_users")?;
sqlx::query!(
"
DELETE FROM shared_instance_invited_users
WHERE invited_user_id = $1
",
id as DBUserId,
)
.execute(&mut *transaction)
.await
.wrap_err("failed to delete shared_instance_invited_users")?;
sqlx::query!(
"
UPDATE users_redeemals
SET user_id = $1
WHERE user_id = $2
",
deleted_user as DBUserId,
id as DBUserId,
)
.execute(&mut *transaction)
.await
.wrap_err("failed to delete users_redeemals")?;
sqlx::query!(
"
UPDATE users_compliance
SET user_id = $1
WHERE user_id = $2
",
deleted_user as DBUserId,
id as DBUserId,
)
.execute(&mut *transaction)
.await
.wrap_err("failed to delete users_compliance")?;
sqlx::query!(
"
DELETE FROM user_limits
WHERE user_id = $1
",
id as DBUserId,
)
.execute(&mut *transaction)
.await
.wrap_err("failed to delete user_limits")?;
sqlx::query!(
"
DELETE FROM users_notifications_preferences
WHERE user_id = $1
",
id as DBUserId,
)
.execute(&mut *transaction)
.await
.wrap_err("failed to delete users_notifications_preferences")?;
sqlx::query!(
"
DELETE FROM moderation_locks
WHERE moderator_id = $1
",
id as DBUserId,
)
.execute(&mut *transaction)
.await
.wrap_err("failed to delete moderation_locks")?;
sqlx::query!(
"
UPDATE oauth_clients
SET created_by = $1
WHERE created_by = $2
",
deleted_user as DBUserId,
id as DBUserId,
)
.execute(&mut *transaction)
.await
.wrap_err("failed to update oauth_clients created_by")?;
Ok(Some(()))
} else {