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.
release/v1.15
Peter Smit 2014-12-17 10:26:19 +02:00
parent d01f2f3c22
commit 99599c099f
2 changed files with 42 additions and 9 deletions

View File

@ -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() {

View File

@ -54,6 +54,7 @@ type User struct {
LowerName string `xorm:"UNIQUE NOT NULL"` LowerName string `xorm:"UNIQUE NOT NULL"`
Name string `xorm:"UNIQUE NOT NULL"` Name string `xorm:"UNIQUE NOT NULL"`
FullName string 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,16 +649,29 @@ 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
} }
if has {
return user, nil 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.
func SearchUserByName(opt SearchOption) (us []*User, err error) { func SearchUserByName(opt SearchOption) (us []*User, err error) {
if len(opt.Keyword) == 0 { if len(opt.Keyword) == 0 {