Backport #27736 by @lng2020 Fix #27722 Fix #27357 Fix #25837 Fix #28732 1. Fix the typo `BlockingByDependenciesNotPermitted`, which causes the `not permitted message` not to show. The correct one is `Blocking` or `BlockedBy` 2. Rewrite the perm check. The perm check uses a very tricky way to avoid duplicate checks for a slice of issues, which is confusing. In fact, it's also the reason causing the bug. It uses `lastRepoID` and `lastPerm` to avoid duplicate checks, but forgets to assign the `lastPerm` at the end of the code block. So I rewrote this to avoid this trick. ![I U1AT{GNFY3 1HZ`6L{(2L](https://github.com/go-gitea/gitea/assets/70063547/79acd02a-a567-4316-ae0d-11c6461becf1) 3. It also reuses the `blocks` slice, which is even more confusing. So I rewrote this too. ![UARFPXRGGZQFB7J$2`R}5_R](https://github.com/go-gitea/gitea/assets/70063547/f21cff0f-d9ac-4ce4-ae4d-adffc98ecd99) Co-authored-by: Nanguan Lin <70063547+lng2020@users.noreply.github.com>tags/v1.21.4
@@ -102,23 +102,24 @@ func GetIssueDependencies(ctx *context.APIContext) { | |||
return | |||
} | |||
var lastRepoID int64 | |||
var lastPerm access_model.Permission | |||
repoPerms := make(map[int64]access_model.Permission) | |||
repoPerms[ctx.Repo.Repository.ID] = ctx.Repo.Permission | |||
for _, blocker := range blockersInfo { | |||
// Get the permissions for this repository | |||
perm := lastPerm | |||
if lastRepoID != blocker.Repository.ID { | |||
if blocker.Repository.ID == ctx.Repo.Repository.ID { | |||
perm = ctx.Repo.Permission | |||
} else { | |||
var err error | |||
perm, err = access_model.GetUserRepoPermission(ctx, &blocker.Repository, ctx.Doer) | |||
if err != nil { | |||
ctx.ServerError("GetUserRepoPermission", err) | |||
return | |||
} | |||
// If the repo ID exists in the map, return the exist permissions | |||
// else get the permission and add it to the map | |||
var perm access_model.Permission | |||
existPerm, ok := repoPerms[blocker.RepoID] | |||
if ok { | |||
perm = existPerm | |||
} else { | |||
var err error | |||
perm, err = access_model.GetUserRepoPermission(ctx, &blocker.Repository, ctx.Doer) | |||
if err != nil { | |||
ctx.ServerError("GetUserRepoPermission", err) | |||
return | |||
} | |||
lastRepoID = blocker.Repository.ID | |||
repoPerms[blocker.RepoID] = perm | |||
} | |||
// check permission | |||
@@ -341,29 +342,31 @@ func GetIssueBlocks(ctx *context.APIContext) { | |||
return | |||
} | |||
var lastRepoID int64 | |||
var lastPerm access_model.Permission | |||
var issues []*issues_model.Issue | |||
repoPerms := make(map[int64]access_model.Permission) | |||
repoPerms[ctx.Repo.Repository.ID] = ctx.Repo.Permission | |||
for i, depMeta := range deps { | |||
if i < skip || i >= max { | |||
continue | |||
} | |||
// Get the permissions for this repository | |||
perm := lastPerm | |||
if lastRepoID != depMeta.Repository.ID { | |||
if depMeta.Repository.ID == ctx.Repo.Repository.ID { | |||
perm = ctx.Repo.Permission | |||
} else { | |||
var err error | |||
perm, err = access_model.GetUserRepoPermission(ctx, &depMeta.Repository, ctx.Doer) | |||
if err != nil { | |||
ctx.ServerError("GetUserRepoPermission", err) | |||
return | |||
} | |||
// If the repo ID exists in the map, return the exist permissions | |||
// else get the permission and add it to the map | |||
var perm access_model.Permission | |||
existPerm, ok := repoPerms[depMeta.RepoID] | |||
if ok { | |||
perm = existPerm | |||
} else { | |||
var err error | |||
perm, err = access_model.GetUserRepoPermission(ctx, &depMeta.Repository, ctx.Doer) | |||
if err != nil { | |||
ctx.ServerError("GetUserRepoPermission", err) | |||
return | |||
} | |||
lastRepoID = depMeta.Repository.ID | |||
repoPerms[depMeta.RepoID] = perm | |||
} | |||
if !perm.CanReadIssuesOrPulls(depMeta.Issue.IsPull) { |
@@ -1948,7 +1948,7 @@ func ViewIssue(ctx *context.Context) { | |||
return | |||
} | |||
ctx.Data["BlockingDependencies"], ctx.Data["BlockingByDependenciesNotPermitted"] = checkBlockedByIssues(ctx, blocking) | |||
ctx.Data["BlockingDependencies"], ctx.Data["BlockingDependenciesNotPermitted"] = checkBlockedByIssues(ctx, blocking) | |||
if ctx.Written() { | |||
return | |||
} | |||
@@ -2009,38 +2009,34 @@ func ViewIssue(ctx *context.Context) { | |||
// checkBlockedByIssues return canRead and notPermitted | |||
func checkBlockedByIssues(ctx *context.Context, blockers []*issues_model.DependencyInfo) (canRead, notPermitted []*issues_model.DependencyInfo) { | |||
var ( | |||
lastRepoID int64 | |||
lastPerm access_model.Permission | |||
) | |||
for i, blocker := range blockers { | |||
repoPerms := make(map[int64]access_model.Permission) | |||
repoPerms[ctx.Repo.Repository.ID] = ctx.Repo.Permission | |||
for _, blocker := range blockers { | |||
// Get the permissions for this repository | |||
perm := lastPerm | |||
if lastRepoID != blocker.Repository.ID { | |||
if blocker.Repository.ID == ctx.Repo.Repository.ID { | |||
perm = ctx.Repo.Permission | |||
} else { | |||
var err error | |||
perm, err = access_model.GetUserRepoPermission(ctx, &blocker.Repository, ctx.Doer) | |||
if err != nil { | |||
ctx.ServerError("GetUserRepoPermission", err) | |||
return nil, nil | |||
} | |||
// If the repo ID exists in the map, return the exist permissions | |||
// else get the permission and add it to the map | |||
var perm access_model.Permission | |||
existPerm, ok := repoPerms[blocker.RepoID] | |||
if ok { | |||
perm = existPerm | |||
} else { | |||
var err error | |||
perm, err = access_model.GetUserRepoPermission(ctx, &blocker.Repository, ctx.Doer) | |||
if err != nil { | |||
ctx.ServerError("GetUserRepoPermission", err) | |||
return nil, nil | |||
} | |||
lastRepoID = blocker.Repository.ID | |||
repoPerms[blocker.RepoID] = perm | |||
} | |||
// check permission | |||
if !perm.CanReadIssuesOrPulls(blocker.Issue.IsPull) { | |||
blockers[len(notPermitted)], blockers[i] = blocker, blockers[len(notPermitted)] | |||
notPermitted = blockers[:len(notPermitted)+1] | |||
if perm.CanReadIssuesOrPulls(blocker.Issue.IsPull) { | |||
canRead = append(canRead, blocker) | |||
} else { | |||
notPermitted = append(notPermitted, blocker) | |||
} | |||
} | |||
blockers = blockers[len(notPermitted):] | |||
sortDependencyInfo(blockers) | |||
sortDependencyInfo(canRead) | |||
sortDependencyInfo(notPermitted) | |||
return blockers, notPermitted | |||
return canRead, notPermitted | |||
} | |||
func sortDependencyInfo(blockers []*issues_model.DependencyInfo) { |