diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index 4d597db31..0f17c93ec 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -127,6 +127,7 @@ import ( "github.com/harness/gitness/registry/app/api/router" "github.com/harness/gitness/registry/app/pkg" "github.com/harness/gitness/registry/app/pkg/docker" + "github.com/harness/gitness/registry/app/pkg/maven" database2 "github.com/harness/gitness/registry/app/store/database" "github.com/harness/gitness/registry/gc" "github.com/harness/gitness/ssh" @@ -480,7 +481,13 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro registryOCIHandler := router.OCIHandlerProvider(handler) cleanupPolicyRepository := database2.ProvideCleanupPolicyDao(db, transactor) apiHandler := router.APIHandlerProvider(registryRepository, upstreamProxyConfigRepository, tagRepository, manifestRepository, cleanupPolicyRepository, imageRepository, storageDriver, spaceStore, transactor, authenticator, provider, authorizer, auditService, spacePathStore) - appRouter := router.AppRouterProvider(registryOCIHandler, apiHandler) + mavenDBStore := maven.DBStoreProvider(registryRepository, imageRepository, artifactRepository, spaceStore, bandwidthStatRepository, downloadStatRepository) + mavenLocalRegistry := maven.LocalRegistryProvider(mavenDBStore, transactor) + mavenRemoteRegistry := maven.RemoteRegistryProvider(mavenDBStore, transactor) + mavenController := maven.ControllerProvider(mavenLocalRegistry, mavenRemoteRegistry, authorizer, mavenDBStore) + mavenHandler := api2.NewMavenHandlerProvider(mavenController, spaceStore, tokenStore, controller, authenticator, authorizer) + handler2 := router.MavenHandlerProvider(mavenHandler) + appRouter := router.AppRouterProvider(registryOCIHandler, apiHandler, handler2) sender := usage.ProvideMediator(ctx, config, spaceStore, usageMetricStore) routerRouter := router2.ProvideRouter(ctx, config, authenticator, repoController, reposettingsController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, gitInterface, serviceaccountController, controller, principalController, usergroupController, checkController, systemController, uploadController, keywordsearchController, infraproviderController, gitspaceController, migrateController, aiagentController, capabilitiesController, provider, openapiService, appRouter, sender) serverServer := server2.ProvideServer(config, routerRouter) diff --git a/registry/app/api/handler/maven/base.go b/registry/app/api/handler/maven/base.go new file mode 100644 index 000000000..30745b10f --- /dev/null +++ b/registry/app/api/handler/maven/base.go @@ -0,0 +1,218 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "context" + "fmt" + "net/http" + "regexp" + "strings" + + usercontroller "github.com/harness/gitness/app/api/controller/user" + "github.com/harness/gitness/app/auth/authn" + "github.com/harness/gitness/app/auth/authz" + corestore "github.com/harness/gitness/app/store" + "github.com/harness/gitness/registry/app/api/controller/metadata" + "github.com/harness/gitness/registry/app/api/handler/utils" + "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/maven" + "github.com/harness/gitness/registry/request" + + "github.com/rs/zerolog/log" +) + +type Handler struct { + Controller *maven.Controller + SpaceStore corestore.SpaceStore + TokenStore corestore.TokenStore + UserCtrl *usercontroller.Controller + Authenticator authn.Authenticator + Authorizer authz.Authorizer +} + +func NewHandler( + controller *maven.Controller, spaceStore corestore.SpaceStore, tokenStore corestore.TokenStore, + userCtrl *usercontroller.Controller, authenticator authn.Authenticator, authorizer authz.Authorizer, +) *Handler { + return &Handler{ + Controller: controller, + SpaceStore: spaceStore, + TokenStore: tokenStore, + UserCtrl: userCtrl, + Authenticator: authenticator, + Authorizer: authorizer, + } +} + +const ( + mavenMetadataFile = "maven-metadata.xml" + extensionMD5 = ".md5" + extensionSHA1 = ".sha1" + extensionSHA256 = ".sha256" + extensionSHA512 = ".sha512" + extensionPom = ".pom" + extensionJar = ".jar" + contentTypeJar = "application/java-archive" + contentTypeXML = "text/xml" +) + +var ( + illegalCharacters = regexp.MustCompile(`[\\/:"<>|?\*]`) + invalidPathFormat = "invalid path format: %s" +) + +func (h *Handler) GetArtifactInfo(r *http.Request, remoteSupport bool) (pkg.MavenArtifactInfo, error) { + ctx := r.Context() + path := r.URL.Path + rootIdentifier, registryIdentifier, groupID, artifactID, version, fileName, err := ExtractPathVars(path) + if err != nil { + return pkg.MavenArtifactInfo{}, err + } + if err = metadata.ValidateIdentifier(rootIdentifier); err != nil { + return pkg.MavenArtifactInfo{}, err + } + + rootSpace, err := h.SpaceStore.FindByRefCaseInsensitive(ctx, rootIdentifier) + if err != nil { + log.Ctx(ctx).Error().Msgf("Root space not found: %s", rootIdentifier) + return pkg.MavenArtifactInfo{}, errcode.ErrCodeRootNotFound + } + + registry, err := h.Controller.DBStore.RegistryDao.GetByRootParentIDAndName(ctx, rootSpace.ID, registryIdentifier) + if err != nil { + log.Ctx(ctx).Error().Msgf( + "registry %s not found for root: %s. Reason: %s", registryIdentifier, rootSpace.Identifier, err, + ) + return pkg.MavenArtifactInfo{}, errcode.ErrCodeRegNotFound + } + _, err = h.SpaceStore.Find(r.Context(), registry.ParentID) + if err != nil { + log.Ctx(ctx).Error().Msgf("Parent space not found: %d", registry.ParentID) + return pkg.MavenArtifactInfo{}, errcode.ErrCodeParentNotFound + } + + pathRoot := getPathRoot(r.Context()) + + info := &pkg.MavenArtifactInfo{ + BaseInfo: &pkg.BaseInfo{ + PathRoot: pathRoot, + RootIdentifier: rootIdentifier, + RootParentID: rootSpace.ID, + ParentID: registry.ParentID, + }, + RegIdentifier: registryIdentifier, + RegistryID: registry.ID, + GroupID: groupID, + ArtifactID: artifactID, + Version: version, + FileName: fileName, + Path: r.URL.Path, + } + + log.Ctx(ctx).Info().Msgf("Dispatch: URI: %s", path) + if commons.IsEmpty(rootSpace.Identifier) { + log.Ctx(ctx).Error().Msgf("ParentRef not found in context") + return pkg.MavenArtifactInfo{}, errcode.ErrCodeParentNotFound + } + + if commons.IsEmpty(registryIdentifier) { + log.Ctx(ctx).Warn().Msgf("registry not found in context") + return pkg.MavenArtifactInfo{}, errcode.ErrCodeRegNotFound + } + + if !commons.IsEmpty(info.GroupID) && !commons.IsEmpty(info.ArtifactID) && !commons.IsEmpty(info.Version) { + flag, err2 := utils.MatchArtifactFilter(registry.AllowedPattern, registry.BlockedPattern, + info.GroupID+":"+info.ArtifactID+":"+info.Version) + if !flag || err2 != nil { + return pkg.MavenArtifactInfo{}, errcode.ErrCodeDenied + } + } + + if registry.Type == artifact.RegistryTypeUPSTREAM && !remoteSupport { + log.Ctx(ctx).Warn().Msgf("Remote registryIdentifier %s not supported", registryIdentifier) + return pkg.MavenArtifactInfo{}, errcode.ErrCodeDenied + } + + return *info, nil +} + +// ExtractPathVars extracts registry, groupId, artifactId, version and tag from the path +// Path format: /maven/:rootSpace/:registry/:groupId/artifactId/:version/:filename (for ex: +// /maven/myRootSpace/reg1/io/example/my-app/1.0/my-app-1.0.jar. +func ExtractPathVars(path string) (rootIdentifier, registry, groupID, artifactID, version, fileName string, err error) { + path = strings.Trim(path, "/") + segments := strings.Split(path, "/") + if len(segments) < 6 { + err = fmt.Errorf(invalidPathFormat, path) + return "", "", "", "", "", "", err + } + rootIdentifier = segments[1] + registry = segments[2] + fileName = segments[len(segments)-1] + + segments = segments[:len(segments)-1] + + version = segments[len(segments)-1] + if isMetadataFile(fileName) && !strings.HasSuffix(version, "-SNAPSHOT") { + version = "" + } else { + segments = segments[:len(segments)-1] + if len(segments) < 5 { + err = fmt.Errorf(invalidPathFormat, path) + return rootIdentifier, registry, groupID, artifactID, version, fileName, err + } + } + + artifactID = segments[len(segments)-1] + groupID = strings.Join(segments[:len(segments)-1], ".") + + if illegalCharacters.MatchString(groupID) || illegalCharacters.MatchString(artifactID) || + illegalCharacters.MatchString(version) { + err = fmt.Errorf(invalidPathFormat, path) + return rootIdentifier, registry, groupID, artifactID, version, fileName, err + } + return rootIdentifier, registry, groupID, artifactID, version, fileName, nil +} + +func isMetadataFile(filename string) bool { + return filename == mavenMetadataFile || + filename == mavenMetadataFile+extensionMD5 || + filename == mavenMetadataFile+extensionSHA1 || + filename == mavenMetadataFile+extensionSHA256 || + filename == mavenMetadataFile+extensionSHA512 +} + +func getPathRoot(ctx context.Context) string { + originalURL := request.OriginalURLFrom(ctx) + pathRoot := "" + if originalURL != "" { + originalURL = strings.Trim(originalURL, "/") + segments := strings.Split(originalURL, "/") + if len(segments) > 1 { + pathRoot = segments[1] + } + } + return pathRoot +} + +func LogError(errList errcode.Errors) { + for _, e1 := range errList { + log.Error().Err(e1).Msgf("error: %v", e1) + } +} diff --git a/registry/app/api/handler/maven/get_artifact.go b/registry/app/api/handler/maven/get_artifact.go new file mode 100644 index 000000000..8c331e492 --- /dev/null +++ b/registry/app/api/handler/maven/get_artifact.go @@ -0,0 +1,23 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "net/http" +) + +func (h *Handler) GetArtifact(_ http.ResponseWriter, _ *http.Request) { + // ctx := r.Context() +} diff --git a/registry/app/api/handler/maven/head_artifact.go b/registry/app/api/handler/maven/head_artifact.go new file mode 100644 index 000000000..9887b0ed2 --- /dev/null +++ b/registry/app/api/handler/maven/head_artifact.go @@ -0,0 +1,23 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "net/http" +) + +func (h *Handler) HeadArtifact(_ http.ResponseWriter, _ *http.Request) { + // ctx := r.Context() +} diff --git a/registry/app/api/handler/maven/put_artifact.go b/registry/app/api/handler/maven/put_artifact.go new file mode 100644 index 000000000..b5c398d7f --- /dev/null +++ b/registry/app/api/handler/maven/put_artifact.go @@ -0,0 +1,23 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "net/http" +) + +func (h *Handler) PutArtifact(_ http.ResponseWriter, _ *http.Request) { + // ctx := r.Context() +} diff --git a/registry/app/api/handler/oci/base.go b/registry/app/api/handler/oci/base.go index 7241b51f9..42350829e 100644 --- a/registry/app/api/handler/oci/base.go +++ b/registry/app/api/handler/oci/base.go @@ -25,6 +25,7 @@ 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/utils" "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact" "github.com/harness/gitness/registry/app/common" "github.com/harness/gitness/registry/app/dist_temp/dcontext" @@ -243,7 +244,7 @@ func (h *Handler) GetRegistryInfo(r *http.Request, remoteSupport bool) (pkg.Regi } if !commons.IsEmpty(info.Image) && !commons.IsEmpty(info.Tag) { - flag, err2 := MatchArtifactFilter(registry.AllowedPattern, registry.BlockedPattern, info.Image+":"+info.Tag) + flag, err2 := utils.MatchArtifactFilter(registry.AllowedPattern, registry.BlockedPattern, info.Image+":"+info.Tag) if !flag || err2 != nil { return pkg.RegistryInfo{}, errcode.ErrCodeDenied } diff --git a/registry/app/api/handler/oci/artifactfilter.go b/registry/app/api/handler/utils/artifactfilter.go similarity index 99% rename from registry/app/api/handler/oci/artifactfilter.go rename to registry/app/api/handler/utils/artifactfilter.go index 0afcfd680..6b0296197 100644 --- a/registry/app/api/handler/oci/artifactfilter.go +++ b/registry/app/api/handler/utils/artifactfilter.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package oci +package utils import ( "errors" diff --git a/registry/app/api/middleware/bandwidth_stats.go b/registry/app/api/middleware/bandwidth_stats.go index b941ba532..2b1d32cd4 100644 --- a/registry/app/api/middleware/bandwidth_stats.go +++ b/registry/app/api/middleware/bandwidth_stats.go @@ -136,7 +136,7 @@ func dbBandwidthStat( } func getImageFromUpstreamProxy(ctx context.Context, c *docker.Controller, info pkg.RegistryInfo) (*types.Image, error) { - repos, err := c.GetOrderedRepos(ctx, info.RegIdentifier, info) + repos, err := c.GetOrderedRepos(ctx, info.RegIdentifier, *info.BaseInfo) if err != nil { return nil, err } diff --git a/registry/app/api/router/maven/route.go b/registry/app/api/router/maven/route.go new file mode 100644 index 000000000..cadc49507 --- /dev/null +++ b/registry/app/api/router/maven/route.go @@ -0,0 +1,65 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "net/http" + + middlewareauthn "github.com/harness/gitness/app/api/middleware/authn" + "github.com/harness/gitness/registry/app/api/handler/maven" + "github.com/harness/gitness/registry/app/api/middleware" + + "github.com/go-chi/chi/v5" + "github.com/rs/zerolog/log" +) + +type Handler interface { + http.Handler +} + +func NewMavenHandler(handler *maven.Handler) Handler { + r := chi.NewRouter() + + var routeHandlers = map[string]http.HandlerFunc{ + http.MethodHead: handler.HeadArtifact, + http.MethodGet: handler.GetArtifact, + http.MethodPut: handler.PutArtifact, + } + + r.Route("/maven", func(r chi.Router) { + r.Use(middleware.StoreOriginalURL) + r.Use(middlewareauthn.Attempt(handler.Authenticator)) + //todo: r.Use(middleware.TrackDownloadStat(handler)) + //todo: r.Use(middleware.TrackBandwidthStat(handler)) + + r.Handle("/*", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + methodType := req.Method + + if h, ok := routeHandlers[methodType]; ok { + h(w, req) + return + } + + w.WriteHeader(http.StatusNotFound) + _, err := w.Write([]byte("Invalid route")) + if err != nil { + log.Error().Err(err).Msg("Failed to write response") + return + } + })) + }) + + return r +} diff --git a/registry/app/api/router/registry_router.go b/registry/app/api/router/registry_router.go index 71e44d336..5593f24e3 100644 --- a/registry/app/api/router/registry_router.go +++ b/registry/app/api/router/registry_router.go @@ -41,7 +41,7 @@ func (r *RegistryRouter) IsEligibleTraffic(req *http.Request) bool { if req.URL.RawPath != "" { urlPath = req.URL.RawPath } - if utils.HasAnyPrefix(urlPath, []string{RegistryMount, "/v2/", "/registry/"}) || + if utils.HasAnyPrefix(urlPath, []string{RegistryMount, "/v2/", "/registry/", "/maven/"}) || (strings.HasPrefix(urlPath, APIMount+"/v1/spaces/") && utils.HasAnySuffix(urlPath, []string{"/artifacts", "/registries"})) { return true diff --git a/registry/app/api/router/router.go b/registry/app/api/router/router.go index 684fc000e..032b1e9ff 100644 --- a/registry/app/api/router/router.go +++ b/registry/app/api/router/router.go @@ -22,6 +22,7 @@ import ( "github.com/harness/gitness/app/api/middleware/logging" "github.com/harness/gitness/registry/app/api/handler/swagger" "github.com/harness/gitness/registry/app/api/router/harness" + "github.com/harness/gitness/registry/app/api/router/maven" "github.com/harness/gitness/registry/app/api/router/oci" "github.com/go-chi/chi/v5" @@ -36,6 +37,7 @@ func GetAppRouter( ociHandler oci.RegistryOCIHandler, appHandler harness.APIHandler, baseURL string, + mavenHandler maven.Handler, ) AppRouter { r := chi.NewRouter() r.Use(hlog.URLHandler("http.url")) @@ -47,6 +49,7 @@ func GetAppRouter( r.Group(func(r chi.Router) { r.Handle(fmt.Sprintf("%s/*", baseURL), appHandler) r.Handle("/v2/*", ociHandler) + r.Handle("/maven/*", mavenHandler) r.Handle("/registry/swagger*", swagger.GetSwaggerHandler("/registry")) }) diff --git a/registry/app/api/router/wire.go b/registry/app/api/router/wire.go index 5ded079ae..eee546e10 100644 --- a/registry/app/api/router/wire.go +++ b/registry/app/api/router/wire.go @@ -21,8 +21,10 @@ import ( corestore "github.com/harness/gitness/app/store" urlprovider "github.com/harness/gitness/app/url" "github.com/harness/gitness/audit" + "github.com/harness/gitness/registry/app/api/handler/maven" hoci "github.com/harness/gitness/registry/app/api/handler/oci" "github.com/harness/gitness/registry/app/api/router/harness" + mavenRouter "github.com/harness/gitness/registry/app/api/router/maven" "github.com/harness/gitness/registry/app/api/router/oci" storagedriver "github.com/harness/gitness/registry/app/driver" "github.com/harness/gitness/registry/app/store" @@ -34,8 +36,9 @@ import ( func AppRouterProvider( ocir oci.RegistryOCIHandler, appHandler harness.APIHandler, + mavenHandler mavenRouter.Handler, ) AppRouter { - return GetAppRouter(ocir, appHandler, config.APIURL) + return GetAppRouter(ocir, appHandler, config.APIURL, mavenHandler) } func APIHandlerProvider( @@ -77,4 +80,8 @@ func OCIHandlerProvider(handlerV2 *hoci.Handler) oci.RegistryOCIHandler { return oci.NewOCIHandler(handlerV2) } -var WireSet = wire.NewSet(APIHandlerProvider, OCIHandlerProvider, AppRouterProvider) +func MavenHandlerProvider(handler *maven.Handler) mavenRouter.Handler { + return mavenRouter.NewMavenHandler(handler) +} + +var WireSet = wire.NewSet(APIHandlerProvider, OCIHandlerProvider, AppRouterProvider, MavenHandlerProvider) diff --git a/registry/app/api/wire.go b/registry/app/api/wire.go index 4e8c32210..4e6f10492 100644 --- a/registry/app/api/wire.go +++ b/registry/app/api/wire.go @@ -20,6 +20,7 @@ import ( "github.com/harness/gitness/app/auth/authz" corestore "github.com/harness/gitness/app/store" urlprovider "github.com/harness/gitness/app/url" + mavenhandler "github.com/harness/gitness/registry/app/api/handler/maven" ocihandler "github.com/harness/gitness/registry/app/api/handler/oci" "github.com/harness/gitness/registry/app/api/router" storagedriver "github.com/harness/gitness/registry/app/driver" @@ -28,6 +29,7 @@ import ( "github.com/harness/gitness/registry/app/driver/s3-aws" "github.com/harness/gitness/registry/app/pkg" "github.com/harness/gitness/registry/app/pkg/docker" + "github.com/harness/gitness/registry/app/pkg/maven" "github.com/harness/gitness/registry/app/store/database" "github.com/harness/gitness/registry/config" "github.com/harness/gitness/registry/gc" @@ -82,12 +84,29 @@ func NewHandlerProvider( ) } +func NewMavenHandlerProvider( + controller *maven.Controller, spaceStore corestore.SpaceStore, + tokenStore corestore.TokenStore, userCtrl *usercontroller.Controller, authenticator authn.Authenticator, + authorizer authz.Authorizer, +) *mavenhandler.Handler { + return mavenhandler.NewHandler( + controller, + spaceStore, + tokenStore, + userCtrl, + authenticator, + authorizer, + ) +} + var WireSet = wire.NewSet( BlobStorageProvider, NewHandlerProvider, + NewMavenHandlerProvider, database.WireSet, pkg.WireSet, docker.WireSet, + maven.WireSet, router.WireSet, gc.WireSet, ) diff --git a/registry/app/pkg/context.go b/registry/app/pkg/context.go index b09f902dd..d46cbe2e8 100644 --- a/registry/app/pkg/context.go +++ b/registry/app/pkg/context.go @@ -56,3 +56,18 @@ func (r *RegistryInfo) SetReference(ref string) { func (a *ArtifactInfo) SetRepoKey(key string) { a.RegIdentifier = key } + +type MavenArtifactInfo struct { + *BaseInfo + RegIdentifier string + RegistryID int64 + GroupID string + ArtifactID string + Version string + FileName string + Path string +} + +func (a *MavenArtifactInfo) SetMavenRepoKey(key string) { + a.RegIdentifier = key +} diff --git a/registry/app/pkg/core_controller.go b/registry/app/pkg/core_controller.go index 7271b59b4..7d6e3bc30 100644 --- a/registry/app/pkg/core_controller.go +++ b/registry/app/pkg/core_controller.go @@ -65,7 +65,7 @@ func (c *CoreController) GetArtifact(registry types.Registry) Artifact { func (c *CoreController) GetOrderedRepos( ctx context.Context, repoKey string, - artInfo RegistryInfo, + artInfo BaseInfo, ) ([]types.Registry, error) { var result []types.Registry if registry, err := c.RegistryDao.GetByParentIDAndName(ctx, artInfo.ParentID, repoKey); err == nil { diff --git a/registry/app/pkg/docker/controller.go b/registry/app/pkg/docker/controller.go index 568189658..d517437bd 100644 --- a/registry/app/pkg/docker/controller.go +++ b/registry/app/pkg/docker/controller.go @@ -26,7 +26,6 @@ import ( "fmt" "io" "net/http" - "reflect" "github.com/harness/gitness/app/auth/authz" corestore "github.com/harness/gitness/app/store" @@ -105,13 +104,6 @@ func NewDBStore( } } -func isEmpty(slice interface{}) bool { - if slice == nil { - return true - } - return reflect.ValueOf(slice).Len() == 0 -} - const ( ResourceTypeBlob = "blob" ResourceTypeManifest = "manifest" @@ -132,7 +124,7 @@ func (c *Controller) ProxyWrapper( var response Response requestRepoKey := info.RegIdentifier imageName := info.Image - if repos, err := c.GetOrderedRepos(ctx, requestRepoKey, info); err == nil { + if repos, err := c.GetOrderedRepos(ctx, requestRepoKey, *info.BaseInfo); err == nil { for _, registry := range repos { log.Ctx(ctx).Info().Msgf("Using Repository: %s, Type: %s", registry.Name, registry.Type) artifact, ok := c.GetArtifact(registry).(Registry) @@ -142,7 +134,7 @@ func (c *Controller) ProxyWrapper( } if artifact != nil { response = f(registry, imageName, artifact) - if isEmpty(response.GetErrors()) { + if pkg.IsEmpty(response.GetErrors()) { return response } log.Ctx(ctx).Warn().Msgf("Repository: %s, Type: %s, errors: %v", registry.Name, registry.Type, @@ -150,7 +142,7 @@ func (c *Controller) ProxyWrapper( } } } - if response != nil && !isEmpty(response.GetErrors()) { + if response != nil && !pkg.IsEmpty(response.GetErrors()) { switch resourceType { case ResourceTypeManifest: response.SetError(errcode.ErrCodeManifestUnknown) @@ -169,7 +161,7 @@ func (c *Controller) HeadManifest( acceptHeaders []string, ifNoneMatchHeader []string, ) Response { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, art.RegIdentifier, art.ParentID, enum.PermissionArtifactsDownload, ) @@ -196,7 +188,7 @@ func (c *Controller) PullManifest( acceptHeaders []string, ifNoneMatchHeader []string, ) Response { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, art.RegIdentifier, art.ParentID, enum.PermissionArtifactsDownload, ) @@ -223,7 +215,7 @@ func (c *Controller) PutManifest( body io.ReadCloser, length int64, ) (responseHeaders *commons.ResponseHeaders, errs []error) { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, artInfo.RegIdentifier, artInfo.ParentID, enum.PermissionArtifactsUpload, enum.PermissionArtifactsDownload, ) @@ -237,7 +229,7 @@ func (c *Controller) DeleteManifest( ctx context.Context, artInfo pkg.RegistryInfo, ) (errs []error, responseHeaders *commons.ResponseHeaders) { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, artInfo.RegIdentifier, artInfo.ParentID, enum.PermissionArtifactsDelete, ) @@ -254,7 +246,7 @@ func (c *Controller) HeadBlob( responseHeaders *commons.ResponseHeaders, fr *storage.FileReader, size int64, readCloser io.ReadCloser, redirectURL string, errs []error, ) { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, info.RegIdentifier, info.ParentID, enum.PermissionArtifactsDownload, ) @@ -265,7 +257,7 @@ func (c *Controller) HeadBlob( } func (c *Controller) GetBlob(ctx context.Context, info pkg.RegistryInfo) Response { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, info.RegIdentifier, info.ParentID, enum.PermissionArtifactsDownload, ) @@ -289,7 +281,7 @@ func (c *Controller) InitiateUploadBlob( fromImageRef string, mountDigest string, ) (*commons.ResponseHeaders, []error) { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, info.RegIdentifier, info.ParentID, enum.PermissionArtifactsUpload, enum.PermissionArtifactsDownload, @@ -305,7 +297,7 @@ func (c *Controller) GetUploadBlobStatus( info pkg.RegistryInfo, token string, ) (responseHeaders *commons.ResponseHeaders, errs []error) { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, info.RegIdentifier, info.ParentID, enum.PermissionArtifactsDownload, ) @@ -327,7 +319,7 @@ func (c *Controller) PatchBlobUpload( body io.ReadCloser, ) (responseHeaders *commons.ResponseHeaders, errors []error) { blobCtx := c.local.App.GetBlobsContext(ctx, info) - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, info.RegIdentifier, info.ParentID, enum.PermissionArtifactsDownload, enum.PermissionArtifactsUpload, @@ -358,7 +350,7 @@ func (c *Controller) CompleteBlobUpload( length int64, stateToken string, ) (responseHeaders *commons.ResponseHeaders, errs []error) { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, info.RegIdentifier, info.ParentID, enum.PermissionArtifactsUpload, enum.PermissionArtifactsDownload, @@ -374,7 +366,7 @@ func (c *Controller) CancelBlobUpload( info pkg.RegistryInfo, stateToken string, ) (responseHeaders *commons.ResponseHeaders, errors []error) { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, info.RegIdentifier, info.ParentID, enum.PermissionArtifactsDelete, ) @@ -415,7 +407,7 @@ func (c *Controller) DeleteBlob( ctx context.Context, info pkg.RegistryInfo, ) (responseHeaders *commons.ResponseHeaders, errs []error) { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, info.RegIdentifier, info.ParentID, enum.PermissionArtifactsDelete, ) @@ -433,7 +425,7 @@ func (c *Controller) GetTags( origURL string, artInfo pkg.RegistryInfo, ) (*commons.ResponseHeaders, []string, error) { - err := GetRegistryCheckAccess( + err := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, artInfo.RegIdentifier, artInfo.ParentID, enum.PermissionArtifactsDownload, ) @@ -452,7 +444,7 @@ func (c *Controller) GetReferrers( artInfo pkg.RegistryInfo, artifactType string, ) (index *v1.Index, responseHeaders *commons.ResponseHeaders, err error) { - accessErr := GetRegistryCheckAccess( + accessErr := pkg.GetRegistryCheckAccess( ctx, c.RegistryDao, c.authorizer, c.spaceStore, artInfo.RegIdentifier, artInfo.ParentID, enum.PermissionArtifactsDownload, ) diff --git a/registry/app/pkg/docker/helpers.go b/registry/app/pkg/helpers.go similarity index 99% rename from registry/app/pkg/docker/helpers.go rename to registry/app/pkg/helpers.go index 5847173fd..abd326372 100644 --- a/registry/app/pkg/docker/helpers.go +++ b/registry/app/pkg/helpers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package docker +package pkg import ( "context" diff --git a/registry/app/pkg/maven/artifact.go b/registry/app/pkg/maven/artifact.go new file mode 100644 index 000000000..3cf9454c8 --- /dev/null +++ b/registry/app/pkg/maven/artifact.go @@ -0,0 +1,19 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +type Artifact interface { + GetMavenArtifactType() string +} diff --git a/registry/app/pkg/maven/controller.go b/registry/app/pkg/maven/controller.go new file mode 100644 index 000000000..050d7180f --- /dev/null +++ b/registry/app/pkg/maven/controller.go @@ -0,0 +1,188 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "context" + + "github.com/harness/gitness/app/auth/authz" + corestore "github.com/harness/gitness/app/store" + "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/store" + registrytypes "github.com/harness/gitness/registry/types" + "github.com/harness/gitness/store/database/dbtx" + "github.com/harness/gitness/types/enum" + + "github.com/rs/zerolog/log" +) + +var _ Artifact = (*LocalRegistry)(nil) +var _ Artifact = (*RemoteRegistry)(nil) + +type ArtifactType int + +const ( + LocalRegistryType ArtifactType = 1 << iota + RemoteRegistryType +) + +var TypeRegistry = map[ArtifactType]Artifact{} + +type Controller struct { + local *LocalRegistry + remote *RemoteRegistry + authorizer authz.Authorizer + DBStore *DBStore + _ dbtx.Transactor +} + +type DBStore struct { + RegistryDao store.RegistryRepository + ImageDao store.ImageRepository + ArtifactDao store.ArtifactRepository + SpaceStore corestore.SpaceStore + BandwidthStatDao store.BandwidthStatRepository + DownloadStatDao store.DownloadStatRepository +} + +func NewController( + local *LocalRegistry, + remote *RemoteRegistry, + authorizer authz.Authorizer, + dBStore *DBStore, +) *Controller { + c := &Controller{ + local: local, + remote: remote, + authorizer: authorizer, + DBStore: dBStore, + } + + TypeRegistry[LocalRegistryType] = local + TypeRegistry[RemoteRegistryType] = remote + return c +} + +func NewDBStore( + registryDao store.RegistryRepository, + imageDao store.ImageRepository, + artifactDao store.ArtifactRepository, + spaceStore corestore.SpaceStore, + bandwidthStatDao store.BandwidthStatRepository, + downloadStatDao store.DownloadStatRepository, +) *DBStore { + return &DBStore{ + RegistryDao: registryDao, + SpaceStore: spaceStore, + ImageDao: imageDao, + ArtifactDao: artifactDao, + BandwidthStatDao: bandwidthStatDao, + DownloadStatDao: downloadStatDao, + } +} + +func (c *Controller) factory(t ArtifactType) Artifact { + switch t { + case LocalRegistryType: + return TypeRegistry[t] + case RemoteRegistryType: + return TypeRegistry[t] + default: + log.Error().Stack().Msgf("Invalid artifact type %v", t) + return nil + } +} + +func (c *Controller) GetArtifactRegistry(registry registrytypes.Registry) Artifact { + if string(registry.Type) == string(artifact.RegistryTypeVIRTUAL) { + return c.factory(LocalRegistryType) + } + return c.factory(RemoteRegistryType) +} + +func (c *Controller) GetArtifact(ctx context.Context, info pkg.MavenArtifactInfo) Response { + err := pkg.GetRegistryCheckAccess( + ctx, c.DBStore.RegistryDao, c.authorizer, c.DBStore.SpaceStore, info.RegIdentifier, info.ParentID, + enum.PermissionArtifactsDownload, + ) + if err != nil { + return &GetArtifactResponse{ + Errors: []error{errcode.ErrCodeDenied}, + } + } + + f := func(registry registrytypes.Registry, a Artifact) Response { + info.SetMavenRepoKey(registry.Name) + headers, body, e := a.(Registry).GetArtifact(ctx, info) + return &GetArtifactResponse{e, headers, body} + } + return c.ProxyWrapper(ctx, f, info) +} + +func (c *Controller) ProxyWrapper( + ctx context.Context, + f func(registry registrytypes.Registry, a Artifact) Response, + info pkg.MavenArtifactInfo, +) Response { + none := pkg.MavenArtifactInfo{} + if info == none { + log.Ctx(ctx).Error().Stack().Msg("artifactinfo is not found") + return nil + } + + var response Response + requestRepoKey := info.RegIdentifier + if repos, err := c.GetOrderedRepos(ctx, requestRepoKey, *info.BaseInfo); err == nil { + for _, registry := range repos { + log.Ctx(ctx).Info().Msgf("Using Repository: %s, Type: %s", registry.Name, registry.Type) + artifact, ok := c.GetArtifactRegistry(registry).(Registry) + if !ok { + log.Ctx(ctx).Warn().Msgf("artifact %s is not a registry", registry.Name) + continue + } + if artifact != nil { + response = f(registry, artifact) + if pkg.IsEmpty(response.GetErrors()) { + return response + } + log.Ctx(ctx).Warn().Msgf("Repository: %s, Type: %s, errors: %v", registry.Name, registry.Type, + response.GetErrors()) + } + } + } + return response +} + +func (c *Controller) GetOrderedRepos( + ctx context.Context, + repoKey string, + artInfo pkg.BaseInfo, +) ([]registrytypes.Registry, error) { + var result []registrytypes.Registry + if registry, err := c.DBStore.RegistryDao.GetByParentIDAndName(ctx, artInfo.ParentID, repoKey); err == nil { + result = append(result, *registry) + proxies := registry.UpstreamProxies + if len(proxies) > 0 { + upstreamRepos, _ := c.DBStore.RegistryDao.GetByIDIn(ctx, proxies) + result = append(result, *upstreamRepos...) + } + } else { + return result, err + } + + return result, nil +} diff --git a/registry/app/pkg/maven/local.go b/registry/app/pkg/maven/local.go new file mode 100644 index 000000000..3f5c1b136 --- /dev/null +++ b/registry/app/pkg/maven/local.go @@ -0,0 +1,60 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "context" + + "github.com/harness/gitness/registry/app/pkg" + "github.com/harness/gitness/registry/app/pkg/commons" + "github.com/harness/gitness/registry/app/storage" + "github.com/harness/gitness/store/database/dbtx" +) + +const ( + ArtifactTypeLocalRegistry = "Local Registry" +) + +func NewLocalRegistry(dBStore *DBStore, tx dbtx.Transactor, +) Registry { + return &LocalRegistry{ + DBStore: dBStore, + tx: tx, + } +} + +type LocalRegistry struct { + DBStore *DBStore + tx dbtx.Transactor +} + +func (r *LocalRegistry) GetMavenArtifactType() string { + return ArtifactTypeLocalRegistry +} + +func (r *LocalRegistry) HeadArtifact(_ context.Context, _ pkg.MavenArtifactInfo) ( + responseHeaders *commons.ResponseHeaders, errs []error) { + return nil, nil +} + +func (r *LocalRegistry) GetArtifact(_ context.Context, _ pkg.MavenArtifactInfo) ( + responseHeaders *commons.ResponseHeaders, body *storage.FileReader, errs []error) { + return nil, nil, nil +} + +func (r *LocalRegistry) PutArtifact(_ context.Context, _ pkg.MavenArtifactInfo) ( + responseHeaders *commons.ResponseHeaders, errs []error) { + return nil, nil +} diff --git a/registry/app/pkg/maven/registry.go b/registry/app/pkg/maven/registry.go new file mode 100644 index 000000000..c92123991 --- /dev/null +++ b/registry/app/pkg/maven/registry.go @@ -0,0 +1,36 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "context" + + "github.com/harness/gitness/registry/app/pkg" + "github.com/harness/gitness/registry/app/pkg/commons" + "github.com/harness/gitness/registry/app/storage" +) + +type Registry interface { + Artifact + + HeadArtifact(ctx context.Context, artInfo pkg.MavenArtifactInfo) ( + responseHeaders *commons.ResponseHeaders, errs []error) + + GetArtifact(ctx context.Context, artInfo pkg.MavenArtifactInfo) ( + responseHeaders *commons.ResponseHeaders, body *storage.FileReader, errs []error) + + PutArtifact(ctx context.Context, artInfo pkg.MavenArtifactInfo) ( + responseHeaders *commons.ResponseHeaders, errs []error) +} diff --git a/registry/app/pkg/maven/remote.go b/registry/app/pkg/maven/remote.go new file mode 100644 index 000000000..906bcc594 --- /dev/null +++ b/registry/app/pkg/maven/remote.go @@ -0,0 +1,60 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "context" + + "github.com/harness/gitness/registry/app/pkg" + "github.com/harness/gitness/registry/app/pkg/commons" + "github.com/harness/gitness/registry/app/storage" + "github.com/harness/gitness/store/database/dbtx" +) + +const ( + ArtifactTypeRemoteRegistry = "Remote Registry" +) + +func NewRemoteRegistry(dBStore *DBStore, tx dbtx.Transactor, +) Registry { + return &RemoteRegistry{ + DBStore: dBStore, + tx: tx, + } +} + +type RemoteRegistry struct { + DBStore *DBStore + tx dbtx.Transactor +} + +func (r *RemoteRegistry) GetMavenArtifactType() string { + return ArtifactTypeRemoteRegistry +} + +func (r *RemoteRegistry) HeadArtifact(_ context.Context, _ pkg.MavenArtifactInfo) ( + responseHeaders *commons.ResponseHeaders, errs []error) { + return nil, nil +} + +func (r *RemoteRegistry) GetArtifact(_ context.Context, _ pkg.MavenArtifactInfo) ( + responseHeaders *commons.ResponseHeaders, body *storage.FileReader, errs []error) { + return nil, nil, nil +} + +func (r *RemoteRegistry) PutArtifact(_ context.Context, _ pkg.MavenArtifactInfo) ( + responseHeaders *commons.ResponseHeaders, errs []error) { + return nil, nil +} diff --git a/registry/app/pkg/maven/response.go b/registry/app/pkg/maven/response.go new file mode 100644 index 000000000..f490e78ed --- /dev/null +++ b/registry/app/pkg/maven/response.go @@ -0,0 +1,69 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "github.com/harness/gitness/registry/app/pkg/commons" + "github.com/harness/gitness/registry/app/storage" +) + +type Response interface { + GetErrors() []error + SetError(error) +} + +var _ Response = (*HeadArtifactResponse)(nil) +var _ Response = (*GetArtifactResponse)(nil) +var _ Response = (*PutArtifactResponse)(nil) + +type HeadArtifactResponse struct { + Errors []error + ResponseHeaders *commons.ResponseHeaders +} + +func (r *HeadArtifactResponse) GetErrors() []error { + return r.Errors +} +func (r *HeadArtifactResponse) SetError(err error) { + r.Errors = make([]error, 1) + r.Errors[0] = err +} + +type GetArtifactResponse struct { + Errors []error + ResponseHeaders *commons.ResponseHeaders + body *storage.FileReader +} + +func (r *GetArtifactResponse) GetErrors() []error { + return r.Errors +} +func (r *GetArtifactResponse) SetError(err error) { + r.Errors = make([]error, 1) + r.Errors[0] = err +} + +type PutArtifactResponse struct { + Errors []error + ResponseHeaders *commons.ResponseHeaders +} + +func (r *PutArtifactResponse) GetErrors() []error { + return r.Errors +} +func (r *PutArtifactResponse) SetError(err error) { + r.Errors = make([]error, 1) + r.Errors[0] = err +} diff --git a/registry/app/pkg/maven/wire.go b/registry/app/pkg/maven/wire.go new file mode 100644 index 000000000..a234efdf9 --- /dev/null +++ b/registry/app/pkg/maven/wire.go @@ -0,0 +1,63 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package maven + +import ( + "github.com/harness/gitness/app/auth/authz" + corestore "github.com/harness/gitness/app/store" + "github.com/harness/gitness/registry/app/store" + "github.com/harness/gitness/store/database/dbtx" + + "github.com/google/wire" +) + +func LocalRegistryProvider( + dBStore *DBStore, + tx dbtx.Transactor, +) *LocalRegistry { + return NewLocalRegistry(dBStore, tx).(*LocalRegistry) +} + +func RemoteRegistryProvider( + dBStore *DBStore, + tx dbtx.Transactor, +) *RemoteRegistry { + return NewRemoteRegistry(dBStore, tx).(*RemoteRegistry) +} + +func ControllerProvider( + local *LocalRegistry, + remote *RemoteRegistry, + authorizer authz.Authorizer, + dBStore *DBStore, +) *Controller { + return NewController(local, remote, authorizer, dBStore) +} + +func DBStoreProvider( + registryDao store.RegistryRepository, + imageDao store.ImageRepository, + artifactDao store.ArtifactRepository, + spaceStore corestore.SpaceStore, + bandwidthStatDao store.BandwidthStatRepository, + downloadStatDao store.DownloadStatRepository, +) *DBStore { + return NewDBStore(registryDao, imageDao, artifactDao, spaceStore, bandwidthStatDao, downloadStatDao) +} + +var ControllerSet = wire.NewSet(ControllerProvider) +var DBStoreSet = wire.NewSet(DBStoreProvider) +var RegistrySet = wire.NewSet(LocalRegistryProvider, RemoteRegistryProvider) +var WireSet = wire.NewSet(ControllerSet, DBStoreSet, RegistrySet) diff --git a/registry/app/pkg/utils.go b/registry/app/pkg/utils.go new file mode 100644 index 000000000..ebbd41a51 --- /dev/null +++ b/registry/app/pkg/utils.go @@ -0,0 +1,24 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pkg + +import "reflect" + +func IsEmpty(slice interface{}) bool { + if slice == nil { + return true + } + return reflect.ValueOf(slice).Len() == 0 +}