Allow User to delete own account (#2949)

* Allow User to delete own account

* Add User delete e2e test

* fix test

* Apply suggestions from code review

Co-authored-by: d11n <mail@dennisreimann.de>

Co-authored-by: d11n <mail@dennisreimann.de>
This commit is contained in:
Andrew Camilleri
2021-10-09 05:18:37 +02:00
committed by GitHub
parent 4321cbf41a
commit 54539001f1
4 changed files with 53 additions and 5 deletions

View File

@@ -206,6 +206,15 @@ namespace BTCPayServer.Tests
// We should be logged in now // We should be logged in now
s.Driver.FindElement(By.Id("mainNav")); s.Driver.FindElement(By.Id("mainNav"));
//let's test delete user quickly while we're at it
s.GoToProfile();
s.Driver.FindElement(By.Id("danger-zone-expander")).Click();
s.Driver.FindElement(By.Id("delete-user")).Click();
s.Driver.WaitForElement(By.Id("ConfirmInput")).SendKeys("DELETE");
s.Driver.FindElement(By.Id("ConfirmContinue")).Click();
Assert.Contains("/login", s.Driver.Url);
} }
} }

View File

@@ -4,6 +4,7 @@ using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Fido2; using BTCPayServer.Fido2;
using BTCPayServer.Models;
using BTCPayServer.Models.ManageViewModels; using BTCPayServer.Models.ManageViewModels;
using BTCPayServer.Security.GreenField; using BTCPayServer.Security.GreenField;
using BTCPayServer.Services; using BTCPayServer.Services;
@@ -19,6 +20,7 @@ using Microsoft.Extensions.Logging;
namespace BTCPayServer.Controllers namespace BTCPayServer.Controllers
{ {
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Route("[controller]/[action]")] [Route("[controller]/[action]")]
public partial class ManageController : Controller public partial class ManageController : Controller
@@ -33,6 +35,7 @@ namespace BTCPayServer.Controllers
private readonly IAuthorizationService _authorizationService; private readonly IAuthorizationService _authorizationService;
private readonly Fido2Service _fido2Service; private readonly Fido2Service _fido2Service;
private readonly LinkGenerator _linkGenerator; private readonly LinkGenerator _linkGenerator;
private readonly UserService _userService;
readonly StoreRepository _StoreRepository; readonly StoreRepository _StoreRepository;
public ManageController( public ManageController(
@@ -41,14 +44,13 @@ namespace BTCPayServer.Controllers
EmailSenderFactory emailSenderFactory, EmailSenderFactory emailSenderFactory,
ILogger<ManageController> logger, ILogger<ManageController> logger,
UrlEncoder urlEncoder, UrlEncoder urlEncoder,
BTCPayWalletProvider walletProvider,
StoreRepository storeRepository, StoreRepository storeRepository,
IWebHostEnvironment env,
BTCPayServerEnvironment btcPayServerEnvironment, BTCPayServerEnvironment btcPayServerEnvironment,
APIKeyRepository apiKeyRepository, APIKeyRepository apiKeyRepository,
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
Fido2Service fido2Service, Fido2Service fido2Service,
LinkGenerator linkGenerator LinkGenerator linkGenerator,
UserService userService
) )
{ {
_userManager = userManager; _userManager = userManager;
@@ -61,6 +63,7 @@ namespace BTCPayServer.Controllers
_authorizationService = authorizationService; _authorizationService = authorizationService;
_fido2Service = fido2Service; _fido2Service = fido2Service;
_linkGenerator = linkGenerator; _linkGenerator = linkGenerator;
_userService = userService;
_StoreRepository = storeRepository; _StoreRepository = storeRepository;
} }
@@ -238,6 +241,30 @@ namespace BTCPayServer.Controllers
return RedirectToAction(nameof(SetPassword)); return RedirectToAction(nameof(SetPassword));
} }
[HttpGet()]
public IActionResult DeleteUser()
{
return View("Confirm", new ConfirmModel("Delete account", "Your account will be permanently deleted. This action will also delete all stores, invoices, apps and data associated with your account.", "Delete")
{
ActionUrl = "DeleteUserPost"
});
}
[HttpPost()]
public async Task<IActionResult> DeleteUserPost()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
await _userService.DeleteUserAndAssociatedData(user);
TempData[WellKnownTempData.SuccessMessage] = "Account successfully deleted.";
await _signInManager.SignOutAsync();
return RedirectToAction(nameof(AccountController.Login), "Account");
}
#region Helpers #region Helpers

View File

@@ -8,7 +8,7 @@ namespace BTCPayServer.Models
public ConfirmModel() {} public ConfirmModel() {}
public ConfirmModel(string title, string desc, string action = null, string buttonClass = ButtonClassDefault) public ConfirmModel(string title, string desc, string action = null, string buttonClass = ButtonClassDefault, string actionUrl = null)
{ {
Title = title; Title = title;
Description = desc; Description = desc;
@@ -19,6 +19,8 @@ namespace BTCPayServer.Models
{ {
DescriptionHtml = true; DescriptionHtml = true;
} }
ActionUrl = actionUrl;
} }
public string Title { get; set; } public string Title { get; set; }

View File

@@ -36,8 +36,18 @@
</div> </div>
</div> </div>
<button type="submit" id="save" class="btn btn-primary">Save</button> <button type="submit" id="save" class="btn btn-primary">Save</button>
<h4 class="mt-5 mb-3">Other actions</h4>
<button id="danger-zone-expander" class="btn btn-link text-secondary mb-3 p-0" type="button" data-bs-toggle="collapse" data-bs-target="#danger-zone">
See more actions
</button>
<div id="danger-zone" class="collapse">
<a id="delete-user" class="btn btn-outline-danger mb-5" asp-action="DeleteUser" data-confirm-input="DELETE" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-action="DeleteUserPost" data-description="This action will also delete all stores, invoices, apps and data associated with the user.">Delete your user.</a>
</div>
</form> </form>
<partial name="_Confirm"
model="@(new ConfirmModel("Delete user", "The user will be permanently deleted. This action will also delete all stores, invoices, apps and data associated with your user.", "Delete", actionUrl:"DeleteUserPost"))"/>
@section PageFootContent { @section PageFootContent {
<partial name="_ValidationScriptsPartial" /> <partial name="_ValidationScriptsPartial"/>
} }