forked from NYANDEV/forgejo
859c2275db
Refs: https://forgejo.org/2023-11-release-v1-20-5-1/#api-and-web-endpoint-vulnerable-to-manually-crafted-identifiers (cherry picked from commit 78dcbb62fe87abe044034d880c9e8c22b44c2c98) (cherry picked from commit 6707c08c1791926060a7735529f1945650030257) (cherry picked from commit 68da5a9cd82415caedac15a07e38206f7bd6fbde) (cherry picked from commit c27fb08cb00f130870d6059a0ebb67b505a3c252) (cherry picked from commit f15a2c558a74aaf954550c71974593bf012004db) (cherry picked from commit 8eb3ae693922fdb65a185ee63703b866d10fa60a) (cherry picked from commit d54d5952f25828e84f7024aae6e62d1a18b788ae) (cherry picked from commit ce22d57485ed718612cd0e40979cc591a5e18126) (cherry picked from commit bfc110ba3303b4d2664638712435cc8d47906da0) (cherry picked from commit 1fb3d555d972ad72d257c7d00e71148c88926e5d)
309 lines
10 KiB
Go
309 lines
10 KiB
Go
// Copyright 2017 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package integration
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
"code.gitea.io/gitea/models/unittest"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
"code.gitea.io/gitea/modules/test"
|
|
"code.gitea.io/gitea/modules/translation"
|
|
"code.gitea.io/gitea/tests"
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func createNewRelease(t *testing.T, session *TestSession, repoURL, tag, title string, preRelease, draft bool) {
|
|
createNewReleaseTarget(t, session, repoURL, tag, title, "master", preRelease, draft)
|
|
}
|
|
|
|
func createNewReleaseTarget(t *testing.T, session *TestSession, repoURL, tag, title, target string, preRelease, draft bool) {
|
|
req := NewRequest(t, "GET", repoURL+"/releases/new")
|
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
|
|
|
link, exists := htmlDoc.doc.Find("form.ui.form").Attr("action")
|
|
assert.True(t, exists, "The template has changed")
|
|
|
|
postData := map[string]string{
|
|
"_csrf": htmlDoc.GetCSRF(),
|
|
"tag_name": tag,
|
|
"tag_target": target,
|
|
"title": title,
|
|
"content": "",
|
|
}
|
|
if preRelease {
|
|
postData["prerelease"] = "on"
|
|
}
|
|
if draft {
|
|
postData["draft"] = "Save Draft"
|
|
}
|
|
req = NewRequestWithValues(t, "POST", link, postData)
|
|
|
|
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
|
|
|
test.RedirectURL(resp) // check that redirect URL exists
|
|
}
|
|
|
|
func checkLatestReleaseAndCount(t *testing.T, session *TestSession, repoURL, version, label string, count int) {
|
|
req := NewRequest(t, "GET", repoURL+"/releases")
|
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
|
labelText := htmlDoc.doc.Find("#release-list > li .detail .label").First().Text()
|
|
assert.EqualValues(t, label, labelText)
|
|
titleText := htmlDoc.doc.Find("#release-list > li .detail h4 a").First().Text()
|
|
assert.EqualValues(t, version, titleText)
|
|
|
|
releaseList := htmlDoc.doc.Find("#release-list > li")
|
|
assert.EqualValues(t, count, releaseList.Length())
|
|
}
|
|
|
|
func TestViewReleases(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
session := loginUser(t, "user2")
|
|
req := NewRequest(t, "GET", "/user2/repo1/releases")
|
|
session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
// if CI is to slow this test fail, so lets wait a bit
|
|
time.Sleep(time.Millisecond * 100)
|
|
}
|
|
|
|
func TestViewReleasesNoLogin(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
req := NewRequest(t, "GET", "/user2/repo1/releases")
|
|
MakeRequest(t, req, http.StatusOK)
|
|
}
|
|
|
|
func TestCreateRelease(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
session := loginUser(t, "user2")
|
|
createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, false)
|
|
|
|
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", translation.NewLocale("en-US").Tr("repo.release.stable"), 4)
|
|
}
|
|
|
|
func TestDeleteRelease(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 57, OwnerName: "user2", LowerName: "repo-release"})
|
|
release := unittest.AssertExistsAndLoadBean(t, &repo_model.Release{TagName: "v2.0"})
|
|
assert.False(t, release.IsTag)
|
|
|
|
// Using the ID of a comment that does not belong to the repository must fail
|
|
session5 := loginUser(t, "user5")
|
|
otherRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user5", LowerName: "repo4"})
|
|
|
|
req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/releases/delete?id=%d", otherRepo.Link(), release.ID), map[string]string{
|
|
"_csrf": GetCSRF(t, session5, otherRepo.Link()),
|
|
})
|
|
session5.MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
session := loginUser(t, "user2")
|
|
req = NewRequestWithValues(t, "POST", fmt.Sprintf("%s/releases/delete?id=%d", repo.Link(), release.ID), map[string]string{
|
|
"_csrf": GetCSRF(t, session, repo.Link()),
|
|
})
|
|
session.MakeRequest(t, req, http.StatusOK)
|
|
release = unittest.AssertExistsAndLoadBean(t, &repo_model.Release{ID: release.ID})
|
|
|
|
if assert.True(t, release.IsTag) {
|
|
req = NewRequestWithValues(t, "POST", fmt.Sprintf("%s/tags/delete?id=%d", otherRepo.Link(), release.ID), map[string]string{
|
|
"_csrf": GetCSRF(t, session5, otherRepo.Link()),
|
|
})
|
|
session5.MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
req = NewRequestWithValues(t, "POST", fmt.Sprintf("%s/tags/delete?id=%d", repo.Link(), release.ID), map[string]string{
|
|
"_csrf": GetCSRF(t, session, repo.Link()),
|
|
})
|
|
session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
unittest.AssertNotExistsBean(t, &repo_model.Release{ID: release.ID})
|
|
}
|
|
}
|
|
|
|
func TestCreateReleasePreRelease(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
session := loginUser(t, "user2")
|
|
createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", true, false)
|
|
|
|
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", translation.NewLocale("en-US").Tr("repo.release.prerelease"), 4)
|
|
}
|
|
|
|
func TestCreateReleaseDraft(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
session := loginUser(t, "user2")
|
|
createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, true)
|
|
|
|
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", translation.NewLocale("en-US").Tr("repo.release.draft"), 4)
|
|
}
|
|
|
|
func TestCreateReleasePaging(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
oldAPIDefaultNum := setting.API.DefaultPagingNum
|
|
defer func() {
|
|
setting.API.DefaultPagingNum = oldAPIDefaultNum
|
|
}()
|
|
setting.API.DefaultPagingNum = 10
|
|
|
|
session := loginUser(t, "user2")
|
|
// Create enough releases to have paging
|
|
for i := 0; i < 12; i++ {
|
|
version := fmt.Sprintf("v0.0.%d", i)
|
|
createNewRelease(t, session, "/user2/repo1", version, version, false, false)
|
|
}
|
|
createNewRelease(t, session, "/user2/repo1", "v0.0.12", "v0.0.12", false, true)
|
|
|
|
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.12", translation.NewLocale("en-US").Tr("repo.release.draft"), 10)
|
|
|
|
// Check that user4 does not see draft and still see 10 latest releases
|
|
session2 := loginUser(t, "user4")
|
|
checkLatestReleaseAndCount(t, session2, "/user2/repo1", "v0.0.11", translation.NewLocale("en-US").Tr("repo.release.stable"), 10)
|
|
}
|
|
|
|
func TestViewReleaseListNoLogin(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 57, OwnerName: "user2", LowerName: "repo-release"})
|
|
|
|
link := repo.Link() + "/releases"
|
|
|
|
req := NewRequest(t, "GET", link)
|
|
rsp := MakeRequest(t, req, http.StatusOK)
|
|
|
|
htmlDoc := NewHTMLParser(t, rsp.Body)
|
|
releases := htmlDoc.Find("#release-list li.ui.grid")
|
|
assert.Equal(t, 5, releases.Length())
|
|
|
|
links := make([]string, 0, 5)
|
|
commitsToMain := make([]string, 0, 5)
|
|
releases.Each(func(i int, s *goquery.Selection) {
|
|
link, exist := s.Find(".release-list-title a").Attr("href")
|
|
if !exist {
|
|
return
|
|
}
|
|
links = append(links, link)
|
|
|
|
commitsToMain = append(commitsToMain, s.Find(".ahead > a").Text())
|
|
})
|
|
|
|
assert.EqualValues(t, []string{
|
|
"/user2/repo-release/releases/tag/empty-target-branch",
|
|
"/user2/repo-release/releases/tag/non-existing-target-branch",
|
|
"/user2/repo-release/releases/tag/v2.0",
|
|
"/user2/repo-release/releases/tag/v1.1",
|
|
"/user2/repo-release/releases/tag/v1.0",
|
|
}, links)
|
|
assert.EqualValues(t, []string{
|
|
"1 commits", // like v1.1
|
|
"1 commits", // like v1.1
|
|
"0 commits",
|
|
"1 commits", // should be 3 commits ahead and 2 commits behind, but not implemented yet
|
|
"3 commits",
|
|
}, commitsToMain)
|
|
}
|
|
|
|
func TestViewSingleReleaseNoLogin(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
req := NewRequest(t, "GET", "/user2/repo-release/releases/tag/v1.0")
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
|
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
|
// check the "number of commits to main since this release"
|
|
releaseList := htmlDoc.doc.Find("#release-list .ahead > a")
|
|
assert.EqualValues(t, 1, releaseList.Length())
|
|
assert.EqualValues(t, "3 commits", releaseList.First().Text())
|
|
}
|
|
|
|
func TestViewReleaseListLogin(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
|
|
link := repo.Link() + "/releases"
|
|
|
|
session := loginUser(t, "user1")
|
|
req := NewRequest(t, "GET", link)
|
|
rsp := session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
htmlDoc := NewHTMLParser(t, rsp.Body)
|
|
releases := htmlDoc.Find("#release-list li.ui.grid")
|
|
assert.Equal(t, 3, releases.Length())
|
|
|
|
links := make([]string, 0, 5)
|
|
releases.Each(func(i int, s *goquery.Selection) {
|
|
link, exist := s.Find(".release-list-title a").Attr("href")
|
|
if !exist {
|
|
return
|
|
}
|
|
links = append(links, link)
|
|
})
|
|
|
|
assert.EqualValues(t, []string{
|
|
"/user2/repo1/releases/tag/draft-release",
|
|
"/user2/repo1/releases/tag/v1.0",
|
|
"/user2/repo1/releases/tag/v1.1",
|
|
}, links)
|
|
}
|
|
|
|
func TestReleaseOnCommit(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
session := loginUser(t, "user2")
|
|
createNewReleaseTarget(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", "65f1bf27bc3bf70f64657658635e66094edbcb4d", false, false)
|
|
|
|
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", translation.NewLocale("en-US").Tr("repo.release.stable"), 4)
|
|
}
|
|
|
|
func TestViewTagsList(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
|
|
link := repo.Link() + "/tags"
|
|
|
|
session := loginUser(t, "user1")
|
|
req := NewRequest(t, "GET", link)
|
|
rsp := session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
htmlDoc := NewHTMLParser(t, rsp.Body)
|
|
tags := htmlDoc.Find(".tag-list tr")
|
|
assert.Equal(t, 3, tags.Length())
|
|
|
|
tagNames := make([]string, 0, 5)
|
|
tags.Each(func(i int, s *goquery.Selection) {
|
|
tagNames = append(tagNames, s.Find(".tag a.gt-df.gt-ac").Text())
|
|
})
|
|
|
|
assert.EqualValues(t, []string{"v1.0", "delete-tag", "v1.1"}, tagNames)
|
|
}
|
|
|
|
func TestDownloadReleaseAttachment(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
tests.PrepareAttachmentsStorage(t)
|
|
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
|
|
|
url := repo.Link() + "/releases/download/v1.1/README.md"
|
|
|
|
req := NewRequest(t, "GET", url)
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
req = NewRequest(t, "GET", url)
|
|
session := loginUser(t, "user2")
|
|
session.MakeRequest(t, req, http.StatusOK)
|
|
}
|