144 lines
3.8 KiB
Go
144 lines
3.8 KiB
Go
package controller
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
models "kemendagri/sipd/services/sipd_auth/model"
|
|
"kemendagri/sipd/services/sipd_auth/utils"
|
|
"kemendagri/sipd/services/sipd_auth/utils/captcha_store"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/dchest/captcha"
|
|
)
|
|
|
|
type CaptchaController struct {
|
|
captchaStore *captcha_store.PostgreSQLStore
|
|
contextTimeout time.Duration
|
|
validate *validator.Validate
|
|
}
|
|
|
|
// https://www.machinet.net/tutorial-eng/implement-go-based-captcha-generator-validator
|
|
|
|
func NewCaptchaController(store *captcha_store.PostgreSQLStore, timeout time.Duration, vld *validator.Validate) *CaptchaController {
|
|
return &CaptchaController{
|
|
captchaStore: store,
|
|
contextTimeout: timeout,
|
|
validate: vld,
|
|
}
|
|
}
|
|
|
|
func (c *CaptchaController) New() (string, string, string, error) {
|
|
var err error
|
|
var captchaId, captchaBase64, audioBase64 string
|
|
|
|
captcha.SetCustomStore(c.captchaStore)
|
|
|
|
captchaId = uuid.New().String()
|
|
//captchaId = captcha.New()
|
|
c.captchaStore.Set(captchaId, captcha.RandomDigits(captcha.DefaultLen))
|
|
//c.captchaStore.Set(captchaId, captcha.RandomDigits(captcha.DefaultLen))
|
|
//c.captchaStore.Set(captchaId, []byte("123456"))
|
|
|
|
var captchaImage bytes.Buffer
|
|
err = captcha.WriteImage(&captchaImage, captchaId, captcha.StdWidth, captcha.StdHeight)
|
|
if err != nil {
|
|
err = utils.RequestError{
|
|
Code: http.StatusInternalServerError,
|
|
Message: "failed to generate image. - " + err.Error(),
|
|
}
|
|
return captchaId, captchaBase64, audioBase64, err
|
|
}
|
|
captchaBase64 = base64.StdEncoding.EncodeToString(captchaImage.Bytes())
|
|
|
|
var captchaAudio bytes.Buffer
|
|
err = captcha.WriteAudio(&captchaAudio, captchaId, "id")
|
|
if err != nil {
|
|
err = utils.RequestError{
|
|
Code: http.StatusInternalServerError,
|
|
Message: "failed to generate audio. - " + err.Error(),
|
|
}
|
|
return captchaId, captchaBase64, audioBase64, err
|
|
}
|
|
|
|
// Encode the audio to Base64
|
|
audioBase64 = base64.StdEncoding.EncodeToString(captchaAudio.Bytes())
|
|
|
|
/*log.Println("captchaId: ", captchaId)
|
|
log.Println("captchaBase64: ", captchaBase64)*/
|
|
|
|
return captchaId, captchaBase64, audioBase64, err
|
|
}
|
|
|
|
func (c *CaptchaController) Reload(captchaId string) (string, string, error) {
|
|
var err error
|
|
var captchaBase64, audioBase64 string
|
|
|
|
captcha.SetCustomStore(c.captchaStore)
|
|
|
|
if !captcha.Reload(captchaId) {
|
|
err = utils.RequestError{
|
|
Code: http.StatusBadRequest,
|
|
Message: "captcha reload failed, invalid captcha ID.",
|
|
}
|
|
return captchaBase64, audioBase64, err
|
|
}
|
|
|
|
var captchaImage bytes.Buffer
|
|
|
|
err = captcha.WriteImage(&captchaImage, captchaId, captcha.StdWidth, captcha.StdHeight)
|
|
if err != nil {
|
|
err = utils.RequestError{
|
|
Code: http.StatusInternalServerError,
|
|
Message: "failed to reload captcha. - " + err.Error(),
|
|
}
|
|
return captchaBase64, audioBase64, err
|
|
}
|
|
captchaBase64 = base64.StdEncoding.EncodeToString(captchaImage.Bytes())
|
|
|
|
var captchaAudio bytes.Buffer
|
|
err = captcha.WriteAudio(&captchaAudio, captchaId, "id")
|
|
if err != nil {
|
|
err = utils.RequestError{
|
|
Code: http.StatusInternalServerError,
|
|
Message: "failed to generate audio. - " + err.Error(),
|
|
}
|
|
return captchaBase64, audioBase64, err
|
|
}
|
|
|
|
// Encode the audio to Base64
|
|
audioBase64 = base64.StdEncoding.EncodeToString(captchaAudio.Bytes())
|
|
|
|
/*log.Println("captchaId: ", captchaId)
|
|
log.Println("captchaBase64: ", captchaBase64)*/
|
|
|
|
return captchaBase64, audioBase64, nil
|
|
}
|
|
|
|
func (c *CaptchaController) Validate(pl models.ValidateCaptcha) error {
|
|
var err error
|
|
|
|
err = c.validate.Struct(pl)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
captcha.SetCustomStore(c.captchaStore)
|
|
|
|
log.Printf("%+v\n", pl)
|
|
|
|
if !captcha.VerifyString(pl.Id, pl.Solution) {
|
|
err = utils.RequestError{
|
|
Code: http.StatusUnprocessableEntity,
|
|
Message: "invalid captcha",
|
|
}
|
|
return err
|
|
}
|
|
|
|
return err
|
|
}
|