answer/internal/service/action/captcha_service.go

157 lines
4.4 KiB
Go
Raw Normal View History

2022-09-27 17:59:05 +08:00
package action
import (
"context"
"image/color"
"strings"
"github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/schema"
2022-09-27 17:59:05 +08:00
"github.com/mojocn/base64Captcha"
"github.com/segmentfault/pacman/errors"
"github.com/segmentfault/pacman/log"
)
// CaptchaRepo captcha repository
type CaptchaRepo interface {
SetCaptcha(ctx context.Context, key, captcha string) (err error)
GetCaptcha(ctx context.Context, key string) (captcha string, err error)
2023-02-24 16:30:21 +08:00
DelCaptcha(ctx context.Context, key string) (err error)
2022-09-27 17:59:05 +08:00
SetActionType(ctx context.Context, ip, actionType string, amount int) (err error)
GetActionType(ctx context.Context, ip, actionType string) (amount int, err error)
DelActionType(ctx context.Context, ip, actionType string) (err error)
}
// CaptchaService kit service
type CaptchaService struct {
captchaRepo CaptchaRepo
}
// NewCaptchaService captcha service
func NewCaptchaService(captchaRepo CaptchaRepo) *CaptchaService {
return &CaptchaService{
captchaRepo: captchaRepo,
}
}
// ActionRecord action record
func (cs *CaptchaService) ActionRecord(ctx context.Context, req *schema.ActionRecordReq) (resp *schema.ActionRecordResp, err error) {
resp = &schema.ActionRecordResp{}
num, err := cs.captchaRepo.GetActionType(ctx, req.IP, req.Action)
2022-09-27 17:59:05 +08:00
if err != nil {
num = 0
}
// TODO config num to config file
if num >= 3 {
resp.CaptchaID, resp.CaptchaImg, err = cs.GenerateCaptcha(ctx)
resp.Verify = true
}
return
}
2022-12-18 00:14:50 +08:00
func (cs *CaptchaService) UserRegisterCaptcha(ctx context.Context) (resp *schema.ActionRecordResp, err error) {
resp = &schema.ActionRecordResp{}
resp.CaptchaID, resp.CaptchaImg, err = cs.GenerateCaptcha(ctx)
resp.Verify = true
return
}
func (cs *CaptchaService) UserRegisterVerifyCaptcha(
ctx context.Context, id string, VerifyValue string,
) bool {
if id == "" || VerifyValue == "" {
return false
}
pass, err := cs.VerifyCaptcha(ctx, id, VerifyValue)
if err != nil {
return false
}
return pass
}
2022-09-27 17:59:05 +08:00
// ActionRecordVerifyCaptcha
// Verify that you need to enter a CAPTCHA, and that the CAPTCHA is correct
func (cs *CaptchaService) ActionRecordVerifyCaptcha(
ctx context.Context, actionType string, ip string, id string, VerifyValue string,
) bool {
2022-09-27 17:59:05 +08:00
num, cahceErr := cs.captchaRepo.GetActionType(ctx, ip, actionType)
if cahceErr != nil {
return true
}
if num >= 3 {
2022-12-18 00:14:50 +08:00
if id == "" || VerifyValue == "" {
return false
}
2022-09-27 17:59:05 +08:00
pass, err := cs.VerifyCaptcha(ctx, id, VerifyValue)
if err != nil {
return false
}
return pass
}
return true
}
func (cs *CaptchaService) ActionRecordAdd(ctx context.Context, actionType string, ip string) (int, error) {
var err error
num, cahceErr := cs.captchaRepo.GetActionType(ctx, ip, actionType)
if cahceErr != nil {
log.Error(err)
}
num++
err = cs.captchaRepo.SetActionType(ctx, ip, actionType, num)
if err != nil {
return 0, err
}
return num, nil
}
func (cs *CaptchaService) ActionRecordDel(ctx context.Context, actionType string, ip string) {
err := cs.captchaRepo.DelActionType(ctx, ip, actionType)
if err != nil {
log.Error(err)
}
}
// GenerateCaptcha generate captcha
func (cs *CaptchaService) GenerateCaptcha(ctx context.Context) (key, captchaBase64 string, err error) {
driverString := base64Captcha.DriverString{
2023-07-04 14:32:34 +08:00
Height: 60,
Width: 200,
2022-09-27 17:59:05 +08:00
NoiseCount: 0,
ShowLineOptions: 2 | 4,
Length: 4,
Source: "1234567890qwertyuioplkjhgfdsazxcvbnm",
2023-07-04 14:32:34 +08:00
BgColor: &color.RGBA{R: 211, G: 211, B: 211, A: 0},
2022-09-27 17:59:05 +08:00
Fonts: []string{"wqy-microhei.ttc"},
}
driver := driverString.ConvertFonts()
id, content, answer := driver.GenerateIdQuestionAnswer()
item, err := driver.DrawCaptcha(content)
if err != nil {
return "", "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
}
err = cs.captchaRepo.SetCaptcha(ctx, id, answer)
if err != nil {
return "", "", err
}
captchaBase64 = item.EncodeB64string()
return id, captchaBase64, nil
}
// VerifyCaptcha generate captcha
func (cs *CaptchaService) VerifyCaptcha(ctx context.Context, key, captcha string) (isCorrect bool, err error) {
realCaptcha, err := cs.captchaRepo.GetCaptcha(ctx, key)
if err != nil {
2023-02-24 16:30:21 +08:00
log.Error("VerifyCaptcha GetCaptcha Error", err.Error())
return false, nil
}
err = cs.captchaRepo.DelCaptcha(ctx, key)
if err != nil {
log.Error("VerifyCaptcha DelCaptcha Error", err.Error())
2022-09-27 17:59:05 +08:00
return false, nil
}
return strings.TrimSpace(captcha) == realCaptcha, nil
}