drone/registry/app/api/handler/packages/handler.go
Arvind Choudhary f660d8b0cd feat: [AH-994]: Updated Client setup details. Update pypi to python (#3547)
* Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into AH-994-client-setup-details-update
* [AH-994]: Merge conflict fixed
* [AH-994]: Merge conflict fixed
* [AH-994]: Updated makefile
* [AH-994]: Merge conflict fixed
* [AH-994]: Updated Client setup details. Update pypi to python
2025-03-13 04:45:55 +00:00

187 lines
5.8 KiB
Go

// 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 packages
import (
"context"
"fmt"
"net/http"
"strings"
"time"
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"
urlprovider "github.com/harness/gitness/app/url"
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/storage"
"github.com/harness/gitness/registry/app/store"
"github.com/harness/gitness/types/enum"
"github.com/rs/zerolog/log"
)
func NewHandler(
registryDao store.RegistryRepository,
spaceStore corestore.SpaceStore, tokenStore corestore.TokenStore,
userCtrl *usercontroller.Controller, authenticator authn.Authenticator,
urlProvider urlprovider.Provider, authorizer authz.Authorizer,
) Handler {
return &handler{
RegistryDao: registryDao,
SpaceStore: spaceStore,
TokenStore: tokenStore,
UserCtrl: userCtrl,
Authenticator: authenticator,
URLProvider: urlProvider,
Authorizer: authorizer,
}
}
type handler struct {
RegistryDao store.RegistryRepository
SpaceStore corestore.SpaceStore
TokenStore corestore.TokenStore
UserCtrl *usercontroller.Controller
Authenticator authn.Authenticator
URLProvider urlprovider.Provider
Authorizer authz.Authorizer
}
type Handler interface {
GetRegistryCheckAccess(
ctx context.Context,
r *http.Request,
reqPermissions ...enum.Permission,
) error
GetArtifactInfo(r *http.Request) (pkg.ArtifactInfo, errcode.Error)
GetAuthenticator() authn.Authenticator
HandleErrors(ctx context.Context, errors errcode.Error, w http.ResponseWriter)
ServeContent(
w http.ResponseWriter, r *http.Request, fileReader *storage.FileReader, filename string,
)
}
type PathPackageType string
const (
PathPackageTypeGeneric PathPackageType = "generic"
PathPackageTypeMaven PathPackageType = "maven"
PathPackageTypePython PathPackageType = "python"
)
var packageTypeMap = map[PathPackageType]artifact2.PackageType{
PathPackageTypeGeneric: artifact2.PackageTypeGENERIC,
PathPackageTypeMaven: artifact2.PackageTypeMAVEN,
PathPackageTypePython: artifact2.PackageTypePYTHON,
}
func (h *handler) GetAuthenticator() authn.Authenticator {
return h.Authenticator
}
func (h *handler) GetRegistryCheckAccess(
ctx context.Context,
r *http.Request,
reqPermissions ...enum.Permission,
) error {
info, _ := h.GetArtifactInfo(r)
return pkg.GetRegistryCheckAccess(ctx, h.RegistryDao, h.Authorizer,
h.SpaceStore,
info.RegIdentifier, info.ParentID, reqPermissions...)
}
func (h *handler) GetArtifactInfo(r *http.Request) (pkg.ArtifactInfo, errcode.Error) {
ctx := r.Context()
rootIdentifier, registryIdentifier, pathPackageType, err := extractPathVars(r)
if err != nil {
return pkg.ArtifactInfo{}, errcode.ErrCodeInvalidRequest.WithDetail(err)
}
rootSpace, err := h.SpaceStore.FindByRefCaseInsensitive(ctx, rootIdentifier)
if err != nil {
log.Ctx(ctx).Error().Msgf("Root space not found: %s", rootIdentifier)
return pkg.ArtifactInfo{}, errcode.ErrCodeRootNotFound.WithDetail(err)
}
registry, err := h.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.ArtifactInfo{}, errcode.ErrCodeRegNotFound.WithDetail(err)
}
_, 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.ArtifactInfo{}, errcode.ErrCodeParentNotFound.WithDetail(err)
}
return pkg.ArtifactInfo{
BaseInfo: &pkg.BaseInfo{
RootIdentifier: rootIdentifier,
RootParentID: rootSpace.ID,
ParentID: registry.ParentID,
PathPackageType: pathPackageType,
},
RegIdentifier: registryIdentifier,
}, errcode.Error{}
}
func (h *handler) HandleErrors(ctx context.Context, err errcode.Error, w http.ResponseWriter) {
if !commons.IsEmptyError(err) {
w.WriteHeader(err.Code.Descriptor().HTTPStatusCode)
_ = errcode.ServeJSON(w, err)
log.Ctx(ctx).Error().Msgf("Error occurred while performing artifact action: %s", err.Message)
}
}
// extractPathVars extracts rootSpace, registryId, pathPackageType from the path
// Path format: /pkg/:rootSpace/:registry/:pathPackageType/...
func extractPathVars(r *http.Request) (
rootIdentifier string,
registry string,
packageType artifact2.PackageType,
err error,
) {
path := r.URL.Path
parts := strings.Split(path, "/")
if len(parts) < 5 {
return "", "", "", fmt.Errorf("invalid path: %s", path)
}
rootIdentifier = parts[2]
registry = parts[3]
pathPackageType := PathPackageType(parts[4])
if _, ok := packageTypeMap[pathPackageType]; !ok {
return "", "", "", fmt.Errorf("invalid package type: %s", packageType)
}
return rootIdentifier, registry, packageTypeMap[pathPackageType], nil
}
func (h *handler) ServeContent(
w http.ResponseWriter, r *http.Request, fileReader *storage.FileReader, filename string,
) {
if fileReader != nil {
http.ServeContent(w, r, filename, time.Time{}, fileReader)
}
}