// // Copyright (C) 2024 veypi // 2025-03-04 16:08:06 // Distributed under terms of the MIT license. // package auth import ( baseauth "github.com/veypi/vbase/auth" "github.com/veypi/vbase/cfg" "github.com/veypi/vbase/libs/crypto" "github.com/veypi/vbase/libs/jwt" "github.com/veypi/vbase/models" "github.com/veypi/vigo" ) // RegisterRequest 注册请求 type RegisterRequest struct { Username string `json:"username" src:"json" desc:"用户名"` Password string `json:"password" src:"json" desc:"密码"` Email string `json:"email,omitempty" src:"json" desc:"邮箱"` Phone string `json:"phone,omitempty" src:"json" desc:"手机号"` Nickname string `json:"nickname,omitempty" src:"json" desc:"昵称"` } // register 用户注册 func register(x *vigo.X, req *RegisterRequest) (*AuthResponse, error) { // 检查用户名是否已存在 var count int64 cfg.DB().Model(&models.User{}).Where("username = ?", req.Username).Count(&count) if count > 0 { return nil, vigo.ErrArgInvalid.WithString("username already exists") } // 检查邮箱是否已存在 if req.Email != "" { cfg.DB().Model(&models.User{}).Where("email = ?", req.Email).Count(&count) if count > 0 { return nil, vigo.ErrArgInvalid.WithString("email already exists") } } // 哈希密码 hashedPassword, err := crypto.HashPassword(req.Password, cfg.Config.Security.BcryptCost) if err != nil { return nil, vigo.ErrInternalServer.WithError(err) } // 创建用户 var email *string if req.Email != "" { email = &req.Email } var phone *string if req.Phone != "" { phone = &req.Phone } user := &models.User{ Username: req.Username, Password: hashedPassword, Email: email, Phone: phone, Nickname: req.Nickname, Status: models.UserStatusActive, } if user.Nickname == "" { user.Nickname = user.Username } if err := cfg.DB().Create(user).Error; err != nil { return nil, vigo.ErrInternalServer.WithError(err) } // 授予默认角色 "user" if err := baseauth.VBaseAuth.GrantRole(x.Context(), user.ID, "", "user"); err != nil { // 记录错误但允许注册继续,或者回滚 // 这里简单处理,继续流程,用户可能需要管理员手动授权 // 或者返回错误 // return nil, vigo.ErrInternalServer.WithError(err) } // 生成token emailStr := "" if user.Email != nil { emailStr = *user.Email } tokenPair, err := jwt.GenerateTokenPair( user.ID, user.Username, user.Nickname, user.Avatar, emailStr, nil, // 新用户无组织 ) if err != nil { return nil, vigo.ErrInternalServer.WithError(err) } return &AuthResponse{ AccessToken: tokenPair.AccessToken, RefreshToken: tokenPair.RefreshToken, TokenType: tokenPair.TokenType, ExpiresIn: tokenPair.ExpiresIn, User: &UserInfo{ ID: user.ID, Username: user.Username, Nickname: user.Nickname, Email: user.Email, Avatar: user.Avatar, }, }, nil }