|
|
@ -14,11 +14,13 @@ import ( |
|
|
|
"code.gitea.io/gitea/models" |
|
|
|
"code.gitea.io/gitea/models" |
|
|
|
"code.gitea.io/gitea/modules/base" |
|
|
|
"code.gitea.io/gitea/modules/base" |
|
|
|
"code.gitea.io/gitea/modules/context" |
|
|
|
"code.gitea.io/gitea/modules/context" |
|
|
|
|
|
|
|
"code.gitea.io/gitea/modules/log" |
|
|
|
"code.gitea.io/gitea/modules/setting" |
|
|
|
"code.gitea.io/gitea/modules/setting" |
|
|
|
"code.gitea.io/gitea/modules/util" |
|
|
|
"code.gitea.io/gitea/modules/util" |
|
|
|
|
|
|
|
|
|
|
|
"github.com/keybase/go-crypto/openpgp" |
|
|
|
"github.com/keybase/go-crypto/openpgp" |
|
|
|
"github.com/keybase/go-crypto/openpgp/armor" |
|
|
|
"github.com/keybase/go-crypto/openpgp/armor" |
|
|
|
|
|
|
|
"github.com/unknwon/com" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
const ( |
|
|
@ -150,24 +152,6 @@ func Dashboard(ctx *context.Context) { |
|
|
|
// Issues render the user issues page
|
|
|
|
// Issues render the user issues page
|
|
|
|
func Issues(ctx *context.Context) { |
|
|
|
func Issues(ctx *context.Context) { |
|
|
|
isPullList := ctx.Params(":type") == "pulls" |
|
|
|
isPullList := ctx.Params(":type") == "pulls" |
|
|
|
repoID := ctx.QueryInt64("repo") |
|
|
|
|
|
|
|
if repoID > 0 { |
|
|
|
|
|
|
|
repo, err := models.GetRepositoryByID(repoID) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
ctx.ServerError("GetRepositoryByID", err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
perm, err := models.GetUserRepoPermission(repo, ctx.User) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
ctx.ServerError("GetUserRepoPermission", err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if !perm.CanReadIssuesOrPulls(isPullList) { |
|
|
|
|
|
|
|
ctx.NotFound("Repository does not exist or you have no permission", nil) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if isPullList { |
|
|
|
if isPullList { |
|
|
|
ctx.Data["Title"] = ctx.Tr("pull_requests") |
|
|
|
ctx.Data["Title"] = ctx.Tr("pull_requests") |
|
|
|
ctx.Data["PageIsPulls"] = true |
|
|
|
ctx.Data["PageIsPulls"] = true |
|
|
@ -210,32 +194,58 @@ func Issues(ctx *context.Context) { |
|
|
|
page = 1 |
|
|
|
page = 1 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
repoID := ctx.QueryInt64("repo") |
|
|
|
isShowClosed = ctx.Query("state") == "closed" |
|
|
|
isShowClosed := ctx.Query("state") == "closed" |
|
|
|
err error |
|
|
|
|
|
|
|
opts = &models.IssuesOptions{ |
|
|
|
|
|
|
|
IsClosed: util.OptionalBoolOf(isShowClosed), |
|
|
|
|
|
|
|
IsPull: util.OptionalBoolOf(isPullList), |
|
|
|
|
|
|
|
SortType: sortType, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get repositories.
|
|
|
|
// Get repositories.
|
|
|
|
if repoID > 0 { |
|
|
|
var err error |
|
|
|
opts.RepoIDs = []int64{repoID} |
|
|
|
var userRepoIDs []int64 |
|
|
|
|
|
|
|
if ctxUser.IsOrganization() { |
|
|
|
|
|
|
|
env, err := ctxUser.AccessibleReposEnv(ctx.User.ID) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
ctx.ServerError("AccessibleReposEnv", err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
userRepoIDs, err = env.RepoIDs(1, ctxUser.NumRepos) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
ctx.ServerError("env.RepoIDs", err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
unitType := models.UnitTypeIssues |
|
|
|
unitType := models.UnitTypeIssues |
|
|
|
if isPullList { |
|
|
|
if isPullList { |
|
|
|
unitType = models.UnitTypePullRequests |
|
|
|
unitType = models.UnitTypePullRequests |
|
|
|
} |
|
|
|
} |
|
|
|
if ctxUser.IsOrganization() { |
|
|
|
userRepoIDs, err = ctxUser.GetAccessRepoIDs(unitType) |
|
|
|
opts.RepoSubQuery = ctxUser.OrgUnitRepositoriesSubQuery(ctx.User.ID, unitType) |
|
|
|
if err != nil { |
|
|
|
} else { |
|
|
|
ctx.ServerError("ctxUser.GetAccessRepoIDs", err) |
|
|
|
opts.RepoSubQuery = ctxUser.UnitRepositoriesSubQuery(unitType) |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if len(userRepoIDs) == 0 { |
|
|
|
|
|
|
|
userRepoIDs = []int64{-1} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
opts := &models.IssuesOptions{ |
|
|
|
|
|
|
|
IsClosed: util.OptionalBoolOf(isShowClosed), |
|
|
|
|
|
|
|
IsPull: util.OptionalBoolOf(isPullList), |
|
|
|
|
|
|
|
SortType: sortType, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if repoID > 0 { |
|
|
|
|
|
|
|
opts.RepoIDs = []int64{repoID} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch filterMode { |
|
|
|
switch filterMode { |
|
|
|
|
|
|
|
case models.FilterModeAll: |
|
|
|
|
|
|
|
if repoID > 0 { |
|
|
|
|
|
|
|
if !com.IsSliceContainsInt64(userRepoIDs, repoID) { |
|
|
|
|
|
|
|
// force an empty result
|
|
|
|
|
|
|
|
opts.RepoIDs = []int64{-1} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
opts.RepoIDs = userRepoIDs |
|
|
|
|
|
|
|
} |
|
|
|
case models.FilterModeAssign: |
|
|
|
case models.FilterModeAssign: |
|
|
|
opts.AssigneeID = ctxUser.ID |
|
|
|
opts.AssigneeID = ctxUser.ID |
|
|
|
case models.FilterModeCreate: |
|
|
|
case models.FilterModeCreate: |
|
|
@ -244,6 +254,14 @@ func Issues(ctx *context.Context) { |
|
|
|
opts.MentionedID = ctxUser.ID |
|
|
|
opts.MentionedID = ctxUser.ID |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
counts, err := models.CountIssuesByRepo(opts) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
ctx.ServerError("CountIssuesByRepo", err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
opts.Page = page |
|
|
|
|
|
|
|
opts.PageSize = setting.UI.IssuePagingNum |
|
|
|
var labelIDs []int64 |
|
|
|
var labelIDs []int64 |
|
|
|
selectLabels := ctx.Query("labels") |
|
|
|
selectLabels := ctx.Query("labels") |
|
|
|
if len(selectLabels) > 0 && selectLabels != "0" { |
|
|
|
if len(selectLabels) > 0 && selectLabels != "0" { |
|
|
@ -255,15 +273,6 @@ func Issues(ctx *context.Context) { |
|
|
|
} |
|
|
|
} |
|
|
|
opts.LabelIDs = labelIDs |
|
|
|
opts.LabelIDs = labelIDs |
|
|
|
|
|
|
|
|
|
|
|
counts, err := models.CountIssuesByRepo(opts) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
ctx.ServerError("CountIssuesByRepo", err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
opts.Page = page |
|
|
|
|
|
|
|
opts.PageSize = setting.UI.IssuePagingNum |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
issues, err := models.Issues(opts) |
|
|
|
issues, err := models.Issues(opts) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
ctx.ServerError("Issues", err) |
|
|
|
ctx.ServerError("Issues", err) |
|
|
@ -280,6 +289,41 @@ func Issues(ctx *context.Context) { |
|
|
|
showReposMap[repoID] = repo |
|
|
|
showReposMap[repoID] = repo |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if repoID > 0 { |
|
|
|
|
|
|
|
if _, ok := showReposMap[repoID]; !ok { |
|
|
|
|
|
|
|
repo, err := models.GetRepositoryByID(repoID) |
|
|
|
|
|
|
|
if models.IsErrRepoNotExist(err) { |
|
|
|
|
|
|
|
ctx.NotFound("GetRepositoryByID", err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} else if err != nil { |
|
|
|
|
|
|
|
ctx.ServerError("GetRepositoryByID", fmt.Errorf("[%d]%v", repoID, err)) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
showReposMap[repoID] = repo |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
repo := showReposMap[repoID] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if user has access to given repository.
|
|
|
|
|
|
|
|
perm, err := models.GetUserRepoPermission(repo, ctxUser) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
ctx.ServerError("GetUserRepoPermission", fmt.Errorf("[%d]%v", repoID, err)) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if !perm.CanRead(models.UnitTypeIssues) { |
|
|
|
|
|
|
|
if log.IsTrace() { |
|
|
|
|
|
|
|
log.Trace("Permission Denied: User %-v cannot read %-v of repo %-v\n"+ |
|
|
|
|
|
|
|
"User in repo has Permissions: %-+v", |
|
|
|
|
|
|
|
ctxUser, |
|
|
|
|
|
|
|
models.UnitTypeIssues, |
|
|
|
|
|
|
|
repo, |
|
|
|
|
|
|
|
perm) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ctx.Status(404) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
showRepos := models.RepositoryListOfMap(showReposMap) |
|
|
|
showRepos := models.RepositoryListOfMap(showReposMap) |
|
|
|
sort.Sort(showRepos) |
|
|
|
sort.Sort(showRepos) |
|
|
|
if err = showRepos.LoadAttributes(); err != nil { |
|
|
|
if err = showRepos.LoadAttributes(); err != nil { |
|
|
@ -297,12 +341,12 @@ func Issues(ctx *context.Context) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
issueStats, err := models.GetUserIssueStats(models.UserIssueStatsOptions{ |
|
|
|
issueStats, err := models.GetUserIssueStats(models.UserIssueStatsOptions{ |
|
|
|
UserID: ctxUser.ID, |
|
|
|
UserID: ctxUser.ID, |
|
|
|
RepoID: repoID, |
|
|
|
RepoID: repoID, |
|
|
|
RepoSubQuery: opts.RepoSubQuery, |
|
|
|
UserRepoIDs: userRepoIDs, |
|
|
|
FilterMode: filterMode, |
|
|
|
FilterMode: filterMode, |
|
|
|
IsPull: isPullList, |
|
|
|
IsPull: isPullList, |
|
|
|
IsClosed: isShowClosed, |
|
|
|
IsClosed: isShowClosed, |
|
|
|
}) |
|
|
|
}) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
ctx.ServerError("GetUserIssueStats", err) |
|
|
|
ctx.ServerError("GetUserIssueStats", err) |
|
|
|