package service import ( "context" "testing" "github.com/user-management-system/internal/auth" "github.com/user-management-system/internal/cache" "github.com/user-management-system/internal/domain" "github.com/user-management-system/internal/repository" gormsqlite "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) // ============================================================================= // Auth Admin Bootstrap Internal Tests // ============================================================================= func setupBootstrapInternalTestEnv(t *testing.T) (*AuthService, *gorm.DB) { t.Helper() db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{ DriverName: "sqlite", DSN: "file:bootstrap_internal_test?mode=memory&cache=shared", }), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), }) if err != nil { t.Fatalf("failed to connect database: %v", err) } if err := db.AutoMigrate(&domain.User{}, &domain.Role{}, &domain.UserRole{}); err != nil { t.Fatalf("failed to migrate: %v", err) } // Create admin role adminRole := &domain.Role{ Name: "管理员", Code: "admin", Status: domain.RoleStatusEnabled, } db.Create(adminRole) userRepo := repository.NewUserRepository(db) userRoleRepo := repository.NewUserRoleRepository(db) roleRepo := repository.NewRoleRepository(db) socialRepo, _ := repository.NewSocialAccountRepository(db) jwtManager, _ := auth.NewJWTWithOptions(auth.JWTOptions{ HS256Secret: "test-secret-for-bootstrap", AccessTokenExpire: 15 * 60 * 1000 * 1000 * 1000, RefreshTokenExpire: 7 * 24 * 60 * 60 * 1000 * 1000 * 1000, }) l1Cache := cache.NewL1Cache() l2Cache := cache.NewRedisCache(false) cacheManager := cache.NewCacheManager(l1Cache, l2Cache) svc := NewAuthService(userRepo, socialRepo, jwtManager, cacheManager, 8, 5, 15*60*1000*1000*1000) svc.SetRoleRepositories(userRoleRepo, roleRepo) return svc, db } func TestBootstrapAdmin_Internal(t *testing.T) { svc, db := setupBootstrapInternalTestEnv(t) ctx := context.Background() t.Run("BootstrapAdmin with nil request", func(t *testing.T) { _, err := svc.BootstrapAdmin(ctx, nil, "127.0.0.1") if err == nil { t.Error("Expected error for nil request") } }) t.Run("BootstrapAdmin with empty username", func(t *testing.T) { req := &BootstrapAdminRequest{ Username: "", Password: "Admin123!", } _, err := svc.BootstrapAdmin(ctx, req, "127.0.0.1") if err == nil { t.Error("Expected error for empty username") } }) t.Run("BootstrapAdmin with empty password", func(t *testing.T) { req := &BootstrapAdminRequest{ Username: "testadmin", Password: "", } _, err := svc.BootstrapAdmin(ctx, req, "127.0.0.1") if err == nil { t.Error("Expected error for empty password") } }) t.Run("BootstrapAdmin with weak password", func(t *testing.T) { req := &BootstrapAdminRequest{ Username: "testadmin", Password: "123", } _, err := svc.BootstrapAdmin(ctx, req, "127.0.0.1") if err == nil { t.Error("Expected error for weak password") } }) t.Run("BootstrapAdmin success", func(t *testing.T) { // Clean up db.Exec("DELETE FROM user_roles") db.Exec("DELETE FROM users") req := &BootstrapAdminRequest{ Username: "newadmin", Password: "Admin123!", Email: "newadmin@test.com", Nickname: "New Admin", } resp, err := svc.BootstrapAdmin(ctx, req, "127.0.0.1") if err != nil { t.Fatalf("BootstrapAdmin failed: %v", err) } if resp.AccessToken == "" { t.Error("Expected access token") } if resp.User.Username != "newadmin" { t.Errorf("Expected username 'newadmin', got %s", resp.User.Username) } }) t.Run("BootstrapAdmin with duplicate username", func(t *testing.T) { req := &BootstrapAdminRequest{ Username: "dupadmin", Password: "Admin123!", } // First create svc.BootstrapAdmin(ctx, req, "127.0.0.1") // Second create should fail _, err := svc.BootstrapAdmin(ctx, req, "127.0.0.1") if err == nil { t.Error("Expected error for duplicate username") } }) t.Run("BootstrapAdmin with duplicate email", func(t *testing.T) { // Clean up db.Exec("DELETE FROM user_roles WHERE user_id IN (SELECT id FROM users WHERE username LIKE 'emailtest%')") db.Exec("DELETE FROM users WHERE username LIKE 'emailtest%'") req1 := &BootstrapAdminRequest{ Username: "emailtest1", Password: "Admin123!", Email: "samemail@test.com", } svc.BootstrapAdmin(ctx, req1, "127.0.0.1") req2 := &BootstrapAdminRequest{ Username: "emailtest2", Password: "Admin123!", Email: "samemail@test.com", } _, err := svc.BootstrapAdmin(ctx, req2, "127.0.0.1") if err == nil { t.Error("Expected error for duplicate email") } }) t.Run("BootstrapAdmin when bootstrap unavailable", func(t *testing.T) { // Create an existing admin to make bootstrap unavailable db.Exec("DELETE FROM user_roles") db.Exec("DELETE FROM users") req := &BootstrapAdminRequest{ Username: "firstadmin", Password: "Admin123!", } svc.BootstrapAdmin(ctx, req, "127.0.0.1") // Now try again - should fail because admin already exists req2 := &BootstrapAdminRequest{ Username: "secondadmin", Password: "Admin123!", } _, err := svc.BootstrapAdmin(ctx, req2, "127.0.0.1") if err == nil { t.Error("Expected error when bootstrap unavailable") } }) } func TestBootstrapAdmin_NilService(t *testing.T) { var nilSvc *AuthService ctx := context.Background() t.Run("nil service returns error", func(t *testing.T) { req := &BootstrapAdminRequest{ Username: "admin", Password: "Admin123!", } _, err := nilSvc.BootstrapAdmin(ctx, req, "127.0.0.1") if err == nil { t.Error("Expected error for nil service") } }) } func TestIsAdminBootstrapRequired(t *testing.T) { svc, db := setupBootstrapInternalTestEnv(t) ctx := context.Background() t.Run("returns true when no admin exists", func(t *testing.T) { db.Exec("DELETE FROM user_roles") db.Exec("DELETE FROM users") required := svc.IsAdminBootstrapRequired(ctx) if !required { t.Error("Expected IsAdminBootstrapRequired to return true when no admin exists") } }) t.Run("returns false when admin exists", func(t *testing.T) { db.Exec("DELETE FROM user_roles") db.Exec("DELETE FROM users") req := &BootstrapAdminRequest{ Username: "bootstrapadmin", Password: "Admin123!", } svc.BootstrapAdmin(ctx, req, "127.0.0.1") required := svc.IsAdminBootstrapRequired(ctx) if required { t.Error("Expected IsAdminBootstrapRequired to return false when admin exists") } }) t.Run("nil service returns false", func(t *testing.T) { var nilSvc *AuthService required := nilSvc.IsAdminBootstrapRequired(ctx) if required { t.Error("Expected IsAdminBootstrapRequired to return false for nil service") } }) }