Skip to content

Commit 7dec8de

Browse files
authored
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. <img src="https://github.com/go-gitea/gitea/assets/15528715/68361714-b784-4bb5-baab-efde4221f466" width="400px" />
1 parent aa36989 commit 7dec8de

11 files changed

+131
-6
lines changed

models/git/commit_status.go

+39-1
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,17 @@ func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (in
171171
return newIdx, nil
172172
}
173173

174-
func (status *CommitStatus) loadAttributes(ctx context.Context) (err error) {
174+
func (status *CommitStatus) loadRepository(ctx context.Context) (err error) {
175175
if status.Repo == nil {
176176
status.Repo, err = repo_model.GetRepositoryByID(ctx, status.RepoID)
177177
if err != nil {
178178
return fmt.Errorf("getRepositoryByID [%d]: %w", status.RepoID, err)
179179
}
180180
}
181+
return nil
182+
}
183+
184+
func (status *CommitStatus) loadCreator(ctx context.Context) (err error) {
181185
if status.Creator == nil && status.CreatorID > 0 {
182186
status.Creator, err = user_model.GetUserByID(ctx, status.CreatorID)
183187
if err != nil {
@@ -187,6 +191,13 @@ func (status *CommitStatus) loadAttributes(ctx context.Context) (err error) {
187191
return nil
188192
}
189193

194+
func (status *CommitStatus) loadAttributes(ctx context.Context) (err error) {
195+
if err := status.loadRepository(ctx); err != nil {
196+
return err
197+
}
198+
return status.loadCreator(ctx)
199+
}
200+
190201
// APIURL returns the absolute APIURL to this commit-status.
191202
func (status *CommitStatus) APIURL(ctx context.Context) string {
192203
_ = status.loadAttributes(ctx)
@@ -198,6 +209,21 @@ func (status *CommitStatus) LocaleString(lang translation.Locale) string {
198209
return lang.TrString("repo.commitstatus." + status.State.String())
199210
}
200211

212+
// HideActionsURL set `TargetURL` to an empty string if the status comes from Gitea Actions
213+
func (status *CommitStatus) HideActionsURL(ctx context.Context) {
214+
if status.Repo == nil {
215+
if err := status.loadRepository(ctx); err != nil {
216+
log.Error("loadRepository: %v", err)
217+
return
218+
}
219+
}
220+
221+
prefix := fmt.Sprintf("%s/actions", status.Repo.Link())
222+
if strings.HasPrefix(status.TargetURL, prefix) {
223+
status.TargetURL = ""
224+
}
225+
}
226+
201227
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
202228
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
203229
var lastStatus *CommitStatus
@@ -506,3 +532,15 @@ func ConvertFromGitCommit(ctx context.Context, commits []*git.Commit, repo *repo
506532
repo,
507533
)
508534
}
535+
536+
// CommitStatusesHideActionsURL hide Gitea Actions urls
537+
func CommitStatusesHideActionsURL(ctx context.Context, statuses []*CommitStatus) {
538+
idToRepos := make(map[int64]*repo_model.Repository)
539+
for _, status := range statuses {
540+
if status.Repo == nil {
541+
status.Repo = idToRepos[status.RepoID]
542+
}
543+
status.HideActionsURL(ctx)
544+
idToRepos[status.RepoID] = status.Repo
545+
}
546+
}

models/git/commit_status_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
package git_test
55

66
import (
7+
"fmt"
78
"testing"
89
"time"
910

11+
actions_model "code.gitea.io/gitea/models/actions"
1012
"code.gitea.io/gitea/models/db"
1113
git_model "code.gitea.io/gitea/models/git"
1214
repo_model "code.gitea.io/gitea/models/repo"
@@ -231,3 +233,26 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) {
231233
assert.Equal(t, "compliance/lint-backend", contexts[0])
232234
}
233235
}
236+
237+
func TestCommitStatusesHideActionsURL(t *testing.T) {
238+
assert.NoError(t, unittest.PrepareTestDatabase())
239+
240+
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
241+
run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: 791, RepoID: repo.ID})
242+
assert.NoError(t, run.LoadAttributes(db.DefaultContext))
243+
244+
statuses := []*git_model.CommitStatus{
245+
{
246+
RepoID: repo.ID,
247+
TargetURL: fmt.Sprintf("%s/jobs/%d", run.Link(), run.Index),
248+
},
249+
{
250+
RepoID: repo.ID,
251+
TargetURL: "https://mycicd.org/1",
252+
},
253+
}
254+
255+
git_model.CommitStatusesHideActionsURL(db.DefaultContext, statuses)
256+
assert.Empty(t, statuses[0].TargetURL)
257+
assert.Equal(t, "https://mycicd.org/1", statuses[1].TargetURL)
258+
}

routers/web/repo/branch.go

+5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ func Branches(ctx *context.Context) {
7070
ctx.ServerError("LoadBranches", err)
7171
return
7272
}
73+
if !ctx.Repo.CanRead(unit.TypeActions) {
74+
for key := range commitStatuses {
75+
git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key])
76+
}
77+
}
7378

