mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
* Add email validity check (#13475) * Improve error feedback for duplicate deploy keys Instead of a generic HTTP 500 error page, a flash message is rendered with the deploy key page template so inform the user that a key with the intended title already exists. * API returns 422 error when key with name exists * Add email validity checking Add email validity checking for the following routes: [Web interface] 1. User registration 2. User creation by admin 3. Adding an email through user settings [API] 1. POST /admin/users 2. PATCH /admin/users/:username 3. POST /user/emails * Add further tests * Add signup email tests * Add email validity check for linking existing account * Address PR comments * Remove unneeded DB session * Move email check to updateUser Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io> * skip email validation on empty string (#13627) - move validation into its own function - use a session for UpdateUserSetting * rm TODO for backport Co-authored-by: Chris Shyi <chrisshyi13@gmail.com> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
@@ -193,6 +193,21 @@ func (err ErrEmailAlreadyUsed) Error() string {
|
||||
return fmt.Sprintf("e-mail already in use [email: %s]", err.Email)
|
||||
}
|
||||
|
||||
// ErrEmailInvalid represents an error where the email address does not comply with RFC 5322
|
||||
type ErrEmailInvalid struct {
|
||||
Email string
|
||||
}
|
||||
|
||||
// IsErrEmailInvalid checks if an error is an ErrEmailInvalid
|
||||
func IsErrEmailInvalid(err error) bool {
|
||||
_, ok := err.(ErrEmailInvalid)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrEmailInvalid) Error() string {
|
||||
return fmt.Sprintf("e-mail invalid [email: %s]", err.Email)
|
||||
}
|
||||
|
||||
// ErrOpenIDAlreadyUsed represents a "OpenIDAlreadyUsed" kind of error.
|
||||
type ErrOpenIDAlreadyUsed struct {
|
||||
OpenID string
|
||||
|
@@ -821,6 +821,10 @@ func CreateUser(u *User) (err error) {
|
||||
return ErrEmailAlreadyUsed{u.Email}
|
||||
}
|
||||
|
||||
if err = ValidateEmail(u.Email); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isExist, err = isEmailUsed(sess, u.Email)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -963,8 +967,12 @@ func checkDupEmail(e Engine, u *User) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateUser(e Engine, u *User) error {
|
||||
_, err := e.ID(u.ID).AllCols().Update(u)
|
||||
func updateUser(e Engine, u *User) (err error) {
|
||||
u.Email = strings.ToLower(u.Email)
|
||||
if err = ValidateEmail(u.Email); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = e.ID(u.ID).AllCols().Update(u)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -984,13 +992,21 @@ func updateUserCols(e Engine, u *User, cols ...string) error {
|
||||
}
|
||||
|
||||
// UpdateUserSetting updates user's settings.
|
||||
func UpdateUserSetting(u *User) error {
|
||||
func UpdateUserSetting(u *User) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
if !u.IsOrganization() {
|
||||
if err := checkDupEmail(x, u); err != nil {
|
||||
if err = checkDupEmail(sess, u); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return updateUser(x, u)
|
||||
if err = updateUser(sess, u); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
// deleteBeans deletes all given beans, beans should contain delete conditions.
|
||||
|
@@ -8,6 +8,7 @@ package models
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -32,6 +33,19 @@ type EmailAddress struct {
|
||||
IsPrimary bool `xorm:"-"`
|
||||
}
|
||||
|
||||
// ValidateEmail check if email is a allowed address
|
||||
func ValidateEmail(email string) error {
|
||||
if len(email) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err := mail.ParseAddress(email); err != nil {
|
||||
return ErrEmailInvalid{email}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetEmailAddresses returns all email addresses belongs to given user.
|
||||
func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
|
||||
emails := make([]*EmailAddress, 0, 5)
|
||||
@@ -143,6 +157,10 @@ func addEmailAddress(e Engine, email *EmailAddress) error {
|
||||
return ErrEmailAlreadyUsed{email.Email}
|
||||
}
|
||||
|
||||
if err = ValidateEmail(email.Email); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = e.Insert(email)
|
||||
return err
|
||||
}
|
||||
@@ -167,6 +185,9 @@ func AddEmailAddresses(emails []*EmailAddress) error {
|
||||
} else if used {
|
||||
return ErrEmailAlreadyUsed{emails[i].Email}
|
||||
}
|
||||
if err = ValidateEmail(emails[i].Email); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := x.Insert(emails); err != nil {
|
||||
|
@@ -346,6 +346,21 @@ func TestCreateUser(t *testing.T) {
|
||||
assert.NoError(t, DeleteUser(user))
|
||||
}
|
||||
|
||||
func TestCreateUserInvalidEmail(t *testing.T) {
|
||||
user := &User{
|
||||
Name: "GiteaBot",
|
||||
Email: "GiteaBot@gitea.io\r\n",
|
||||
Passwd: ";p['////..-++']",
|
||||
IsAdmin: false,
|
||||
Theme: setting.UI.DefaultTheme,
|
||||
MustChangePassword: false,
|
||||
}
|
||||
|
||||
err := CreateUser(user)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrEmailInvalid(err))
|
||||
}
|
||||
|
||||
func TestCreateUser_Issue5882(t *testing.T) {
|
||||
|
||||
// Init settings
|
||||
|
Reference in New Issue
Block a user