Fix issues/pulls dependencies problems (#9842) (#9864)

* Fix issues/pulls dependencies problems

* fix swagger and api param name

* fix js
This commit is contained in:
Lunny Xiao 2020-01-20 01:56:57 +08:00 committed by techknowlogick
parent aa6ed1b7c1
commit 8add1dfacc
8 changed files with 57 additions and 26 deletions

View File

@ -95,8 +95,8 @@ func (r *Repository) CanUseTimetracker(issue *models.Issue, user *models.User) b
} }
// CanCreateIssueDependencies returns whether or not a user can create dependencies. // CanCreateIssueDependencies returns whether or not a user can create dependencies.
func (r *Repository) CanCreateIssueDependencies(user *models.User) bool { func (r *Repository) CanCreateIssueDependencies(user *models.User, isPull bool) bool {
return r.Permission.CanWrite(models.UnitTypeIssues) && r.Repository.IsDependenciesEnabled() return r.Repository.IsDependenciesEnabled() && r.Permission.CanWriteIssuesOrPulls(isPull)
} }
// GetCommitsCount returns cached commit count for current view // GetCommitsCount returns cached commit count for current view

View File

@ -51,6 +51,10 @@ func SearchIssues(ctx *context.APIContext) {
// description: repository to prioritize in the results // description: repository to prioritize in the results
// type: integer // type: integer
// format: int64 // format: int64
// - name: type
// in: query
// description: filter by type (issues / pulls) if set
// type: string
// responses: // responses:
// "200": // "200":
// "$ref": "#/responses/IssueList" // "$ref": "#/responses/IssueList"
@ -129,6 +133,16 @@ func SearchIssues(ctx *context.APIContext) {
} }
} }
var isPull util.OptionalBool
switch ctx.Query("type") {
case "pulls":
isPull = util.OptionalBoolTrue
case "issues":
isPull = util.OptionalBoolFalse
default:
isPull = util.OptionalBoolNone
}
// Only fetch the issues if we either don't have a keyword or the search returned issues // Only fetch the issues if we either don't have a keyword or the search returned issues
// This would otherwise return all issues if no issues were found by the search. // This would otherwise return all issues if no issues were found by the search.
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 { if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
@ -141,6 +155,7 @@ func SearchIssues(ctx *context.APIContext) {
LabelIDs: labelIDs, LabelIDs: labelIDs,
SortType: "priorityrepo", SortType: "priorityrepo",
PriorityRepoID: ctx.QueryInt64("priority_repo_id"), PriorityRepoID: ctx.QueryInt64("priority_repo_id"),
IsPull: isPull,
}) })
} }

View File

@ -415,7 +415,7 @@ func CompareDiff(ctx *context.Context) {
if !nothingToCompare { if !nothingToCompare {
// Setup information for new form. // Setup information for new form.
RetrieveRepoMetas(ctx, ctx.Repo.Repository) RetrieveRepoMetas(ctx, ctx.Repo.Repository, true)
if ctx.Written() { if ctx.Written() {
return return
} }

View File

@ -348,7 +348,7 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repos
} }
// RetrieveRepoMetas find all the meta information of a repository // RetrieveRepoMetas find all the meta information of a repository
func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository) []*models.Label { func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository, isPull bool) []*models.Label {
if !ctx.Repo.CanWrite(models.UnitTypeIssues) { if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
return nil return nil
} }
@ -373,7 +373,7 @@ func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository) []*models.
ctx.Data["Branches"] = brs ctx.Data["Branches"] = brs
// Contains true if the user can create issue dependencies // Contains true if the user can create issue dependencies
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User) ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User, isPull)
return labels return labels
} }
@ -443,7 +443,7 @@ func NewIssue(ctx *context.Context) {
setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates) setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates)
renderAttachmentSettings(ctx) renderAttachmentSettings(ctx)
RetrieveRepoMetas(ctx, ctx.Repo.Repository) RetrieveRepoMetas(ctx, ctx.Repo.Repository, false)
if ctx.Written() { if ctx.Written() {
return return
} }
@ -458,7 +458,7 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm, isPull b
err error err error
) )
labels := RetrieveRepoMetas(ctx, ctx.Repo.Repository) labels := RetrieveRepoMetas(ctx, ctx.Repo.Repository, isPull)
if ctx.Written() { if ctx.Written() {
return nil, nil, 0 return nil, nil, 0
} }
@ -670,6 +670,14 @@ func ViewIssue(ctx *context.Context) {
ctx.Data["PageIsIssueList"] = true ctx.Data["PageIsIssueList"] = true
} }
if issue.IsPull && !ctx.Repo.CanRead(models.UnitTypeIssues) {
ctx.Data["IssueType"] = "pulls"
} else if !issue.IsPull && !ctx.Repo.CanRead(models.UnitTypePullRequests) {
ctx.Data["IssueType"] = "issues"
} else {
ctx.Data["IssueType"] = "all"
}
ctx.Data["RequireHighlightJS"] = true ctx.Data["RequireHighlightJS"] = true
ctx.Data["RequireDropzone"] = true ctx.Data["RequireDropzone"] = true
ctx.Data["RequireTribute"] = true ctx.Data["RequireTribute"] = true
@ -807,7 +815,7 @@ func ViewIssue(ctx *context.Context) {
} }
// Check if the user can use the dependencies // Check if the user can use the dependencies
ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User) ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User, issue.IsPull)
// check if dependencies can be created across repositories // check if dependencies can be created across repositories
ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies

View File

@ -14,14 +14,6 @@ import (
// AddDependency adds new dependencies // AddDependency adds new dependencies
func AddDependency(ctx *context.Context) { func AddDependency(ctx *context.Context) {
// Check if the Repo is allowed to have dependencies
if !ctx.Repo.CanCreateIssueDependencies(ctx.User) {
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
return
}
depID := ctx.QueryInt64("newDependency")
issueIndex := ctx.ParamsInt64("index") issueIndex := ctx.ParamsInt64("index")
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex) issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
if err != nil { if err != nil {
@ -29,6 +21,14 @@ func AddDependency(ctx *context.Context) {
return return
} }
// Check if the Repo is allowed to have dependencies
if !ctx.Repo.CanCreateIssueDependencies(ctx.User, issue.IsPull) {
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
return
}
depID := ctx.QueryInt64("newDependency")
if err = issue.LoadRepo(); err != nil { if err = issue.LoadRepo(); err != nil {
ctx.ServerError("LoadRepo", err) ctx.ServerError("LoadRepo", err)
return return
@ -73,14 +73,6 @@ func AddDependency(ctx *context.Context) {
// RemoveDependency removes the dependency // RemoveDependency removes the dependency
func RemoveDependency(ctx *context.Context) { func RemoveDependency(ctx *context.Context) {
// Check if the Repo is allowed to have dependencies
if !ctx.Repo.CanCreateIssueDependencies(ctx.User) {
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
return
}
depID := ctx.QueryInt64("removeDependencyID")
issueIndex := ctx.ParamsInt64("index") issueIndex := ctx.ParamsInt64("index")
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex) issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, issueIndex)
if err != nil { if err != nil {
@ -88,6 +80,14 @@ func RemoveDependency(ctx *context.Context) {
return return
} }
// Check if the Repo is allowed to have dependencies
if !ctx.Repo.CanCreateIssueDependencies(ctx.User, issue.IsPull) {
ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
return
}
depID := ctx.QueryInt64("removeDependencyID")
if err = issue.LoadRepo(); err != nil { if err = issue.LoadRepo(); err != nil {
ctx.ServerError("LoadRepo", err) ctx.ServerError("LoadRepo", err)
return return

View File

@ -428,6 +428,7 @@
<input type="hidden" id="repolink" value="{{$.RepoRelPath}}"> <input type="hidden" id="repolink" value="{{$.RepoRelPath}}">
<input type="hidden" id="repoId" value="{{.Repository.ID}}"> <input type="hidden" id="repoId" value="{{.Repository.ID}}">
<input type="hidden" id="crossRepoSearch" value="{{.AllowCrossRepositoryDependencies}}"> <input type="hidden" id="crossRepoSearch" value="{{.AllowCrossRepositoryDependencies}}">
<input type="hidden" id="type" value="{{.IssueType}}">
<!-- I know, there is probably a better way to do this --> <!-- I know, there is probably a better way to do this -->
<input type="hidden" id="issueIndex" value="{{.Issue.Index}}"/> <input type="hidden" id="issueIndex" value="{{.Issue.Index}}"/>

View File

@ -1173,6 +1173,12 @@
"description": "repository to prioritize in the results", "description": "repository to prioritize in the results",
"name": "priority_repo_id", "name": "priority_repo_id",
"in": "query" "in": "query"
},
{
"type": "string",
"description": "filter by type (issues / pulls) if set",
"name": "type",
"in": "query"
} }
], ],
"responses": { "responses": {

View File

@ -3455,9 +3455,10 @@ function initIssueList() {
const repolink = $('#repolink').val(); const repolink = $('#repolink').val();
const repoId = $('#repoId').val(); const repoId = $('#repoId').val();
const crossRepoSearch = $('#crossRepoSearch').val(); const crossRepoSearch = $('#crossRepoSearch').val();
let issueSearchUrl = `${suburl}/api/v1/repos/${repolink}/issues?q={query}`; const tp = $('#type').val();
let issueSearchUrl = `${suburl}/api/v1/repos/${repolink}/issues?q={query}&type=${tp}`;
if (crossRepoSearch === 'true') { if (crossRepoSearch === 'true') {
issueSearchUrl = `${suburl}/api/v1/repos/issues/search?q={query}&priority_repo_id=${repoId}`; issueSearchUrl = `${suburl}/api/v1/repos/issues/search?q={query}&priority_repo_id=${repoId}&type=${tp}`;
} }
$('#new-dependency-drop-list') $('#new-dependency-drop-list')
.dropdown({ .dropdown({