From 4129e0e79bbf30e4297efd33feb2602c40322d10 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Mon, 11 Mar 2024 14:07:36 +0800 Subject: [PATCH] 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) ![image](https://github.com/go-gitea/gitea/assets/15528715/6737b221-a3a2-4180-9ef8-b846c10f96e0) --- models/user/email_address.go | 16 ++++++++-------- options/locale/locale_en-US.ini | 1 + routers/api/v1/admin/user.go | 9 +++++++++ routers/web/admin/users.go | 8 ++++++++ services/forms/user_form.go | 8 ++------ tests/integration/api_admin_test.go | 6 ++++-- 6 files changed, 32 insertions(+), 16 deletions(-) diff --git a/models/user/email_address.go b/models/user/email_address.go index 11700a0129c..a9dbb8e8915 100644 --- a/models/user/email_address.go +++ b/models/user/email_address.go @@ -539,17 +539,17 @@ func validateEmailBasic(email string) error { // validateEmailDomain checks whether the email domain is allowed or blocked func validateEmailDomain(email string) error { - // if there is no allow list, then check email against block list - if len(setting.Service.EmailDomainAllowList) == 0 && - validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, email) { + if !IsEmailDomainAllowed(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 nil +} + +func IsEmailDomainAllowed(email string) bool { + if len(setting.Service.EmailDomainAllowList) == 0 { + return !validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, email) } - return nil + return validation.IsEmailDomainListed(setting.Service.EmailDomainAllowList, email) } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index e7ba7dd8c96..afd613af590 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -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. email_been_used = The email address is already used. email_invalid = The email address is invalid. +email_domain_is_not_allowed = The domain of user email %s 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. username_password_incorrect = Username or password is incorrect. password_complexity = Password does not pass complexity requirements: diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 986305d4235..87a5b28fad0 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -147,6 +147,11 @@ func CreateUser(ctx *context.APIContext) { } 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) // Send email notification. @@ -220,6 +225,10 @@ func EditUser(ctx *context.APIContext) { } 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{ diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 671a0d8885c..6dfcfc3d9a1 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -202,6 +202,11 @@ func NewUserPost(ctx *context.Context) { } 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) // Send email notification. @@ -425,6 +430,9 @@ func EditUserPost(ctx *context.Context) { } return } + if !user_model.IsEmailDomainAllowed(form.Email) { + ctx.Flash.Warning(ctx.Tr("form.email_domain_is_not_allowed", form.Email)) + } } opts := &user_service.UpdateOptions{ diff --git a/services/forms/user_form.go b/services/forms/user_form.go index 416592bfda0..e2e6c208f7d 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -10,9 +10,9 @@ import ( "strings" 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/structs" - "code.gitea.io/gitea/modules/validation" "code.gitea.io/gitea/modules/web/middleware" "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 blocklist, if any such list is not empty. func (f *RegisterForm) IsEmailDomainAllowed() bool { - if len(setting.Service.EmailDomainAllowList) == 0 { - return !validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, f.Email) - } - - return validation.IsEmailDomainListed(setting.Service.EmailDomainAllowList, f.Email) + return user_model.IsEmailDomainAllowed(f.Email) } // MustChangePasswordForm form for updating your password after account creation diff --git a/tests/integration/api_admin_test.go b/tests/integration/api_admin_test.go index 8a330a68e24..e8954f5b208 100644 --- a/tests/integration/api_admin_test.go +++ b/tests/integration/api_admin_test.go @@ -354,7 +354,8 @@ func TestAPICreateUser_NotAllowedEmailDomain(t *testing.T) { "password": "allowedUser1_pass", "must_change_password": "true", }).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) MakeRequest(t, req, http.StatusNoContent) @@ -378,7 +379,8 @@ func TestAPIEditUser_NotAllowedEmailDomain(t *testing.T) { SourceID: 0, Email: &newEmail, }).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" req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{