283 lines
7.6 KiB
Go
283 lines
7.6 KiB
Go
package auth
|
||
|
||
import (
|
||
"nl-video-api/internal/consts"
|
||
"nl-video-api/internal/model/entity"
|
||
"nl-video-api/utility/crypto"
|
||
"nl-video-api/utility/jwt"
|
||
"nl-video-api/utility/response"
|
||
"time"
|
||
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
"github.com/gogf/gf/v2/net/ghttp"
|
||
)
|
||
|
||
type cAuth struct{}
|
||
|
||
var Auth = cAuth{}
|
||
|
||
// LoginReq 登录请求
|
||
type LoginReq struct {
|
||
Username string `json:"username" v:"required#用户名不能为空"`
|
||
Password string `json:"password" v:"required#密码不能为空"`
|
||
}
|
||
|
||
// RegisterReq 注册请求
|
||
type RegisterReq struct {
|
||
Username string `json:"username" v:"required|length:3,20#用户名不能为空|用户名长度为3-20位"`
|
||
Phone string `json:"phone" v:"required|phone#手机号不能为空|手机号格式错误"`
|
||
Password string `json:"password" v:"required|length:6,20#密码不能为空|密码长度为6-20位"`
|
||
Code string `json:"code" v:"required#验证码不能为空"`
|
||
}
|
||
|
||
// UpdateProfileReq 更新资料请求
|
||
type UpdateProfileReq struct {
|
||
Nickname string `json:"nickname" v:"length:1,20#昵称长度为1-20位"`
|
||
Avatar string `json:"avatar" v:"url#头像格式错误"`
|
||
Gender int `json:"gender" v:"in:0,1,2#性别参数错误"`
|
||
Birthday string `json:"birthday" v:"date#生日格式错误"`
|
||
}
|
||
|
||
// Login 用户登录
|
||
func (c *cAuth) Login(r *ghttp.Request) {
|
||
var req LoginReq
|
||
if err := r.Parse(&req); err != nil {
|
||
response.Error(r, response.CodeInvalidParam, err.Error())
|
||
return
|
||
}
|
||
|
||
// 查询用户
|
||
var user entity.NlUser
|
||
err := g.DB().Model("nl_user").Where("username = ? OR phone = ?", req.Username, req.Username).Scan(&user)
|
||
if err != nil || user.Id == 0 {
|
||
response.Error(r, response.CodeError, "用户名或密码错误")
|
||
return
|
||
}
|
||
|
||
// 验证密码
|
||
if !crypto.CheckPassword(req.Password, user.Password) {
|
||
response.Error(r, response.CodeError, "用户名或密码错误")
|
||
return
|
||
}
|
||
|
||
// 检查用户状态
|
||
if user.Status != consts.UserStatusNormal {
|
||
response.Error(r, response.CodeError, "账号已被禁用")
|
||
return
|
||
}
|
||
|
||
// 生成Token
|
||
token, err := jwt.GenerateToken(user.Id, user.Username, consts.UserTypeUser)
|
||
if err != nil {
|
||
response.Error(r, response.CodeServerError, "Token生成失败")
|
||
return
|
||
}
|
||
|
||
// 更新最后登录信息
|
||
now := int(time.Now().Unix())
|
||
clientIP := r.GetClientIp()
|
||
// 将IPv6地址::1转换为IPv4地址127.0.0.1,或者使用IP地址的哈希值
|
||
if clientIP == "::1" {
|
||
clientIP = "127.0.0.1"
|
||
}
|
||
|
||
g.DB().Model("nl_user").Where("id", user.Id).Update(g.Map{
|
||
"last_login_time": now,
|
||
"last_login_ip": clientIP,
|
||
"login_count": g.DB().Raw("login_count + 1"),
|
||
})
|
||
|
||
// 格式化用户信息返回
|
||
userMap := g.Map{
|
||
"id": user.Id,
|
||
"username": user.Username,
|
||
"nick_name": user.NickName,
|
||
"avatar": user.Avatar,
|
||
"phone": user.Phone,
|
||
"email": user.Email,
|
||
"gender": user.Gender,
|
||
"vip_level": user.VipLevel,
|
||
"vip_expire_time": response.FormatTimestamp(user.VipExpireTime),
|
||
"balance": user.Balance,
|
||
"points": user.Points,
|
||
"status": user.Status,
|
||
"last_login_time": response.FormatTimestamp(now),
|
||
"created_at": response.FormatTimestamp(user.CreatedAt),
|
||
"updated_at": response.FormatTimestamp(user.UpdatedAt),
|
||
}
|
||
|
||
response.Success(r, g.Map{
|
||
"token": token,
|
||
"user": userMap,
|
||
})
|
||
}
|
||
|
||
// Register 用户注册
|
||
func (c *cAuth) Register(r *ghttp.Request) {
|
||
var req RegisterReq
|
||
if err := r.Parse(&req); err != nil {
|
||
response.Error(r, response.CodeInvalidParam, err.Error())
|
||
return
|
||
}
|
||
|
||
// 验证验证码(这里简化处理,实际应该验证短信验证码)
|
||
if req.Code != "123456" {
|
||
response.Error(r, response.CodeError, "验证码错误")
|
||
return
|
||
}
|
||
|
||
// 检查用户名是否存在
|
||
count, _ := g.DB().Model("nl_user").Where("username", req.Username).Count()
|
||
if count > 0 {
|
||
response.Error(r, response.CodeError, "用户名已存在")
|
||
return
|
||
}
|
||
|
||
// 检查手机号是否存在
|
||
count, _ = g.DB().Model("nl_user").Where("phone", req.Phone).Count()
|
||
if count > 0 {
|
||
response.Error(r, response.CodeError, "手机号已注册")
|
||
return
|
||
}
|
||
|
||
// 加密密码
|
||
hashedPassword, err := crypto.HashPassword(req.Password)
|
||
if err != nil {
|
||
response.Error(r, response.CodeServerError, "密码加密失败")
|
||
return
|
||
}
|
||
|
||
// 创建用户
|
||
now := int(time.Now().Unix())
|
||
userId, err := g.DB().Model("nl_user").InsertAndGetId(g.Map{
|
||
"username": req.Username,
|
||
"nick_name": req.Username,
|
||
"phone": req.Phone,
|
||
"password": hashedPassword,
|
||
"vip_level": consts.VipLevelNormal,
|
||
"status": consts.UserStatusNormal,
|
||
"created_at": now,
|
||
"updated_at": now,
|
||
})
|
||
if err != nil {
|
||
response.Error(r, response.CodeServerError, "注册失败")
|
||
return
|
||
}
|
||
|
||
// 生成Token
|
||
token, err := jwt.GenerateToken(uint(userId), req.Username, consts.UserTypeUser)
|
||
if err != nil {
|
||
response.Error(r, response.CodeServerError, "Token生成失败")
|
||
return
|
||
}
|
||
|
||
response.Success(r, g.Map{
|
||
"token": token,
|
||
"user_id": userId,
|
||
"message": "注册成功",
|
||
})
|
||
}
|
||
|
||
// Profile 获取用户信息
|
||
func (c *cAuth) Profile(r *ghttp.Request) {
|
||
userId := r.GetCtxVar("user_id").Uint()
|
||
|
||
var user entity.NlUser
|
||
err := g.DB().Model("nl_user").Where("id", userId).Scan(&user)
|
||
if err != nil {
|
||
response.Error(r, response.CodeServerError, "获取用户信息失败")
|
||
return
|
||
}
|
||
|
||
// 格式化用户信息返回
|
||
userMap := g.Map{
|
||
"id": user.Id,
|
||
"username": user.Username,
|
||
"nick_name": user.NickName,
|
||
"avatar": user.Avatar,
|
||
"phone": user.Phone,
|
||
"email": user.Email,
|
||
"gender": user.Gender,
|
||
"birthday": user.Birthday,
|
||
"vip_level": user.VipLevel,
|
||
"vip_expire_time": response.FormatTimestamp(user.VipExpireTime),
|
||
"balance": user.Balance,
|
||
"points": user.Points,
|
||
"status": user.Status,
|
||
"last_login_time": response.FormatTimestamp(user.LastLoginTime),
|
||
"login_count": user.LoginCount,
|
||
"desc": user.Desc,
|
||
"created_at": response.FormatTimestamp(user.CreatedAt),
|
||
"updated_at": response.FormatTimestamp(user.UpdatedAt),
|
||
}
|
||
|
||
response.Success(r, userMap)
|
||
}
|
||
|
||
// UpdateProfile 更新用户信息
|
||
func (c *cAuth) UpdateProfile(r *ghttp.Request) {
|
||
var req UpdateProfileReq
|
||
if err := r.Parse(&req); err != nil {
|
||
response.Error(r, response.CodeInvalidParam, err.Error())
|
||
return
|
||
}
|
||
|
||
userId := r.GetCtxVar("user_id").Uint()
|
||
|
||
// 构建更新数据
|
||
updateData := g.Map{
|
||
"updated_at": int(time.Now().Unix()),
|
||
}
|
||
|
||
if req.Nickname != "" {
|
||
updateData["nickname"] = req.Nickname
|
||
}
|
||
if req.Avatar != "" {
|
||
updateData["avatar"] = req.Avatar
|
||
}
|
||
if req.Gender > 0 {
|
||
updateData["gender"] = req.Gender
|
||
}
|
||
if req.Birthday != "" {
|
||
updateData["birthday"] = req.Birthday
|
||
}
|
||
|
||
// 更新用户信息
|
||
_, err := g.DB().Model("nl_user").Where("id", userId).Update(updateData)
|
||
if err != nil {
|
||
response.Error(r, response.CodeServerError, "更新失败")
|
||
return
|
||
}
|
||
|
||
response.Success(r, g.Map{
|
||
"message": "更新成功",
|
||
})
|
||
}
|
||
|
||
// Logout 用户登出
|
||
func (c *cAuth) Logout(r *ghttp.Request) {
|
||
// 这里可以将token加入黑名单,简化处理直接返回成功
|
||
response.Success(r, g.Map{
|
||
"message": "登出成功",
|
||
})
|
||
}
|
||
|
||
// RefreshToken 刷新Token
|
||
func (c *cAuth) RefreshToken(r *ghttp.Request) {
|
||
authHeader := r.Header.Get("Authorization")
|
||
if authHeader == "" {
|
||
response.Error(r, response.CodeUnauthorized, "请提供认证令牌")
|
||
return
|
||
}
|
||
|
||
tokenString := authHeader[7:] // 去掉 "Bearer "
|
||
newToken, err := jwt.RefreshToken(tokenString)
|
||
if err != nil {
|
||
response.Error(r, response.CodeTokenInvalid, "Token刷新失败")
|
||
return
|
||
}
|
||
|
||
response.Success(r, g.Map{
|
||
"token": newToken,
|
||
})
|
||
} |