From 3e07a681a12d8c9d5fb650950a830816e8a8e63a Mon Sep 17 00:00:00 2001 From: Sourabh Awashti Date: Mon, 28 Apr 2025 05:10:07 +0000 Subject: [PATCH] feat:[AH-1231]: changes for switching routes for generic artifacts (#3703) * feat:[AH-1231]: fix checks * feat:[AH-1231]: review changes * feat:[AH-1231]: changes for switching routes for generic artifacts * Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness * Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness * Merge branch 'release/registry-api_1.18.0' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness * feat:[AH-1083]: url fix (#3669) * feat:[AH-1083]: url fix --- cmd/gitness/wire_gen.go | 4 +- .../metadata/get_client_setup_details.go | 8 ++-- registry/app/api/handler/generic/base.go | 43 +++++++++++++++++-- .../app/api/handler/generic/pull_artifact.go | 2 +- .../app/api/handler/generic/push_artifact.go | 2 +- .../app/api/middleware/bandwidth_stats.go | 2 +- registry/app/api/middleware/download_stats.go | 2 +- registry/app/api/router/packages/route.go | 14 ++++-- registry/app/api/wire.go | 3 +- registry/app/pkg/context.go | 16 +++++++ 10 files changed, 77 insertions(+), 19 deletions(-) diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index 29cec164a..79a43b56a 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -537,9 +537,9 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro handler2 := router.MavenHandlerProvider(mavenHandler) genericDBStore := generic.DBStoreProvider(imageRepository, artifactRepository, bandwidthStatRepository, downloadStatRepository, registryRepository) genericController := generic.ControllerProvider(spaceStore, authorizer, fileManager, genericDBStore, transactor) - genericHandler := api2.NewGenericHandlerProvider(spaceStore, genericController, tokenStore, controller, authenticator, provider, authorizer) - handler3 := router.GenericHandlerProvider(genericHandler) packagesHandler := api2.NewPackageHandlerProvider(registryRepository, downloadStatRepository, spaceStore, tokenStore, controller, authenticator, provider, authorizer) + genericHandler := api2.NewGenericHandlerProvider(spaceStore, genericController, tokenStore, controller, authenticator, provider, authorizer, packagesHandler) + handler3 := router.GenericHandlerProvider(genericHandler) packageTagRepository := database2.ProvidePackageTagDao(db) localBase := base.LocalBaseProvider(registryRepository, fileManager, transactor, imageRepository, artifactRepository, nodesRepository, packageTagRepository) pythonLocalRegistry := python.LocalRegistryProvider(localBase, fileManager, upstreamProxyConfigRepository, transactor, registryRepository, imageRepository, artifactRepository, provider) diff --git a/registry/app/api/controller/metadata/get_client_setup_details.go b/registry/app/api/controller/metadata/get_client_setup_details.go index 3268c71c2..3982aea74 100644 --- a/registry/app/api/controller/metadata/get_client_setup_details.go +++ b/registry/app/api/controller/metadata/get_client_setup_details.go @@ -278,7 +278,7 @@ func (c *APIController) generateGenericClientSetupDetail( header2 := "Upload Artifact" section2step1Header := "Run this curl command in your terminal to push the artifact." //nolint:lll - pushValue := "curl --location --request PUT '///' \\\n--form 'filename=\"\"' \\\n--form 'file=@\"\"' \\\n--form 'description=\"\"' \\\n--header 'x-api-key: '" + pushValue := "curl --location --request PUT '//' \\\n--form 'filename=\"\"' \\\n--form 'file=@\"\"' \\\n--form 'description=\"\"' \\\n--header 'x-api-key: '" section2step1Commands := []artifact.ClientSetupStepCommand{ {Label: &blankString, Value: &pushValue}, } @@ -299,8 +299,8 @@ func (c *APIController) generateGenericClientSetupDetail( header3 := "Download Artifact" section3step1Header := "Run this command in your terminal to download the artifact." //nolint:lll - pullValue := "curl --location '//::' --header 'x-api-key: ' " + - "-J -O" + pullValue := "curl --location '//' \\\n--form 'filename=\"\"' --header 'x-api-key: ' " + + "-o " section3step1Commands := []artifact.ClientSetupStepCommand{ {Label: &blankString, Value: &pullValue}, } @@ -1250,7 +1250,7 @@ func (c *APIController) replacePlaceholdersInSection( _, registryName, _ := paths.DisectLeaf(regRef) var hostname string if pkgType == string(artifact.PackageTypeGENERIC) { - hostname = c.URLProvider.RegistryURL(ctx, rootSpace, "generic") + hostname = c.URLProvider.PackageURL(ctx, regRef, "generic") } else { hostname = common.TrimURLScheme(c.URLProvider.RegistryURL(ctx, rootSpace)) } diff --git a/registry/app/api/handler/generic/base.go b/registry/app/api/handler/generic/base.go index e736390fc..5a6d320ff 100644 --- a/registry/app/api/handler/generic/base.go +++ b/registry/app/api/handler/generic/base.go @@ -27,12 +27,15 @@ import ( corestore "github.com/harness/gitness/app/store" urlprovider "github.com/harness/gitness/app/url" "github.com/harness/gitness/registry/app/api/controller/metadata" + "github.com/harness/gitness/registry/app/api/handler/packages" "github.com/harness/gitness/registry/app/api/handler/utils" artifact2 "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact" "github.com/harness/gitness/registry/app/dist_temp/errcode" "github.com/harness/gitness/registry/app/pkg" "github.com/harness/gitness/registry/app/pkg/commons" "github.com/harness/gitness/registry/app/pkg/generic" + "github.com/harness/gitness/registry/app/pkg/types/npm" + "github.com/harness/gitness/registry/request" "github.com/rs/zerolog/log" ) @@ -47,9 +50,10 @@ const ( func NewGenericArtifactHandler( spaceStore corestore.SpaceStore, controller *generic.Controller, tokenStore corestore.TokenStore, userCtrl *usercontroller.Controller, authenticator authn.Authenticator, urlProvider urlprovider.Provider, - authorizer authz.Authorizer, + authorizer authz.Authorizer, packageHandler packages.Handler, ) *Handler { return &Handler{ + Handler: packageHandler, Controller: controller, SpaceStore: spaceStore, TokenStore: tokenStore, @@ -61,6 +65,7 @@ func NewGenericArtifactHandler( } type Handler struct { + packages.Handler Controller *generic.Controller SpaceStore corestore.SpaceStore TokenStore corestore.TokenStore @@ -70,8 +75,12 @@ type Handler struct { Authorizer authz.Authorizer } -func (h *Handler) GetArtifactInfo(r *http.Request) (pkg.GenericArtifactInfo, errcode.Error) { +func (h *Handler) GetGenericArtifactInfo(r *http.Request) (pkg.GenericArtifactInfo, errcode.Error) { ctx := r.Context() + info, ok := request.ArtifactInfoFrom(ctx).(pkg.GenericArtifactInfo) + if ok { + return info, errcode.Error{} + } path := r.URL.Path rootIdentifier, registryIdentifier, artifact, tag, fileName, description, err := ExtractPathVars(r) @@ -115,7 +124,7 @@ func (h *Handler) GetArtifactInfo(r *http.Request) (pkg.GenericArtifactInfo, err return pkg.GenericArtifactInfo{}, errcode.ErrCodeParentNotFound.WithDetail(err) } - info := &pkg.GenericArtifactInfo{ + info = pkg.GenericArtifactInfo{ ArtifactInfo: &pkg.ArtifactInfo{ BaseInfo: &pkg.BaseInfo{ RootIdentifier: rootIdentifier, @@ -150,7 +159,7 @@ func (h *Handler) GetArtifactInfo(r *http.Request) (pkg.GenericArtifactInfo, err } } - return *info, errcode.Error{} + return info, errcode.Error{} } // ExtractPathVars extracts registry,image, reference, digest and tag from the path @@ -242,3 +251,29 @@ func validatePackageVersionAndFileName(packageName, version, filename string) er return nil } + +func (h *Handler) GetPackageArtifactInfo(r *http.Request) (pkg.PackageArtifactInfo, error) { + info, e := h.GetArtifactInfo(r) + + if !commons.IsEmpty(e) { + return npm.ArtifactInfo{}, e + } + + info.Image = r.PathValue("package") + version := r.PathValue("version") + fileName := r.FormValue("filename") + description := r.FormValue("description") + + if err := validatePackageVersionAndFileName(info.Image, version, fileName); err != nil { + log.Error().Msgf("Invalid image name/version/fileName: %s/%s/%s", info.Image, version, fileName) + return nil, err + } + + return pkg.GenericArtifactInfo{ + ArtifactInfo: &info, + Version: version, + FileName: fileName, + Description: description, + RegistryID: info.RegistryID, + }, nil +} diff --git a/registry/app/api/handler/generic/pull_artifact.go b/registry/app/api/handler/generic/pull_artifact.go index 0c84ad1ca..08c9059d0 100644 --- a/registry/app/api/handler/generic/pull_artifact.go +++ b/registry/app/api/handler/generic/pull_artifact.go @@ -25,7 +25,7 @@ import ( func (h *Handler) PullArtifact(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - info, err := h.GetArtifactInfo(r) + info, err := h.GetGenericArtifactInfo(r) if !commons.IsEmptyError(err) { handleErrors(r.Context(), err, w) return diff --git a/registry/app/api/handler/generic/push_artifact.go b/registry/app/api/handler/generic/push_artifact.go index 094deaef5..9e3da69dc 100644 --- a/registry/app/api/handler/generic/push_artifact.go +++ b/registry/app/api/handler/generic/push_artifact.go @@ -23,7 +23,7 @@ import ( ) func (h *Handler) PushArtifact(w http.ResponseWriter, r *http.Request) { - info, err := h.GetArtifactInfo(r) + info, err := h.GetGenericArtifactInfo(r) if !commons.IsEmptyError(err) { handleErrors(r.Context(), err, w) return diff --git a/registry/app/api/middleware/bandwidth_stats.go b/registry/app/api/middleware/bandwidth_stats.go index 71817f45a..1e002e38f 100644 --- a/registry/app/api/middleware/bandwidth_stats.go +++ b/registry/app/api/middleware/bandwidth_stats.go @@ -135,7 +135,7 @@ func TrackBandwidthStatForGenericArtifacts(h *generic.Handler) func(http.Handler } ctx := r.Context() - info, err := h.GetArtifactInfo(r) + info, err := h.GetGenericArtifactInfo(r) if !commons.IsEmptyError(err) { log.Ctx(ctx).Error().Stack().Str("middleware", "TrackBandwidthStat").Err(err).Msgf("error while putting bandwidth stat for artifact, %v", diff --git a/registry/app/api/middleware/download_stats.go b/registry/app/api/middleware/download_stats.go index 6dc191006..9772f051d 100644 --- a/registry/app/api/middleware/download_stats.go +++ b/registry/app/api/middleware/download_stats.go @@ -138,7 +138,7 @@ func TrackDownloadStatForGenericArtifact(h *generic.Handler) func(http.Handler) return } - info, err := h.GetArtifactInfo(r) + info, err := h.GetGenericArtifactInfo(r) if !commons.IsEmptyError(err) { log.Ctx(ctx).Error().Stack().Str("middleware", "TrackDownloadStat").Err(err).Msgf("error while putting download stat of artifact, %v", diff --git a/registry/app/api/router/packages/route.go b/registry/app/api/router/packages/route.go index 034fd6d0f..1931577f4 100644 --- a/registry/app/api/router/packages/route.go +++ b/registry/app/api/router/packages/route.go @@ -70,11 +70,17 @@ func NewRouter( r.Route("/generic", func(r chi.Router) { r.Use(middlewareauthn.Attempt(packageHandler.GetAuthenticator())) r.Use(middleware.CheckAuth()) - r.Use(middleware.TrackDownloadStatForGenericArtifact(genericHandler)) - r.Use(middleware.TrackBandwidthStatForGenericArtifacts(genericHandler)) + r.Route("/{package}/{version}", func(r chi.Router) { + r.Use(middleware.StoreArtifactInfo(genericHandler)) + r.Use(middleware.TrackDownloadStatForGenericArtifact(genericHandler)) + r.Use(middleware.TrackBandwidthStatForGenericArtifacts(genericHandler)) - r.Get("/*", genericHandler.PullArtifact) - r.Put("/*", genericHandler.PushArtifact) + r.With(middleware.RequestPackageAccess(packageHandler, enum.PermissionArtifactsDownload)). + Get("/", genericHandler.PullArtifact) + + r.With(middleware.RequestPackageAccess(packageHandler, enum.PermissionArtifactsUpload)). + Put("/", genericHandler.PushArtifact) + }) }) r.Route("/python", func(r chi.Router) { diff --git a/registry/app/api/wire.go b/registry/app/api/wire.go index 37c216e26..60141ffa1 100644 --- a/registry/app/api/wire.go +++ b/registry/app/api/wire.go @@ -168,7 +168,7 @@ func NewRpmHandlerProvider( func NewGenericHandlerProvider( spaceStore corestore.SpaceStore, controller *generic2.Controller, tokenStore corestore.TokenStore, userCtrl *usercontroller.Controller, authenticator authn.Authenticator, urlProvider urlprovider.Provider, - authorizer authz.Authorizer, + authorizer authz.Authorizer, packageHandler packages.Handler, ) *generic.Handler { return generic.NewGenericArtifactHandler( spaceStore, @@ -178,6 +178,7 @@ func NewGenericHandlerProvider( authenticator, urlProvider, authorizer, + packageHandler, ) } diff --git a/registry/app/pkg/context.go b/registry/app/pkg/context.go index 11fff98ef..ba3524fcc 100644 --- a/registry/app/pkg/context.go +++ b/registry/app/pkg/context.go @@ -79,3 +79,19 @@ type GenericArtifactInfo struct { func (a *MavenArtifactInfo) SetMavenRepoKey(key string) { a.RegIdentifier = key } + +// BaseArtifactInfo implements pkg.PackageArtifactInfo interface. +func (a GenericArtifactInfo) BaseArtifactInfo() ArtifactInfo { + return *a.ArtifactInfo +} + +func (a GenericArtifactInfo) GetImageVersion() (exists bool, imageVersion string) { + if a.Image != "" && a.Version != "" { + return true, JoinWithSeparator(":", a.Image, a.Version) + } + return false, "" +} + +func (a GenericArtifactInfo) GetVersion() string { + return a.Version +}