mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 01:34:27 +00:00 
			
		
		
		
	Add a warning for disallowed email domains (#29658)
Resolve #29660 Follow #29522 and #29609 Add a warning for disallowed email domains when admins manually add/edit users. Thanks @yp05327 for the [comment](https://github.com/go-gitea/gitea/pull/29605#issuecomment-1980105119) 
This commit is contained in:
		@@ -539,17 +539,17 @@ func validateEmailBasic(email string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// validateEmailDomain checks whether the email domain is allowed or blocked
 | 
					// validateEmailDomain checks whether the email domain is allowed or blocked
 | 
				
			||||||
func validateEmailDomain(email string) error {
 | 
					func validateEmailDomain(email string) error {
 | 
				
			||||||
	// if there is no allow list, then check email against block list
 | 
						if !IsEmailDomainAllowed(email) {
 | 
				
			||||||
	if len(setting.Service.EmailDomainAllowList) == 0 &&
 | 
					 | 
				
			||||||
		validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, email) {
 | 
					 | 
				
			||||||
		return ErrEmailInvalid{email}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// if there is an allow list, then check email against allow list
 | 
					 | 
				
			||||||
	if len(setting.Service.EmailDomainAllowList) > 0 &&
 | 
					 | 
				
			||||||
		!validation.IsEmailDomainListed(setting.Service.EmailDomainAllowList, email) {
 | 
					 | 
				
			||||||
		return ErrEmailInvalid{email}
 | 
							return ErrEmailInvalid{email}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func IsEmailDomainAllowed(email string) bool {
 | 
				
			||||||
 | 
						if len(setting.Service.EmailDomainAllowList) == 0 {
 | 
				
			||||||
 | 
							return !validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, email)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return validation.IsEmailDomainListed(setting.Service.EmailDomainAllowList, email)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -573,6 +573,7 @@ team_name_been_taken = The team name is already taken.
 | 
				
			|||||||
team_no_units_error = Allow access to at least one repository section.
 | 
					team_no_units_error = Allow access to at least one repository section.
 | 
				
			||||||
email_been_used = The email address is already used.
 | 
					email_been_used = The email address is already used.
 | 
				
			||||||
email_invalid = The email address is invalid.
 | 
					email_invalid = The email address is invalid.
 | 
				
			||||||
 | 
					email_domain_is_not_allowed = The domain of user email <b>%s</b> conflicts with EMAIL_DOMAIN_ALLOWLIST or EMAIL_DOMAIN_BLOCKLIST. Please ensure your operation is expected.
 | 
				
			||||||
openid_been_used = The OpenID address "%s" is already used.
 | 
					openid_been_used = The OpenID address "%s" is already used.
 | 
				
			||||||
username_password_incorrect = Username or password is incorrect.
 | 
					username_password_incorrect = Username or password is incorrect.
 | 
				
			||||||
password_complexity = Password does not pass complexity requirements:
 | 
					password_complexity = Password does not pass complexity requirements:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -147,6 +147,11 @@ func CreateUser(ctx *context.APIContext) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !user_model.IsEmailDomainAllowed(u.Email) {
 | 
				
			||||||
 | 
							ctx.Resp.Header().Add("X-Gitea-Warning", fmt.Sprintf("the domain of user email %s conflicts with EMAIL_DOMAIN_ALLOWLIST or EMAIL_DOMAIN_BLOCKLIST", u.Email))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Trace("Account created by admin (%s): %s", ctx.Doer.Name, u.Name)
 | 
						log.Trace("Account created by admin (%s): %s", ctx.Doer.Name, u.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Send email notification.
 | 
						// Send email notification.
 | 
				
			||||||
@@ -220,6 +225,10 @@ func EditUser(ctx *context.APIContext) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !user_model.IsEmailDomainAllowed(*form.Email) {
 | 
				
			||||||
 | 
								ctx.Resp.Header().Add("X-Gitea-Warning", fmt.Sprintf("the domain of user email %s conflicts with EMAIL_DOMAIN_ALLOWLIST or EMAIL_DOMAIN_BLOCKLIST", *form.Email))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts := &user_service.UpdateOptions{
 | 
						opts := &user_service.UpdateOptions{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -202,6 +202,11 @@ func NewUserPost(ctx *context.Context) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !user_model.IsEmailDomainAllowed(u.Email) {
 | 
				
			||||||
 | 
							ctx.Flash.Warning(ctx.Tr("form.email_domain_is_not_allowed", u.Email))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Trace("Account created by admin (%s): %s", ctx.Doer.Name, u.Name)
 | 
						log.Trace("Account created by admin (%s): %s", ctx.Doer.Name, u.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Send email notification.
 | 
						// Send email notification.
 | 
				
			||||||
@@ -425,6 +430,9 @@ func EditUserPost(ctx *context.Context) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if !user_model.IsEmailDomainAllowed(form.Email) {
 | 
				
			||||||
 | 
								ctx.Flash.Warning(ctx.Tr("form.email_domain_is_not_allowed", form.Email))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts := &user_service.UpdateOptions{
 | 
						opts := &user_service.UpdateOptions{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,9 +10,9 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auth_model "code.gitea.io/gitea/models/auth"
 | 
						auth_model "code.gitea.io/gitea/models/auth"
 | 
				
			||||||
 | 
						user_model "code.gitea.io/gitea/models/user"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/structs"
 | 
						"code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/validation"
 | 
					 | 
				
			||||||
	"code.gitea.io/gitea/modules/web/middleware"
 | 
						"code.gitea.io/gitea/modules/web/middleware"
 | 
				
			||||||
	"code.gitea.io/gitea/services/context"
 | 
						"code.gitea.io/gitea/services/context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -109,11 +109,7 @@ func (f *RegisterForm) Validate(req *http.Request, errs binding.Errors) binding.
 | 
				
			|||||||
// domains in the whitelist or if it doesn't match any of
 | 
					// domains in the whitelist or if it doesn't match any of
 | 
				
			||||||
// domains in the blocklist, if any such list is not empty.
 | 
					// domains in the blocklist, if any such list is not empty.
 | 
				
			||||||
func (f *RegisterForm) IsEmailDomainAllowed() bool {
 | 
					func (f *RegisterForm) IsEmailDomainAllowed() bool {
 | 
				
			||||||
	if len(setting.Service.EmailDomainAllowList) == 0 {
 | 
						return user_model.IsEmailDomainAllowed(f.Email)
 | 
				
			||||||
		return !validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, f.Email)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return validation.IsEmailDomainListed(setting.Service.EmailDomainAllowList, f.Email)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MustChangePasswordForm form for updating your password after account creation
 | 
					// MustChangePasswordForm form for updating your password after account creation
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -354,7 +354,8 @@ func TestAPICreateUser_NotAllowedEmailDomain(t *testing.T) {
 | 
				
			|||||||
		"password":             "allowedUser1_pass",
 | 
							"password":             "allowedUser1_pass",
 | 
				
			||||||
		"must_change_password": "true",
 | 
							"must_change_password": "true",
 | 
				
			||||||
	}).AddTokenAuth(token)
 | 
						}).AddTokenAuth(token)
 | 
				
			||||||
	MakeRequest(t, req, http.StatusCreated)
 | 
						resp := MakeRequest(t, req, http.StatusCreated)
 | 
				
			||||||
 | 
						assert.Equal(t, "the domain of user email allowedUser1@example1.org conflicts with EMAIL_DOMAIN_ALLOWLIST or EMAIL_DOMAIN_BLOCKLIST", resp.Header().Get("X-Gitea-Warning"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req = NewRequest(t, "DELETE", "/api/v1/admin/users/allowedUser1").AddTokenAuth(token)
 | 
						req = NewRequest(t, "DELETE", "/api/v1/admin/users/allowedUser1").AddTokenAuth(token)
 | 
				
			||||||
	MakeRequest(t, req, http.StatusNoContent)
 | 
						MakeRequest(t, req, http.StatusNoContent)
 | 
				
			||||||
@@ -378,7 +379,8 @@ func TestAPIEditUser_NotAllowedEmailDomain(t *testing.T) {
 | 
				
			|||||||
		SourceID:  0,
 | 
							SourceID:  0,
 | 
				
			||||||
		Email:     &newEmail,
 | 
							Email:     &newEmail,
 | 
				
			||||||
	}).AddTokenAuth(token)
 | 
						}).AddTokenAuth(token)
 | 
				
			||||||
	MakeRequest(t, req, http.StatusOK)
 | 
						resp := MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
						assert.Equal(t, "the domain of user email user2@example1.com conflicts with EMAIL_DOMAIN_ALLOWLIST or EMAIL_DOMAIN_BLOCKLIST", resp.Header().Get("X-Gitea-Warning"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	originalEmail := "user2@example.com"
 | 
						originalEmail := "user2@example.com"
 | 
				
			||||||
	req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{
 | 
						req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user