mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-27 00:23:41 +09:00 
			
		
		
		
	Fix nuget/conan/container packages upload bugs (#31967)
This commit is contained in:
		| @@ -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) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user