Ejemplo n.º 1
0
        public async Task <IActionResult> Get(string id, string version, CancellationToken cancellationToken)
        {
            if (!NuGetVersion.TryParse(version, out var nugetVersion))
            {
                return(NotFound());
            }

            // Allow read-through caching to happen if it is confiured.
            await _mirror.MirrorAsync(id, nugetVersion, cancellationToken);

            var package = await _packages.FindAsync(id, nugetVersion);

            if (package == null)
            {
                return(NotFound());
            }

            // Documentation: https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource
            var result = new RegistrationLeaf(
                registrationUri: Url.PackageRegistration(id, nugetVersion),
                listed: package.Listed,
                downloads: package.Downloads,
                packageContentUri: Url.PackageDownload(id, nugetVersion),
                published: package.Published,
                registrationIndexUri: Url.PackageRegistration(id));

            return(Json(result));
        }
Ejemplo n.º 2
0
        public async Task <IActionResult> Get(string id, string version, CancellationToken cancellationToken)
        {
            if (!NuGetVersion.TryParse(version, out var nugetVersion))
            {
                return(NotFound());
            }

            // Allow read-through caching to happen if it is configured.
            await _mirror.MirrorAsync(id, nugetVersion, cancellationToken);

            var package = await _packages.FindOrNullAsync(id, nugetVersion, includeUnlisted : true);

            if (package == null)
            {
                return(NotFound());
            }

            var result = new RegistrationLeaf(
                type: RegistrationLeaf.DefaultType,
                registrationUri: Url.PackageRegistration(id, nugetVersion),
                listed: package.Listed,
                downloads: package.Downloads,
                packageContentUrl: Url.PackageDownload(id, nugetVersion),
                published: package.Published,
                registrationIndexUrl: Url.PackageRegistration(id));

            return(Json(result));
        }
Ejemplo n.º 3
0
        public async Task WriteLeafAsync(
            HiveType hive,
            IReadOnlyList <HiveType> replicaHives,
            string id,
            NuGetVersion version,
            RegistrationLeaf leaf)
        {
            var path = _urlBuilder.GetLeafPath(id, version);

            await WriteAsync(hive, replicaHives, path, leaf, "leaf", _entityBuilder.UpdateLeafUrls);
        }
        public async Task <IActionResult> Get(string id, string version)
        {
            if (!NuGetVersion.TryParse(version, out var nugetVersion))
            {
                return(NotFound());
            }

            var package = await _packages.FindAsync(id, nugetVersion);

            if (package == null)
            {
                return(NotFound());
            }

            // Documentation: https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource
            var result = new RegistrationLeaf(
                registrationUri: Url.PackageRegistration(id, nugetVersion),
                listed: package.Listed,
                packageContentUri: Url.PackageDownload(id, nugetVersion),
                published: package.Published,
                registrationIndexUri: Url.PackageRegistration(id));

            return(Json(result));
        }
