From 0dbc6230286e113accbc6d5e829ce8dae1d1f5d4 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Sun, 28 Jul 2024 23:11:40 +0800 Subject: [PATCH] Hide the "Details" link of commit status when the user cannot access actions (#30156) Fix #26685 If a commit status comes from Gitea Actions and the user cannot access the repo's actions unit (the user does not have the permission or the actions unit is disabled), a 404 page will occur after clicking the "Details" link. We should hide the "Details" link in this case. (cherry picked from commit 7dec8de9147b20c014d68bb1020afe28a263b95a) Conflicts: routers/web/repo/commit.go trivial context commit --- models/git/commit_status.go | 40 +++++++++++++++++++++++++++++++- models/git/commit_status_test.go | 25 ++++++++++++++++++++ routers/web/repo/branch.go | 5 ++++ routers/web/repo/commit.go | 21 ++++++++++++++--- routers/web/repo/compare.go | 2 +- routers/web/repo/issue.go | 11 +++++++++ routers/web/repo/pull.go | 14 ++++++++++- routers/web/repo/repo.go | 3 +++ routers/web/repo/view.go | 3 +++ routers/web/user/home.go | 6 +++++ routers/web/user/notification.go | 7 ++++++ 11 files changed, 131 insertions(+), 6 deletions(-) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index d975f0572c..76870f9eb1 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -141,13 +141,17 @@ func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (in return newIdx, nil } -func (status *CommitStatus) loadAttributes(ctx context.Context) (err error) { +func (status *CommitStatus) loadRepository(ctx context.Context) (err error) { if status.Repo == nil { status.Repo, err = repo_model.GetRepositoryByID(ctx, status.RepoID) if err != nil { return fmt.Errorf("getRepositoryByID [%d]: %w", status.RepoID, err) } } + return nil +} + +func (status *CommitStatus) loadCreator(ctx context.Context) (err error) { if status.Creator == nil && status.CreatorID > 0 { status.Creator, err = user_model.GetUserByID(ctx, status.CreatorID) if err != nil { @@ -157,6 +161,13 @@ func (status *CommitStatus) loadAttributes(ctx context.Context) (err error) { return nil } +func (status *CommitStatus) loadAttributes(ctx context.Context) (err error) { + if err := status.loadRepository(ctx); err != nil { + return err + } + return status.loadCreator(ctx) +} + // APIURL returns the absolute APIURL to this commit-status. func (status *CommitStatus) APIURL(ctx context.Context) string { _ = status.loadAttributes(ctx) @@ -168,6 +179,21 @@ func (status *CommitStatus) LocaleString(lang translation.Locale) string { return lang.TrString("repo.commitstatus." + status.State.String()) } +// HideActionsURL set `TargetURL` to an empty string if the status comes from Gitea Actions +func (status *CommitStatus) HideActionsURL(ctx context.Context) { + if status.Repo == nil { + if err := status.loadRepository(ctx); err != nil { + log.Error("loadRepository: %v", err) + return + } + } + + prefix := fmt.Sprintf("%s/actions", status.Repo.Link()) + if strings.HasPrefix(status.TargetURL, prefix) { + status.TargetURL = "" + } +} + // CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus { if len(statuses) == 0 { @@ -471,3 +497,15 @@ func ConvertFromGitCommit(ctx context.Context, commits []*git.Commit, repo *repo repo, ) } + +// CommitStatusesHideActionsURL hide Gitea Actions urls +func CommitStatusesHideActionsURL(ctx context.Context, statuses []*CommitStatus) { + idToRepos := make(map[int64]*repo_model.Repository) + for _, status := range statuses { + if status.Repo == nil { + status.Repo = idToRepos[status.RepoID] + } + status.HideActionsURL(ctx) + idToRepos[status.RepoID] = status.Repo + } +} diff --git a/models/git/commit_status_test.go b/models/git/commit_status_test.go index 07b9031c5c..bff3d3dccf 100644 --- a/models/git/commit_status_test.go +++ b/models/git/commit_status_test.go @@ -4,9 +4,11 @@ package git_test import ( + "fmt" "testing" "time" + actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" @@ -240,3 +242,26 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) { assert.Equal(t, "compliance/lint-backend", contexts[0]) } } + +func TestCommitStatusesHideActionsURL(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) + run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: 791, RepoID: repo.ID}) + assert.NoError(t, run.LoadAttributes(db.DefaultContext)) + + statuses := []*git_model.CommitStatus{ + { + RepoID: repo.ID, + TargetURL: fmt.Sprintf("%s/jobs/%d", run.Link(), run.Index), + }, + { + RepoID: repo.ID, + TargetURL: "https://mycicd.org/1", + }, + } + + git_model.CommitStatusesHideActionsURL(db.DefaultContext, statuses) + assert.Empty(t, statuses[0].TargetURL) + assert.Equal(t, "https://mycicd.org/1", statuses[1].TargetURL) +} diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index f879a98786..4897a5f4fc 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -70,6 +70,11 @@ func Branches(ctx *context.Context) { ctx.ServerError("LoadBranches", err) return } + if !ctx.Repo.CanRead(unit.TypeActions) { + for key := range commitStatuses { + git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key]) + } + } commitStatus := make(map[string]*git_model.CommitStatus) for commitID, cs := range commitStatuses { diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index bf9a448ec5..3da8b1506c 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" + unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/charset" @@ -81,7 +82,7 @@ func Commits(ctx *context.Context) { ctx.ServerError("CommitsByRange", err) return } - ctx.Data["Commits"] = git_model.ConvertFromGitCommit(ctx, commits, ctx.Repo.Repository) + ctx.Data["Commits"] = processGitCommits(ctx, commits) ctx.Data["Username"] = ctx.Repo.Owner.Name ctx.Data["Reponame"] = ctx.Repo.Repository.Name @@ -199,7 +200,7 @@ func SearchCommits(ctx *context.Context) { return } ctx.Data["CommitCount"] = len(commits) - ctx.Data["Commits"] = git_model.ConvertFromGitCommit(ctx, commits, ctx.Repo.Repository) + ctx.Data["Commits"] = processGitCommits(ctx, commits) ctx.Data["Keyword"] = query if all { @@ -264,7 +265,7 @@ func FileHistory(ctx *context.Context) { } } - ctx.Data["Commits"] = git_model.ConvertFromGitCommit(ctx, commits, ctx.Repo.Repository) + ctx.Data["Commits"] = processGitCommits(ctx, commits) ctx.Data["Username"] = ctx.Repo.Owner.Name ctx.Data["Reponame"] = ctx.Repo.Repository.Name @@ -375,6 +376,9 @@ func Diff(ctx *context.Context) { if err != nil { log.Error("GetLatestCommitStatus: %v", err) } + if !ctx.Repo.CanRead(unit_model.TypeActions) { + git_model.CommitStatusesHideActionsURL(ctx, statuses) + } ctx.Data["CommitStatus"] = git_model.CalcCommitStatus(statuses) ctx.Data["CommitStatuses"] = statuses @@ -454,3 +458,14 @@ func RawDiff(ctx *context.Context) { return } } + +func processGitCommits(ctx *context.Context, gitCommits []*git.Commit) []*git_model.SignCommitWithStatuses { + commits := git_model.ConvertFromGitCommit(ctx, gitCommits, ctx.Repo.Repository) + if !ctx.Repo.CanRead(unit_model.TypeActions) { + for _, commit := range commits { + commit.Status.HideActionsURL(ctx) + git_model.CommitStatusesHideActionsURL(ctx, commit.Statuses) + } + } + return commits +} diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index 088e5150f6..38d6004ec6 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -643,7 +643,7 @@ func PrepareCompareDiff( return false } - commits := git_model.ConvertFromGitCommit(ctx, ci.CompareInfo.Commits, ci.HeadRepo) + commits := processGitCommits(ctx, ci.CompareInfo.Commits) ctx.Data["Commits"] = commits ctx.Data["CommitCount"] = len(commits) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index dcc1cdd467..b48b078736 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -346,6 +346,11 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt ctx.ServerError("GetIssuesAllCommitStatus", err) return } + if !ctx.Repo.CanRead(unit.TypeActions) { + for key := range commitStatuses { + git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key]) + } + } if err := issues.LoadAttributes(ctx); err != nil { ctx.ServerError("issues.LoadAttributes", err) @@ -1777,6 +1782,12 @@ func ViewIssue(ctx *context.Context) { ctx.ServerError("LoadPushCommits", err) return } + if !ctx.Repo.CanRead(unit.TypeActions) { + for _, commit := range comment.Commits { + commit.Status.HideActionsURL(ctx) + git_model.CommitStatusesHideActionsURL(ctx, commit.Statuses) + } + } } else if comment.Type == issues_model.CommentTypeAddTimeManual || comment.Type == issues_model.CommentTypeStopTracking || comment.Type == issues_model.CommentTypeDeleteTimeManual { diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index aa1f506483..a9213790cb 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -515,6 +515,10 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue) ctx.ServerError("GetLatestCommitStatus", err) return nil } + if !ctx.Repo.CanRead(unit.TypeActions) { + git_model.CommitStatusesHideActionsURL(ctx, commitStatuses) + } + if len(commitStatuses) != 0 { ctx.Data["LatestCommitStatuses"] = commitStatuses ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(commitStatuses) @@ -577,6 +581,10 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C ctx.ServerError("GetLatestCommitStatus", err) return nil } + if !ctx.Repo.CanRead(unit.TypeActions) { + git_model.CommitStatusesHideActionsURL(ctx, commitStatuses) + } + if len(commitStatuses) > 0 { ctx.Data["LatestCommitStatuses"] = commitStatuses ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(commitStatuses) @@ -669,6 +677,10 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C ctx.ServerError("GetLatestCommitStatus", err) return nil } + if !ctx.Repo.CanRead(unit.TypeActions) { + git_model.CommitStatusesHideActionsURL(ctx, commitStatuses) + } + if len(commitStatuses) > 0 { ctx.Data["LatestCommitStatuses"] = commitStatuses ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(commitStatuses) @@ -835,7 +847,7 @@ func ViewPullCommits(ctx *context.Context) { ctx.Data["Username"] = ctx.Repo.Owner.Name ctx.Data["Reponame"] = ctx.Repo.Repository.Name - commits := git_model.ConvertFromGitCommit(ctx, prInfo.Commits, ctx.Repo.Repository) + commits := processGitCommits(ctx, prInfo.Commits) ctx.Data["Commits"] = commits ctx.Data["CommitCount"] = len(commits) diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 7e20d3afaa..652738afda 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -683,6 +683,9 @@ func SearchRepo(ctx *context.Context) { ctx.JSON(http.StatusInternalServerError, nil) return } + if !ctx.Repo.CanRead(unit.TypeActions) { + git_model.CommitStatusesHideActionsURL(ctx, latestCommitStatuses) + } results := make([]*repo_service.WebSearchRepository, len(repos)) for i, repo := range repos { diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 5295bfdb2a..caa4bfae1b 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -368,6 +368,9 @@ func loadLatestCommitData(ctx *context.Context, latestCommit *git.Commit) bool { if err != nil { log.Error("GetLatestCommitStatus: %v", err) } + if !ctx.Repo.CanRead(unit_model.TypeActions) { + git_model.CommitStatusesHideActionsURL(ctx, statuses) + } ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(statuses) ctx.Data["LatestCommitStatuses"] = statuses diff --git a/routers/web/user/home.go b/routers/web/user/home.go index df22c3fb8d..0a1b08c57b 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -17,6 +17,7 @@ import ( activities_model "code.gitea.io/gitea/models/activities" asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/db" + git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" @@ -597,6 +598,11 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { ctx.ServerError("GetIssuesLastCommitStatus", err) return } + if !ctx.Repo.CanRead(unit.TypeActions) { + for key := range commitStatuses { + git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key]) + } + } // ------------------------------- // Fill stats to post to ctx.Data. diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index 2105cfe5c5..f8b68fb18e 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -13,8 +13,10 @@ import ( activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" + git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/optional" @@ -303,6 +305,11 @@ func NotificationSubscriptions(ctx *context.Context) { ctx.ServerError("GetIssuesAllCommitStatus", err) return } + if !ctx.Repo.CanRead(unit.TypeActions) { + for key := range commitStatuses { + git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key]) + } + } ctx.Data["CommitLastStatus"] = lastStatus ctx.Data["CommitStatuses"] = commitStatuses ctx.Data["Issues"] = issues