Fix nuget/conan/container packages upload bugs (#31967) (#31982)

Backport #31967 by @lunny

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
Giteabot 2024-09-05 15:34:41 +08:00 committed by GitHub
parent 244fb11c6b
commit b39aa8528b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 512 additions and 90 deletions

View file

@ -26,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/packages/nuget"
packageService "code.gitea.io/gitea/services/packages"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@ -81,7 +82,9 @@ func TestPackageNuGet(t *testing.T) {
}
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
token := getUserToken(t, user.Name, auth_model.AccessTokenScopeWritePackage)
writeToken := getUserToken(t, user.Name, auth_model.AccessTokenScopeWritePackage)
readToken := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadPackage)
badToken := getUserToken(t, user.Name, auth_model.AccessTokenScopeReadNotification)
packageName := "test.package"
packageVersion := "1.0.3"
@ -127,34 +130,44 @@ func TestPackageNuGet(t *testing.T) {
privateUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{Visibility: structs.VisibleTypePrivate})
cases := []struct {
Owner string
UseBasicAuth bool
UseTokenAuth bool
Owner string
UseBasicAuth bool
token string
expectedStatus int
}{
{privateUser.Name, false, false},
{privateUser.Name, true, false},
{privateUser.Name, false, true},
{user.Name, false, false},
{user.Name, true, false},
{user.Name, false, true},
{privateUser.Name, false, "", http.StatusOK},
{privateUser.Name, true, "", http.StatusOK},
{privateUser.Name, false, writeToken, http.StatusOK},
{privateUser.Name, false, readToken, http.StatusOK},
{privateUser.Name, false, badToken, http.StatusOK},
{user.Name, false, "", http.StatusOK},
{user.Name, true, "", http.StatusOK},
{user.Name, false, writeToken, http.StatusOK},
{user.Name, false, readToken, http.StatusOK},
{user.Name, false, badToken, http.StatusOK},
}
for _, c := range cases {
url := fmt.Sprintf("/api/packages/%s/nuget", c.Owner)
t.Run(c.Owner, func(t *testing.T) {
url := fmt.Sprintf("/api/packages/%s/nuget", c.Owner)
req := NewRequest(t, "GET", url)
if c.UseBasicAuth {
req.AddBasicAuth(user.Name)
} else if c.UseTokenAuth {
addNuGetAPIKeyHeader(req, token)
}
resp := MakeRequest(t, req, http.StatusOK)
req := NewRequest(t, "GET", url)
if c.UseBasicAuth {
req.AddBasicAuth(user.Name)
} else if c.token != "" {
addNuGetAPIKeyHeader(req, c.token)
}
resp := MakeRequest(t, req, c.expectedStatus)
if c.expectedStatus != http.StatusOK {
return
}
var result nuget.ServiceIndexResponseV2
decodeXML(t, resp, &result)
var result nuget.ServiceIndexResponseV2
decodeXML(t, resp, &result)
assert.Equal(t, setting.AppURL+url[1:], result.Base)
assert.Equal(t, "Packages", result.Workspace.Collection.Href)
assert.Equal(t, setting.AppURL+url[1:], result.Base)
assert.Equal(t, "Packages", result.Workspace.Collection.Href)
})
}
})
@ -164,56 +177,67 @@ func TestPackageNuGet(t *testing.T) {
privateUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{Visibility: structs.VisibleTypePrivate})
cases := []struct {
Owner string
UseBasicAuth bool
UseTokenAuth bool
Owner string
UseBasicAuth bool
token string
expectedStatus int
}{
{privateUser.Name, false, false},
{privateUser.Name, true, false},
{privateUser.Name, false, true},
{user.Name, false, false},
{user.Name, true, false},
{user.Name, false, true},
{privateUser.Name, false, "", http.StatusOK},
{privateUser.Name, true, "", http.StatusOK},
{privateUser.Name, false, writeToken, http.StatusOK},
{privateUser.Name, false, readToken, http.StatusOK},
{privateUser.Name, false, badToken, http.StatusOK},
{user.Name, false, "", http.StatusOK},
{user.Name, true, "", http.StatusOK},
{user.Name, false, writeToken, http.StatusOK},
{user.Name, false, readToken, http.StatusOK},
{user.Name, false, badToken, http.StatusOK},
}
for _, c := range cases {
url := fmt.Sprintf("/api/packages/%s/nuget", c.Owner)
t.Run(c.Owner, func(t *testing.T) {
url := fmt.Sprintf("/api/packages/%s/nuget", c.Owner)
req := NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url))
if c.UseBasicAuth {
req.AddBasicAuth(user.Name)
} else if c.UseTokenAuth {
addNuGetAPIKeyHeader(req, token)
}
resp := MakeRequest(t, req, http.StatusOK)
var result nuget.ServiceIndexResponseV3
DecodeJSON(t, resp, &result)
assert.Equal(t, "3.0.0", result.Version)
assert.NotEmpty(t, result.Resources)
root := setting.AppURL + url[1:]
for _, r := range result.Resources {
switch r.Type {
case "SearchQueryService":
fallthrough
case "SearchQueryService/3.0.0-beta":
fallthrough
case "SearchQueryService/3.0.0-rc":
assert.Equal(t, root+"/query", r.ID)
case "RegistrationsBaseUrl":
fallthrough
case "RegistrationsBaseUrl/3.0.0-beta":
fallthrough
case "RegistrationsBaseUrl/3.0.0-rc":
assert.Equal(t, root+"/registration", r.ID)
case "PackageBaseAddress/3.0.0":
assert.Equal(t, root+"/package", r.ID)
case "PackagePublish/2.0.0":
assert.Equal(t, root, r.ID)
req := NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url))
if c.UseBasicAuth {
req.AddBasicAuth(user.Name)
} else if c.token != "" {
addNuGetAPIKeyHeader(req, c.token)
}
}
resp := MakeRequest(t, req, c.expectedStatus)
if c.expectedStatus != http.StatusOK {
return
}
var result nuget.ServiceIndexResponseV3
DecodeJSON(t, resp, &result)
assert.Equal(t, "3.0.0", result.Version)
assert.NotEmpty(t, result.Resources)
root := setting.AppURL + url[1:]
for _, r := range result.Resources {
switch r.Type {
case "SearchQueryService":
fallthrough
case "SearchQueryService/3.0.0-beta":
fallthrough
case "SearchQueryService/3.0.0-rc":
assert.Equal(t, root+"/query", r.ID)
case "RegistrationsBaseUrl":
fallthrough
case "RegistrationsBaseUrl/3.0.0-beta":
fallthrough
case "RegistrationsBaseUrl/3.0.0-rc":
assert.Equal(t, root+"/registration", r.ID)
case "PackageBaseAddress/3.0.0":
assert.Equal(t, root+"/package", r.ID)
case "PackagePublish/2.0.0":
assert.Equal(t, root, r.ID)
}
}
})
}
})
})
@ -222,6 +246,7 @@ func TestPackageNuGet(t *testing.T) {
t.Run("DependencyPackage", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
// create with username/password
req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusCreated)
@ -258,6 +283,52 @@ func TestPackageNuGet(t *testing.T) {
req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusConflict)
// delete the package
assert.NoError(t, packageService.DeletePackageVersionAndReferences(db.DefaultContext, pvs[0]))
// create failure with token without write access
req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
AddTokenAuth(readToken)
MakeRequest(t, req, http.StatusUnauthorized)
// create with token
req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
AddTokenAuth(writeToken)
MakeRequest(t, req, http.StatusCreated)
pvs, err = packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeNuGet)
assert.NoError(t, err)
assert.Len(t, pvs, 1, "Should have one version")
pd, err = packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
assert.NoError(t, err)
assert.NotNil(t, pd.SemVer)
assert.IsType(t, &nuget_module.Metadata{}, pd.Metadata)
assert.Equal(t, packageName, pd.Package.Name)
assert.Equal(t, packageVersion, pd.Version.Version)
pfs, err = packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID)
assert.NoError(t, err)
assert.Len(t, pfs, 2, "Should have 2 files: nuget and nuspec")
for _, pf := range pfs {
switch pf.Name {
case fmt.Sprintf("%s.%s.nupkg", packageName, packageVersion):
assert.True(t, pf.IsLead)
pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID)
assert.NoError(t, err)
assert.Equal(t, int64(len(content)), pb.Size)
case fmt.Sprintf("%s.nuspec", packageName):
assert.False(t, pf.IsLead)
default:
assert.Fail(t, "unexpected filename: %v", pf.Name)
}
}
req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusConflict)
})
t.Run("SymbolPackage", func(t *testing.T) {