You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

captcha.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package context
  4. import (
  5. "fmt"
  6. "sync"
  7. "code.gitea.io/gitea/modules/base"
  8. "code.gitea.io/gitea/modules/cache"
  9. "code.gitea.io/gitea/modules/hcaptcha"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/mcaptcha"
  12. "code.gitea.io/gitea/modules/recaptcha"
  13. "code.gitea.io/gitea/modules/setting"
  14. "code.gitea.io/gitea/modules/turnstile"
  15. "gitea.com/go-chi/captcha"
  16. )
  17. var (
  18. imageCaptchaOnce sync.Once
  19. cpt *captcha.Captcha
  20. )
  21. // GetImageCaptcha returns global image captcha
  22. func GetImageCaptcha() *captcha.Captcha {
  23. imageCaptchaOnce.Do(func() {
  24. cpt = captcha.NewCaptcha(captcha.Options{
  25. SubURL: setting.AppSubURL,
  26. })
  27. cpt.Store = cache.GetCache().ChiCache()
  28. })
  29. return cpt
  30. }
  31. // SetCaptchaData sets common captcha data
  32. func SetCaptchaData(ctx *Context) {
  33. if !setting.Service.EnableCaptcha {
  34. return
  35. }
  36. ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
  37. ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
  38. ctx.Data["Captcha"] = GetImageCaptcha()
  39. ctx.Data["CaptchaType"] = setting.Service.CaptchaType
  40. ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
  41. ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
  42. ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
  43. ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
  44. ctx.Data["CfTurnstileSitekey"] = setting.Service.CfTurnstileSitekey
  45. }
  46. const (
  47. gRecaptchaResponseField = "g-recaptcha-response"
  48. hCaptchaResponseField = "h-captcha-response"
  49. mCaptchaResponseField = "m-captcha-response"
  50. cfTurnstileResponseField = "cf-turnstile-response"
  51. )
  52. // VerifyCaptcha verifies Captcha data
  53. // No-op if captchas are not enabled
  54. func VerifyCaptcha(ctx *Context, tpl base.TplName, form any) {
  55. if !setting.Service.EnableCaptcha {
  56. return
  57. }
  58. var valid bool
  59. var err error
  60. switch setting.Service.CaptchaType {
  61. case setting.ImageCaptcha:
  62. valid = GetImageCaptcha().VerifyReq(ctx.Req)
  63. case setting.ReCaptcha:
  64. valid, err = recaptcha.Verify(ctx, ctx.Req.Form.Get(gRecaptchaResponseField))
  65. case setting.HCaptcha:
  66. valid, err = hcaptcha.Verify(ctx, ctx.Req.Form.Get(hCaptchaResponseField))
  67. case setting.MCaptcha:
  68. valid, err = mcaptcha.Verify(ctx, ctx.Req.Form.Get(mCaptchaResponseField))
  69. case setting.CfTurnstile:
  70. valid, err = turnstile.Verify(ctx, ctx.Req.Form.Get(cfTurnstileResponseField))
  71. default:
  72. ctx.ServerError("Unknown Captcha Type", fmt.Errorf("unknown Captcha Type: %s", setting.Service.CaptchaType))
  73. return
  74. }
  75. if err != nil {
  76. log.Debug("Captcha Verify failed: %v", err)
  77. }
  78. if !valid {
  79. ctx.Data["Err_Captcha"] = true
  80. ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tpl, form)
  81. }
  82. }