2021-01-26 18:36:53 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2021-01-26 18:36:53 +03:00
package context
import (
2022-11-23 00:13:18 +03:00
"fmt"
2021-01-26 18:36:53 +03:00
"sync"
2021-01-27 17:56:54 +03:00
"code.gitea.io/gitea/modules/cache"
2022-11-23 00:13:18 +03:00
"code.gitea.io/gitea/modules/hcaptcha"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/mcaptcha"
"code.gitea.io/gitea/modules/recaptcha"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/setting"
2024-12-22 18:33:19 +03:00
"code.gitea.io/gitea/modules/templates"
2023-02-05 10:29:03 +03:00
"code.gitea.io/gitea/modules/turnstile"
2021-01-26 18:36:53 +03:00
"gitea.com/go-chi/captcha"
)
2022-01-20 20:46:10 +03:00
var (
imageCaptchaOnce sync . Once
cpt * captcha . Captcha
)
2021-01-26 18:36:53 +03:00
// GetImageCaptcha returns global image captcha
func GetImageCaptcha ( ) * captcha . Captcha {
imageCaptchaOnce . Do ( func ( ) {
cpt = captcha . NewCaptcha ( captcha . Options {
SubURL : setting . AppSubURL ,
} )
2024-04-13 11:38:44 +03:00
cpt . Store = cache . GetCache ( ) . ChiCache ( )
2021-01-26 18:36:53 +03:00
} )
return cpt
}
2022-11-23 00:13:18 +03:00
// SetCaptchaData sets common captcha data
func SetCaptchaData ( ctx * Context ) {
if ! setting . Service . EnableCaptcha {
return
}
ctx . Data [ "EnableCaptcha" ] = setting . Service . EnableCaptcha
ctx . Data [ "RecaptchaURL" ] = setting . Service . RecaptchaURL
ctx . Data [ "Captcha" ] = GetImageCaptcha ( )
ctx . Data [ "CaptchaType" ] = setting . Service . CaptchaType
ctx . Data [ "RecaptchaSitekey" ] = setting . Service . RecaptchaSitekey
ctx . Data [ "HcaptchaSitekey" ] = setting . Service . HcaptchaSitekey
ctx . Data [ "McaptchaSitekey" ] = setting . Service . McaptchaSitekey
ctx . Data [ "McaptchaURL" ] = setting . Service . McaptchaURL
2023-02-05 10:29:03 +03:00
ctx . Data [ "CfTurnstileSitekey" ] = setting . Service . CfTurnstileSitekey
2022-11-23 00:13:18 +03:00
}
const (
2023-02-05 10:29:03 +03:00
gRecaptchaResponseField = "g-recaptcha-response"
hCaptchaResponseField = "h-captcha-response"
mCaptchaResponseField = "m-captcha-response"
cfTurnstileResponseField = "cf-turnstile-response"
2022-11-23 00:13:18 +03:00
)
// VerifyCaptcha verifies Captcha data
// No-op if captchas are not enabled
2024-12-22 18:33:19 +03:00
func VerifyCaptcha ( ctx * Context , tpl templates . TplName , form any ) {
2022-11-23 00:13:18 +03:00
if ! setting . Service . EnableCaptcha {
return
}
var valid bool
var err error
switch setting . Service . CaptchaType {
case setting . ImageCaptcha :
valid = GetImageCaptcha ( ) . VerifyReq ( ctx . Req )
case setting . ReCaptcha :
valid , err = recaptcha . Verify ( ctx , ctx . Req . Form . Get ( gRecaptchaResponseField ) )
case setting . HCaptcha :
valid , err = hcaptcha . Verify ( ctx , ctx . Req . Form . Get ( hCaptchaResponseField ) )
case setting . MCaptcha :
valid , err = mcaptcha . Verify ( ctx , ctx . Req . Form . Get ( mCaptchaResponseField ) )
2023-02-05 10:29:03 +03:00
case setting . CfTurnstile :
valid , err = turnstile . Verify ( ctx , ctx . Req . Form . Get ( cfTurnstileResponseField ) )
2022-11-23 00:13:18 +03:00
default :
2024-04-07 14:17:06 +03:00
ctx . ServerError ( "Unknown Captcha Type" , fmt . Errorf ( "unknown Captcha Type: %s" , setting . Service . CaptchaType ) )
2022-11-23 00:13:18 +03:00
return
}
if err != nil {
2024-04-07 14:17:06 +03:00
log . Debug ( "Captcha Verify failed: %v" , err )
2022-11-23 00:13:18 +03:00
}
if ! valid {
ctx . Data [ "Err_Captcha" ] = true
ctx . RenderWithErr ( ctx . Tr ( "form.captcha_incorrect" ) , tpl , form )
}
}