mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-08 14:03:24 +09:00
fix(api): accept fully-qualified refs in contents API (#38650)
`GET/POST` repository contents endpoints resolve the `ref` query parameter through `ResolveRefCommit`, which previously only accepted short branch/tag names or commit IDs. Clients that pass fully-qualified Git refs (GitHub-compatible), e.g. `ref=refs%2Fheads%2Fmain` or `ref=refs%2Ftags%2Fv1.0`, received 404 "object does not exist". This change accepts fully-qualified **`refs/heads/*`** and **`refs/tags/*`** only, then falls back to the existing short-name and SHA logic. Other `refs/*` prefixes (e.g. `refs/pull/`, `refs/for/`) are rejected. Fixes #38197 --------- Co-authored-by: roman s <roman.sukach@dust-labs.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
co-authored by
roman s
wxiaoguang
parent
4da9b59414
commit
cebdc90ed9
@@ -63,33 +63,50 @@ func TestAPIGetRequestedFiles(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/file-contents?body="+url.QueryEscape(string(reqBodyParam)))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
ret := DecodeJSON(t, resp, []*api.ContentsResponse{})
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents(repo1.DefaultBranch, "branch", lastCommit.ID.String())}
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("master", "refs/heads/master", lastCommit.ID.String())}
|
||||
assert.Equal(t, expected, ret)
|
||||
})
|
||||
t.Run("User2NoRef", func(t *testing.T) {
|
||||
ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents", []string{"README.md"})
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents(repo1.DefaultBranch, "branch", lastCommit.ID.String())}
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("master", "refs/heads/master", lastCommit.ID.String())}
|
||||
assert.Equal(t, expected, ret)
|
||||
})
|
||||
t.Run("User2RefBranch", func(t *testing.T) {
|
||||
ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=master", []string{"README.md"})
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents(repo1.DefaultBranch, "branch", lastCommit.ID.String())}
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("master", "refs/heads/master", lastCommit.ID.String())}
|
||||
assert.Equal(t, expected, ret)
|
||||
})
|
||||
t.Run("User2RefTag", func(t *testing.T) {
|
||||
ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=v1.1", []string{"README.md"})
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("v1.1", "tag", lastCommit.ID.String())}
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("v1.1", "refs/tags/v1.1", lastCommit.ID.String())}
|
||||
assert.Equal(t, expected, ret)
|
||||
})
|
||||
t.Run("User2RefCommit", func(t *testing.T) {
|
||||
ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=65f1bf27bc3bf70f64657658635e66094edbcb4d", []string{"README.md"})
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("65f1bf27bc3bf70f64657658635e66094edbcb4d", "commit", lastCommit.ID.String())}
|
||||
commitID := "65f1bf27bc3bf70f64657658635e66094edbcb4d"
|
||||
ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref="+commitID, []string{"README.md"})
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents(commitID, git.RefNameFromCommit(commitID), lastCommit.ID.String())}
|
||||
assert.Equal(t, expected, ret)
|
||||
})
|
||||
t.Run("User2RefNotExist", func(t *testing.T) {
|
||||
ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=not-exist", []string{"README.md"}, http.StatusNotFound)
|
||||
assert.Empty(t, ret)
|
||||
})
|
||||
t.Run("User2RefFullBranch", func(t *testing.T) {
|
||||
ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=refs/heads/master", []string{"README.md"})
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("refs/heads/master", "refs/heads/master", lastCommit.ID.String())}
|
||||
assert.Equal(t, expected, ret)
|
||||
})
|
||||
t.Run("User2RefFullTag", func(t *testing.T) {
|
||||
ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref=refs/tags/v1.1", []string{"README.md"})
|
||||
expected := []*api.ContentsResponse{getExpectedContentsResponseForContents("refs/tags/v1.1", "refs/tags/v1.1", lastCommit.ID.String())}
|
||||
assert.Equal(t, expected, ret)
|
||||
})
|
||||
t.Run("User2RefInternalPullRejected", func(t *testing.T) {
|
||||
// repo1 has refs/pull/2/head in fixtures; contents API must not resolve it
|
||||
assert.True(t, git.IsReferenceExist(t.Context(), gitRepo, "refs/pull/2/head"))
|
||||
ret := requestFiles(t, "/api/v1/repos/user2/repo1/file-contents?ref="+url.QueryEscape("refs/pull/2/head"), []string{"README.md"}, http.StatusNotFound)
|
||||
assert.Empty(t, ret)
|
||||
})
|
||||
|
||||
t.Run("PermissionCheck", func(t *testing.T) {
|
||||
filesOptions := &api.GetFilesOptions{Files: []string{"README.md"}}
|
||||
|
||||
Reference in New Issue
Block a user