diff --git a/model/task_cas_test.go b/model/task_cas_test.go index 052bf638..54ec7bda 100644 --- a/model/task_cas_test.go +++ b/model/task_cas_test.go @@ -45,6 +45,7 @@ func TestMain(m *testing.M) { &SubscriptionPlan{}, &SubscriptionOrder{}, &UserSubscription{}, + &UserOAuthBinding{}, &PerfMetric{}, ); err != nil { panic("failed to migrate: " + err.Error()) @@ -66,6 +67,7 @@ func truncateTables(t *testing.T) { DB.Exec("DELETE FROM subscription_orders") DB.Exec("DELETE FROM subscription_plans") DB.Exec("DELETE FROM user_subscriptions") + DB.Exec("DELETE FROM user_oauth_bindings") DB.Exec("DELETE FROM perf_metrics") }) } diff --git a/model/user.go b/model/user.go index a50fab0d..53f93b02 100644 --- a/model/user.go +++ b/model/user.go @@ -328,8 +328,12 @@ func HardDeleteUserById(id int) error { if id == 0 { return errors.New("id 为空!") } - err := DB.Unscoped().Delete(&User{}, "id = ?", id).Error - return err + return DB.Transaction(func(tx *gorm.DB) error { + if err := deleteUserOAuthBindingsByUserId(tx, id); err != nil { + return err + } + return tx.Unscoped().Delete(&User{}, "id = ?", id).Error + }) } func inviteUser(inviterId int) (err error) { @@ -589,8 +593,12 @@ func (user *User) HardDelete() error { if user.Id == 0 { return errors.New("id 为空!") } - err := DB.Unscoped().Delete(user).Error - return err + return DB.Transaction(func(tx *gorm.DB) error { + if err := deleteUserOAuthBindingsByUserId(tx, user.Id); err != nil { + return err + } + return tx.Unscoped().Delete(user).Error + }) } // ValidateAndFill check password & user status diff --git a/model/user_oauth_binding.go b/model/user_oauth_binding.go index 49216625..cc337995 100644 --- a/model/user_oauth_binding.go +++ b/model/user_oauth_binding.go @@ -10,9 +10,9 @@ import ( // UserOAuthBinding stores the binding relationship between users and custom OAuth providers type UserOAuthBinding struct { Id int `json:"id" gorm:"primaryKey"` - UserId int `json:"user_id" gorm:"not null;uniqueIndex:ux_user_provider"` // User ID - one binding per user per provider - ProviderId int `json:"provider_id" gorm:"not null;uniqueIndex:ux_user_provider;uniqueIndex:ux_provider_userid"` // Custom OAuth provider ID - ProviderUserId string `json:"provider_user_id" gorm:"type:varchar(256);not null;uniqueIndex:ux_provider_userid"` // User ID from OAuth provider - one OAuth account per provider + UserId int `json:"user_id" gorm:"not null;uniqueIndex:ux_user_provider"` // User ID - one binding per user per provider + ProviderId int `json:"provider_id" gorm:"not null;uniqueIndex:ux_user_provider;uniqueIndex:ux_provider_userid"` // Custom OAuth provider ID + ProviderUserId string `json:"provider_user_id" gorm:"type:varchar(256);not null;uniqueIndex:ux_provider_userid"` // User ID from OAuth provider - one OAuth account per provider CreatedAt time.Time `json:"created_at"` } @@ -134,9 +134,8 @@ func DeleteUserOAuthBinding(userId, providerId int) error { return DB.Where("user_id = ? AND provider_id = ?", userId, providerId).Delete(&UserOAuthBinding{}).Error } -// DeleteUserOAuthBindingsByUserId deletes all OAuth bindings for a user -func DeleteUserOAuthBindingsByUserId(userId int) error { - return DB.Where("user_id = ?", userId).Delete(&UserOAuthBinding{}).Error +func deleteUserOAuthBindingsByUserId(tx *gorm.DB, userId int) error { + return tx.Where("user_id = ?", userId).Delete(&UserOAuthBinding{}).Error } // GetBindingCountByProviderId returns the number of bindings for a provider