diff options
Diffstat (limited to 'models')
-rw-r--r-- | models/fixtures/user.yml | 9 | ||||
-rw-r--r-- | models/issue_mail.go | 8 | ||||
-rw-r--r-- | models/migrations/migrations.go | 2 | ||||
-rw-r--r-- | models/migrations/v93.go | 16 | ||||
-rw-r--r-- | models/user.go | 37 | ||||
-rw-r--r-- | models/user_test.go | 33 |
6 files changed, 95 insertions, 10 deletions
diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml index d89dc3c126..37225f1449 100644 --- a/models/fixtures/user.yml +++ b/models/fixtures/user.yml @@ -6,6 +6,7 @@ name: user1 full_name: User One email: user1@example.com + email_notifications_preference: enabled passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password type: 0 # individual salt: ZogKvWdyEx @@ -22,6 +23,7 @@ full_name: " < U<se>r Tw<o > >< " email: user2@example.com keep_email_private: true + email_notifications_preference: enabled passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password type: 0 # individual salt: ZogKvWdyEx @@ -40,6 +42,7 @@ name: user3 full_name: " <<<< >> >> > >> > >>> >> " email: user3@example.com + email_notifications_preference: onmention passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password type: 1 # organization salt: ZogKvWdyEx @@ -56,6 +59,7 @@ name: user4 full_name: " " email: user4@example.com + email_notifications_preference: onmention passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password type: 0 # individual salt: ZogKvWdyEx @@ -72,6 +76,7 @@ name: user5 full_name: User Five email: user5@example.com + email_notifications_preference: enabled passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password type: 0 # individual salt: ZogKvWdyEx @@ -89,6 +94,7 @@ name: user6 full_name: User Six email: user6@example.com + email_notifications_preference: enabled passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password type: 1 # organization salt: ZogKvWdyEx @@ -105,6 +111,7 @@ name: user7 full_name: User Seven email: user7@example.com + email_notifications_preference: disabled passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password type: 1 # organization salt: ZogKvWdyEx @@ -121,6 +128,7 @@ name: user8 full_name: User Eight email: user8@example.com + email_notifications_preference: enabled passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password type: 0 # individual salt: ZogKvWdyEx @@ -138,6 +146,7 @@ name: user9 full_name: User Nine email: user9@example.com + email_notifications_preference: onmention passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password type: 0 # individual salt: ZogKvWdyEx diff --git a/models/issue_mail.go b/models/issue_mail.go index 829c4cea78..87d991e500 100644 --- a/models/issue_mail.go +++ b/models/issue_mail.go @@ -70,7 +70,7 @@ func mailIssueCommentToParticipants(e Engine, issue *Issue, doer *User, content if err != nil { return fmt.Errorf("GetUserByID [%d]: %v", watchers[i].UserID, err) } - if to.IsOrganization() { + if to.IsOrganization() || to.EmailNotifications() != EmailNotificationsEnabled { continue } @@ -78,9 +78,9 @@ func mailIssueCommentToParticipants(e Engine, issue *Issue, doer *User, content names = append(names, to.Name) } for i := range participants { - if participants[i].ID == doer.ID { - continue - } else if com.IsSliceContainsStr(names, participants[i].Name) { + if participants[i].ID == doer.ID || + com.IsSliceContainsStr(names, participants[i].Name) || + participants[i].EmailNotifications() != EmailNotificationsEnabled { continue } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 7d97741a20..15e021c05a 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -240,6 +240,8 @@ var migrations = []Migration{ NewMigration("add index on owner_id of repository and type, review_id of comment", addIndexOnRepositoryAndComment), // v92 -> v93 NewMigration("remove orphaned repository index statuses", removeLingeringIndexStatus), + // v93 -> v94 + NewMigration("add email notification enabled preference to user", addEmailNotificationEnabledToUser), } // Migrate database to current version diff --git a/models/migrations/v93.go b/models/migrations/v93.go new file mode 100644 index 0000000000..0b0441cd5d --- /dev/null +++ b/models/migrations/v93.go @@ -0,0 +1,16 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import "github.com/go-xorm/xorm" + +func addEmailNotificationEnabledToUser(x *xorm.Engine) error { + // User see models/user.go + type User struct { + EmailNotificationsPreference string `xorm:"VARCHAR(20) NOT NULL DEFAULT 'enabled'"` + } + + return x.Sync2(new(User)) +} diff --git a/models/user.go b/models/user.go index ed0fe524e4..af4ccacf6f 100644 --- a/models/user.go +++ b/models/user.go @@ -58,6 +58,13 @@ const ( algoScrypt = "scrypt" algoArgon2 = "argon2" algoPbkdf2 = "pbkdf2" + + // EmailNotificationsEnabled indicates that the user would like to receive all email notifications + EmailNotificationsEnabled = "enabled" + // EmailNotificationsOnMention indicates that the user would like to be notified via email when mentioned. + EmailNotificationsOnMention = "onmention" + // EmailNotificationsDisabled indicates that the user would not like to be notified via email. + EmailNotificationsDisabled = "disabled" ) var ( @@ -87,10 +94,11 @@ type User struct { Name string `xorm:"UNIQUE NOT NULL"` FullName string // Email is the primary email address (to be used for communication) - Email string `xorm:"NOT NULL"` - KeepEmailPrivate bool - Passwd string `xorm:"NOT NULL"` - PasswdHashAlgo string `xorm:"NOT NULL DEFAULT 'pbkdf2'"` + Email string `xorm:"NOT NULL"` + KeepEmailPrivate bool + EmailNotificationsPreference string `xorm:"VARCHAR(20) NOT NULL DEFAULT 'enabled'"` + Passwd string `xorm:"NOT NULL"` + PasswdHashAlgo string `xorm:"NOT NULL DEFAULT 'pbkdf2'"` // MustChangePassword is an attribute that determines if a user // is to change his/her password after registration. @@ -719,6 +727,21 @@ func (u *User) IsMailable() bool { return u.IsActive } +// EmailNotifications returns the User's email notification preference +func (u *User) EmailNotifications() string { + return u.EmailNotificationsPreference +} + +// SetEmailNotifications sets the user's email notification preference +func (u *User) SetEmailNotifications(set string) error { + u.EmailNotificationsPreference = set + if err := UpdateUserCols(u, "email_notifications_preference"); err != nil { + log.Error("SetEmailNotifications: %v", err) + return err + } + return nil +} + func isUserExist(e Engine, uid int64, name string) (bool, error) { if len(name) == 0 { return false, nil @@ -868,6 +891,7 @@ func CreateUser(u *User) (err error) { } u.HashPassword(u.Passwd) u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization && !setting.Admin.DisableRegularOrgCreation + u.EmailNotificationsPreference = setting.Admin.DefaultEmailNotification u.MaxRepoCreation = -1 u.Theme = setting.UI.DefaultTheme @@ -1253,7 +1277,8 @@ func getUserByName(e Engine, name string) (*User, error) { return u, nil } -// GetUserEmailsByNames returns a list of e-mails corresponds to names. +// GetUserEmailsByNames returns a list of e-mails corresponds to names of users +// that have their email notifications set to enabled or onmention. func GetUserEmailsByNames(names []string) []string { return getUserEmailsByNames(x, names) } @@ -1265,7 +1290,7 @@ func getUserEmailsByNames(e Engine, names []string) []string { if err != nil { continue } - if u.IsMailable() { + if u.IsMailable() && u.EmailNotifications() != EmailNotificationsDisabled { mails = append(mails, u.Email) } } diff --git a/models/user_test.go b/models/user_test.go index 290253c4b1..d01b482ae8 100644 --- a/models/user_test.go +++ b/models/user_test.go @@ -74,6 +74,8 @@ func TestGetUserEmailsByNames(t *testing.T) { // ignore none active user email assert.Equal(t, []string{"user8@example.com"}, GetUserEmailsByNames([]string{"user8", "user9"})) assert.Equal(t, []string{"user8@example.com", "user5@example.com"}, GetUserEmailsByNames([]string{"user8", "user5"})) + + assert.Equal(t, []string{"user8@example.com"}, GetUserEmailsByNames([]string{"user8", "user7"})) } func TestUser_APIFormat(t *testing.T) { @@ -196,6 +198,37 @@ func TestDeleteUser(t *testing.T) { test(11) } +func TestEmailNotificationPreferences(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + for _, test := range []struct { + expected string + userID int64 + }{ + {EmailNotificationsEnabled, 1}, + {EmailNotificationsEnabled, 2}, + {EmailNotificationsOnMention, 3}, + {EmailNotificationsOnMention, 4}, + {EmailNotificationsEnabled, 5}, + {EmailNotificationsEnabled, 6}, + {EmailNotificationsDisabled, 7}, + {EmailNotificationsEnabled, 8}, + {EmailNotificationsOnMention, 9}, + } { + user := AssertExistsAndLoadBean(t, &User{ID: test.userID}).(*User) + assert.Equal(t, test.expected, user.EmailNotifications()) + + // Try all possible settings + assert.NoError(t, user.SetEmailNotifications(EmailNotificationsEnabled)) + assert.Equal(t, EmailNotificationsEnabled, user.EmailNotifications()) + + assert.NoError(t, user.SetEmailNotifications(EmailNotificationsOnMention)) + assert.Equal(t, EmailNotificationsOnMention, user.EmailNotifications()) + + assert.NoError(t, user.SetEmailNotifications(EmailNotificationsDisabled)) + assert.Equal(t, EmailNotificationsDisabled, user.EmailNotifications()) + } +} + func TestHashPasswordDeterministic(t *testing.T) { b := make([]byte, 16) rand.Read(b) |