Files
user-system/internal/service/auth_admin_bootstrap_internal_test.go

246 lines
6.7 KiB
Go
Raw Normal View History

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")
}
})
}