* implement email domain whitelisttags/v1.21.12.1
| @@ -311,6 +311,9 @@ ACTIVE_CODE_LIVE_MINUTES = 180 | |||||
| RESET_PASSWD_CODE_LIVE_MINUTES = 180 | RESET_PASSWD_CODE_LIVE_MINUTES = 180 | ||||
| ; Whether a new user needs to confirm their email when registering. | ; Whether a new user needs to confirm their email when registering. | ||||
| REGISTER_EMAIL_CONFIRM = false | REGISTER_EMAIL_CONFIRM = false | ||||
| ; List of domain names that are allowed to be used to register on a Gitea instance | |||||
| ; gitea.io,example.com | |||||
| EMAIL_DOMAIN_WHITELIST= | |||||
| ; Disallow registration, only allow admins to create accounts. | ; Disallow registration, only allow admins to create accounts. | ||||
| DISABLE_REGISTRATION = false | DISABLE_REGISTRATION = false | ||||
| ; Allow registration only using third part services, it works only when DISABLE_REGISTRATION is false | ; Allow registration only using third part services, it works only when DISABLE_REGISTRATION is false | ||||
| @@ -194,6 +194,8 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`. | |||||
| - `RECAPTCHA_SITEKEY`: **""**: Go to https://www.google.com/recaptcha/admin to get a sitekey for recaptcha. | - `RECAPTCHA_SITEKEY`: **""**: Go to https://www.google.com/recaptcha/admin to get a sitekey for recaptcha. | ||||
| - `DEFAULT_ENABLE_DEPENDENCIES`: **true** Enable this to have dependencies enabled by default. | - `DEFAULT_ENABLE_DEPENDENCIES`: **true** Enable this to have dependencies enabled by default. | ||||
| - `ENABLE_USER_HEATMAP`: **true** Enable this to display the heatmap on users profiles. | - `ENABLE_USER_HEATMAP`: **true** Enable this to display the heatmap on users profiles. | ||||
| - `EMAIL_DOMAIN_WHITELIST`: **\<empty\>**: If non-empty, list of domain names that can only be used to register | |||||
| on this instance. | |||||
| ## Webhook (`webhook`) | ## Webhook (`webhook`) | ||||
| @@ -1,4 +1,5 @@ | |||||
| // Copyright 2014 The Gogs Authors. All rights reserved. | // Copyright 2014 The Gogs Authors. All rights reserved. | ||||
| // Copyright 2018 The Gitea Authors. All rights reserved. | |||||
| // Use of this source code is governed by a MIT-style | // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | // license that can be found in the LICENSE file. | ||||
| @@ -6,6 +7,9 @@ package auth | |||||
| import ( | import ( | ||||
| "mime/multipart" | "mime/multipart" | ||||
| "strings" | |||||
| "code.gitea.io/gitea/modules/setting" | |||||
| "github.com/go-macaron/binding" | "github.com/go-macaron/binding" | ||||
| "gopkg.in/macaron.v1" | "gopkg.in/macaron.v1" | ||||
| @@ -84,6 +88,31 @@ func (f *RegisterForm) Validate(ctx *macaron.Context, errs binding.Errors) bindi | |||||
| return validate(errs, ctx.Data, f, ctx.Locale) | return validate(errs, ctx.Data, f, ctx.Locale) | ||||
| } | } | ||||
| // IsEmailDomainWhitelisted validates that the email address | |||||
| // provided by the user matches what has been configured . | |||||
| // If the domain whitelist from the config is empty, it marks the | |||||
| // email as whitelisted | |||||
| func (f RegisterForm) IsEmailDomainWhitelisted() bool { | |||||
| if len(setting.Service.EmailDomainWhitelist) == 0 { | |||||
| return true | |||||
| } | |||||
| n := strings.LastIndex(f.Email, "@") | |||||
| if n <= 0 { | |||||
| return false | |||||
| } | |||||
| domain := strings.ToLower(f.Email[n+1:]) | |||||
| for _, v := range setting.Service.EmailDomainWhitelist { | |||||
| if strings.ToLower(v) == domain { | |||||
| return true | |||||
| } | |||||
| } | |||||
| return false | |||||
| } | |||||
| // MustChangePasswordForm form for updating your password after account creation | // MustChangePasswordForm form for updating your password after account creation | ||||
| // by an admin | // by an admin | ||||
| type MustChangePasswordForm struct { | type MustChangePasswordForm struct { | ||||
| @@ -0,0 +1,64 @@ | |||||
| // Copyright 2018 The Gogs 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 auth | |||||
| import ( | |||||
| "testing" | |||||
| "code.gitea.io/gitea/modules/setting" | |||||
| "github.com/stretchr/testify/assert" | |||||
| ) | |||||
| func TestRegisterForm_IsDomainWhiteList_Empty(t *testing.T) { | |||||
| _ = setting.Service | |||||
| setting.Service.EmailDomainWhitelist = []string{} | |||||
| form := RegisterForm{} | |||||
| assert.True(t, form.IsEmailDomainWhitelisted()) | |||||
| } | |||||
| func TestRegisterForm_IsDomainWhiteList_InvalidEmail(t *testing.T) { | |||||
| _ = setting.Service | |||||
| setting.Service.EmailDomainWhitelist = []string{"gitea.io"} | |||||
| tt := []struct { | |||||
| email string | |||||
| }{ | |||||
| {"securitygieqqq"}, | |||||
| {"hdudhdd"}, | |||||
| } | |||||
| for _, v := range tt { | |||||
| form := RegisterForm{Email: v.email} | |||||
| assert.False(t, form.IsEmailDomainWhitelisted()) | |||||
| } | |||||
| } | |||||
| func TestRegisterForm_IsDomainWhiteList_ValidEmail(t *testing.T) { | |||||
| _ = setting.Service | |||||
| setting.Service.EmailDomainWhitelist = []string{"gitea.io"} | |||||
| tt := []struct { | |||||
| email string | |||||
| valid bool | |||||
| }{ | |||||
| {"security@gitea.io", true}, | |||||
| {"security@gITea.io", true}, | |||||
| {"hdudhdd", false}, | |||||
| {"seee@example.com", false}, | |||||
| } | |||||
| for _, v := range tt { | |||||
| form := RegisterForm{Email: v.email} | |||||
| assert.Equal(t, v.valid, form.IsEmailDomainWhitelisted()) | |||||
| } | |||||
| } | |||||
| @@ -1215,6 +1215,7 @@ var Service struct { | |||||
| ActiveCodeLives int | ActiveCodeLives int | ||||
| ResetPwdCodeLives int | ResetPwdCodeLives int | ||||
| RegisterEmailConfirm bool | RegisterEmailConfirm bool | ||||
| EmailDomainWhitelist []string | |||||
| DisableRegistration bool | DisableRegistration bool | ||||
| AllowOnlyExternalRegistration bool | AllowOnlyExternalRegistration bool | ||||
| ShowRegistrationButton bool | ShowRegistrationButton bool | ||||
| @@ -1248,6 +1249,7 @@ func newService() { | |||||
| Service.ResetPwdCodeLives = sec.Key("RESET_PASSWD_CODE_LIVE_MINUTES").MustInt(180) | Service.ResetPwdCodeLives = sec.Key("RESET_PASSWD_CODE_LIVE_MINUTES").MustInt(180) | ||||
| Service.DisableRegistration = sec.Key("DISABLE_REGISTRATION").MustBool() | Service.DisableRegistration = sec.Key("DISABLE_REGISTRATION").MustBool() | ||||
| Service.AllowOnlyExternalRegistration = sec.Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").MustBool() | Service.AllowOnlyExternalRegistration = sec.Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").MustBool() | ||||
| Service.EmailDomainWhitelist = sec.Key("EMAIL_DOMAIN_WHITELIST").Strings(",") | |||||
| Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration)) | Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration)) | ||||
| Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool() | Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool() | ||||
| Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool() | Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool() | ||||
| @@ -242,6 +242,7 @@ openid_register_title = Create new account | |||||
| openid_register_desc = The chosen OpenID URI is unknown. Associate it with a new account here. | openid_register_desc = The chosen OpenID URI is unknown. Associate it with a new account here. | ||||
| openid_signin_desc = Enter your OpenID URI. For example: https://anne.me, bob.openid.org.cn or gnusocial.net/carry. | openid_signin_desc = Enter your OpenID URI. For example: https://anne.me, bob.openid.org.cn or gnusocial.net/carry. | ||||
| disable_forgot_password_mail = Password reset is disabled. Please contact your site administrator. | disable_forgot_password_mail = Password reset is disabled. Please contact your site administrator. | ||||
| email_domain_blacklisted = You cannot register with your email address. | |||||
| [mail] | [mail] | ||||
| activate_account = Please activate your account | activate_account = Please activate your account | ||||
| @@ -948,6 +948,11 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo | |||||
| } | } | ||||
| } | } | ||||
| if !form.IsEmailDomainWhitelisted() { | |||||
| ctx.RenderWithErr(ctx.Tr("auth.email_domain_blacklisted"), tplSignUp, &form) | |||||
| return | |||||
| } | |||||
| if form.Password != form.Retype { | if form.Password != form.Retype { | ||||
| ctx.Data["Err_Password"] = true | ctx.Data["Err_Password"] = true | ||||
| ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplSignUp, &form) | ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplSignUp, &form) | ||||