summaryrefslogtreecommitdiffstats
path: root/models/issue_assignees.go
diff options
context:
space:
mode:
authorDavid Svantesson <davidsvantesson@gmail.com>2019-10-25 16:46:37 +0200
committerLunny Xiao <xiaolunwen@gmail.com>2019-10-25 22:46:37 +0800
commit6aa3f8bc29cb1ed3a1b165cbf526079a751c8c71 (patch)
treed18aafe7855f9d21fb0d8d7104e7ac7b4aba72b2 /models/issue_assignees.go
parentc34e58fc008d53a5ec92cadadab2b13fb4e0ae94 (diff)
downloadgitea-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 'models/issue_assignees.go')
-rw-r--r--models/issue_assignees.go138
1 files changed, 54 insertions, 84 deletions
diff --git a/models/issue_assignees.go b/models/issue_assignees.go
index 00ee498860..ed0576b38b 100644
--- a/models/issue_assignees.go
+++ b/models/issue_assignees.go
@@ -58,8 +58,11 @@ func getAssigneesByIssue(e Engine, issue *Issue) (assignees []*User, err error)
// IsUserAssignedToIssue returns true when the user is assigned to the issue
func IsUserAssignedToIssue(issue *Issue, user *User) (isAssigned bool, err error) {
- isAssigned, err = x.Exist(&IssueAssignees{IssueID: issue.ID, AssigneeID: user.ID})
- return
+ return isUserAssignedToIssue(x, issue, user)
+}
+
+func isUserAssignedToIssue(e Engine, issue *Issue, user *User) (isAssigned bool, err error) {
+ return e.Get(&IssueAssignees{IssueID: issue.ID, AssigneeID: user.ID})
}
// DeleteNotPassedAssignee deletes all assignees who aren't passed via the "assignees" array
@@ -78,7 +81,7 @@ func DeleteNotPassedAssignee(issue *Issue, doer *User, assignees []*User) (err e
if !found {
// This function also does comments and hooks, which is why we call it seperatly instead of directly removing the assignees here
- if err := UpdateAssignee(issue, doer, assignee.ID); err != nil {
+ if _, _, err := issue.ToggleAssignee(doer, assignee.ID); err != nil {
return err
}
}
@@ -110,73 +113,56 @@ func clearAssigneeByUserID(sess *xorm.Session, userID int64) (err error) {
return
}
-// AddAssigneeIfNotAssigned adds an assignee only if he isn't aleady assigned to the issue
-func AddAssigneeIfNotAssigned(issue *Issue, doer *User, assigneeID int64) (err error) {
- // Check if the user is already assigned
- isAssigned, err := IsUserAssignedToIssue(issue, &User{ID: assigneeID})
- if err != nil {
- return err
- }
-
- if !isAssigned {
- return issue.ChangeAssignee(doer, assigneeID)
- }
- return nil
-}
-
-// UpdateAssignee deletes or adds an assignee to an issue
-func UpdateAssignee(issue *Issue, doer *User, assigneeID int64) (err error) {
- return issue.ChangeAssignee(doer, assigneeID)
-}
-
-// ChangeAssignee changes the Assignee of this issue.
-func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
+// ToggleAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
+func (issue *Issue) ToggleAssignee(doer *User, assigneeID int64) (removed bool, comment *Comment, err error) {
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
- return err
+ return false, nil, err
}
- if err := issue.changeAssignee(sess, doer, assigneeID, false); err != nil {
- return err
+ removed, comment, err = issue.toggleAssignee(sess, doer, assigneeID, false)
+ if err != nil {
+ return false, nil, err
}
if err := sess.Commit(); err != nil {
- return err
+ return false, nil, err
}
go HookQueue.Add(issue.RepoID)
- return nil
+
+ return removed, comment, nil
}
-func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID int64, isCreate bool) (err error) {
- // Update the assignee
- removed, err := updateIssueAssignee(sess, issue, assigneeID)
+func (issue *Issue) toggleAssignee(sess *xorm.Session, doer *User, assigneeID int64, isCreate bool) (removed bool, comment *Comment, err error) {
+ removed, err = toggleUserAssignee(sess, issue, assigneeID)
if err != nil {
- return fmt.Errorf("UpdateIssueUserByAssignee: %v", err)
+ return false, nil, fmt.Errorf("UpdateIssueUserByAssignee: %v", err)
}
// Repo infos
if err = issue.loadRepo(sess); err != nil {
- return fmt.Errorf("loadRepo: %v", err)
+ return false, nil, fmt.Errorf("loadRepo: %v", err)
}
// Comment
- if _, err = createAssigneeComment(sess, doer, issue.Repo, issue, assigneeID, removed); err != nil {
- return fmt.Errorf("createAssigneeComment: %v", err)
+ comment, err = createAssigneeComment(sess, doer, issue.Repo, issue, assigneeID, removed)
+ if err != nil {
+ return false, nil, fmt.Errorf("createAssigneeComment: %v", err)
}
// if pull request is in the middle of creation - don't call webhook
if isCreate {
- return nil
+ return removed, comment, err
}
if issue.IsPull {
mode, _ := accessLevelUnit(sess, doer, issue.Repo, UnitTypePullRequests)
if err = issue.loadPullRequest(sess); err != nil {
- return fmt.Errorf("loadPullRequest: %v", err)
+ return false, nil, fmt.Errorf("loadPullRequest: %v", err)
}
issue.PullRequest.Issue = issue
apiPullRequest := &api.PullRequestPayload{
@@ -190,9 +176,10 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
} else {
apiPullRequest.Action = api.HookIssueAssigned
}
+ // Assignee comment triggers a webhook
if err := prepareWebhooks(sess, issue.Repo, HookEventPullRequest, apiPullRequest); err != nil {
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
- return nil
+ return false, nil, err
}
} else {
mode, _ := accessLevelUnit(sess, doer, issue.Repo, UnitTypeIssues)
@@ -208,67 +195,50 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
} else {
apiIssue.Action = api.HookIssueAssigned
}
+ // Assignee comment triggers a webhook
if err := prepareWebhooks(sess, issue.Repo, HookEventIssues, apiIssue); err != nil {
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
- return nil
+ return false, nil, err
}
}
- return nil
+ return removed, comment, nil
}
-// UpdateAPIAssignee is a helper function to add or delete one or multiple issue assignee(s)
-// Deleting is done the GitHub way (quote from their api documentation):
-// https://developer.github.com/v3/issues/#edit-an-issue
-// "assignees" (array): Logins for Users to assign to this issue.
-// Pass one or more user logins to replace the set of assignees on this Issue.
-// Send an empty array ([]) to clear all assignees from the Issue.
-func UpdateAPIAssignee(issue *Issue, oneAssignee string, multipleAssignees []string, doer *User) (err error) {
- var allNewAssignees []*User
+// toggles user assignee state in database
+func toggleUserAssignee(e *xorm.Session, issue *Issue, assigneeID int64) (removed bool, err error) {
- // Keep the old assignee thingy for compatibility reasons
- if oneAssignee != "" {
- // Prevent double adding assignees
- var isDouble bool
- for _, assignee := range multipleAssignees {
- if assignee == oneAssignee {
- isDouble = true
- break
- }
- }
-
- if !isDouble {
- multipleAssignees = append(multipleAssignees, oneAssignee)
- }
+ // Check if the user exists
+ assignee, err := getUserByID(e, assigneeID)
+ if err != nil {
+ return false, err
}
- // Loop through all assignees to add them
- for _, assigneeName := range multipleAssignees {
- assignee, err := GetUserByName(assigneeName)
- if err != nil {
- return err
+ // Check if the submitted user is already assigned, if yes delete him otherwise add him
+ var i int
+ for i = 0; i < len(issue.Assignees); i++ {
+ if issue.Assignees[i].ID == assigneeID {
+ break
}
-
- allNewAssignees = append(allNewAssignees, assignee)
}
- // Delete all old assignees not passed
- if err = DeleteNotPassedAssignee(issue, doer, allNewAssignees); err != nil {
- return err
- }
+ assigneeIn := IssueAssignees{AssigneeID: assigneeID, IssueID: issue.ID}
- // Add all new assignees
- // Update the assignee. The function will check if the user exists, is already
- // assigned (which he shouldn't as we deleted all assignees before) and
- // has access to the repo.
- for _, assignee := range allNewAssignees {
- // Extra method to prevent double adding (which would result in removing)
- err = AddAssigneeIfNotAssigned(issue, doer, assignee.ID)
+ toBeDeleted := i < len(issue.Assignees)
+ if toBeDeleted {
+ issue.Assignees = append(issue.Assignees[:i], issue.Assignees[i:]...)
+ _, err = e.Delete(assigneeIn)
if err != nil {
- return err
+ return toBeDeleted, err
+ }
+ } else {
+ issue.Assignees = append(issue.Assignees, assignee)
+ _, err = e.Insert(assigneeIn)
+ if err != nil {
+ return toBeDeleted, err
}
}
- return
+ return toBeDeleted, nil
}
// MakeIDsFromAPIAssigneesToAdd returns an array with all assignee IDs
@@ -292,7 +262,7 @@ func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string
}
// Get the IDs of all assignees
- assigneeIDs = GetUserIDsByNames(multipleAssignees)
+ assigneeIDs, err = GetUserIDsByNames(multipleAssignees, false)
return
}