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

Add bulk revalidate buttons to Validation admin panel #8738

Merged
merged 4 commits into from
Aug 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 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.

4 changes: 4 additions & 0 deletions src/Bootstrap/less/theme/base.less
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ body {
}
}

.form-inline-empty {
display: inline-block;
}

.footer {
background-color: @panel-footer-bg;
color: @panel-footer-color;
Expand Down
5 changes: 4 additions & 1 deletion src/NuGetGallery/App_Code/ViewHelpers.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -653,14 +653,15 @@ var hlp = new AccordionHelper(name, formModelStatePrefix, expanded, page);
string controllerName,
string role,
string area = "",
string classes = null,
Dictionary<string, string> formValues = null)
{
using (page.Html.BeginForm(
actionName,
controllerName,
new { area = area },
FormMethod.Post,
new { id = formId }))
new { id = formId, @class = classes }))
{
@page.Html.AntiForgeryToken();
if (formValues != null)
Expand All @@ -682,6 +683,7 @@ var hlp = new AccordionHelper(name, formModelStatePrefix, expanded, page);
string controllerName,
string role,
string area = "",
string classes = null,
Dictionary<string, string> formValues = null)
{
@PostLink(
Expand All @@ -692,6 +694,7 @@ var hlp = new AccordionHelper(name, formModelStatePrefix, expanded, page);
controllerName,
role,
area,
classes,
formValues);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using NuGet.Services.Entities;
using NuGet.Services.Validation;
using NuGet.Versioning;
using NuGetGallery.Areas.Admin.Services;
Expand Down Expand Up @@ -40,6 +42,25 @@ public virtual ActionResult Pending()
return View(nameof(Index), new ValidationPageViewModel(query, packageValidations));
}

[HttpPost]
[ValidateAntiForgeryToken]
public virtual async Task<RedirectToRouteResult> RevalidatePending(ValidatingType validatingType)
{
var revalidatedCount = await _validationAdminService.RevalidatePendingAsync(validatingType);

if (revalidatedCount == 0)
{
TempData["Message"] = $"There are no {validatingType} instances that are in the {PackageStatus.Validating} state so no validations were enqueued.";
}
else
{
TempData["Message"] = $"{revalidatedCount} validations were enqueued for {validatingType} instances that are in the {PackageStatus.Validating} state. " +
$"It may take some time for the new validations to appear as the validation subsystem reacts to the enqueued messages.";
}

return RedirectToAction(nameof(Pending));
}

[HttpGet]
public virtual ActionResult Search(string q)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using NuGet.Services.Entities;
using NuGet.Services.Validation;
using NuGet.Versioning;
Expand All @@ -20,17 +21,20 @@ public class ValidationAdminService
private readonly IEntityRepository<PackageValidation> _validations;
private readonly IEntityRepository<Package> _packages;
private readonly IEntityRepository<SymbolPackage> _symbolPackages;
private readonly IValidationService _validationService;

public ValidationAdminService(
IEntityRepository<PackageValidationSet> validationSets,
IEntityRepository<PackageValidation> validations,
IEntityRepository<Package> packages,
IEntityRepository<SymbolPackage> symbolPackages)
IEntityRepository<SymbolPackage> symbolPackages,
IValidationService validationService)
{
_validationSets = validationSets ?? throw new ArgumentNullException(nameof(validationSets));
_validations = validations ?? throw new ArgumentNullException(nameof(validations));
_packages = packages ?? throw new ArgumentNullException(nameof(packages));
_symbolPackages = symbolPackages ?? throw new ArgumentNullException(nameof(symbolPackages));
_validationService = validationService ?? throw new ArgumentNullException(nameof(validationService));
}

/// <summary>
Expand Down Expand Up @@ -83,6 +87,45 @@ public IReadOnlyList<PackageValidationSet> GetPending()
return pendingValidations;
}

public async Task<int> RevalidatePendingAsync(ValidatingType validatingType)
{
if (validatingType == ValidatingType.Package)
{
var pendingPackages = _packages
.GetAll()
.Include(p => p.PackageRegistration)
.Where(p => p.PackageStatusKey == PackageStatus.Validating)
.ToList();

foreach (var package in pendingPackages)
{
await _validationService.RevalidateAsync(package);
}

return pendingPackages.Count;
}
else if (validatingType == ValidatingType.SymbolPackage)
{
var pendingSymbolPackages = _symbolPackages
.GetAll()
.Include(p => p.Package)
.Include(p => p.Package.PackageRegistration)
.Where(s => s.StatusKey == PackageStatus.Validating)
.ToList();

foreach (var symbolPackage in pendingSymbolPackages)
{
await _validationService.RevalidateAsync(symbolPackage);
}

return pendingSymbolPackages.Count;
}
else
{
throw new NotSupportedException("The validating type " + validatingType + " is not supported.");
}
}