Ejemplo n.º 5
0
            public Facts(ITestOutputHelper output)
            {
                CloudBlobClient = new Mock <ICloudBlobClient>();
                EntityBuilder   = new Mock <IEntityBuilder>();
                Throttle        = new Mock <IThrottle>();
                Options         = new Mock <IOptionsSnapshot <Catalog2RegistrationConfiguration> >();
                Logger          = output.GetLogger <HiveStorage>();

                Config = new Catalog2RegistrationConfiguration
                {
                    LegacyBaseUrl           = "https://example/reg/",
                    LegacyStorageContainer  = "reg",
                    GzippedBaseUrl          = "https://example/reg-gz/",
                    GzippedStorageContainer = "reg-gz",
                    SemVer2BaseUrl          = "https://example/reg-gz-semver2/",
                    SemVer2StorageContainer = "reg-gz-semver2",
                    EnsureSingleSnapshot    = false,
                };
                LegacyContainer  = new Mock <ICloudBlobContainer>();
                GzippedContainer = new Mock <ICloudBlobContainer>();
                SemVer2Container = new Mock <ICloudBlobContainer>();
                LegacyBlob       = new Mock <ISimpleCloudBlob>();
                GzippedBlob      = new Mock <ISimpleCloudBlob>();
                SemVer2Blob      = new Mock <ISimpleCloudBlob>();
                LegacyStream     = new MemoryStream();
                GzippedStream    = new MemoryStream();
                SemVer2Stream    = new MemoryStream();
                LegacySegment    = new Mock <ISimpleBlobResultSegment>();
                Hive             = HiveType.Legacy;
                ReplicaHives     = new List <HiveType>();
                Id    = "NuGet.Versioning";
                Index = new RegistrationIndex();
                Page  = new RegistrationPage();
                Leaf  = new RegistrationLeaf();

                Options.Setup(x => x.Value).Returns(() => Config);
                CloudBlobClient.Setup(x => x.GetContainerReference(Config.LegacyStorageContainer)).Returns(() => LegacyContainer.Object);
                CloudBlobClient.Setup(x => x.GetContainerReference(Config.GzippedStorageContainer)).Returns(() => GzippedContainer.Object);
                CloudBlobClient.Setup(x => x.GetContainerReference(Config.SemVer2StorageContainer)).Returns(() => SemVer2Container.Object);
                LegacyContainer.Setup(x => x.GetBlobReference(It.IsAny <string>())).Returns(() => LegacyBlob.Object);
                GzippedContainer.Setup(x => x.GetBlobReference(It.IsAny <string>())).Returns(() => GzippedBlob.Object);
                SemVer2Container.Setup(x => x.GetBlobReference(It.IsAny <string>())).Returns(() => SemVer2Blob.Object);
                LegacyBlob.Setup(x => x.Properties).Returns(new BlobProperties());
                LegacyBlob.Setup(x => x.OpenReadAsync(It.IsAny <AccessCondition>())).ReturnsAsync(() => LegacyStream);
                LegacyBlob.Setup(x => x.Uri).Returns(new Uri("https://example/reg/something.json"));
                LegacyBlob
                .Setup(x => x.UploadFromStreamAsync(It.IsAny <Stream>(), It.IsAny <AccessCondition>()))
                .Returns(Task.CompletedTask)
                .Callback <Stream, AccessCondition>((s, _) => s.CopyTo(LegacyStream));
                LegacyBlob.Setup(x => x.ExistsAsync()).ReturnsAsync(true);
                LegacyContainer
                .Setup(x => x.ListBlobsSegmentedAsync(
                           It.IsAny <string>(),
                           It.IsAny <bool>(),
                           It.IsAny <BlobListingDetails>(),
                           It.IsAny <int?>(),
                           It.IsAny <BlobContinuationToken>(),
                           It.IsAny <BlobRequestOptions>(),
                           It.IsAny <OperationContext>(),
                           It.IsAny <CancellationToken>()))
                .Returns(() => Task.FromResult(LegacySegment.Object));
                LegacySegment.Setup(x => x.Results).Returns(new List <ISimpleCloudBlob>());
                GzippedBlob.Setup(x => x.Properties).Returns(new BlobProperties());
                GzippedBlob.Setup(x => x.OpenReadAsync(It.IsAny <AccessCondition>())).ReturnsAsync(() => GzippedStream);
                GzippedBlob.Setup(x => x.Uri).Returns(new Uri("https://example/reg-gz/something.json"));
                GzippedBlob
                .Setup(x => x.UploadFromStreamAsync(It.IsAny <Stream>(), It.IsAny <AccessCondition>()))
                .Returns(Task.CompletedTask)
                .Callback <Stream, AccessCondition>((s, _) => s.CopyTo(GzippedStream));
                GzippedBlob.Setup(x => x.ExistsAsync()).ReturnsAsync(true);
                SemVer2Blob.Setup(x => x.Properties).Returns(new BlobProperties());
                SemVer2Blob.Setup(x => x.OpenReadAsync(It.IsAny <AccessCondition>())).ReturnsAsync(() => SemVer2Stream);
                SemVer2Blob.Setup(x => x.Uri).Returns(new Uri("https://example/reg-gz-semver2/something.json"));
                SemVer2Blob
                .Setup(x => x.UploadFromStreamAsync(It.IsAny <Stream>(), It.IsAny <AccessCondition>()))
                .Returns(Task.CompletedTask)
                .Callback <Stream, AccessCondition>((s, _) => s.CopyTo(SemVer2Stream));
                SemVer2Blob.Setup(x => x.ExistsAsync()).ReturnsAsync(true);

                SerializeToStream(LegacyStream, new Dictionary <string, string> {
                    { "@id", LegacyBlob.Object.Uri.AbsoluteUri }
                });
                SerializeToStream(GzippedStream, new Dictionary <string, string> {
                    { "@id", GzippedBlob.Object.Uri.AbsoluteUri }
                });
                SerializeToStream(SemVer2Stream, new Dictionary <string, string> {
                    { "@id", SemVer2Blob.Object.Uri.AbsoluteUri }
                });

                Target = new HiveStorage(
                    CloudBlobClient.Object,
                    new RegistrationUrlBuilder(Options.Object),
                    EntityBuilder.Object,
                    Throttle.Object,
                    Options.Object,
                    Logger);
            }
