Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

178 wiersze
6.1 KiB

  1. package model
  2. import (
  3. "errors"
  4. "time"
  5. "gorm.io/gorm"
  6. )
  7. // UserOAuthBinding stores the binding relationship between users and custom OAuth providers
  8. type UserOAuthBinding struct {
  9. Id int `json:"id" gorm:"primaryKey"`
  10. UserId int `json:"user_id" gorm:"not null;uniqueIndex:ux_user_provider"` // User ID - one binding per user per provider
  11. ProviderId int `json:"provider_id" gorm:"not null;uniqueIndex:ux_user_provider;uniqueIndex:ux_provider_userid"` // Custom OAuth provider ID
  12. 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
  13. CreatedAt time.Time `json:"created_at"`
  14. }
  15. func (UserOAuthBinding) TableName() string {
  16. return "user_oauth_bindings"
  17. }
  18. // GetUserOAuthBindingsByUserId returns all OAuth bindings for a user
  19. func GetUserOAuthBindingsByUserId(userId int) ([]*UserOAuthBinding, error) {
  20. var bindings []*UserOAuthBinding
  21. err := DB.Where("user_id = ?", userId).Find(&bindings).Error
  22. return bindings, err
  23. }
  24. // GetUserOAuthBinding returns a specific binding for a user and provider
  25. func GetUserOAuthBinding(userId, providerId int) (*UserOAuthBinding, error) {
  26. var binding UserOAuthBinding
  27. err := DB.Where("user_id = ? AND provider_id = ?", userId, providerId).First(&binding).Error
  28. if err != nil {
  29. return nil, err
  30. }
  31. return &binding, nil
  32. }
  33. // GetUserByOAuthBinding finds a user by provider ID and provider user ID
  34. func GetUserByOAuthBinding(providerId int, providerUserId string) (*User, error) {
  35. var binding UserOAuthBinding
  36. err := DB.Where("provider_id = ? AND provider_user_id = ?", providerId, providerUserId).First(&binding).Error
  37. if err != nil {
  38. return nil, err
  39. }
  40. var user User
  41. err = DB.First(&user, binding.UserId).Error
  42. if err != nil {
  43. return nil, err
  44. }
  45. return &user, nil
  46. }
  47. // IsProviderUserIdTaken checks if a provider user ID is already bound to any user
  48. func IsProviderUserIdTaken(providerId int, providerUserId string) bool {
  49. var count int64
  50. DB.Model(&UserOAuthBinding{}).Where("provider_id = ? AND provider_user_id = ?", providerId, providerUserId).Count(&count)
  51. return count > 0
  52. }
  53. // CreateUserOAuthBinding creates a new OAuth binding
  54. func CreateUserOAuthBinding(binding *UserOAuthBinding) error {
  55. if binding.UserId == 0 {
  56. return errors.New("user ID is required")
  57. }
  58. if binding.ProviderId == 0 {
  59. return errors.New("provider ID is required")
  60. }
  61. if binding.ProviderUserId == "" {
  62. return errors.New("provider user ID is required")
  63. }
  64. // Check if this provider user ID is already taken
  65. if IsProviderUserIdTaken(binding.ProviderId, binding.ProviderUserId) {
  66. return errors.New("this OAuth account is already bound to another user")
  67. }
  68. binding.CreatedAt = time.Now()
  69. return DB.Create(binding).Error
  70. }
  71. // CreateUserOAuthBindingWithTx creates a new OAuth binding within a transaction
  72. func CreateUserOAuthBindingWithTx(tx *gorm.DB, binding *UserOAuthBinding) error {
  73. if binding.UserId == 0 {
  74. return errors.New("user ID is required")
  75. }
  76. if binding.ProviderId == 0 {
  77. return errors.New("provider ID is required")
  78. }
  79. if binding.ProviderUserId == "" {
  80. return errors.New("provider user ID is required")
  81. }
  82. // Check if this provider user ID is already taken (use tx to check within the same transaction)
  83. var count int64
  84. tx.Model(&UserOAuthBinding{}).Where("provider_id = ? AND provider_user_id = ?", binding.ProviderId, binding.ProviderUserId).Count(&count)
  85. if count > 0 {
  86. return errors.New("this OAuth account is already bound to another user")
  87. }
  88. binding.CreatedAt = time.Now()
  89. return tx.Create(binding).Error
  90. }
  91. func CopyOAuthBindingsIfMissing(userId int, bindings []*UserOAuthBinding) error {
  92. return CopyOAuthBindingsIfMissingTx(DB, userId, bindings)
  93. }
  94. func CopyOAuthBindingsIfMissingTx(tx *gorm.DB, userId int, bindings []*UserOAuthBinding) error {
  95. for _, binding := range bindings {
  96. if binding == nil {
  97. continue
  98. }
  99. var existing UserOAuthBinding
  100. result := tx.Where("user_id = ? AND provider_id = ?", userId, binding.ProviderId).Limit(1).Find(&existing)
  101. if result.Error != nil {
  102. return result.Error
  103. }
  104. if result.RowsAffected > 0 {
  105. continue
  106. }
  107. newBinding := &UserOAuthBinding{
  108. UserId: userId,
  109. ProviderId: binding.ProviderId,
  110. ProviderUserId: binding.ProviderUserId,
  111. }
  112. if err := CreateUserOAuthBindingWithTx(tx, newBinding); err != nil {
  113. return err
  114. }
  115. }
  116. return nil
  117. }
  118. // UpdateUserOAuthBinding updates an existing OAuth binding (e.g., rebind to different OAuth account)
  119. func UpdateUserOAuthBinding(userId, providerId int, newProviderUserId string) error {
  120. // Check if the new provider user ID is already taken by another user
  121. var existingBinding UserOAuthBinding
  122. err := DB.Where("provider_id = ? AND provider_user_id = ?", providerId, newProviderUserId).First(&existingBinding).Error
  123. if err == nil && existingBinding.UserId != userId {
  124. return errors.New("this OAuth account is already bound to another user")
  125. }
  126. // Check if user already has a binding for this provider
  127. var binding UserOAuthBinding
  128. err = DB.Where("user_id = ? AND provider_id = ?", userId, providerId).First(&binding).Error
  129. if err != nil {
  130. // No existing binding, create new one
  131. return CreateUserOAuthBinding(&UserOAuthBinding{
  132. UserId: userId,
  133. ProviderId: providerId,
  134. ProviderUserId: newProviderUserId,
  135. })
  136. }
  137. // Update existing binding
  138. return DB.Model(&binding).Update("provider_user_id", newProviderUserId).Error
  139. }
  140. // DeleteUserOAuthBinding deletes an OAuth binding
  141. func DeleteUserOAuthBinding(userId, providerId int) error {
  142. return DB.Where("user_id = ? AND provider_id = ?", userId, providerId).Delete(&UserOAuthBinding{}).Error
  143. }
  144. // DeleteUserOAuthBindingsByUserId deletes all OAuth bindings for a user
  145. func DeleteUserOAuthBindingsByUserId(userId int) error {
  146. return DB.Where("user_id = ?", userId).Delete(&UserOAuthBinding{}).Error
  147. }
  148. // GetBindingCountByProviderId returns the number of bindings for a provider
  149. func GetBindingCountByProviderId(providerId int) (int64, error) {
  150. var count int64
  151. err := DB.Model(&UserOAuthBinding{}).Where("provider_id = ?", providerId).Count(&count).Error
  152. return count, err
  153. }