diff options
author | a1012112796 <1012112796@qq.com> | 2020-10-21 02:18:25 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-20 14:18:25 -0400 |
commit | b9850375fca1ed72f5a5ba265d48c241aff2e21e (patch) | |
tree | bc5f03623003b95911686e3e472c97f3c8cbe04e /services/issue/assignee.go | |
parent | b50448b28698b5c9cd1825bf95f2331fa030790f (diff) | |
download | gitea-b9850375fca1ed72f5a5ba265d48c241aff2e21e.tar.gz gitea-b9850375fca1ed72f5a5ba265d48c241aff2e21e.zip |
Add review request api (#11355)
* Add review request api
* add : POST /repos/{owner}/{repo}/pulls/{index}/requested_reviewers
* Remove : DELET /repos/{owner}/{repo}/pulls/{index}/requested_reviewers
* fix some request review bug
* block delet request review by models/DeleteReview()
Signed-off-by: a1012112796 <1012112796@qq.com>
* make fmt
* fix bug
* fix test code
* fix typo
* Apply suggestion from code review @jonasfranz
* fix swagger ref
* fix typo
Co-authored-by: Lauris BH <lauris@nix.lv>
* fix comment
* Change response message
* chang response so some simplfy
* Add ErrIllLegalReviewRequest
fix some nits
* make fmt
* Apply suggestions from code review
Co-authored-by: silverwind <me@silverwind.io>
* * Add team support
* fix test
* fix an known bug
* fix nit
* fix test
* Apply suggestions from code review
Co-authored-by: zeripath <art27@cantab.net>
* update get api and add test
Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: zeripath <art27@cantab.net>
Diffstat (limited to 'services/issue/assignee.go')
-rw-r--r-- | services/issue/assignee.go | 164 |
1 files changed, 158 insertions, 6 deletions
diff --git a/services/issue/assignee.go b/services/issue/assignee.go index f48e55e53c..f24a242f6b 100644 --- a/services/issue/assignee.go +++ b/services/issue/assignee.go @@ -6,6 +6,7 @@ package issue import ( "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification" ) @@ -53,8 +54,7 @@ func ToggleAssignee(issue *models.Issue, doer *models.User, assigneeID int64) (r } // ReviewRequest add or remove a review request from a user for this PR, and make comment for it. -func ReviewRequest(issue *models.Issue, doer *models.User, reviewer *models.User, isAdd bool) (err error) { - var comment *models.Comment +func ReviewRequest(issue *models.Issue, doer *models.User, reviewer *models.User, isAdd bool) (comment *models.Comment, err error) { if isAdd { comment, err = models.AddReviewRequest(issue, reviewer, doer) } else { @@ -62,19 +62,171 @@ func ReviewRequest(issue *models.Issue, doer *models.User, reviewer *models.User } if err != nil { - return + return nil, err } if comment != nil { notification.NotifyPullReviewRequest(doer, issue, reviewer, isAdd, comment) } + return +} + +// IsValidReviewRequest Check permission for ReviewRequest +func IsValidReviewRequest(reviewer, doer *models.User, isAdd bool, issue *models.Issue, permDoer *models.Permission) error { + if reviewer.IsOrganization() { + return models.ErrNotValidReviewRequest{ + Reason: "Organization can't be added as reviewer", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + if doer.IsOrganization() { + return models.ErrNotValidReviewRequest{ + Reason: "Organization can't be doer to add reviewer", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + + permReviewer, err := models.GetUserRepoPermission(issue.Repo, reviewer) + if err != nil { + return err + } + + if permDoer == nil { + permDoer = new(models.Permission) + *permDoer, err = models.GetUserRepoPermission(issue.Repo, doer) + if err != nil { + return err + } + } + + lastreview, err := models.GetReviewByIssueIDAndUserID(issue.ID, reviewer.ID) + if err != nil && !models.IsErrReviewNotExist(err) { + return err + } + + var pemResult bool + if isAdd { + pemResult = permReviewer.CanAccessAny(models.AccessModeRead, models.UnitTypePullRequests) + if !pemResult { + return models.ErrNotValidReviewRequest{ + Reason: "Reviewer can't read", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + + if doer.ID == issue.PosterID && issue.OriginalAuthorID == 0 && lastreview != nil && lastreview.Type != models.ReviewTypeRequest { + return nil + } + + pemResult = permDoer.CanAccessAny(models.AccessModeWrite, models.UnitTypePullRequests) + if !pemResult { + pemResult, err = models.IsOfficialReviewer(issue, doer) + if err != nil { + return err + } + if !pemResult { + return models.ErrNotValidReviewRequest{ + Reason: "Doer can't choose reviewer", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + } + + if doer.ID == reviewer.ID { + return models.ErrNotValidReviewRequest{ + Reason: "doer can't be reviewer", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + + if reviewer.ID == issue.PosterID && issue.OriginalAuthorID == 0 { + return models.ErrNotValidReviewRequest{ + Reason: "poster of pr can't be reviewer", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + } else { + if lastreview != nil && lastreview.Type == models.ReviewTypeRequest && lastreview.ReviewerID == doer.ID { + return nil + } + + pemResult = permDoer.IsAdmin() + if !pemResult { + return models.ErrNotValidReviewRequest{ + Reason: "Doer is not admin", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + } + + return nil +} + +// IsValidTeamReviewRequest Check permission for ReviewRequest Team +func IsValidTeamReviewRequest(reviewer *models.Team, doer *models.User, isAdd bool, issue *models.Issue) error { + if doer.IsOrganization() { + return models.ErrNotValidReviewRequest{ + Reason: "Organization can't be doer to add reviewer", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + + permission, err := models.GetUserRepoPermission(issue.Repo, doer) + if err != nil { + log.Error("Unable to GetUserRepoPermission for %-v in %-v#%d", doer, issue.Repo, issue.Index) + return err + } + + if isAdd { + if issue.Repo.IsPrivate { + hasTeam := models.HasTeamRepo(reviewer.OrgID, reviewer.ID, issue.RepoID) + + if !hasTeam { + return models.ErrNotValidReviewRequest{ + Reason: "Reviewing team can't read repo", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + } + + doerCanWrite := permission.CanAccessAny(models.AccessModeWrite, models.UnitTypePullRequests) + if !doerCanWrite { + official, err := models.IsOfficialReviewer(issue, doer) + if err != nil { + log.Error("Unable to Check if IsOfficialReviewer for %-v in %-v#%d", doer, issue.Repo, issue.Index) + return err + } + if !official { + return models.ErrNotValidReviewRequest{ + Reason: "Doer can't choose reviewer", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + } + } else if !permission.IsAdmin() { + return models.ErrNotValidReviewRequest{ + Reason: "Only admin users can remove team requests. Doer is not admin", + UserID: doer.ID, + RepoID: issue.Repo.ID, + } + } + return nil } // TeamReviewRequest add or remove a review request from a team for this PR, and make comment for it. -func TeamReviewRequest(issue *models.Issue, doer *models.User, reviewer *models.Team, isAdd bool) (err error) { - var comment *models.Comment +func TeamReviewRequest(issue *models.Issue, doer *models.User, reviewer *models.Team, isAdd bool) (comment *models.Comment, err error) { if isAdd { comment, err = models.AddTeamReviewRequest(issue, reviewer, doer) } else { @@ -106,5 +258,5 @@ func TeamReviewRequest(issue *models.Issue, doer *models.User, reviewer *models. notification.NotifyPullReviewRequest(doer, issue, member, isAdd, comment) } - return nil + return } |