* Fix issues/pulls dependencies problems * fix swagger and api param name * fix jstags/v1.12.0-dev
@@ -138,8 +138,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 { | |||||
return r.Permission.CanWrite(models.UnitTypeIssues) && r.Repository.IsDependenciesEnabled() | |||||
func (r *Repository) CanCreateIssueDependencies(user *models.User, isPull bool) bool { | |||||
return r.Repository.IsDependenciesEnabled() && r.Permission.CanWriteIssuesOrPulls(isPull) | |||||
} | } | ||||
// GetCommitsCount returns cached commit count for current view | // GetCommitsCount returns cached commit count for current view | ||||
@@ -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" | ||||
@@ -128,6 +132,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 { | ||||
@@ -140,6 +154,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, | |||||
}) | }) | ||||
} | } | ||||
@@ -413,7 +413,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 | ||||
} | } | ||||
@@ -343,7 +343,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 | ||||
} | } | ||||
@@ -368,7 +368,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 | ||||
} | } | ||||
@@ -438,7 +438,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 | ||||
} | } | ||||
@@ -453,7 +453,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 | ||||
} | } | ||||
@@ -665,6 +665,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 | ||||
@@ -802,7 +810,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 | ||||
@@ -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 | ||||
@@ -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}}"/> | ||||
@@ -1397,6 +1397,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": { | ||||
@@ -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({ | ||||