package web import ( "net/http" "strings" "videoweb/app/service/authser" "videoweb/pub/common/log" "videoweb/pub/common/useragent" "github.com/gin-gonic/gin" ) type registerBody struct { AccountNo string `json:"accountNo"` Email string `json:"email"` Password string `json:"password"` AgentInviteCode string `json:"agentInviteCode"` DevID string `json:"devID"` Channel string `json:"channel"` } type loginBody struct { Account string `json:"account"` Password string `json:"password"` DevID string `json:"devID"` Channel string `json:"channel"` } type resetPasswordBody struct { AccountNo string `json:"accountNo"` Email string `json:"email"` NewPassword string `json:"newPassword"` } type updateProfileBody struct { Avatar string `json:"avatar"` Introduction string `json:"introduction"` NickName string `json:"nickName"` OldPassword string `json:"oldPassword"` NewPassword string `json:"newPassword"` PrivacyMode *bool `json:"privacyMode"` } // Register 代理上游注册,成功后写入登录 cookie。 func Register(c *gin.Context) { var body registerBody if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 1001, "msg": "参数错误", "tip": "参数错误", "data": nil, }) return } body.AccountNo = strings.TrimSpace(body.AccountNo) body.Email = strings.TrimSpace(body.Email) body.AgentInviteCode = strings.TrimSpace(body.AgentInviteCode) body.DevID = strings.TrimSpace(body.DevID) body.Channel = strings.TrimSpace(body.Channel) if body.AccountNo == "" || body.Password == "" { c.JSON(http.StatusOK, gin.H{ "code": 1001, "msg": "参数错误", "tip": "请填写账号和密码", "data": nil, }) return } // 上游 registerReq 仍要求 email;前端已去掉邮箱输入时,用账号生成唯一占位邮箱。 if body.Email == "" { body.Email = body.AccountNo + "@qmdj.local" } env, user, err := authser.Register(c, authser.RegisterReq{ AccountNo: body.AccountNo, Email: body.Email, Password: body.Password, AgentInviteCode: body.AgentInviteCode, DevID: body.DevID, Channel: body.Channel, }) if err != nil { log.Error("register upstream failed", log.E(err)) c.JSON(http.StatusOK, gin.H{ "code": 500, "msg": "register failed", "tip": "注册失败,请稍后重试", "data": nil, }) return } if env.Code != 200 || user == nil { tip := strings.TrimSpace(env.Tip) if tip == "" { tip = strings.TrimSpace(env.Msg) } if tip == "" { tip = "注册失败" } c.JSON(http.StatusOK, gin.H{ "code": env.Code, "msg": env.Msg, "tip": tip, "data": nil, }) return } authser.SetAuthCookies(c, user) c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": env.Msg, "tip": firstNonEmpty(env.Tip, "注册成功"), "data": user, }) } // Login 代理上游登录,成功后写入登录 cookie。 func Login(c *gin.Context) { var body loginBody if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 1001, "msg": "参数错误", "tip": "参数错误", "data": nil, }) return } body.Account = strings.TrimSpace(body.Account) body.DevID = strings.TrimSpace(body.DevID) body.Channel = strings.TrimSpace(body.Channel) if body.Account == "" || body.Password == "" { c.JSON(http.StatusOK, gin.H{ "code": 1001, "msg": "参数错误", "tip": "请填写账号和密码", "data": nil, }) return } env, user, err := authser.Login(c, authser.LoginReq{ Account: body.Account, Password: body.Password, DevID: body.DevID, Channel: body.Channel, }) if err != nil { log.Error("login upstream failed", log.E(err)) c.JSON(http.StatusOK, gin.H{ "code": 500, "msg": "login failed", "tip": "登录失败,请稍后重试", "data": nil, }) return } if env.Code != 200 || user == nil { tip := strings.TrimSpace(env.Tip) if tip == "" { tip = strings.TrimSpace(env.Msg) } if tip == "" { tip = "登录失败" } c.JSON(http.StatusOK, gin.H{ "code": env.Code, "msg": env.Msg, "tip": tip, "data": nil, }) return } authser.SetAuthCookies(c, user) c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": env.Msg, "tip": firstNonEmpty(env.Tip, "登录成功"), "data": user, }) } // ResetPassword 代理上游找回密码接口。 func ResetPassword(c *gin.Context) { var body resetPasswordBody if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 1001, "msg": "参数错误", "tip": "参数错误", "data": nil}) return } body.AccountNo = strings.TrimSpace(body.AccountNo) body.Email = strings.TrimSpace(body.Email) if body.AccountNo == "" || body.Email == "" || body.NewPassword == "" { c.JSON(http.StatusOK, gin.H{"code": 1001, "msg": "参数错误", "tip": "请填写账号、邮箱和新密码", "data": nil}) return } env, err := authser.ResetPassword(c, authser.ResetPasswordReq{ AccountNo: body.AccountNo, Email: body.Email, NewPassword: body.NewPassword, }) if err != nil { log.Error("reset password upstream failed", log.E(err)) c.JSON(http.StatusOK, gin.H{"code": 500, "msg": "reset password failed", "tip": "重置密码失败,请稍后重试", "data": nil}) return } tip := firstNonEmpty(env.Tip, env.Msg) if env.Code == 200 { tip = firstNonEmpty(tip, "密码重置成功") } else { tip = firstNonEmpty(tip, "密码重置失败") } c.JSON(http.StatusOK, gin.H{"code": env.Code, "msg": env.Msg, "tip": tip, "data": env.Data}) } // Guest 代理上游游客登录,成功后写入登录 cookie。 // 对应 POST /api/app/auth/guest;需传 devID,上游要求 X-User-Agent(由 BFF 组装)。 func Guest(c *gin.Context) { var body struct { DevID string `json:"devID"` DeviceID string `json:"deviceId"` Mac string `json:"mac"` Channel string `json:"channel"` } if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 1001, "msg": "参数错误", "tip": "参数错误", "data": nil, }) return } body.DevID = strings.TrimSpace(body.DevID) body.DeviceID = strings.TrimSpace(body.DeviceID) body.Mac = strings.TrimSpace(body.Mac) body.Channel = strings.TrimSpace(body.Channel) if body.DevID == "" { c.JSON(http.StatusOK, gin.H{ "code": 1001, "msg": "参数错误", "tip": "缺少设备标识", "data": nil, }) return } if body.DeviceID == "" { body.DeviceID = body.DevID } env, user, err := authser.GuestLogin(c, authser.GuestLoginReq{ DevID: body.DevID, DeviceID: body.DeviceID, Mac: body.Mac, Channel: body.Channel, }) if err != nil { log.Error("guest login upstream failed", log.E(err)) c.JSON(http.StatusOK, gin.H{ "code": 500, "msg": "guest login failed", "tip": "游客登录失败,请稍后重试", "data": nil, }) return } if env.Code != 200 || user == nil { tip := strings.TrimSpace(env.Tip) if tip == "" { tip = strings.TrimSpace(env.Msg) } if tip == "" { tip = "游客登录失败" } c.JSON(http.StatusOK, gin.H{ "code": env.Code, "msg": env.Msg, "tip": tip, "data": nil, }) return } authser.SetAuthCookies(c, user) c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": firstNonEmpty(env.Msg, "success"), "tip": firstNonEmpty(env.Tip, "游客登录成功"), "data": user, }) } // UpdateProfile 代理上游修改资料,成功后刷新 getInfo 并写 cookie。 func UpdateProfile(c *gin.Context) { var body updateProfileBody if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 1001, "msg": "参数错误", "tip": "参数错误", "data": nil, }) return } body.Avatar = strings.TrimSpace(body.Avatar) body.Introduction = strings.TrimSpace(body.Introduction) body.NickName = strings.TrimSpace(body.NickName) body.OldPassword = strings.TrimSpace(body.OldPassword) body.NewPassword = strings.TrimSpace(body.NewPassword) req := authser.UpdateProfileReq{ Avatar: body.Avatar, Introduction: body.Introduction, NickName: body.NickName, OldPassword: body.OldPassword, NewPassword: body.NewPassword, PrivacyMode: body.PrivacyMode, } if req.Avatar == "" && req.Introduction == "" && req.NickName == "" && req.OldPassword == "" && req.NewPassword == "" && req.PrivacyMode == nil { c.JSON(http.StatusOK, gin.H{ "code": 1001, "msg": "参数错误", "tip": "请至少修改一项资料", "data": nil, }) return } if (req.OldPassword == "") != (req.NewPassword == "") { c.JSON(http.StatusOK, gin.H{ "code": 1001, "msg": "参数错误", "tip": "修改密码需同时填写旧密码和新密码", "data": nil, }) return } env, err := authser.UpdateProfile(c, req) if err != nil { log.Error("update profile upstream failed", log.E(err)) c.JSON(http.StatusOK, gin.H{ "code": 500, "msg": "update profile failed", "tip": "保存失败,请稍后重试", "data": nil, }) return } if env != nil && TryJSONSessionRecover(c, env.Code) { env, err = authser.UpdateProfile(c, req) if err != nil { log.Error("update profile retry failed", log.E(err)) c.JSON(http.StatusOK, gin.H{ "code": 500, "msg": "update profile failed", "tip": "保存失败,请稍后重试", "data": nil, }) return } } if env == nil || env.Code != 200 { tip := "保存失败" msg := "" code := 500 if env != nil { code = env.Code msg = env.Msg tip = firstNonEmpty(env.Tip, env.Msg, tip) } c.JSON(http.StatusOK, gin.H{ "code": code, "msg": msg, "tip": tip, "data": nil, }) return } // 上游成功后拉最新资料写 cookie _, user, infoErr := authser.GetInfo(c) if infoErr != nil || user == nil { log.Error("update profile getInfo failed", log.E(infoErr)) c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": env.Msg, "tip": firstNonEmpty(env.Tip, "保存成功"), "data": nil, }) return } authser.SetAuthCookies(c, user) c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": env.Msg, "tip": firstNonEmpty(env.Tip, "保存成功"), "data": user, }) } // UploadImage 代理上游图片上传(头像不加 watermark)。 func UploadImage(c *gin.Context) { fileHeader, err := c.FormFile("file") if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 1001, "msg": "参数错误", "tip": "请选择图片文件", "data": nil, }) return } f, err := fileHeader.Open() if err != nil { c.JSON(http.StatusOK, gin.H{ "code": 500, "msg": "open file failed", "tip": "读取图片失败", "data": nil, }) return } defer f.Close() resp, err := authser.UploadImage(c, fileHeader.Filename, f) if err != nil { log.Error("upload image upstream failed", log.E(err)) c.JSON(http.StatusOK, gin.H{ "code": 500, "msg": "upload failed", "tip": "上传失败,请稍后重试", "data": nil, }) return } if resp == nil || resp.Code != 200 || resp.Data == nil || strings.TrimSpace(resp.Data.SourceNameFs) == "" { tip := "上传失败" msg := "" code := 500 if resp != nil { code = resp.Code msg = resp.Msg tip = firstNonEmpty(resp.Tip, resp.Msg, tip) } c.JSON(http.StatusOK, gin.H{ "code": code, "msg": msg, "tip": tip, "data": nil, }) return } c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": firstNonEmpty(resp.Msg, "success"), "tip": firstNonEmpty(resp.Tip, "上传成功"), "data": gin.H{ "id": resp.Data.ID, "sourceNameFs": resp.Data.SourceNameFs, "url": resp.Data.SourceNameFs, }, }) } // GetUserInfo 代理上游 GET /api/app/auth/getInfo。 func GetUserInfo(c *gin.Context) { if useragent.TokenFromRequest(c.Request) == "" { c.JSON(http.StatusOK, gin.H{ "code": 401, "msg": "unauthorized", "tip": "请先登录", "data": nil, }) return } env, user, err := authser.GetInfo(c) if err != nil { log.Error("getInfo upstream failed", log.E(err)) c.JSON(http.StatusOK, gin.H{ "code": 500, "msg": "getInfo failed", "tip": "获取用户信息失败,请稍后重试", "data": nil, }) return } if env != nil && TryJSONSessionRecover(c, env.Code) { env, user, err = authser.GetInfo(c) if err != nil { log.Error("getInfo retry failed", log.E(err)) c.JSON(http.StatusOK, gin.H{ "code": 500, "msg": "getInfo failed", "tip": "获取用户信息失败,请稍后重试", "data": nil, }) return } } if env == nil || env.Code != 200 || user == nil { tip := "获取用户信息失败" msg := "" code := 500 if env != nil { code = env.Code msg = env.Msg tip = firstNonEmpty(env.Tip, env.Msg, tip) } c.JSON(http.StatusOK, gin.H{ "code": code, "msg": msg, "tip": tip, "data": nil, }) return } authser.SetAuthCookies(c, user) c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": firstNonEmpty(env.Msg, "success"), "tip": firstNonEmpty(env.Tip, "成功"), "data": user, }) } func firstNonEmpty(values ...string) string { for _, v := range values { if strings.TrimSpace(v) != "" { return v } } return "" }