Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Search DV] Display deprecation and vulnerabilities on search page. #9440

Merged
merged 12 commits into from
Apr 26, 2023
26 changes: 26 additions & 0 deletions src/Bootstrap/dist/css/bootstrap-theme.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions src/Bootstrap/less/theme/common-list-packages.less
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,30 @@
margin-top: 75px;
margin-bottom: 0px;
}

@severe-warning-background-color: rgb(254, 217, 204);
@severe-warning-icon-color: rgb(216, 59, 1);
@warning-background-color: rgb(255, 244, 206);
@package-warning-color: rgb(50, 49, 48);
@badge-border-radius: 2px;
dannyjdev marked this conversation as resolved.
Show resolved Hide resolved

.package-warning {
padding-right: 8px;
padding-left: 8px;
border-radius: @badge-border-radius;
margin-right: 5px;
color: @package-warning-color
}

.package-warning--vulnerable {
.package-warning;
background-color: @severe-warning-background-color;
i {
color: @severe-warning-icon-color;
}
}

.package-warning--deprecated {
.package-warning;
background-color: @warning-background-color;
}
12 changes: 12 additions & 0 deletions src/NuGet.Services.Entities/AlternatePackage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace NuGet.Services.Entities
{
public class AlternatePackage
{
public string Id { get; set; }

public string Range { get; set; }
}
}
14 changes: 14 additions & 0 deletions src/NuGet.Services.Entities/Deprecation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace NuGet.Services.Entities
{
public class Deprecation
{
public AlternatePackage AlternatePackage { get; set; }

public string Message { get; set; }

public string[] Reasons { get; set; }
}
}
12 changes: 12 additions & 0 deletions src/NuGet.Services.Entities/Package.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,5 +310,17 @@ public string Id
public bool HasEmbeddedIcon { get; set; }

public EmbeddedReadmeFileType EmbeddedReadmeType { get; set; }