Ejemplo n.º 6
0
        public RegistrationIndexModule(IPackageService packageService)
        {
            _packages = packageService ?? throw new ArgumentNullException(nameof(packageService));
            this.Get("v3/registration/{id}/index.json", async(req, res, routeData) =>
            {
                string id = routeData.As <string>("id");
                // Documentation: https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource
                var packages = await _packages.FindAsync(id, includeUnlisted: false, includeDependencies: true);
                var versions = packages.Select(p => p.Version).ToList();

                if (!packages.Any())
                {
                    res.StatusCode = 404;
                    return;
                }

                // TODO: Paging of registration items.
                // "Un-paged" example: https://api.nuget.org/v3/registration3/newtonsoft.json/index.json
                // Paged example: https://api.nuget.org/v3/registration3/fake/index.json
                await res.AsJson(new
                {
                    Count          = packages.Count,
                    TotalDownloads = packages.Sum(p => p.Downloads),
                    Items          = new[]
                    {
                        new RegistrationIndexItem(
                            packageId: id,
                            items: packages.Select(p => ToRegistrationIndexLeaf(req, p)).ToList(),
                            lower: versions.Min().ToNormalizedString(),
                            upper: versions.Max().ToNormalizedString()
                            ),
                    }
                });
            });

            this.Get("v3/registration/{id}/{version}.json", async(req, res, routeData) =>
            {
                string id      = routeData.As <string>("id");
                string version = routeData.As <string>("version");

                if (!NuGetVersion.TryParse(version, out var nugetVersion))
                {
                    res.StatusCode = 400;
                    return;
                }

                var package = await _packages.FindAsync(id, nugetVersion, false, includeDependencies: false);

                if (package == null)
                {
                    res.StatusCode = 404;
                    return;
                }

                // Documentation: https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource
                var result = new RegistrationLeaf(
                    registrationUri: req.PackageRegistration(id, nugetVersion, ""),
                    listed: package.Listed,
                    downloads: package.Downloads,
                    packageContentUri: req.PackageDownload(id, nugetVersion, ""),
                    published: package.Published,
                    registrationIndexUri: req.PackageRegistration(id, ""));

                await res.AsJson(result);
            });
        }
Ejemplo n.º 7
0
 public void UpdateLeafUrls(RegistrationLeaf leaf, HiveType fromHive, HiveType toHive)
 {
     leaf.Url          = _urlBuilder.ConvertHive(fromHive, toHive, leaf.Url);
     leaf.Registration = _urlBuilder.ConvertHive(fromHive, toHive, leaf.Registration);
 }
Ejemplo n.º 8
0
        public CacheRegistrationIndexModule(IMirrorService mirror)
        {
            this._mirror = mirror ?? throw new ArgumentNullException(nameof(mirror));
            this.Get("cache/v3/registration/{id}/index.json", async(req, res, routeData) =>
            {
                string id = routeData.As <string>("id");
                // Documentation: https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource
                var upstreamPackages = (await _mirror.FindUpstreamMetadataAsync(id, CancellationToken.None)).ToList();
                var versions         = upstreamPackages.Select(p => p.Identity.Version).ToList();

                if (!upstreamPackages.Any())
                {
                    res.StatusCode = 404;
                    return;
                }

                // TODO: Paging of registration items.
                // "Un-paged" example: https://api.nuget.org/v3/registration3/newtonsoft.json/index.json
                // Paged example: https://api.nuget.org/v3/registration3/fake/index.json
                await res.AsJson(new
                {
                    Count          = upstreamPackages.Count,
                    TotalDownloads = upstreamPackages.Sum(p => p.DownloadCount),
                    Items          = new[]
                    {
                        new RegistrationIndexItem(
                            packageId: id,
                            items: upstreamPackages.Select(p => ToRegistrationIndexLeaf(req, p)).ToList(),
                            lower: versions.Min().ToNormalizedString(),
                            upper: versions.Max().ToNormalizedString()
                            ),
                    }
                });
            });

            this.Get("cache/v3/registration/{id}/{version}.json", async(req, res, routeData) =>
            {
                string id      = routeData.As <string>("id");
                string version = routeData.As <string>("version");

                if (!NuGetVersion.TryParse(version, out var nugetVersion))
                {
                    res.StatusCode = 400;
                    return;
                }

                // Allow read-through caching to happen if it is confiured.
                await _mirror.MirrorAsync(id, nugetVersion, CancellationToken.None);

                var package = await _mirror.FindAsync(new PackageIdentity(id, nugetVersion));

                if (package == null)
                {
                    res.StatusCode = 404;
                    return;
                }

                // Documentation: https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource
                var result = new RegistrationLeaf(
                    registrationUri: req.PackageRegistration(id, nugetVersion, "cache"),
                    listed: package.IsListed,
                    downloads: package.DownloadCount.GetValueOrDefault(),
                    packageContentUri: req.PackageDownload(id, nugetVersion, "cache"),
                    published: package.Published.GetValueOrDefault(),
                    registrationIndexUri: req.PackageRegistration(id, "cache"));

                await res.AsJson(result);
            });
        }
