implement user registration with email verification, enhance error handling, and update database configuration

This commit is contained in:
2025-07-22 09:15:12 +08:00
parent 1f5f67761b
commit 00c28fea9c
5 changed files with 72 additions and 18 deletions

View File

@ -20,16 +20,17 @@ type UserLoginResp struct {
}
type UserRegisterReq struct {
Username string `json:"username"` // 用户名
Nickname string `json:"nickname"` // 昵称
Password string `json:"password"` // 密码
Email string `json:"email"` // 邮箱
Username string `json:"username"` // 用户名
Nickname string `json:"nickname"` // 昵称
Password string `json:"password"` // 密码
Email string `json:"email"` // 邮箱
VerificationCode string `json:"verification_code"` // 邮箱验证码
}
type UserRegisterResp struct {
Token string `json:"token"` // 访问令牌
RefreshToken string `json:"refresh_token"` // 刷新令牌
User UserDto `json:"user"` // 用户信息
Token string `json:"token"` // 访问令牌
RefreshToken string `json:"refresh_token"` // 刷新令牌
User *UserDto `json:"user"` // 用户信息
}
type VerifyEmailReq struct {

View File

@ -7,10 +7,10 @@ import (
type User struct {
gorm.Model
Username string `gorm:"unique;index"` // 用户名,唯一
Username string `gorm:"uniqueIndex"` // 用户名,唯一
Nickname string
AvatarUrl string
Email string `gorm:"unique;index"`
Email string `gorm:"uniqueIndex"`
Gender string
Role string `gorm:"default:'user'"`

View File

@ -35,14 +35,14 @@ type DBConfig struct {
// loadDBConfig 从配置文件加载数据库配置
func loadDBConfig() DBConfig {
return DBConfig{
Driver: utils.Env.Get("database.driver", "sqlite"),
Path: utils.Env.Get("database.path", "./data/data.db"),
Host: utils.Env.Get("database.host", "postgres"),
Port: utils.Env.GetenvAsInt("database.port", 5432),
User: utils.Env.Get("database.user", "spage"),
Password: utils.Env.Get("database.password", "spage"),
DBName: utils.Env.Get("database.dbname", "spage"),
SSLMode: utils.Env.Get("database.sslmode", "disable"),
Driver: utils.Env.Get("DB_DRIVER", "sqlite"),
Path: utils.Env.Get("DB_PATH", "./data/data.db"),
Host: utils.Env.Get("DB_HOST", "postgres"),
Port: utils.Env.GetenvAsInt("DB_PORT", 5432),
User: utils.Env.Get("DB_USER", "blog"),
Password: utils.Env.Get("DB_PASSWORD", "blog"),
DBName: utils.Env.Get("DB_NAME", "blog"),
SSLMode: utils.Env.Get("DB_SSLMODE", "disable"),
}
}

View File

@ -3,11 +3,13 @@ package service
import (
"github.com/sirupsen/logrus"
"github.com/snowykami/neo-blog/internal/dto"
"github.com/snowykami/neo-blog/internal/model"
"github.com/snowykami/neo-blog/internal/repo"
"github.com/snowykami/neo-blog/internal/static"
"github.com/snowykami/neo-blog/pkg/constant"
"github.com/snowykami/neo-blog/pkg/errs"
"github.com/snowykami/neo-blog/pkg/utils"
"net/http"
"time"
)
@ -62,7 +64,57 @@ func (s *userService) UserLogin(req *dto.UserLoginReq) (*dto.UserLoginResp, erro
}
func (s *userService) UserRegister(req *dto.UserRegisterReq) (*dto.UserRegisterResp, error) {
return nil, nil
// 验证邮箱验证码
kv := utils.KV.GetInstance()
verificationCode, ok := kv.Get(constant.KVKeyEmailVerificationCode + ":" + req.Email)
if !ok || verificationCode != req.VerificationCode {
return nil, errs.ErrInvalidCredentials
}
// 检查用户名或邮箱是否已存在
existingUser, err := repo.User.GetByUsernameOrEmail(req.Username)
if err != nil {
return nil, errs.ErrInternalServer
}
if existingUser != nil {
return nil, errs.New(http.StatusConflict, "Username or email already exists", nil)
}
// 创建新用户
newUser := &model.User{
Username: req.Username,
Nickname: req.Nickname,
Email: req.Email,
Gender: "",
Role: "user",
Password: "",
}
err = repo.User.Create(newUser)
if err != nil {
return nil, errs.ErrInternalServer
}
// 生成访问令牌和刷新令牌
token := utils.Jwt.NewClaims(newUser.ID, "", false, time.Duration(utils.Env.GetenvAsInt(constant.EnvKeyTokenDuration, 24)*int(time.Hour)))
tokenString, err := token.ToString()
if err != nil {
return nil, errs.ErrInternalServer
}
refreshToken := utils.Jwt.NewClaims(newUser.ID, utils.Strings.GenerateRandomString(64), true, time.Duration(utils.Env.GetenvAsInt(constant.EnvKeyRefreshTokenDuration, 30)*int(time.Hour)))
refreshTokenString, err := refreshToken.ToString()
if err != nil {
return nil, errs.ErrInternalServer
}
// 对refresh token进行持久化存储
err = repo.Session.SaveSession(refreshToken.SessionKey)
if err != nil {
return nil, errs.ErrInternalServer
}
resp := &dto.UserRegisterResp{
Token: tokenString,
RefreshToken: refreshTokenString,
User: newUser.ToDto(),
}
return resp, nil
}
func (s *userService) VerifyEmail(req *dto.VerifyEmailReq) (*dto.VerifyEmailResp, error) {