summaryrefslogtreecommitdiffstats
path: root/services/issue/assignee.go
diff options
context:
space:
mode:
authora1012112796 <1012112796@qq.com>2020-10-21 02:18:25 +0800
committerGitHub <noreply@github.com>2020-10-20 14:18:25 -0400
commitb9850375fca1ed72f5a5ba265d48c241aff2e21e (patch)
treebc5f03623003b95911686e3e472c97f3c8cbe04e /services/issue/assignee.go
parentb50448b28698b5c9cd1825bf95f2331fa030790f (diff)
downloadgitea-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.go164
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
}