Ejemplo n.º 9
0
            public Facts(ITestOutputHelper output)
            {
                Storage       = new Mock <IHiveStorage>();
                Merger        = new Mock <IHiveMerger>();
                EntityBuilder = new Mock <IEntityBuilder>();
                Options       = new Mock <IOptionsSnapshot <Catalog2RegistrationConfiguration> >();
                Logger        = output.GetLogger <HiveUpdater>();

                Config             = new Catalog2RegistrationConfiguration();
                Hive               = HiveType.SemVer2;
                ReplicaHives       = new List <HiveType>();
                Id                 = "NuGet.Versioning";
                Entries            = new List <CatalogCommitItem>();
                EntryToCatalogLeaf = new Dictionary <CatalogCommitItem, PackageDetailsCatalogLeaf>(
                    ReferenceEqualityComparer <CatalogCommitItem> .Default);
                RegistrationIndex = new RegistrationIndex
                {
                    Items = new List <RegistrationPage>
                    {
                        new RegistrationPage
                        {
                            Lower = "1.0.0",
                            Upper = "3.0.0",
                            Count = 2,
                            Items = new List <RegistrationLeafItem>
                            {
                                new RegistrationLeafItem
                                {
                                    Url          = $"https://example/reg/{Id.ToLowerInvariant()}/1.0.0.json",
                                    CatalogEntry = new RegistrationCatalogEntry
                                    {
                                        Version = "1.0.0",
                                    }
                                },
                                new RegistrationLeafItem
                                {
                                    Url          = $"https://example/reg/{Id.ToLowerInvariant()}/3.0.0.json",
                                    CatalogEntry = new RegistrationCatalogEntry
                                    {
                                        Version = "3.0.0",
                                    }
                                },
                            }
                        }
                    }
                };
                MergeResult = new HiveMergeResult(
                    new HashSet <PageInfo>(),
                    new HashSet <LeafInfo>(),
                    new HashSet <LeafInfo>());
                RegistrationLeaf   = new RegistrationLeaf();
                RegistrationCommit = new CatalogCommit(
                    "b580f835-f041-4361-aa46-57e5dc338a63",
                    new DateTimeOffset(2019, 10, 25, 0, 0, 0, TimeSpan.Zero));

                Options.Setup(x => x.Value).Returns(() => Config);
                Storage
                .Setup(x => x.ReadIndexOrNullAsync(It.IsAny <HiveType>(), It.IsAny <string>()))
                .ReturnsAsync(() => RegistrationIndex);
                var concreteHiveMerger = new HiveMerger(Options.Object, output.GetLogger <HiveMerger>());

                Merger
                .Setup(x => x.MergeAsync(It.IsAny <IndexInfo>(), It.IsAny <IReadOnlyList <CatalogCommitItem> >()))
                .Returns <IndexInfo, IReadOnlyList <CatalogCommitItem> >((i, e) => concreteHiveMerger.MergeAsync(i, e));
                EntityBuilder
                .Setup(x => x.NewLeaf(It.IsAny <RegistrationLeafItem>()))
                .Returns(() => RegistrationLeaf);
                EntityBuilder
                .Setup(x => x.UpdateNonInlinedPageItem(
                           It.IsAny <RegistrationPage>(),
                           It.IsAny <HiveType>(),
                           It.IsAny <string>(),
                           It.IsAny <int>(),
                           It.IsAny <NuGetVersion>(),
                           It.IsAny <NuGetVersion>()))
                .Callback <RegistrationPage, HiveType, string, int, NuGetVersion, NuGetVersion>((p, h, id, c, l, u) =>
                {
                    p.Url = $"https://example/reg/" +
                            $"{id.ToLowerInvariant()}/" +
                            $"{l.ToNormalizedString().ToLowerInvariant()}/" +
                            $"{u.ToNormalizedString().ToLowerInvariant()}.json";
                });

                Target = new HiveUpdater(
                    Storage.Object,
                    Merger.Object,
                    EntityBuilder.Object,
                    Options.Object,
                    Logger);
            }
