mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Add support for NuGet API keys (#20721)
* Add support for NuGet API key. * lint * Apply suggestions from code review Co-authored-by: delvh <dev.lh@web.de> Co-authored-by: delvh <dev.lh@web.de> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
		@@ -47,6 +47,8 @@ For example:
 | 
				
			|||||||
dotnet nuget add source --name gitea --username testuser --password password123 https://gitea.example.com/api/packages/testuser/nuget/index.json
 | 
					dotnet nuget add source --name gitea --username testuser --password password123 https://gitea.example.com/api/packages/testuser/nuget/index.json
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can add the source without credentials and use the [`--api-key`](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-nuget-push) parameter when publishing packages. In this case you need to provide a [personal access token]({{< relref "doc/developers/api-usage.en-us.md#authentication" >}}).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Publish a package
 | 
					## Publish a package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Publish a package by running the following command:
 | 
					Publish a package by running the following command:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,9 +24,16 @@ import (
 | 
				
			|||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addNuGetAPIKeyHeader(request *http.Request, token string) *http.Request {
 | 
				
			||||||
 | 
						request.Header.Set("X-NuGet-ApiKey", token)
 | 
				
			||||||
 | 
						return request
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPackageNuGet(t *testing.T) {
 | 
					func TestPackageNuGet(t *testing.T) {
 | 
				
			||||||
	defer prepareTestEnv(t)()
 | 
						defer prepareTestEnv(t)()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
 | 
						user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
 | 
				
			||||||
 | 
						token := getUserToken(t, user.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	packageName := "test.package"
 | 
						packageName := "test.package"
 | 
				
			||||||
	packageVersion := "1.0.3"
 | 
						packageVersion := "1.0.3"
 | 
				
			||||||
@@ -60,6 +67,10 @@ func TestPackageNuGet(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		req := NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url))
 | 
							req := NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url))
 | 
				
			||||||
		req = AddBasicAuthHeader(req, user.Name)
 | 
							req = AddBasicAuthHeader(req, user.Name)
 | 
				
			||||||
 | 
							MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req = NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url))
 | 
				
			||||||
 | 
							req = addNuGetAPIKeyHeader(req, token)
 | 
				
			||||||
		resp := MakeRequest(t, req, http.StatusOK)
 | 
							resp := MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var result nuget.ServiceIndexResponse
 | 
							var result nuget.ServiceIndexResponse
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,7 @@ func Routes() *web.Route {
 | 
				
			|||||||
	authMethods := []auth.Method{
 | 
						authMethods := []auth.Method{
 | 
				
			||||||
		&auth.OAuth2{},
 | 
							&auth.OAuth2{},
 | 
				
			||||||
		&auth.Basic{},
 | 
							&auth.Basic{},
 | 
				
			||||||
 | 
							&nuget.Auth{},
 | 
				
			||||||
		&conan.Auth{},
 | 
							&conan.Auth{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if setting.Service.EnableReverseProxyAuth {
 | 
						if setting.Service.EnableReverseProxyAuth {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										45
									
								
								routers/api/packages/nuget/auth.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								routers/api/packages/nuget/auth.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					// Copyright 2022 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package nuget
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
 | 
						user_model "code.gitea.io/gitea/models/user"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/timeutil"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/services/auth"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Auth struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *Auth) Name() string {
 | 
				
			||||||
 | 
						return "nuget"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// https://docs.microsoft.com/en-us/nuget/api/package-publish-resource#request-parameters
 | 
				
			||||||
 | 
					func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) *user_model.User {
 | 
				
			||||||
 | 
						token, err := models.GetAccessTokenBySHA(req.Header.Get("X-NuGet-ApiKey"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if !(models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err)) {
 | 
				
			||||||
 | 
								log.Error("GetAccessTokenBySHA: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u, err := user_model.GetUserByID(token.UID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error("GetUserByID:  %v", err)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						token.UpdatedUnix = timeutil.TimeStampNow()
 | 
				
			||||||
 | 
						if err := models.UpdateAccessToken(token); err != nil {
 | 
				
			||||||
 | 
							log.Error("UpdateAccessToken:  %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return u
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user