Skip to content

Commit 5a438ee

Browse files
authored
Move all mail related codes from models to services/mailer (#7200)
* move all mail related codes from models to modules/mailer * fix lint * use DBContext instead Engine * use WithContext not WithEngine * Use DBContext instead of Engine * don't use defer when sess.Close() * move DBContext to context.go and add some methods * move mailer from modules/ to services * fix lint * fix tests * fix fmt * add gitea copyright * fix tests * don't expose db functions * make code clear * add DefaultDBContext * fix build * fix bug
1 parent 730065a commit 5a438ee

22 files changed

+253
-134
lines changed

models/context.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package models
6+
7+
// DBContext represents a db context
8+
type DBContext struct {
9+
e Engine
10+
}
11+
12+
// DefaultDBContext represents a DBContext with default Engine
13+
func DefaultDBContext() DBContext {
14+
return DBContext{x}
15+
}
16+
17+
// Committer represents an interface to Commit or Close the dbcontext
18+
type Committer interface {
19+
Commit() error
20+
Close()
21+
}
22+
23+
// TxDBContext represents a transaction DBContext
24+
func TxDBContext() (DBContext, Committer, error) {
25+
sess := x.NewSession()
26+
if err := sess.Begin(); err != nil {
27+
sess.Close()
28+
return DBContext{}, nil, err
29+
}
30+
31+
return DBContext{sess}, sess, nil
32+
}
33+
34+
// WithContext represents executing database operations
35+
func WithContext(f func(ctx DBContext) error) error {
36+
return f(DBContext{x})
37+
}
38+
39+
// WithTx represents executing database operations on a trasaction
40+
func WithTx(f func(ctx DBContext) error) error {
41+
sess := x.NewSession()
42+
if err := sess.Begin(); err != nil {
43+
sess.Close()
44+
return err
45+
}
46+
47+
if err := f(DBContext{sess}); err != nil {
48+
sess.Close()
49+
return err
50+
}
51+
52+
err := sess.Commit()
53+
sess.Close()
54+
return err
55+
}

models/error.go

+15
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,21 @@ import (
1111
"code.gitea.io/gitea/modules/git"
1212
)
1313

14+
// ErrNotExist represents a non-exist error.
15+
type ErrNotExist struct {
16+
ID int64
17+
}
18+
19+
// IsErrNotExist checks if an error is an ErrNotExist
20+
func IsErrNotExist(err error) bool {
21+
_, ok := err.(ErrNotExist)
22+
return ok
23+
}
24+
25+
func (err ErrNotExist) Error() string {
26+
return fmt.Sprintf("record does not exist [id: %d]", err.ID)
27+
}
28+
1429
// ErrNameReserved represents a "reserved name" error.
1530
type ErrNameReserved struct {
1631
Name string

models/issue.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -1503,7 +1503,7 @@ func getParticipantsByIssueID(e Engine, issueID int64) ([]*User, error) {
15031503

15041504
// UpdateIssueMentions extracts mentioned people from content and
15051505
// updates issue-user relations for them.
1506-
func UpdateIssueMentions(e Engine, issueID int64, mentions []string) error {
1506+
func UpdateIssueMentions(ctx DBContext, issueID int64, mentions []string) error {
15071507
if len(mentions) == 0 {
15081508
return nil
15091509
}
@@ -1513,7 +1513,7 @@ func UpdateIssueMentions(e Engine, issueID int64, mentions []string) error {
15131513
}
15141514
users := make([]*User, 0, len(mentions))
15151515

1516-
if err := e.In("lower_name", mentions).Asc("lower_name").Find(&users); err != nil {
1516+
if err := ctx.e.In("lower_name", mentions).Asc("lower_name").Find(&users); err != nil {
15171517
return fmt.Errorf("find mentioned users: %v", err)
15181518
}
15191519

@@ -1525,7 +1525,7 @@ func UpdateIssueMentions(e Engine, issueID int64, mentions []string) error {
15251525
}
15261526

15271527
memberIDs := make([]int64, 0, user.NumMembers)
1528-
orgUsers, err := getOrgUsersByOrgID(e, user.ID)
1528+
orgUsers, err := getOrgUsersByOrgID(ctx.e, user.ID)
15291529
if err != nil {
15301530
return fmt.Errorf("GetOrgUsersByOrgID [%d]: %v", user.ID, err)
15311531
}
@@ -1537,7 +1537,7 @@ func UpdateIssueMentions(e Engine, issueID int64, mentions []string) error {
15371537
ids = append(ids, memberIDs...)
15381538
}
15391539

1540-
if err := UpdateIssueUsersByMentions(e, issueID, ids); err != nil {
1540+
if err := UpdateIssueUsersByMentions(ctx, issueID, ids); err != nil {
15411541
return fmt.Errorf("UpdateIssueUsersByMentions: %v", err)
15421542
}
15431543

models/issue_comment.go

-35
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212

1313
"code.gitea.io/gitea/modules/git"
1414
"code.gitea.io/gitea/modules/log"
15-
"code.gitea.io/gitea/modules/markup"
1615
"code.gitea.io/gitea/modules/markup/markdown"
1716
api "code.gitea.io/gitea/modules/structs"
1817
"code.gitea.io/gitea/modules/timeutil"
@@ -395,40 +394,6 @@ func (c *Comment) LoadDepIssueDetails() (err error) {
395394
return err
396395
}
397396

398-
// MailParticipants sends new comment emails to repository watchers
399-
// and mentioned people.
400-
func (c *Comment) MailParticipants(opType ActionType, issue *Issue) (err error) {
401-
return c.mailParticipants(x, opType, issue)
402-
}
403-
404-
func (c *Comment) mailParticipants(e Engine, opType ActionType, issue *Issue) (err error) {
405-
mentions := markup.FindAllMentions(c.Content)
406-
if err = UpdateIssueMentions(e, c.IssueID, mentions); err != nil {
407-
return fmt.Errorf("UpdateIssueMentions [%d]: %v", c.IssueID, err)
408-
}
409-
410-
if len(c.Content) > 0 {
411-
if err = mailIssueCommentToParticipants(e, issue, c.Poster, c.Content, c, mentions); err != nil {
412-
log.Error("mailIssueCommentToParticipants: %v", err)
413-
}
414-
}
415-
416-
switch opType {
417-
case ActionCloseIssue:
418-
ct := fmt.Sprintf("Closed #%d.", issue.Index)
419-
if err = mailIssueCommentToParticipants(e, issue, c.Poster, ct, c, mentions); err != nil {
420-
log.Error("mailIssueCommentToParticipants: %v", err)
421-
}
422-
case ActionReopenIssue:
423-
ct := fmt.Sprintf("Reopened #%d.", issue.Index)
424-
if err = mailIssueCommentToParticipants(e, issue, c.Poster, ct, c, mentions); err != nil {
425-
log.Error("mailIssueCommentToParticipants: %v", err)
426-
}
427-
}
428-
429-
return nil
430-
}
431-
432397
func (c *Comment) loadReactions(e Engine) (err error) {
433398
if c.Reactions != nil {
434399
return nil

models/issue_user.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,22 +94,22 @@ func UpdateIssueUserByRead(uid, issueID int64) error {
9494
}
9595

9696
// UpdateIssueUsersByMentions updates issue-user pairs by mentioning.
97-
func UpdateIssueUsersByMentions(e Engine, issueID int64, uids []int64) error {
97+
func UpdateIssueUsersByMentions(ctx DBContext, issueID int64, uids []int64) error {
9898
for _, uid := range uids {
9999
iu := &IssueUser{
100100
UID: uid,
101101
IssueID: issueID,
102102
}
103-
has, err := e.Get(iu)
103+
has, err := ctx.e.Get(iu)
104104
if err != nil {
105105
return err
106106
}
107107

108108
iu.IsMentioned = true
109109
if has {
110-
_, err = e.ID(iu.ID).Cols("is_mentioned").Update(iu)
110+
_, err = ctx.e.ID(iu.ID).Cols("is_mentioned").Update(iu)
111111
} else {
112-
_, err = e.Insert(iu)
112+
_, err = ctx.e.Insert(iu)
113113
}
114114
if err != nil {
115115
return err

models/issue_user_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func TestUpdateIssueUsersByMentions(t *testing.T) {
5050
issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
5151

5252
uids := []int64{2, 5}
53-
assert.NoError(t, UpdateIssueUsersByMentions(x, issue.ID, uids))
53+
assert.NoError(t, UpdateIssueUsersByMentions(DefaultDBContext(), issue.ID, uids))
5454
for _, uid := range uids {
5555
AssertExistsAndLoadBean(t, &IssueUser{IssueID: issue.ID, UID: uid}, "is_mentioned=1")
5656
}

modules/notification/mail/mail.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"code.gitea.io/gitea/models"
99
"code.gitea.io/gitea/modules/log"
1010
"code.gitea.io/gitea/modules/notification/base"
11+
"code.gitea.io/gitea/services/mailer"
1112
)
1213

1314
type mailNotifier struct {
@@ -36,13 +37,13 @@ func (m *mailNotifier) NotifyCreateIssueComment(doer *models.User, repo *models.
3637
act = models.ActionCommentIssue
3738
}
3839

39-
if err := comment.MailParticipants(act, issue); err != nil {
40+
if err := mailer.MailParticipantsComment(comment, act, issue); err != nil {
4041
log.Error("MailParticipants: %v", err)
4142
}
4243
}
4344

4445
func (m *mailNotifier) NotifyNewIssue(issue *models.Issue) {
45-
if err := issue.MailParticipants(issue.Poster, models.ActionCreateIssue); err != nil {
46+
if err := mailer.MailParticipants(issue, issue.Poster, models.ActionCreateIssue); err != nil {
4647
log.Error("MailParticipants: %v", err)
4748
}
4849
}
@@ -63,13 +64,13 @@ func (m *mailNotifier) NotifyIssueChangeStatus(doer *models.User, issue *models.
6364
}
6465
}
6566

66-
if err := issue.MailParticipants(doer, actionType); err != nil {
67+
if err := mailer.MailParticipants(issue, doer, actionType); err != nil {
6768
log.Error("MailParticipants: %v", err)
6869
}
6970
}
7071

7172
func (m *mailNotifier) NotifyNewPullRequest(pr *models.PullRequest) {
72-
if err := pr.Issue.MailParticipants(pr.Issue.Poster, models.ActionCreatePullRequest); err != nil {
73+
if err := mailer.MailParticipants(pr.Issue, pr.Issue.Poster, models.ActionCreatePullRequest); err != nil {
7374
log.Error("MailParticipants: %v", err)
7475
}
7576
}
@@ -83,7 +84,7 @@ func (m *mailNotifier) NotifyPullRequestReview(pr *models.PullRequest, r *models
8384
} else if comment.Type == models.CommentTypeComment {
8485
act = models.ActionCommentIssue
8586
}
86-
if err := comment.MailParticipants(act, pr.Issue); err != nil {
87+
if err := mailer.MailParticipantsComment(comment, act, pr.Issue); err != nil {
8788
log.Error("MailParticipants: %v", err)
8889
}
8990
}

routers/admin/admin.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"code.gitea.io/gitea/modules/process"
2323
"code.gitea.io/gitea/modules/setting"
2424
"code.gitea.io/gitea/modules/timeutil"
25+
"code.gitea.io/gitea/services/mailer"
2526

2627
"gitea.com/macaron/macaron"
2728
"github.com/unknwon/com"
@@ -197,7 +198,7 @@ func Dashboard(ctx *context.Context) {
197198
func SendTestMail(ctx *context.Context) {
198199
email := ctx.Query("email")
199200
// Send a test email to the user's email address and redirect back to Config
200-
if err := models.SendTestMail(email); err != nil {
201+
if err := mailer.SendTestMail(email); err != nil {
201202
ctx.Flash.Error(ctx.Tr("admin.config.test_mail_failed", email, err))
202203
} else {
203204
ctx.Flash.Info(ctx.Tr("admin.config.test_mail_sent", email))

routers/admin/users.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"code.gitea.io/gitea/modules/log"
1515
"code.gitea.io/gitea/modules/setting"
1616
"code.gitea.io/gitea/routers"
17+
"code.gitea.io/gitea/services/mailer"
1718

1819
"github.com/unknwon/com"
1920
)
@@ -116,8 +117,8 @@ func NewUserPost(ctx *context.Context, form auth.AdminCreateUserForm) {
116117
log.Trace("Account created by admin (%s): %s", ctx.User.Name, u.Name)
117118

118119
// Send email notification.
119-
if form.SendNotify && setting.MailService != nil {
120-
models.SendRegisterNotifyMail(ctx.Context, u)
120+
if form.SendNotify {
121+
mailer.SendRegisterNotifyMail(ctx.Locale, u)
121122
}
122123

123124
ctx.Flash.Success(ctx.Tr("admin.users.new_success", u.Name))

routers/api/v1/admin/user.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import (
99
"code.gitea.io/gitea/models"
1010
"code.gitea.io/gitea/modules/context"
1111
"code.gitea.io/gitea/modules/log"
12-
"code.gitea.io/gitea/modules/setting"
1312
api "code.gitea.io/gitea/modules/structs"
1413
"code.gitea.io/gitea/routers/api/v1/convert"
1514
"code.gitea.io/gitea/routers/api/v1/user"
15+
"code.gitea.io/gitea/services/mailer"
1616
)
1717

1818
func parseLoginSource(ctx *context.APIContext, u *models.User, sourceID int64, loginName string) {
@@ -88,8 +88,8 @@ func CreateUser(ctx *context.APIContext, form api.CreateUserOption) {
8888
log.Trace("Account created by admin (%s): %s", ctx.User.Name, u.Name)
8989

9090
// Send email notification.
91-
if form.SendNotify && setting.MailService != nil {
92-
models.SendRegisterNotifyMail(ctx.Context.Context, u)
91+
if form.SendNotify {
92+
mailer.SendRegisterNotifyMail(ctx.Locale, u)
9393
}
9494
ctx.JSON(201, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
9595
}

routers/init.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ import (
1616
"code.gitea.io/gitea/modules/highlight"
1717
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
1818
"code.gitea.io/gitea/modules/log"
19-
"code.gitea.io/gitea/modules/mailer"
2019
"code.gitea.io/gitea/modules/markup"
2120
"code.gitea.io/gitea/modules/markup/external"
2221
"code.gitea.io/gitea/modules/setting"
2322
"code.gitea.io/gitea/modules/ssh"
23+
"code.gitea.io/gitea/services/mailer"
2424

2525
"gitea.com/macaron/macaron"
2626
)

routers/repo/setting.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"code.gitea.io/gitea/modules/timeutil"
2525
"code.gitea.io/gitea/modules/validation"
2626
"code.gitea.io/gitea/routers/utils"
27+
"code.gitea.io/gitea/services/mailer"
2728

2829
"github.com/unknwon/com"
2930
"mvdan.cc/xurls/v2"
@@ -549,7 +550,7 @@ func CollaborationPost(ctx *context.Context) {
549550
}
550551

551552
if setting.Service.EnableNotifyMail {
552-
models.SendCollaboratorMail(u, ctx.User, ctx.Repo.Repository)
553+
mailer.SendCollaboratorMail(u, ctx.User, ctx.Repo.Repository)
553554
}
554555

555556
ctx.Flash.Success(ctx.Tr("repo.settings.add_collaborator_success"))

routers/routes/routes.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"code.gitea.io/gitea/routers/repo"
3535
"code.gitea.io/gitea/routers/user"
3636
userSetting "code.gitea.io/gitea/routers/user/setting"
37+
"code.gitea.io/gitea/services/mailer"
3738

3839
// to registers all internal adapters
3940
_ "code.gitea.io/gitea/modules/session"
@@ -166,7 +167,7 @@ func NewMacaron() *macaron.Macaron {
166167
))
167168

168169
m.Use(templates.HTMLRenderer())
169-
models.InitMailRender(templates.Mailer())
170+
mailer.InitMailRender(templates.Mailer())
170171

171172
localeNames, err := options.Dir("locale")
172173

0 commit comments

Comments
 (0)