Ejemplo n.º 10
0
        /// <summary>
        /// Handle the logic to index a package from the <paramref name="nuspecReader"/> and store information in the <paramref name="registrationIndex"/> if provided or create a new entry
        /// </summary>
        /// <param name="nuspecReader">The nuspecReader to be used to read package information</param>
        /// <param name="registrationIndex">The <see cref="RegistrationResult"/> instance which should be used to create new version if package id already exists</param>
        /// <returns>The <paramref name="registrationIndex"/> instance of provided or a new one</returns>
        protected virtual async Task <RegistrationResult> IndexPackageCore(INuspecCoreReader nuspecReader, RegistrationResult registrationIndex)
        {
            bool   isNewPackageId             = false;
            var    metadata                   = nuspecReader.GetMetadata();
            string version                    = nuspecReader.GetVersion().ToNormalizedString();
            string packageRegistrationBaseUrl = $"{registrationServiceUrl + nuspecReader.GetId()}/index.json";

            if (registrationIndex == null)
            {
                registrationIndex = new RegistrationResult()
                {
                    Id = packageRegistrationBaseUrl
                };

                isNewPackageId = true;
            }

            RegistrationPage registrationPage = registrationIndex.Items.FirstOrDefault();

            if (registrationPage == null)
            {
                registrationPage = new RegistrationPage();
                registrationIndex.Items.Add(registrationPage);
            }

            bool versionExists = this.IsVersionAlreadyExisting(nuspecReader.GetId(), version);

            if (versionExists)
            {
                throw new PackageVersionAlreadyExistsException($"The version {version} already exists for package {nuspecReader.GetId()}");
            }

            var packageSummary = new NuGetPackageSummary()
            {
                PackageMetadataUrl = registrationServiceUrl + nuspecReader.GetId() + "/index.json",
                Id      = nuspecReader.GetId(),
                Version = nuspecReader.GetVersion().ToFullString()
            };

            await this.AddNewVersion(packageSummary.Id, new NuGetPackageVersion()
            {
                PackageMetadataUrl = registrationServiceUrl + nuspecReader.GetId() + "/" + version, Version = version, Downloads = 0
            });

            foreach (var m in metadata)
            {
                if ("title".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase))
                {
                    packageSummary.Title = m.Value;
                }
                else if ("description".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase))
                {
                    packageSummary.Description = m.Value;
                }
                else if ("authors".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase) && !string.IsNullOrEmpty(m.Value))
                {
                    packageSummary.Authors = m.Value.Split(",");
                }
                else if ("owners".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase) && !string.IsNullOrEmpty(m.Value))
                {
                    packageSummary.Owners = m.Value.Split(",");
                }
                else if ("requireLicenseAcceptance".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase))
                {
                    packageSummary.RequireLicenseAcceptance = bool.Parse(m.Value);
                }
                else if ("licenseUrl".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase))
                {
                    packageSummary.LicenseUrl = m.Value;
                }
                else if ("projectUrl".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase))
                {
                    packageSummary.ProjectUrl = m.Value;
                }
                else if ("iconUrl".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase))
                {
                    packageSummary.IconUrl = m.Value;
                }
                else if ("copyright".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase))
                {
                    packageSummary.Copyright = m.Value;
                }
                else if ("tags".Equals(m.Key, StringComparison.InvariantCultureIgnoreCase))
                {
                    packageSummary.Tags = m.Value;
                }
            }

            RegistrationLeaf registrationLeaf = new RegistrationLeaf();

            registrationLeaf.CatalogEntry   = packageSummary;
            registrationLeaf.PackageContent = $"{this.packageContentServiceUrl}{nuspecReader.GetId()}/{version}/{nuspecReader.GetId()}.{version}.nupkg";

            var versions = await this.GetAllVersions(packageSummary.Id).ConfigureAwait(false);

            string lowerVersion = versions.First();
            string upperVersion = versions.Last();

            registrationPage.Id = $"{registrationServiceUrl + nuspecReader.GetId()}/index.json/#page/{lowerVersion}/{upperVersion}";
            registrationPage.Items.Add(registrationLeaf);
            registrationPage.Lower = lowerVersion;
            registrationPage.Upper = upperVersion;

            if (isNewPackageId)
            {
                await this.AddRegistrationResult(registrationIndex).ConfigureAwait(false);
            }

            return(registrationIndex);
        }