package operation import ( "context" "errors" "fmt" "game/common/model" "game/common/model/user" "game/common/proto/pb" "game/common/serialization" "game/common/utils" "github.com/fox/fox/log" "github.com/go-redis/redis/v8" "gorm.io/gorm" "strconv" ) type UserAccountOp struct { logDb *gorm.DB db *gorm.DB accountRedis *redis.Client accountOp *model.TableOp[user.UserAccount] } func NewUserAccountOp() *UserAccountOp { return &UserAccountOp{ logDb: LogDB, db: UserDB, accountRedis: AccountRedis, accountOp: model.NewTableOp[user.UserAccount](UserDB, AccountRedis), } } func (s *UserAccountOp) redisKey(username string) string { return fmt.Sprintf("username:%s", username) } func (s *UserAccountOp) GetUserAccount(username string) (*user.UserAccount, pb.ErrCode) { sUid, err := s.accountRedis.Get(context.Background(), s.redisKey(username)).Result() if err != nil { if errors.Is(err, redis.Nil) { us := &user.UserAccount{} err = s.db.Where("username = ?", username).First(us).Error if err != nil { log.DebugF("find user:%v err:%v", username, err) return nil, pb.ErrCode_SystemErr } // 从db中查到后写入redis,并建立索引 if us.Username != "" && us.ID > 0 { _, _ = s.accountOp.Update(us.ID, serialization.StructToMap(us)) _ = s.accountRedis.Set(context.Background(), s.redisKey(username), us.ID, model.TableExpire).Err() } return us, pb.ErrCode_OK } else { log.ErrorF("find user:%v err:%v", username, err) return nil, pb.ErrCode_SystemErr } } uid, _ := strconv.ParseInt(sUid, 10, 64) if uid < 0 { log.ErrorF("get user account:%v failed, uid is: %d", username, uid) return nil, pb.ErrCode_SystemErr } return s.accountOp.Find(uid) } // 创建用户 func (s *UserAccountOp) CreateUserAccount(us *user.UserAccount) (*user.UserAccount, pb.ErrCode) { // 密码加密 hashedPassword, err := utils.Password(us.Password) if err != nil { log.ErrorF("username :%v generate password err:%v", us.Username, err) return nil, pb.ErrCode_SystemErr } us.Password = hashedPassword var code pb.ErrCode us, code = s.accountOp.Create(us) log.DebugF("create user:%v", utils.JsonMarshal(us)) if code != pb.ErrCode_OK { return nil, code } // 建立索引 _ = s.accountRedis.Set(context.Background(), s.redisKey(us.Username), us.ID, model.TableExpire).Err() return us, pb.ErrCode_OK } // 更新密码 func (s *UserAccountOp) UpdateUserPassword(us *user.UserAccount) (*user.UserAccount, pb.ErrCode) { // 密码加密 hashedPassword, err := utils.Password(us.Password) if err != nil { log.ErrorF("username :%v generate password err:%v", us.Username, err) return nil, pb.ErrCode_SystemErr } var code pb.ErrCode us, code = s.accountOp.Update(us.ID, map[string]any{"password": hashedPassword}) if code != pb.ErrCode_OK { _ = s.accountRedis.Expire(context.Background(), s.redisKey(us.Username), model.TableExpire).Err() } return us, code } // 记录登录日志 func (s *UserAccountOp) RecordLoginLog(logEntry *user.UserLoginLog) { if err := s.logDb.Create(&logEntry).Error; err != nil { log.ErrorF("记录登录日志失败: %v", err) } } // //// 生成JWT令牌(简化版) //func generateToken(userID uint, username string) (string, error) { // _ = userID // _ = username // // 这里应该使用JWT库生成实际令牌 // // 简化实现,实际项目中请使用安全的JWT实现 // return "generated-token-placeholder", nil //}