7479
commitStatus := make(map[string]*git_model.CommitStatus)
7580
for commitID, cs := range commitStatuses {

routers/web/repo/commit.go

+18-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"code.gitea.io/gitea/models/db"
1717
git_model "code.gitea.io/gitea/models/git"
1818
repo_model "code.gitea.io/gitea/models/repo"
19+
unit_model "code.gitea.io/gitea/models/unit"
1920
user_model "code.gitea.io/gitea/models/user"
2021
"code.gitea.io/gitea/modules/base"
2122
"code.gitea.io/gitea/modules/charset"
@@ -81,7 +82,7 @@ func Commits(ctx *context.Context) {
8182
ctx.ServerError("CommitsByRange", err)
8283
return
8384
}
84-
ctx.Data["Commits"] = git_model.ConvertFromGitCommit(ctx, commits, ctx.Repo.Repository)
85+
ctx.Data["Commits"] = processGitCommits(ctx, commits)
8586

8687
ctx.Data["Username"] = ctx.Repo.Owner.Name
8788
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
@@ -199,7 +200,7 @@ func SearchCommits(ctx *context.Context) {
199200
return
200201
}
201202
ctx.Data["CommitCount"] = len(commits)
202-
ctx.Data["Commits"] = git_model.ConvertFromGitCommit(ctx, commits, ctx.Repo.Repository)
203+
ctx.Data["Commits"] = processGitCommits(ctx, commits)
203204

204205
ctx.Data["Keyword"] = query
205206
if all {
@@ -242,7 +243,7 @@ func FileHistory(ctx *context.Context) {
242243
ctx.ServerError("CommitsByFileAndRange", err)
243244
return
244245
}
245-
ctx.Data["Commits"] = git_model.ConvertFromGitCommit(ctx, commits, ctx.Repo.Repository)
246+
ctx.Data["Commits"] = processGitCommits(ctx, commits)
246247

247248
ctx.Data["Username"] = ctx.Repo.Owner.Name
248249
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
@@ -353,6 +354,9 @@ func Diff(ctx *context.Context) {
353354
if err != nil {
354355
log.Error("GetLatestCommitStatus: %v", err)
355356
}
357+
if !ctx.Repo.CanRead(unit_model.TypeActions) {
358+
git_model.CommitStatusesHideActionsURL(ctx, statuses)
359+
}
356360

357361
ctx.Data["CommitStatus"] = git_model.CalcCommitStatus(statuses)
358362
ctx.Data["CommitStatuses"] = statuses
@@ -433,3 +437,14 @@ func RawDiff(ctx *context.Context) {
433437
return
434438
}
435439
}
440+
441+
func processGitCommits(ctx *context.Context, gitCommits []*git.Commit) []*git_model.SignCommitWithStatuses {
442+
commits := git_model.ConvertFromGitCommit(ctx, gitCommits, ctx.Repo.Repository)
443+
if !ctx.Repo.CanRead(unit_model.TypeActions) {
444+
for _, commit := range commits {
445+
commit.Status.HideActionsURL(ctx)
446+
git_model.CommitStatusesHideActionsURL(ctx, commit.Statuses)
447+
}
448+
}
449+
return commits
450+
}

routers/web/repo/compare.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ func PrepareCompareDiff(
643643
return false
644644
}
645645

646-
commits := git_model.ConvertFromGitCommit(ctx, ci.CompareInfo.Commits, ci.HeadRepo)
646+
commits := processGitCommits(ctx, ci.CompareInfo.Commits)
647647
ctx.Data["Commits"] = commits
648648
ctx.Data["CommitCount"] = len(commits)
649649

routers/web/repo/issue.go

+11
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,11 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
339339
ctx.ServerError("GetIssuesAllCommitStatus", err)
340340
return
341341
}
342+
if !ctx.Repo.CanRead(unit.TypeActions) {
343+
for key := range commitStatuses {
344+
git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key])
345+
}
346+
}
342347

