diff --git a/apps/user.go b/apps/user.go index 1fc3868..c9ef1fd 100644 --- a/apps/user.go +++ b/apps/user.go @@ -15,7 +15,7 @@ func InitUserGroup(g *echo.Group) { //注册 g.POST("register", func(c echo.Context) error { - req := new(dto.ThirdRegisterReq) + req := new(dto.RegisterReq) if err := c.Bind(req); err != nil { return c.JSON(http.StatusOK, utils.Error(err)) } @@ -28,7 +28,7 @@ func InitUserGroup(g *echo.Group) { } //登录 - token, _ := service.Login.Login(ctx, dto.ThirdLoginReq{ + token, _ := service.Login.Login(ctx, dto.LoginReq{ Account: req.Account, Password: req.Password, }) @@ -38,7 +38,7 @@ func InitUserGroup(g *echo.Group) { //登录 g.POST("login", func(c echo.Context) error { - req := new(dto.ThirdLoginReq) + req := new(dto.LoginReq) if err := c.Bind(req); err != nil { return c.JSON(http.StatusOK, utils.Error(err)) } @@ -70,7 +70,7 @@ func InitUserGroup(g *echo.Group) { //重置密码 g.POST("resetPwd", func(c echo.Context) error { - req := new(dto.ThirdResetPwdReq) + req := new(dto.ResetPwdReq) if err := c.Bind(req); err != nil { return c.JSON(http.StatusOK, utils.Error(err)) } diff --git a/common/constant/redis.go b/common/constant/redis.go index 5b7cea6..78fbc61 100644 --- a/common/constant/redis.go +++ b/common/constant/redis.go @@ -1,7 +1,7 @@ package constant const ( - THIRD_LOGIN_TOKEN = "third:login:token:" + THIRD_LOGIN_TOKEN = ":login:token:" G_RESET_PWD_CODE = "g:reset:pwd:email:" ) diff --git a/common/dto/third_user_login.go b/common/dto/third_user_login.go index 01f5fbd..d834e35 100644 --- a/common/dto/third_user_login.go +++ b/common/dto/third_user_login.go @@ -1,20 +1,17 @@ package dto -type ThirdRegisterReq struct { - Account string `json:"account"` // 帐号 +type RegisterReq struct { + LoginReq - Password string `json:"password"` // 密码 - - Name string `json:"name"` // 昵称 - - Icon string `json:"icon"` // 头像 + NickName *string `json:"nickName"` // 昵称 + Avatar *string `json:"avatar"` // 头像 } type SendResetPwdCodeReq struct { Account string `json:"account"` // 帐号 } -type ThirdResetPwdReq struct { +type ResetPwdReq struct { Account string `json:"account"` // 帐号 Password string `json:"password"` // 密码 @@ -22,13 +19,21 @@ type ThirdResetPwdReq struct { Code string `json:"code"` // 验证码 } -type ThirdLoginReq struct { - Account string `json:"account"` // 帐号 +type LoginReq struct { + Account *string `json:"account"` // 帐号 + Email *string `json:"email"` // 邮箱 + Phone *string `json:"phone"` // 手机号码 + + WxId *string `json:"wxId"` // 微信unionId + QqId *string `json:"qqId"` // qqId + + GoogleId *string `json:"googleId"` // googleId + FacebookId *string `json:"facebookId"` // facebookId Password string `json:"password"` // 密码 } -type ThirdUserLoginToken struct { +type UserLoginToken struct { Uid uint64 `json:"uid"` AccessToken string `json:"accessToken"` } diff --git a/common/dto/user_vo.go b/common/dto/user_vo.go new file mode 100644 index 0000000..cec2172 --- /dev/null +++ b/common/dto/user_vo.go @@ -0,0 +1,10 @@ +package dto + +type UserVO struct { + Sn string `json:"sn"` + Token string `json:"token"` + Account *string `json:"Account"` + + Nickname *string `json:"nickname"` + Avatar *string `json:"avatar"` +} diff --git a/common/filter/limit.go b/common/filter/limit.go index c02e27e..e5314aa 100644 --- a/common/filter/limit.go +++ b/common/filter/limit.go @@ -16,7 +16,7 @@ func UseLimit(next echo.HandlerFunc) echo.HandlerFunc { bizId := c.Get(constant.BizId).(uint64) uid := c.Get(constant.UID).(uint64) - breakLimit := service.ThirdApiLimit.BreakLimit(c.Request().Context(), corpId, bizId, uid) + breakLimit := service.ApiLimit.BreakLimit(c.Request().Context(), corpId, bizId, uid) if breakLimit { return c.JSON(http.StatusOK, map[string]interface{}{ "code": http.StatusNotAcceptable, diff --git a/infrastructure/convert/user_convert.go b/infrastructure/convert/user_convert.go new file mode 100644 index 0000000..84032ae --- /dev/null +++ b/infrastructure/convert/user_convert.go @@ -0,0 +1,41 @@ +package convert + +import ( + "mylomen_server/common/dto" + "mylomen_server/common/utils" + "mylomen_server/infrastructure/repository" +) + +func UserReq2DO(req dto.RegisterReq) repository.UserDO { + data := repository.UserDO{} + data.Account = req.Account + data.GoogleId = req.GoogleId + data.FacebookId = req.FacebookId + data.WxId = req.WxId + data.QqId = req.QqId + data.Phone = req.Phone + data.Email = req.Email + + data.NickName = req.NickName + if data.NickName == nil { + data.NickName = utils.ToPtr("default") + } + //todo 默认头像 + data.Avatar = req.Avatar + if data.Avatar == nil { + data.Avatar = utils.ToPtr("default") + } + + return data +} + +func UserDO2VO(req repository.UserDO) dto.UserVO { + data := dto.UserVO{} + + data.Sn = req.Sn + data.Account = req.Account + data.Nickname = req.NickName + data.Avatar = req.Avatar + + return data +} diff --git a/infrastructure/repository/g_account.go b/infrastructure/repository/g_account.go index 4779e48..53e689b 100644 --- a/infrastructure/repository/g_account.go +++ b/infrastructure/repository/g_account.go @@ -1,8 +1,13 @@ package repository -import "context" +import ( + "context" + "mylomen_server/common/dto" +) type gUserRepository interface { + FindByReq(ctx context.Context, req dto.LoginReq) *UserDO + FindById(ctx context.Context, id int64) *UserDO //FindByAccount 根据 account 查询用户 FindByAccount(ctx context.Context, account string) *UserDO diff --git a/infrastructure/repository/g_account_repository.go b/infrastructure/repository/g_account_repository.go index 23d0a12..afaa825 100644 --- a/infrastructure/repository/g_account_repository.go +++ b/infrastructure/repository/g_account_repository.go @@ -4,23 +4,26 @@ import ( "context" "gorm.io/gorm" "gorm.io/gorm/clause" + "mylomen_server/common/dto" "time" ) // UserDO 游戏帐号表 type UserDO struct { - Id uint64 `gorm:"column:id;type:bigint(20) unsigned;primary_key;AUTO_INCREMENT" json:"id"` - Account string `gorm:"column:account;type:varchar(64);comment:账号;NOT NULL" json:"account"` - Pwd string `gorm:"column:pwd;type:varchar(128);comment:密码;NOT NULL" json:"pwd"` - NickName string `gorm:"column:nickname;type:varchar(64);nickname:昵称" json:"nickname"` - Avatar string `gorm:"column:avatar;type:varchar(128);comment:头像" json:"avatar"` - Gender uint `gorm:"column:gender;type:smallint(4) unsigned;default:0;comment:性别。0:未知 ;1:男;2:女; 3:其他" json:"gender"` - Phone string `gorm:"column:phone;type:varchar(16);comment:手机号码" json:"phone"` - WxId string `gorm:"column:wxId;type:varchar(16);comment:微信unionId" json:"wxId"` - QqId string `gorm:"column:qqId;type:varchar(16);comment:qqId" json:"qqId"` - Email string `gorm:"column:email;type:varchar(64);comment:email" json:"email"` - GoogleId string `gorm:"column:google_id;type:varchar(32);comment:GoogleId" json:"google_id"` - FacebookId string `gorm:"column:facebook_id;type:varchar(32);comment:FacebookId" json:"facebook_id"` + Id uint64 `gorm:"column:id;type:bigint(20) unsigned;primary_key;AUTO_INCREMENT" json:"id"` + Sn string `gorm:"column:sn;type:varchar(64);comment:sn;NOT NULL" json:"sn"` + + Account *string `gorm:"column:account;type:varchar(64);comment:账号;NOT NULL" json:"account"` + Pwd *string `gorm:"column:pwd;type:varchar(128);comment:密码;NOT NULL" json:"pwd"` + NickName *string `gorm:"column:nickname;type:varchar(64);nickname:昵称" json:"nickname"` + Avatar *string `gorm:"column:avatar;type:varchar(128);comment:头像" json:"avatar"` + Gender uint `gorm:"column:gender;type:smallint(4) unsigned;default:0;comment:性别。0:未知 ;1:男;2:女; 3:其他" json:"gender"` + Phone *string `gorm:"column:phone;type:varchar(16);comment:手机号码" json:"phone"` + WxId *string `gorm:"column:wxId;type:varchar(16);comment:微信unionId" json:"wxId"` + QqId *string `gorm:"column:qqId;type:varchar(16);comment:qqId" json:"qqId"` + Email *string `gorm:"column:email;type:varchar(64);comment:email" json:"email"` + GoogleId *string `gorm:"column:google_id;type:varchar(32);comment:GoogleId" json:"google_id"` + FacebookId *string `gorm:"column:facebook_id;type:varchar(32);comment:FacebookId" json:"facebook_id"` VipType uint `gorm:"column:vip_type;type:smallint(4) unsigned;default:0;comment:会员类型:0:非会员;1:普通会员;2:永久会员;NOT NULL" json:"vip_type"` VipExpired *uint64 `gorm:"column:vip_expired;type:smallint(4) unsigned;default:0;comment:会员过期时间;NOT NULL" json:"vip_expired"` @@ -43,7 +46,34 @@ func (m *UserDO) TableName() string { type gUserRepositoryImpl struct { } -func (gUserRepositoryImpl) FindById(ctx context.Context, id int64) *UserDO { +func (rp *gUserRepositoryImpl) FindByReq(ctx context.Context, req dto.LoginReq) *UserDO { + if req.Account != nil { + return rp.FindByAccount(ctx, *req.Account) + } + if req.Email != nil { + return rp.FindByEmail(ctx, *req.Email) + } + if req.Phone != nil { + return rp.FindByPhone(ctx, *req.Phone) + } + + if req.WxId != nil { + return rp.FindByWxId(ctx, *req.WxId) + } + if req.QqId != nil { + return rp.FindByQqId(ctx, *req.QqId) + } + + if req.GoogleId != nil { + return rp.FindByGoogleId(ctx, *req.GoogleId) + } + if req.FacebookId != nil { + return rp.FindByFacebookId(ctx, *req.FacebookId) + } + return nil +} + +func (rp *gUserRepositoryImpl) FindById(ctx context.Context, id int64) *UserDO { //验证参数 if id <= 0 { return nil @@ -60,9 +90,9 @@ func (gUserRepositoryImpl) FindById(ctx context.Context, id int64) *UserDO { return &model } -func (gUserRepositoryImpl) FindByAccount(ctx context.Context, account string) *UserDO { +func (rp *gUserRepositoryImpl) FindByAccount(ctx context.Context, account string) *UserDO { //验证参数 - if account == "" { + if account == "" || len(account) > 32 { return nil } db, ok := ctx.Value("db").(*gorm.DB) @@ -77,9 +107,9 @@ func (gUserRepositoryImpl) FindByAccount(ctx context.Context, account string) *U return &model } -func (gUserRepositoryImpl) FindByEmail(ctx context.Context, email string) *UserDO { +func (rp *gUserRepositoryImpl) FindByEmail(ctx context.Context, email string) *UserDO { //验证参数 - if email == "" { + if email == "" || len(email) > 64 { return nil } db, ok := ctx.Value("db").(*gorm.DB) @@ -94,9 +124,9 @@ func (gUserRepositoryImpl) FindByEmail(ctx context.Context, email string) *UserD return &model } -func (gUserRepositoryImpl) FindByPhone(ctx context.Context, phone string) *UserDO { +func (rp *gUserRepositoryImpl) FindByPhone(ctx context.Context, phone string) *UserDO { //验证参数 - if phone == "" { + if phone == "" || len(phone) > 16 { return nil } db, ok := ctx.Value("db").(*gorm.DB) @@ -111,9 +141,9 @@ func (gUserRepositoryImpl) FindByPhone(ctx context.Context, phone string) *UserD return &model } -func (gUserRepositoryImpl) FindByWxId(ctx context.Context, wxId string) *UserDO { +func (rp *gUserRepositoryImpl) FindByWxId(ctx context.Context, wxId string) *UserDO { //验证参数 - if wxId == "" { + if wxId == "" || len(wxId) > 16 { return nil } db, ok := ctx.Value("db").(*gorm.DB) @@ -128,9 +158,9 @@ func (gUserRepositoryImpl) FindByWxId(ctx context.Context, wxId string) *UserDO return &model } -func (gUserRepositoryImpl) FindByQqId(ctx context.Context, qqId string) *UserDO { +func (rp *gUserRepositoryImpl) FindByQqId(ctx context.Context, qqId string) *UserDO { //验证参数 - if qqId == "" { + if qqId == "" || len(qqId) > 32 { return nil } db, ok := ctx.Value("db").(*gorm.DB) @@ -145,9 +175,9 @@ func (gUserRepositoryImpl) FindByQqId(ctx context.Context, qqId string) *UserDO return &model } -func (gUserRepositoryImpl) FindByGoogleId(ctx context.Context, googleId string) *UserDO { +func (rp *gUserRepositoryImpl) FindByGoogleId(ctx context.Context, googleId string) *UserDO { //验证参数 - if googleId == "" { + if googleId == "" || len(googleId) > 32 { return nil } db, ok := ctx.Value("db").(*gorm.DB) @@ -162,9 +192,9 @@ func (gUserRepositoryImpl) FindByGoogleId(ctx context.Context, googleId string) return &model } -func (gUserRepositoryImpl) FindByFacebookId(ctx context.Context, facebookId string) *UserDO { +func (rp *gUserRepositoryImpl) FindByFacebookId(ctx context.Context, facebookId string) *UserDO { //验证参数 - if facebookId == "" { + if facebookId == "" || len(facebookId) > 32 { return nil } db, ok := ctx.Value("db").(*gorm.DB) @@ -180,7 +210,7 @@ func (gUserRepositoryImpl) FindByFacebookId(ctx context.Context, facebookId stri } // Create 创建用户 -func (gUserRepositoryImpl) Create(ctx context.Context, data *UserDO) error { +func (rp *gUserRepositoryImpl) Create(ctx context.Context, data *UserDO) error { db, ok := ctx.Value("db").(*gorm.DB) if !ok { db = Db @@ -195,7 +225,7 @@ func (gUserRepositoryImpl) Create(ctx context.Context, data *UserDO) error { } // UpdateById 根据ID更新用户 -func (gUserRepositoryImpl) UpdateById(ctx context.Context, data *UserDO) error { +func (rp *gUserRepositoryImpl) UpdateById(ctx context.Context, data *UserDO) error { db, ok := ctx.Value("db").(*gorm.DB) if !ok { db = Db diff --git a/service/third_api_limit.go b/service/third_api_limit.go index 6f4801b..df7cfdf 100644 --- a/service/third_api_limit.go +++ b/service/third_api_limit.go @@ -5,7 +5,7 @@ import "context" type limit struct { } -var ThirdApiLimit limit +var ApiLimit limit func (limit) BreakLimit(ctx context.Context, corpId, bizId, uid uint64) bool { diff --git a/service/third_login.go b/service/third_login.go index a63d113..32968e5 100644 --- a/service/third_login.go +++ b/service/third_login.go @@ -14,6 +14,7 @@ import ( "mylomen_server/common/email" "mylomen_server/common/logs" "mylomen_server/common/utils" + "mylomen_server/infrastructure/convert" "mylomen_server/infrastructure/redis" "mylomen_server/infrastructure/repository" "strings" @@ -29,62 +30,55 @@ var Login login var limiter = rate.NewLimiter(10, 10) // Register 注册 -func (l login) Register(ctx context.Context, req dto.ThirdRegisterReq) error { - acUser := repository.GUser.FindByAccount(ctx, req.Account) +func (l login) Register(ctx context.Context, req dto.RegisterReq) error { + acUser := repository.GUser.FindByReq(ctx, req.LoginReq) if acUser != nil && acUser.Deleted == 0 { return errors.New("user exist") } - var user repository.UserDO - user.Name = req.Name - user.Avatar = req.Icon + userDO := convert.UserReq2DO(req) - user.Email = req.Account //密码加密 h := sha256.Sum256([]byte(req.Password)) passHash := hex.EncodeToString(h[:]) - user.Pwd = passHash + userDO.Pwd = &passHash - repository.GUser.Create(ctx, &user) - return nil + return repository.GUser.Create(ctx, &userDO) } -func (l login) Login(ctx context.Context, req dto.ThirdLoginReq) (string, error) { +func (l login) Login(ctx context.Context, req dto.LoginReq) (*dto.UserVO, error) { start := time.Now().UnixMilli() - //1. 验证账号密码 - h := sha256.Sum256([]byte(req.Password)) - passHash := hex.EncodeToString(h[:]) - acUser := repository.GUser.FindByAccount(ctx, req.Account) + //1. 查询用户 + acUser := repository.GUser.FindByReq(ctx, req) if acUser == nil || acUser.Deleted == 1 { - return "", errors.New("user not exist") - } - if passHash != acUser.Pwd { - return "", errors.New("password is error") + return nil, errors.New("user not exist") } - //生成token + //2. email 和 手机号登录 和account 需要验证密码。其他情况不需要验证密码 + if req.Account != nil || req.Email != nil || req.Phone != nil { + if acUser.Pwd == nil { + return nil, errors.New("password not set") + } + // 验证账号密码 + h := sha256.Sum256([]byte(req.Password)) + passHash := hex.EncodeToString(h[:]) + if acUser.Pwd == nil || passHash != *acUser.Pwd { + return nil, errors.New("password is error") + } + } + + //3. 组装数据 + result := convert.UserDO2VO(*acUser) + + //生成token todo 使用jwt token := uuid.New().String() token = strings.ReplaceAll(token, "-", "") - var thirdUserToken = repository.GLoginToken{ - Uid: acUser.Id, - AccessToken: token, - ExpireTime: time.Now().Add(time.Duration(24*365*100) * time.Hour).UnixMilli(), - } - - gUserToken := repository.GUserToken.FindByUid(ctx, acUser.Id) - if gUserToken == nil { - repository.GUserToken.SaveUserLoginToken(ctx, &thirdUserToken) - return l.GenAccessToken(&thirdUserToken), nil - } - - gUserToken.AccessToken = thirdUserToken.AccessToken - gUserToken.ExpireTime = thirdUserToken.ExpireTime - repository.GUserToken.UpdateUserLoginToken(ctx, gUserToken) + result.Token = token diff := time.Now().UnixMilli() - start logs.NewLog("").Infof("Login cost: %d", diff) - return l.GenAccessToken(gUserToken), nil + return &result, nil } func (l login) SendResetPwdCode(ctx context.Context, account string) error { @@ -116,7 +110,7 @@ func (l login) SendResetPwdCode(ctx context.Context, account string) error { } // ResetPwd 重置密码 -func (l login) ResetPwd(ctx context.Context, req dto.ThirdResetPwdReq) error { +func (l login) ResetPwd(ctx context.Context, req dto.ResetPwdReq) error { //1. 验证code redisStr, err := redis.Get(constant.G_RESET_PWD_CODE + req.Account) if err != nil && redisStr != req.Code { @@ -132,32 +126,17 @@ func (l login) ResetPwd(ctx context.Context, req dto.ThirdResetPwdReq) error { //3. 重置密码 h := sha256.Sum256([]byte(req.Password)) passHash := hex.EncodeToString(h[:]) - acUser.Pwd = passHash + acUser.Pwd = &passHash repository.GUser.UpdateById(ctx, acUser) //生成token token := uuid.New().String() token = strings.ReplaceAll(token, "-", "") - var thirdUserToken = repository.GLoginToken{ - Uid: acUser.Id, - Platform: "web", - AccessToken: token, - ExpireTime: time.Now().Add(time.Duration(24*365*100) * time.Hour).UnixMilli(), - } - loginUserToken := repository.GUserToken.FindByUid(ctx, acUser.Id) - if loginUserToken == nil { - repository.GUserToken.SaveUserLoginToken(ctx, &thirdUserToken) - return nil - } - - loginUserToken.AccessToken = thirdUserToken.AccessToken - loginUserToken.ExpireTime = thirdUserToken.ExpireTime - repository.GUserToken.UpdateUserLoginToken(ctx, loginUserToken) return nil } -func (l login) GetLoginResult(ctx context.Context, c *echo.Context) *dto.ThirdUserLoginToken { +func (l login) GetLoginResult(ctx context.Context, c *echo.Context) *dto.UserVO { accessToken := utils.GetAccessToken(c) if accessToken == "" { return nil @@ -166,31 +145,11 @@ func (l login) GetLoginResult(ctx context.Context, c *echo.Context) *dto.ThirdUs //redis redisStr, err := redis.Get(constant.THIRD_LOGIN_TOKEN + accessToken) if err != nil && redisStr != "" { - var loginInfo dto.ThirdUserLoginToken + var loginInfo dto.UserLoginToken if redisErr := json.Unmarshal([]byte(redisStr), &loginInfo); redisErr == nil { - return &loginInfo + return nil } } - //repository - dbData := repository.GUserToken.FindByToken(ctx, accessToken) - if dbData == nil { - return nil - } - - var finalData = dto.ThirdUserLoginToken{ - Uid: dbData.Uid, - AccessToken: l.GenAccessToken(dbData), - } - - //save into redis - if bytes, saveErr := json.Marshal(finalData); saveErr == nil { - redis.Set(constant.THIRD_LOGIN_TOKEN+accessToken, string(bytes), time.Duration(6)*time.Hour) - } - - return &finalData -} - -func (login) GenAccessToken(data *repository.GLoginToken) string { - return data.AccessToken + return nil }