Files
web_hgdjb_server/app/api/authapi/auth.go
T
2026-11-07 10:47:32 +08:00

233 lines
8.0 KiB
Go

package authapi
import (
"strings"
"videoweb/app/service/authser"
"videoweb/app/service/wordsfilterser"
"videoweb/pub/common"
"videoweb/pub/common/ipaddr"
"videoweb/pub/common/srvdef"
"videoweb/pub/common/useragent"
"videoweb/pub/pubdef"
"github.com/gin-gonic/gin"
)
func requestUA(ctx *gin.Context) useragent.UA {
ua, _ := common.GetUA(ctx)
return ua
}
func applyRequestDevID(ua useragent.UA, devID string) useragent.UA {
if v := strings.TrimSpace(devID); v != "" {
ua.DevID = v
}
return ua
}
type registerReq struct {
AccountNo string `json:"accountNo" binding:"required"` // 账号
Email string `json:"email"` // 邮箱(可选)
Password string `json:"password" binding:"required"` // 明文密码
AgentInviteCode string `json:"agentInviteCode"` // 邀请人的邀请码(可选)
DevID string `json:"devID"` // 设备唯一标示(可选)
Channel string `json:"channel"` // 渠道码(可选,用户无商区码时写入)
}
type loginReq struct {
Account string `json:"account" binding:"required"` // 账号或邮箱
Password string `json:"password" binding:"required"` // 明文密码
DevID string `json:"devID"` // 设备唯一标示(可选)
Channel string `json:"channel"` // 渠道码(可选,用户无商区码时写入)
}
type resetPasswordReq struct {
AccountNo string `json:"accountNo" binding:"required"` // 账号
Email string `json:"email" binding:"required"` // 邮箱
NewPassword string `json:"newPassword" binding:"required"` // 新密码
}
type updateProfileReq struct {
NickName *string `json:"nickName"` // 新昵称(可选)
Avatar *string `json:"avatar"` // 新头像 URL(可选)
Introduction *string `json:"introduction"` // 简介(可选)
PrivacyMode *bool `json:"privacyMode"` // 隐私模式:true-开启,false-关闭(可选)
OldPassword *string `json:"oldPassword"` // 旧密码明文(已设置密码时修改必填)
NewPassword *string `json:"newPassword"` // 新密码明文(设置或修改密码时必填)
}
// GuestLogin 游客登录
// @Tags 用户认证
// @Summary 游客登录
// @Description 按设备ID创建或找回游客账号;请求头可带 Authorization 复用已有游客会话。需传 X-User-Agent
// @Accept json
// @Produce json
// @Param param body authser.GuestLoginReq true "游客登录参数"
// @Success 200 {object} authser.LoginResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/guest [POST]
func GuestLogin(ctx *gin.Context) {
var req authser.GuestLoginReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
ua, err := common.GetUA(ctx)
if err != nil {
common.ServerJSON(ctx, srvdef.NoUA, nil)
return
}
if req.DevID == "" {
common.ServerJSON(ctx, srvdef.ErrParamError, "devID不能为空")
return
}
ua.DevID = req.DevID
resp, serr := authser.GuestLogin(ctx, common.GetUserId(ctx), ipaddr.ResolveClientIP(ctx), &req, ua)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Register 用户注册
// @Tags 用户认证
// @Summary 注册
// @Description 传入账号和明文密码,邮箱可选,请求头带游客 Authorization 时升级该游客为普通用户,否则新建用户
// @Accept json
// @Produce json
// @Param param body registerReq true "注册参数"
// @Success 200 {object} authser.LoginResp "注册成功,返回 token 及用户基本信息"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/register [POST]
func Register(ctx *gin.Context) {
var req registerReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
ua := applyRequestDevID(requestUA(ctx), req.DevID)
resp, serr := authser.Register(ctx, common.GetUserId(ctx), req.AccountNo, req.Email, req.Password, req.AgentInviteCode, ua, ipaddr.ResolveClientIP(ctx), req.Channel)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Login 用户登录
// @Tags 用户认证
// @Summary 登录
// @Description 账号或邮箱均可作为登录凭证
// @Accept json
// @Produce json
// @Param param body loginReq true "登录参数"
// @Success 200 {object} authser.LoginResp "登录成功,返回 token 及用户基本信息"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/login [POST]
func Login(ctx *gin.Context) {
var req loginReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
ua := applyRequestDevID(requestUA(ctx), req.DevID)
resp, serr := authser.Login(ctx, req.Account, req.Password, ua, ipaddr.ResolveClientIP(ctx), req.Channel)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// UpdateProfile 修改用户资料
// @Tags 用户认证
// @Summary 修改用户资料(头像 / 简介 / 密码,可任意组合)
// @Description 用户信息通过 token 获取,无需传账号;nickName、avatar、introduction、oldPassword+newPassword 均为可选,至少提供一项。未设置密码时传 newPassword 可设置密码,已设置密码时修改需传 oldPassword+newPassword
// @Accept json
// @Produce json
// @Param param body updateProfileReq true "修改资料参数"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/profile [POST]
func UpdateProfile(ctx *gin.Context) {
userId := common.GetUserId(ctx)
if userId <= 0 {
common.ServerJSON(ctx, srvdef.InvalidToken, nil)
return
}
var req updateProfileReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if req.NickName != nil && !wordsfilterser.Validate(*req.NickName) {
common.ServerJSON(ctx, srvdef.ErrContainIllegalWord, "包含非法字符")
return
}
serr := authser.UpdateProfile(ctx, &authser.UpdateProfileReq{
UserId: userId,
NickName: req.NickName,
Avatar: req.Avatar,
Introduction: req.Introduction,
PrivacyMode: req.PrivacyMode,
OldPassword: req.OldPassword,
NewPassword: req.NewPassword,
})
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// GetInfo 获取当前用户信息
// @Tags 用户认证
// @Summary 获取当前用户信息
// @Description 通过 token 获取最新用户信息,包含金币余额、VIP状态等
// @Produce json
// @Success 200 {object} authser.LoginResp "用户信息"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/getInfo [GET]
func GetInfo(ctx *gin.Context) {
userId := common.GetUserId(ctx)
if pubdef.IsCrawlerUser(userId) {
common.ServerJSON(ctx, srvdef.Success, authser.CrawlerLoginResp(""))
return
}
if userId <= 0 {
common.ServerJSON(ctx, srvdef.InvalidToken, nil)
return
}
resp, serr := authser.GetInfo(ctx, userId, requestUA(ctx))
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ResetPassword 找回密码
// @Tags 用户认证
// @Summary 找回密码
// @Description 通过账号和邮箱双重校验后重置密码,两者必须同时匹配同一用户
// @Accept json
// @Produce json
// @Param param body resetPasswordReq true "找回密码参数"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/resetPassword [POST]
func ResetPassword(ctx *gin.Context) {
var req resetPasswordReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := authser.ResetPassword(ctx, req.AccountNo, req.Email, req.NewPassword)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}