gitea源码

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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/cache"
  8. "code.gitea.io/gitea/modules/hcaptcha"
  9. "code.gitea.io/gitea/modules/log"
  10. "code.gitea.io/gitea/modules/mcaptcha"
  11. "code.gitea.io/gitea/modules/recaptcha"
  12. "code.gitea.io/gitea/modules/setting"
  13. "code.gitea.io/gitea/modules/templates"
  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 templates.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. }