按意图重做在 huakui 代码底: - 删除数据埋点逻辑:移除 pub/dataReport、reportser、srv_report、 eventmod、上报定时任务及注册/登录/点赞/收藏/评论/解锁/订单处的 上报调用和 reportSdkConfig 配置下发 - app 认证改为按设备ID识别用户:去掉 token 校验、Register/Login/ ResetPassword/GuestLogin 接口,新增 ResolveDeviceUser 和设备缓存 - 广告改为按 AppId 从媒资中心拉取:pub/storage 新增 QueryAdvitise, UpdateAdvitiseData 替代 UpdateAdvitiseDataFromJt - 后台登录取消谷歌二次验证,密码正确即登录 - 短剧/专题 slug 改为 10 位大小写字母+数字混合 - 本地 app.yaml/web.yaml 保留 HKDJNET_* 模板(不提交生产凭据) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
179 lines
6.1 KiB
Go
179 lines
6.1 KiB
Go
package authser
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
"hkdj-web-server/pub/common/log"
|
|
"hkdj-web-server/pub/common/srvdef"
|
|
"hkdj-web-server/pub/common/useragent"
|
|
"hkdj-web-server/pub/common/utils"
|
|
"hkdj-web-server/pub/models/usermod"
|
|
"hkdj-web-server/pub/pubdef"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
)
|
|
|
|
var defaultAvatars = []string{
|
|
"v3/image/bo/ty/1016/girl1.jpeg",
|
|
"v3/image/re/9y/1016/girl2.jpeg",
|
|
"v3/image/wr/1t/1016/girl3.jpeg",
|
|
"v3/image/8l/26/1016/girl4.jpeg",
|
|
"v3/image/22/6l/1016/girl5.jpeg",
|
|
"v3/image/8h/16/1016/girl6.jpeg",
|
|
"v3/image/wj/15/1016/girl7.jpeg",
|
|
"v3/image/t2/13/1016/girl8.jpeg",
|
|
"v3/image/4r/j/1016/girl9.jpeg",
|
|
"v3/image/16c/9/1016/girl10.jpeg",
|
|
}
|
|
|
|
func randomAvatar() string {
|
|
idx := time.Now().UnixNano() % int64(len(defaultAvatars))
|
|
return defaultAvatars[idx]
|
|
}
|
|
|
|
// generateUniqueInviteCode 生成不与已有用户冲突的 12 位邀请码(简化实现)
|
|
func generateUniqueInviteCode(ctx context.Context) string {
|
|
return strings.ToUpper(utils.GetRandomLetters(12))
|
|
}
|
|
|
|
// LoginResp 用户信息
|
|
type LoginResp struct {
|
|
UserId int64 `json:"userId"`
|
|
AccountNo string `json:"accountNo"`
|
|
Email string `json:"email"`
|
|
NickName string `json:"nickName"`
|
|
Avatar string `json:"avatar"`
|
|
Introduction string `json:"introduction"`
|
|
DevID string `json:"devID"`
|
|
Mac string `json:"mac"`
|
|
DeviceId string `json:"deviceId"`
|
|
InviteCode string `json:"inviteCode"`
|
|
AgentInviteCode string `json:"agentInviteCode"`
|
|
Invites int64 `json:"invites"`
|
|
Status pubdef.UserStatus `json:"status"`
|
|
Type pubdef.UserType `json:"type"` // 身份类型:0游客 1普通用户
|
|
LoginType pubdef.LoginType `json:"loginType"` // 登陆方式
|
|
IsRegister bool `json:"isRegister"` // 是否已注册
|
|
PrivacyMode bool `json:"privacyMode"` // 隐私模式
|
|
Score int64 `json:"score"` // 积分
|
|
Recharge int64 `json:"recharge"` // 金币余额
|
|
}
|
|
|
|
// CrawlerLoginResp 爬虫虚拟游客资料,不对应任何数据库用户。
|
|
func CrawlerLoginResp() *LoginResp {
|
|
return &LoginResp{
|
|
UserId: pubdef.CrawlerUserId,
|
|
NickName: "游客",
|
|
Status: pubdef.UserStatusNormal,
|
|
Type: pubdef.UserTypeGuest,
|
|
LoginType: pubdef.LoginTypeDevice,
|
|
IsRegister: false,
|
|
}
|
|
}
|
|
|
|
// GetInfo 获取当前用户的最新信息
|
|
func GetInfo(ctx context.Context, userId int64, ua useragent.UA) (*LoginResp, *srvdef.SrvErr) {
|
|
if pubdef.IsCrawlerUser(userId) {
|
|
return CrawlerLoginResp(), nil
|
|
}
|
|
user, _ := usermod.FindOneUser(ctx, bson.M{usermod.FN.User.Id: userId})
|
|
if user == nil {
|
|
return nil, srvdef.New(srvdef.ErrUserNotExsit, srvdef.ErrUserNotExsit.Msg(), "")
|
|
}
|
|
now := time.Now()
|
|
setDoc := bson.M{}
|
|
if v := strings.TrimSpace(ua.DevID); v != "" && v != user.DevID {
|
|
setDoc[usermod.FN.User.DevID] = v
|
|
user.DevID = v
|
|
}
|
|
if v := strings.TrimSpace(ua.DevType); v != "" && v != user.Device {
|
|
setDoc[usermod.FN.User.Device] = v
|
|
user.Device = v
|
|
}
|
|
if v := strings.TrimSpace(ua.SysType); v != "" && v != user.SysType {
|
|
setDoc[usermod.FN.User.SysType] = v
|
|
user.SysType = v
|
|
}
|
|
if v := strings.TrimSpace(ua.Ver); v != "" && v != user.AppVer {
|
|
setDoc[usermod.FN.User.AppVer] = v
|
|
user.AppVer = v
|
|
}
|
|
mergeUAExtFieldsToSet(setDoc, user, ua)
|
|
if len(setDoc) > 0 {
|
|
setDoc[usermod.FN.User.UpdatedAt] = now
|
|
_ = usermod.UpdateOneUser(ctx, bson.M{usermod.FN.User.Id: user.Id}, bson.M{"$set": setDoc})
|
|
}
|
|
return toLoginResp(ctx, user, true), nil
|
|
}
|
|
|
|
func mergeUAExtFieldsToSet(setDoc bson.M, user *usermod.User, ua useragent.UA) {
|
|
if v := strings.TrimSpace(ua.SessionID); v != "" && v != user.SessionID {
|
|
setDoc[usermod.FN.User.SessionID] = v
|
|
}
|
|
if v := strings.TrimSpace(ua.DeviceBrand); v != "" && v != user.DeviceBrand {
|
|
setDoc[usermod.FN.User.DeviceBrand] = v
|
|
}
|
|
if v := strings.TrimSpace(ua.DeviceModel); v != "" && v != user.DeviceModel {
|
|
setDoc[usermod.FN.User.DeviceModel] = v
|
|
}
|
|
if v := strings.TrimSpace(ua.SystemName); v != "" && v != user.SystemName {
|
|
setDoc[usermod.FN.User.SystemName] = v
|
|
}
|
|
if v := strings.TrimSpace(ua.SystemVersion); v != "" && v != user.SystemVersion {
|
|
setDoc[usermod.FN.User.SystemVersion] = v
|
|
}
|
|
if v := strings.TrimSpace(ua.Ver); v != "" && user.OriVer == "" {
|
|
setDoc[usermod.FN.User.OriVer] = v
|
|
}
|
|
}
|
|
|
|
// UpdateProfileReq 修改用户资料的参数(所有字段均为可选)
|
|
type UpdateProfileReq struct {
|
|
UserId int64 // 用户ID(按设备ID识别)
|
|
NickName *string // 新昵称(可选)
|
|
Avatar *string // 新头像 URL(可选)
|
|
Introduction *string // 简介(可选)
|
|
PrivacyMode *bool // 隐私模式:true-开启,false-关闭(可选)
|
|
}
|
|
|
|
// UpdateProfile 修改用户资料:支持修改昵称、头像、简介、隐私模式,或组合修改
|
|
func UpdateProfile(ctx context.Context, req *UpdateProfileReq) *srvdef.SrvErr {
|
|
user, _ := usermod.FindOneUser(ctx, bson.M{usermod.FN.User.Id: req.UserId})
|
|
if user == nil {
|
|
return srvdef.New(srvdef.ErrUserNotExsit, srvdef.ErrUserNotExsit.Msg(), "")
|
|
}
|
|
|
|
setDoc := bson.M{usermod.FN.User.UpdatedAt: time.Now()}
|
|
if req.NickName != nil {
|
|
nick := strings.TrimSpace(*req.NickName)
|
|
if nick == "" {
|
|
return srvdef.New(srvdef.ErrParamError, "昵称不能为空", "")
|
|
}
|
|
setDoc[usermod.FN.User.NickName] = nick
|
|
}
|
|
if req.Avatar != nil {
|
|
setDoc[usermod.FN.User.Avatar] = strings.TrimSpace(*req.Avatar)
|
|
}
|
|
if req.Introduction != nil {
|
|
setDoc[usermod.FN.User.Introduction] = strings.TrimSpace(*req.Introduction)
|
|
}
|
|
if req.PrivacyMode != nil {
|
|
setDoc[usermod.FN.User.PrivacyMode] = *req.PrivacyMode
|
|
}
|
|
|
|
// 没有任何需要更新的字段
|
|
if len(setDoc) == 1 {
|
|
return srvdef.New(srvdef.ErrParamError, "至少需要修改一项资料", "")
|
|
}
|
|
|
|
if serr := usermod.UpdateOneUser(ctx,
|
|
bson.M{usermod.FN.User.Id: user.Id},
|
|
bson.M{"$set": setDoc},
|
|
); serr != nil {
|
|
log.Error("UpdateProfile UpdateOneUser failed", log.Any("userId", user.Id), log.E(serr))
|
|
return serr
|
|
}
|
|
return nil
|
|
}
|