diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 244298790b5..ccdd250a3b2 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -15,6 +15,7 @@ import ( activities_model "gitea.dev/models/activities" "gitea.dev/models/renderhelper" repo_model "gitea.dev/models/repo" + "gitea.dev/models/unit" "gitea.dev/modules/markup" "gitea.dev/modules/markup/markdown" "gitea.dev/modules/setting" @@ -276,27 +277,29 @@ func GetFeedType(name string, req *http.Request) (showFeed bool, feedType string // feedActionsToFeedItems convert gitea's Repo's Releases to feeds Item func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release) (items []*feeds.Item, err error) { + canReadReleases := ctx.Repo.Permission.CanRead(unit.TypeReleases) for _, rel := range releases { err := rel.LoadAttributes(ctx) if err != nil { return nil, err } - var title string var content template.HTML - - if rel.IsTag { - title = rel.TagName - } else { - title = rel.Title - } - + title := rel.TagName link := &feeds.Link{Href: rel.HTMLURL()} - rctx := renderhelper.NewRenderContextRepoComment(ctx, rel.Repo).WithUseAbsoluteLink(true) - content, err = markdown.RenderString(rctx, - rel.Note) - if err != nil { - return nil, err + + if !canReadReleases { + // the tags feed only requires code access, so list releases as plain tags like the tags page does + link.Href = rel.Repo.HTMLURL() + "/src/tag/" + util.PathEscapeSegments(rel.TagName) + } else { + if !rel.IsTag { + title = rel.Title + } + rctx := renderhelper.NewRenderContextRepoComment(ctx, rel.Repo).WithUseAbsoluteLink(true) + content, err = markdown.RenderString(rctx, rel.Note) + if err != nil { + return nil, err + } } items = append(items, &feeds.Item{ diff --git a/tests/integration/feed_repo_test.go b/tests/integration/feed_repo_test.go index ffe908c74bd..dcce2cfdb11 100644 --- a/tests/integration/feed_repo_test.go +++ b/tests/integration/feed_repo_test.go @@ -9,9 +9,14 @@ import ( "testing" auth_model "gitea.dev/models/auth" + repo_model "gitea.dev/models/repo" + unit_model "gitea.dev/models/unit" + "gitea.dev/models/unittest" + repo_service "gitea.dev/services/repository" "gitea.dev/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestFeedRepo(t *testing.T) { @@ -33,6 +38,19 @@ func TestFeedRepo(t *testing.T) { assert.Equal(t, "issue5", rss.Channel.Items[0].Description) assert.NotEmpty(t, rss.Channel.Items[0].PubDate) }) + + t.Run("TagsWithoutReleasesAccess", func(t *testing.T) { + defer tests.PrepareTestEnv(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.TypeReleases})) + + resp := MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/tags.rss"), http.StatusOK) + data := resp.Body.String() + assert.Contains(t, data, "/user2/repo1/src/tag/v1.0") + assert.NotContains(t, data, "pre-release") + assert.NotContains(t, data, "some text for a pre release") + }) } // TestFeedRepoContentTokenScopes ensures repository feed endpoints enforce the