public PackageDeletedStatus GetDeletedStatus(int key, ValidatingType validatingType)
{
switch (validatingType)
Expand Down
55 changes: 50 additions & 5 deletions src/NuGetGallery/Areas/Admin/Views/Validation/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,37 @@
<section role="main" class="container main-container">
<h2>Package Validations</h2>

<p>Get <a href="@Url.Action(actionName:"Pending")">pending validations</a>.</p>
<div>
<a href="@Url.Action(actionName:"Pending")">Get pending validations</a>
|
@ViewHelpers.PostLink(
this,
formId: "revalidate-pending-packages",
linkText: "Revalidate pending packages",
actionName: "RevalidatePending",
controllerName: "Validation",
role: string.Empty,
area: "Admin",
classes: "form-inline-empty",
formValues: new Dictionary<string, string>
{
{ "validatingType", ValidatingType.Package.ToString() },
})
|
@ViewHelpers.PostLink(
this,
formId: "revalidate-pending-symbol-packages",
linkText: "Revalidate pending symbol packages",
actionName: "RevalidatePending",
controllerName: "Validation",
role: string.Empty,
area: "Admin",
classes: "form-inline-empty",
formValues: new Dictionary<string, string>
{
{ "validatingType", ValidatingType.SymbolPackage.ToString() },
})
</div>

<form method="get" action="@Url.Action(actionName: "Search")">
<p>
Expand Down Expand Up @@ -78,7 +108,7 @@
{
@ViewHelpers.PostLink(
this,
formId: "revalidate-package-form",
formId: "revalidate-package-form-" + package.PackageKey,
linkText: "Revalidate package",
actionName: "Revalidate",
controllerName: "Packages",
Expand All @@ -87,14 +117,15 @@
{
{ "id", package.Id },
{ "version", package.NormalizedVersion },
{ "returnUrl", Url.Current() },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀🚀

})
<br />
}
else if (package.ValidatingType == ValidatingType.SymbolPackage)
{
@ViewHelpers.PostLink(
this,
formId: "revalidate-symbols-form",
formId: "revalidate-symbols-form-" + package.PackageKey,
linkText: "Revalidate symbols",
actionName: "RevalidateSymbols",
controllerName: "Packages",
Expand All @@ -103,6 +134,7 @@
{
{ "id", package.Id },
{ "version", package.NormalizedVersion },
{ "returnUrl", Url.Current() },
})
<br />
}
Expand Down Expand Up @@ -193,8 +225,21 @@
</table>
}
</div>

}
</div>
}
</section>
</section>

@section BottomScripts {
<script>
$(document).ready(function () {
$('#revalidate-pending-packages, #revalidate-pending-symbol-packages').submit(function (e) {
var operation = $(".post-link[data-form-id='" + e.target.id + "']").text().toLowerCase();
if (!operation || !confirm('Are you sure you want to ' + operation + '?')) {
e.preventDefault();
}
});
});
</script>
}
22 changes: 18 additions & 4 deletions src/NuGetGallery/Controllers/PackagesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1911,7 +1911,7 @@ public virtual async Task<ActionResult> Reflow(string id, string version)
[ValidateAntiForgeryToken]
[UIAuthorize(Roles = "Admins")]
[RequiresAccountConfirmation("revalidate a package")]
public virtual async Task<ActionResult> Revalidate(string id, string version)
public virtual async Task<ActionResult> Revalidate(string id, string version, string returnUrl = null)
{
var package = _packageService.FindPackageByIdAndVersionStrict(id, version);

Expand All @@ -1933,14 +1933,21 @@ public virtual async Task<ActionResult> Revalidate(string id, string version)
TempData["Message"] = $"An error occurred while revalidating the package. {ex.Message}";
}

return SafeRedirect(Url.Package(id, version));
if (string.IsNullOrEmpty(returnUrl))
{
return SafeRedirect(Url.Package(id, version));
}
else
{
return SafeRedirect(returnUrl);
}
}

[HttpPost]
[ValidateAntiForgeryToken]
[UIAuthorize(Roles = "Admins")]
[RequiresAccountConfirmation("revalidate a symbols package")]
public virtual async Task<ActionResult> RevalidateSymbols(string id, string version)
public virtual async Task<ActionResult> RevalidateSymbols(string id, string version, string returnUrl = null)
{
var package = _packageService.FindPackageByIdAndVersionStrict(id, version);

Expand Down Expand Up @@ -1988,7 +1995,14 @@ public virtual async Task<ActionResult> RevalidateSymbols(string id, string vers
TempData["Message"] = $"An error occurred while revalidating the symbols package. {ex.Message}";
}

return SafeRedirect(Url.Package(id, version));
if (string.IsNullOrEmpty(returnUrl))
{
return SafeRedirect(Url.Package(id, version));
}
else
{
return SafeRedirect(returnUrl);
}
}

/// <summary>
Expand Down
Loading