aboutsummaryrefslogtreecommitdiff
path: root/internal/db
diff options
context:
space:
mode:
Diffstat (limited to 'internal/db')
-rw-r--r--internal/db/issue_mail.go16
-rw-r--r--internal/db/user.go24
-rw-r--r--internal/db/users.go18
-rw-r--r--internal/db/users_test.go17
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()