diff --git a/registry/app/api/controller/metadata/artifact_mapper.go b/registry/app/api/controller/metadata/artifact_mapper.go index 4154da43e..b803afff1 100644 --- a/registry/app/api/controller/metadata/artifact_mapper.go +++ b/registry/app/api/controller/metadata/artifact_mapper.go @@ -16,14 +16,17 @@ package metadata import ( "context" + "encoding/json" "errors" "fmt" "path/filepath" + "strconv" "strings" "github.com/harness/gitness/app/url" artifactapi "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact" "github.com/harness/gitness/registry/app/metadata" + npm2 "github.com/harness/gitness/registry/app/metadata/npm" "github.com/harness/gitness/registry/types" "github.com/rs/zerolog/log" @@ -503,19 +506,31 @@ func GetPythonArtifactDetail( func GetNPMArtifactDetail( image *types.Image, artifact *types.Artifact, metadata map[string]interface{}, + downloadCount int64, ) artifactapi.ArtifactDetail { createdAt := GetTimeInMs(artifact.CreatedAt) modifiedAt := GetTimeInMs(artifact.UpdatedAt) - artifactDetail := &artifactapi.ArtifactDetail{ - CreatedAt: &createdAt, - ModifiedAt: &modifiedAt, - Name: &image.Name, - Version: artifact.Version, + var npmMetadata npm2.NpmMetadata + err := json.Unmarshal(artifact.Metadata, &npmMetadata) + if err != nil { + log.Error().Err(err).Msgf("Error unmarshalling the artifact metadata "+ + "for image: [%s], version: [%s]", image.Name, artifact.Version) + return artifactapi.ArtifactDetail{} } - err := artifactDetail.FromNpmArtifactDetailConfig(artifactapi.NpmArtifactDetailConfig{ + totalSize := strconv.FormatInt(npmMetadata.Size, 10) + artifactDetail := &artifactapi.ArtifactDetail{ + CreatedAt: &createdAt, + ModifiedAt: &modifiedAt, + Name: &image.Name, + Version: artifact.Version, + DownloadCount: &downloadCount, + Size: &totalSize, + } + err = artifactDetail.FromNpmArtifactDetailConfig(artifactapi.NpmArtifactDetailConfig{ Metadata: &metadata, }) if err != nil { + log.Error().Err(err).Msgf("Error setting the artifact details for image: [%s]", image.Name) return artifactapi.ArtifactDetail{} } return *artifactDetail diff --git a/registry/app/api/controller/metadata/get_artifact_detail.go b/registry/app/api/controller/metadata/get_artifact_detail.go index 1eda90d07..4e9aad17d 100644 --- a/registry/app/api/controller/metadata/get_artifact_detail.go +++ b/registry/app/api/controller/metadata/get_artifact_detail.go @@ -95,6 +95,16 @@ func (c *APIController) GetArtifactDetails( }, nil } + downloadCount, err := c.DownloadStatRepository.GetTotalDownloadsForArtifactID(ctx, art.ID) + + if err != nil { + return artifact.GetArtifactDetails500JSONResponse{ + InternalServerErrorJSONResponse: artifact.InternalServerErrorJSONResponse( + *GetErrorResponse(http.StatusInternalServerError, err.Error()), + ), + }, nil + } + var artifactDetails artifact.ArtifactDetail // FIXME: Arvind: Unify the metadata structure to avoid this type checking @@ -144,7 +154,7 @@ func (c *APIController) GetArtifactDetails( ), }, nil } - artifactDetails = GetNPMArtifactDetail(img, art, result) + artifactDetails = GetNPMArtifactDetail(img, art, result, downloadCount) case artifact.PackageTypeDOCKER: case artifact.PackageTypeHELM: default: diff --git a/registry/app/api/controller/pkg/npm/download.go b/registry/app/api/controller/pkg/npm/download.go index f8d578c04..f42637dd4 100644 --- a/registry/app/api/controller/pkg/npm/download.go +++ b/registry/app/api/controller/pkg/npm/download.go @@ -34,6 +34,8 @@ func (c *controller) DownloadPackageFile( f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response { info.RegIdentifier = registry.Name info.RegistryID = registry.ID + info.Registry = registry + info.ParentID = registry.ParentID npmRegistry, ok := a.(npm2.Registry) if !ok { return &GetArtifactResponse{ diff --git a/registry/app/api/controller/pkg/npm/download_file.go b/registry/app/api/controller/pkg/npm/download_file.go index 906b6c00c..386891117 100644 --- a/registry/app/api/controller/pkg/npm/download_file.go +++ b/registry/app/api/controller/pkg/npm/download_file.go @@ -34,6 +34,8 @@ func (c *controller) DownloadPackageFileByName( f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response { info.RegIdentifier = registry.Name info.RegistryID = registry.ID + info.Registry = registry + info.ParentID = registry.ParentID npmRegistry, ok := a.(npm2.Registry) if !ok { return &GetArtifactResponse{ diff --git a/registry/app/api/controller/pkg/npm/head_file.go b/registry/app/api/controller/pkg/npm/head_file.go index 738e6f8c8..6f062e8b5 100644 --- a/registry/app/api/controller/pkg/npm/head_file.go +++ b/registry/app/api/controller/pkg/npm/head_file.go @@ -34,6 +34,8 @@ func (c *controller) HeadPackageFileByName( f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response { info.RegIdentifier = registry.Name info.RegistryID = registry.ID + info.Registry = registry + info.ParentID = registry.ParentID npmRegistry, ok := a.(npm2.Registry) if !ok { return &HeadMetadataResponse{ diff --git a/registry/app/api/controller/pkg/npm/list_tag.go b/registry/app/api/controller/pkg/npm/list_tag.go index a6a6046a0..f65a01b3b 100644 --- a/registry/app/api/controller/pkg/npm/list_tag.go +++ b/registry/app/api/controller/pkg/npm/list_tag.go @@ -34,6 +34,8 @@ func (c *controller) ListTags( f := func(registry types.Registry, a pkg.Artifact) response.Response { info.RegIdentifier = registry.Name info.RegistryID = registry.ID + info.Registry = registry + info.ParentID = registry.ParentID npmRegistry, ok := a.(npm2.Registry) if !ok { return &ListTagResponse{ diff --git a/registry/app/api/controller/pkg/npm/metadata.go b/registry/app/api/controller/pkg/npm/metadata.go index 19263a003..670df88d8 100644 --- a/registry/app/api/controller/pkg/npm/metadata.go +++ b/registry/app/api/controller/pkg/npm/metadata.go @@ -42,6 +42,8 @@ func (c *controller) GetPackageMetadata( f := func(registry types.Registry, a pkg.Artifact) response.Response { info.RegIdentifier = registry.Name info.RegistryID = registry.ID + info.Registry = registry + info.ParentID = registry.ParentID npmRegistry, ok := a.(npm2.Registry) if !ok { return &GetMetadataResponse{ diff --git a/registry/app/store/database.go b/registry/app/store/database.go index 70c08647d..dfcfe68aa 100644 --- a/registry/app/store/database.go +++ b/registry/app/store/database.go @@ -505,6 +505,7 @@ type DownloadStatRepository interface { imageID int64, ) (map[string]int64, error) CreateByRegistryIDImageAndArtifactName(ctx context.Context, regID int64, image string, artifactName string) error + GetTotalDownloadsForArtifactID(ctx context.Context, artifactID int64) (int64, error) } type BandwidthStatRepository interface { diff --git a/registry/app/store/database/download_stat.go b/registry/app/store/database/download_stat.go index e05dba8d5..a28fbd438 100644 --- a/registry/app/store/database/download_stat.go +++ b/registry/app/store/database/download_stat.go @@ -155,6 +155,28 @@ func (d DownloadStatDao) GetTotalDownloadsForImage(ctx context.Context, imageID return count, nil } +func (d DownloadStatDao) GetTotalDownloadsForArtifactID(ctx context.Context, artifactID int64) (int64, error) { + q := databaseg.Builder.Select(`count(*)`). + From("download_stats ds").Where("ds.download_stat_artifact_id = ?", artifactID) + + sql, args, err := q.ToSql() + if err != nil { + return 0, errors.Wrap(err, "Failed to convert query to sql") + } + // Log the final sql query + finalQuery := util.FormatQuery(sql, args) + log.Ctx(ctx).Debug().Str("sql", finalQuery).Msg("Executing GetTotalDownloadsForArtifact query") + // Execute query + db := dbtx.GetAccessor(ctx, d.db) + + var count int64 + err = db.QueryRowContext(ctx, sql, args...).Scan(&count) + if err != nil { + return 0, databaseg.ProcessSQLErrorf(ctx, err, "Failed executing count query") + } + return count, nil +} + func (d DownloadStatDao) GetTotalDownloadsForManifests( ctx context.Context, artifactVersions []string, diff --git a/registry/app/store/database/upstream_proxy.go b/registry/app/store/database/upstream_proxy.go index 06032467e..bf0b46fa1 100644 --- a/registry/app/store/database/upstream_proxy.go +++ b/registry/app/store/database/upstream_proxy.go @@ -135,7 +135,7 @@ func (r UpstreamproxyDao) Get(ctx context.Context, id int64) (upstreamProxy *typ dst := new(upstreamProxyDB) if err = db.GetContext(ctx, dst, sql, args...); err != nil { - return nil, databaseg.ProcessSQLErrorf(ctx, err, "Failed to get tag detail") + return nil, databaseg.ProcessSQLErrorf(ctx, err, "Failed to get upstream proxy detail") } return r.mapToUpstreamProxy(ctx, dst) @@ -159,7 +159,7 @@ func (r UpstreamproxyDao) GetByRegistryIdentifier( dst := new(upstreamProxyDB) if err = db.GetContext(ctx, dst, sql, args...); err != nil { - return nil, databaseg.ProcessSQLErrorf(ctx, err, "Failed to get tag detail") + return nil, databaseg.ProcessSQLErrorf(ctx, err, "Failed to get upstream proxy detail") } return r.mapToUpstreamProxy(ctx, dst)