pronounsfu/backend/routes/auth/captcha.go

58 lines
1.3 KiB
Go

package auth
import (
"context"
"encoding/json"
"io"
"net/http"
"net/url"
"strings"
"codeberg.org/u1f320/pronouns.cc/backend/server"
"emperror.dev/errors"
)
const hcaptchaURL = "https://hcaptcha.com/siteverify"
type hcaptchaResponse struct {
Success bool `json:"success"`
}
// verifyCaptcha verifies a captcha response.
func (s *Server) verifyCaptcha(ctx context.Context, response string) (ok bool, err error) {
vals := url.Values{
"response": []string{response},
"secret": []string{s.hcaptchaSecret},
"sitekey": []string{s.hcaptchaSitekey},
}
req, err := http.NewRequestWithContext(ctx, "POST", hcaptchaURL, strings.NewReader(vals.Encode()))
if err != nil {
return false, errors.Wrap(err, "creating request")
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("User-Agent", "pronouns.cc/"+server.Tag)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, errors.Wrap(err, "sending request")
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
return false, errors.Sentinel("error status code")
}
b, err := io.ReadAll(resp.Body)
if err != nil {
return false, errors.Wrap(err, "reading body")
}
var hr hcaptchaResponse
err = json.Unmarshal(b, &hr)
if err != nil {
return false, errors.Wrap(err, "unmarshaling json")
}
return hr.Success, nil
}