mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 06:21:11 +00:00 
			
		
		
		
	chore: add email blocklist unit test
This commit is contained in:
		
					parent
					
						
							
								cf1fda81f6
							
						
					
				
			
			
				commit
				
					
						a511e37572
					
				
			
		
					 9 changed files with 92 additions and 21 deletions
				
			
		|  | @ -72,22 +72,22 @@ func validateEmailBasic(email string) error { | |||
| } | ||||
| 
 | ||||
| func validateEmailDomain(email string) error { | ||||
| 	if !IsEmailDomainAllowed(email) { | ||||
| 	if _, ok := IsEmailDomainAllowed(email); !ok { | ||||
| 		return ErrEmailInvalid{email} | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func IsEmailDomainAllowed(email string) bool { | ||||
| func IsEmailDomainAllowed(email string) (validEmail, ok bool) { | ||||
| 	// Normalized the address. This strips for example comments which could be | ||||
| 	// used to smuggle a different domain | ||||
| 	parsedAddress, err := mail.ParseAddress(email) | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 		return false, false | ||||
| 	} | ||||
| 
 | ||||
| 	return isEmailDomainAllowedInternal( | ||||
| 	return true, isEmailDomainAllowedInternal( | ||||
| 		parsedAddress.Address, | ||||
| 		setting.Service.EmailDomainAllowList, | ||||
| 		setting.Service.EmailDomainBlockList) | ||||
|  |  | |||
|  | @ -67,8 +67,3 @@ func TestEmailAddressValidate(t *testing.T) { | |||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestEmailDomainAllowList(t *testing.T) { | ||||
| 	res := IsEmailDomainAllowed("someuser@localhost.localdomain") | ||||
| 	assert.True(t, res) | ||||
| } | ||||
|  |  | |||
|  | @ -149,7 +149,7 @@ func CreateUser(ctx *context.APIContext) { | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if !validation.IsEmailDomainAllowed(u.Email) { | ||||
| 	if _, ok := validation.IsEmailDomainAllowed(u.Email); !ok { | ||||
| 		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)) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -235,7 +235,7 @@ func EditUser(ctx *context.APIContext) { | |||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if !validation.IsEmailDomainAllowed(*form.Email) { | ||||
| 		if _, ok := validation.IsEmailDomainAllowed(*form.Email); !ok { | ||||
| 			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)) | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -201,7 +201,7 @@ func NewUserPost(ctx *context.Context) { | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if !validation.IsEmailDomainAllowed(u.Email) { | ||||
| 	if _, ok := validation.IsEmailDomainAllowed(u.Email); !ok { | ||||
| 		ctx.Flash.Warning(ctx.Tr("form.email_domain_is_not_allowed", u.Email)) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -421,7 +421,7 @@ func EditUserPost(ctx *context.Context) { | |||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 		if !validation.IsEmailDomainAllowed(form.Email) { | ||||
| 		if _, ok := validation.IsEmailDomainAllowed(form.Email); !ok { | ||||
| 			ctx.Flash.Warning(ctx.Tr("form.email_domain_is_not_allowed", form.Email)) | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -452,7 +452,10 @@ func SignUpPost(ctx *context.Context) { | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if !form.IsEmailDomainAllowed() { | ||||
| 	if emailValid, ok := form.IsEmailDomainAllowed(); !emailValid { | ||||
| 		ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplSignUp, form) | ||||
| 		return | ||||
| 	} else if !ok { | ||||
| 		ctx.RenderWithErr(ctx.Tr("auth.email_domain_blacklisted"), tplSignUp, &form) | ||||
| 		return | ||||
| 	} | ||||
|  |  | |||
|  | @ -226,7 +226,10 @@ func LinkAccountPostRegister(ctx *context.Context) { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if !form.IsEmailDomainAllowed() { | ||||
| 	if emailValid, ok := form.IsEmailDomainAllowed(); !emailValid { | ||||
| 		ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplSignUp, form) | ||||
| 		return | ||||
| 	} else if !ok { | ||||
| 		ctx.RenderWithErr(ctx.Tr("auth.email_domain_blacklisted"), tplLinkAccount, &form) | ||||
| 		return | ||||
| 	} | ||||
|  |  | |||
|  | @ -109,7 +109,7 @@ func (f *RegisterForm) Validate(req *http.Request, errs binding.Errors) binding. | |||
| // The email is marked as allowed if it matches any of the | ||||
| // 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 { | ||||
| func (f *RegisterForm) IsEmailDomainAllowed() (validEmail, ok bool) { | ||||
| 	return validation.IsEmailDomainAllowed(f.Email) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,7 +20,9 @@ func TestRegisterForm_IsDomainAllowed_Empty(t *testing.T) { | |||
| 
 | ||||
| 	form := RegisterForm{} | ||||
| 
 | ||||
| 	assert.True(t, form.IsEmailDomainAllowed()) | ||||
| 	emailValid, ok := form.IsEmailDomainAllowed() | ||||
| 	assert.False(t, emailValid) | ||||
| 	assert.False(t, ok) | ||||
| } | ||||
| 
 | ||||
| func TestRegisterForm_IsDomainAllowed_InvalidEmail(t *testing.T) { | ||||
|  | @ -36,7 +38,8 @@ func TestRegisterForm_IsDomainAllowed_InvalidEmail(t *testing.T) { | |||
| 	for _, v := range tt { | ||||
| 		form := RegisterForm{Email: v.email} | ||||
| 
 | ||||
| 		assert.False(t, form.IsEmailDomainAllowed()) | ||||
| 		_, ok := form.IsEmailDomainAllowed() | ||||
| 		assert.False(t, ok) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -59,7 +62,8 @@ func TestRegisterForm_IsDomainAllowed_AllowedEmail(t *testing.T) { | |||
| 	for _, v := range tt { | ||||
| 		form := RegisterForm{Email: v.email} | ||||
| 
 | ||||
| 		assert.Equal(t, v.valid, form.IsEmailDomainAllowed()) | ||||
| 		_, ok := form.IsEmailDomainAllowed() | ||||
| 		assert.Equal(t, v.valid, ok) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -72,7 +76,6 @@ func TestRegisterForm_IsDomainAllowed_BlockedEmail(t *testing.T) { | |||
| 	}{ | ||||
| 		{"security@gitea.io", false}, | ||||
| 		{"security@gitea.example", true}, | ||||
| 		{"invalid", true}, | ||||
| 
 | ||||
| 		{"user@my.block", false}, | ||||
| 		{"user@my.block1", true}, | ||||
|  | @ -81,7 +84,8 @@ func TestRegisterForm_IsDomainAllowed_BlockedEmail(t *testing.T) { | |||
| 	for _, v := range tt { | ||||
| 		form := RegisterForm{Email: v.email} | ||||
| 
 | ||||
| 		assert.Equal(t, v.valid, form.IsEmailDomainAllowed()) | ||||
| 		_, ok := form.IsEmailDomainAllowed() | ||||
| 		assert.Equal(t, v.valid, ok) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										66
									
								
								tests/integration/email_block_allowlist_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								tests/integration/email_block_allowlist_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| // Copyright 2025 The Forgejo Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
| 
 | ||||
| package integration | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"forgejo.org/modules/setting" | ||||
| 	"forgejo.org/modules/test" | ||||
| 	"forgejo.org/modules/validation" | ||||
| 	"forgejo.org/tests" | ||||
| 
 | ||||
| 	"github.com/gobwas/glob" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
| 
 | ||||
| func TestEmailBlocklist(t *testing.T) { | ||||
| 	defer test.MockVariableValue( | ||||
| 		&setting.Service.EmailDomainBlockList, | ||||
| 		[]glob.Glob{glob.MustCompile("evil")}, | ||||
| 	)() | ||||
| 
 | ||||
| 	defer tests.PrepareTestEnv(t)() | ||||
| 
 | ||||
| 	emailValid, ok := validation.IsEmailDomainAllowed("🐸@pond") | ||||
| 	assert.True(t, emailValid) | ||||
| 	assert.True(t, ok) | ||||
| 
 | ||||
| 	emailValid, ok = validation.IsEmailDomainAllowed("🐸@pond (what-is-this@evil)") | ||||
| 	assert.True(t, emailValid) | ||||
| 	assert.True(t, ok) | ||||
| 
 | ||||
| 	emailValid, ok = validation.IsEmailDomainAllowed("jomo@evil") | ||||
| 	assert.True(t, emailValid) | ||||
| 	assert.False(t, ok) | ||||
| 
 | ||||
| 	emailValid, ok = validation.IsEmailDomainAllowed("jomo@evil (but-does-it@break)") | ||||
| 	assert.True(t, emailValid) | ||||
| 	assert.False(t, ok) | ||||
| } | ||||
| 
 | ||||
| func TestEmailAllowlist(t *testing.T) { | ||||
| 	defer test.MockVariableValue( | ||||
| 		&setting.Service.EmailDomainAllowList, | ||||
| 		[]glob.Glob{glob.MustCompile("pond")}, | ||||
| 	)() | ||||
| 
 | ||||
| 	defer tests.PrepareTestEnv(t)() | ||||
| 
 | ||||
| 	emailValid, ok := validation.IsEmailDomainAllowed("🐸@pond") | ||||
| 	assert.True(t, emailValid) | ||||
| 	assert.True(t, ok) | ||||
| 
 | ||||
| 	emailValid, ok = validation.IsEmailDomainAllowed("🐸@pond (what-is-this@evil)") | ||||
| 	assert.True(t, emailValid) | ||||
| 	assert.True(t, ok) | ||||
| 
 | ||||
| 	emailValid, ok = validation.IsEmailDomainAllowed("jomo@evil") | ||||
| 	assert.True(t, emailValid) | ||||
| 	assert.False(t, ok) | ||||
| 
 | ||||
| 	emailValid, ok = validation.IsEmailDomainAllowed("jomo@evil (but-does-it@break)") | ||||
| 	assert.True(t, emailValid) | ||||
| 	assert.False(t, ok) | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue