Пример #1
0
        public void NullThrowsException()
        {
            // Arrange
            string packageId = null;

            // Act & Assert
            ExceptionAssert.ThrowsArgNull(() => PackageIdValidator.IsValidPackageId(packageId), "packageId");
        }
Пример #2
0
 private void ValidateBundleId(string id)
 {
     if (string.IsNullOrWhiteSpace(id) || !PackageIdValidator.IsValidPackageId(id))
     {
         string message = string.Format(Resources.ExtensionBundleConfigMissingId, ScriptConstants.HostMetadataFileName);
         throw new ArgumentException(message);
     }
 }
Пример #3
0
        public void ValidatePackageIdInvalidIdThrows()
        {
            // Arrange
            string packageId = "  Invalid  . Woo   .";

            // Act & Assert
            ExceptionAssert.ThrowsArgumentException(() => PackageIdValidator.ValidatePackageId(packageId), "The package ID '  Invalid  . Woo   .' contains invalid characters. Examples of valid package IDs include 'MyPackage' and 'MyPackage.Sample'.");
        }
Пример #4
0
        public void ValidatePackageIdInvalidIdThrows()
        {
            // Arrange
            string packageId = "  Invalid  . Woo   .";

            // Act & Assert
            ExceptionAssert.ThrowsArgumentException(() => PackageIdValidator.ValidatePackageId(packageId), "Package id '  Invalid  . Woo   .' is invalid.");
        }
        public void NullThrowsException()
        {
            // Arrange
            string packageId = null;

            // Act & Assert
            Assert.Throws <ArgumentNullException>(paramName: "packageId",
                                                  testCode: () => PackageIdValidator.IsValidPackageId(packageId));
        }
        public void IdExceedingMaxLengthThrows(int idTestLength)
        {
            // Arrange
            string packageId = new string('d', idTestLength);

            // Act && Assert
            ExceptionAssert.ThrowsArgumentException(
                () => PackageIdValidator.ValidatePackageId(packageId),
                "Id must not exceed 100 characters.");
        }