343348
if err := issues.LoadAttributes(ctx); err != nil {
344349
ctx.ServerError("issues.LoadAttributes", err)
@@ -1757,6 +1762,12 @@ func ViewIssue(ctx *context.Context) {
17571762
ctx.ServerError("LoadPushCommits", err)
17581763
return
17591764
}
1765+
if !ctx.Repo.CanRead(unit.TypeActions) {
1766+
for _, commit := range comment.Commits {
1767+
commit.Status.HideActionsURL(ctx)
1768+
git_model.CommitStatusesHideActionsURL(ctx, commit.Statuses)
1769+
}
1770+
}
17601771
} else if comment.Type == issues_model.CommentTypeAddTimeManual ||
17611772
comment.Type == issues_model.CommentTypeStopTracking ||
17621773
comment.Type == issues_model.CommentTypeDeleteTimeManual {

routers/web/repo/pull.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,10 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue)
283283
ctx.ServerError("GetLatestCommitStatus", err)
284284
return nil
285285
}
286+
if !ctx.Repo.CanRead(unit.TypeActions) {
287+
git_model.CommitStatusesHideActionsURL(ctx, commitStatuses)
288+
}
289+
286290
if len(commitStatuses) != 0 {
287291
ctx.Data["LatestCommitStatuses"] = commitStatuses
288292
ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(commitStatuses)
@@ -345,6 +349,10 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C
345349
ctx.ServerError("GetLatestCommitStatus", err)
346350
return nil
347351
}
352+
if !ctx.Repo.CanRead(unit.TypeActions) {
353+
git_model.CommitStatusesHideActionsURL(ctx, commitStatuses)
354+
}
355+
348356
if len(commitStatuses) > 0 {
349357
ctx.Data["LatestCommitStatuses"] = commitStatuses
350358
ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(commitStatuses)
@@ -437,6 +445,10 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C
437445
ctx.ServerError("GetLatestCommitStatus", err)
438446
return nil
439447
}
448+
if !ctx.Repo.CanRead(unit.TypeActions) {
449+
git_model.CommitStatusesHideActionsURL(ctx, commitStatuses)
450+
}
451+
440452
if len(commitStatuses) > 0 {
441453
ctx.Data["LatestCommitStatuses"] = commitStatuses
442454
ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(commitStatuses)
@@ -603,7 +615,7 @@ func ViewPullCommits(ctx *context.Context) {
603615
ctx.Data["Username"] = ctx.Repo.Owner.Name
604616
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
605617

606-
commits := git_model.ConvertFromGitCommit(ctx, prInfo.Commits, ctx.Repo.Repository)
618+
commits := processGitCommits(ctx, prInfo.Commits)
607619
ctx.Data["Commits"] = commits
608620
ctx.Data["CommitCount"] = len(commits)
609621

routers/web/repo/repo.go

+3
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,9 @@ func SearchRepo(ctx *context.Context) {
656656
ctx.JSON(http.StatusInternalServerError, nil)
657657
return
658658
}
659+
if !ctx.Repo.CanRead(unit.TypeActions) {
660+
git_model.CommitStatusesHideActionsURL(ctx, latestCommitStatuses)
661+
}
659662

660663
results := make([]*repo_service.WebSearchRepository, len(repos))
661664
for i, repo := range repos {

routers/web/repo/view.go

+3
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,9 @@ func loadLatestCommitData(ctx *context.Context, latestCommit *git.Commit) bool {
363363
if err != nil {
364364
log.Error("GetLatestCommitStatus: %v", err)
365365
}
366+
if !ctx.Repo.CanRead(unit_model.TypeActions) {
367+
git_model.CommitStatusesHideActionsURL(ctx, statuses)
368+
}
366369

367370
ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(statuses)
368371
ctx.Data["LatestCommitStatuses"] = statuses

routers/web/user/home.go

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
activities_model "code.gitea.io/gitea/models/activities"
1818
asymkey_model "code.gitea.io/gitea/models/asymkey"
1919
"code.gitea.io/gitea/models/db"
20+
git_model "code.gitea.io/gitea/models/git"
2021
issues_model "code.gitea.io/gitea/models/issues"
2122
"code.gitea.io/gitea/models/organization"
2223
repo_model "code.gitea.io/gitea/models/repo"
@@ -568,6 +569,11 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
568569
ctx.ServerError("GetIssuesLastCommitStatus", err)
569570
return
570571
}
572+
if !ctx.Repo.CanRead(unit.TypeActions) {
573+
for key := range commitStatuses {
574+
git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key])
575+
}
576+
}
571577

572578
// -------------------------------
573579
// Fill stats to post to ctx.Data.

routers/web/user/notification.go

+7
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import (
1313

1414
activities_model "code.gitea.io/gitea/models/activities"
1515
"code.gitea.io/gitea/models/db"
16+
git_model "code.gitea.io/gitea/models/git"
1617
issues_model "code.gitea.io/gitea/models/issues"
1718
repo_model "code.gitea.io/gitea/models/repo"
19+
"code.gitea.io/gitea/models/unit"
1820
"code.gitea.io/gitea/modules/base"
1921
"code.gitea.io/gitea/modules/log"
2022
"code.gitea.io/gitea/modules/optional"
@@ -303,6 +305,11 @@ func NotificationSubscriptions(ctx *context.Context) {
303305
ctx.ServerError("GetIssuesAllCommitStatus", err)
304306
return
305307
}
308+
if !ctx.Repo.CanRead(unit.TypeActions) {
309+
for key := range commitStatuses {
310+
git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key])
311+
}
312+
}
306313
ctx.Data["CommitLastStatus"] = lastStatus
307314
ctx.Data["CommitStatuses"] = commitStatuses
308315
ctx.Data["Issues"] = issues

0 commit comments

Comments
 (0)