2026-03-23 02:42:12 +08:00

79 lines
2.2 KiB
Go

package captcha
import (
"context"
"github.com/pkg/errors"
"github.com/redis/go-redis/v9"
"github.com/perfect-panel/server/pkg/xerr"
)
// VerifyInput holds the captcha fields from a login/register/reset request.
type VerifyInput struct {
CaptchaId string
CaptchaCode string
CfToken string
SliderToken string
IP string
}
// VerifyCaptcha validates the captcha according to captchaType.
// Returns nil when captchaType is empty / unrecognised (i.e. captcha disabled).
func VerifyCaptcha(
ctx context.Context,
redisClient *redis.Client,
captchaType string,
turnstileSecret string,
input VerifyInput,
) error {
switch captchaType {
case string(CaptchaTypeLocal):
if input.CaptchaId == "" || input.CaptchaCode == "" {
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "captcha required")
}
svc := NewService(Config{
Type: CaptchaTypeLocal,
RedisClient: redisClient,
})
valid, err := svc.Verify(ctx, input.CaptchaId, input.CaptchaCode, input.IP)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "verify captcha error")
}
if !valid {
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "invalid captcha")
}
case string(CaptchaTypeTurnstile):
if input.CfToken == "" {
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "captcha required")
}
svc := NewService(Config{
Type: CaptchaTypeTurnstile,
TurnstileSecret: turnstileSecret,
})
valid, err := svc.Verify(ctx, input.CfToken, "", input.IP)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "verify captcha error")
}
if !valid {
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "invalid captcha")
}
case string(CaptchaTypeSlider):
if input.SliderToken == "" {
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "slider captcha required")
}
sliderSvc := NewSliderService(redisClient)
valid, err := sliderSvc.VerifySliderToken(ctx, input.SliderToken)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "verify captcha error")
}
if !valid {
return errors.Wrapf(xerr.NewErrCode(xerr.VerifyCodeError), "invalid slider captcha")
}
}
return nil
}