Bläddra i källkod

Add alternative email addresses to the model

A new struct is created named EmailAddress that contains alternative
email addresses for users. Also the email related methods; IsEmailUsed
and GetUserByEmail are updated.

DeleteUser deletes the extra email addresses and DeleteInactivateUsers
also deletes inactive accounts. This could be factored out, but should
do it for now.
Peter Smit 10 år sedan
förälder
incheckning
99599c099f
2 ändrade filer med 42 tillägg och 9 borttagningar
  1. 1 1
      models/models.go
  2. 41 8
      models/user.go

+ 1 - 1
models/models.go

@@ -45,7 +45,7 @@ func init() {
 		new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone),
 		new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone),
 		new(Mirror), new(Release), new(LoginSource), new(Webhook),
 		new(Mirror), new(Release), new(LoginSource), new(Webhook),
 		new(UpdateTask), new(HookTask), new(Team), new(OrgUser), new(TeamUser),
 		new(UpdateTask), new(HookTask), new(Team), new(OrgUser), new(TeamUser),
-		new(Notice))
+		new(Notice), new(EmailAddress))
 }
 }
 
 
 func LoadModelsConfig() {
 func LoadModelsConfig() {

+ 41 - 8
models/user.go

@@ -50,10 +50,11 @@ var (
 
 
 // User represents the object of individual and member of organization.
 // User represents the object of individual and member of organization.
 type User struct {
 type User struct {
-	Id          int64
-	LowerName   string `xorm:"UNIQUE NOT NULL"`
-	Name        string `xorm:"UNIQUE NOT NULL"`
-	FullName    string
+	Id        int64
+	LowerName string `xorm:"UNIQUE NOT NULL"`
+	Name      string `xorm:"UNIQUE NOT NULL"`
+	FullName  string
+	// Email is the primary email address (to be used for communication).
 	Email       string `xorm:"UNIQUE(s) NOT NULL"`
 	Email       string `xorm:"UNIQUE(s) NOT NULL"`
 	Passwd      string `xorm:"NOT NULL"`
 	Passwd      string `xorm:"NOT NULL"`
 	LoginType   LoginType
 	LoginType   LoginType
@@ -93,6 +94,15 @@ type User struct {
 	Members     []*User `xorm:"-"`
 	Members     []*User `xorm:"-"`
 }
 }
 
 
+// EmailAdresses is the list of all email addresses of a user. Can contain the
+// primary email address, but is not obligatory
+type EmailAddress struct {
+	Id          int64
+	OwnerId     int64  `xorm:"INDEX NOT NULL"`
+	Email       string `xorm:"UNIQUE NOT NULL"`
+	IsActivated bool
+}
+
 // DashboardLink returns the user dashboard page link.
 // DashboardLink returns the user dashboard page link.
 func (u *User) DashboardLink() string {
 func (u *User) DashboardLink() string {
 	if u.IsOrganization() {
 	if u.IsOrganization() {
@@ -248,6 +258,9 @@ func IsEmailUsed(email string) (bool, error) {
 	if len(email) == 0 {
 	if len(email) == 0 {
 		return false, nil
 		return false, nil
 	}
 	}
+	if used, err := x.Get(&EmailAddress{Email: email}); used || err != nil {
+		return used, err
+	}
 	return x.Get(&User{Email: email})
 	return x.Get(&User{Email: email})
 }
 }
 
 
@@ -488,6 +501,10 @@ func DeleteUser(u *User) error {
 	if _, err = x.Delete(&Access{UserName: u.LowerName}); err != nil {
 	if _, err = x.Delete(&Access{UserName: u.LowerName}); err != nil {
 		return err
 		return err
 	}
 	}
+	// Delete all alternative email addresses
+	if _, err = x.Delete(&EmailAddress{OwnerId: u.Id}); err != nil {
+		return err
+	}
 	// Delete all SSH keys.
 	// Delete all SSH keys.
 	keys := make([]*PublicKey, 0, 10)
 	keys := make([]*PublicKey, 0, 10)
 	if err = x.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil {
 	if err = x.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil {
@@ -508,9 +525,12 @@ func DeleteUser(u *User) error {
 	return err
 	return err
 }
 }
 
 
-// DeleteInactivateUsers deletes all inactivate users.
+// DeleteInactivateUsers deletes all inactivate users and email addresses.
 func DeleteInactivateUsers() error {
 func DeleteInactivateUsers() error {
 	_, err := x.Where("is_active=?", false).Delete(new(User))
 	_, err := x.Where("is_active=?", false).Delete(new(User))
+	if err == nil {
+		_, err = x.Delete(&EmailAddress{IsActivated: false})
+	}
 	return err
 	return err
 }
 }
 
 
@@ -629,14 +649,27 @@ func GetUserByEmail(email string) (*User, error) {
 	if len(email) == 0 {
 	if len(email) == 0 {
 		return nil, ErrUserNotExist
 		return nil, ErrUserNotExist
 	}
 	}
+	// First try to find the user by primary email
 	user := &User{Email: strings.ToLower(email)}
 	user := &User{Email: strings.ToLower(email)}
 	has, err := x.Get(user)
 	has, err := x.Get(user)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
-	} else if !has {
-		return nil, ErrUserNotExist
 	}
 	}
-	return user, nil
+	if has {
+		return user, nil
+	}
+
+	// Otherwise, check in alternative list for activated email addresses
+	emailAddress := &EmailAddress{Email: strings.ToLower(email), IsActivated: true}
+	has, err = x.Get(emailAddress)
+	if err != nil {
+		return nil, err
+	}
+	if has {
+		return GetUserById(emailAddress.OwnerId)
+	}
+
+	return nil, ErrUserNotExist
 }
 }
 
 
 // SearchUserByName returns given number of users whose name contains keyword.
 // SearchUserByName returns given number of users whose name contains keyword.