loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Skip email domain check when admin users adds user manually (#29522)

Fix #27457

Administrators should be able to manually create any user even if the
user's email address is not in `EMAIL_DOMAIN_ALLOWLIST`.

(cherry picked from commit 4fd9c56ed09b31e2f6164a5f534a31c6624d0478)

authored by

Zettat123 and committed by
Earl Warren
b6057a34 907c3d0c

+93 -32
+47 -28
models/user/email_address.go
··· 157 157 158 158 var emailRegexp = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") 159 159 160 - // ValidateEmail check if email is a allowed address 160 + // ValidateEmail check if email is a valid & allowed address 161 161 func ValidateEmail(email string) error { 162 - if len(email) == 0 { 163 - return ErrEmailInvalid{email} 162 + if err := validateEmailBasic(email); err != nil { 163 + return err 164 164 } 165 + return validateEmailDomain(email) 166 + } 165 167 166 - if !emailRegexp.MatchString(email) { 167 - return ErrEmailCharIsNotSupported{email} 168 - } 169 - 170 - if email[0] == '-' { 171 - return ErrEmailInvalid{email} 172 - } 173 - 174 - if _, err := mail.ParseAddress(email); err != nil { 175 - return ErrEmailInvalid{email} 176 - } 177 - 178 - // if there is no allow list, then check email against block list 179 - if len(setting.Service.EmailDomainAllowList) == 0 && 180 - validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, email) { 181 - return ErrEmailInvalid{email} 182 - } 183 - 184 - // if there is an allow list, then check email against allow list 185 - if len(setting.Service.EmailDomainAllowList) > 0 && 186 - !validation.IsEmailDomainListed(setting.Service.EmailDomainAllowList, email) { 187 - return ErrEmailInvalid{email} 188 - } 189 - 190 - return nil 168 + // ValidateEmailForAdmin check if email is a valid address when admins manually add users 169 + func ValidateEmailForAdmin(email string) error { 170 + return validateEmailBasic(email) 171 + // In this case we do not need to check the email domain 191 172 } 192 173 193 174 func GetEmailAddressByEmail(ctx context.Context, email string) (*EmailAddress, error) { ··· 543 524 544 525 return committer.Commit() 545 526 } 527 + 528 + // validateEmailBasic checks whether the email complies with the rules 529 + func validateEmailBasic(email string) error { 530 + if len(email) == 0 { 531 + return ErrEmailInvalid{email} 532 + } 533 + 534 + if !emailRegexp.MatchString(email) { 535 + return ErrEmailCharIsNotSupported{email} 536 + } 537 + 538 + if email[0] == '-' { 539 + return ErrEmailInvalid{email} 540 + } 541 + 542 + if _, err := mail.ParseAddress(email); err != nil { 543 + return ErrEmailInvalid{email} 544 + } 545 + 546 + return nil 547 + } 548 + 549 + // validateEmailDomain checks whether the email domain is allowed or blocked 550 + func validateEmailDomain(email string) error { 551 + // if there is no allow list, then check email against block list 552 + if len(setting.Service.EmailDomainAllowList) == 0 && 553 + validation.IsEmailDomainListed(setting.Service.EmailDomainBlockList, email) { 554 + return ErrEmailInvalid{email} 555 + } 556 + 557 + // if there is an allow list, then check email against allow list 558 + if len(setting.Service.EmailDomainAllowList) > 0 && 559 + !validation.IsEmailDomainListed(setting.Service.EmailDomainAllowList, email) { 560 + return ErrEmailInvalid{email} 561 + } 562 + 563 + return nil 564 + }
+18 -2
models/user/user.go
··· 598 598 599 599 // CreateUser creates record of a new user. 600 600 func CreateUser(ctx context.Context, u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err error) { 601 + return createUser(ctx, u, false, overwriteDefault...) 602 + } 603 + 604 + // AdminCreateUser is used by admins to manually create users 605 + func AdminCreateUser(ctx context.Context, u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err error) { 606 + return createUser(ctx, u, true, overwriteDefault...) 607 + } 608 + 609 + // createUser creates record of a new user. 610 + func createUser(ctx context.Context, u *User, createdByAdmin bool, overwriteDefault ...*CreateUserOverwriteOptions) (err error) { 601 611 if err = IsUsableUsername(u.Name); err != nil { 602 612 return err 603 613 } ··· 651 661 return err 652 662 } 653 663 654 - if err := ValidateEmail(u.Email); err != nil { 655 - return err 664 + if createdByAdmin { 665 + if err := ValidateEmailForAdmin(u.Email); err != nil { 666 + return err 667 + } 668 + } else { 669 + if err := ValidateEmail(u.Email); err != nil { 670 + return err 671 + } 656 672 } 657 673 658 674 ctx, committer, err := db.TxContext(ctx)
+1 -1
routers/api/v1/admin/user.go
··· 133 133 u.UpdatedUnix = u.CreatedUnix 134 134 } 135 135 136 - if err := user_model.CreateUser(ctx, u, overwriteDefault); err != nil { 136 + if err := user_model.AdminCreateUser(ctx, u, overwriteDefault); err != nil { 137 137 if user_model.IsErrUserAlreadyExist(err) || 138 138 user_model.IsErrEmailAlreadyUsed(err) || 139 139 db.IsErrNameReserved(err) ||
+1 -1
routers/web/admin/users.go
··· 177 177 u.MustChangePassword = form.MustChangePassword 178 178 } 179 179 180 - if err := user_model.CreateUser(ctx, u, overwriteDefault); err != nil { 180 + if err := user_model.AdminCreateUser(ctx, u, overwriteDefault); err != nil { 181 181 switch { 182 182 case user_model.IsErrUserAlreadyExist(err): 183 183 ctx.Data["Err_UserName"] = true
+26
tests/integration/api_admin_test.go
··· 14 14 "code.gitea.io/gitea/models/unittest" 15 15 user_model "code.gitea.io/gitea/models/user" 16 16 "code.gitea.io/gitea/modules/json" 17 + "code.gitea.io/gitea/modules/setting" 17 18 api "code.gitea.io/gitea/modules/structs" 18 19 "code.gitea.io/gitea/tests" 19 20 21 + "github.com/gobwas/glob" 20 22 "github.com/stretchr/testify/assert" 21 23 ) 22 24 ··· 333 335 } 334 336 }) 335 337 } 338 + 339 + func TestAPICreateUser_NotAllowedEmailDomain(t *testing.T) { 340 + defer tests.PrepareTestEnv(t)() 341 + 342 + setting.Service.EmailDomainAllowList = []glob.Glob{glob.MustCompile("example.org")} 343 + defer func() { 344 + setting.Service.EmailDomainAllowList = []glob.Glob{} 345 + }() 346 + 347 + adminUsername := "user1" 348 + token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin) 349 + 350 + req := NewRequestWithValues(t, "POST", "/api/v1/admin/users", map[string]string{ 351 + "email": "allowedUser1@example1.org", 352 + "login_name": "allowedUser1", 353 + "username": "allowedUser1", 354 + "password": "allowedUser1_pass", 355 + "must_change_password": "true", 356 + }).AddTokenAuth(token) 357 + MakeRequest(t, req, http.StatusCreated) 358 + 359 + req = NewRequest(t, "DELETE", "/api/v1/admin/users/allowedUser1").AddTokenAuth(token) 360 + MakeRequest(t, req, http.StatusNoContent) 361 + }