@ -654,34 +654,66 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
// repoReviewerSelection items to bee shown
// repoReviewerSelection items to bee shown
type repoReviewerSelection struct {
type repoReviewerSelection struct {
IsTeam bool
IsTeam bool
Team * organization . Team
Team * organization . Team
User * user_model . User
User * user_model . User
Review * issues_model . Review
Review * issues_model . Review
CanChange bool
CanBeDismissed bool
Checked bool
CanChange bool
ItemID int64
Requested bool
ItemID int64
}
}
// RetrieveRepoReviewers find all reviewers of a repository
type issueSidebarReviewersData struct {
Repository * repo_model . Repository
RepoOwnerName string
RepoLink string
IssueID int64
CanChooseReviewer bool
OriginalReviews issues_model . ReviewList
TeamReviewers [ ] * repoReviewerSelection
Reviewers [ ] * repoReviewerSelection
CurrentPullReviewers [ ] * repoReviewerSelection
}
// RetrieveRepoReviewers find all reviewers of a repository. If issue is nil, it means the doer is creating a new PR.
func RetrieveRepoReviewers ( ctx * context . Context , repo * repo_model . Repository , issue * issues_model . Issue , canChooseReviewer bool ) {
func RetrieveRepoReviewers ( ctx * context . Context , repo * repo_model . Repository , issue * issues_model . Issue , canChooseReviewer bool ) {
ctx . Data [ "CanChooseReviewer" ] = canChooseReviewer
data := & issueSidebarReviewersData { }
data . RepoLink = ctx . Repo . RepoLink
data . Repository = repo
data . RepoOwnerName = repo . OwnerName
data . CanChooseReviewer = canChooseReviewer
originalAuthorReviews , err := issues_model . GetReviewersFromOriginalAuthorsByIssueID ( ctx , issue . ID )
var posterID int64
if err != nil {
var isClosed bool
ctx . ServerError ( "GetReviewersFromOriginalAuthorsByIssueID" , err )
var reviews issues_model . ReviewList
return
}
ctx . Data [ "OriginalReviews" ] = originalAuthorReviews
reviews , err := issues_model . GetReviewsByIssueID ( ctx , issue . ID )
if issue == nil {
if err != nil {
posterID = ctx . Doer . ID
ctx . ServerError ( "GetReviewersByIssueID" , err )
} else {
return
posterID = issue . PosterID
}
if issue . OriginalAuthorID > 0 {
posterID = 0 // for migrated PRs, no poster ID
}
if len ( reviews ) == 0 && ! canChooseReviewer {
data . IssueID = issue . ID
return
isClosed = issue . IsClosed || issue . PullRequest . HasMerged
originalAuthorReviews , err := issues_model . GetReviewersFromOriginalAuthorsByIssueID ( ctx , issue . ID )
if err != nil {
ctx . ServerError ( "GetReviewersFromOriginalAuthorsByIssueID" , err )
return
}
data . OriginalReviews = originalAuthorReviews
reviews , err = issues_model . GetReviewsByIssueID ( ctx , issue . ID )
if err != nil {
ctx . ServerError ( "GetReviewersByIssueID" , err )
return
}
if len ( reviews ) == 0 && ! canChooseReviewer {
return
}
}
}
var (
var (
@ -693,11 +725,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
)
)
if canChooseReviewer {
if canChooseReviewer {
posterID := issue . PosterID
var err error
if issue . OriginalAuthorID > 0 {
posterID = 0
}
reviewers , err = repo_model . GetReviewers ( ctx , repo , ctx . Doer . ID , posterID )
reviewers , err = repo_model . GetReviewers ( ctx , repo , ctx . Doer . ID , posterID )
if err != nil {
if err != nil {
ctx . ServerError ( "GetReviewers" , err )
ctx . ServerError ( "GetReviewers" , err )
@ -723,9 +751,9 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
for _ , review := range reviews {
for _ , review := range reviews {
tmp := & repoReviewerSelection {
tmp := & repoReviewerSelection {
Check ed: review . Type == issues_model . ReviewTypeRequest ,
Request ed: review . Type == issues_model . ReviewTypeRequest ,
Review : review ,
Review : review ,
ItemID : review . ReviewerID ,
ItemID : review . ReviewerID ,
}
}
if review . ReviewerTeamID > 0 {
if review . ReviewerTeamID > 0 {
tmp . IsTeam = true
tmp . IsTeam = true
@ -756,7 +784,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
currentPullReviewers := make ( [ ] * repoReviewerSelection , 0 , len ( pullReviews ) )
currentPullReviewers := make ( [ ] * repoReviewerSelection , 0 , len ( pullReviews ) )
for _ , item := range pullReviews {
for _ , item := range pullReviews {
if item . Review . ReviewerID > 0 {
if item . Review . ReviewerID > 0 {
if err = item . Review . LoadReviewer ( ctx ) ; err != nil {
if err : = item . Review . LoadReviewer ( ctx ) ; err != nil {
if user_model . IsErrUserNotExist ( err ) {
if user_model . IsErrUserNotExist ( err ) {
continue
continue
}
}
@ -765,7 +793,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
}
}
item . User = item . Review . Reviewer
item . User = item . Review . Reviewer
} else if item . Review . ReviewerTeamID > 0 {
} else if item . Review . ReviewerTeamID > 0 {
if err = item . Review . LoadReviewerTeam ( ctx ) ; err != nil {
if err : = item . Review . LoadReviewerTeam ( ctx ) ; err != nil {
if organization . IsErrTeamNotExist ( err ) {
if organization . IsErrTeamNotExist ( err ) {
continue
continue
}
}
@ -776,10 +804,11 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
} else {
} else {
continue
continue
}
}
item . CanBeDismissed = ctx . Repo . Permission . IsAdmin ( ) && ! isClosed &&
( item . Review . Type == issues_model . ReviewTypeApprove || item . Review . Type == issues_model . ReviewTypeReject )
currentPullReviewers = append ( currentPullReviewers , item )
currentPullReviewers = append ( currentPullReviewers , item )
}
}
ctx . Data [ "PullReviewers" ] = currentPullReviewers
data . CurrentPullReviewers = currentPullReviewers
}
}
if canChooseReviewer && reviewersResult != nil {
if canChooseReviewer && reviewersResult != nil {
@ -807,7 +836,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
} )
} )
}
}
ctx . Data [ "Reviewers" ] = reviewersResult
data . Reviewers = reviewersResult
}
}
if canChooseReviewer && teamReviewersResult != nil {
if canChooseReviewer && teamReviewersResult != nil {
@ -835,8 +864,10 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
} )
} )
}
}
ctx . Data [ "TeamReviewers" ] = teamReviewersResult
data . TeamReviewers = teamReviewersResult
}
}
ctx . Data [ "IssueSidebarReviewersData" ] = data
}
}
// RetrieveRepoMetas find all the meta information of a repository
// RetrieveRepoMetas find all the meta information of a repository
@ -1117,7 +1148,14 @@ func DeleteIssue(ctx *context.Context) {
}
}
// ValidateRepoMetas check and returns repository's meta information
// ValidateRepoMetas check and returns repository's meta information
func ValidateRepoMetas ( ctx * context . Context , form forms . CreateIssueForm , isPull bool ) ( [ ] int64 , [ ] int64 , int64 , int64 ) {
func ValidateRepoMetas ( ctx * context . Context , form forms . CreateIssueForm , isPull bool ) ( ret struct {
LabelIDs , AssigneeIDs [ ] int64
MilestoneID , ProjectID int64
Reviewers [ ] * user_model . User
TeamReviewers [ ] * organization . Team
} ,
) {
var (
var (
repo = ctx . Repo . Repository
repo = ctx . Repo . Repository
err error
err error
@ -1125,7 +1163,7 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull
labels := RetrieveRepoMetas ( ctx , ctx . Repo . Repository , isPull )
labels := RetrieveRepoMetas ( ctx , ctx . Repo . Repository , isPull )
if ctx . Written ( ) {
if ctx . Written ( ) {
return nil , nil , 0 , 0
return ret
}
}
var labelIDs [ ] int64
var labelIDs [ ] int64
@ -1134,7 +1172,7 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull
if len ( form . LabelIDs ) > 0 {
if len ( form . LabelIDs ) > 0 {
labelIDs , err = base . StringsToInt64s ( strings . Split ( form . LabelIDs , "," ) )
labelIDs , err = base . StringsToInt64s ( strings . Split ( form . LabelIDs , "," ) )
if err != nil {
if err != nil {
return nil , nil , 0 , 0
return ret
}
}
labelIDMark := make ( container . Set [ int64 ] )
labelIDMark := make ( container . Set [ int64 ] )
labelIDMark . AddMultiple ( labelIDs ... )
labelIDMark . AddMultiple ( labelIDs ... )
@ -1157,11 +1195,11 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull
milestone , err := issues_model . GetMilestoneByRepoID ( ctx , ctx . Repo . Repository . ID , milestoneID )
milestone , err := issues_model . GetMilestoneByRepoID ( ctx , ctx . Repo . Repository . ID , milestoneID )
if err != nil {
if err != nil {
ctx . ServerError ( "GetMilestoneByID" , err )
ctx . ServerError ( "GetMilestoneByID" , err )
return nil , nil , 0 , 0
return ret
}
}
if milestone . RepoID != repo . ID {
if milestone . RepoID != repo . ID {
ctx . ServerError ( "GetMilestoneByID" , err )
ctx . ServerError ( "GetMilestoneByID" , err )
return nil , nil , 0 , 0
return ret
}
}
ctx . Data [ "Milestone" ] = milestone
ctx . Data [ "Milestone" ] = milestone
ctx . Data [ "milestone_id" ] = milestoneID
ctx . Data [ "milestone_id" ] = milestoneID
@ -1171,11 +1209,11 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull
p , err := project_model . GetProjectByID ( ctx , form . ProjectID )
p , err := project_model . GetProjectByID ( ctx , form . ProjectID )
if err != nil {
if err != nil {
ctx . ServerError ( "GetProjectByID" , err )
ctx . ServerError ( "GetProjectByID" , err )
return nil , nil , 0 , 0
return ret
}
}
if p . RepoID != ctx . Repo . Repository . ID && p . OwnerID != ctx . Repo . Repository . OwnerID {
if p . RepoID != ctx . Repo . Repository . ID && p . OwnerID != ctx . Repo . Repository . OwnerID {
ctx . NotFound ( "" , nil )
ctx . NotFound ( "" , nil )
return nil , nil , 0 , 0
return ret
}
}
ctx . Data [ "Project" ] = p
ctx . Data [ "Project" ] = p
@ -1187,7 +1225,7 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull
if len ( form . AssigneeIDs ) > 0 {
if len ( form . AssigneeIDs ) > 0 {
assigneeIDs , err = base . StringsToInt64s ( strings . Split ( form . AssigneeIDs , "," ) )
assigneeIDs , err = base . StringsToInt64s ( strings . Split ( form . AssigneeIDs , "," ) )
if err != nil {
if err != nil {
return nil , nil , 0 , 0
return ret
}
}
// Check if the passed assignees actually exists and is assignable
// Check if the passed assignees actually exists and is assignable
@ -1195,18 +1233,18 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull
assignee , err := user_model . GetUserByID ( ctx , aID )
assignee , err := user_model . GetUserByID ( ctx , aID )
if err != nil {
if err != nil {
ctx . ServerError ( "GetUserByID" , err )
ctx . ServerError ( "GetUserByID" , err )
return nil , nil , 0 , 0
return ret
}
}
valid , err := access_model . CanBeAssigned ( ctx , assignee , repo , isPull )
valid , err := access_model . CanBeAssigned ( ctx , assignee , repo , isPull )
if err != nil {
if err != nil {
ctx . ServerError ( "CanBeAssigned" , err )
ctx . ServerError ( "CanBeAssigned" , err )
return nil , nil , 0 , 0
return ret
}
}
if ! valid {
if ! valid {
ctx . ServerError ( "canBeAssigned" , repo_model . ErrUserDoesNotHaveAccessToRepo { UserID : aID , RepoName : repo . Name } )
ctx . ServerError ( "canBeAssigned" , repo_model . ErrUserDoesNotHaveAccessToRepo { UserID : aID , RepoName : repo . Name } )
return nil , nil , 0 , 0
return ret
}
}
}
}
}
}
@ -1216,7 +1254,39 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull
assigneeIDs = append ( assigneeIDs , form . AssigneeID )
assigneeIDs = append ( assigneeIDs , form . AssigneeID )
}
}
return labelIDs , assigneeIDs , milestoneID , form . ProjectID
// Check reviewers
var reviewers [ ] * user_model . User
var teamReviewers [ ] * organization . Team
if isPull && len ( form . ReviewerIDs ) > 0 {
reviewerIDs , err := base . StringsToInt64s ( strings . Split ( form . ReviewerIDs , "," ) )
if err != nil {
return ret
}
// Check if the passed reviewers (user/team) actually exist
for _ , rID := range reviewerIDs {
// negative reviewIDs represent team requests
if rID < 0 {
teamReviewer , err := organization . GetTeamByID ( ctx , - rID )
if err != nil {
ctx . ServerError ( "GetTeamByID" , err )
return ret
}
teamReviewers = append ( teamReviewers , teamReviewer )
continue
}
reviewer , err := user_model . GetUserByID ( ctx , rID )
if err != nil {
ctx . ServerError ( "GetUserByID" , err )
return ret
}
reviewers = append ( reviewers , reviewer )
}
}
ret . LabelIDs , ret . AssigneeIDs , ret . MilestoneID , ret . ProjectID = labelIDs , assigneeIDs , milestoneID , form . ProjectID
ret . Reviewers , ret . TeamReviewers = reviewers , teamReviewers
return ret
}
}
// NewIssuePost response for creating new issue
// NewIssuePost response for creating new issue
@ -1234,11 +1304,13 @@ func NewIssuePost(ctx *context.Context) {
attachments [ ] string
attachments [ ] string
)
)
labelIDs , assigneeIDs , milestoneID , projectID := ValidateRepoMetas ( ctx , * form , false )
validateRet := ValidateRepoMetas ( ctx , * form , false )
if ctx . Written ( ) {
if ctx . Written ( ) {
return
return
}
}
labelIDs , assigneeIDs , milestoneID , projectID := validateRet . LabelIDs , validateRet . AssigneeIDs , validateRet . MilestoneID , validateRet . ProjectID
if projectID > 0 {
if projectID > 0 {
if ! ctx . Repo . CanRead ( unit . TypeProjects ) {
if ! ctx . Repo . CanRead ( unit . TypeProjects ) {
// User must also be able to see the project.
// User must also be able to see the project.
@ -2479,7 +2551,7 @@ func UpdatePullReviewRequest(ctx *context.Context) {
return
return
}
}
err = issue_service . IsValid TeamReviewRequest( ctx , team , ctx . Doer , action == "attach" , issue )
_ , err = issue_service . TeamReviewRequest ( ctx , issue , ctx . Doer , team , action == "attach" )
if err != nil {
if err != nil {
if issues_model . IsErrNotValidReviewRequest ( err ) {
if issues_model . IsErrNotValidReviewRequest ( err ) {
log . Warn (
log . Warn (
@ -2490,12 +2562,6 @@ func UpdatePullReviewRequest(ctx *context.Context) {
ctx . Status ( http . StatusForbidden )
ctx . Status ( http . StatusForbidden )
return
return
}
}
ctx . ServerError ( "IsValidTeamReviewRequest" , err )
return
}
_ , err = issue_service . TeamReviewRequest ( ctx , issue , ctx . Doer , team , action == "attach" )
if err != nil {
ctx . ServerError ( "TeamReviewRequest" , err )
ctx . ServerError ( "TeamReviewRequest" , err )
return
return
}
}
@ -2517,7 +2583,7 @@ func UpdatePullReviewRequest(ctx *context.Context) {
return
return
}
}
err = issue_service . IsValid ReviewRequest( ctx , reviewer , ctx . Doer , action == "attach" , issue , nil )
_ , err = issue_service . ReviewRequest ( ctx , issue , ctx . Doer , & ctx . Repo . Permission , reviewer , action == "attach" )
if err != nil {
if err != nil {
if issues_model . IsErrNotValidReviewRequest ( err ) {
if issues_model . IsErrNotValidReviewRequest ( err ) {
log . Warn (
log . Warn (
@ -2528,12 +2594,6 @@ func UpdatePullReviewRequest(ctx *context.Context) {
ctx . Status ( http . StatusForbidden )
ctx . Status ( http . StatusForbidden )
return
return
}
}
ctx . ServerError ( "isValidReviewRequest" , err )
return
}
_ , err = issue_service . ReviewRequest ( ctx , issue , ctx . Doer , reviewer , action == "attach" )
if err != nil {
if issues_model . IsErrReviewRequestOnClosedPR ( err ) {
if issues_model . IsErrReviewRequestOnClosedPR ( err ) {
ctx . Status ( http . StatusForbidden )
ctx . Status ( http . StatusForbidden )
return
return