aboutsummaryrefslogtreecommitdiffstats
path: root/routers/repo
diff options
context:
space:
mode:
Diffstat (limited to 'routers/repo')
-rw-r--r--routers/repo/issue.go152
1 files changed, 151 insertions, 1 deletions
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index 0697d11a66..0a059bf789 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -289,6 +289,8 @@ func issues(ctx *context.Context, milestoneID int64, isPullOption util.OptionalB
reviewTyp := models.ReviewTypeApprove
if typ == "reject" {
reviewTyp = models.ReviewTypeReject
+ } else if typ == "waiting" {
+ reviewTyp = models.ReviewTypeRequest
}
for _, count := range counts {
if count.Type == reviewTyp {
@@ -377,6 +379,16 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repos
}
}
+// RetrieveRepoReviewers find all reviewers of a repository
+func RetrieveRepoReviewers(ctx *context.Context, repo *models.Repository, issuePosterID int64) {
+ var err error
+ ctx.Data["Reviewers"], err = repo.GetReviewers(ctx.User.ID, issuePosterID)
+ if err != nil {
+ ctx.ServerError("GetReviewers", err)
+ return
+ }
+}
+
// RetrieveRepoMetas find all the meta information of a repository
func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository, isPull bool) []*models.Label {
if !ctx.Repo.CanWriteIssuesOrPulls(isPull) {
@@ -815,6 +827,28 @@ func ViewIssue(ctx *context.Context) {
}
}
+ if issue.IsPull {
+ canChooseReviewer := ctx.Repo.CanWrite(models.UnitTypePullRequests)
+ if !canChooseReviewer && ctx.User != nil && ctx.IsSigned {
+ canChooseReviewer, err = models.IsOfficialReviewer(issue, ctx.User)
+ if err != nil {
+ ctx.ServerError("IsOfficialReviewer", err)
+ return
+ }
+ }
+
+ if canChooseReviewer {
+ RetrieveRepoReviewers(ctx, repo, issue.PosterID)
+ ctx.Data["CanChooseReviewer"] = true
+ } else {
+ ctx.Data["CanChooseReviewer"] = false
+ }
+
+ if ctx.Written() {
+ return
+ }
+ }
+
if ctx.IsSigned {
// Update issue-user.
if err = issue.ReadBy(ctx.User.ID); err != nil {
@@ -926,7 +960,7 @@ func ViewIssue(ctx *context.Context) {
if comment.MilestoneID > 0 && comment.Milestone == nil {
comment.Milestone = ghostMilestone
}
- } else if comment.Type == models.CommentTypeAssignees {
+ } else if comment.Type == models.CommentTypeAssignees || comment.Type == models.CommentTypeReviewRequest {
if err = comment.LoadAssigneeUser(); err != nil {
ctx.ServerError("LoadAssigneeUser", err)
return
@@ -1273,6 +1307,122 @@ func UpdateIssueAssignee(ctx *context.Context) {
})
}
+func isLegalReviewRequest(reviewer, doer *models.User, isAdd bool, issue *models.Issue) error {
+ if reviewer.IsOrganization() {
+ return fmt.Errorf("Organization can't be added as reviewer [user_id: %d, repo_id: %d]", reviewer.ID, issue.PullRequest.BaseRepo.ID)
+ }
+ if doer.IsOrganization() {
+ return fmt.Errorf("Organization can't be doer to add reviewer [user_id: %d, repo_id: %d]", doer.ID, issue.PullRequest.BaseRepo.ID)
+ }
+
+ permReviewer, err := models.GetUserRepoPermission(issue.Repo, reviewer)
+ if err != nil {
+ return err
+ }
+
+ permDoer, err := models.GetUserRepoPermission(issue.Repo, doer)
+ if err != nil {
+ return err
+ }
+
+ lastreview, err := models.GetReviewerByIssueIDAndUserID(issue.ID, reviewer.ID)
+ if err != nil {
+ return err
+ }
+
+ var pemResult bool
+ if isAdd {
+ pemResult = permReviewer.CanAccessAny(models.AccessModeRead, models.UnitTypePullRequests)
+ if !pemResult {
+ return fmt.Errorf("Reviewer can't read [user_id: %d, repo_name: %s]", reviewer.ID, issue.Repo.Name)
+ }
+
+ if doer.ID == issue.PosterID && 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 fmt.Errorf("Doer can't choose reviewer [user_id: %d, repo_name: %s, issue_id: %d]", doer.ID, issue.Repo.Name, issue.ID)
+ }
+ }
+
+ if doer.ID == reviewer.ID {
+ return fmt.Errorf("doer can't be reviewer [user_id: %d, repo_name: %s]", doer.ID, issue.Repo.Name)
+ }
+
+ if reviewer.ID == issue.PosterID {
+ return fmt.Errorf("poster of pr can't be reviewer [user_id: %d, repo_name: %s]", reviewer.ID, issue.Repo.Name)
+ }
+ } else {
+ if lastreview.Type == models.ReviewTypeRequest && lastreview.ReviewerID == doer.ID {
+ return nil
+ }
+
+ pemResult = permDoer.IsAdmin()
+ if !pemResult {
+ return fmt.Errorf("Doer is not admin [user_id: %d, repo_name: %s]", doer.ID, issue.Repo.Name)
+ }
+ }
+
+ return nil
+}
+
+// updatePullReviewRequest change pull's request reviewers
+func updatePullReviewRequest(ctx *context.Context) {
+ issues := getActionIssues(ctx)
+ if ctx.Written() {
+ return
+ }
+
+ reviewID := ctx.QueryInt64("id")
+ event := ctx.Query("is_add")
+
+ if event != "add" && event != "remove" {
+ ctx.ServerError("updatePullReviewRequest", fmt.Errorf("is_add should not be \"%s\"", event))
+ return
+ }
+
+ for _, issue := range issues {
+ if issue.IsPull {
+
+ reviewer, err := models.GetUserByID(reviewID)
+ if err != nil {
+ ctx.ServerError("GetUserByID", err)
+ return
+ }
+
+ err = isLegalReviewRequest(reviewer, ctx.User, event == "add", issue)
+ if err != nil {
+ ctx.ServerError("isLegalRequestReview", err)
+ return
+ }
+
+ err = issue_service.ReviewRequest(issue, ctx.User, reviewer, event == "add")
+ if err != nil {
+ ctx.ServerError("ReviewRequest", err)
+ return
+ }
+ } else {
+ ctx.ServerError("updatePullReviewRequest", fmt.Errorf("%d in %d is not Pull Request", issue.ID, issue.Repo.ID))
+ }
+ }
+
+ ctx.JSON(200, map[string]interface{}{
+ "ok": true,
+ })
+}
+
+// UpdatePullReviewRequest add or remove review request
+func UpdatePullReviewRequest(ctx *context.Context) {
+ updatePullReviewRequest(ctx)
+}
+
// UpdateIssueStatus change issue's status
func UpdateIssueStatus(ctx *context.Context) {
issues := getActionIssues(ctx)