初始化
This commit is contained in:
107
internal/handler/auth.go
Normal file
107
internal/handler/auth.go
Normal file
@@ -0,0 +1,107 @@
|
||||
// Package handler 存放全部 HTTP 接口处理函数
|
||||
package handler
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"nl-game-api-gin/internal/database"
|
||||
"nl-game-api-gin/internal/model"
|
||||
"nl-game-api-gin/internal/service"
|
||||
"nl-game-api-gin/pkg/jwtutil"
|
||||
"nl-game-api-gin/pkg/resp"
|
||||
)
|
||||
|
||||
// registerReq 注册请求体
|
||||
type registerReq struct {
|
||||
Username string `json:"username" binding:"required,min=3,max=20"` // 用户名:3-20位
|
||||
Password string `json:"password" binding:"required,min=6,max=32"` // 密码:6-32位
|
||||
Nickname string `json:"nickname" binding:"max=20"` // 昵称:可选,默认同用户名
|
||||
Avatar string `json:"avatar"` // emoji 头像:可选
|
||||
}
|
||||
|
||||
// Register 用户注册:校验重名、加密密码、发注册礼积分
|
||||
func Register(c *gin.Context) {
|
||||
var req registerReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
resp.Fail(c, "参数有误:用户名3-20位、密码6-32位")
|
||||
return
|
||||
}
|
||||
req.Username = strings.TrimSpace(req.Username)
|
||||
// 用户名查重
|
||||
var count int64
|
||||
database.DB.Model(&model.User{}).Where("username = ?", req.Username).Count(&count)
|
||||
if count > 0 {
|
||||
resp.Fail(c, "用户名已被占用")
|
||||
return
|
||||
}
|
||||
// bcrypt 加密密码
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
resp.Fail(c, "密码加密失败")
|
||||
return
|
||||
}
|
||||
if req.Nickname == "" {
|
||||
req.Nickname = req.Username
|
||||
}
|
||||
if req.Avatar == "" {
|
||||
req.Avatar = "🙂"
|
||||
}
|
||||
user := model.User{
|
||||
Username: req.Username, Password: string(hash),
|
||||
Nickname: req.Nickname, Avatar: req.Avatar, Role: model.RoleNormal,
|
||||
}
|
||||
if err := database.DB.Create(&user).Error; err != nil {
|
||||
resp.Fail(c, "注册失败,请稍后重试")
|
||||
return
|
||||
}
|
||||
// 注册礼积分(金额可在后台配置)
|
||||
gift := service.GetConfigInt(model.ConfKeyRegisterGift, 200)
|
||||
if gift > 0 {
|
||||
service.ChangePoints(nil, user.ID, gift, model.PointTypeRegister, 0, "新用户注册礼")
|
||||
user.Points = gift
|
||||
}
|
||||
token, _ := jwtutil.Generate(user.ID, user.Role)
|
||||
resp.OK(c, gin.H{"token": token, "user": user})
|
||||
}
|
||||
|
||||
// loginReq 登录请求体
|
||||
type loginReq struct {
|
||||
Username string `json:"username" binding:"required"` // 用户名
|
||||
Password string `json:"password" binding:"required"` // 密码
|
||||
}
|
||||
|
||||
// Login 用户登录:校验密码、记录登录日志、签发 Token
|
||||
func Login(c *gin.Context) {
|
||||
var req loginReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
resp.Fail(c, "请输入用户名和密码")
|
||||
return
|
||||
}
|
||||
var user model.User
|
||||
if err := database.DB.Where("username = ?", strings.TrimSpace(req.Username)).First(&user).Error; err != nil {
|
||||
resp.Fail(c, "用户名或密码错误")
|
||||
return
|
||||
}
|
||||
// bcrypt 校验密码
|
||||
if bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)) != nil {
|
||||
resp.Fail(c, "用户名或密码错误")
|
||||
return
|
||||
}
|
||||
if user.Status == model.UserStatusBanned {
|
||||
resp.Fail(c, "账号已被封禁,请联系管理员")
|
||||
return
|
||||
}
|
||||
// 写登录日志(IP + 浏览器UA)
|
||||
database.DB.Create(&model.LoginLog{
|
||||
UserID: user.ID, IP: c.ClientIP(), UserAgent: c.GetHeader("User-Agent"),
|
||||
})
|
||||
token, err := jwtutil.Generate(user.ID, user.Role)
|
||||
if err != nil {
|
||||
resp.Fail(c, "登录凭证生成失败")
|
||||
return
|
||||
}
|
||||
resp.OK(c, gin.H{"token": token, "user": user})
|
||||
}
|
||||
Reference in New Issue
Block a user