fix-20231231-Robin-BUG0001 #28
|
@ -23,16 +23,17 @@ const (
|
|||
|
||||
// apollo_config
|
||||
const (
|
||||
MaxPswdWrongTimesKey = "max_pswd_wrong_times"
|
||||
MaxVeriCodeValidDurationKey = "max_veri_code_valid_duration"
|
||||
IosKey = "ios"
|
||||
AndroidKey = "android"
|
||||
AccountInitKey = "account_init"
|
||||
TagNumKey = "tag_num"
|
||||
PlatformNumKey = "platform_num"
|
||||
SupportWxIdNumKey = "support_wx_id_num"
|
||||
ImageIdForUploadFail = "image_id_for_upload_fail"
|
||||
VideoIdForUploadFail = "video_id_for_upload_fail"
|
||||
MaxPswdWrongTimesKey = "max_pswd_wrong_times"
|
||||
MaxVeriCodeValidDurationKey = "max_veri_code_valid_duration"
|
||||
IosKey = "ios"
|
||||
AndroidKey = "android"
|
||||
AccountInitKey = "account_init"
|
||||
TagNumKey = "tag_num"
|
||||
PlatformNumKey = "platform_num"
|
||||
SupportWxIdNumKey = "support_wx_id_num"
|
||||
MaxDailyVeriCodeSendTimesKey = "max_daily_veri_code_send_times"
|
||||
ImageIdForUploadFail = "image_id_for_upload_fail"
|
||||
VideoIdForUploadFail = "video_id_for_upload_fail"
|
||||
)
|
||||
|
||||
// del_flag
|
||||
|
|
|
@ -126,6 +126,10 @@ var ErrCodeMsgMap = map[ErrCode]string{
|
|||
|
||||
ErrCodeContactCustomerServiceSessionSrvFail: "联系客服对话表服务错误",
|
||||
ErrCodeContactCustomerServiceSessionNotExist: "联系客服对话表不存在",
|
||||
|
||||
ErrCodeVeriCodeSendTimesSrvFail: "验证码频次表服务错误",
|
||||
ErrCodeVeriCodeSendTimesNotExist: "验证码频次表不存在",
|
||||
ErrCodeVeriCodeSendTimesReachedDailyUpperbound: "验证码发送次数已达每日上限",
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -300,6 +304,12 @@ const (
|
|||
ErrCodeContactCustomerServiceSessionSrvFail ErrCode = -24001 // 联系客服对话表服务错误
|
||||
ErrCodeContactCustomerServiceSessionNotExist ErrCode = -24002 // 联系客服对话表不存在
|
||||
|
||||
// VeriCodeSendTimes: 25xxx
|
||||
ErrCodeVeriCodeSendTimesSrvOk ErrCode = ErrCodeOk
|
||||
ErrCodeVeriCodeSendTimesSrvFail ErrCode = -25001 // 验证码频次表服务错误
|
||||
ErrCodeVeriCodeSendTimesNotExist ErrCode = -25002 // 验证码频次表不存在
|
||||
ErrCodeVeriCodeSendTimesReachedDailyUpperbound ErrCode = -25003 // 验证码发送次数已达每日上限
|
||||
|
||||
// Media: 60xxx
|
||||
ErrCodeMediaSrvOk ErrCode = ErrCodeOk
|
||||
ErrCodeMediaSrvFail ErrCode = -60001 // 媒体服务错误
|
||||
|
|
|
@ -15,7 +15,7 @@ func OpSendVeriCode(ctx *gin.Context) {
|
|||
ec := service.DefaultService.OpSendVeriCode(ctx, req)
|
||||
if ec != errcode.ErrCodeLoginSrvOk {
|
||||
logger.Error("OpSendVeriCode fail, req: %v, ec: %v", util.ToJson(req), ec)
|
||||
ReplyErrorMsg(ctx, "server error")
|
||||
ReplyErrCodeMsg(ctx, ec)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ func ApiSendVeriCode(ctx *gin.Context) {
|
|||
ec := service.DefaultService.ApiSendVeriCode(ctx, req)
|
||||
if ec != errcode.ErrCodeLoginSrvOk {
|
||||
logger.Error("ApiSendVeriCode fail, req: %v, ec: %v", util.ToJson(req), ec)
|
||||
ReplyErrorMsg(ctx, "server error")
|
||||
ReplyErrCodeMsg(ctx, ec)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -86,8 +86,9 @@ const (
|
|||
DBAccount = "account"
|
||||
COLAccount = "account"
|
||||
|
||||
DBVeriCode = "vericode"
|
||||
COLVeriCode = "vericode"
|
||||
DBVeriCode = "vericode"
|
||||
COLVeriCode = "vericode"
|
||||
COLVeriCodeSendTimes = "vericode_send_times"
|
||||
|
||||
DBMoment = "moment"
|
||||
COLMoment = "moment"
|
||||
|
@ -214,6 +215,11 @@ func (m *Mongo) getColVeriCode() *qmgo.Collection {
|
|||
return m.clientMix.Database(DBVeriCode).Collection(COLVeriCode)
|
||||
}
|
||||
|
||||
// VeriCode频次表
|
||||
func (m *Mongo) getColVeriCodeSendTimes() *qmgo.Collection {
|
||||
return m.clientMix.Database(DBVeriCode).Collection(COLVeriCodeSendTimes)
|
||||
}
|
||||
|
||||
// 动态表
|
||||
func (m *Mongo) getColMoment() *qmgo.Collection {
|
||||
return m.clientMix.Database(DBMoment).Collection(COLMoment)
|
||||
|
@ -1020,6 +1026,32 @@ func (m *Mongo) GetVeriCodeListByPhoneHash(ctx *gin.Context, req *vericodeproto.
|
|||
return vericode, err
|
||||
}
|
||||
|
||||
// 验证码频次
|
||||
func (m *Mongo) GetAndUpdateVeriCodeSendTimes(ctx *gin.Context, deviceId string) (veriCodeSendTimes *dbstruct.VeriCodeSendTimes, err error) {
|
||||
col := m.getColVeriCodeSendTimes()
|
||||
|
||||
change := qmgo.Change{
|
||||
Update: qmgo.M{"$inc": qmgo.M{"send_times": 1}},
|
||||
Upsert: true,
|
||||
ReturnNew: false,
|
||||
}
|
||||
|
||||
veriCodeSendTimesInstance := dbstruct.VeriCodeSendTimes{}
|
||||
if err = col.Find(ctx, qmgo.M{"_id": deviceId}).Apply(change, &veriCodeSendTimesInstance); err != nil {
|
||||
logger.Error("change error : %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
return &veriCodeSendTimesInstance, err
|
||||
}
|
||||
|
||||
// 清空验证码频次表
|
||||
func (m *Mongo) ClearVeriCodeSendTimes(ctx *gin.Context) error {
|
||||
col := m.getColVeriCodeSendTimes()
|
||||
_, err := col.RemoveAll(ctx, qmgo.M{})
|
||||
return err
|
||||
}
|
||||
|
||||
// 动态相关
|
||||
func (m *Mongo) CreateMoment(ctx *gin.Context, moment *dbstruct.Moment) error {
|
||||
col := m.getColMoment()
|
||||
|
|
|
@ -37,7 +37,13 @@ import (
|
|||
|
||||
// 发送验证码
|
||||
func (s *Service) ApiSendVeriCode(ctx *gin.Context, req *vericodeproto.ApiSendReq) (ec errcode.ErrCode) {
|
||||
ec = errcode.ErrCodeResourceSrvOk
|
||||
ec = errcode.ErrCodeLoginSrvOk
|
||||
|
||||
ec = s.ApiSendVeriCodeBusinessValidate(ctx, req)
|
||||
if ec != errcode.ErrCodeLoginSrvOk {
|
||||
return
|
||||
}
|
||||
|
||||
err := _DefaultVeriCode.OpSendVeriCode(ctx, &vericodeproto.OpSendReq{
|
||||
MobilePhone: req.MobilePhone,
|
||||
RegionCode: req.RegionCode,
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
loginproto "service/api/proto/login/proto"
|
||||
streamerproto "service/api/proto/streamer/proto"
|
||||
streamerauthapprovalproto "service/api/proto/streamerauthapproval/proto"
|
||||
vericodeproto "service/api/proto/vericode/proto"
|
||||
businessvalidator "service/app/mix/service/business_validator"
|
||||
"service/bizcommon/util"
|
||||
"service/dbstruct"
|
||||
|
@ -18,6 +19,24 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 发送验证码
|
||||
func (s *Service) ApiSendVeriCodeBusinessValidate(ctx *gin.Context, req *vericodeproto.ApiSendReq) (ec errcode.ErrCode) {
|
||||
ec = errcode.ErrCodeLoginSrvOk
|
||||
|
||||
resultList := businessvalidator.NewLoginBusinessValidator(ctx, req).
|
||||
QueryVeriCodeSendTimes(_DefaultVeriCodeSendTimes.OpGetAndUpdate, req.Did).
|
||||
EnsureVeriCodeSendTimesNotReachedDailyUpperbound().
|
||||
Validate().
|
||||
Collect()
|
||||
ec, _ = resultList[0].(errcode.ErrCode)
|
||||
if ec != errcode.ErrCodeLoginSrvOk {
|
||||
logger.Error("ApiSendVeriCodeBusinessValidate business validation failed!")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 密码登录
|
||||
func (s *Service) ApiLoginByPswdBusinessValidate(ctx *gin.Context, req *loginproto.ApiLoginByPswdReq) (login *dbstruct.Login, account *dbstruct.Account, ec errcode.ErrCode) {
|
||||
ec = errcode.ErrCodeLoginSrvOk
|
||||
|
|
|
@ -25,9 +25,10 @@ type LoginBusinessValidator struct {
|
|||
passwordAccessor loginproto.PasswordAccessible //访问密码的接口
|
||||
|
||||
// 结果
|
||||
login *dbstruct.Login
|
||||
account *dbstruct.Account
|
||||
vericode *dbstruct.VeriCode
|
||||
login *dbstruct.Login
|
||||
account *dbstruct.Account
|
||||
vericode *dbstruct.VeriCode
|
||||
vericodeSendTimes *dbstruct.VeriCodeSendTimes
|
||||
}
|
||||
|
||||
func NewLoginBusinessValidator(ctx *gin.Context, req any) *LoginBusinessValidator {
|
||||
|
@ -242,6 +243,40 @@ func (l *LoginBusinessValidator) EnsureIsOpRole() *LoginBusinessValidator {
|
|||
return l
|
||||
}
|
||||
|
||||
func (l *LoginBusinessValidator) QueryVeriCodeSendTimes(fun func(*gin.Context, string) (*dbstruct.VeriCodeSendTimes, error), devId string) *LoginBusinessValidator {
|
||||
l.oplist = append(l.oplist, func() {
|
||||
|
||||
vericodeSendTimes, err := fun(l.ctx, devId)
|
||||
if err != nil {
|
||||
l.ec = errcode.ErrCodeVeriCodeSendTimesSrvFail
|
||||
return
|
||||
}
|
||||
|
||||
l.vericodeSendTimes = vericodeSendTimes
|
||||
})
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *LoginBusinessValidator) EnsureVeriCodeSendTimesNotReachedDailyUpperbound() *LoginBusinessValidator {
|
||||
l.oplist = append(l.oplist, func() {
|
||||
|
||||
// 读取每日发送上限
|
||||
maxDailyVeriCodeSendTimes, err := apollo.GetIntValue(consts.MaxDailyVeriCodeSendTimesKey, apollo.ApolloOpts().SetNamespace("application"))
|
||||
if err != nil {
|
||||
logger.Error("Apollo read failed : %v", err)
|
||||
l.ec = errcode.ErrCodeApolloReadFail
|
||||
return
|
||||
}
|
||||
|
||||
if l.vericodeSendTimes.SendTimes >= int64(maxDailyVeriCodeSendTimes) {
|
||||
logger.Error("the vericode send times of this device has reached its daily upperbound")
|
||||
l.ec = errcode.ErrCodeVeriCodeSendTimesReachedDailyUpperbound
|
||||
return
|
||||
}
|
||||
})
|
||||
return l
|
||||
}
|
||||
|
||||
// 执行校验
|
||||
func (s *LoginBusinessValidator) Validate() *LoginBusinessValidator {
|
||||
s.BusinessValidateStream.Validate()
|
||||
|
|
|
@ -30,6 +30,7 @@ func (s *CronService) Run() {
|
|||
s.ReloadRecommList()
|
||||
s.ImageAuditBatch()
|
||||
s.TextAuditBatch()
|
||||
s.ClearVeriCodeSendTimes()
|
||||
}
|
||||
|
||||
func (s *CronService) ReloadRecommList() {
|
||||
|
@ -79,3 +80,18 @@ func (s *CronService) TextAuditBatch() {
|
|||
})
|
||||
scheduler.StartAsync()
|
||||
}
|
||||
|
||||
func (s *CronService) ClearVeriCodeSendTimes() {
|
||||
loc, _ := time.LoadLocation("Asia/Shanghai")
|
||||
scheduler := gocron.NewScheduler(loc)
|
||||
|
||||
scheduler.Every(1).Day().At("00:00").Do(func() {
|
||||
logger.Info("Clearing vericode_send_times collection...")
|
||||
ctx := &gin.Context{}
|
||||
if err := _DefaultVeriCodeSendTimes.OpClear(ctx); err != nil {
|
||||
logger.Error("Clear vericode_send_times collection fail: %v", err)
|
||||
}
|
||||
logger.Info("vericode_send_times collection has been cleared")
|
||||
})
|
||||
scheduler.StartAsync()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"service/app/mix/dao"
|
||||
"service/dbstruct"
|
||||
"service/library/logger"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type VeriCodeSendTimes struct {
|
||||
store *dao.Store
|
||||
}
|
||||
|
||||
func NewVeriCodeSendTimes(store *dao.Store) (a *VeriCodeSendTimes) {
|
||||
a = &VeriCodeSendTimes{
|
||||
store: store,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *VeriCodeSendTimes) OpGetAndUpdate(ctx *gin.Context, devId string) (*dbstruct.VeriCodeSendTimes, error) {
|
||||
|
||||
vericodeSendTimes, err := p.store.GetAndUpdateVeriCodeSendTimes(ctx, devId)
|
||||
if err != nil {
|
||||
logger.Error("GetAndUpdateVeriCodeSendTimes fail, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vericodeSendTimes, nil
|
||||
}
|
||||
|
||||
func (p *VeriCodeSendTimes) OpClear(ctx *gin.Context) error {
|
||||
err := p.store.ClearVeriCodeSendTimes(ctx)
|
||||
if err != nil {
|
||||
logger.Error("ClearVeriCodeSendTimes fail, err: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -16,6 +16,7 @@ import (
|
|||
streamerlinkproto "service/api/proto/streamerlink/proto"
|
||||
textaudittaskproto "service/api/proto/textaudittask/proto"
|
||||
userwxaddcheckproto "service/api/proto/userwxaddcheck/proto"
|
||||
vericodeproto "service/api/proto/vericode/proto"
|
||||
businessvalidator "service/app/mix/service/business_validator"
|
||||
"service/dbstruct"
|
||||
"service/library/logger"
|
||||
|
@ -23,6 +24,24 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 发送验证码
|
||||
func (s *Service) OpSendVeriCodeBusinessValidate(ctx *gin.Context, req *vericodeproto.OpSendReq) (ec errcode.ErrCode) {
|
||||
ec = errcode.ErrCodeLoginSrvOk
|
||||
|
||||
resultList := businessvalidator.NewLoginBusinessValidator(ctx, req).
|
||||
QueryVeriCodeSendTimes(_DefaultVeriCodeSendTimes.OpGetAndUpdate, req.Did).
|
||||
EnsureVeriCodeSendTimesNotReachedDailyUpperbound().
|
||||
Validate().
|
||||
Collect()
|
||||
ec, _ = resultList[0].(errcode.ErrCode)
|
||||
if ec != errcode.ErrCodeLoginSrvOk {
|
||||
logger.Error("OpSendVeriCodeBusinessValidate business validation failed!")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 密码登录
|
||||
func (s *Service) OpLoginByPswdBusinessValidate(ctx *gin.Context, req *loginproto.OpLoginByPswdReq) (login *dbstruct.Login, account *dbstruct.Account, ec errcode.ErrCode) {
|
||||
ec = errcode.ErrCodeLoginSrvOk
|
||||
|
|
|
@ -65,6 +65,7 @@ var (
|
|||
var (
|
||||
_DefaultToken *logic.Token
|
||||
_DefaultVeriCode *logic.VeriCode
|
||||
_DefaultVeriCodeSendTimes *logic.VeriCodeSendTimes
|
||||
_DefaultAccount *logic.Account
|
||||
_DefaultProduct *logic.Product
|
||||
_DefaultCatalog *logic.Catalog
|
||||
|
@ -129,6 +130,7 @@ func (s *Service) Init(c any) (err error) {
|
|||
|
||||
_DefaultToken = logic.NewToken(store, cfg.Crypto)
|
||||
_DefaultVeriCode = logic.NewVeriCode(store, cfg.Dysmsapi)
|
||||
_DefaultVeriCodeSendTimes = logic.NewVeriCodeSendTimes(store)
|
||||
_DefaultAccount = logic.NewAccount(store)
|
||||
_DefaultProduct = logic.NewProduct(store)
|
||||
_DefaultCatalog = logic.NewCatalog(store)
|
||||
|
@ -439,6 +441,12 @@ func (s *Service) GetBannerList(ctx *gin.Context) (list []*dbstruct.Banner, ec e
|
|||
// 发送验证码
|
||||
func (s *Service) OpSendVeriCode(ctx *gin.Context, req *vericodeproto.OpSendReq) (ec errcode.ErrCode) {
|
||||
ec = errcode.ErrCodeResourceSrvOk
|
||||
|
||||
ec = s.OpSendVeriCodeBusinessValidate(ctx, req)
|
||||
if ec != errcode.ErrCodeLoginSrvOk {
|
||||
return
|
||||
}
|
||||
|
||||
err := _DefaultVeriCode.OpSendVeriCode(ctx, req)
|
||||
if err != nil {
|
||||
logger.Error("OpSendVeriCode fail, err: %v", err)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package dbstruct
|
||||
|
||||
type VeriCodeSendTimes struct {
|
||||
Id string `json:"id" bson:"_id"` //id,用户的b_did
|
||||
SendTimes int64 `json:"send_times" bson:"send_times"` //发送次数
|
||||
}
|
Loading…
Reference in New Issue