diff options
author | David Svantesson <davidsvantesson@gmail.com> | 2019-10-25 16:46:37 +0200 |
---|---|---|
committer | Lunny Xiao <xiaolunwen@gmail.com> | 2019-10-25 22:46:37 +0800 |
commit | 6aa3f8bc29cb1ed3a1b165cbf526079a751c8c71 (patch) | |
tree | d18aafe7855f9d21fb0d8d7104e7ac7b4aba72b2 /routers | |
parent | c34e58fc008d53a5ec92cadadab2b13fb4e0ae94 (diff) | |
download | gitea-6aa3f8bc29cb1ed3a1b165cbf526079a751c8c71.tar.gz gitea-6aa3f8bc29cb1ed3a1b165cbf526079a751c8c71.zip |
Mail assignee when issue/pull request is assigned (#8546)
* Send email to assigned user
* Only send mail if enabled
* Mail also when assigned through API
* Need to refactor functions from models to issue service
* Refer to issue index rather than ID
* Disable email notifications completly at initalization if global disable
* Check of user enbled mail shall be in mail notification function only
* Initialize notifications from routers init function.
* Use the assigned comment when sending assigned mail
* Refactor so that assignees always added as separate step when new issue/pr.
* Check error from AddAssignees
* Check if user can be assiged to issue or pull request
* Missing return
* Refactor of CanBeAssigned check.
CanBeAssigned shall have same check as UI.
* Clarify function names (toggle rather than update/change), and clean up.
* Fix review comments.
* Flash error if assignees was not added when creating issue/pr
* Generate error if assignee users doesn't exist
Diffstat (limited to 'routers')
-rw-r--r-- | routers/api/v1/repo/issue.go | 30 | ||||
-rw-r--r-- | routers/api/v1/repo/pull.go | 30 | ||||
-rw-r--r-- | routers/init.go | 2 | ||||
-rw-r--r-- | routers/repo/issue.go | 44 | ||||
-rw-r--r-- | routers/repo/pull.go | 8 |
5 files changed, 97 insertions, 17 deletions
diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index aab167bc68..9529e09b29 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -213,12 +213,31 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) { } return } + + // Check if the passed assignees is assignable + for _, aID := range assigneeIDs { + assignee, err := models.GetUserByID(aID) + if err != nil { + ctx.Error(500, "GetUserByID", err) + return + } + + valid, err := models.CanBeAssigned(assignee, ctx.Repo.Repository, false) + if err != nil { + ctx.Error(500, "canBeAssigned", err) + return + } + if !valid { + ctx.Error(422, "canBeAssigned", models.ErrUserDoesNotHaveAccessToRepo{UserID: aID, RepoName: ctx.Repo.Repository.Name}) + return + } + } } else { // setting labels is not allowed if user is not a writer form.Labels = make([]int64, 0) } - if err := issue_service.NewIssue(ctx.Repo.Repository, issue, form.Labels, assigneeIDs, nil); err != nil { + if err := issue_service.NewIssue(ctx.Repo.Repository, issue, form.Labels, nil); err != nil { if models.IsErrUserDoesNotHaveAccessToRepo(err) { ctx.Error(400, "UserDoesNotHaveAccessToRepo", err) return @@ -227,6 +246,11 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) { return } + if err := issue_service.AddAssignees(issue, ctx.User, assigneeIDs); err != nil { + ctx.ServerError("AddAssignees", err) + return + } + notification.NotifyNewIssue(issue) if form.Closed { @@ -336,9 +360,9 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { oneAssignee = *form.Assignee } - err = models.UpdateAPIAssignee(issue, oneAssignee, form.Assignees, ctx.User) + err = issue_service.UpdateAssignees(issue, oneAssignee, form.Assignees, ctx.User) if err != nil { - ctx.Error(500, "UpdateAPIAssignee", err) + ctx.Error(500, "UpdateAssignees", err) return } } diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 16ddd10c60..6b20844c51 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/modules/notification" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" + issue_service "code.gitea.io/gitea/services/issue" milestone_service "code.gitea.io/gitea/services/milestone" pull_service "code.gitea.io/gitea/services/pull" ) @@ -285,8 +286,26 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption } return } + // Check if the passed assignees is assignable + for _, aID := range assigneeIDs { + assignee, err := models.GetUserByID(aID) + if err != nil { + ctx.Error(500, "GetUserByID", err) + return + } - if err := pull_service.NewPullRequest(repo, prIssue, labelIDs, []string{}, pr, patch, assigneeIDs); err != nil { + valid, err := models.CanBeAssigned(assignee, repo, true) + if err != nil { + ctx.Error(500, "canBeAssigned", err) + return + } + if !valid { + ctx.Error(422, "canBeAssigned", models.ErrUserDoesNotHaveAccessToRepo{UserID: aID, RepoName: repo.Name}) + return + } + } + + if err := pull_service.NewPullRequest(repo, prIssue, labelIDs, []string{}, pr, patch); err != nil { if models.IsErrUserDoesNotHaveAccessToRepo(err) { ctx.Error(400, "UserDoesNotHaveAccessToRepo", err) return @@ -298,6 +317,11 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption return } + if err := issue_service.AddAssignees(prIssue, ctx.User, assigneeIDs); err != nil { + ctx.ServerError("AddAssignees", err) + return + } + notification.NotifyNewPullRequest(pr) log.Trace("Pull request created: %d/%d", repo.ID, prIssue.ID) @@ -387,12 +411,12 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { // Send an empty array ([]) to clear all assignees from the Issue. if ctx.Repo.CanWrite(models.UnitTypePullRequests) && (form.Assignees != nil || len(form.Assignee) > 0) { - err = models.UpdateAPIAssignee(issue, form.Assignee, form.Assignees, ctx.User) + err = issue_service.UpdateAssignees(issue, form.Assignee, form.Assignees, ctx.User) if err != nil { if models.IsErrUserNotExist(err) { ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err)) } else { - ctx.Error(500, "UpdateAPIAssignee", err) + ctx.Error(500, "UpdateAssignees", err) } return } diff --git a/routers/init.go b/routers/init.go index e4e880dbbb..bdd978d717 100644 --- a/routers/init.go +++ b/routers/init.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/external" + "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/ssh" "code.gitea.io/gitea/modules/task" @@ -44,6 +45,7 @@ func NewServices() { setting.NewServices() mailer.NewContext() _ = cache.NewContext() + notification.NewContext() } // In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology diff --git a/routers/repo/issue.go b/routers/repo/issue.go index dee2c6e698..94c39ae224 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -503,21 +503,21 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm, isPull b return nil, nil, 0 } - // Check if the passed assignees actually exists and has write access to the repo + // Check if the passed assignees actually exists and is assignable for _, aID := range assigneeIDs { - user, err := models.GetUserByID(aID) + assignee, err := models.GetUserByID(aID) if err != nil { ctx.ServerError("GetUserByID", err) return nil, nil, 0 } - perm, err := models.GetUserRepoPermission(repo, user) + valid, err := models.CanBeAssigned(assignee, repo, isPull) if err != nil { - ctx.ServerError("GetUserRepoPermission", err) + ctx.ServerError("canBeAssigned", err) return nil, nil, 0 } - if !perm.CanWriteIssuesOrPulls(isPull) { - ctx.ServerError("CanWriteIssuesOrPulls", fmt.Errorf("No permission for %s", user.Name)) + if !valid { + ctx.ServerError("canBeAssigned", models.ErrUserDoesNotHaveAccessToRepo{UserID: aID, RepoName: repo.Name}) return nil, nil, 0 } } @@ -574,7 +574,7 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) { Content: form.Content, Ref: form.Ref, } - if err := issue_service.NewIssue(repo, issue, labelIDs, assigneeIDs, attachments); err != nil { + if err := issue_service.NewIssue(repo, issue, labelIDs, attachments); err != nil { if models.IsErrUserDoesNotHaveAccessToRepo(err) { ctx.Error(400, "UserDoesNotHaveAccessToRepo", err.Error()) return @@ -583,6 +583,11 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) { return } + if err := issue_service.AddAssignees(issue, ctx.User, assigneeIDs); err != nil { + log.Error("AddAssignees: %v", err) + ctx.Flash.Error(ctx.Tr("issues.assignee.error")) + } + notification.NotifyNewIssue(issue) log.Trace("Issue created: %d/%d", repo.ID, issue.ID) @@ -1112,7 +1117,7 @@ func UpdateIssueMilestone(ctx *context.Context) { }) } -// UpdateIssueAssignee change issue's assignee +// UpdateIssueAssignee change issue's or pull's assignee func UpdateIssueAssignee(ctx *context.Context) { issues := getActionIssues(ctx) if ctx.Written() { @@ -1130,10 +1135,29 @@ func UpdateIssueAssignee(ctx *context.Context) { return } default: - if err := issue.ChangeAssignee(ctx.User, assigneeID); err != nil { - ctx.ServerError("ChangeAssignee", err) + assignee, err := models.GetUserByID(assigneeID) + if err != nil { + ctx.ServerError("GetUserByID", err) + return + } + + valid, err := models.CanBeAssigned(assignee, issue.Repo, issue.IsPull) + if err != nil { + ctx.ServerError("canBeAssigned", err) return } + if !valid { + ctx.ServerError("canBeAssigned", models.ErrUserDoesNotHaveAccessToRepo{UserID: assigneeID, RepoName: issue.Repo.Name}) + return + } + + removed, comment, err := issue.ToggleAssignee(ctx.User, assigneeID) + if err != nil { + ctx.ServerError("ToggleAssignee", err) + return + } + + notification.NotifyIssueChangeAssignee(ctx.User, issue, assignee, removed, comment) } } ctx.JSON(200, map[string]interface{}{ diff --git a/routers/repo/pull.go b/routers/repo/pull.go index 4b73571e66..23d97e7b7e 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" + issue_service "code.gitea.io/gitea/services/issue" pull_service "code.gitea.io/gitea/services/pull" "github.com/unknwon/com" @@ -770,7 +771,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) // FIXME: check error in the case two people send pull request at almost same time, give nice error prompt // instead of 500. - if err := pull_service.NewPullRequest(repo, pullIssue, labelIDs, attachments, pullRequest, patch, assigneeIDs); err != nil { + if err := pull_service.NewPullRequest(repo, pullIssue, labelIDs, attachments, pullRequest, patch); err != nil { if models.IsErrUserDoesNotHaveAccessToRepo(err) { ctx.Error(400, "UserDoesNotHaveAccessToRepo", err.Error()) return @@ -782,6 +783,11 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) return } + if err := issue_service.AddAssignees(pullIssue, ctx.User, assigneeIDs); err != nil { + log.Error("AddAssignees: %v", err) + ctx.Flash.Error(ctx.Tr("issues.assignee.error")) + } + notification.NotifyNewPullRequest(pullRequest) log.Trace("Pull request created: %d/%d", repo.ID, pullIssue.ID) |