game_sync/dbproxy/svc/u_account.go

594 lines
16 KiB
Go

package svc
import (
"crypto/md5"
"encoding/hex"
"errors"
"fmt"
"io"
"net/rpc"
"strings"
"time"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/common"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
)
var (
AccountDBName = "user"
AccountCollName = "user_account"
AccountDelBackupCollName = "user_account_del_backup"
ErrAccDBNotOpen = model.NewDBError(AccountDBName, AccountCollName, model.NOT_OPEN)
)
func AccountCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, AccountDBName)
if s != nil {
c, first := s.DB().C(AccountCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"username", "tagkey"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"tel", "tagkey"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"registerts"}, Background: true, Sparse: true})
}
return c
}
return nil
}
func AccountDelBackupCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, AccountDBName)
if s != nil {
c, _ := s.DB().C(AccountDelBackupCollName)
return c
}
return nil
}
type AccountSvc struct {
}
func (svc *AccountSvc) AccountIsExist(args *model.AccIsExistArg, ret *model.AccRet) error {
caccounts := AccountCollection(args.Platform)
if caccounts == nil {
ret.Tag = 0
return ErrAccDBNotOpen
}
acc := &model.Account{}
defer func() {
// 修改旧数据
// 补充渠道信息
svc.setParam(acc)
}()
switch args.LoginType {
case common.LoginTypeGuest:
//游客登录
err := caccounts.Find(bson.M{"username": args.Username, "tagkey": args.TagKey}).One(acc)
if err != nil {
if errors.Is(err, mgo.ErrNotFound) {
ret.Tag = common.LoginNew
return nil
}
return err
}
raw := fmt.Sprintf("%v%v%v", acc.PassWord, common.GetAppId(), args.Ts)
h := md5.New()
io.WriteString(h, raw)
pwd := hex.EncodeToString(h.Sum(nil))
if pwd != args.Password {
logger.Logger.Warnf("Password is error:%v raw:%v get:%v expect:%v", acc.AccountId, raw, args.Password, pwd)
ret.Tag = common.LoginPasswordError
return nil
}
case common.LoginTypeAccount:
//帐号登录
err := caccounts.Find(bson.M{"username": args.Username, "tagkey": args.TagKey}).One(acc)
if err != nil {
logger.Logger.Info("Tel or Password is error:", err)
ret.Tag = common.LoginPasswordError
return nil
}
// 用户密码
userPwd := common.GetRawPassword(acc.TelPassWord, args.Ts)
if userPwd != args.Password {
// 管理员密码
adminPwd := common.GetRawPassword(common.GetRawPassword(model.GameParamData.AdminPassword), args.Ts)
if !model.GameParamData.UseAdminPassword || args.Password != adminPwd {
logger.Logger.Warnf("Password is error: accountId:%v get:%v expect:%v", acc.AccountId, args.Password, userPwd)
ret.Tag = common.LoginPasswordError
return nil
}
}
case common.LoginTypeTelCode:
err := caccounts.Find(bson.M{"tel": args.Tel, "tagkey": args.TagKey}).One(acc)
if err != nil {
if errors.Is(err, mgo.ErrNotFound) {
// 兼容8550开头的手机号,8550和855算同一个区号
if strings.HasPrefix(args.Tel, "855") {
tel := make([]byte, len(args.Tel)+1)
copy(tel, "8550")
copy(tel[4:], args.Tel[3:])
err = caccounts.Find(bson.M{"tel": string(tel), "tagkey": args.TagKey}).One(acc)
if err != nil {
if errors.Is(err, mgo.ErrNotFound) {
ret.Tag = common.LoginNew
return nil
} else {
return err
}
} else {
acc.Tel = args.Tel
caccounts.Update(bson.M{"_id": acc.AccountId}, bson.D{{"$set", bson.D{{"tel", args.Tel}}}})
}
} else {
ret.Tag = common.LoginNew
return nil
}
} else {
return err
}
}
if args.CodeValid {
// 刷新密码和有效期
raw := fmt.Sprintf("%v%v", bson.NewObjectId().Hex(), common.GetAppId())
h := md5.New()
io.WriteString(h, raw)
pwd := hex.EncodeToString(h.Sum(nil))
acc.TelPassWord = pwd
acc.TelPassWordExpire = time.Now().AddDate(0, 0, common.TelLoginValidDays).Unix()
err = caccounts.UpdateId(acc.AccountId, acc)
if err != nil {
return err
}
} else {
// 验证密码和有效期
rawt := fmt.Sprintf("%v%v%v", acc.TelPassWord, common.GetAppId(), args.Ts)
ht := md5.New()
io.WriteString(ht, rawt)
pwdt := hex.EncodeToString(ht.Sum(nil))
if pwdt != args.Password {
logger.Logger.Warnf("Password is error:%v raw:%v get:%v expect:%v", acc.AccountId, rawt, args.Password, pwdt)
ret.Tag = common.LoginPasswordError
return nil
}
// 判断是否过期
if time.Now().Unix()-acc.TelPassWordExpire > 0 { // 过期
logger.Logger.Tracef("TelPassWordExpire AccountId:%v", acc.AccountId)
ret.Tag = common.LoginTelCodeExpire
return nil
}
}
case common.LoginTypeTelegram:
// telegram
err := caccounts.Find(bson.M{"username": args.Username, "tagkey": args.TagKey}).One(acc)
if err != nil {
if errors.Is(err, mgo.ErrNotFound) {
ret.Tag = common.LoginNew
return nil
}
return err
}
if args.VerifyToken {
if acc.PassWord != args.Password {
logger.Logger.Warnf("Password is error:%v get:%v ", acc.AccountId, args.Password)
ret.Tag = common.LoginPasswordError
return nil
}
}
case common.LoginTypeGoogle:
err := caccounts.Find(bson.M{"username": args.Username, "tagkey": args.TagKey}).One(acc)
if err != nil {
if errors.Is(err, mgo.ErrNotFound) {
ret.Tag = common.LoginNew
return nil
}
return err
}
// 验证
case common.RegisterTypeTel:
//帐号注册,验证手机号
err := caccounts.Find(bson.M{"tel": args.Tel, "tagkey": args.TagKey}).One(acc)
if err != nil {
} else {
//手机号已经注册
ret.Tag = common.LoginTelExist
return nil
}
//帐号注册,验证游客帐号
err = caccounts.Find(bson.M{"username": args.Username, "tagkey": args.TagKey}).One(acc)
if err != nil {
//设备号没有注册
//logger.Logger.Info("Username is not Exist:", err)
ret.Tag = common.RegisterNotExist
return nil
} else {
//设备号已经注册
//logger.Logger.Info("Username is Exist:", err)
ret.Tag = common.RegisterExist
return nil
}
case common.RegisterTypeName:
//账号注册 不需要验证手机号
//帐号注册,验证游客帐号
err := caccounts.Find(bson.M{"username": args.Username, "tagkey": args.TagKey}).One(acc)
if err != nil {
//设备号没有注册
//logger.Logger.Info("Username is not Exist:", err)
ret.Tag = common.RegisterNotExist
return nil
} else {
//设备号已经注册
//logger.Logger.Info("Username is Exist:", err)
ret.Tag = common.RegisterExist
return nil
}
default:
ret.Tag = common.LoginTypeNoExist
return nil
}
// freeze
if acc.State > time.Now().Unix() {
ret.Tag = common.LoginFreeze
ret.Acc = acc
return nil
}
// ok
ret.Tag = common.LoginOk
ret.Acc = acc
return nil
}
func (svc *AccountSvc) setParam(acc *model.Account) {
if acc == nil || (acc.Channel != "" && acc.Channel != "0") {
return
}
c := PlayerDataCollection(acc.Platform)
if c == nil {
return
}
p := new(model.PlayerData)
err := c.Find(bson.M{"snid": acc.SnId}).One(p)
if err != nil {
logger.Logger.Errorf("setChannel error:%v", err)
return
}
c = AccountCollection(acc.Platform)
if c == nil {
return
}
acc.Channel = p.Channel
if acc.Channel != "" {
err = c.Update(bson.M{"_id": acc.AccountId}, bson.D{{"$set", bson.D{{"channel", acc.Channel}}}})
if err != nil {
logger.Logger.Errorf("setChannel error:%v", err)
}
}
}
func (svc *AccountSvc) AccountTelIsRegiste(args *model.AccIsExistArg, exist *bool) error {
caccounts := AccountCollection(args.Platform)
if caccounts != nil {
err := caccounts.Find(bson.M{"tel": args.Tel, "tagkey": args.TagKey}).One(nil)
if err == nil {
*exist = true
}
}
*exist = false
return nil
}
func (svc *AccountSvc) InsertAccount(args *model.Account, ret *model.AccRet) error {
caccounts := AccountCollection(args.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
id, err := GetOnePlayerIdFromBucket()
if err == nil {
args.SnId = id
}
err = caccounts.Insert(args)
if err != nil {
logger.Logger.Info("InsertAccount error:", err)
return nil
}
ret.Acc = args
ret.Tag = common.InsertAccountOk
return nil
}
func (svc *AccountSvc) UpgradeAccount(args *model.Account, ret *model.AccRet) error {
caccounts := AccountCollection(args.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
acc := &model.Account{}
err := caccounts.Find(bson.M{"tel": args.Tel, "tagkey": args.TagKey}).One(acc)
if err == nil && acc.AccountId != args.AccountId {
return fmt.Errorf("tel used account %v", acc.AccountId.Hex())
}
if acc.Tel != "" {
return errors.New("Tel is Bind")
}
err = caccounts.Update(bson.M{"_id": args.AccountId}, bson.D{{"$set", bson.D{{"tel", args.Tel}, {"telpassword", args.PassWord}}}})
if err != nil {
logger.Logger.Info("UpgradeAccount error ", err)
}
return err
}
func (svc *AccountSvc) BindTelAccount(args *model.BindTelAccountArgs, ret *model.BindTelAccountRet) error {
caccounts := AccountCollection(args.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
ret.Code = 1
acc := &model.Account{}
err := caccounts.Find(bson.M{"tel": args.Tel, "tagkey": args.TagKey}).One(acc)
if err == nil {
return fmt.Errorf("tel used account %v", acc.AccountId.Hex())
}
if !errors.Is(err, mgo.ErrNotFound) {
return err
}
if acc.Tel != "" {
return errors.New("Tel is Bind")
}
err = caccounts.Update(bson.M{"_id": bson.ObjectIdHex(args.AccId)}, bson.D{{"$set", bson.D{{"tel", args.Tel}}}})
if err != nil {
logger.Logger.Info("BindTelAccount error ", err)
return err
}
ret.Acc = acc
ret.Code = 0
return err
}
func (svc *AccountSvc) LogoutAccount(acc *model.Account, ret *model.AccRet) error {
caccounts := AccountCollection(acc.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
return caccounts.Update(bson.M{"_id": acc.AccountId}, bson.D{{"$set", bson.D{{"logintimes", acc.LoginTimes}, {"lastlogouttime", acc.LastLogoutTime}}}})
}
func (svc *AccountSvc) FreezeAccount(args *model.AccFreezeArg, ret *model.AccRet) error {
caccounts := AccountCollection(args.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
endTime := time.Now().Unix() + int64(time.Minute.Seconds())*int64(args.FreezeTime)
return caccounts.Update(bson.M{"_id": bson.ObjectIdHex(args.AccId)}, bson.D{{"$set", bson.D{{"state", endTime}}}})
}
func (svc *AccountSvc) UnfreezeAccount(args *model.AccFreezeArg, ret *model.AccRet) error {
caccounts := AccountCollection(args.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
return caccounts.Update(bson.M{"_id": bson.ObjectIdHex(args.AccId)}, bson.D{{"$set", bson.D{{"state", 0}}}})
}
func (svc *AccountSvc) getAccount(plt, accId string) (*model.Account, error) {
caccounts := AccountCollection(plt)
if caccounts == nil {
return nil, ErrAccDBNotOpen
}
var acc model.Account
err := caccounts.Find(bson.M{"_id": bson.ObjectIdHex(accId)}).One(&acc)
if err != nil {
return nil, err
}
return &acc, err
}
func (svc *AccountSvc) getAccountBySnId(plt string, snid int32) (*model.Account, error) {
caccounts := AccountCollection(plt)
if caccounts == nil {
return nil, ErrAccDBNotOpen
}
var acc model.Account
err := caccounts.Find(bson.M{"snid": snid}).One(&acc)
if err != nil {
return nil, err
}
return &acc, err
}
func (svc *AccountSvc) GetAccountBySnId(args *model.UserSnidArg, ret *model.AccRet) error {
var err error
ret.Acc, err = svc.getAccountBySnId(args.Platform, args.Snid)
return err
}
func (svc *AccountSvc) getAccountByUserName(plt, username string) (*model.Account, error) {
caccounts := AccountCollection(plt)
if caccounts == nil {
return nil, ErrAccDBNotOpen
}
var acc model.Account
err := caccounts.Find(bson.M{"username": username}).One(&acc)
if err != nil {
return nil, err
}
return &acc, err
}
func (svc *AccountSvc) GetAccountByUserName(args *model.UserNameArg, ret *model.AccRet) error {
var err error
ret.Acc, err = svc.getAccountByUserName(args.Platform, args.UserName)
return err
}
func (svc *AccountSvc) GetAccount(args *model.AccIdArg, ret *model.AccRet) error {
var err error
ret.Acc, err = svc.getAccount(args.Platform, args.AccId)
return err
}
// 删除账号
func (svc *AccountSvc) RemoveAccount(args *model.AccIdArg, ret *model.AccRet) error {
caccounts := AccountCollection(args.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
return caccounts.RemoveId(bson.ObjectIdHex(args.AccId))
}
// pwd暂时用明文.需要使用MD5加密。参照task_login.go
func (svc *AccountSvc) EditAccountPwd(acc *model.Account, ret *model.AccRet) error {
caccounts := AccountCollection(acc.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
hashsum := model.GenAccountPwd(acc.PassWord)
return caccounts.Update(bson.M{"_id": acc.AccountId}, bson.D{{"$set", bson.D{{"backpassword", acc.TelPassWord}, {"telpassword", hashsum}}}})
}
//func (svc *AccountSvc) ResetBackAccountPwd(args *model.AccIdArg, ret *model.AccRet) error {
// caccounts := AccountCollection(args.Platform)
// if caccounts == nil {
// return ErrAccDBNotOpen
// }
//
// var acc model.Account
// err := caccounts.Find(bson.M{"_id": bson.ObjectIdHex(args.AccId)}).One(&acc)
// if err != nil {
// return err
// }
// if len(acc.BackPassWord) > 0 {
// return caccounts.Update(bson.M{"_id": acc.AccountId}, bson.D{{"$set", bson.D{{"telpassword", acc.BackPassWord}}}})
// }
// return nil
//}
/*
* 修改帐号密码
*/
func (svc *AccountSvc) UpdatePlayerPassword(acc *model.Account, ret *model.AccRet) error {
caccounts := AccountCollection(acc.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
return caccounts.Update(bson.M{"_id": acc.AccountId, "telpassword": acc.BackPassWord}, bson.D{{"$set", bson.D{{"telpassword", acc.PassWord}}}})
}
/*
* 修改Token帐号密码
*/
func (svc *AccountSvc) UpdatePlayerTokenPassword(acc *model.Account, ret *model.AccRet) error {
caccounts := AccountCollection(acc.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
return caccounts.Update(bson.M{"_id": acc.AccountId}, bson.D{{"$set", bson.D{{"password", acc.PassWord}}}})
}
/*
* 找回密码
*/
func (svc *AccountSvc) GetBackPlayerPassword(acc *model.Account, ret *model.AccRet) error {
caccounts := AccountCollection(acc.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
return caccounts.Update(bson.M{"tel": acc.Tel, "tagkey": acc.TagKey}, bson.D{{"$set", bson.D{{"telpassword", acc.PassWord}}}})
}
func (svc *AccountSvc) UpdateAccountPlatformInfo(acc *model.Account, ret *model.AccRet) error {
caccounts := AccountCollection(acc.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
return caccounts.Update(bson.M{"_id": acc.AccountId},
bson.D{{"$set", bson.M{"platform": acc.Platform,
"channel": acc.Channel, "packegetag": acc.PackegeTag}}})
}
func (svc *AccountSvc) GetRobotAccounts(limit int, accs *[]model.Account) error {
caccounts := AccountCollection(mongo.G_P)
if caccounts == nil {
return nil
}
*accs = make([]model.Account, 0, limit)
err := caccounts.Find(bson.M{"platform": common.Platform_Rob}).Limit(limit).All(&accs)
if err != nil {
logger.Logger.Info("GetAllRobotAccounts error:", err)
return nil
}
return nil
}
func (svc *AccountSvc) SaveToDelBackupAccount(acc *model.Account, ret *model.AccRet) error {
cDelBackup := AccountDelBackupCollection(acc.Platform)
if cDelBackup == nil {
return ErrAccDBNotOpen
}
_, err := cDelBackup.Upsert(bson.M{"_id": acc.AccountId}, acc)
if err != nil {
logger.Logger.Info("InsertDelBackupAccount error:", err)
}
return err
}
func (svc *AccountSvc) UpdateAccount(acc *model.Account, ret *model.AccRet) error {
caccounts := AccountCollection(acc.Platform)
if caccounts == nil {
return ErrAccDBNotOpen
}
err := caccounts.UpdateId(acc.AccountId, acc)
if err != nil {
logger.Logger.Info("UpdateAccount error:", err)
}
return err
}
var _AccountSvc = &AccountSvc{}
func init() {
rpc.Register(_AccountSvc)
}