package service import ( "crypto/rand" "encoding/base64" "errors" "git.zkcoi.com/zkcoi/meshray/internal/model" "git.zkcoi.com/zkcoi/meshray/internal/store/sqlite" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) // 字符集用于生成随机密码(保留用于特殊场景) const passwordChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*" // generateRandomPassword 使用 crypto/rand 生成安全的随机密码 func generateRandomPassword(length int) string { b := make([]byte, length) _, err := rand.Read(b) if err != nil { // 极端情况下回退到简单方案(几乎不会发生) return "REPLACE_WITH_SECURE_PASSWORD" } // 使用 Base64 编码,确保包含各种字符 encoded := base64.StdEncoding.EncodeToString(b) // 截取所需长度(Base64 编码后长度为 4/3 倍) if len(encoded) >= length { return encoded[:length] } return encoded } // GenerateRandomPassword 生成随机密码(公开函数) func GenerateRandomPassword(length int) string { return generateRandomPassword(length) } // UserService 用户服务 type UserService struct { store *sqlite.Store } // NewUserService 创建用户服务实例 func NewUserService(store *sqlite.Store) *UserService { return &UserService{store: store} } // InitializeAdmin 初始化管理员账户(首次启动时调用) func (s *UserService) InitializeAdmin() (username, password string, err error) { // 检查是否已存在 admin 用户 var existingUser model.User if err := s.store.DB().Where("role = ?", "admin").First(&existingUser).Error; err == nil { // 已存在,返回当前用户名(密码不返回) return existingUser.Username, "", nil } // 生成随机密码 randomPassword := generateRandomPassword(16) // 密码加密 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(randomPassword), bcrypt.DefaultCost) if err != nil { return "", "", err } // 创建 admin 用户 adminUser := &model.User{ Username: "admin", PasswordHash: string(hashedPassword), Email: "", Role: "admin", Status: "active", } if err := s.store.DB().Create(adminUser).Error; err != nil { return "", "", err } return "admin", randomPassword, nil } // Authenticate 验证用户登录 func (s *UserService) Authenticate(username, password string) (*model.User, error) { var user model.User if err := s.store.DB().Where("username = ?", username).First(&user).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("用户不存在") } return nil, err } // 验证密码 if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password)); err != nil { return nil, errors.New("密码错误") } // 检查用户状态 if user.Status != "active" { return nil, errors.New("账户已被禁用") } return &user, nil } // ChangePasswordRequest 修改密码请求 type ChangePasswordRequest struct { OldPassword string `json:"old_password"` NewPassword string `json:"new_password"` } // ChangePassword 修改用户密码 func (s *UserService) ChangePassword(userID uint, req *ChangePasswordRequest) error { // 1. 查询用户 var user model.User if err := s.store.DB().First(&user, userID).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return errors.New("用户不存在") } return err } // 2. 验证旧密码 if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.OldPassword)); err != nil { return errors.New("原密码错误") } // 3. 验证新密码强度 if len(req.NewPassword) < 6 { return errors.New("密码长度不能少于 6 位") } // 4. 加密新密码 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost) if err != nil { return err } // 5. 更新密码 user.PasswordHash = string(hashedPassword) if err := s.store.DB().Save(&user).Error; err != nil { return err } return nil } // GetUserByID 根据 ID 获取用户 func (s *UserService) GetUserByID(userID uint) (*model.User, error) { var user model.User if err := s.store.DB().First(&user, userID).Error; err != nil { return nil, err } return &user, nil } // UpdateUser 更新用户信息 func (s *UserService) UpdateUser(userID uint, updates map[string]interface{}) (*model.User, error) { var user model.User if err := s.store.DB().First(&user, userID).Error; err != nil { return nil, err } if err := s.store.DB().Model(&user).Updates(updates).Error; err != nil { return nil, err } return &user, nil } // UpdateAdminProfile 更新管理员资料(仅允许 admin 用户调用) func (s *UserService) UpdateAdminProfile(username, email, password string) error { var user model.User if err := s.store.DB().Where("role = ?", "admin").First(&user).Error; err != nil { return errors.New("管理员账户不存在") } updates := make(map[string]interface{}) if username != "" && username != user.Username { // 检查新用户名是否已被使用 var existing model.User if err := s.store.DB().Where("username = ? AND role = ?", username, "admin").First(&existing).Error; err == nil { return errors.New("用户名已存在") } updates["username"] = username } if email != "" && email != user.Email { updates["email"] = email } if password != "" { hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return err } updates["password_hash"] = string(hashedPassword) } if len(updates) == 0 { return nil // 没有需要更新的 } return s.store.DB().Model(&user).Updates(updates).Error } // ResetAdminPassword 重置管理员密码(命令行工具使用) func (s *UserService) ResetAdminPassword(newPassword string) error { var user model.User if err := s.store.DB().Where("role = ?", "admin").First(&user).Error; err != nil { return errors.New("管理员账户不存在") } // 加密新密码 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost) if err != nil { return err } return s.store.DB().Model(&user).Update("password_hash", string(hashedPassword)).Error }