-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Recaptcha functionality to Gitea #4044
Changes from 4 commits
a467186
55bbfac
76b57f1
0b12d2a
f6d9d2b
a39289d
22d6265
02ac7e3
f203c2f
7e6a60a
e787c7f
1effea1
b49c864
313e7dd
d9e4392
5039fe1
f4ddfa1
f2199d1
59cba2c
5aa9afb
628ca1b
8357eb5
7ff8e14
3239fad
795019c
6786290
d32a204
93b4909
a2b9ba2
1812cd0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Copyright 2018 The Gitea Authors. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package recaptcha | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
"net/url" | ||
"time" | ||
|
||
"code.gitea.io/gitea/modules/setting" | ||
) | ||
|
||
// Response is the structure of JSON returned from API | ||
type Response struct { | ||
Success bool `json:"success"` | ||
ChallengeTS time.Time `json:"challenge_ts"` | ||
Hostname string `json:"hostname"` | ||
ErrorCodes []string `json:"error-codes"` | ||
} | ||
|
||
const apiURL = "https://www.google.com/recaptcha/api/siteverify" | ||
|
||
// Verify calls Google Recaptcha API to verify token | ||
func Verify(response string) (bool, error) { | ||
resp, err := http.PostForm(apiURL, | ||
url.Values{"secret": {setting.Service.RecaptchaSecret}, "response": {response}}) | ||
if err != nil { | ||
return false, fmt.Errorf("Failed to send CAPTCHA response: %s", err) | ||
} | ||
defer resp.Body.Close() | ||
body, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
return false, fmt.Errorf("Failed to read CAPTCHA response: %s", err) | ||
} | ||
jsonResponse := Response{Success: false} // set a default of fail for CAPTCHA | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default value of |
||
err = json.Unmarshal(body, &jsonResponse) | ||
if err != nil { | ||
return false, fmt.Errorf("Failed to parse CAPTCHA response: %s", err) | ||
} | ||
|
||
return jsonResponse.Success, nil | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove empty line |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -186,6 +186,12 @@ func NewFuncMap() []template.FuncMap { | |
"ParseDeadline": func(deadline string) []string { | ||
return strings.Split(deadline, "|") | ||
}, | ||
"EnableRecaptcha": func() bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need a helper function for that? Please use |
||
return setting.Service.EnableRecaptcha | ||
}, | ||
"RecaptchaSitekey": func() string { | ||
return setting.Service.RecaptchaSitekey | ||
}, | ||
}} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ import ( | |
"code.gitea.io/gitea/modules/base" | ||
"code.gitea.io/gitea/modules/context" | ||
"code.gitea.io/gitea/modules/log" | ||
"code.gitea.io/gitea/modules/recaptcha" | ||
"code.gitea.io/gitea/modules/setting" | ||
|
||
"github.com/go-macaron/captcha" | ||
|
@@ -640,6 +641,8 @@ func LinkAccount(ctx *context.Context) { | |
ctx.Data["Title"] = ctx.Tr("link_account") | ||
ctx.Data["LinkAccountMode"] = true | ||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha | ||
ctx.Data["EnableRecaptcha"] = setting.Service.EnableRecaptcha | ||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey | ||
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration | ||
ctx.Data["ShowRegistrationButton"] = false | ||
|
||
|
@@ -665,6 +668,8 @@ func LinkAccountPostSignIn(ctx *context.Context, signInForm auth.SignInForm) { | |
ctx.Data["LinkAccountMode"] = true | ||
ctx.Data["LinkAccountModeSignIn"] = true | ||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha | ||
ctx.Data["EnableRecaptcha"] = setting.Service.EnableRecaptcha | ||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey | ||
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration | ||
ctx.Data["ShowRegistrationButton"] = false | ||
|
||
|
@@ -731,6 +736,8 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au | |
ctx.Data["LinkAccountMode"] = true | ||
ctx.Data["LinkAccountModeRegister"] = true | ||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha | ||
ctx.Data["EnableRecaptcha"] = setting.Service.EnableRecaptcha | ||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey | ||
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration | ||
ctx.Data["ShowRegistrationButton"] = false | ||
|
||
|
@@ -760,6 +767,16 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au | |
return | ||
} | ||
|
||
if setting.Service.EnableRecaptcha { | ||
ctx.Req.ParseForm() | ||
valid, _ := recaptcha.Verify(ctx.Req.Form.Get("g-recaptcha-response")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add |
||
if !valid { | ||
ctx.Data["Err_Captcha"] = true | ||
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplLinkAccount, &form) | ||
return | ||
} | ||
} | ||
|
||
if (len(strings.TrimSpace(form.Password)) > 0 || len(strings.TrimSpace(form.Retype)) > 0) && form.Password != form.Retype { | ||
ctx.Data["Err_Password"] = true | ||
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplLinkAccount, &form) | ||
|
@@ -857,6 +874,9 @@ func SignUp(ctx *context.Context) { | |
|
||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha | ||
|
||
ctx.Data["EnableRecaptcha"] = setting.Service.EnableRecaptcha | ||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey | ||
|
||
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration | ||
|
||
ctx.HTML(200, tplSignUp) | ||
|
@@ -870,6 +890,9 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo | |
|
||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha | ||
|
||
ctx.Data["EnableRecaptcha"] = setting.Service.EnableRecaptcha | ||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey | ||
|
||
//Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true | ||
if !setting.Service.ShowRegistrationButton { | ||
ctx.Error(403) | ||
|
@@ -887,6 +910,16 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo | |
return | ||
} | ||
|
||
if setting.Service.EnableRecaptcha { | ||
ctx.Req.ParseForm() | ||
valid, _ := recaptcha.Verify(ctx.Req.Form.Get("g-recaptcha-response")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add |
||
if !valid { | ||
ctx.Data["Err_Captcha"] = true | ||
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplSignUp, &form) | ||
return | ||
} | ||
} | ||
|
||
if form.Password != form.Retype { | ||
ctx.Data["Err_Password"] = true | ||
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplSignUp, &form) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ import ( | |
"code.gitea.io/gitea/modules/context" | ||
"code.gitea.io/gitea/modules/generate" | ||
"code.gitea.io/gitea/modules/log" | ||
"code.gitea.io/gitea/modules/recaptcha" | ||
"code.gitea.io/gitea/modules/setting" | ||
|
||
"github.com/go-macaron/captcha" | ||
|
@@ -308,6 +309,8 @@ func RegisterOpenID(ctx *context.Context) { | |
ctx.Data["PageIsOpenIDRegister"] = true | ||
ctx.Data["EnableOpenIDSignUp"] = setting.Service.EnableOpenIDSignUp | ||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha | ||
ctx.Data["EnableRecaptcha"] = setting.Service.EnableRecaptcha | ||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey | ||
ctx.Data["OpenID"] = oid | ||
userName, _ := ctx.Session.Get("openid_determined_username").(string) | ||
if userName != "" { | ||
|
@@ -333,6 +336,8 @@ func RegisterOpenIDPost(ctx *context.Context, cpt *captcha.Captcha, form auth.Si | |
ctx.Data["PageIsOpenIDRegister"] = true | ||
ctx.Data["EnableOpenIDSignUp"] = setting.Service.EnableOpenIDSignUp | ||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha | ||
ctx.Data["EnableRecaptcha"] = setting.Service.EnableRecaptcha | ||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey | ||
ctx.Data["OpenID"] = oid | ||
|
||
if setting.Service.EnableCaptcha && !cpt.VerifyReq(ctx.Req) { | ||
|
@@ -341,6 +346,16 @@ func RegisterOpenIDPost(ctx *context.Context, cpt *captcha.Captcha, form auth.Si | |
return | ||
} | ||
|
||
if setting.Service.EnableRecaptcha { | ||
ctx.Req.ParseForm() | ||
valid, _ := recaptcha.Verify(ctx.Req.Form.Get("g-recaptcha-response")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
if !valid { | ||
ctx.Data["Err_Captcha"] = true | ||
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplSignUpOID, &form) | ||
return | ||
} | ||
} | ||
|
||
len := setting.MinPasswordLength | ||
if len < 256 { | ||
len = 256 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,13 @@ | |
</div> | ||
{{end}} | ||
|
||
{{if .EnableRecaptcha}} | ||
<div class="inline field required"> | ||
<div class="g-recaptcha" data-sitekey="{{ .RecaptchaSitekey }}" style="margin: 0 auto; width: 304px; padding-left: 30px"></div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not use inline css. Please add the style to the |
||
<script src="https://www.google.com/recaptcha/api.js" async></script> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Scripts should be placed in footer. |
||
</div> | ||
{{end}} | ||
|
||
<div class="inline field"> | ||
<label></label> | ||
<button class="ui green button">{{.i18n.Tr "auth.create_new_account"}}</button> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,12 @@ | |
<input id="captcha" name="captcha" value="{{.captcha}}" autocomplete="off"> | ||
</div> | ||
{{end}} | ||
{{if .EnableRecaptcha}} | ||
<div class="inline field required"> | ||
<div class="g-recaptcha" data-sitekey="{{ .RecaptchaSitekey }}" style="margin: 0 auto; width: 304px; padding-left: 30px"></div> | ||
<script src="https://www.google.com/recaptcha/api.js" async></script> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
</div> | ||
{{end}} | ||
<div class="inline field"> | ||
<label for="openid">OpenID URI</label> | ||
<input id="openid" value="{{ .OpenID }}" readonly> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not change default as this way it will be breaking change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default value is actually
false
but the documentation is wrongThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi. Yes
false
is the default, and I changed it to be correct like @JonasFranzDEV said.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like you use a captcha type and currently you have three options: disabled, image and recaptcha and default is disabled.