diff --git a/routers/web/feed/branch.go b/routers/web/feed/branch.go index 76184d64438..6793bb6a695 100644 --- a/routers/web/feed/branch.go +++ b/routers/web/feed/branch.go @@ -13,8 +13,7 @@ import ( "github.com/gorilla/feeds" ) -// ShowBranchFeed shows tags and/or releases on the repo as RSS / Atom feed -func ShowBranchFeed(ctx *context.Context, repo *repo.Repository, formatType string) { +func showBranchFeed(ctx *context.Context, repo *repo.Repository, formatType string) { if !checkRepoFeedTokenScope(ctx) { return } diff --git a/routers/web/feed/file.go b/routers/web/feed/file.go index debb6dd4c9c..9ea35a796cc 100644 --- a/routers/web/feed/file.go +++ b/routers/web/feed/file.go @@ -14,8 +14,7 @@ import ( "github.com/gorilla/feeds" ) -// ShowFileFeed shows tags and/or releases on the repo as RSS / Atom feed -func ShowFileFeed(ctx *context.Context, repo *repo.Repository, formatType string) { +func showFileFeed(ctx *context.Context, repo *repo.Repository, formatType string) { if !checkRepoFeedTokenScope(ctx) { return } diff --git a/routers/web/feed/render.go b/routers/web/feed/render.go index d2af9824c4d..daf714c7970 100644 --- a/routers/web/feed/render.go +++ b/routers/web/feed/render.go @@ -19,9 +19,9 @@ func checkRepoFeedTokenScope(ctx *context.Context) bool { // RenderBranchFeed render format for branch or file func RenderBranchFeed(ctx *context.Context, feedType string) { if ctx.Repo.TreePath == "" { - ShowBranchFeed(ctx, ctx.Repo.Repository, feedType) + showBranchFeed(ctx, ctx.Repo.Repository, feedType) } else { - ShowFileFeed(ctx, ctx.Repo.Repository, feedType) + showFileFeed(ctx, ctx.Repo.Repository, feedType) } } diff --git a/routers/web/repo/view_home.go b/routers/web/repo/view_home.go index 2772b5d348b..083218c0d1e 100644 --- a/routers/web/repo/view_home.go +++ b/routers/web/repo/view_home.go @@ -349,10 +349,12 @@ func handleRepoHomeFeed(ctx *context.Context) bool { } if ctx.Link == fmt.Sprintf("%s.%s", ctx.Repo.RepoLink, showFeedType) { feed.ShowRepoFeed(ctx, ctx.Repo.Repository, showFeedType) - } else if ctx.Repo.TreePath == "" { - feed.ShowBranchFeed(ctx, ctx.Repo.Repository, showFeedType) + } else if !ctx.Repo.Permission.CanRead(unit_model.TypeCode) && !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { + // the branch and file feeds list commits, so gate them like RequireUnitReader(TypeCode) on "/rss/branch/*", + // which also admits maintainers of a PR allowing maintainer edits, who can push to its head branch without code read access + ctx.NotFound(nil) } else { - feed.ShowFileFeed(ctx, ctx.Repo.Repository, showFeedType) + feed.RenderBranchFeed(ctx, showFeedType) } return true } diff --git a/tests/integration/feed_user_test.go b/tests/integration/feed_user_test.go index cd6f3527b34..280b21ffd6e 100644 --- a/tests/integration/feed_user_test.go +++ b/tests/integration/feed_user_test.go @@ -153,4 +153,12 @@ func TestFeedUser(t *testing.T) { assert.NotContains(t, data, "pre-release") assert.NotContains(t, data, "some text for a pre release") }) + + t.Run("RepoBranchFeedWithoutCodeAccess", func(t *testing.T) { + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + require.NoError(t, repo_service.UpdateRepositoryUnits(t.Context(), repo, nil, []unit_model.Type{unit_model.TypeCode})) + MakeRequest(t, NewRequest(t, "GET", "/user2/repo1").SetHeader("Accept", "application/rss+xml"), http.StatusNotFound) + MakeRequest(t, NewRequest(t, "GET", "/user2/repo1").SetHeader("Accept", "application/atom+xml"), http.StatusNotFound) + MakeRequest(t, NewRequest(t, "GET", "/user2/repo1.rss"), http.StatusOK) + }) }