diff options
Diffstat (limited to 'internal/db')
-rw-r--r-- | internal/db/issue_mail.go | 16 | ||||
-rw-r--r-- | internal/db/user.go | 24 | ||||
-rw-r--r-- | internal/db/users.go | 18 | ||||
-rw-r--r-- | internal/db/users_test.go | 17 |
4 files changed, 42 insertions, 33 deletions
diff --git a/internal/db/issue_mail.go b/internal/db/issue_mail.go index d529ecdd..f094cf98 100644 --- a/internal/db/issue_mail.go +++ b/internal/db/issue_mail.go @@ -8,6 +8,7 @@ import ( "context" "fmt" + "github.com/pkg/errors" "github.com/unknwon/com" log "unknwon.dev/clog/v2" @@ -99,6 +100,8 @@ func NewMailerIssue(issue *Issue) email.Issue { // 1. Repository watchers, users who participated in comments and the assignee. // 2. Users who are not in 1. but get mentioned in current issue/comment. func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string) error { + ctx := context.TODO() + if !conf.User.EnableEmailNotification { return nil } @@ -125,7 +128,7 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string) continue } - to, err := Users.GetByID(context.TODO(), watchers[i].UserID) + to, err := Users.GetByID(ctx, watchers[i].UserID) if err != nil { return fmt.Errorf("GetUserByID [%d]: %v", watchers[i].UserID, err) } @@ -156,15 +159,20 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string) // Mail mentioned people and exclude watchers. names = append(names, doer.Name) - tos = make([]string, 0, len(mentions)) // list of user names. + toUsernames := make([]string, 0, len(mentions)) // list of user names. for i := range mentions { if com.IsSliceContainsStr(names, mentions[i]) { continue } - tos = append(tos, mentions[i]) + toUsernames = append(toUsernames, mentions[i]) + } + + tos, err = Users.GetMailableEmailsByUsernames(ctx, toUsernames) + if err != nil { + return errors.Wrap(err, "get mailable emails by usernames") } - email.SendIssueMentionMail(NewMailerIssue(issue), NewMailerRepo(issue.Repo), NewMailerUser(doer), GetUserEmailsByNames(tos)) + email.SendIssueMentionMail(NewMailerIssue(issue), NewMailerRepo(issue.Repo), NewMailerUser(doer), tos) return nil } diff --git a/internal/db/user.go b/internal/db/user.go index 1048a2eb..17e0f66b 100644 --- a/internal/db/user.go +++ b/internal/db/user.go @@ -200,36 +200,12 @@ func DeleteInactivateUsers() (err error) { return err } -// GetUserEmailsByNames returns a list of e-mails corresponds to names. -func GetUserEmailsByNames(names []string) []string { - mails := make([]string, 0, len(names)) - for _, name := range names { - u, err := Users.GetByUsername(context.TODO(), name) - if err != nil { - continue - } - if u.IsMailable() { - mails = append(mails, u.Email) - } - } - return mails -} - // UserCommit represents a commit with validation of user. type UserCommit struct { User *User *git.Commit } -// ValidateCommitWithEmail checks if author's e-mail of commit is corresponding to a user. -func ValidateCommitWithEmail(c *git.Commit) *User { - u, err := Users.GetByEmail(context.TODO(), c.Author.Email) - if err != nil { - return nil - } - return u -} - // ValidateCommitsWithEmails checks if authors' e-mails of commits are corresponding to users. func ValidateCommitsWithEmails(oldCommits []*git.Commit) []*UserCommit { emails := make(map[string]*User) diff --git a/internal/db/users.go b/internal/db/users.go index 468bb3ac..7e986a47 100644 --- a/internal/db/users.go +++ b/internal/db/users.go @@ -73,6 +73,10 @@ type UsersStore interface { // GetByKeyID returns the owner of given public key ID. It returns // ErrUserNotExist when not found. GetByKeyID(ctx context.Context, keyID int64) (*User, error) + // GetMailableEmailsByUsernames returns a list of verified primary email + // addresses (where email notifications are sent to) of users with given list of + // usernames. Non-existing usernames are ignored. + GetMailableEmailsByUsernames(ctx context.Context, usernames []string) ([]string, error) // HasForkedRepository returns true if the user has forked given repository. HasForkedRepository(ctx context.Context, userID, repoID int64) bool // IsUsernameUsed returns true if the given username has been used other than @@ -509,6 +513,15 @@ func (db *users) GetByKeyID(ctx context.Context, keyID int64) (*User, error) { return user, nil } +func (db *users) GetMailableEmailsByUsernames(ctx context.Context, usernames []string) ([]string, error) { + emails := make([]string, 0, len(usernames)) + return emails, db.WithContext(ctx). + Model(&User{}). + Select("email"). + Where("lower_name IN (?) AND is_active = ?", usernames, true). + Find(&emails).Error +} + func (db *users) HasForkedRepository(ctx context.Context, userID, repoID int64) bool { var count int64 db.WithContext(ctx).Model(new(Repository)).Where("owner_id = ? AND fork_id = ?", userID, repoID).Count(&count) @@ -816,11 +829,6 @@ func (u *User) IsOrganization() bool { return u.Type == UserTypeOrganization } -// IsMailable returns true if the user is eligible to receive emails. -func (u *User) IsMailable() bool { - return u.IsActive -} - // APIFormat returns the API format of a user. func (u *User) APIFormat() *api.User { return &api.User{ diff --git a/internal/db/users_test.go b/internal/db/users_test.go index c302d2e8..10f30b81 100644 --- a/internal/db/users_test.go +++ b/internal/db/users_test.go @@ -100,6 +100,7 @@ func TestUsers(t *testing.T) { {"GetByID", usersGetByID}, {"GetByUsername", usersGetByUsername}, {"GetByKeyID", usersGetByKeyID}, + {"GetMailableEmailsByUsernames", usersGetMailableEmailsByUsernames}, {"HasForkedRepository", usersHasForkedRepository}, {"IsUsernameUsed", usersIsUsernameUsed}, {"List", usersList}, @@ -582,6 +583,22 @@ func usersGetByKeyID(t *testing.T, db *users) { assert.Equal(t, wantErr, err) } +func usersGetMailableEmailsByUsernames(t *testing.T, db *users) { + ctx := context.Background() + + alice, err := db.Create(ctx, "alice", "alice@exmaple.com", CreateUserOptions{}) + require.NoError(t, err) + bob, err := db.Create(ctx, "bob", "bob@exmaple.com", CreateUserOptions{Activated: true}) + require.NoError(t, err) + _, err = db.Create(ctx, "cindy", "cindy@exmaple.com", CreateUserOptions{Activated: true}) + require.NoError(t, err) + + got, err := db.GetMailableEmailsByUsernames(ctx, []string{alice.Name, bob.Name, "404"}) + require.NoError(t, err) + want := []string{bob.Email} + assert.Equal(t, want, got) +} + func usersHasForkedRepository(t *testing.T, db *users) { ctx := context.Background() |