|
- package model
-
- import (
- "errors"
- "testing"
-
- "github.com/QuantumNous/new-api/common"
- "github.com/glebarez/sqlite"
- "github.com/stretchr/testify/require"
- "gorm.io/gorm"
- )
-
- func setupRegionMigrationUserDB(t *testing.T) *gorm.DB {
- t.Helper()
-
- db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
- require.NoError(t, err)
-
- sqlDB, err := db.DB()
- require.NoError(t, err)
- sqlDB.SetMaxOpenConns(1)
-
- require.NoError(t, db.AutoMigrate(&User{}, &CustomOAuthProvider{}, &UserOAuthBinding{}))
-
- return db
- }
-
- func TestInsertImportedUserWithHashedPassword_PreservesHash(t *testing.T) {
- db := setupRegionMigrationUserDB(t)
- orig := DB
- DB = db
- defer func() {
- DB = orig
- }()
-
- user := &User{
- Username: "ov-alice",
- Password: "already-hashed-value",
- Email: "alice@example.com",
- DisplayName: "Alice",
- Status: common.UserStatusEnabled,
- Role: common.RoleCommonUser,
- Group: "default",
- Quota: 123,
- AffCode: "A001",
- CreatedAt: 1710000000,
- }
-
- require.NoError(t, InsertImportedUserWithHashedPassword(user))
-
- var saved User
- require.NoError(t, db.Where("username = ?", "ov-alice").First(&saved).Error)
- require.Equal(t, "already-hashed-value", saved.Password)
- require.Greater(t, saved.Id, 0)
- }
-
- func TestInsertImportedUserWithHashedPassword_RejectsExplicitId(t *testing.T) {
- db := setupRegionMigrationUserDB(t)
- orig := DB
- DB = db
- defer func() {
- DB = orig
- }()
-
- user := &User{
- Id: 10000001,
- Username: "bad-import",
- Password: "hash",
- AffCode: "X001",
- }
-
- err := InsertImportedUserWithHashedPassword(user)
- require.Error(t, err)
- require.Contains(t, err.Error(), "Id must not be set")
- }
-
- func TestCopyOAuthBindingsIfMissing_Idempotent(t *testing.T) {
- db := setupRegionMigrationUserDB(t)
- orig := DB
- DB = db
- defer func() {
- DB = orig
- }()
-
- require.NoError(t, db.Create(&CustomOAuthProvider{
- Id: 10,
- Name: "GitHub Enterprise",
- Slug: "gh-enterprise",
- Enabled: true,
- ClientId: "x",
- AuthorizationEndpoint: "a",
- TokenEndpoint: "t",
- UserInfoEndpoint: "u",
- }).Error)
- require.NoError(t, db.Create(&User{Id: 1, Username: "cn-user", Password: "hash", AffCode: "AFF1"}).Error)
-
- bindings := []*UserOAuthBinding{{
- ProviderId: 10,
- ProviderUserId: "u-100",
- }}
-
- require.NoError(t, CopyOAuthBindingsIfMissing(1, bindings))
- require.NoError(t, CopyOAuthBindingsIfMissing(1, bindings))
-
- var count int64
- require.NoError(t, db.Model(&UserOAuthBinding{}).Where("user_id = ?", 1).Count(&count).Error)
- require.EqualValues(t, 1, count)
- }
-
- func TestConvertUserToSynced_Idempotent(t *testing.T) {
- db := setupRegionMigrationUserDB(t)
- orig := DB
- DB = db
- defer func() {
- DB = orig
- }()
-
- require.NoError(t, db.Create(&User{
- Id: 10000001,
- Username: "ov-user",
- Password: "hash",
- AffCode: "AFF2",
- Quota: 88,
- Source: common.UserSourceLocal,
- }).Error)
-
- require.NoError(t, ConvertUserToSynced(10000001, 2001, 88))
- require.NoError(t, ConvertUserToSynced(10000001, 2001, 88))
-
- var saved User
- require.NoError(t, db.First(&saved, 10000001).Error)
- require.Equal(t, common.UserSourceSynced, saved.Source)
- require.Equal(t, 2001, saved.RemoteUserId)
- }
-
- func TestConvertUserToSynced_DifferentRemoteUserIdFails(t *testing.T) {
- db := setupRegionMigrationUserDB(t)
- orig := DB
- DB = db
- defer func() {
- DB = orig
- }()
-
- require.NoError(t, db.Create(&User{
- Id: 10000002,
- Username: "ov-user2",
- Password: "hash",
- AffCode: "AFF3",
- Source: common.UserSourceLocal,
- }).Error)
-
- require.NoError(t, ConvertUserToSynced(10000002, 3001, 100))
-
- err := ConvertUserToSynced(10000002, 9999, 100)
- require.Error(t, err)
- require.ErrorIs(t, err, ErrSyncedUserRemoteUserIDImmutable)
- }
-
- func TestListLocalUsersForMigration_FiltersLocalOnly(t *testing.T) {
- db := setupRegionMigrationUserDB(t)
- orig := DB
- DB = db
- defer func() {
- DB = orig
- }()
-
- require.NoError(t, db.Create(&User{
- Id: 10000001,
- Username: "local-1",
- Password: "h",
- AffCode: "L1",
- Source: common.UserSourceLocal,
- }).Error)
- require.NoError(t, db.Create(&User{
- Id: 10000002,
- Username: "synced-1",
- Password: "h",
- AffCode: "S1",
- Source: common.UserSourceSynced,
- RemoteUserId: 1,
- }).Error)
- require.NoError(t, db.Create(&User{
- Id: 10000003,
- Username: "root",
- Password: "h",
- AffCode: "R1",
- Source: common.UserSourceLocal,
- Role: common.RoleRootUser,
- }).Error)
-
- users, total, err := ListLocalUsersForMigration(0, 20)
- require.NoError(t, err)
- require.EqualValues(t, 1, total)
- require.Len(t, users, 1)
- require.Equal(t, "local-1", users[0].Username)
- }
-
- func TestConvertUserToSynced_RejectsRootUser(t *testing.T) {
- db := setupRegionMigrationUserDB(t)
- orig := DB
- DB = db
- defer func() {
- DB = orig
- }()
-
- require.NoError(t, db.Create(&User{
- Id: 10000010,
- Username: "root",
- Password: "hash",
- AffCode: "ROOT1",
- Source: common.UserSourceLocal,
- Role: common.RoleRootUser,
- }).Error)
-
- err := ConvertUserToSynced(10000010, 2001, 88)
- require.Error(t, err)
- require.ErrorIs(t, err, ErrConvertRootUserToSynced)
-
- var saved User
- require.NoError(t, db.First(&saved, 10000010).Error)
- require.Equal(t, common.UserSourceLocal, saved.Source)
- require.Equal(t, 0, saved.RemoteUserId)
- }
-
- func TestConvertUserToSynced_SentinelErrorsRemainDistinct(t *testing.T) {
- db := setupRegionMigrationUserDB(t)
- orig := DB
- DB = db
- defer func() {
- DB = orig
- }()
-
- require.NoError(t, db.Create(&User{
- Id: 10000020,
- Username: "already-synced",
- Password: "hash",
- AffCode: "SYNC20",
- Source: common.UserSourceSynced,
- RemoteUserId: 3001,
- }).Error)
-
- err := ConvertUserToSynced(10000020, 9999, 100)
- require.Error(t, err)
- require.True(t, errors.Is(err, ErrSyncedUserRemoteUserIDImmutable))
- require.False(t, errors.Is(err, ErrConvertRootUserToSynced))
- }
|