mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Prevent payment request to be created when a wallet is not set up (#5620)
* Prevent payment request to be created when a wallet is not set up * Created an extension method for store wallet checks * fix for invoice and payment request selenium test * refactoring payment request controller * removing unused variable * Unify behaviour across controllers --------- Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
This commit is contained in:
parent
e90414bded
commit
f7542c988d
4 changed files with 89 additions and 66 deletions
|
@ -565,9 +565,11 @@ namespace BTCPayServer.Tests
|
|||
s.RegisterNewUser(true);
|
||||
s.CreateNewStore();
|
||||
s.GoToInvoices();
|
||||
s.Driver.FindElement(By.Id("CreateNewInvoice")).Click();
|
||||
|
||||
// Should give us an error message if we try to create an invoice before adding a wallet
|
||||
s.Driver.FindElement(By.Id("CreateNewInvoice")).Click();
|
||||
Assert.Contains("To create an invoice, you need to", s.Driver.PageSource);
|
||||
|
||||
s.AddDerivationScheme();
|
||||
s.GoToInvoices();
|
||||
s.CreateInvoice();
|
||||
|
@ -1195,8 +1197,13 @@ namespace BTCPayServer.Tests
|
|||
await s.StartAsync();
|
||||
s.RegisterNewUser();
|
||||
s.CreateNewStore();
|
||||
s.AddDerivationScheme();
|
||||
s.Driver.FindElement(By.Id("StoreNav-PaymentRequests")).Click();
|
||||
|
||||
// Should give us an error message if we try to create a payment request before adding a wallet
|
||||
s.Driver.FindElement(By.Id("CreatePaymentRequest")).Click();
|
||||
Assert.Contains("To create a payment request, you need to", s.Driver.PageSource);
|
||||
|
||||
s.AddDerivationScheme();
|
||||
s.Driver.FindElement(By.Id("StoreNav-PaymentRequests")).Click();
|
||||
s.Driver.FindElement(By.Id("CreatePaymentRequest")).Click();
|
||||
s.Driver.FindElement(By.Id("Title")).SendKeys("Pay123");
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Mime;
|
||||
using System.Net.WebSockets;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
|
@ -32,10 +29,8 @@ using Microsoft.AspNetCore.Mvc.Rendering;
|
|||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NBitcoin;
|
||||
using NBitpayClient;
|
||||
using NBXplorer;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using BitpayCreateInvoiceRequest = BTCPayServer.Models.BitpayCreateInvoiceRequest;
|
||||
using StoreData = BTCPayServer.Data.StoreData;
|
||||
|
||||
namespace BTCPayServer.Controllers
|
||||
|
@ -1149,63 +1144,34 @@ namespace BTCPayServer.Controllers
|
|||
};
|
||||
}
|
||||
|
||||
private SelectList GetPaymentMethodsSelectList()
|
||||
{
|
||||
var store = GetCurrentStore();
|
||||
var excludeFilter = store.GetStoreBlob().GetExcludedPaymentMethods();
|
||||
|
||||
return new SelectList(store.GetSupportedPaymentMethods(_NetworkProvider)
|
||||
.Where(s => !excludeFilter.Match(s.PaymentId))
|
||||
.Select(method => new SelectListItem(method.PaymentId.ToPrettyString(), method.PaymentId.ToString())),
|
||||
nameof(SelectListItem.Value),
|
||||
nameof(SelectListItem.Text));
|
||||
}
|
||||
|
||||
private bool AnyPaymentMethodAvailable(StoreData store)
|
||||
{
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var excludeFilter = storeBlob.GetExcludedPaymentMethods();
|
||||
|
||||
return store.GetSupportedPaymentMethods(_NetworkProvider).Where(s => !excludeFilter.Match(s.PaymentId)).Any();
|
||||
}
|
||||
|
||||
[HttpGet("/stores/{storeId}/invoices/create")]
|
||||
[HttpGet("invoices/create")]
|
||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
[BitpayAPIConstraint(false)]
|
||||
public async Task<IActionResult> CreateInvoice(InvoicesModel? model = null)
|
||||
{
|
||||
if (model?.StoreId != null)
|
||||
{
|
||||
var store = await _StoreRepository.FindStore(model.StoreId, GetUserId());
|
||||
if (store == null)
|
||||
return NotFound();
|
||||
|
||||
if (!AnyPaymentMethodAvailable(store))
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Error,
|
||||
Html = $"To create an invoice, you need to <a href='{Url.Action(nameof(UIStoresController.SetupWallet), "UIStores", new { cryptoCode = _NetworkProvider.DefaultNetwork.CryptoCode, storeId = store.Id })}' class='alert-link'>set up a wallet</a> first",
|
||||
AllowDismiss = false
|
||||
});
|
||||
}
|
||||
|
||||
HttpContext.SetStoreData(store);
|
||||
}
|
||||
else
|
||||
if (string.IsNullOrEmpty(model?.StoreId))
|
||||
{
|
||||
TempData[WellKnownTempData.ErrorMessage] = "You need to select a store before creating an invoice.";
|
||||
return RedirectToAction(nameof(UIHomeController.Index), "UIHome");
|
||||
}
|
||||
|
||||
var storeBlob = HttpContext.GetStoreData()?.GetStoreBlob();
|
||||
var store = await _StoreRepository.FindStore(model.StoreId, GetUserId());
|
||||
if (store == null)
|
||||
return NotFound();
|
||||
|
||||
if (!store.AnyPaymentMethodAvailable(_NetworkProvider))
|
||||
{
|
||||
return NoPaymentMethodResult(store.Id);
|
||||
}
|
||||
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var vm = new CreateInvoiceModel
|
||||
{
|
||||
StoreId = model.StoreId,
|
||||
Currency = storeBlob?.DefaultCurrency,
|
||||
CheckoutType = storeBlob?.CheckoutType ?? CheckoutType.V2,
|
||||
AvailablePaymentMethods = GetPaymentMethodsSelectList()
|
||||
Currency = storeBlob.DefaultCurrency,
|
||||
CheckoutType = storeBlob.CheckoutType,
|
||||
AvailablePaymentMethods = GetPaymentMethodsSelectList(store)
|
||||
};
|
||||
|
||||
return View(vm);
|
||||
|
@ -1218,9 +1184,14 @@ namespace BTCPayServer.Controllers
|
|||
public async Task<IActionResult> CreateInvoice(CreateInvoiceModel model, CancellationToken cancellationToken)
|
||||
{
|
||||
var store = HttpContext.GetStoreData();
|
||||
if (!store.AnyPaymentMethodAvailable(_NetworkProvider))
|
||||
{
|
||||
return NoPaymentMethodResult(store.Id);
|
||||
}
|
||||
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
model.CheckoutType = storeBlob.CheckoutType;
|
||||
model.AvailablePaymentMethods = GetPaymentMethodsSelectList();
|
||||
model.AvailablePaymentMethods = GetPaymentMethodsSelectList(store);
|
||||
|
||||
JObject? metadataObj = null;
|
||||
if (!string.IsNullOrEmpty(model.Metadata))
|
||||
|
@ -1239,18 +1210,6 @@ namespace BTCPayServer.Controllers
|
|||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
if (!AnyPaymentMethodAvailable(store))
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Error,
|
||||
Html = $"To create an invoice, you need to <a href='{Url.Action(nameof(UIStoresController.SetupWallet), "UIStores", new { cryptoCode = _NetworkProvider.DefaultNetwork.CryptoCode, storeId = store.Id })}' class='alert-link'>set up a wallet</a> first",
|
||||
AllowDismiss = false
|
||||
});
|
||||
return View(model);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var metadata = metadataObj is null ? new InvoiceMetadata() : InvoiceMetadata.FromJObject(metadataObj);
|
||||
|
@ -1396,5 +1355,26 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SelectList GetPaymentMethodsSelectList(StoreData store)
|
||||
{
|
||||
var excludeFilter = store.GetStoreBlob().GetExcludedPaymentMethods();
|
||||
return new SelectList(store.GetSupportedPaymentMethods(_NetworkProvider)
|
||||
.Where(s => !excludeFilter.Match(s.PaymentId))
|
||||
.Select(method => new SelectListItem(method.PaymentId.ToPrettyString(), method.PaymentId.ToString())),
|
||||
nameof(SelectListItem.Value),
|
||||
nameof(SelectListItem.Text));
|
||||
}
|
||||
|
||||
private IActionResult NoPaymentMethodResult(string storeId)
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Error,
|
||||
Html = $"To create an invoice, you need to <a href='{Url.Action(nameof(UIStoresController.SetupWallet), "UIStores", new { cryptoCode = _NetworkProvider.DefaultNetwork.CryptoCode, storeId })}' class='alert-link'>set up a wallet</a> first",
|
||||
AllowDismiss = false
|
||||
});
|
||||
return RedirectToAction(nameof(ListInvoices), new { storeId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Form;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
|
@ -39,6 +41,7 @@ namespace BTCPayServer.Controllers
|
|||
private readonly DisplayFormatter _displayFormatter;
|
||||
private readonly InvoiceRepository _InvoiceRepository;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly BTCPayNetworkProvider _networkProvider;
|
||||
|
||||
private FormComponentProviders FormProviders { get; }
|
||||
public FormDataService FormDataService { get; }
|
||||
|
@ -54,7 +57,8 @@ namespace BTCPayServer.Controllers
|
|||
StoreRepository storeRepository,
|
||||
InvoiceRepository invoiceRepository,
|
||||
FormComponentProviders formProviders,
|
||||
FormDataService formDataService)
|
||||
FormDataService formDataService,
|
||||
BTCPayNetworkProvider networkProvider)
|
||||
{
|
||||
_InvoiceController = invoiceController;
|
||||
_UserManager = userManager;
|
||||
|
@ -67,6 +71,7 @@ namespace BTCPayServer.Controllers
|
|||
_InvoiceRepository = invoiceRepository;
|
||||
FormProviders = formProviders;
|
||||
FormDataService = formDataService;
|
||||
_networkProvider = networkProvider;
|
||||
}
|
||||
|
||||
[HttpGet("/stores/{storeId}/payment-requests")]
|
||||
|
@ -107,12 +112,20 @@ namespace BTCPayServer.Controllers
|
|||
public async Task<IActionResult> EditPaymentRequest(string storeId, string payReqId)
|
||||
{
|
||||
var store = GetCurrentStore();
|
||||
if (store == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
var paymentRequest = GetCurrentPaymentRequest();
|
||||
if (paymentRequest == null && !string.IsNullOrEmpty(payReqId))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (!store.AnyPaymentMethodAvailable(_networkProvider))
|
||||
{
|
||||
return NoPaymentMethodResult(storeId);
|
||||
}
|
||||
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var prInvoices = payReqId is null ? null : (await _PaymentRequestService.GetPaymentRequest(payReqId, GetUserId())).Invoices;
|
||||
var vm = new UpdatePaymentRequestViewModel(paymentRequest)
|
||||
|
@ -143,7 +156,11 @@ namespace BTCPayServer.Controllers
|
|||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (!store.AnyPaymentMethodAvailable(_networkProvider))
|
||||
{
|
||||
return NoPaymentMethodResult(store.Id);
|
||||
}
|
||||
|
||||
if (paymentRequest?.Archived is true && viewModel.Archived)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "You cannot edit an archived payment request.");
|
||||
|
@ -441,5 +458,16 @@ namespace BTCPayServer.Controllers
|
|||
private StoreData GetCurrentStore() => HttpContext.GetStoreData();
|
||||
|
||||
private PaymentRequestData GetCurrentPaymentRequest() => HttpContext.GetPaymentRequestData();
|
||||
|
||||
private IActionResult NoPaymentMethodResult(string storeId)
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Error,
|
||||
Html = $"To create a payment request, you need to <a href='{Url.Action(nameof(UIStoresController.SetupWallet), "UIStores", new { cryptoCode = _networkProvider.DefaultNetwork.CryptoCode, storeId })}' class='alert-link'>set up a wallet</a> first",
|
||||
AllowDismiss = false
|
||||
});
|
||||
return RedirectToAction(nameof(GetPaymentRequests), new { storeId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,14 @@ namespace BTCPayServer.Data
|
|||
return result;
|
||||
}
|
||||
|
||||
public static bool AnyPaymentMethodAvailable(this StoreData storeData, BTCPayNetworkProvider networkProvider)
|
||||
{
|
||||
var storeBlob = GetStoreBlob(storeData);
|
||||
var excludeFilter = storeBlob.GetExcludedPaymentMethods();
|
||||
|
||||
return GetSupportedPaymentMethods(storeData, networkProvider).Where(s => !excludeFilter.Match(s.PaymentId)).Any();
|
||||
}
|
||||
|
||||
public static bool SetStoreBlob(this StoreData storeData, StoreBlob storeBlob)
|
||||
{
|
||||
var original = new Serializer(null).ToString(storeData.GetStoreBlob());
|
||||
|
|
Loading…
Add table
Reference in a new issue