refactor: simplify setup flow — eliminate redundant DB calls and login round-trips
- Add AdminExists() to UserRepository (EXISTS query, not full table scan) - SetupInitialAdmin returns tokens directly (skip separate Login call) - Add SetupRequest DTO to auth_dto.go (replace inline struct) - Extract defaultEmail() helper (removes duplicated email logic) - AuthPage uses setup tokens directly (skip redundant apiLogin call) - Use customAxiosInstance for auth API calls (consistent with codebase)
This commit is contained in:
@ -80,53 +80,53 @@ type UserWorkspaceOptions struct {
|
||||
QuotaGPUMem string
|
||||
}
|
||||
|
||||
// IsAdminExists checks whether any admin user already exists in the database.
|
||||
func (s *AuthService) IsAdminExists(ctx context.Context) (bool, error) {
|
||||
users, err := s.userRepo.List(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, u := range users {
|
||||
if u.Role == authz.RoleAdmin {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
func defaultEmail(username string) string {
|
||||
return username + "@local.ocdp"
|
||||
}
|
||||
|
||||
// SetupInitialAdmin creates the first admin user. Fails if an admin already exists.
|
||||
func (s *AuthService) SetupInitialAdmin(ctx context.Context, username, password, email string) (*entity.User, error) {
|
||||
// IsAdminExists checks whether any admin user already exists in the database.
|
||||
func (s *AuthService) IsAdminExists(ctx context.Context) (bool, error) {
|
||||
return s.userRepo.AdminExists(ctx)
|
||||
}
|
||||
|
||||
// SetupInitialAdmin creates the first admin user and returns access + refresh tokens.
|
||||
// Fails if an admin already exists.
|
||||
func (s *AuthService) SetupInitialAdmin(ctx context.Context, username, password, email string) (*entity.User, string, string, error) {
|
||||
hasAdmin, err := s.IsAdminExists(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
if hasAdmin {
|
||||
return nil, entity.ErrForbidden
|
||||
return nil, "", "", entity.ErrForbidden
|
||||
}
|
||||
|
||||
// Hash password
|
||||
passwordHash, err := s.passwordHasher.Hash(password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
|
||||
if email == "" {
|
||||
email = username + "@local.ocdp"
|
||||
email = defaultEmail(username)
|
||||
}
|
||||
|
||||
user := entity.NewUser(username, passwordHash, email)
|
||||
user.ID = uuid.New().String()
|
||||
user.Role = authz.RoleAdmin
|
||||
user.WorkspaceID = entity.DefaultWorkspaceID
|
||||
user.IsActive = true
|
||||
|
||||
if err := user.Validate(); err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
if err := s.userRepo.Create(ctx, user); err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
return user, nil
|
||||
|
||||
// Generate tokens directly — avoid a separate login round-trip
|
||||
accessToken, refreshToken, err := s.tokenGenerator.Generate(user.ID, user.Username, user.Role, user.WorkspaceID)
|
||||
if err != nil {
|
||||
return nil, "", "", err
|
||||
}
|
||||
return user, accessToken, refreshToken, nil
|
||||
}
|
||||
|
||||
func (s *AuthService) Register(ctx context.Context, username, password, role, workspaceID string, opts UserWorkspaceOptions, isActive, mustChangePassword *bool) (*entity.User, error) {
|
||||
@ -158,7 +158,7 @@ func (s *AuthService) Register(ctx context.Context, username, password, role, wo
|
||||
}
|
||||
|
||||
// 默认生成占位邮箱,避免数据库约束失败
|
||||
email := username + "@local.ocdp"
|
||||
email := defaultEmail(username)
|
||||
|
||||
// 创建用户
|
||||
user := entity.NewUser(username, passwordHash, email)
|
||||
|
||||
Reference in New Issue
Block a user