-
Notifications
You must be signed in to change notification settings - Fork 644
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 initial support for user deletion request #5007
Conversation
if (!allowDelete | ||
&& reportForm.DeleteDecision == PackageDeleteDecision.DeletePackage) | ||
{ | ||
reportForm.DeleteDecision = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that lack of permissions is going to result in the same UI validation error for when a delete decision wasn't provided?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, the UI will behave as if the delete decision UI was hidden. Really, the user should never get into this case because the UI doesn't allow it. The missing delete decision validation error only occurs if allowDelete
is true (which is not the case here).
{ | ||
// Swallow exceptions that occur during the delete process. If this happens, we'll just | ||
// send out the support request as usual and handle it manually. | ||
QuietLog.LogHandledException(e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will the user receive a message that the support request was sent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleted
will still be false
so we will show the "support request sent" message as usual.
@@ -291,6 +291,19 @@ public static HtmlString ShowCheckboxFor<TModel>(this HtmlHelper<TModel> html, E | |||
public static MvcHtmlString ShowEnumDropDownListFor<TModel, TEnum>( | |||
this HtmlHelper<TModel> html, | |||
Expression<Func<TModel, TEnum?>> expression, | |||
string emptyItemText) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's also a HtmlExtensions class. Maybe we should move these HtmlHelper extensions there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, good point. I'll take a look at that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this is a big mess already. I will create an issue to clean this up.
#5015
can you attach screenshots? |
} | ||
|
||
// Enforce the auto-delete rules. | ||
var allowDelete = await _packageDeleteService.CanPackageBeDeletedByUserAsync(package); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to evaluate CanPackageBeDeletedByUserAsync is DeleteDecision is not DeletePackage? If the user just wants to contact support we are doing unnecessary work here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point, no we don't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
{ | ||
return HttpNotFound(); | ||
reportForm.CopySender = false; | ||
reportForm.Message = "This support request is intended for automatic deletion."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
automatic package deletion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. Good point.
user, | ||
package); | ||
|
||
if (supportRequest != null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when will AddNewSupportRequestAsync return null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the commit to the support request DB fails. This is existing logic in the support request service.
"change to propagate through our system."; | ||
|
||
return Redirect(Url.Package(id, version)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method is to big. Can you split it to smaller methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
|
||
TempData["Message"] = | ||
"We're performing the package delete right now. It may take a while for this " + | ||
"change to propagate through our system."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this controller doesn't do much use of Strings, but perhaps it time to start?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
return HttpNotFound(); | ||
} | ||
|
||
if (!PermissionsService.IsActionAllowed(package, User, PackageActions.ReportMyPackage)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the permissions required for reporting a package are the same as for deleting a package? Do we need a special check for the later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same permissions. The keyword here is "My" in "ReportMyPackage".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🕐
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A subsequent commit will complete the work and fully enable this feature. Progress on NuGet/Engineering#921
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
woops, looks like i missed the bell
@@ -35,6 +36,29 @@ namespace NuGetGallery | |||
public partial class PackagesController | |||
: AppController | |||
{ | |||
private static readonly IReadOnlyList<ReportPackageReason> ReportAbuseReasons = new[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add some comments on what these are for.
/// <summary>
/// Reasons that users can select when reporting abuse by a package they do not own.
/// </summary>
private static readonly IReadOnlyList<ReportPackageReason> ReportAbuseReasons = new[] { ... }
/// <summary>
/// Reasons that users can select when reporting their own package.
/// </summary>
private static readonly IReadOnlyList<ReportPackageReason> ReportMyPackageReasons = new[] { ... }
/// <summary>
/// Subset of <see cref="ReportMyPackageReasons"/> that suggests a user would like to delete a package.
/// </summary>
private static readonly IReadOnlyList<ReportPackageReason> DeleteReasons = new[] { ... }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good idea. Thanks for doing the work for me 😉
|
||
var modelIsValid = ModelState.IsValid; | ||
if (reportForm.Reason == ReportPackageReason.ViolatesALicenseIOwn) | ||
reportForm.Message = HttpUtility.HtmlEncode(reportForm.Message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this isn't related to this PR, but shouldn't MVC do this encoding for us?
If it's needed, we should have a comment describing why.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of scope of this PR. I think we are encoding it since it makes its way into the email system.
modelIsValid = modelIsValid && !string.IsNullOrEmpty(reportForm.Signature); | ||
ModelState.AddModelError( | ||
nameof(ReportAbuseViewModel.Signature), | ||
"The signature is required."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 - This should be in Strings.resx
2 - We should be more verbose here: for example, "A signature is required when submitting a copyright violation request."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that should be in Strings.
The context of the UI negates the need for verbosity. If the message field is visible, it is required.
return RedirectToAction(nameof(ReportAbuse), new { id = package.PackageRegistration.Id, version = package.NormalizedVersion }); | ||
} | ||
|
||
reportForm.Message = HttpUtility.HtmlEncode(reportForm.Message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above: shouldn't MVC do the encoding for us?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above.
allowDelete = await _packageDeleteService.CanPackageBeDeletedByUserAsync(package); | ||
if (!allowDelete) | ||
{ | ||
reportForm.DeleteDecision = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems really odd to me that we are changing the form here. It also made the logic more confusing for me.
If someone specifies they would like to delete their package, shouldn't we either
1 - return an error message that says they package does not meet the criteria
2 - keep the deletion state so that the on-call can see it in the support request
Regardless, there should be a comment on this line describing what we are doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 - return an error message that says they package does not meet the criteria
Why show an error message? The only way this can happen is if someone is fiddling with the request or if they get the form while the package can be deleted and only submit it after the package can't be deleted. We shouldn't put extra effort into these cases.
2 - keep the deletion state so that the on-call can see it in the support request
The deletion state shouldn't even be persisted in this case. It's a bad request which should be rejected early on.
Regardless, there should be a comment on this line describing what we are doing.
Sounds good.
package.PackageRegistration.Id, | ||
package.NormalizedVersion); | ||
var reason = EnumHelper.GetDescription(reportForm.Reason.Value); | ||
var supportRequest = await _supportRequestService.AddNewSupportRequestAsync( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the user attempts to the delete the package, why are we creating a support request?
Seems unnecessary. We should just delete it and if it fails, then create the request. Probably makes this code simpler because we don't need to pass around this support request object.
Also, it's very odd to be creating support requests we don't get emails for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to track the auto-delete in a way the PMs asked for.
@@ -61,6 +61,13 @@ public class PackageDeleteService | |||
_auditingService = auditingService; | |||
} | |||
|
|||
public Task<bool> CanPackageBeDeletedByUserAsync(Package package) | |||
{ | |||
// For now, don't allow user's to delete their packages. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: user's
-> users
@Html.ShowCheckboxFor(m => m.DeleteConfirmation) | ||
I understand that this action cannot be undone. This will permanently delete the package | ||
@Model.PackageId @Model.PackageVersion and make it unavailable for download and package restore. | ||
This does not allow uploading a new package with the same version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To keep the same phrasing, this I will not be able to upload a new package with the same version.
or something similar might be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I like that better too.
_viewModel); | ||
|
||
// Assert | ||
Assert.Contains( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can consolidate this into a helper message to be used in a number of these other tests
private void AssertContainsMessage(PackagesController controller, string message)
{
Assert.Contains(message, _controller.ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage));
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
} | ||
|
||
[Theory] | ||
[InlineData(ReportPackageReason.ContainsMaliciousCode)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
two thoughts:
1 - we should make this run on all members of PackagesController.DeleteReasons
2 - if we are concerned about the members of PackageController.DeleteReasons
changing, then there should be tests for that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of out of scope, as there was no pre-existing validation on which reasons were being sent, but I'll add tests for it.
@scottbommarito, I will address these comments in a follow-up PR. |
A subsequent commit will complete the work and fully enable this feature. Progress on NuGet/Engineering#921
Progress on https://github.com/NuGet/Engineering/issues/921.
The changes were getting big so I stopped and made a PR. Hopefully easier to review.
This PR:
IPackageDeleteService
to determine if a package can be deleted. It always returns false right now.TODO:
Without these TODOs, the new code paths introduced by this PR will not be available yet.