mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-23 18:54:39 +02:00
Several `/repos/{owner}/{repo}/issues/{index}/...` API endpoints load
the issue by index without checking
`CanReadIssuesOrPulls(issue.IsPull)`, unlike `GetIssue`,
`ListIssueComments` and `GetIssueReactions`. The route group's
`mustEnableIssuesOrPulls` passes when the caller can read either unit,
so someone who can read issues but not pull requests (a team with only
the Issues unit, or per-unit anonymous access on a public repo) can read
a pull request's whole conversation through `/timeline`, plus its
labels, subscribers, attachments and tracked times, and can subscribe to
it. The reverse holds for issues.
These handlers now return 404 in that case, like their siblings.
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
45 lines
1.3 KiB
Go
45 lines
1.3 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package repo
|
|
|
|
import (
|
|
"net/http"
|
|
"testing"
|
|
|
|
perm_model "gitea.dev/models/perm"
|
|
access_model "gitea.dev/models/perm/access"
|
|
repo_model "gitea.dev/models/repo"
|
|
"gitea.dev/models/unit"
|
|
"gitea.dev/models/unittest"
|
|
"gitea.dev/services/context"
|
|
"gitea.dev/services/contexttest"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestIssueReadEndpointsRequireUnitPermission(t *testing.T) {
|
|
unittest.PrepareTestEnv(t)
|
|
|
|
for name, handler := range map[string]func(*context.APIContext){
|
|
"timeline": ListIssueCommentsAndTimeline,
|
|
"labels": ListIssueLabels,
|
|
"subscribers": GetIssueSubscribers,
|
|
"attachments": ListIssueAttachments,
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
request := func(index string) int {
|
|
ctx, resp := contexttest.MockAPIContext(t, "user2/repo1")
|
|
contexttest.LoadRepo(t, ctx, 1)
|
|
ctx.Repo.Permission = access_model.Permission{}
|
|
ctx.Repo.Permission.SetUnitsWithDefaultAccessMode([]*repo_model.RepoUnit{{Type: unit.TypeIssues}}, perm_model.AccessModeRead)
|
|
ctx.SetPathParam("index", index)
|
|
handler(ctx)
|
|
return resp.Code
|
|
}
|
|
assert.Equal(t, http.StatusOK, request("1"))
|
|
assert.Equal(t, http.StatusNotFound, request("2"))
|
|
})
|
|
}
|
|
}
|