325 lines
8.1 KiB
Go
325 lines
8.1 KiB
Go
package logic
|
|
|
|
import (
|
|
"ecs/proto"
|
|
"ecs/proto/pb"
|
|
"errors"
|
|
"github.com/oylshe1314/framework/client/db"
|
|
"github.com/oylshe1314/framework/log"
|
|
"github.com/oylshe1314/framework/server"
|
|
"github.com/oylshe1314/framework/util"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"golang.org/x/crypto/bcrypt"
|
|
"sync"
|
|
)
|
|
|
|
type manager struct {
|
|
server server.Server
|
|
}
|
|
|
|
func (this *manager) Logger() log.Logger {
|
|
return this.server.Logger()
|
|
}
|
|
|
|
type UserManager struct {
|
|
manager
|
|
|
|
mongoClient db.MongoClient
|
|
|
|
locker sync.RWMutex
|
|
users map[string]*User
|
|
tokens map[uint64]string
|
|
}
|
|
|
|
func NewUserManager(svr server.Server, mongoClient db.MongoClient) *UserManager {
|
|
return &UserManager{
|
|
manager: manager{
|
|
server: svr,
|
|
},
|
|
mongoClient: mongoClient,
|
|
users: map[string]*User{},
|
|
tokens: map[uint64]string{},
|
|
}
|
|
}
|
|
|
|
func (this *UserManager) Init() error {
|
|
return nil
|
|
}
|
|
|
|
func (this *UserManager) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (this *UserManager) saveUser(user *User) error {
|
|
_, err := this.mongoClient.Collection(TableUser).InsertOne(this.mongoClient.Context(), user)
|
|
return err
|
|
}
|
|
|
|
func (this *UserManager) queryUser(filter bson.M) (*User, error) {
|
|
var user = new(User)
|
|
var err = this.mongoClient.Collection(TableUser).FindOne(this.mongoClient.Context(), filter).Decode(user)
|
|
if err != nil {
|
|
if errors.Is(err, mongo.ErrNoDocuments) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
return user, nil
|
|
}
|
|
|
|
func (this *UserManager) updateUser(id string, set bson.M) error {
|
|
var _, err = this.mongoClient.Collection(TableUser).UpdateByID(this.mongoClient.Context(), id, bson.M{"$set": set})
|
|
return err
|
|
}
|
|
|
|
func (this *UserManager) signUp(origin *proto.UserOrigin, auth *proto.UserAuth, thirdInfo map[string]interface{}) (*User, error) {
|
|
counter, err := this.mongoClient.Counter("user_id", 1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var uid = util.EncryptUid(counter)
|
|
|
|
if len(auth.Password) > 0 {
|
|
password, err := bcrypt.GenerateFromPassword([]byte(auth.Password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
return nil, err
|
|
}
|
|
|
|
auth.Password = string(password)
|
|
}
|
|
|
|
var user = &User{
|
|
Id: UserKey(origin.Channel, auth.Username),
|
|
UserId: uid,
|
|
Platform: origin.Platform,
|
|
Channel: origin.Channel,
|
|
Username: auth.Username,
|
|
Password: auth.Password,
|
|
CreateTime: util.NowUnix(),
|
|
ThirdInfo: thirdInfo,
|
|
}
|
|
|
|
err = this.saveUser(user)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return user, nil
|
|
}
|
|
|
|
func (this *UserManager) SignUp(origin *proto.UserOrigin, auth *proto.UserAuth) (*User, error) {
|
|
if origin == nil {
|
|
this.Logger().Error("Parameter error, UserOrigin == nil")
|
|
return nil, proto.ErrParameterError
|
|
}
|
|
|
|
if auth == nil {
|
|
this.Logger().Error("Parameter error, UserAuth == nil")
|
|
return nil, proto.ErrParameterError
|
|
}
|
|
|
|
user, err := this.queryUser(bson.M{"_id": UserKey(origin.Channel, auth.Username)})
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
return nil, proto.ErrInternalError
|
|
}
|
|
|
|
if user != nil {
|
|
return nil, proto.ErrUsernameExists
|
|
}
|
|
|
|
user, err = this.signUp(origin, auth, nil)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
return nil, proto.ErrInternalError
|
|
}
|
|
return user, nil
|
|
}
|
|
|
|
func (this *UserManager) Login(origin *proto.UserOrigin, auth *proto.UserAuth, third *proto.UserThird) (*User, string, error) {
|
|
if origin == nil {
|
|
this.Logger().Error("Parameter error, UserOrigin == nil")
|
|
return nil, "", proto.ErrParameterError
|
|
}
|
|
|
|
//var thirdInfo map[string]any
|
|
switch pb.Channel(origin.Channel) {
|
|
case pb.Channel_Internal:
|
|
if auth == nil {
|
|
this.Logger().Error("Parameter error, UserAuth == nil")
|
|
return nil, "", proto.ErrParameterError
|
|
}
|
|
//case pb.Channel_WechatMiniGame:
|
|
// if third == nil {
|
|
// this.logger.Error("Parameter error, UserThird == nil")
|
|
// return nil, "", proto.ErrParameterError
|
|
// }
|
|
//
|
|
// ack, err := wechat.Code2Session(third.Token)
|
|
// if err != nil {
|
|
// this.logger.Error("Code to session failed, ", err)
|
|
// return nil, "", proto.ErrUserLoginFailed
|
|
// }
|
|
//
|
|
// if ack.ErrCode != 0 {
|
|
// this.logger.Error("Third user login failed, msg: ", ack.ErrMsg)
|
|
// return nil, "", proto.ErrUserLoginFailed
|
|
// }
|
|
//
|
|
// auth = &proto.UserAuth{Username: ack.OpenId}
|
|
// thirdInfo = map[string]any{"openid": ack.OpenId, "unionid": ack.UnionId, "sessionKey": ack.SessionKey}
|
|
//case proto.ChannelTapTap:
|
|
// if third == nil {
|
|
// this.logger.Error("Parameter error, UserThird == nil")
|
|
// return nil, "", proto.ErrParameterError
|
|
// }
|
|
//
|
|
// if third.Args == nil || third.Args.TapTap == nil || third.Args.TapTap.MacKey == "" {
|
|
// return nil, "", proto.ErrParameterError
|
|
// }
|
|
//
|
|
// ack, err := taptap.AccountProfile(third.Token, third.Args.TapTap.MacKey)
|
|
// if err != nil {
|
|
// this.logger.Error(err)
|
|
// return nil, "", proto.ErrUserLoginFailed
|
|
// }
|
|
//
|
|
// if !ack.Success {
|
|
// return nil, "", proto.ErrUserLoginFailed
|
|
// }
|
|
//
|
|
// auth = &proto.UserAuth{Username: ack.Data.Openid}
|
|
// thirdInfo = map[string]interface{}{"name": ack.Data.Name, "avatar": ack.Data.Avatar}
|
|
default:
|
|
return nil, "", proto.ErrChannelError
|
|
}
|
|
|
|
user, err := this.queryUser(bson.M{"_id": UserKey(origin.Channel, auth.Username)})
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
return nil, "", proto.ErrInternalError
|
|
}
|
|
|
|
if user == nil {
|
|
user, err = this.signUp(origin, auth, nil)
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
return nil, "", proto.ErrInternalError
|
|
}
|
|
} else {
|
|
if user.BanLogin && user.BanLoginTime > util.NowUnix() {
|
|
return nil, "", proto.ErrUserBanLogin
|
|
}
|
|
|
|
if len(auth.Password) > 0 {
|
|
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(auth.Password))
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
return nil, "", proto.ErrPasswordError
|
|
}
|
|
}
|
|
|
|
//if thirdInfo != nil {
|
|
// if !reflect.DeepEqual(user.ThirdInfo, thirdInfo) {
|
|
// user.ThirdInfo = thirdInfo
|
|
// err = this.updateUser(user.Id, bson.M{"third_info": user.ThirdInfo})
|
|
// if err != nil {
|
|
// this.Logger().Error(err)
|
|
// return nil, "", proto.ErrInternalError
|
|
// }
|
|
// }
|
|
//}
|
|
}
|
|
|
|
var token = util.RandomToken()
|
|
|
|
this.locker.Lock()
|
|
defer this.locker.Unlock()
|
|
|
|
if expired, ok := this.tokens[user.UserId]; ok {
|
|
delete(this.users, expired)
|
|
}
|
|
|
|
this.users[token] = user
|
|
this.tokens[user.UserId] = token
|
|
|
|
return user, token, nil
|
|
}
|
|
|
|
func (this *UserManager) TokenVerify(token string, serverId uint32) (*User, error) {
|
|
this.locker.RLock()
|
|
var user = this.users[token]
|
|
this.locker.RUnlock()
|
|
if user == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
if user.RecentServer != serverId {
|
|
user.RecentServer = serverId
|
|
var err = this.updateUser(user.Id, bson.M{"recent_server": user.RecentServer})
|
|
if err != nil {
|
|
this.Logger().Error(err)
|
|
return nil, proto.ErrInternalError
|
|
}
|
|
}
|
|
|
|
return user, nil
|
|
}
|
|
|
|
//func (this *UserManager) Ban(userId string, banDays uint32) error {
|
|
// user, err := this.queryUser(bson.M{"_id": userId})
|
|
// if err != nil {
|
|
// this.logger.Error("Query user error, ", err)
|
|
// return proto.RawErrInternalError
|
|
// }
|
|
//
|
|
// if user == nil {
|
|
// return proto.RawErrUserNotExists
|
|
// }
|
|
//
|
|
// if banDays == 0 {
|
|
// user.BanLogin = false
|
|
// user.BanLoginTime = int64(0)
|
|
// } else {
|
|
// user.BanLogin = true
|
|
// user.BanLoginTime = util.TodayBeginTime() + 86400*int64(banDays)
|
|
// }
|
|
//
|
|
// _, err = this.mongoClient.Collection(TableUser).UpdateByID(this.mongoClient.Context(), user.Id, bson.M{"$set": bson.M{"ban_login": user.BanLogin, "ban_login_time": user.BanLoginTime}})
|
|
// if err != nil {
|
|
// this.logger.Error(err)
|
|
// return proto.RawErrInternalError
|
|
// }
|
|
//
|
|
// if banDays == 0 {
|
|
// return nil
|
|
// }
|
|
//
|
|
// return nil
|
|
//}
|
|
//
|
|
//func (this *UserManager) ResetPassword(userId string, password string) error {
|
|
// user, err := this.queryUser(bson.M{"_id": userId})
|
|
// if err != nil {
|
|
// this.logger.Error("Query user error, ", err)
|
|
// return proto.RawErrInternalError
|
|
// }
|
|
//
|
|
// if user == nil {
|
|
// return proto.RawErrUserNotExists
|
|
// }
|
|
//
|
|
// user.Password = password
|
|
//
|
|
// _, err = this.mongoClient.Collection(TableUser).UpdateByID(this.mongoClient.Context(), user.Id, bson.M{"$set": bson.M{"password": user.Password}})
|
|
// if err != nil {
|
|
// this.logger.Error(err)
|
|
// return proto.RawErrInternalError
|
|
// }
|
|
//
|
|
// return nil
|
|
//}
|