mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 19:06:18 +01:00 
			
		
		
		
	Skip email domain check when admins edit user emails (#29609)
Follow #29522 Administrators should be able to set a user's email address even if the email address is not in `EMAIL_DOMAIN_ALLOWLIST`
This commit is contained in:
		| @@ -162,7 +162,7 @@ func ValidateEmail(email string) error { | |||||||
| 	return validateEmailDomain(email) | 	return validateEmailDomain(email) | ||||||
| } | } | ||||||
|  |  | ||||||
| // ValidateEmailForAdmin check if email is a valid address when admins manually add users | // ValidateEmailForAdmin check if email is a valid address when admins manually add or edit users | ||||||
| func ValidateEmailForAdmin(email string) error { | func ValidateEmailForAdmin(email string) error { | ||||||
| 	return validateEmailBasic(email) | 	return validateEmailBasic(email) | ||||||
| 	// In this case we do not need to check the email domain | 	// In this case we do not need to check the email domain | ||||||
|   | |||||||
| @@ -209,7 +209,7 @@ func EditUser(ctx *context.APIContext) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if form.Email != nil { | 	if form.Email != nil { | ||||||
| 		if err := user_service.AddOrSetPrimaryEmailAddress(ctx, ctx.ContextUser, *form.Email); err != nil { | 		if err := user_service.AdminAddOrSetPrimaryEmailAddress(ctx, ctx.ContextUser, *form.Email); err != nil { | ||||||
| 			switch { | 			switch { | ||||||
| 			case user_model.IsErrEmailCharIsNotSupported(err), user_model.IsErrEmailInvalid(err): | 			case user_model.IsErrEmailCharIsNotSupported(err), user_model.IsErrEmailInvalid(err): | ||||||
| 				ctx.Error(http.StatusBadRequest, "EmailInvalid", err) | 				ctx.Error(http.StatusBadRequest, "EmailInvalid", err) | ||||||
|   | |||||||
| @@ -412,7 +412,7 @@ func EditUserPost(ctx *context.Context) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if form.Email != "" { | 	if form.Email != "" { | ||||||
| 		if err := user_service.AddOrSetPrimaryEmailAddress(ctx, u, form.Email); err != nil { | 		if err := user_service.AdminAddOrSetPrimaryEmailAddress(ctx, u, form.Email); err != nil { | ||||||
| 			switch { | 			switch { | ||||||
| 			case user_model.IsErrEmailCharIsNotSupported(err), user_model.IsErrEmailInvalid(err): | 			case user_model.IsErrEmailCharIsNotSupported(err), user_model.IsErrEmailInvalid(err): | ||||||
| 				ctx.Data["Err_Email"] = true | 				ctx.Data["Err_Email"] = true | ||||||
|   | |||||||
| @@ -14,12 +14,13 @@ import ( | |||||||
| 	"code.gitea.io/gitea/modules/util" | 	"code.gitea.io/gitea/modules/util" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func AddOrSetPrimaryEmailAddress(ctx context.Context, u *user_model.User, emailStr string) error { | // AdminAddOrSetPrimaryEmailAddress is used by admins to add or set a user's primary email address | ||||||
|  | func AdminAddOrSetPrimaryEmailAddress(ctx context.Context, u *user_model.User, emailStr string) error { | ||||||
| 	if strings.EqualFold(u.Email, emailStr) { | 	if strings.EqualFold(u.Email, emailStr) { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := user_model.ValidateEmail(emailStr); err != nil { | 	if err := user_model.ValidateEmailForAdmin(emailStr); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,11 +10,13 @@ import ( | |||||||
| 	organization_model "code.gitea.io/gitea/models/organization" | 	organization_model "code.gitea.io/gitea/models/organization" | ||||||
| 	"code.gitea.io/gitea/models/unittest" | 	"code.gitea.io/gitea/models/unittest" | ||||||
| 	user_model "code.gitea.io/gitea/models/user" | 	user_model "code.gitea.io/gitea/models/user" | ||||||
|  | 	"code.gitea.io/gitea/modules/setting" | ||||||
|  |  | ||||||
|  | 	"github.com/gobwas/glob" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func TestAddOrSetPrimaryEmailAddress(t *testing.T) { | func TestAdminAddOrSetPrimaryEmailAddress(t *testing.T) { | ||||||
| 	assert.NoError(t, unittest.PrepareTestDatabase()) | 	assert.NoError(t, unittest.PrepareTestDatabase()) | ||||||
|  |  | ||||||
| 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 27}) | 	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 27}) | ||||||
| @@ -28,7 +30,7 @@ func TestAddOrSetPrimaryEmailAddress(t *testing.T) { | |||||||
| 	assert.NotEqual(t, "new-primary@example.com", primary.Email) | 	assert.NotEqual(t, "new-primary@example.com", primary.Email) | ||||||
| 	assert.Equal(t, user.Email, primary.Email) | 	assert.Equal(t, user.Email, primary.Email) | ||||||
|  |  | ||||||
| 	assert.NoError(t, AddOrSetPrimaryEmailAddress(db.DefaultContext, user, "new-primary@example.com")) | 	assert.NoError(t, AdminAddOrSetPrimaryEmailAddress(db.DefaultContext, user, "new-primary@example.com")) | ||||||
|  |  | ||||||
| 	primary, err = user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) | 	primary, err = user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| @@ -39,7 +41,19 @@ func TestAddOrSetPrimaryEmailAddress(t *testing.T) { | |||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, emails, 2) | 	assert.Len(t, emails, 2) | ||||||
|  |  | ||||||
| 	assert.NoError(t, AddOrSetPrimaryEmailAddress(db.DefaultContext, user, "user27@example.com")) | 	setting.Service.EmailDomainAllowList = []glob.Glob{glob.MustCompile("example.org")} | ||||||
|  | 	defer func() { | ||||||
|  | 		setting.Service.EmailDomainAllowList = []glob.Glob{} | ||||||
|  | 	}() | ||||||
|  |  | ||||||
|  | 	assert.NoError(t, AdminAddOrSetPrimaryEmailAddress(db.DefaultContext, user, "new-primary2@example2.com")) | ||||||
|  |  | ||||||
|  | 	primary, err = user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Equal(t, "new-primary2@example2.com", primary.Email) | ||||||
|  | 	assert.Equal(t, user.Email, primary.Email) | ||||||
|  |  | ||||||
|  | 	assert.NoError(t, AdminAddOrSetPrimaryEmailAddress(db.DefaultContext, user, "user27@example.com")) | ||||||
|  |  | ||||||
| 	primary, err = user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) | 	primary, err = user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| @@ -48,7 +62,7 @@ func TestAddOrSetPrimaryEmailAddress(t *testing.T) { | |||||||
|  |  | ||||||
| 	emails, err = user_model.GetEmailAddresses(db.DefaultContext, user.ID) | 	emails, err = user_model.GetEmailAddresses(db.DefaultContext, user.ID) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Len(t, emails, 2) | 	assert.Len(t, emails, 3) | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestReplacePrimaryEmailAddress(t *testing.T) { | func TestReplacePrimaryEmailAddress(t *testing.T) { | ||||||
|   | |||||||
| @@ -359,3 +359,32 @@ func TestAPICreateUser_NotAllowedEmailDomain(t *testing.T) { | |||||||
| 	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) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestAPIEditUser_NotAllowedEmailDomain(t *testing.T) { | ||||||
|  | 	defer tests.PrepareTestEnv(t)() | ||||||
|  |  | ||||||
|  | 	setting.Service.EmailDomainAllowList = []glob.Glob{glob.MustCompile("example.org")} | ||||||
|  | 	defer func() { | ||||||
|  | 		setting.Service.EmailDomainAllowList = []glob.Glob{} | ||||||
|  | 	}() | ||||||
|  |  | ||||||
|  | 	adminUsername := "user1" | ||||||
|  | 	token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin) | ||||||
|  | 	urlStr := fmt.Sprintf("/api/v1/admin/users/%s", "user2") | ||||||
|  |  | ||||||
|  | 	newEmail := "user2@example1.com" | ||||||
|  | 	req := NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{ | ||||||
|  | 		LoginName: "user2", | ||||||
|  | 		SourceID:  0, | ||||||
|  | 		Email:     &newEmail, | ||||||
|  | 	}).AddTokenAuth(token) | ||||||
|  | 	MakeRequest(t, req, http.StatusOK) | ||||||
|  |  | ||||||
|  | 	originalEmail := "user2@example.com" | ||||||
|  | 	req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{ | ||||||
|  | 		LoginName: "user2", | ||||||
|  | 		SourceID:  0, | ||||||
|  | 		Email:     &originalEmail, | ||||||
|  | 	}).AddTokenAuth(token) | ||||||
|  | 	MakeRequest(t, req, http.StatusOK) | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user