From cfef1f3432b01fb812c237e398a29fde69bff69e Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Wed, 15 Jul 2020 19:51:01 +0200 Subject: [PATCH] Add separate recovery seed backup view fix --- BTCPayServer/Controllers/HomeController.cs | 8 ++ .../Controllers/StoresController.BTCLike.cs | 11 ++- BTCPayServer/Controllers/WalletsController.cs | 11 ++- BTCPayServer/Extensions.cs | 20 +++++ .../RecoverySeedBackupViewModel.cs | 21 +++++ .../Views/Home/RecoverySeedBackup.cshtml | 59 +++++++++++++ BTCPayServer/Views/Shared/PostRedirect.cshtml | 15 +++- BTCPayServer/Views/Shared/_LayoutPlain.cshtml | 84 +++++++++++++++++++ 8 files changed, 226 insertions(+), 3 deletions(-) create mode 100644 BTCPayServer/Models/StoreViewModels/RecoverySeedBackupViewModel.cs create mode 100644 BTCPayServer/Views/Home/RecoverySeedBackup.cshtml create mode 100644 BTCPayServer/Views/Shared/_LayoutPlain.cshtml diff --git a/BTCPayServer/Controllers/HomeController.cs b/BTCPayServer/Controllers/HomeController.cs index 29a2e65b7..1b79ef93b 100644 --- a/BTCPayServer/Controllers/HomeController.cs +++ b/BTCPayServer/Controllers/HomeController.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using BTCPayServer.Data; using BTCPayServer.HostedServices; using BTCPayServer.Models; +using BTCPayServer.Models.StoreViewModels; using BTCPayServer.Security; using BTCPayServer.Services.Apps; using Microsoft.AspNetCore.Authorization; @@ -191,6 +192,13 @@ namespace BTCPayServer.Controllers return View(vm); } + [Route("recovery-seed-backup")] + [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] + public IActionResult RecoverySeedBackup(RecoverySeedBackupViewModel vm) + { + return View("RecoverySeedBackup", vm); + } + public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); diff --git a/BTCPayServer/Controllers/StoresController.BTCLike.cs b/BTCPayServer/Controllers/StoresController.BTCLike.cs index f827b5599..df7661736 100644 --- a/BTCPayServer/Controllers/StoresController.BTCLike.cs +++ b/BTCPayServer/Controllers/StoresController.BTCLike.cs @@ -305,8 +305,17 @@ namespace BTCPayServer.Controllers TempData.SetStatusMessageModel(new StatusMessageModel() { Severity = StatusMessageModel.StatusSeverity.Success, - Html = $"Your wallet has been generated. Please store your seed securely!
{response.Mnemonic}" + Html = $"Your wallet has been generated. Please store your seed securely!" }); + var vm = new RecoverySeedBackupViewModel() + { + CryptoCode = cryptoCode, + Mnemonic = response.Mnemonic, + Passphrase = response.Passphrase, + IsStored = request.SavePrivateKeys, + ReturnUrl = Url.Action(nameof(UpdateStore), new { storeId }) + }; + return this.RedirectToRecoverySeedBackup(vm); } else { diff --git a/BTCPayServer/Controllers/WalletsController.cs b/BTCPayServer/Controllers/WalletsController.cs index 8eed1b862..5774f3a40 100644 --- a/BTCPayServer/Controllers/WalletsController.cs +++ b/BTCPayServer/Controllers/WalletsController.cs @@ -9,6 +9,7 @@ using BTCPayServer.Data; using BTCPayServer.HostedServices; using BTCPayServer.ModelBinders; using BTCPayServer.Models; +using BTCPayServer.Models.StoreViewModels; using BTCPayServer.Models.WalletViewModels; using BTCPayServer.Payments; using BTCPayServer.Security; @@ -1147,8 +1148,16 @@ namespace BTCPayServer.Controllers TempData.SetStatusMessageModel(new StatusMessageModel() { Severity = StatusMessageModel.StatusSeverity.Success, - Html = $"Please store your seed securely!
{seed}" + Html = $"Please store your seed securely!" }); + var recoveryVm = new RecoverySeedBackupViewModel() + { + CryptoCode = walletId.CryptoCode, + Mnemonic = seed, + IsStored = true, + ReturnUrl = Url.Action(nameof(WalletSettings), new { walletId }) + }; + return this.RedirectToRecoverySeedBackup(recoveryVm); } return RedirectToAction(nameof(WalletSettings)); diff --git a/BTCPayServer/Extensions.cs b/BTCPayServer/Extensions.cs index dab1efc7f..52f4b54d5 100644 --- a/BTCPayServer/Extensions.cs +++ b/BTCPayServer/Extensions.cs @@ -12,12 +12,14 @@ using BTCPayServer.Configuration; using BTCPayServer.Data; using BTCPayServer.Lightning; using BTCPayServer.Models; +using BTCPayServer.Models.StoreViewModels; using BTCPayServer.Payments; using BTCPayServer.Payments.Bitcoin; using BTCPayServer.Services; using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Wallets; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -429,5 +431,23 @@ namespace BTCPayServer { ctx.Items["BTCPAY.STORESDATA"] = storeData; } + + public static IActionResult RedirectToRecoverySeedBackup(this Controller controller, RecoverySeedBackupViewModel vm) + { + var redirectVm = new PostRedirectViewModel() + { + AspController = "Home", + AspAction = "RecoverySeedBackup", + Parameters = + { + new KeyValuePair("cryptoCode", vm.CryptoCode), + new KeyValuePair("mnemonic", vm.Mnemonic), + new KeyValuePair("passphrase", vm.Passphrase), + new KeyValuePair("isStored", vm.IsStored ? "true" : "false"), + new KeyValuePair("returnUrl", vm.ReturnUrl) + } + }; + return controller.View("PostRedirect", redirectVm); + } } } diff --git a/BTCPayServer/Models/StoreViewModels/RecoverySeedBackupViewModel.cs b/BTCPayServer/Models/StoreViewModels/RecoverySeedBackupViewModel.cs new file mode 100644 index 000000000..265d37f27 --- /dev/null +++ b/BTCPayServer/Models/StoreViewModels/RecoverySeedBackupViewModel.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Http; +using NBitcoin; + +namespace BTCPayServer.Models.StoreViewModels +{ + public class RecoverySeedBackupViewModel + { + public string CryptoCode { get; set; } + public string Mnemonic { get; set; } + public string Passphrase { get; set; } + public bool IsStored { get; set; } + public string ReturnUrl { get; set; } + + public string[] Words + { + get => Mnemonic.Split(" "); + } + } +} diff --git a/BTCPayServer/Views/Home/RecoverySeedBackup.cshtml b/BTCPayServer/Views/Home/RecoverySeedBackup.cshtml new file mode 100644 index 000000000..e5b4f9fb2 --- /dev/null +++ b/BTCPayServer/Views/Home/RecoverySeedBackup.cshtml @@ -0,0 +1,59 @@ +@model RecoverySeedBackupViewModel +@{ + Layout = "_LayoutSimple"; + ViewData["Title"] = "Save your recovery phrase"; +} + +
+
+ + +

@ViewData["Title"]

+ +
+
+ +
+
+

+ The words below are called your recovery phrase. + Please save these words securely. + They will allow you to recover your wallet. +

+ @if (!Model.IsStored) + { +

The recovery phrase will only be shown before being wiped from the server.

+ } +

+ Do not photograph or store this in a non air-gapped digital format. + Anyone with access to your recovery phrase can steal your funds. +

+ @if (!string.IsNullOrEmpty(Model.Passphrase)) + { +

Please make also sure to store your passphrase.

+ } +
+
+ +
    + @foreach (var word in Model.Words) + { +
  1. + @word +
  2. + } +
+ +
+ + + + +
+
+
diff --git a/BTCPayServer/Views/Shared/PostRedirect.cshtml b/BTCPayServer/Views/Shared/PostRedirect.cshtml index 7100ec505..b27abb221 100644 --- a/BTCPayServer/Views/Shared/PostRedirect.cshtml +++ b/BTCPayServer/Views/Shared/PostRedirect.cshtml @@ -1,12 +1,25 @@ @model PostRedirectViewModel @{ Layout = null; + + var routeData = Context.GetRouteData(); + var routeParams = new Dictionary(); + if (routeData != null) + { + routeParams["walletId"] = routeData.Values["walletId"]?.ToString(); + } } -
+ @foreach(var o in Model.Parameters) { } diff --git a/BTCPayServer/Views/Shared/_LayoutPlain.cshtml b/BTCPayServer/Views/Shared/_LayoutPlain.cshtml new file mode 100644 index 000000000..c59a38464 --- /dev/null +++ b/BTCPayServer/Views/Shared/_LayoutPlain.cshtml @@ -0,0 +1,84 @@ +@{ + Layout = null; +} + + + + + + + + + +
+ + + +
+ @RenderBody() +
+
+ @await Html.PartialAsync("_ValidationScriptsPartial") + +