public virtual ActionResult SubmitPackageValidationResults(string apiKey, string id, string version, bool success, string validationComments) { Guid parsedApiKey; if (!Guid.TryParse(apiKey, out parsedApiKey)) { return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, Strings.InvalidApiKey)); } var testReporterUser = userSvc.FindByApiKey(parsedApiKey); if (testReporterUser == null) { return(new HttpStatusCodeWithBodyResult(HttpStatusCode.Forbidden, String.Format(CultureInfo.CurrentCulture, Strings.ApiKeyNotAuthorized, "submitvalidationresults"))); } // Only the package operations user can submit test results if (testReporterUser.Key != settings.PackageOperationsUserKey) { return(new HttpStatusCodeWithBodyResult(HttpStatusCode.Forbidden, String.Format(CultureInfo.CurrentCulture, Strings.ApiKeyNotAuthorized, "submitvalidationresults"))); } if (String.IsNullOrEmpty(id) || String.IsNullOrEmpty(version)) { return(new HttpStatusCodeWithBodyResult(HttpStatusCode.NotFound, string.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version))); } if (string.IsNullOrWhiteSpace(validationComments)) { return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "Submitting validation results requires 'validationComments' and 'success'.")); } var package = packageSvc.FindPackageByIdAndVersion(id, version, allowPrerelease: true, useCache: false); if (package == null) { return(new HttpStatusCodeWithBodyResult(HttpStatusCode.NotFound, string.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version))); } package.PackageValidationResultDate = DateTime.UtcNow; package.PackageValidationResultStatus = PackageAutomatedReviewResultStatusType.Failing; var message = "{0} has failed automated validation.".format_with(package.PackageRegistration.Id); if (success) { package.PackageValidationResultStatus = PackageAutomatedReviewResultStatusType.Passing; message = "{0} has passed automated validation. It may have or may still fail other checks like testing (verification).".format_with(package.PackageRegistration.Id); } message += "{0}{1}".format_with(Environment.NewLine, validationComments); packageSvc.UpdateSubmittedStatusAfterAutomatedReviews(package); packageSvc.ChangePackageStatus(package, package.Status, package.ReviewComments, message, testReporterUser, testReporterUser, sendMaintainerEmail: true, submittedStatus: success ? package.SubmittedStatus : PackageSubmittedStatusType.Waiting, assignReviewer: false); return(new HttpStatusCodeWithBodyResult(HttpStatusCode.Accepted, "Package validation results have been updated.")); }
public virtual ActionResult DisplayPackage(string id, string version, FormCollection form) { if (!ModelState.IsValid) { return(DisplayPackage(id, version)); } var currentUser = userSvc.FindByUsername(GetIdentity().Name); var package = packageSvc.FindPackageByIdAndVersion(id, version, allowPrerelease: true, useCache: false); if (package == null) { return(PackageNotFound(id, version)); } var scanResults = packageSvc.GetPackageScanResults(id, version, useCache: false); package.Files = packageSvc.GetPackageFiles(package, useCache: false).ToList(); package.Description = FindAndCorrectInvalidMarkdownHeaders(package.Description); package.ReleaseNotes = FindAndCorrectInvalidMarkdownHeaders(package.ReleaseNotes); var model = new DisplayPackageViewModel(package, scanResults); if (currentUser.IsBanned) { TempData["Message"] = "Changes to package status have been saved."; return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } var packageRegistration = package.PackageRegistration; var isMaintainer = packageRegistration.Owners.AnySafe(x => x.Key == currentUser.Key); var isModerationRole = User.IsInAnyModerationRole() && !isMaintainer; var isModerator = User.IsModerator() && !isMaintainer; if (packageRegistration != null && !isMaintainer && !isModerationRole) { ModelState.AddModelError(String.Empty, String.Format(CultureInfo.CurrentCulture, Strings.ApiKeyNotAuthorized, "maintain")); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } if (!ModelState.IsValid) { return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } var status = PackageStatusType.Unknown; if (isMaintainer) { status = package.Status; } else { try { status = (PackageStatusType)Enum.Parse(typeof(PackageStatusType), form["Status"].clean_html()); } catch (Exception ex) { // Log but swallow the exception ErrorSignal.FromCurrentContext().Raise(ex); } } // maintainers and reviewers cannot change the current status if (User.IsReviewer() || isMaintainer) { status = package.Status; } if (package.Status != PackageStatusType.Unknown && status == PackageStatusType.Unknown) { ModelState.AddModelError(String.Empty, "A package cannot be moved into unknown status."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } if (package.Status == PackageStatusType.Unknown && status == PackageStatusType.Submitted) { ModelState.AddModelError(String.Empty, "A package cannot be moved from unknown to submitted status."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } if (User.IsReviewer() && status != PackageStatusType.Submitted) { ModelState.AddModelError(String.Empty, "A reviewer can only comment/submit in submitted status."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } var reviewedPlusOneHour = package.ReviewedDate.GetValueOrDefault().AddHours(1); if (!User.IsAdmin() && package.Status != status && reviewedPlusOneHour < DateTime.UtcNow && (package.Status == PackageStatusType.Approved || package.Status == PackageStatusType.Exempted || package.Status == PackageStatusType.Rejected ) ) { ModelState.AddModelError(String.Empty, "Only an admin can move a package from approved/exempt/rejected after one hour of status change. Please reach out on Gitter or use contact site admins link in the left side bar."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } var newComments = form["NewReviewComments"].clean_html(); bool sendMaintainerEmail = form["SendEmail"].clean_html() == "true"; bool trustedPackage = form["IsTrusted"].clean_html() == "true,false"; bool maintainerReject = form["MaintainerReject"].clean_html() == "true"; bool changeSubmittedStatus = form["ChangeSubmittedStatus"].clean_html() == "true"; //if (comments != package.ReviewComments) //{ // ModelState.AddModelError(String.Empty, "New comments have been added, please reload."); // return View("~/Views/Packages/DisplayPackage.cshtml", model); //} if (maintainerReject && string.IsNullOrWhiteSpace(newComments)) { ModelState.AddModelError(String.Empty, "In order to reject a package version, you must provide comments indicating why it is being rejected."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } if (isMaintainer && string.IsNullOrWhiteSpace(newComments)) { ModelState.AddModelError(String.Empty, "You need to provide comments."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } if (isMaintainer && maintainerReject) { status = PackageStatusType.Rejected; } bool exemptVerfication = form["IsExemptedFromVerification"].clean_html() == "true,false"; var exemptVerficationReason = form["ExemptedFromVerificationReason"].clean_html(); if (exemptVerfication && string.IsNullOrWhiteSpace(exemptVerficationReason)) { ModelState.AddModelError(String.Empty, "In order to exempt a package from automated testing, a reason should be specified."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } if (isModerationRole) { packageSvc.ExemptPackageFromTesting(package, exemptVerfication, exemptVerficationReason, currentUser); } bool rerunTests = form["RerunTests"].clean_html() == "true"; if (rerunTests) { packageSvc.ResetPackageTestStatus(package); if (!string.IsNullOrWhiteSpace(newComments)) { newComments += "{0}".format_with(Environment.NewLine); } newComments += "Auto Verification Change - Verification tests have been set to rerun."; } bool rerunValidation = form["RerunValidation"].clean_html() == "true"; if (rerunValidation) { packageSvc.ResetPackageValidationStatus(package); if (!string.IsNullOrWhiteSpace(newComments)) { newComments += "{0}".format_with(Environment.NewLine); } newComments += "Auto Validation Change - Validation tests have been set to rerun."; } bool rerunVirusScanner = form["RerunVirusScanner"].clean_html() == "true"; if (rerunVirusScanner) { package.PackageScanStatus = PackageScanStatusType.Unknown; packageSvc.SaveMinorPackageChanges(package); if (!string.IsNullOrWhiteSpace(newComments)) { newComments += "{0}".format_with(Environment.NewLine); } newComments += "Virus Scanner has ben set to rerun"; } bool rerunPackageCacher = form["RerunPackageCacher"].clean_html() == "true"; if (rerunPackageCacher) { package.DownloadCacheStatus = PackageDownloadCacheStatusType.Unknown; packageSvc.SaveMinorPackageChanges(package); if (!string.IsNullOrWhiteSpace(newComments)) { newComments += "{0}".format_with(Environment.NewLine); } newComments += "Package Cacher (CDN Download Cache) has ben set to rerun"; } bool exemptPackageFromValidation = form["ExemptPackageFromValidation"].clean_html() == "true"; if (exemptPackageFromValidation) { packageSvc.ExemptPackageFromValidation(package); if (!string.IsNullOrWhiteSpace(newComments)) { newComments += "{0}".format_with(Environment.NewLine); } newComments += "Auto Validation Change - Validation tests have been exempted."; } // could be null if no moderation has happened yet var moderator = isModerationRole ? currentUser : package.ReviewedBy; packageSvc.ChangePackageStatus(package, status, package.ReviewComments, newComments, currentUser, moderator, sendMaintainerEmail, isModerationRole ? changeSubmittedStatus ? PackageSubmittedStatusType.Waiting : package.SubmittedStatus : PackageSubmittedStatusType.Responded, assignReviewer: true ); if (isModerator) { packageSvc.ChangeTrustedStatus(package, trustedPackage, moderator); } //grab updated package package = packageSvc.FindPackageByIdAndVersion(id, version, allowPrerelease: true, useCache: false); scanResults = packageSvc.GetPackageScanResults(id, version, useCache: false); package.Files = packageSvc.GetPackageFiles(package, useCache: false).ToList(); model = new DisplayPackageViewModel(package, scanResults); TempData["Message"] = "Changes to package status have been saved."; return(View("~/Views/Packages/DisplayPackage.cshtml", model)); }
public virtual ActionResult DisplayPackage(string id, string version, FormCollection form) { if (!ModelState.IsValid) { return(DisplayPackage(id, version)); } var package = packageSvc.FindPackageByIdAndVersion(id, version); if (package == null) { return(PackageNotFound(id, version)); } var model = new DisplayPackageViewModel(package); if (!ModelState.IsValid) { return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } var status = PackageStatusType.Unknown; try { status = (PackageStatusType)Enum.Parse(typeof(PackageStatusType), form["Status"]); } catch (Exception ex) { // Log but swallow the exception ErrorSignal.FromCurrentContext().Raise(ex); } //reviewers cannot change the current status if (User.IsReviewer()) { status = package.Status; } if (package.Status != PackageStatusType.Unknown && status == PackageStatusType.Unknown) { ModelState.AddModelError(String.Empty, "A package cannot be moved into unknown status."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } if (package.Status == PackageStatusType.Unknown && status == PackageStatusType.Submitted) { ModelState.AddModelError(String.Empty, "A package cannot be moved from unknown to submitted status."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } if (User.IsReviewer() && status != PackageStatusType.Submitted) { ModelState.AddModelError(String.Empty, "A reviewer can only comment/submit in submitted status."); return(View("~/Views/Packages/DisplayPackage.cshtml", model)); } var comments = form["ReviewComments"]; bool sendEmail = form["SendEmail"] != null; bool trustedPackage = form["IsTrusted"] == "true,false"; var moderator = userSvc.FindByUsername(HttpContext.User.Identity.Name); packageSvc.ChangePackageStatus(package, status, comments, moderator, sendEmail); packageSvc.ChangeTrustedStatus(package, trustedPackage, moderator); //grab updated package package = packageSvc.FindPackageByIdAndVersion(id, version); model = new DisplayPackageViewModel(package); TempData["Message"] = "Changes to package status have been saved."; return(View("~/Views/Packages/DisplayPackage.cshtml", model)); }