From 1eaa7e148aba3eab1f914e575c232c3ddeb088d2 Mon Sep 17 00:00:00 2001 From: lyndaidaii <64443925+lyndaidaii@users.noreply.github.com> Date: Tue, 30 Mar 2021 10:38:22 -0700 Subject: [PATCH 1/5] reject empty readme file & fix error message for invalid extension (#8464) * reject empty readme file & fix error message for invalid extension --- .../Services/PackageMetadataValidationService.cs | 10 ++++++++++ src/NuGetGallery/Strings.Designer.cs | 11 ++++++++++- src/NuGetGallery/Strings.resx | 5 ++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/NuGetGallery/Services/PackageMetadataValidationService.cs b/src/NuGetGallery/Services/PackageMetadataValidationService.cs index 959f621c5d..f384bfc37b 100644 --- a/src/NuGetGallery/Services/PackageMetadataValidationService.cs +++ b/src/NuGetGallery/Services/PackageMetadataValidationService.cs @@ -458,6 +458,16 @@ private async Task CheckReadmeMetadataAsync(PackageArch } var readmeFileEntry = nuGetPackage.GetEntry(readmeFilePath); + + if (readmeFileEntry.Length == 0) + { + return PackageValidationResult.Invalid( + string.Format( + Strings.ReadmeErrorEmpty, + Strings.UploadPackage_ReadmeFileType, + readmeFilePath)); + } + if (readmeFileEntry.Length > MaxAllowedReadmeLengthForUploading) { return PackageValidationResult.Invalid( diff --git a/src/NuGetGallery/Strings.Designer.cs b/src/NuGetGallery/Strings.Designer.cs index 51d32b707e..c23dc2cb63 100644 --- a/src/NuGetGallery/Strings.Designer.cs +++ b/src/NuGetGallery/Strings.Designer.cs @@ -1588,6 +1588,15 @@ public static string PreviewReadMe_ReadMeMissing { } } + /// + /// Looks up a localized string similar to The readme file '{0}' cannot be empty.. + /// + public static string ReadmeErrorEmpty { + get { + return ResourceManager.GetString("ReadmeErrorEmpty", resourceCulture); + } + } + /// /// Looks up a localized string similar to '{0}' is not a valid Markdown Documentation source type.. /// @@ -2598,7 +2607,7 @@ public static string UploadPackage_InvalidPackage { } /// - /// Looks up a localized string similar to The readme file has an invalid extension '{0}'. Extension must be one of the following: {1}.. + /// Looks up a localized string similar to The readme file has an invalid extension '{0}'. The extension must be: '{1}'.. /// public static string UploadPackage_InvalidReadmeFileExtension { get { diff --git a/src/NuGetGallery/Strings.resx b/src/NuGetGallery/Strings.resx index b841942641..a7b8dcbfc9 100644 --- a/src/NuGetGallery/Strings.resx +++ b/src/NuGetGallery/Strings.resx @@ -1166,7 +1166,7 @@ The {1} Team The <readme> element is not currently supported. - The readme file has an invalid extension '{0}'. Extension must be one of the following: {1}. + The readme file has an invalid extension '{0}'. The extension must be: '{1}'. {0} is the readme file extension specified in the .nuspec, {1} is the list of allowed extensions @@ -1215,4 +1215,7 @@ The {1} Team The package ID is reserved. You can upload your package with a different package ID. Reach out to <a href="mailto:support@nuget.org">support@nuget.org</a> if you have questions. + + The readme file '{0}' cannot be empty. + \ No newline at end of file From be38792c3d3d327765113a32d82cd5b9b68cd1b0 Mon Sep 17 00:00:00 2001 From: lyndaidaii <64443925+lyndaidaii@users.noreply.github.com> Date: Tue, 30 Mar 2021 14:34:06 -0700 Subject: [PATCH 2/5] Revert "reject empty readme file & fix error message for invalid extension (#8464)" (#8470) This reverts commit 1eaa7e148aba3eab1f914e575c232c3ddeb088d2. --- .../Services/PackageMetadataValidationService.cs | 10 ---------- src/NuGetGallery/Strings.Designer.cs | 11 +---------- src/NuGetGallery/Strings.resx | 5 +---- 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/src/NuGetGallery/Services/PackageMetadataValidationService.cs b/src/NuGetGallery/Services/PackageMetadataValidationService.cs index f384bfc37b..959f621c5d 100644 --- a/src/NuGetGallery/Services/PackageMetadataValidationService.cs +++ b/src/NuGetGallery/Services/PackageMetadataValidationService.cs @@ -458,16 +458,6 @@ private async Task CheckReadmeMetadataAsync(PackageArch } var readmeFileEntry = nuGetPackage.GetEntry(readmeFilePath); - - if (readmeFileEntry.Length == 0) - { - return PackageValidationResult.Invalid( - string.Format( - Strings.ReadmeErrorEmpty, - Strings.UploadPackage_ReadmeFileType, - readmeFilePath)); - } - if (readmeFileEntry.Length > MaxAllowedReadmeLengthForUploading) { return PackageValidationResult.Invalid( diff --git a/src/NuGetGallery/Strings.Designer.cs b/src/NuGetGallery/Strings.Designer.cs index c23dc2cb63..51d32b707e 100644 --- a/src/NuGetGallery/Strings.Designer.cs +++ b/src/NuGetGallery/Strings.Designer.cs @@ -1588,15 +1588,6 @@ public static string PreviewReadMe_ReadMeMissing { } } - /// - /// Looks up a localized string similar to The readme file '{0}' cannot be empty.. - /// - public static string ReadmeErrorEmpty { - get { - return ResourceManager.GetString("ReadmeErrorEmpty", resourceCulture); - } - } - /// /// Looks up a localized string similar to '{0}' is not a valid Markdown Documentation source type.. /// @@ -2607,7 +2598,7 @@ public static string UploadPackage_InvalidPackage { } /// - /// Looks up a localized string similar to The readme file has an invalid extension '{0}'. The extension must be: '{1}'.. + /// Looks up a localized string similar to The readme file has an invalid extension '{0}'. Extension must be one of the following: {1}.. /// public static string UploadPackage_InvalidReadmeFileExtension { get { diff --git a/src/NuGetGallery/Strings.resx b/src/NuGetGallery/Strings.resx index a7b8dcbfc9..b841942641 100644 --- a/src/NuGetGallery/Strings.resx +++ b/src/NuGetGallery/Strings.resx @@ -1166,7 +1166,7 @@ The {1} Team The <readme> element is not currently supported. - The readme file has an invalid extension '{0}'. The extension must be: '{1}'. + The readme file has an invalid extension '{0}'. Extension must be one of the following: {1}. {0} is the readme file extension specified in the .nuspec, {1} is the list of allowed extensions @@ -1215,7 +1215,4 @@ The {1} Team The package ID is reserved. You can upload your package with a different package ID. Reach out to <a href="mailto:support@nuget.org">support@nuget.org</a> if you have questions. - - The readme file '{0}' cannot be empty. - \ No newline at end of file From a2ab1c7052e55431c3d46073d41e6da3ca966c48 Mon Sep 17 00:00:00 2001 From: lyndaidaii <64443925+lyndaidaii@users.noreply.github.com> Date: Fri, 23 Apr 2021 11:56:28 -0700 Subject: [PATCH 3/5] change sql get vulnerabilities by package id (#8540) * change sql get vulunerabilities by package id * Adjusted logic to provide correct groupings, adjusted UTs Co-authored-by: Drew Gillies --- .../Services/PackageVulnerabilitiesService.cs | 31 ++++++------------- .../PackageVulnerabilitiesServiceFacts.cs | 29 ++++++----------- 2 files changed, 19 insertions(+), 41 deletions(-) diff --git a/src/NuGetGallery/Services/PackageVulnerabilitiesService.cs b/src/NuGetGallery/Services/PackageVulnerabilitiesService.cs index d8b335c019..f17b8431ee 100644 --- a/src/NuGetGallery/Services/PackageVulnerabilitiesService.cs +++ b/src/NuGetGallery/Services/PackageVulnerabilitiesService.cs @@ -3,8 +3,8 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Data.Entity; -using System.IO; using System.Linq; using NuGet.Services.Entities; @@ -21,26 +21,15 @@ public PackageVulnerabilitiesService(IEntitiesContext entitiesContext) public IReadOnlyDictionary> GetVulnerabilitiesById(string id) { - var result = new Dictionary>(); - var packagesMatchingId = _entitiesContext.Packages - .Where(p => p.PackageRegistration != null && p.PackageRegistration.Id == id) - .Include($"{nameof(Package.VulnerablePackageRanges)}.{nameof(VulnerablePackageVersionRange.Vulnerability)}"); - foreach (var package in packagesMatchingId) - { - if (package.VulnerablePackageRanges == null) - { - continue; - } - - if (package.VulnerablePackageRanges.Any()) - { - result.Add(package.Key, - package.VulnerablePackageRanges.Select(vr => vr.Vulnerability).ToList()); - } - } - - return !result.Any() ? null : - result.ToDictionary(kv => kv.Key, kv => kv.Value as IReadOnlyList); + var packageKeyAndVulnerability = _entitiesContext.VulnerableRanges + .Include(x => x.Vulnerability) + .Where(x => x.PackageId == id) + .SelectMany(x => x.Packages.Select(p => new {PackageKey = p.Key, x.Vulnerability})) + .GroupBy(pv => pv.PackageKey, pv => pv.Vulnerability) + .ToDictionary(pv => pv.Key, pv => pv.ToList().AsReadOnly() as IReadOnlyList); + + return !packageKeyAndVulnerability.Any() ? null + : new ReadOnlyDictionary>(packageKeyAndVulnerability); } public bool IsPackageVulnerable(Package package) diff --git a/tests/NuGetGallery.Facts/Services/PackageVulnerabilitiesServiceFacts.cs b/tests/NuGetGallery.Facts/Services/PackageVulnerabilitiesServiceFacts.cs index 77121a2ab9..ebc224c1f9 100644 --- a/tests/NuGetGallery.Facts/Services/PackageVulnerabilitiesServiceFacts.cs +++ b/tests/NuGetGallery.Facts/Services/PackageVulnerabilitiesServiceFacts.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using System.Linq; using NuGet.Services.Entities; using NuGetGallery.Framework; using Xunit; @@ -22,7 +21,6 @@ public class PackageVulnerabilitiesServiceFacts : TestContainer private Package _packageVulnerable100; private Package _packageVulnerable110; private Package _packageVulnerable111; - private Package _packageVulnerable112; private Package _packageNotVulnerable; @@ -31,16 +29,9 @@ public void GetsVulnerabilitiesOfPackage() { // Arrange SetUp(); - var packages = new[] - { - _packageVulnerable100, - _packageVulnerable110, - _packageVulnerable111, - _packageVulnerable112, - _packageNotVulnerable - }; + var vulnerableRanges = new[] {_versionRangeModerate, _versionRangeCritical}; var context = GetFakeContext(); - context.Packages.AddRange(packages); + context.VulnerableRanges.AddRange(vulnerableRanges); var target = Get(); // Act @@ -96,12 +87,14 @@ private void SetUp() _versionRangeCritical = new VulnerablePackageVersionRange { + PackageId = "Vulnerable", Vulnerability = _vulnerabilityCritical, PackageVersionRange = "1.1.1", FirstPatchedPackageVersion = "1.1.2" }; _versionRangeModerate = new VulnerablePackageVersionRange { + PackageId = "Vulnerable", Vulnerability = _vulnerabilityModerate, PackageVersionRange = "<=1.1.1", FirstPatchedPackageVersion = "1.1.2" @@ -129,7 +122,7 @@ private void SetUp() }; _packageVulnerable111 = new Package { - Key = 3, // simulate a different order in db - create a non-contiguous range of rows, even if the range is contiguous + Key = 2, PackageRegistration = _registrationVulnerable, Version = "1.1.1", VulnerablePackageRanges = new List @@ -138,19 +131,15 @@ private void SetUp() _versionRangeCritical } }; - _packageVulnerable112 = new Package - { - Key = 2, // simulate a different order in db - create a non-contiguous range of rows, even if the range is contiguous - PackageRegistration = _registrationVulnerable, - Version = "1.1.2", - VulnerablePackageRanges = new List() - }; _packageNotVulnerable = new Package { - Key = 4, + Key = 3, PackageRegistration = new PackageRegistration { Id = "NotVulnerable" }, VulnerablePackageRanges = new List() }; + + _versionRangeCritical.Packages = new List { _packageVulnerable111 }; + _versionRangeModerate.Packages = new List { _packageVulnerable100, _packageVulnerable110, _packageVulnerable111 }; } } } From cdb13af641d401f4740442a66d64207701d1363f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Sharma?= <737941+loic-sharma@users.noreply.github.com> Date: Thu, 29 Apr 2021 13:48:32 -0700 Subject: [PATCH 4/5] Revert "change sql get vulnerabilities by package id (#8540)" (#8555) This reverts commit a2ab1c7052e55431c3d46073d41e6da3ca966c48. --- .../Services/PackageVulnerabilitiesService.cs | 31 +++++++++++++------ .../PackageVulnerabilitiesServiceFacts.cs | 29 +++++++++++------ 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/NuGetGallery/Services/PackageVulnerabilitiesService.cs b/src/NuGetGallery/Services/PackageVulnerabilitiesService.cs index f17b8431ee..d8b335c019 100644 --- a/src/NuGetGallery/Services/PackageVulnerabilitiesService.cs +++ b/src/NuGetGallery/Services/PackageVulnerabilitiesService.cs @@ -3,8 +3,8 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Data.Entity; +using System.IO; using System.Linq; using NuGet.Services.Entities; @@ -21,15 +21,26 @@ public PackageVulnerabilitiesService(IEntitiesContext entitiesContext) public IReadOnlyDictionary> GetVulnerabilitiesById(string id) { - var packageKeyAndVulnerability = _entitiesContext.VulnerableRanges - .Include(x => x.Vulnerability) - .Where(x => x.PackageId == id) - .SelectMany(x => x.Packages.Select(p => new {PackageKey = p.Key, x.Vulnerability})) - .GroupBy(pv => pv.PackageKey, pv => pv.Vulnerability) - .ToDictionary(pv => pv.Key, pv => pv.ToList().AsReadOnly() as IReadOnlyList); - - return !packageKeyAndVulnerability.Any() ? null - : new ReadOnlyDictionary>(packageKeyAndVulnerability); + var result = new Dictionary>(); + var packagesMatchingId = _entitiesContext.Packages + .Where(p => p.PackageRegistration != null && p.PackageRegistration.Id == id) + .Include($"{nameof(Package.VulnerablePackageRanges)}.{nameof(VulnerablePackageVersionRange.Vulnerability)}"); + foreach (var package in packagesMatchingId) + { + if (package.VulnerablePackageRanges == null) + { + continue; + } + + if (package.VulnerablePackageRanges.Any()) + { + result.Add(package.Key, + package.VulnerablePackageRanges.Select(vr => vr.Vulnerability).ToList()); + } + } + + return !result.Any() ? null : + result.ToDictionary(kv => kv.Key, kv => kv.Value as IReadOnlyList); } public bool IsPackageVulnerable(Package package) diff --git a/tests/NuGetGallery.Facts/Services/PackageVulnerabilitiesServiceFacts.cs b/tests/NuGetGallery.Facts/Services/PackageVulnerabilitiesServiceFacts.cs index ebc224c1f9..77121a2ab9 100644 --- a/tests/NuGetGallery.Facts/Services/PackageVulnerabilitiesServiceFacts.cs +++ b/tests/NuGetGallery.Facts/Services/PackageVulnerabilitiesServiceFacts.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Linq; using NuGet.Services.Entities; using NuGetGallery.Framework; using Xunit; @@ -21,6 +22,7 @@ public class PackageVulnerabilitiesServiceFacts : TestContainer private Package _packageVulnerable100; private Package _packageVulnerable110; private Package _packageVulnerable111; + private Package _packageVulnerable112; private Package _packageNotVulnerable; @@ -29,9 +31,16 @@ public void GetsVulnerabilitiesOfPackage() { // Arrange SetUp(); - var vulnerableRanges = new[] {_versionRangeModerate, _versionRangeCritical}; + var packages = new[] + { + _packageVulnerable100, + _packageVulnerable110, + _packageVulnerable111, + _packageVulnerable112, + _packageNotVulnerable + }; var context = GetFakeContext(); - context.VulnerableRanges.AddRange(vulnerableRanges); + context.Packages.AddRange(packages); var target = Get(); // Act @@ -87,14 +96,12 @@ private void SetUp() _versionRangeCritical = new VulnerablePackageVersionRange { - PackageId = "Vulnerable", Vulnerability = _vulnerabilityCritical, PackageVersionRange = "1.1.1", FirstPatchedPackageVersion = "1.1.2" }; _versionRangeModerate = new VulnerablePackageVersionRange { - PackageId = "Vulnerable", Vulnerability = _vulnerabilityModerate, PackageVersionRange = "<=1.1.1", FirstPatchedPackageVersion = "1.1.2" @@ -122,7 +129,7 @@ private void SetUp() }; _packageVulnerable111 = new Package { - Key = 2, + Key = 3, // simulate a different order in db - create a non-contiguous range of rows, even if the range is contiguous PackageRegistration = _registrationVulnerable, Version = "1.1.1", VulnerablePackageRanges = new List @@ -131,15 +138,19 @@ private void SetUp() _versionRangeCritical } }; + _packageVulnerable112 = new Package + { + Key = 2, // simulate a different order in db - create a non-contiguous range of rows, even if the range is contiguous + PackageRegistration = _registrationVulnerable, + Version = "1.1.2", + VulnerablePackageRanges = new List() + }; _packageNotVulnerable = new Package { - Key = 3, + Key = 4, PackageRegistration = new PackageRegistration { Id = "NotVulnerable" }, VulnerablePackageRanges = new List() }; - - _versionRangeCritical.Packages = new List { _packageVulnerable111 }; - _versionRangeModerate.Packages = new List { _packageVulnerable100, _packageVulnerable110, _packageVulnerable111 }; } } } From 908da7fb5c1ae6768fd04e5ee093bab6ef5c1dba Mon Sep 17 00:00:00 2001 From: Drew Gillies Date: Fri, 18 Jun 2021 14:15:38 +1000 Subject: [PATCH 5/5] Add safety categories to report abuse form (#8635) --- .../Fakes/FakeFeatureFlagService.cs | 5 ++ .../Configuration/FeatureFlagService.cs | 6 ++ .../Configuration/IFeatureFlagService.cs | 6 ++ .../Models/ReportPackageReason.cs | 18 +++++ .../Controllers/PackagesController.cs | 18 ++++- .../Views/Packages/ReportAbuse.cshtml | 79 +++++++++++++++++-- .../Fakes/FakeFeatureFlagService.cs | 2 + 7 files changed, 128 insertions(+), 6 deletions(-) diff --git a/src/GitHubVulnerabilities2Db/Fakes/FakeFeatureFlagService.cs b/src/GitHubVulnerabilities2Db/Fakes/FakeFeatureFlagService.cs index daf1860865..e94bb13a10 100644 --- a/src/GitHubVulnerabilities2Db/Fakes/FakeFeatureFlagService.cs +++ b/src/GitHubVulnerabilities2Db/Fakes/FakeFeatureFlagService.cs @@ -205,6 +205,11 @@ public bool IsODataV2SearchNonHijackedEnabled() throw new NotImplementedException(); } + public bool IsShowReportAbuseSafetyChangesEnabled() + { + throw new NotImplementedException(); + } + public bool IsPackageDependentsEnabled(User user) { throw new NotImplementedException(); diff --git a/src/NuGetGallery.Services/Configuration/FeatureFlagService.cs b/src/NuGetGallery.Services/Configuration/FeatureFlagService.cs index df5a6cfc6b..5a0d0044de 100644 --- a/src/NuGetGallery.Services/Configuration/FeatureFlagService.cs +++ b/src/NuGetGallery.Services/Configuration/FeatureFlagService.cs @@ -49,6 +49,7 @@ public class FeatureFlagService : IFeatureFlagService private const string ImageAllowlistFlightName = GalleryPrefix + "ImageAllowlist"; private const string DisplayBannerFlightName = GalleryPrefix + "Banner"; private const string DisplayPackagePageV2FeatureName = GalleryPrefix + "DisplayPackagePageV2"; + private const string ShowReportAbuseSafetyChanges = GalleryPrefix + "ShowReportAbuseSafetyChanges"; private const string ODataV1GetAllNonHijackedFeatureName = GalleryPrefix + "ODataV1GetAllNonHijacked"; private const string ODataV1GetAllCountNonHijackedFeatureName = GalleryPrefix + "ODataV1GetAllCountNonHijacked"; @@ -319,6 +320,11 @@ public bool IsODataV2SearchCountNonHijackedEnabled() return _client.IsEnabled(ODataV2SearchCountNonHijackedFeatureName, defaultValue: true); } + public bool IsShowReportAbuseSafetyChangesEnabled() + { + return _client.IsEnabled(ShowReportAbuseSafetyChanges, defaultValue: false); + } + public bool IsMarkdigMdRenderingEnabled() { return _client.IsEnabled(MarkdigMdRenderingFlightName, defaultValue: false); diff --git a/src/NuGetGallery.Services/Configuration/IFeatureFlagService.cs b/src/NuGetGallery.Services/Configuration/IFeatureFlagService.cs index 804eecb5d8..4df4ea5a31 100644 --- a/src/NuGetGallery.Services/Configuration/IFeatureFlagService.cs +++ b/src/NuGetGallery.Services/Configuration/IFeatureFlagService.cs @@ -248,10 +248,16 @@ public interface IFeatureFlagService /// bool IsLicenseMdRenderingEnabled(User user); + /// /// Whether the /Search()/$count endpoint is enabled for non-hijacked queries for the V2 OData API. /// bool IsODataV2SearchCountNonHijackedEnabled(); + /// + /// Whether the online safety changes to the report abuse form have been enabled + /// + bool IsShowReportAbuseSafetyChangesEnabled(); + /// /// Whether rendering Markdown content to HTML using Markdig is enabled /// diff --git a/src/NuGetGallery.Services/Models/ReportPackageReason.cs b/src/NuGetGallery.Services/Models/ReportPackageReason.cs index fb2687fcaa..2e8a6a5b16 100644 --- a/src/NuGetGallery.Services/Models/ReportPackageReason.cs +++ b/src/NuGetGallery.Services/Models/ReportPackageReason.cs @@ -24,5 +24,23 @@ public enum ReportPackageReason [Description("The package was not intended to be published publicly on nuget.org")] ReleasedInPublicByAccident, + + [Description("Child sexual exploitation or abuse")] + ChildSexualExploitationOrAbuse, + + [Description("Terrorism or violent extremism")] + TerrorismOrViolentExtremism, + + [Description("The package contains hate speech")] + HateSpeech, + + [Description("The package contains content related to imminent harm")] + ImminentHarm, + + [Description("The package contains non-consensual intimate imagery (i.e. \"revenge porn\")")] + RevengePorn, + + [Description("Other nudity or pornography (not \"revenge porn\")")] + OtherNudityOrPornography, } } diff --git a/src/NuGetGallery/Controllers/PackagesController.cs b/src/NuGetGallery/Controllers/PackagesController.cs index d3c324f0e0..b3dc2d1358 100644 --- a/src/NuGetGallery/Controllers/PackagesController.cs +++ b/src/NuGetGallery/Controllers/PackagesController.cs @@ -67,6 +67,20 @@ public partial class PackagesController ReportPackageReason.Other }; + private static readonly IReadOnlyList ReportAbuseWithSafetyReasons = new[] + { + ReportPackageReason.ViolatesALicenseIOwn, + ReportPackageReason.ContainsMaliciousCode, + ReportPackageReason.HasABugOrFailedToInstall, + ReportPackageReason.ChildSexualExploitationOrAbuse, + ReportPackageReason.TerrorismOrViolentExtremism, + ReportPackageReason.HateSpeech, + ReportPackageReason.ImminentHarm, + ReportPackageReason.RevengePorn, + ReportPackageReason.OtherNudityOrPornography, + ReportPackageReason.Other + }; + private static readonly IReadOnlyList ReportMyPackageReasons = new[] { ReportPackageReason.ContainsPrivateAndConfidentialData, @@ -1336,7 +1350,9 @@ public virtual ActionResult ReportAbuse(string id, string version) var model = new ReportAbuseViewModel { - ReasonChoices = ReportAbuseReasons, + ReasonChoices = _featureFlagService.IsShowReportAbuseSafetyChangesEnabled() + ? ReportAbuseWithSafetyReasons + : ReportAbuseReasons, PackageId = id, PackageVersion = package.Version, CopySender = true, diff --git a/src/NuGetGallery/Views/Packages/ReportAbuse.cshtml b/src/NuGetGallery/Views/Packages/ReportAbuse.cshtml index 34435ec418..e1f5c835b9 100644 --- a/src/NuGetGallery/Views/Packages/ReportAbuse.cshtml +++ b/src/NuGetGallery/Views/Packages/ReportAbuse.cshtml @@ -25,13 +25,13 @@ ) -

+

Please provide a detailed abuse report with evidence to support your claim! We cannot delete packages without evidence that they exhibit malicious behavior.

@if (!Model.ConfirmedUser) { -

+

Note: If this is your package and you would like to contact support, please sign in.

@@ -42,7 +42,7 @@
@Html.ShowLabelFor(m => m.Reason) -

Please select the reason for contacting support about this package.

+

Please select the reason for contacting support about this package.

@Html.ShowEnumDropDownListFor(m => m.Reason, Model.ReasonChoices, "") @Html.ShowValidationMessagesFor(m => m.Reason)
@@ -53,14 +53,47 @@ @Html.ShowTextBoxFor(m => m.Email) @Html.ShowValidationMessagesFor(m => m.Email) -
+
@Html.ShowCheckboxFor(m => m.AlreadyContactedOwner) @Html.ShowLabelFor(m => m.AlreadyContactedOwner) @Html.ShowValidationMessagesFor(m => m.AlreadyContactedOwner)
@Html.ShowLabelFor(m => m.Message) -

Please provide a detailed description of the problem. If you are reporting copyright infringement, please describe the copyrighted material with particularity and provide us with information about your copyright (i.e. title of copyrighted work, URL where to view your copyrighted work, description of your copyrighted work, and any copyright registrations you may have, etc.). For trademark infringement, include the name of your trademark, registration number, and country where registered.

+

+ Please provide a detailed description of the problem. +

+

+

+ If you are reporting copyright infringement, please describe the copyrighted material with particularity and provide us with information about your copyright (i.e. title of copyrighted work, URL where to view your copyrighted work, description of your copyrighted work, and any copyright registrations you may have, etc.). For trademark infringement, include the name of your trademark, registration number, and country where registered. +

+
+
+

+ Note: Please complete this form and submit it so we can proceed with an appropriate response regarding the NuGet package (e.g. removing it). In addition, please proceed to https://report.cybertip.org to report the matter in more detail. +

+
+
+

+ Note: Please complete this form and submit it so we can proceed with an appropriate response regarding the NuGet package (e.g. removing it). In addition, please proceed to https://www.microsoft.com/en-au/concern/terroristcontent to report the matter in more detail. +

+
+
+

+ Note: please ensure when reporting this type of abuse that you've considered whether the following are present: +

    +
  • A targeted person or group (including self)
  • +
  • An identified actor--i.e. person intending to commit the offense
  • +
  • Details of the threat
  • +
  • Time and/or place where the act will be carried out
  • +
+

+
+
+

+ Note: Please complete this form and submit it so we can proceed with an appropriate response regarding the NuGet package (e.g. removing it). In addition, please proceed to https://www.microsoft.com/en-us/concern/revengeporn to report the matter in more detail. +

+
@Html.ShowTextAreaFor(m => m.Message, 10, 50) @Html.ShowValidationMessagesFor(m => m.Message)
@@ -112,6 +145,42 @@ $('#report-abuse-form').show(); } + // We don't suggest the customer contact the owner in the case of safety violations + if (val === 'ChildSexualExploitationOrAbuse' + || val === 'TerrorismOrViolentExtremism' + || val === 'HateSpeech' + || val === 'ImminentHarm' + || val === 'RevengePorn' + || val === 'OtherNudityOrPornography') { + $form.find('.already-contacted-owner').hide(); + } else { + $form.find('.already-contacted-owner').show(); + } + + if (val === 'ChildSexualExploitationOrAbuse') { + $form.find('.child-sexual-exploitation').show(); + } else { + $form.find('.child-sexual-exploitation').hide(); + } + + if (val === 'TerrorismOrViolentExtremism') { + $form.find('.terrorism-or-violent-extremism').show(); + } else { + $form.find('.terrorism-or-violent-extremism').hide(); + } + + if (val === 'ImminentHarm') { + $form.find('.imminent-harm').show(); + } else { + $form.find('.imminent-harm').hide(); + } + + if (val === 'RevengePorn') { + $form.find('.revenge-porn').show(); + } else { + $form.find('.revenge-porn').hide(); + } + if (val == 'ViolatesALicenseIOwn') { $form.find('.infringement-claim-requirements').show(); $('#Signature').rules("add", { diff --git a/src/VerifyMicrosoftPackage/Fakes/FakeFeatureFlagService.cs b/src/VerifyMicrosoftPackage/Fakes/FakeFeatureFlagService.cs index c16caf364f..4d6773ea1b 100644 --- a/src/VerifyMicrosoftPackage/Fakes/FakeFeatureFlagService.cs +++ b/src/VerifyMicrosoftPackage/Fakes/FakeFeatureFlagService.cs @@ -103,6 +103,8 @@ public class FakeFeatureFlagService : IFeatureFlagService public bool IsODataV2SearchCountNonHijackedEnabled() => throw new NotImplementedException(); + public bool IsShowReportAbuseSafetyChangesEnabled() => throw new NotImplementedException(); + public bool IsMarkdigMdRenderingEnabled() => throw new NotImplementedException(); public bool IsDeletePackageApiEnabled(User user) => throw new NotImplementedException();