fix(oauth): enhance error handling and transaction management for OAuth user creation and binding
- Improve error handling in DeleteCustomOAuthProvider to log and return errors when fetching binding counts. - Refactor user creation and OAuth binding logic to use transactions for atomic operations, ensuring data integrity. - Add unique constraints to UserOAuthBinding model to prevent duplicate bindings. - Enhance GitHub OAuth provider error logging for non-200 responses. - Update AccountManagement component to provide clearer error messages on API failures.
This commit is contained in:
@@ -3,18 +3,17 @@ package model
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 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:"index;not null"` // User ID
|
||||
ProviderId int `json:"provider_id" gorm:"index;not null"` // Custom OAuth provider ID
|
||||
ProviderUserId string `json:"provider_user_id" gorm:"type:varchar(256);not null"` // User ID from OAuth 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"`
|
||||
|
||||
// Composite unique index to prevent duplicate bindings
|
||||
// One OAuth account can only be bound to one user
|
||||
}
|
||||
|
||||
func (UserOAuthBinding) TableName() string {
|
||||
@@ -82,6 +81,29 @@ func CreateUserOAuthBinding(binding *UserOAuthBinding) error {
|
||||
return DB.Create(binding).Error
|
||||
}
|
||||
|
||||
// CreateUserOAuthBindingWithTx creates a new OAuth binding within a transaction
|
||||
func CreateUserOAuthBindingWithTx(tx *gorm.DB, binding *UserOAuthBinding) error {
|
||||
if binding.UserId == 0 {
|
||||
return errors.New("user ID is required")
|
||||
}
|
||||
if binding.ProviderId == 0 {
|
||||
return errors.New("provider ID is required")
|
||||
}
|
||||
if binding.ProviderUserId == "" {
|
||||
return errors.New("provider user ID is required")
|
||||
}
|
||||
|
||||
// Check if this provider user ID is already taken (use tx to check within the same transaction)
|
||||
var count int64
|
||||
tx.Model(&UserOAuthBinding{}).Where("provider_id = ? AND provider_user_id = ?", binding.ProviderId, binding.ProviderUserId).Count(&count)
|
||||
if count > 0 {
|
||||
return errors.New("this OAuth account is already bound to another user")
|
||||
}
|
||||
|
||||
binding.CreatedAt = time.Now()
|
||||
return tx.Create(binding).Error
|
||||
}
|
||||
|
||||
// UpdateUserOAuthBinding updates an existing OAuth binding (e.g., rebind to different OAuth account)
|
||||
func UpdateUserOAuthBinding(userId, providerId int, newProviderUserId string) error {
|
||||
// Check if the new provider user ID is already taken by another user
|
||||
|
||||
Reference in New Issue
Block a user