init: web_hgdjc_server
This commit is contained in:
@@ -0,0 +1,486 @@
|
||||
package authser
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
"videoweb/app/appg"
|
||||
"videoweb/app/service/reportser"
|
||||
"videoweb/pub/common/enum/consts"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/common/useragent"
|
||||
"videoweb/pub/common/utils"
|
||||
"videoweb/pub/models/usermod"
|
||||
"videoweb/pub/mongos"
|
||||
"videoweb/pub/pubdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var tokener = utils.NewTokenRedis()
|
||||
|
||||
var defaultAvatars = []string{
|
||||
"v3/image/bo/ty/1016/girl1.jpeg",
|
||||
"v3/image/re/9y/1016/girl2.jpeg",
|
||||
"v3/image/5f/k4/1016/girl3.jpeg",
|
||||
"v3/image/ej/ss/1016/girl4.jpeg",
|
||||
"v3/image/yq/ys/1016/girl5.jpeg",
|
||||
"v3/image/9e/d3/1016/girl6.jpeg",
|
||||
}
|
||||
|
||||
func randomAvatar() string {
|
||||
return defaultAvatars[time.Now().UnixNano()%int64(len(defaultAvatars))]
|
||||
}
|
||||
|
||||
// generateUniqueInviteCode 生成 8 位唯一邀请码(纯大写字母),最多重试 10 次
|
||||
func generateUniqueInviteCode(ctx context.Context) string {
|
||||
for i := 0; i < 10; i++ {
|
||||
code := strings.ToUpper(utils.GetRandomLetters(8))
|
||||
exist, _ := usermod.FindOneUser(ctx, bson.M{usermod.FN.User.InviteCode: code})
|
||||
if exist == nil {
|
||||
return code
|
||||
}
|
||||
log.Warn("authser:generateUniqueInviteCode collision, retrying", log.Any("code", code))
|
||||
}
|
||||
// 极小概率走到这里:用更长的随机串兜底
|
||||
return strings.ToUpper(utils.GetRandomLetters(12))
|
||||
}
|
||||
|
||||
// LoginResp 登录/注册成功后的响应数据
|
||||
type LoginResp struct {
|
||||
Token string `json:"token"`
|
||||
UserId int64 `json:"userId"`
|
||||
AccountNo string `json:"accountNo"`
|
||||
Email string `json:"email"`
|
||||
NickName string `json:"nickName"`
|
||||
Introduction string `json:"introduction"` // 简介
|
||||
VipType pubdef.VipType `json:"vipType"`
|
||||
CurrentVipExpire time.Time `json:"currentVipExpire"` // VIP 过期时间,客户端需结合 vipType 判断是否真正有效
|
||||
ShowCardId int64 `json:"showCardId"` // 最新会员卡id
|
||||
ShowCardName string `json:"showCardName"` // 最新会员卡名称
|
||||
Status pubdef.UserStatus `json:"status"`
|
||||
Avatar string `json:"avatar"` // 头像
|
||||
InviteCode string `json:"inviteCode"` // 邀请码
|
||||
Type pubdef.UserType `json:"type"` // 身份类型:0游客 1普通用户
|
||||
LoginType pubdef.LoginType `json:"loginType"` // 登陆方式
|
||||
IsRegister bool `json:"isRegister"` // 是否已注册
|
||||
IsNewUser bool `json:"isNewUser"` // 本次是否新建游客
|
||||
PrivacyMode bool `json:"privacyMode"` // 隐私模式
|
||||
HasPassword bool `json:"hasPassword"` // 是否已设置密码
|
||||
Score int64 `json:"score"` // 积分
|
||||
Recharge int64 `json:"recharge"` // 金币余额
|
||||
}
|
||||
|
||||
// hashPassword 使用 bcrypt 对明文密码进行哈希
|
||||
func hashPassword(plain string) (string, error) {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(plain), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(hash), nil
|
||||
}
|
||||
|
||||
// checkPassword 验证明文密码与 bcrypt 哈希是否匹配
|
||||
func checkPassword(plain, hash string) bool {
|
||||
return bcrypt.CompareHashAndPassword([]byte(hash), []byte(plain)) == nil
|
||||
}
|
||||
|
||||
// generateAndSaveToken 生成 JWT 并存入 Redis
|
||||
func generateAndSaveToken(userId int64) (string, *srvdef.SrvErr) {
|
||||
token, err := utils.GenerateUserToken(utils.UserClaims{
|
||||
UserID: userId,
|
||||
Expire: consts.UserJwtTokenExpire,
|
||||
}, appg.Conf.JwtKey)
|
||||
if err != nil {
|
||||
return "", srvdef.New(srvdef.GenerateTokenFailed, srvdef.GenerateTokenFailed.Msg(), "")
|
||||
}
|
||||
if err = tokener.Save(userId, token); err != nil {
|
||||
return "", srvdef.New(srvdef.StoreLevel, "token存储失败", "")
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// generateCrawlerToken 签发爬虫观看 JWT,不写入 Redis,避免占用真实用户槽位。
|
||||
func generateCrawlerToken() (string, *srvdef.SrvErr) {
|
||||
token, err := utils.GenerateUserToken(utils.UserClaims{
|
||||
UserID: pubdef.CrawlerUserId,
|
||||
Expire: consts.UserJwtTokenExpire,
|
||||
}, appg.Conf.JwtKey)
|
||||
if err != nil {
|
||||
return "", srvdef.New(srvdef.GenerateTokenFailed, srvdef.GenerateTokenFailed.Msg(), "")
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// CrawlerLoginResp 爬虫虚拟游客资料,不对应任何数据库用户。
|
||||
func CrawlerLoginResp(token string) *LoginResp {
|
||||
return &LoginResp{
|
||||
Token: token,
|
||||
UserId: pubdef.CrawlerUserId,
|
||||
NickName: "游客",
|
||||
Status: pubdef.UserStatusNormal,
|
||||
Type: pubdef.UserTypeGuest,
|
||||
LoginType: pubdef.LoginTypeDevice,
|
||||
IsRegister: false,
|
||||
IsNewUser: false,
|
||||
}
|
||||
}
|
||||
|
||||
// Register 用户注册
|
||||
// guestUserId:请求头 Authorization 解析出的用户ID;若为游客则升级该用户,否则新建
|
||||
// agentInviteCode:邀请人的邀请码,可为空
|
||||
func Register(ctx context.Context, guestUserId int64, accountNo, email, password, agentInviteCode string, ua useragent.UA, ip, channel string) (*LoginResp, *srvdef.SrvErr) {
|
||||
accountNo = strings.TrimSpace(accountNo)
|
||||
email = strings.TrimSpace(email)
|
||||
password = strings.TrimSpace(password)
|
||||
|
||||
// 检查账号是否已存在
|
||||
exist, _ := usermod.FindOneUser(ctx, bson.M{usermod.FN.User.AccountNo: accountNo})
|
||||
if exist != nil {
|
||||
return nil, srvdef.New(srvdef.ErrDbInputExist, "账号已存在", "")
|
||||
}
|
||||
// 填写邮箱时检查是否已存在
|
||||
if email != "" {
|
||||
exist, _ = usermod.FindOneUser(ctx, bson.M{usermod.FN.User.Email: email})
|
||||
if exist != nil {
|
||||
return nil, srvdef.New(srvdef.ErrDbInputExist, "邮箱已被注册", "")
|
||||
}
|
||||
}
|
||||
|
||||
hashed, err := hashPassword(password)
|
||||
if err != nil {
|
||||
return nil, srvdef.New(srvdef.Failure, "密码处理失败", "")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
// 请求头带游客 token:升级当前游客为普通用户
|
||||
if guestUserId > 0 {
|
||||
guest, serr := usermod.FindOneUser(ctx, bson.M{usermod.FN.User.Id: guestUserId})
|
||||
if serr == nil && isGuestUser(guest) {
|
||||
setDoc := bson.M{
|
||||
usermod.FN.User.AccountNo: accountNo,
|
||||
usermod.FN.User.Email: email,
|
||||
usermod.FN.User.Password: hashed,
|
||||
usermod.FN.User.Type: pubdef.UserTypeNormal,
|
||||
usermod.FN.User.IsRegister: true,
|
||||
usermod.FN.User.LoginType: pubdef.LoginTypeAccount,
|
||||
usermod.FN.User.RegisterTime: now,
|
||||
usermod.FN.User.LastLoginAt: now,
|
||||
usermod.FN.User.UpdatedAt: now,
|
||||
usermod.FN.User.LastIp: ip,
|
||||
}
|
||||
if agentInviteCode != "" && guest.AgentInviteCode == "" {
|
||||
setDoc[usermod.FN.User.AgentInviteCode] = agentInviteCode
|
||||
setDoc[usermod.FN.User.IsDirect] = false
|
||||
guest.IsDirect = false
|
||||
}
|
||||
if v := strings.TrimSpace(ua.DevID); v != "" {
|
||||
setDoc[usermod.FN.User.DevID] = v
|
||||
}
|
||||
if v := strings.TrimSpace(ua.DevType); v != "" {
|
||||
setDoc[usermod.FN.User.Device] = v
|
||||
}
|
||||
if v := strings.TrimSpace(ua.SysType); v != "" {
|
||||
setDoc[usermod.FN.User.SysType] = v
|
||||
}
|
||||
if v := strings.TrimSpace(ua.Ver); v != "" {
|
||||
setDoc[usermod.FN.User.AppVer] = v
|
||||
}
|
||||
mergeUAExtFieldsToSet(setDoc, guest, ua)
|
||||
if serr = usermod.UpdateOneUser(ctx, bson.M{usermod.FN.User.Id: guest.Id}, bson.M{"$set": setDoc}); serr != nil {
|
||||
return nil, serr
|
||||
}
|
||||
if agentInviteCode != "" && guest.AgentInviteCode == "" {
|
||||
_ = usermod.UpdateOneUser(ctx,
|
||||
bson.M{usermod.FN.User.InviteCode: agentInviteCode},
|
||||
bson.M{
|
||||
"$inc": bson.M{usermod.FN.User.Invites: 1},
|
||||
"$set": bson.M{usermod.FN.User.UpdatedAt: now},
|
||||
},
|
||||
)
|
||||
}
|
||||
guest.AccountNo = accountNo
|
||||
guest.Email = email
|
||||
guest.Type = pubdef.UserTypeNormal
|
||||
guest.IsRegister = true
|
||||
guest.LoginType = pubdef.LoginTypeAccount
|
||||
guest.RegisterTime = now
|
||||
token, serr := generateAndSaveToken(guest.Id)
|
||||
if serr != nil {
|
||||
return nil, serr
|
||||
}
|
||||
reportser.ReportUserRegister(guest, ua, ip, "username")
|
||||
reportser.ReportUserLogin(guest, ua, ip, pubdef.LoginTypeAccount)
|
||||
return toLoginResp(ctx, guest, token, true), nil
|
||||
}
|
||||
}
|
||||
|
||||
user := &usermod.User{
|
||||
Id: mongos.Lid.User.Get(),
|
||||
AccountNo: accountNo,
|
||||
Email: email,
|
||||
Password: hashed,
|
||||
NickName: appg.GenerateNickname(),
|
||||
Avatar: randomAvatar(),
|
||||
InviteCode: generateUniqueInviteCode(ctx),
|
||||
AgentInviteCode: agentInviteCode,
|
||||
Type: pubdef.UserTypeNormal,
|
||||
Status: pubdef.UserStatusNormal,
|
||||
IsRegister: true,
|
||||
LoginType: pubdef.LoginTypeAccount,
|
||||
RegIp: ip,
|
||||
LastIp: ip,
|
||||
DevID: ua.DevID,
|
||||
Device: ua.DevType,
|
||||
SysType: ua.SysType,
|
||||
AppVer: ua.Ver,
|
||||
OriVer: ua.Ver,
|
||||
SessionID: ua.SessionID,
|
||||
DeviceBrand: ua.DeviceBrand,
|
||||
DeviceModel: ua.DeviceModel,
|
||||
SystemName: ua.SystemName,
|
||||
SystemVersion: ua.SystemVersion,
|
||||
DistrictCode: normalizeChannel(channel),
|
||||
IsDirect: resolveUserDistrict(channel, agentInviteCode, ip, ua.SysType).IsDirect,
|
||||
LastLoginAt: now,
|
||||
RegisterTime: now,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if serr := usermod.InsertOneUser(ctx, user); serr != nil {
|
||||
return nil, serr
|
||||
}
|
||||
|
||||
// 若填写了邀请码,给对应用户的 invites +1
|
||||
if agentInviteCode != "" {
|
||||
_ = usermod.UpdateOneUser(ctx,
|
||||
bson.M{usermod.FN.User.InviteCode: agentInviteCode},
|
||||
bson.M{
|
||||
"$inc": bson.M{usermod.FN.User.Invites: 1},
|
||||
"$set": bson.M{usermod.FN.User.UpdatedAt: time.Now()},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
token, serr := generateAndSaveToken(user.Id)
|
||||
if serr != nil {
|
||||
return nil, serr
|
||||
}
|
||||
reportser.ReportUserRegister(user, ua, ip, "username")
|
||||
reportser.ReportUserLogin(user, ua, ip, pubdef.LoginTypeAccount)
|
||||
return toLoginResp(ctx, user, token, false), nil
|
||||
}
|
||||
|
||||
// Login 用户登录(账号或邮箱均可)
|
||||
func Login(ctx context.Context, account, password string, ua useragent.UA, ip, channel string) (*LoginResp, *srvdef.SrvErr) {
|
||||
// 账号或邮箱均可登录
|
||||
user, _ := usermod.FindOneUser(ctx, bson.M{
|
||||
"$or": []bson.M{
|
||||
{usermod.FN.User.AccountNo: account},
|
||||
{usermod.FN.User.Email: account},
|
||||
},
|
||||
})
|
||||
if user == nil {
|
||||
return nil, srvdef.New(srvdef.AccountIsNotExists, srvdef.AccountIsNotExists.Msg(), "")
|
||||
}
|
||||
|
||||
if user.Status == pubdef.UserStatusDisable {
|
||||
return nil, srvdef.New(srvdef.AccountErrAccessForbid, srvdef.AccountErrAccessForbid.Msg(), "")
|
||||
}
|
||||
|
||||
if !checkPassword(password, user.Password) {
|
||||
return nil, srvdef.New(srvdef.AccountErrPasswordError, srvdef.AccountErrPasswordError.Msg(), "")
|
||||
}
|
||||
|
||||
token, serr := generateAndSaveToken(user.Id)
|
||||
if serr != nil {
|
||||
return nil, serr
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
setDoc := bson.M{
|
||||
usermod.FN.User.LastLoginAt: now,
|
||||
usermod.FN.User.UpdatedAt: now,
|
||||
}
|
||||
if ip != "" {
|
||||
setDoc[usermod.FN.User.LastIp] = ip
|
||||
}
|
||||
if v := strings.TrimSpace(ua.DevID); v != "" {
|
||||
setDoc[usermod.FN.User.DevID] = v
|
||||
}
|
||||
if v := strings.TrimSpace(ua.DevType); v != "" {
|
||||
setDoc[usermod.FN.User.Device] = v
|
||||
}
|
||||
if v := strings.TrimSpace(ua.SysType); v != "" {
|
||||
setDoc[usermod.FN.User.SysType] = v
|
||||
}
|
||||
if v := strings.TrimSpace(ua.Ver); v != "" {
|
||||
setDoc[usermod.FN.User.AppVer] = v
|
||||
}
|
||||
// 已有账号的历史用户统一修正为普通用户
|
||||
if strings.TrimSpace(user.AccountNo) != "" && user.Type != pubdef.UserTypeNormal {
|
||||
setDoc[usermod.FN.User.Type] = pubdef.UserTypeNormal
|
||||
setDoc[usermod.FN.User.IsRegister] = true
|
||||
user.Type = pubdef.UserTypeNormal
|
||||
user.IsRegister = true
|
||||
}
|
||||
mergeUAExtFieldsToSet(setDoc, user, ua)
|
||||
_ = usermod.UpdateOneUser(ctx,
|
||||
bson.M{usermod.FN.User.Id: user.Id},
|
||||
bson.M{"$set": setDoc},
|
||||
)
|
||||
reportser.ReportUserLogin(user, ua, ip, pubdef.LoginTypeAccount)
|
||||
return toLoginResp(ctx, user, token, true), nil
|
||||
}
|
||||
|
||||
// GetInfo 获取当前登录用户的最新信息(不刷新 token)
|
||||
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
|
||||
}
|
||||
if v := strings.TrimSpace(ua.DevType); v != "" && v != user.Device {
|
||||
setDoc[usermod.FN.User.Device] = v
|
||||
}
|
||||
if v := strings.TrimSpace(ua.SysType); v != "" && v != user.SysType {
|
||||
setDoc[usermod.FN.User.SysType] = v
|
||||
}
|
||||
if v := strings.TrimSpace(ua.Ver); v != "" && v != user.AppVer {
|
||||
setDoc[usermod.FN.User.AppVer] = v
|
||||
}
|
||||
if strings.TrimSpace(user.AccountNo) != "" && user.Type != pubdef.UserTypeNormal {
|
||||
setDoc[usermod.FN.User.Type] = pubdef.UserTypeNormal
|
||||
setDoc[usermod.FN.User.IsRegister] = true
|
||||
user.Type = pubdef.UserTypeNormal
|
||||
user.IsRegister = true
|
||||
}
|
||||
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 user == nil {
|
||||
return
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateProfileReq 修改用户资料的参数(所有字段均为可选)
|
||||
type UpdateProfileReq struct {
|
||||
UserId int64 // 用户ID(从 token 中获取)
|
||||
NickName *string // 新昵称(可选)
|
||||
Avatar *string // 新头像 URL(可选)
|
||||
Introduction *string // 简介(可选)
|
||||
PrivacyMode *bool // 隐私模式:true-开启,false-关闭(可选)
|
||||
OldPassword *string // 旧密码明文(已设置密码时修改必传)
|
||||
NewPassword *string // 新密码明文(设置或修改密码时必传)
|
||||
}
|
||||
|
||||
// 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 && *req.NickName != "" {
|
||||
setDoc[usermod.FN.User.NickName] = *req.NickName
|
||||
}
|
||||
if req.Avatar != nil && *req.Avatar != "" {
|
||||
setDoc[usermod.FN.User.Avatar] = *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 req.OldPassword != nil || req.NewPassword != nil {
|
||||
if req.NewPassword == nil || strings.TrimSpace(*req.NewPassword) == "" {
|
||||
return srvdef.New(srvdef.ErrParamError, "新密码不能为空", "")
|
||||
}
|
||||
if strings.TrimSpace(user.Password) != "" {
|
||||
if req.OldPassword == nil || strings.TrimSpace(*req.OldPassword) == "" {
|
||||
return srvdef.New(srvdef.ErrParamError, "修改密码时旧密码和新密码均需提供", "")
|
||||
}
|
||||
if !checkPassword(*req.OldPassword, user.Password) {
|
||||
return srvdef.New(srvdef.AccountErrPasswordError, "旧密码错误", "")
|
||||
}
|
||||
} else if req.OldPassword != nil && strings.TrimSpace(*req.OldPassword) != "" {
|
||||
return srvdef.New(srvdef.ErrParamError, "修改密码时旧密码和新密码均需提供", "")
|
||||
}
|
||||
hashed, err := hashPassword(*req.NewPassword)
|
||||
if err != nil {
|
||||
return srvdef.New(srvdef.Failure, "密码处理失败", "")
|
||||
}
|
||||
setDoc[usermod.FN.User.Password] = hashed
|
||||
}
|
||||
|
||||
// 没有任何需要更新的字段
|
||||
if len(setDoc) == 1 {
|
||||
return srvdef.New(srvdef.ErrParamError, "至少需要修改一项资料", "")
|
||||
}
|
||||
|
||||
return usermod.UpdateOneUser(ctx,
|
||||
bson.M{usermod.FN.User.Id: user.Id},
|
||||
bson.M{"$set": setDoc},
|
||||
)
|
||||
}
|
||||
|
||||
// ResetPassword 通过账号+邮箱双重校验后重置密码
|
||||
func ResetPassword(ctx context.Context, accountNo, email, newPassword string) *srvdef.SrvErr {
|
||||
user, _ := usermod.FindOneUser(ctx, bson.M{
|
||||
usermod.FN.User.AccountNo: accountNo,
|
||||
usermod.FN.User.Email: email,
|
||||
})
|
||||
if user == nil {
|
||||
return srvdef.New(srvdef.ErrUserNotExsit, "账号或邮箱不匹配", "")
|
||||
}
|
||||
|
||||
hashed, err := hashPassword(newPassword)
|
||||
if err != nil {
|
||||
return srvdef.New(srvdef.Failure, "密码处理失败", "")
|
||||
}
|
||||
|
||||
return usermod.UpdateOneUser(ctx,
|
||||
bson.M{usermod.FN.User.Id: user.Id},
|
||||
bson.M{"$set": bson.M{
|
||||
usermod.FN.User.Password: hashed,
|
||||
usermod.FN.User.UpdatedAt: time.Now(),
|
||||
}},
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user