From fd51209fa029a3d16345cb9f9668a190bf1667d0 Mon Sep 17 00:00:00 2001 From: Gary Kim Date: Fri, 9 Aug 2019 17:31:40 +0800 Subject: [PATCH 01/13] Add Backend Logic for Toggling Email Notification This commit adds the backend logic for allowing users to enable or disable email notifications. The implementation ensures that only issue notification emails get disabled and important emails are still sent regardless of the setting. The UI to toggle this setting has not yet been implemented. --- models/issue_mail.go | 8 ++++---- models/migrations/migrations.go | 2 ++ models/migrations/v93.go | 16 ++++++++++++++++ models/user.go | 23 ++++++++++++++++++----- routers/user/setting/account.go | 6 ++++++ 5 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 models/migrations/v93.go diff --git a/models/issue_mail.go b/models/issue_mail.go index 01a12b16d2a8e..f6c293938eb8e 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.EnabledEmailNotifications() { 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].EnabledEmailNotifications() { continue } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 9ffcfb4df2005..f324df8325a98 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 boolean 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 0000000000000..679b4d0da3727 --- /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 { + // Issue see models/user.go + type User struct { + EmailNotificationsEnabled bool `xorm:"NOT NULL DEFAULT true"` + } + + return x.Sync2(new(User)) +} diff --git a/models/user.go b/models/user.go index 2e4f971662ad9..3678ac9e9f152 100644 --- a/models/user.go +++ b/models/user.go @@ -87,10 +87,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 + EmailNotificationsEnabled bool `xorm:"NOT NULL DEFAULT true"` + 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 +720,18 @@ func (u *User) IsMailable() bool { return u.IsActive } +// EnabledEmailNotifications checks if the user has +// enabled receiving notifications by email +func (u *User) EnabledEmailNotifications() bool { + return u.EmailNotificationsEnabled +} + +// SetEmailNotifications sets whether the user +// would like to receive notifications by email +func (u *User) SetEmailNotifications(set bool) { + u.EmailNotificationsEnabled = set +} + func isUserExist(e Engine, uid int64, name string) (bool, error) { if len(name) == 0 { return false, nil @@ -1265,7 +1278,7 @@ func getUserEmailsByNames(e Engine, names []string) []string { if err != nil { continue } - if u.IsMailable() { + if u.IsMailable() && u.EnabledEmailNotifications() { mails = append(mails, u.Email) } } diff --git a/routers/user/setting/account.go b/routers/user/setting/account.go index 3fd6a8db5ee0a..4795e0dc2020e 100644 --- a/routers/user/setting/account.go +++ b/routers/user/setting/account.go @@ -81,6 +81,12 @@ func EmailPost(ctx *context.Context, form auth.AddEmailForm) { ctx.Redirect(setting.AppSubURL + "/user/settings/account") return } + // Set Email Notification Preference + if ctx.Query("_method") == "NOTIFICATION" { + ctx.User.SetEmailNotifications(ctx.QueryBool("enable")) + ctx.Redirect(setting.AppSubURL + "/user/settings/account") + return + } if ctx.HasError() { loadAccountData(ctx) From 3a3e1156aec4f02b01c4bb418c0fe8b293c8e2a4 Mon Sep 17 00:00:00 2001 From: Gary Kim Date: Thu, 15 Aug 2019 23:54:43 +0800 Subject: [PATCH 02/13] Add UI and complete user email notification enable This commit completes the functionality to allow users to disable their own email notifications. Signed-off-by: Gary Kim --- models/migrations/v93.go | 2 +- models/user.go | 3 ++- options/locale/locale_en-US.ini | 5 +++++ routers/user/setting/account.go | 2 ++ templates/user/settings/account.tmpl | 13 +++++++++++++ 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/models/migrations/v93.go b/models/migrations/v93.go index 679b4d0da3727..60e1f90fba63c 100644 --- a/models/migrations/v93.go +++ b/models/migrations/v93.go @@ -9,7 +9,7 @@ import "github.com/go-xorm/xorm" func addEmailNotificationEnabledToUser(x *xorm.Engine) error { // Issue see models/user.go type User struct { - EmailNotificationsEnabled bool `xorm:"NOT NULL DEFAULT true"` + EmailNotificationsEnabled bool `xorm:"DEFAULT true"` } return x.Sync2(new(User)) diff --git a/models/user.go b/models/user.go index 3678ac9e9f152..ed647d5ceb5c3 100644 --- a/models/user.go +++ b/models/user.go @@ -89,7 +89,7 @@ type User struct { // Email is the primary email address (to be used for communication) Email string `xorm:"NOT NULL"` KeepEmailPrivate bool - EmailNotificationsEnabled bool `xorm:"NOT NULL DEFAULT true"` + EmailNotificationsEnabled bool `xorm:"DEFAULT true"` Passwd string `xorm:"NOT NULL"` PasswdHashAlgo string `xorm:"NOT NULL DEFAULT 'pbkdf2'"` @@ -730,6 +730,7 @@ func (u *User) EnabledEmailNotifications() bool { // would like to receive notifications by email func (u *User) SetEmailNotifications(set bool) { u.EmailNotificationsEnabled = set + _ = UpdateUser(u) } func isUserExist(e Engine, uid int64, name string) (bool, error) { diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 0df7cdf7e0d09..caf6be558550a 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -557,6 +557,9 @@ confirm_delete_account = Confirm Deletion delete_account_title = Delete User Account delete_account_desc = Are you sure you want to permanently delete this user account? +email_notifications.enable = Enable Email Notifications +email_notifications.disable = Disable Email Notifications + [repo] owner = Owner repo_name = Repository Name @@ -1126,6 +1129,8 @@ settings.basic_settings = Basic Settings settings.mirror_settings = Mirror Settings settings.sync_mirror = Synchronize Now settings.mirror_sync_in_progress = Mirror synchronization is in progress. Check back in a minute. +settings.email_notifications.enable = Enable Email Notifications +settings.email_notifications.disable = Disable Email Notifications settings.site = Website settings.update_settings = Update Settings settings.advanced_settings = Advanced Settings diff --git a/routers/user/setting/account.go b/routers/user/setting/account.go index 4795e0dc2020e..60bc289b2ad26 100644 --- a/routers/user/setting/account.go +++ b/routers/user/setting/account.go @@ -23,6 +23,7 @@ func Account(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsAccount"] = true ctx.Data["Email"] = ctx.User.Email + ctx.Data["NotificationsEnabled"] = ctx.User.EnabledEmailNotifications() loadAccountData(ctx) @@ -84,6 +85,7 @@ func EmailPost(ctx *context.Context, form auth.AddEmailForm) { // Set Email Notification Preference if ctx.Query("_method") == "NOTIFICATION" { ctx.User.SetEmailNotifications(ctx.QueryBool("enable")) + log.Trace("Email notifications enabled made %s: %s", ctx.QueryBool("enable"), ctx.User.Name) ctx.Redirect(setting.AppSubURL + "/user/settings/account") return } diff --git a/templates/user/settings/account.tmpl b/templates/user/settings/account.tmpl index 778103e44de32..2729b96f6decc 100644 --- a/templates/user/settings/account.tmpl +++ b/templates/user/settings/account.tmpl @@ -44,6 +44,19 @@