From 9ce997b51b3f3334d6b0dfe867175635dfc758a6 Mon Sep 17 00:00:00 2001 From: eson <9673575+githubcontent@user.noreply.gitee.com> Date: Thu, 31 Aug 2023 11:12:49 +0800 Subject: [PATCH] fix --- go.mod | 1 - go.sum | 2 - server/auth/internal/logic/email_manager.go | 52 ++++++++++--------- .../internal/logic/useremailregisterlogic.go | 4 ++ .../auth/internal/logic/userregisterlogic.go | 4 ++ utils/basic/basic.go | 9 ++-- utils/check/limit.go | 52 +++++++++++++++++-- 7 files changed, 90 insertions(+), 34 deletions(-) diff --git a/go.mod b/go.mod index 22fb2b9f..a0803be1 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,6 @@ require ( require ( cloud.google.com/go/compute v1.20.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - github.com/474420502/execute v0.2.2 // indirect github.com/DataDog/zstd v1.4.5 // indirect github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect github.com/VictoriaMetrics/metrics v1.18.1 // indirect diff --git a/go.sum b/go.sum index aa02629a..e2b9c05e 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/474420502/execute v0.2.2 h1:Hzzb/HFa/urRvi3xWe+p/DnJgRyxXFVyEBEXbbITy/E= -github.com/474420502/execute v0.2.2/go.mod h1:wkKeKBIXYp7T844eU1YS2nPvFj8lra4VRcQYnWyXej4= github.com/474420502/passer v0.0.1 h1:ZWnt7hpFzsYDV7LHSEyLvLUvW5mRxrnDmgFdIl17q3w= github.com/474420502/passer v0.0.1/go.mod h1:MmnnrF9d51sPkFzdRq2pQtxQKqyjburVM1LjMbOCezE= github.com/474420502/random v0.4.1 h1:HUUyLXRWMijVb7CJoEC16f0aFQOW25Lkr80Mut6PoKU= diff --git a/server/auth/internal/logic/email_manager.go b/server/auth/internal/logic/email_manager.go index b54883ca..08b03a28 100644 --- a/server/auth/internal/logic/email_manager.go +++ b/server/auth/internal/logic/email_manager.go @@ -2,6 +2,7 @@ package logic import ( "bytes" + "fusenapi/utils/check" "log" "net/smtp" "sync" @@ -9,8 +10,35 @@ import ( "time" ) +var TimeLimit *check.TimeLimit[string] var EmailManager *EmailSender +func init() { + + TimeLimit = check.NewTimelimit[string](time.Second * 25) + + // Initialize the email manager + EmailManager = &EmailSender{ + EmailTasks: make(chan *EmailFormat, 10), + Auth: smtp.PlainAuth( + "", + "support@fusenpack.com", + "wfbjpdgvaozjvwah", + "smtp.gmail.com", + ), + FromEmail: "support@fusenpack.com", + emailSending: make(map[string]*EmailTask, 10), + ResendTimeLimit: time.Minute * 1, + semaphore: make(chan struct{}, 10), // Initialize semaphore with a capacity of 10 + } + + // Start processing email tasks + go EmailManager.ProcessEmailTasks() + + // Start clearing expired tasks + go EmailManager.ClearExpiredTasks() +} + type EmailFormat struct { TargetEmail string // 发送的目标email CompanyName string // fs公司名 @@ -110,30 +138,6 @@ func (m *EmailSender) ClearExpiredTasks() { } } -func init() { - - // Initialize the email manager - EmailManager = &EmailSender{ - EmailTasks: make(chan *EmailFormat, 10), - Auth: smtp.PlainAuth( - "", - "support@fusenpack.com", - "wfbjpdgvaozjvwah", - "smtp.gmail.com", - ), - FromEmail: "support@fusenpack.com", - emailSending: make(map[string]*EmailTask, 10), - ResendTimeLimit: time.Minute * 1, - semaphore: make(chan struct{}, 10), // Initialize semaphore with a capacity of 10 - } - - // Start processing email tasks - go EmailManager.ProcessEmailTasks() - - // Start clearing expired tasks - go EmailManager.ClearExpiredTasks() -} - const emailTemplate = `Subject: Your {{.CompanyName}} Account Confirmation Dear diff --git a/server/auth/internal/logic/useremailregisterlogic.go b/server/auth/internal/logic/useremailregisterlogic.go index 50b360e2..1de536f0 100644 --- a/server/auth/internal/logic/useremailregisterlogic.go +++ b/server/auth/internal/logic/useremailregisterlogic.go @@ -47,6 +47,10 @@ func (l *UserEmailRegisterLogic) UserEmailRegister(req *types.RequestEmailRegist return resp.SetStatus(basic.CodeOAuthEmailErr) } + if !TimeLimit.Is(req.Email) { + return resp.SetStatus(basic.CodeEmailTimeShortErr) + } + token, err := l.svcCtx.OAuthTokenManger.Decrypt(req.RegisterToken) if err != nil { logx.Error(err) diff --git a/server/auth/internal/logic/userregisterlogic.go b/server/auth/internal/logic/userregisterlogic.go index 03c3bece..a813c66f 100644 --- a/server/auth/internal/logic/userregisterlogic.go +++ b/server/auth/internal/logic/userregisterlogic.go @@ -46,6 +46,10 @@ func (l *UserRegisterLogic) UserRegister(req *types.RequestUserRegister, userinf return resp.SetStatus(basic.CodeEmailExistsErr) } + if !TimeLimit.Is(req.Email) { + return resp.SetStatus(basic.CodeEmailTimeShortErr) + } + token := &auth.RegisterToken{ OperateType: auth.OpTypeRegister, GuestId: userinfo.GuestId, diff --git a/utils/basic/basic.go b/utils/basic/basic.go index faefee61..20fc1ccc 100644 --- a/utils/basic/basic.go +++ b/utils/basic/basic.go @@ -52,10 +52,11 @@ var ( CodeS3PutSizeLimitErr = &StatusResponse{5061, "s3 over limit size error"} // s3 超过文件大小限制 错误 CodeS3CategoryErr = &StatusResponse{5062, "s3 category not exists error"} // s3 类别不存在 错误 - CodeEmailNotFoundErr = &StatusResponse{5050, "email not found"} // 未找到email - CodeUserIdNotFoundErr = &StatusResponse{5051, "user not found"} // 未找到用户 - CodePasswordErr = &StatusResponse{5052, "invalid password"} // 无效密码 - CodeEmailExistsErr = &StatusResponse{5053, "email exists"} // email存在 + CodeEmailNotFoundErr = &StatusResponse{5050, "email not found"} // 未找到email + CodeUserIdNotFoundErr = &StatusResponse{5051, "user not found"} // 未找到用户 + CodePasswordErr = &StatusResponse{5052, "invalid password"} // 无效密码 + CodeEmailExistsErr = &StatusResponse{5053, "email exists"} // email存在 + CodeEmailTimeShortErr = &StatusResponse{5053, "email with the time of resend is too short"} // email存在 CodeSafeValueRangeErr = &StatusResponse{5040, "value not in range"} // 值不在范围内 CodeTemplateErr = &StatusResponse{5040, "template parsed error"} // 模板解析错误 diff --git a/utils/check/limit.go b/utils/check/limit.go index b6814ef5..fdf3503e 100644 --- a/utils/check/limit.go +++ b/utils/check/limit.go @@ -1,7 +1,53 @@ +// Timeup是一个限制某个值的重复频率的工具 +// 通过内部计时器实现限制同一个值的访问频率不超过指定时间间隔 package check -import "sync" +import ( + "sync" + "time" +) -type LimitAfter struct { - sync.Map +// TimeLimit结构体包含需要限频的映射表,以及时间间隔 +// 使用sync.Mutex保证对字典的线程安全访问 +type TimeLimit[T comparable] struct { + mu sync.Mutex + dict map[T]struct{} + dur time.Duration +} + +// NewTimelimit构造函数,接收限频的时间间隔 +// 并初始化内部字典和间隔字段 +func NewTimelimit[T comparable](dur time.Duration) *TimeLimit[T] { + return &TimeLimit[T]{ + dict: make(map[T]struct{}), + dur: dur, + } +} + +// WithTime方法用于更新限频的时间间隔 +func (tup *TimeLimit[T]) WithTime(dur time.Duration) *TimeLimit[T] { + tup.mu.Lock() + defer tup.mu.Unlock() + tup.dur = dur + return tup +} + +// Is方法检查传入值是否是一个新的值 +// 首先会查询字典,如果存在则表示在间隔内已经访问过 +// 否则将其添加到字典,并启动一个定时器在间隔后删除 +// 返回true表示新值,false表示重复值 +func (tup *TimeLimit[T]) Is(v T) bool { + tup.mu.Lock() + defer tup.mu.Unlock() + + if _, ok := tup.dict[v]; ok { + return false + } + tup.dict[v] = struct{}{} + time.AfterFunc(tup.dur, func() { + tup.mu.Lock() + defer tup.mu.Unlock() + delete(tup.dict, v) + }) + return true }