package authapi import ( "videoweb/app/service/authser" "videoweb/app/service/wordsfilterser" "videoweb/pub/common" "videoweb/pub/common/enum/consts" "videoweb/pub/common/srvdef" "videoweb/pub/pubdef" "github.com/gin-gonic/gin" ) // extractUA 从 gin context 中提取 UA 中间件解析到的设备/系统信息 func extractUA(ctx *gin.Context) authser.UAInfo { return authser.UAInfo{ Device: ctx.GetString(consts.CtxDevType), SysType: pubdef.SysType(ctx.GetString(consts.CtxSysType)), AppVer: ctx.GetString(consts.CtxVersion), IP: ctx.ClientIP(), } } type guestLoginReq struct { DevID string `json:"devID"` // 设备 ID(首选) Mac string `json:"mac"` // 设备 MAC 地址(备用) DeviceId string `json:"deviceId"` // 设备 ID 第二版本(备用) } type registerReq struct { AccountNo string `json:"accountNo" binding:"required"` // 账号 Password string `json:"password" binding:"required"` // 明文密码 AgentInviteCode string `json:"agentInviteCode"` // 邀请人的邀请码(可选) } type loginReq struct { Account string `json:"account" binding:"required"` // 账号 Password string `json:"password" binding:"required"` // 明文密码 } type updateProfileReq struct { AccountNo string `json:"accountNo" binding:"required"` // 账号(必填,用于定位用户) Avatar *string `json:"avatar"` // 新头像 URL(可选) NikeName *string `json:"nikeName"` // 昵称 OldPassword *string `json:"oldPassword"` // 旧密码明文(修改密码时必填) NewPassword *string `json:"newPassword"` // 新密码明文(修改密码时必填) } // GuestLogin 游客登录/自动注册 // @Tags 用户认证 // @Summary 游客登录 // @Description 按设备 ID 查找已有游客账号,找不到则自动注册。若请求携带有效 token 则优先复用该用户。 // @Accept json // @Produce json // @Param param body guestLoginReq true "设备信息" // @Success 200 {object} authser.LoginResp "登录成功" // @Failure 400 {string} string "失败" // @Router /api/app/login/guest [POST] func GuestLogin(ctx *gin.Context) { var req guestLoginReq _ = ctx.ShouldBind(&req) // 若设备信息为空,尝试从 UA 中间件补充 DevID if req.DevID == "" { req.DevID = ctx.GetString(consts.CtxDevId) } currentUserId := common.GetUserId(ctx) resp, serr := authser.GuestLogin(ctx, &authser.GuestLoginReq{ DevID: req.DevID, Mac: req.Mac, DeviceId: req.DeviceId, UA: extractUA(ctx), }, currentUserId) if serr != nil { common.ServerJSON(ctx, serr.Code, serr.Tips) return } common.ServerJSON(ctx, srvdef.Success, resp) } // Register 账号注册(游客升级 or 直接注册) // @Tags 用户认证 // @Summary 注册 // @Description 已登录游客传入账号密码完成升级;未登录用户直接注册新账号。 // @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 } currentUserId := common.GetUserId(ctx) resp, serr := authser.Register(ctx, req.AccountNo, req.Password, req.AgentInviteCode, currentUserId, extractUA(ctx)) 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 } resp, serr := authser.Login(ctx, req.Account, req.Password, extractUA(ctx)) if serr != nil { common.ServerJSON(ctx, serr.Code, serr.Tips) return } common.ServerJSON(ctx, srvdef.Success, resp) } // GetInfo 获取当前登录用户信息 // @Tags 用户认证 // @Summary 获取当前登录用户信息 // @Description 根据当前登录 token 查询用户基础信息 // @Accept json // @Produce json // @Success 200 {object} authser.UserInfoResp "成功" // @Failure 400 {string} string "失败" // @Router /api/app/auth/getInfo [get] func GetInfo(ctx *gin.Context) { userId := common.GetUserId(ctx) if userId <= 0 { common.ServerJSON(ctx, srvdef.InvalidToken, nil) return } resp, serr := authser.GetInfo(ctx, userId) if serr != nil { common.ServerJSON(ctx, serr.Code, serr.Tips) return } common.ServerJSON(ctx, srvdef.Success, resp) } // UpdateProfile 修改用户资料 // @Tags 用户认证 // @Summary 修改用户资料(头像 / 密码,可任意组合) // @Description 账号必填;avatar、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) { var req updateProfileReq if err := ctx.ShouldBind(&req); err != nil { common.ServerJSON(ctx, srvdef.ErrParamError, nil) return } if req.NikeName != nil && !wordsfilterser.Validate(*req.NikeName) { common.ServerJSON(ctx, srvdef.ErrContainIllegalWord, "包含非法字符") return } serr := authser.UpdateProfile(ctx, &authser.UpdateProfileReq{ AccountNo: req.AccountNo, Avatar: req.Avatar, NikeName: req.NikeName, OldPassword: req.OldPassword, NewPassword: req.NewPassword, }) if serr != nil { common.ServerJSON(ctx, serr.Code, serr.Tips) return } common.ServerJSON(ctx, srvdef.Success, "") }