/// <summary>
/// Deprecation data retrieved from search service.
/// </summary>
[NotMapped]
public Deprecation Deprecation { get; set; }
dannyjdev marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Vulnerability data retrieved from search service.
/// </summary>
[NotMapped]
public IReadOnlyList<Vulnerability> Vulnerabilities { get; set; }
}
}
12 changes: 12 additions & 0 deletions src/NuGet.Services.Entities/Vulnerability.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace NuGet.Services.Entities
{
public class Vulnerability
{
public string AdvisoryURL { get; set; }

public int Severity { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ private ListPackageItemViewModel SetupInternal(ListPackageItemViewModel viewMode
viewModel.MinClientVersion = package.MinClientVersion;
viewModel.Owners = package.PackageRegistration?.Owners?.Select(GetBasicUserViewModel).ToList();
viewModel.IsVerified = package.PackageRegistration?.IsVerified;
viewModel.IsDeprecated = package.Deprecation?.Reasons?.Length > 0;
viewModel.IsVulnerable = package.Vulnerabilities?.Count > 0;

viewModel.CanDisplayPrivateMetadata = CanPerformAction(currentUser, package, ActionsRequiringPermissions.DisplayPrivatePackageMetadata);
viewModel.CanEdit = CanPerformAction(currentUser, package, ActionsRequiringPermissions.EditPackage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,49 @@ internal static Package ReadPackage(JObject doc, string semVerLevel)
var isLatestStable = doc.Value<bool>("IsLatestStable");
var semVer2 = SemVerLevelKey.ForSemVerLevel(semVerLevel) == SemVerLevelKey.SemVer2;

var docDeprecation = doc["Deprecation"];
Deprecation deprecation = null;
if (docDeprecation != null)
{
var docReasons = docDeprecation.Value<JArray>("Reasons");
if (docReasons != null && docReasons.HasValues)
{
var reasons = docReasons
.Select(v => v.Value<string>())
.ToArray();

var docAlternatePackage = docDeprecation["AlternatePackage"];
AlternatePackage alternatePackage = null;
if (docAlternatePackage != null)
{
alternatePackage = new AlternatePackage()
{
Id = docAlternatePackage.Value<string>("Id"),
Range = docAlternatePackage.Value<string>("Range")
};
}

deprecation = new Deprecation()
{
Message = docDeprecation.Value<string>("Message"),
Reasons = reasons,
AlternatePackage = alternatePackage
};
}
}

var docVulnerabilities = doc.Value<JArray>("Vulnerabilities");
var vulnerabilities = new List<Vulnerability>();
if (docVulnerabilities != null)
{
vulnerabilities = docVulnerabilities.Select(obj => new Vulnerability()
{
AdvisoryURL = obj.Value<string>("AdvisoryURL"),
Severity = obj.Value<int>("Severity")
})
.ToList();
}

return new Package
{
Copyright = doc.Value<string>("Copyright"),
Expand Down Expand Up @@ -243,7 +286,9 @@ internal static Package ReadPackage(JObject doc, string semVerLevel)
LicenseNames = doc.Value<string>("LicenseNames"),
LicenseReportUrl = doc.Value<string>("LicenseReportUrl"),
HideLicenseReport = doc.Value<bool>("HideLicenseReport"),
Listed = doc.Value<bool>("Listed")
Listed = doc.Value<bool>("Listed"),
Deprecation = deprecation,
Vulnerabilities = vulnerabilities
};
}

Expand Down
1 change: 0 additions & 1 deletion src/NuGetGallery/NuGetGallery.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -1444,7 +1444,6 @@
<Compile Include="Services\NullReportService.cs" />
<Compile Include="Services\NullStatisticsService.cs" />
<Compile Include="Services\PackageFileService.cs" />
<Compile Include="Services\PackageSearchResults.cs" />
<Compile Include="Services\JsonAggregateStatsService.cs" />
<Compile Include="Services\SearchResults.cs" />
<Compile Include="Services\SqlAggregateStatsService.cs" />
Expand Down
1 change: 1 addition & 0 deletions src/NuGetGallery/ViewModels/PackageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class PackageViewModel : IPackageVersionModel
public string FullVersion { get; set; }
public PackageStatusSummary PackageStatusSummary { get; set; }
public bool IsVulnerable { get; set; }
public bool IsDeprecated { get; set; }

public bool IsCurrent(IPackageVersionModel current)
{
Expand Down
34 changes: 27 additions & 7 deletions src/NuGetGallery/Views/Shared/_ListPackage.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,16 @@
<div class="package-header">
<a class="package-title"
href="@Url.Package(Model.Id, Model.UseVersion ? Model.Version : null).TrimEnd('/')"
@if (itemIndex.HasValue)
{
@:data-track="@eventName" data-track-value="@itemIndex"
@:data-package-id="@Model.Id" data-package-version="@Model.Version" data-use-version="@Model.UseVersion"
}
>@Html.BreakWord(Model.Id)</a>
@if (itemIndex.HasValue) { @: data-track="@eventName" data-track-value="@itemIndex"
@: data-package-id="@Model.Id" data-package-version="@Model.Version" data-use-version="@Model.UseVersion"
}>@Html.BreakWord(Model.Id)</a>
dannyjdev marked this conversation as resolved.
Show resolved Hide resolved

@if (Model.IsVerified.HasValue && Model.IsVerified.Value)
{
<img class="reserved-indicator"
src="~/Content/gallery/img/reserved-indicator.svg"
@ViewHelpers.ImageFallback(Url.Absolute("~/Content/gallery/img/reserved-indicator-20x20.png"))
data-content="@Strings.ReservedNamespace_ReservedIndicatorTooltip" tabindex="0" alt="@Strings.ReservedNamespace_ReservedIndicatorTooltip"/>
data-content="@Strings.ReservedNamespace_ReservedIndicatorTooltip" tabindex="0" alt="@Strings.ReservedNamespace_ReservedIndicatorTooltip" />
}

@if (showEditButton && (Model.CanEdit || Model.CanManageOwners || Model.CanUnlistOrRelist))
Expand All @@ -72,6 +69,29 @@
}
</div>


@if(Model.IsVulnerable || Model.IsDeprecated)
{
<ul class="package-list">
<li>
@if(Model.IsVulnerable)
{
<span class="icon-text package-warning--vulnerable">
<i class="ms-Icon ms-Icon--BlockedSiteSolid12" aria-hidden="true"></i>
Vulnerable
joelverhagen marked this conversation as resolved.
Show resolved Hide resolved
</span>
}
@if(Model.IsDeprecated)
{
<span class="icon-text package-warning--deprecated">
<i class="ms-Icon ms-Icon--ShieldAlert" aria-hidden="true"></i>
Deprecated
dannyjdev marked this conversation as resolved.
Show resolved Hide resolved
</span>
}
</li>
</ul>
}

<ul class="package-list">
<li>
<span class="icon-text">
Expand Down
71 changes: 71 additions & 0 deletions tests/NuGetGallery.Facts/Helpers/DeprecationItemsHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using NuGet.Services.Entities;
using System.Collections.Generic;

namespace NuGetGallery.Helpers
{
public static class DeprecationItemsHelper
{
public static IEnumerable<object[]> ValidObjects
{
get
{
yield return new object[] {
new Deprecation()
{
Message = "message",
Reasons = new [] { "Other", "Legacy", "CriticalBugs" },
AlternatePackage = new AlternatePackage() {
Id = "AnotherId",
Range = "[13.0.2-beta1, )"
}
}
};
yield return new object[] {
new Deprecation()
{
Reasons = new [] { "Other", "Legacy", "CriticalBugs" },
AlternatePackage = new AlternatePackage() {
Id = "AnotherId",
Range = "[13.0.2-beta1, )"
}
}
};
yield return new object[] {
new Deprecation()
{
Message = "message",
Reasons = new [] { "Other", "Legacy", "CriticalBugs" },
}
};
yield return new object[] {
new Deprecation()
{
Reasons = new [] { "Legacy" },
}
};
}
}

public static IEnumerable<object[]> InvalidObjects
{
get
{
yield return new object[] {
new Deprecation()
{
Message = "message",
AlternatePackage = new AlternatePackage() {
Id = "AnotherId",
Range = "[13.0.2-beta1, )"
}
}
};
yield return new object[] { new Deprecation() };
yield return new object[] { null };
}
}
}
}
50 changes: 50 additions & 0 deletions tests/NuGetGallery.Facts/Helpers/VulnerabilityItemsHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using NuGet.Services.Entities;
using System.Collections.Generic;

namespace NuGetGallery.Helpers
{
public static class VulnerabilityItemsHelper
{
public static IEnumerable<object[]> ValidObjects
{
get
{
yield return new object[] {
new List<Vulnerability>() {
new Vulnerability()
{
AdvisoryURL = "url",
Severity = 1
}
}
};
yield return new object[] {
new List<Vulnerability>() {
new Vulnerability()
{
AdvisoryURL = "url",
Severity = 1
},
new Vulnerability()
{
AdvisoryURL = "url",
Severity = 2
}
}
};
}
}

public static IEnumerable<object[]> InvalidObjects
{
get
{
yield return new object[] { new List<Vulnerability>() };
yield return new object[] { null };
}
}
}
}
Loading