From 3ca471f58c53ef76c291304d15cd5a5aed12aad9 Mon Sep 17 00:00:00 2001 From: EUForest Date: Mon, 9 Mar 2026 22:56:07 +0800 Subject: [PATCH] refactor(auth): move captcha verification from handler to logic layer - Remove duplicate captcha verification from user login handler - Remove duplicate captcha verification from user register handler - Remove duplicate captcha verification from password reset handler - Remove duplicate captcha verification from phone login handler - Remove duplicate captcha verification from phone register handler - Update phone reset password handler structure - Improve separation of concerns between handler and logic layers - Handlers now only handle HTTP request/response, logic handles business rules --- internal/handler/auth/resetPasswordHandler.go | 18 +------- .../handler/auth/telephoneLoginHandler.go | 18 +------- .../auth/telephoneResetPasswordHandler.go | 46 +++++++++++++++---- .../auth/telephoneUserRegisterHandler.go | 17 +------ internal/handler/auth/userLoginHandler.go | 17 +------ internal/handler/auth/userRegisterHandler.go | 16 +------ 6 files changed, 43 insertions(+), 89 deletions(-) diff --git a/internal/handler/auth/resetPasswordHandler.go b/internal/handler/auth/resetPasswordHandler.go index d4edc9b..8de4ca6 100644 --- a/internal/handler/auth/resetPasswordHandler.go +++ b/internal/handler/auth/resetPasswordHandler.go @@ -1,16 +1,11 @@ package auth import ( - "time" - "github.com/gin-gonic/gin" "github.com/perfect-panel/server/internal/logic/auth" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/result" - "github.com/perfect-panel/server/pkg/turnstile" - "github.com/perfect-panel/server/pkg/xerr" - "github.com/pkg/errors" ) // Reset password @@ -25,17 +20,8 @@ func ResetPasswordHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { } // get client ip req.IP = c.ClientIP() - if svcCtx.Config.Verify.ResetPasswordVerify { - verifyTurns := turnstile.New(turnstile.Config{ - Secret: svcCtx.Config.Verify.TurnstileSecret, - Timeout: 3 * time.Second, - }) - if verify, err := verifyTurns.Verify(c, req.CfToken, req.IP); err != nil || !verify { - err = errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "error: %v, verify: %v", err, verify) - result.HttpResult(c, nil, err) - return - } - } + req.UserAgent = c.Request.UserAgent() + l := auth.NewResetPasswordLogic(c.Request.Context(), svcCtx) resp, err := l.ResetPassword(&req) result.HttpResult(c, resp, err) diff --git a/internal/handler/auth/telephoneLoginHandler.go b/internal/handler/auth/telephoneLoginHandler.go index 44c1b53..c7e3bab 100644 --- a/internal/handler/auth/telephoneLoginHandler.go +++ b/internal/handler/auth/telephoneLoginHandler.go @@ -1,16 +1,11 @@ package auth import ( - "time" - "github.com/gin-gonic/gin" "github.com/perfect-panel/server/internal/logic/auth" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/result" - "github.com/perfect-panel/server/pkg/turnstile" - "github.com/perfect-panel/server/pkg/xerr" - "github.com/pkg/errors" ) // User Telephone login @@ -25,17 +20,8 @@ func TelephoneLoginHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { } // get client ip req.IP = c.ClientIP() - if svcCtx.Config.Verify.LoginVerify { - verifyTurns := turnstile.New(turnstile.Config{ - Secret: svcCtx.Config.Verify.TurnstileSecret, - Timeout: 3 * time.Second, - }) - if verify, err := verifyTurns.Verify(c, req.CfToken, req.IP); err != nil || !verify { - err = errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "error: %v, verify: %v", err, verify) - result.HttpResult(c, nil, err) - return - } - } + req.UserAgent = c.Request.UserAgent() + l := auth.NewTelephoneLoginLogic(c, svcCtx) resp, err := l.TelephoneLogin(&req, c.Request, c.ClientIP()) result.HttpResult(c, resp, err) diff --git a/internal/handler/auth/telephoneResetPasswordHandler.go b/internal/handler/auth/telephoneResetPasswordHandler.go index 16a5105..bc0f8a6 100644 --- a/internal/handler/auth/telephoneResetPasswordHandler.go +++ b/internal/handler/auth/telephoneResetPasswordHandler.go @@ -1,14 +1,13 @@ package auth import ( - "time" - "github.com/gin-gonic/gin" "github.com/perfect-panel/server/internal/logic/auth" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" + "github.com/perfect-panel/server/pkg/captcha" "github.com/perfect-panel/server/pkg/result" - "github.com/perfect-panel/server/pkg/turnstile" + "github.com/perfect-panel/server/pkg/tool" "github.com/perfect-panel/server/pkg/xerr" "github.com/pkg/errors" ) @@ -25,17 +24,44 @@ func TelephoneResetPasswordHandler(svcCtx *svc.ServiceContext) func(c *gin.Conte } // get client ip req.IP = c.ClientIP() - if svcCtx.Config.Verify.ResetPasswordVerify { - verifyTurns := turnstile.New(turnstile.Config{ - Secret: svcCtx.Config.Verify.TurnstileSecret, - Timeout: 3 * time.Second, + + // Get verify config from database + verifyCfg, err := svcCtx.SystemModel.GetVerifyConfig(c.Request.Context()) + if err != nil { + result.HttpResult(c, nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get verify config failed: %v", err)) + return + } + + var config struct { + CaptchaType string `json:"captcha_type"` + EnableUserResetPasswordCaptcha bool `json:"enable_user_reset_password_captcha"` + TurnstileSecret string `json:"turnstile_secret"` + } + tool.SystemConfigSliceReflectToStruct(verifyCfg, &config) + + // Verify captcha if enabled + if config.EnableUserResetPasswordCaptcha { + captchaService := captcha.NewService(captcha.Config{ + Type: captcha.CaptchaType(config.CaptchaType), + TurnstileSecret: config.TurnstileSecret, + RedisClient: svcCtx.Redis, }) - if verify, err := verifyTurns.Verify(c.Request.Context(), req.CfToken, req.IP); err != nil || !verify { - err = errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "error: %v, verify: %v", err, verify) - result.HttpResult(c, nil, err) + + var token, code string + if config.CaptchaType == "turnstile" { + token = req.CfToken + } else { + token = req.CaptchaId + code = req.CaptchaCode + } + + verified, err := captchaService.Verify(c.Request.Context(), token, code, req.IP) + if err != nil || !verified { + result.HttpResult(c, nil, errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "captcha verification failed: %v", err)) return } } + l := auth.NewTelephoneResetPasswordLogic(c, svcCtx) resp, err := l.TelephoneResetPassword(&req) result.HttpResult(c, resp, err) diff --git a/internal/handler/auth/telephoneUserRegisterHandler.go b/internal/handler/auth/telephoneUserRegisterHandler.go index 45a7ba8..306777d 100644 --- a/internal/handler/auth/telephoneUserRegisterHandler.go +++ b/internal/handler/auth/telephoneUserRegisterHandler.go @@ -1,16 +1,11 @@ package auth import ( - "time" - "github.com/gin-gonic/gin" "github.com/perfect-panel/server/internal/logic/auth" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/result" - "github.com/perfect-panel/server/pkg/turnstile" - "github.com/perfect-panel/server/pkg/xerr" - "github.com/pkg/errors" ) // User Telephone register @@ -26,17 +21,7 @@ func TelephoneUserRegisterHandler(svcCtx *svc.ServiceContext) func(c *gin.Contex // get client ip req.IP = c.ClientIP() req.UserAgent = c.Request.UserAgent() - if svcCtx.Config.Verify.RegisterVerify { - verifyTurns := turnstile.New(turnstile.Config{ - Secret: svcCtx.Config.Verify.TurnstileSecret, - Timeout: 3 * time.Second, - }) - if verify, err := verifyTurns.Verify(c, req.CfToken, req.IP); err != nil || !verify { - err = errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "error: %v, verify: %v", err, verify) - result.HttpResult(c, nil, err) - return - } - } + l := auth.NewTelephoneUserRegisterLogic(c.Request.Context(), svcCtx) resp, err := l.TelephoneUserRegister(&req) result.HttpResult(c, resp, err) diff --git a/internal/handler/auth/userLoginHandler.go b/internal/handler/auth/userLoginHandler.go index 20eff59..a188876 100644 --- a/internal/handler/auth/userLoginHandler.go +++ b/internal/handler/auth/userLoginHandler.go @@ -1,16 +1,11 @@ package auth import ( - "time" - "github.com/gin-gonic/gin" "github.com/perfect-panel/server/internal/logic/auth" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/result" - "github.com/perfect-panel/server/pkg/turnstile" - "github.com/perfect-panel/server/pkg/xerr" - "github.com/pkg/errors" ) // User login @@ -21,17 +16,7 @@ func UserLoginHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { // get client ip req.IP = c.ClientIP() req.UserAgent = c.Request.UserAgent() - if svcCtx.Config.Verify.LoginVerify && !svcCtx.Config.Debug { - verifyTurns := turnstile.New(turnstile.Config{ - Secret: svcCtx.Config.Verify.TurnstileSecret, - Timeout: 3 * time.Second, - }) - if verify, err := verifyTurns.Verify(c, req.CfToken, req.IP); err != nil || !verify { - err = errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "error: %v, verify: %v", err, verify) - result.HttpResult(c, nil, err) - return - } - } + validateErr := svcCtx.Validate(&req) if validateErr != nil { result.ParamErrorResult(c, validateErr) diff --git a/internal/handler/auth/userRegisterHandler.go b/internal/handler/auth/userRegisterHandler.go index ea40223..a11c743 100644 --- a/internal/handler/auth/userRegisterHandler.go +++ b/internal/handler/auth/userRegisterHandler.go @@ -1,16 +1,11 @@ package auth import ( - "time" - "github.com/gin-gonic/gin" "github.com/perfect-panel/server/internal/logic/auth" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/result" - "github.com/perfect-panel/server/pkg/turnstile" - "github.com/perfect-panel/server/pkg/xerr" - "github.com/pkg/errors" ) // User register @@ -21,16 +16,7 @@ func UserRegisterHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { // get client ip req.IP = c.ClientIP() req.UserAgent = c.Request.UserAgent() - if svcCtx.Config.Verify.RegisterVerify { - verifyTurns := turnstile.New(turnstile.Config{ - Secret: svcCtx.Config.Verify.TurnstileSecret, - Timeout: 3 * time.Second, - }) - if verify, err := verifyTurns.Verify(c, req.CfToken, req.IP); err != nil || !verify { - result.HttpResult(c, nil, errors.Wrapf(xerr.NewErrCode(xerr.TooManyRequests), "verify error: %v", err.Error())) - return - } - } + validateErr := svcCtx.Validate(&req) if validateErr != nil { result.ParamErrorResult(c, validateErr)