You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

188 lines
4.4 KiB

  1. package model
  2. import (
  3. "testing"
  4. "github.com/QuantumNous/new-api/common"
  5. "github.com/glebarez/sqlite"
  6. "github.com/stretchr/testify/require"
  7. "gorm.io/gorm"
  8. )
  9. func setupRegionMigrationUserDB(t *testing.T) *gorm.DB {
  10. t.Helper()
  11. db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
  12. require.NoError(t, err)
  13. sqlDB, err := db.DB()
  14. require.NoError(t, err)
  15. sqlDB.SetMaxOpenConns(1)
  16. require.NoError(t, db.AutoMigrate(&User{}, &CustomOAuthProvider{}, &UserOAuthBinding{}))
  17. return db
  18. }
  19. func TestInsertImportedUserWithHashedPassword_PreservesHash(t *testing.T) {
  20. db := setupRegionMigrationUserDB(t)
  21. orig := DB
  22. DB = db
  23. defer func() {
  24. DB = orig
  25. }()
  26. user := &User{
  27. Username: "ov-alice",
  28. Password: "already-hashed-value",
  29. Email: "alice@example.com",
  30. DisplayName: "Alice",
  31. Status: common.UserStatusEnabled,
  32. Role: common.RoleCommonUser,
  33. Group: "default",
  34. Quota: 123,
  35. AffCode: "A001",
  36. CreatedAt: 1710000000,
  37. }
  38. require.NoError(t, InsertImportedUserWithHashedPassword(user))
  39. var saved User
  40. require.NoError(t, db.Where("username = ?", "ov-alice").First(&saved).Error)
  41. require.Equal(t, "already-hashed-value", saved.Password)
  42. require.Greater(t, saved.Id, 0)
  43. }
  44. func TestInsertImportedUserWithHashedPassword_RejectsExplicitId(t *testing.T) {
  45. db := setupRegionMigrationUserDB(t)
  46. orig := DB
  47. DB = db
  48. defer func() {
  49. DB = orig
  50. }()
  51. user := &User{
  52. Id: 10000001,
  53. Username: "bad-import",
  54. Password: "hash",
  55. AffCode: "X001",
  56. }
  57. err := InsertImportedUserWithHashedPassword(user)
  58. require.Error(t, err)
  59. require.Contains(t, err.Error(), "Id must not be set")
  60. }
  61. func TestCopyOAuthBindingsIfMissing_Idempotent(t *testing.T) {
  62. db := setupRegionMigrationUserDB(t)
  63. orig := DB
  64. DB = db
  65. defer func() {
  66. DB = orig
  67. }()
  68. require.NoError(t, db.Create(&CustomOAuthProvider{
  69. Id: 10,
  70. Name: "GitHub Enterprise",
  71. Slug: "gh-enterprise",
  72. Enabled: true,
  73. ClientId: "x",
  74. AuthorizationEndpoint: "a",
  75. TokenEndpoint: "t",
  76. UserInfoEndpoint: "u",
  77. }).Error)
  78. require.NoError(t, db.Create(&User{Id: 1, Username: "cn-user", Password: "hash", AffCode: "AFF1"}).Error)
  79. bindings := []*UserOAuthBinding{{
  80. ProviderId: 10,
  81. ProviderUserId: "u-100",
  82. }}
  83. require.NoError(t, CopyOAuthBindingsIfMissing(1, bindings))
  84. require.NoError(t, CopyOAuthBindingsIfMissing(1, bindings))
  85. var count int64
  86. require.NoError(t, db.Model(&UserOAuthBinding{}).Where("user_id = ?", 1).Count(&count).Error)
  87. require.EqualValues(t, 1, count)
  88. }
  89. func TestConvertUserToSynced_Idempotent(t *testing.T) {
  90. db := setupRegionMigrationUserDB(t)
  91. orig := DB
  92. DB = db
  93. defer func() {
  94. DB = orig
  95. }()
  96. require.NoError(t, db.Create(&User{
  97. Id: 10000001,
  98. Username: "ov-user",
  99. Password: "hash",
  100. AffCode: "AFF2",
  101. Quota: 88,
  102. Source: common.UserSourceLocal,
  103. }).Error)
  104. require.NoError(t, ConvertUserToSynced(10000001, 2001, 88))
  105. require.NoError(t, ConvertUserToSynced(10000001, 2001, 88))
  106. var saved User
  107. require.NoError(t, db.First(&saved, 10000001).Error)
  108. require.Equal(t, common.UserSourceSynced, saved.Source)
  109. require.Equal(t, 2001, saved.RemoteUserId)
  110. }
  111. func TestConvertUserToSynced_DifferentRemoteUserIdFails(t *testing.T) {
  112. db := setupRegionMigrationUserDB(t)
  113. orig := DB
  114. DB = db
  115. defer func() {
  116. DB = orig
  117. }()
  118. require.NoError(t, db.Create(&User{
  119. Id: 10000002,
  120. Username: "ov-user2",
  121. Password: "hash",
  122. AffCode: "AFF3",
  123. Source: common.UserSourceLocal,
  124. }).Error)
  125. require.NoError(t, ConvertUserToSynced(10000002, 3001, 100))
  126. err := ConvertUserToSynced(10000002, 9999, 100)
  127. require.Error(t, err)
  128. require.Contains(t, err.Error(), "already synced")
  129. }
  130. func TestListLocalUsersForMigration_FiltersLocalOnly(t *testing.T) {
  131. db := setupRegionMigrationUserDB(t)
  132. orig := DB
  133. DB = db
  134. defer func() {
  135. DB = orig
  136. }()
  137. require.NoError(t, db.Create(&User{
  138. Id: 10000001,
  139. Username: "local-1",
  140. Password: "h",
  141. AffCode: "L1",
  142. Source: common.UserSourceLocal,
  143. }).Error)
  144. require.NoError(t, db.Create(&User{
  145. Id: 10000002,
  146. Username: "synced-1",
  147. Password: "h",
  148. AffCode: "S1",
  149. Source: common.UserSourceSynced,
  150. RemoteUserId: 1,
  151. }).Error)
  152. users, total, err := ListLocalUsersForMigration(0, 20)
  153. require.NoError(t, err)
  154. require.EqualValues(t, 1, total)
  155. require.Len(t, users, 1)
  156. require.Equal(t, "local-1", users[0].Username)
  157. }