Пример #7
0
        public void IsValidPackageId_LongPackageIdWithUnMatchedCharAtTheEnd_Fails()
        {
            // Arrange
            string packageId = string.Concat(new string('_', 100), "!");

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
Пример #8
0
        public void IsValidPackageId_PackageIdWithTwoUnderscores_Success()
        {
            // Arrange
            string packageId = "Hello__World";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
        public void NumbersAndWordsDotSeparatedAllowd()
        {
            // Arrange
            string packageId = "1.2.3.4.Uno.Dos.Tres.Cuatro";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
        public void MultipleDotSeparatorsAllowed()
        {
            // Arrange
            string packageId = "I.Like.Writing.Unit.Tests";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
        public void UnderscoreDotAndDashSeparatorsAreValid()
        {
            // Arrange
            string packageId = "Nu_Get.Core-IsCool";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
        public void EndingWithSeparatorsNotAllowed()
        {
            // Arrange
            string packageId = "StartWithSeparator.";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
        public void EmptyIsNotValid()
        {
            // Arrange
            string packageId = "";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
        public void DotToolsIsNotAllowed()
        {
            // Arrange
            string packageId = ".tools";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
Пример #15
0
        public virtual async Task <ActionResult> GetPackage(string id, string version)
        {
            // some security paranoia about URL hacking somehow creating e.g. open redirects
            // validate user input: explicit calls to the same validators used during Package Registrations
            // Ideally shouldn't be necessary?
            if (!PackageIdValidator.IsValidPackageId(id ?? ""))
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The format of the package id is invalid"));
            }

            // if version is non-null, check if it's semantically correct and normalize it.
            if (!String.IsNullOrEmpty(version))
            {
                NuGetVersion dummy;
                if (!NuGetVersion.TryParse(version, out dummy))
                {
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The package version is not a valid semantic version"));
                }
                // Normalize the version
                version = NuGetVersionNormalizer.Normalize(version);
            }
            else
            {
                // if version is null, get the latest version from the database.
                // This ensures that on package restore scenario where version will be non null, we don't hit the database.
                try
                {
                    var package = PackageService.FindPackageByIdAndVersion(id, version, allowPrerelease: false);
                    if (package == null)
                    {
                        return(new HttpStatusCodeWithBodyResult(HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version)));
                    }
                    version = package.NormalizedVersion;
                }
                catch (SqlException e)
                {
                    QuietLog.LogHandledException(e);

                    // Database was unavailable and we don't have a version, return a 503
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
                }
                catch (DataException e)
                {
                    QuietLog.LogHandledException(e);

                    // Database was unavailable and we don't have a version, return a 503
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
                }
            }

            return(await PackageFileService.CreateDownloadPackageActionResultAsync(
                       HttpContext.Request.Url,
                       id, version));
        }
        public void ConsecutiveSeparatorsNotAllowed()
        {
            // Arrange
            string packageId = "I_.Like.-Separators";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
        public void NonAlphaNumericUnderscoreDotDashIsInvalid()
        {
            // Arrange
            string packageId = "ILike*Asterisks";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
        public void AlphaNumericIsValid()
        {
            // Arrange
            string packageId = "42This1Is4You";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
Пример #19
0
        private void CleanDownloadData(DownloadData data)
        {
            var invalidIdCount            = 0;
            var invalidVersionCount       = 0;
            var nonNormalizedVersionCount = 0;

            foreach (var id in data.Keys.ToList())
            {
                var isValidId = id.Length <= PackageIdValidator.MaxPackageIdLength &&
                                PackageIdValidator.IsValidPackageIdWithTimeout(id);
                if (!isValidId)
                {
                    invalidIdCount++;
                }

                foreach (var version in data[id].Keys.ToList())
                {
                    var isValidVersion = NuGetVersion.TryParse(version, out var parsedVersion);
                    if (!isValidVersion)
                    {
                        invalidVersionCount++;
                    }

                    if (!isValidId || !isValidVersion)
                    {
                        // Clear the download count if the ID or version is invalid.
                        data.SetDownloadCount(id, version, 0);
                        continue;
                    }

                    var normalizedVersion   = parsedVersion.ToNormalizedString();
                    var isNormalizedVersion = StringComparer.OrdinalIgnoreCase.Equals(version, normalizedVersion);

                    if (!isNormalizedVersion)
                    {
                        nonNormalizedVersionCount++;

                        // Use the normalized version string if the original was not normalized.
                        var downloads = data.GetDownloadCount(id, version);
                        data.SetDownloadCount(id, version, 0);
                        data.SetDownloadCount(id, normalizedVersion, downloads);
                    }
                }
            }

            _logger.LogInformation(
                "There were {InvalidIdCount} invalid IDs, {InvalidVersionCount} invalid versions, and " +
                "{NonNormalizedVersionCount} non-normalized IDs.",
                invalidIdCount,
                invalidVersionCount,
                nonNormalizedVersionCount);
        }
Пример #20
0
        private string IsValid(string columnName)
        {
            if (columnName == "Id")
            {
                if (String.IsNullOrEmpty(Id))
                {
                    return(null);
                }

                if (!PackageIdValidator.IsValidPackageId(Id))
                {
                    return("Value '" + Id + "' cannot be converted.");
                }
            }

            return(null);
        }
        public async Task <bool> DoesPackageIdExistAsync(
            string packageIdPattern,
            SearchScorerSettings settings)
        {
            Task <bool> controlExistsTask;
            Task <bool> treatmentExistsTask;

            if (PackageIdValidator.IsValidPackageId(packageIdPattern))
            {
                var query = $"packageid:{packageIdPattern}";
                controlExistsTask   = DoesPackageIdExistInQueryAsync(packageIdPattern, settings.ControlBaseUrl, query, take: 1);
                treatmentExistsTask = DoesPackageIdExistInQueryAsync(packageIdPattern, settings.TreatmentBaseUrl, query, take: 1);
            }
            else if (packageIdPattern.EndsWith("*"))
            {
                var prefix = packageIdPattern.Substring(0, packageIdPattern.Length - 1).TrimEnd(Separators);
                if (!PackageIdValidator.IsValidPackageId(prefix))
                {
                    throw new ArgumentException($"The package ID '{packageIdPattern}' looks like a pattern but the part before the wildcard is not a valid package ID.");
                }

                var pieces = prefix
                             .Split(Separators)
                             .Where(x => !string.IsNullOrWhiteSpace(x));
                var query = string.Join(" ", pieces);
                controlExistsTask   = DoesPackageIdExistInQueryAsync(packageIdPattern, settings.ControlBaseUrl, query, take: 1000);
                treatmentExistsTask = DoesPackageIdExistInQueryAsync(packageIdPattern, settings.TreatmentBaseUrl, query, take: 1000);
            }
            else
            {
                throw new NotSupportedException();
            }

            await Task.WhenAll(controlExistsTask, treatmentExistsTask);

            if (controlExistsTask.Result != treatmentExistsTask.Result)
            {
                throw new ArgumentNullException(
                          $"The package ID '{packageIdPattern}' has inconsistent availability. " +
                          $"Exists in control: {controlExistsTask.Result}. " +
                          $"Exists in treatment: {treatmentExistsTask.Result}.");
            }

            return(controlExistsTask.Result);
        }
        private bool TryGetSinglePackageId(
            ParsedQuery parsed,
            out string packageId)
        {
            if (parsed.Grouping.TryGetValue(QueryField.PackageId, out var terms) &&
                terms.Count == 1)
            {
                packageId = terms.First();
                if (packageId.Length <= PackageIdValidator.MaxPackageIdLength &&
                    PackageIdValidator.IsValidPackageIdWithTimeout(packageId))
                {
                    return(true);
                }
            }

            packageId = null;
            return(false);
        }
        public static Validated <string> PackageId(object value)
        {
            var validatedString = String(value);

            if (!validatedString.IsValid)
            {
                return(validatedString);
            }

            try
            {
                PackageIdValidator.ValidatePackageId(validatedString.Data);
                return(validatedString);
            }
            catch (Exception ex)
            {
                return(Validated.Invalid <string>(ex));
            }
        }
        bool IsValidLibraryName()
        {
            LibraryNameError = null;

            if (string.IsNullOrEmpty(libraryName))
            {
                return(false);
            }
            else if (libraryName.Length > NuGetPackageMetadata.MaxPackageIdLength)
            {
                LibraryNameError = GettextCatalog.GetString("Library name must not exceed 100 characters.");
                return(false);
            }
            else if (!PackageIdValidator.IsValidPackageId(libraryName))
            {
                LibraryNameError = GettextCatalog.GetString("The library name contains invalid characters. Examples of valid library names include 'MyPackage' and 'MyPackage.Sample'.");
                return(false);
            }

            return(true);
        }
        bool IsValidId()
        {
            IdError = null;

            if (string.IsNullOrEmpty(id))
            {
                return(false);
            }
            else if (id.Length > NuGetPackageMetadata.MaxPackageIdLength)
            {
                IdError = GettextCatalog.GetString("The package id must not exceed 100 characters.");
                return(false);
            }
            else if (!PackageIdValidator.IsValidPackageId(id))
            {
                IdError = GettextCatalog.GetString("The package id contains invalid characters. Examples of valid package ids include 'MyPackage' and 'MyPackage.Sample'.");
                return(false);
            }

            return(true);
        }
        private void ApplySearchIndexFilter(
            SearchParameters searchParameters,
            SearchRequest request,
            bool excludePackagesHiddenByDefault,
            string packageType)
        {
            var searchFilters = GetSearchFilters(request);

            var filterString = $"{IndexFields.Search.SearchFilters} eq '{DocumentUtilities.GetSearchFilterString(searchFilters)}'";

            if (excludePackagesHiddenByDefault)
            {
                filterString += $" and ({IndexFields.Search.IsExcludedByDefault} eq false or {IndexFields.Search.IsExcludedByDefault} eq null)";
            }

            // Verify that the package type only has valid package ID characters so we don't need to worry about
            // escaping quotes and such.
            if (packageType != null && PackageIdValidator.IsValidPackageId(packageType))
            {
                filterString += $" and {IndexFields.Search.FilterablePackageTypes}/any(p: p eq '{packageType.ToLowerInvariant()}')";
            }

            searchParameters.Filter = filterString;
        }
Пример #27
0
 private static bool IsId(string query)
 {
     return(query.Length <= PackageIdValidator.MaxPackageIdLength &&
            PackageIdValidator.IsValidPackageId(query));
 }
Пример #28
0
        public virtual async Task <ActionResult> GetPackage(string id, string version)
        {
            // some security paranoia about URL hacking somehow creating e.g. open redirects
            // validate user input: explicit calls to the same validators used during Package Registrations
            // Ideally shouldn't be necessary?
            if (!PackageIdValidator.IsValidPackageId(id ?? ""))
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The format of the package id is invalid"));
            }

            // if version is non-null, check if it's semantically correct and normalize it.
            if (!String.IsNullOrEmpty(version))
            {
                NuGetVersion dummy;
                if (!NuGetVersion.TryParse(version, out dummy))
                {
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The package version is not a valid semantic version"));
                }
                // Normalize the version
                version = NuGetVersionNormalizer.Normalize(version);
            }
            else
            {
                // if version is null, get the latest version from the database.
                // This ensures that on package restore scenario where version will be non null, we don't hit the database.
                try
                {
                    var package = PackageService.FindPackageByIdAndVersion(id, version, allowPrerelease: false);
                    if (package == null)
                    {
                        return(new HttpStatusCodeWithBodyResult(HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version)));
                    }
                    version = package.NormalizedVersion;
                }
                catch (SqlException e)
                {
                    QuietLog.LogHandledException(e);

                    // Database was unavailable and we don't have a version, return a 503
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
                }
                catch (DataException e)
                {
                    QuietLog.LogHandledException(e);

                    // Database was unavailable and we don't have a version, return a 503
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
                }
            }

            // If metrics service is specified we post the data to it asynchronously. Else we skip stats.
            if (_config != null && _config.MetricsServiceUri != null)
            {
                try
                {
                    var userHostAddress  = Request.UserHostAddress;
                    var userAgent        = Request.UserAgent;
                    var operation        = Request.Headers["NuGet-Operation"];
                    var dependentPackage = Request.Headers["NuGet-DependentPackage"];
                    var projectGuids     = Request.Headers["NuGet-ProjectGuids"];

                    HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => PostDownloadStatistics(id, version, userHostAddress, userAgent, operation, dependentPackage, projectGuids, cancellationToken));
                }
                catch (Exception ex)
                {
                    QuietLog.LogHandledException(ex);
                }
            }

            return(await PackageFileService.CreateDownloadPackageActionResultAsync(
                       HttpContext.Request.Url,
                       id, version));
        }
Пример #29
0
        public virtual async Task <ActionResult> GetPackage(string id, string version)
        {
            // some security paranoia about URL hacking somehow creating e.g. open redirects
            // validate user input: explicit calls to the same validators used during Package Registrations
            // Ideally shouldn't be necessary?
            if (!PackageIdValidator.IsValidPackageId(id ?? ""))
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The format of the package id is invalid"));
            }

            if (!String.IsNullOrEmpty(version))
            {
                SemanticVersion dummy;
                if (!SemanticVersion.TryParse(version, out dummy))
                {
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The package version is not a valid semantic version"));
                }
            }

            // if the version is null, the user is asking for the latest version. Presumably they don't want includePrerelease release versions.
            // The allow prerelease flag is ignored if both partialId and version are specified.
            // In general we want to try to add download statistics for any package regardless of whether a version was specified.
            try
            {
                Package package = _packageService.FindPackageByIdAndVersion(id, version, allowPrerelease: false);
                if (package == null)
                {
                    return(new HttpStatusCodeWithBodyResult(
                               HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version)));
                }

                try
                {
                    _packageService.AddDownloadStatistics(
                        package,
                        Request.UserHostAddress,
                        Request.UserAgent,
                        Request.Headers["NuGet-Operation"]);
                }
                catch (ReadOnlyModeException)
                {
                    // *gulp* Swallowed. It's OK not to add statistics and ok to not log errors in read only mode.
                }
                catch (SqlException e)
                {
                    // Log the error and continue
                    QuietlyLogException(e);
                }
                catch (DataException e)
                {
                    // Log the error and continue
                    QuietlyLogException(e);
                }

                return(await _packageFileService.CreateDownloadPackageActionResultAsync(HttpContext.Request.Url, package));
            }
            catch (SqlException e)
            {
                QuietlyLogException(e);
            }
            catch (DataException e)
            {
                QuietlyLogException(e);
            }

            // Fall back to constructing the URL based on the package version and ID.

            return(await _packageFileService.CreateDownloadPackageActionResultAsync(HttpContext.Request.Url, id, version));
        }
Пример #30
0
        public virtual async Task <ActionResult> GetPackage(string id, string version)
        {
            // some security paranoia about URL hacking somehow creating e.g. open redirects
            // validate user input: explicit calls to the same validators used during Package Registrations
            // Ideally shouldn't be necessary?
            if (!PackageIdValidator.IsValidPackageId(id ?? ""))
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The format of the package id is invalid"));
            }

            if (!String.IsNullOrEmpty(version))
            {
                SemanticVersion dummy;
                if (!SemanticVersion.TryParse(version, out dummy))
                {
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The package version is not a valid semantic version"));
                }
            }

            // Normalize the version
            version = SemanticVersionExtensions.Normalize(version);

            // if the version is null, the user is asking for the latest version. Presumably they don't want includePrerelease release versions.
            // The allow prerelease flag is ignored if both partialId and version are specified.
            // In general we want to try to add download statistics for any package regardless of whether a version was specified.

            Package package = null;

            try
            {
                package = PackageService.FindPackageByIdAndVersion(id, version, allowPrerelease: false);
                if (package == null)
                {
                    return(new HttpStatusCodeWithBodyResult(
                               HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version)));
                }

                try
                {
                    var stats = new PackageStatistics
                    {
                        // IMPORTANT: Timestamp is managed by the database.
                        IPAddress        = Request.UserHostAddress,
                        UserAgent        = Request.UserAgent,
                        Package          = package,
                        Operation        = Request.Headers["NuGet-Operation"],
                        DependentPackage = Request.Headers["NuGet-DependentPackage"],
                        ProjectGuids     = Request.Headers["NuGet-ProjectGuids"],
                    };

                    PackageService.AddDownloadStatistics(stats);
                }
                catch (ReadOnlyModeException)
                {
                    // *gulp* Swallowed. It's OK not to add statistics and ok to not log errors in read only mode.
                }
                catch (SqlException e)
                {
                    // Log the error and continue
                    QuietLog.LogHandledException(e);
                }
                catch (DataException e)
                {
                    // Log the error and continue
                    QuietLog.LogHandledException(e);
                }
            }
            catch (SqlException e)
            {
                QuietLog.LogHandledException(e);
            }
            catch (DataException e)
            {
                QuietLog.LogHandledException(e);
            }

            // Fall back to constructing the URL based on the package version and ID.
            if (String.IsNullOrEmpty(version) && package == null)
            {
                // Database was unavailable and we don't have a version, return a 503
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
            }
            return(await PackageFileService.CreateDownloadPackageActionResultAsync(
                       HttpContext.Request.Url,
                       id,
                       String.IsNullOrEmpty(version)?package.NormalizedVersion : version));
        }