From d480be925b4909a97b4bc7444e09f54ee1dcf31b Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Fri, 27 Jul 2018 13:37:16 +0200 Subject: [PATCH] Can disable method of payments --- BTCPayServer/Controllers/InvoiceController.cs | 6 +- .../Controllers/StoresController.BTCLike.cs | 7 +- .../StoresController.LightningLike.cs | 61 ++++++++------- BTCPayServer/Controllers/StoresController.cs | 10 ++- BTCPayServer/Data/StoreData.cs | 35 ++++++++- .../DerivationSchemeViewModel.cs | 1 + .../StoreViewModels/LightningNodeViewModel.cs | 1 + .../Models/StoreViewModels/StoreViewModel.cs | 2 + BTCPayServer/Payments/IPaymentFilter.cs | 74 +++++++++++++++++++ .../Views/Stores/AddDerivationScheme.cshtml | 12 ++- .../Views/Stores/AddLightningNode.cshtml | 7 +- BTCPayServer/Views/Stores/UpdateStore.cshtml | 11 +++ 12 files changed, 185 insertions(+), 42 deletions(-) create mode 100644 BTCPayServer/Payments/IPaymentFilter.cs diff --git a/BTCPayServer/Controllers/InvoiceController.cs b/BTCPayServer/Controllers/InvoiceController.cs index 379cd4590..1b8932914 100644 --- a/BTCPayServer/Controllers/InvoiceController.cs +++ b/BTCPayServer/Controllers/InvoiceController.cs @@ -123,9 +123,10 @@ namespace BTCPayServer.Controllers HashSet currencyPairsToFetch = new HashSet(); var rules = storeBlob.GetRateRules(_NetworkProvider); - + var excludeFilter = storeBlob.GetExcludedPaymentMethods(); // Here we can compose filters from other origin with PaymentFilter.Any() foreach (var network in store.GetSupportedPaymentMethods(_NetworkProvider) - .Select(c => _NetworkProvider.GetNetwork(c.PaymentId.CryptoCode)) + .Where(s => !excludeFilter.Match(s.PaymentId)) + .Select(c => _NetworkProvider.GetNetwork(c.PaymentId.CryptoCode)) .Where(c => c != null)) { currencyPairsToFetch.Add(new CurrencyPair(network.CryptoCode, invoice.Currency)); @@ -140,6 +141,7 @@ namespace BTCPayServer.Controllers var fetchingAll = WhenAllFetched(logs, fetchingByCurrencyPair); var supportedPaymentMethods = store.GetSupportedPaymentMethods(_NetworkProvider) + .Where(s => !excludeFilter.Match(s.PaymentId)) .Select(c => (Handler: (IPaymentMethodHandler)_ServiceProvider.GetService(typeof(IPaymentMethodHandler<>).MakeGenericType(c.GetType())), SupportedPaymentMethod: c, diff --git a/BTCPayServer/Controllers/StoresController.BTCLike.cs b/BTCPayServer/Controllers/StoresController.BTCLike.cs index 62d16df2e..cc0c3cc91 100644 --- a/BTCPayServer/Controllers/StoresController.BTCLike.cs +++ b/BTCPayServer/Controllers/StoresController.BTCLike.cs @@ -44,6 +44,7 @@ namespace BTCPayServer.Controllers private void SetExistingValues(StoreData store, DerivationSchemeViewModel vm) { vm.DerivationScheme = GetExistingDerivationStrategy(vm.CryptoCode, store)?.DerivationStrategyBase.ToString(); + vm.Enabled = !store.GetStoreBlob().IsExcluded(new PaymentMethodId(vm.CryptoCode, PaymentTypes.BTCLike)); } private DerivationStrategy GetExistingDerivationStrategy(string cryptoCode, StoreData store) @@ -93,10 +94,8 @@ namespace BTCPayServer.Controllers vm.Confirmation = false; return View(vm); } - if (!vm.Confirmation && strategy != null) return ShowAddresses(vm, strategy); - if (vm.Confirmation && !string.IsNullOrWhiteSpace(vm.HintAddress)) { BitcoinAddress address = null; @@ -132,6 +131,10 @@ namespace BTCPayServer.Controllers if (strategy != null) await wallet.TrackAsync(strategy.DerivationStrategyBase); store.SetSupportedPaymentMethod(paymentMethodId, strategy); + + var storeBlob = store.GetStoreBlob(); + storeBlob.SetExcluded(paymentMethodId, !vm.Enabled); + store.SetStoreBlob(storeBlob); } catch { diff --git a/BTCPayServer/Controllers/StoresController.LightningLike.cs b/BTCPayServer/Controllers/StoresController.LightningLike.cs index 79e46ad91..6aafb1aec 100644 --- a/BTCPayServer/Controllers/StoresController.LightningLike.cs +++ b/BTCPayServer/Controllers/StoresController.LightningLike.cs @@ -24,9 +24,11 @@ namespace BTCPayServer.Controllers var store = HttpContext.GetStoreData(); if (store == null) return NotFound(); - LightningNodeViewModel vm = new LightningNodeViewModel(); - vm.CryptoCode = cryptoCode; - vm.InternalLightningNode = GetInternalLighningNode(cryptoCode)?.ToString(); + LightningNodeViewModel vm = new LightningNodeViewModel + { + CryptoCode = cryptoCode, + InternalLightningNode = GetInternalLighningNode(cryptoCode)?.ToString() + }; SetExistingValues(store, vm); return View(vm); } @@ -34,6 +36,7 @@ namespace BTCPayServer.Controllers private void SetExistingValues(StoreData store, LightningNodeViewModel vm) { vm.ConnectionString = GetExistingLightningSupportedPaymentMethod(vm.CryptoCode, store)?.GetLightningUrl()?.ToString(); + vm.Enabled = !store.GetStoreBlob().IsExcluded(new PaymentMethodId(vm.CryptoCode, PaymentTypes.LightningLike)); } private LightningSupportedPaymentMethod GetExistingLightningSupportedPaymentMethod(string cryptoCode, StoreData store) { @@ -132,41 +135,43 @@ namespace BTCPayServer.Controllers CryptoCode = paymentMethodId.CryptoCode }; paymentMethod.SetLightningUrl(connectionString); + var storeBlob = store.GetStoreBlob(); + storeBlob.SetExcluded(paymentMethod.PaymentId , vm.Enabled); + store.SetStoreBlob(storeBlob); } - if (command == "save") + switch (command) { - store.SetSupportedPaymentMethod(paymentMethodId, paymentMethod); - await _Repo.UpdateStore(store); - StatusMessage = $"Lightning node modified ({network.CryptoCode})"; - return RedirectToAction(nameof(UpdateStore), new { storeId = storeId }); - } - else // if(command == "test") - { - if (paymentMethod == null) - { + case "save": + store.SetSupportedPaymentMethod(paymentMethodId, paymentMethod); + await _Repo.UpdateStore(store); + StatusMessage = $"Lightning node modified ({network.CryptoCode})"; + return RedirectToAction(nameof(UpdateStore), new { storeId = storeId }); + case "test" when paymentMethod == null: ModelState.AddModelError(nameof(vm.ConnectionString), "Missing url parameter"); return View(vm); - } - var handler = (LightningLikePaymentHandler)_ServiceProvider.GetRequiredService>(); - try - { - var info = await handler.Test(paymentMethod, network); - if (!vm.SkipPortTest) + case "test": + var handler = (LightningLikePaymentHandler)_ServiceProvider.GetRequiredService>(); + try { - using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(20))) + var info = await handler.Test(paymentMethod, network); + if (!vm.SkipPortTest) { - await handler.TestConnection(info, cts.Token); + using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(20))) + { + await handler.TestConnection(info, cts.Token); + } } + vm.StatusMessage = $"Connection to the lightning node succeeded ({info})"; + } + catch (Exception ex) + { + vm.StatusMessage = $"Error: {ex.Message}"; + return View(vm); } - vm.StatusMessage = $"Connection to the lightning node succeeded ({info})"; - } - catch (Exception ex) - { - vm.StatusMessage = $"Error: {ex.Message}"; return View(vm); - } - return View(vm); + default: + return View(vm); } } diff --git a/BTCPayServer/Controllers/StoresController.cs b/BTCPayServer/Controllers/StoresController.cs index 8ae212e46..0f223608d 100644 --- a/BTCPayServer/Controllers/StoresController.cs +++ b/BTCPayServer/Controllers/StoresController.cs @@ -404,7 +404,7 @@ namespace BTCPayServer.Controllers vm.NetworkFee = !storeBlob.NetworkFeeDisabled; vm.SpeedPolicy = store.SpeedPolicy; vm.CanDelete = _Repo.CanDeleteStores(); - AddPaymentMethods(store, vm); + AddPaymentMethods(store, storeBlob, vm); vm.MonitoringExpiration = storeBlob.MonitoringExpiration; vm.InvoiceExpiration = storeBlob.InvoiceExpiration; vm.LightningDescriptionTemplate = storeBlob.LightningDescriptionTemplate; @@ -413,8 +413,9 @@ namespace BTCPayServer.Controllers } - private void AddPaymentMethods(StoreData store, StoreViewModel vm) + private void AddPaymentMethods(StoreData store, StoreBlob storeBlob, StoreViewModel vm) { + var excludeFilters = storeBlob.GetExcludedPaymentMethods(); var derivationByCryptoCode = store .GetSupportedPaymentMethods(_NetworkProvider) @@ -428,6 +429,7 @@ namespace BTCPayServer.Controllers Crypto = network.CryptoCode, Value = strategy?.DerivationStrategyBase?.ToString() ?? string.Empty, WalletId = new WalletId(store.Id, network.CryptoCode), + Enabled = !excludeFilters.Match(new Payments.PaymentMethodId(network.CryptoCode, Payments.PaymentTypes.BTCLike)) }); } @@ -439,10 +441,12 @@ namespace BTCPayServer.Controllers foreach (var network in _NetworkProvider.GetAll()) { var lightning = lightningByCryptoCode.TryGet(network.CryptoCode); + var paymentId = new Payments.PaymentMethodId(network.CryptoCode, Payments.PaymentTypes.LightningLike); vm.LightningNodes.Add(new StoreViewModel.LightningNode() { CryptoCode = network.CryptoCode, - Address = lightning?.GetLightningUrl()?.BaseUri.AbsoluteUri ?? string.Empty + Address = lightning?.GetLightningUrl()?.BaseUri.AbsoluteUri ?? string.Empty, + Enabled = !excludeFilters.Match(paymentId) }); } } diff --git a/BTCPayServer/Data/StoreData.cs b/BTCPayServer/Data/StoreData.cs index 5fcb772ac..60fa59658 100644 --- a/BTCPayServer/Data/StoreData.cs +++ b/BTCPayServer/Data/StoreData.cs @@ -199,7 +199,7 @@ namespace BTCPayServer.Data #pragma warning disable CS0618 public string GetDefaultCrypto(BTCPayNetworkProvider networkProvider = null) { - return DefaultCrypto ?? (networkProvider == null? "BTC" : GetSupportedPaymentMethods(networkProvider).First().PaymentId.CryptoCode); + return DefaultCrypto ?? (networkProvider == null ? "BTC" : GetSupportedPaymentMethods(networkProvider).First().PaymentId.CryptoCode); } public void SetDefaultCrypto(string defaultCryptoCurrency) { @@ -336,8 +336,8 @@ namespace BTCPayServer.Data public BTCPayServer.Rating.RateRules GetRateRules(BTCPayNetworkProvider networkProvider) { - if (!RateScripting || - string.IsNullOrEmpty(RateScript) || + if (!RateScripting || + string.IsNullOrEmpty(RateScript) || !BTCPayServer.Rating.RateRules.TryParse(RateScript, out var rules)) { return GetDefaultRateRules(networkProvider); @@ -373,5 +373,34 @@ namespace BTCPayServer.Data rules.GlobalMultiplier = GetRateMultiplier(); return rules; } + + [Obsolete("Use GetExcludedPaymentMethods instead")] + public string[] ExcludedPaymentMethods { get; set; } + + public IPaymentFilter GetExcludedPaymentMethods() + { +#pragma warning disable CS0618 // Type or member is obsolete + if (ExcludedPaymentMethods == null || ExcludedPaymentMethods.Length == 0) + return PaymentFilter.Never(); + return PaymentFilter.Any(ExcludedPaymentMethods.Select(p => PaymentFilter.WhereIs(PaymentMethodId.Parse(p))).ToArray()); +#pragma warning restore CS0618 // Type or member is obsolete + } + + public bool IsExcluded(PaymentMethodId paymentMethodId) + { + return GetExcludedPaymentMethods().Match(paymentMethodId); + } + + public void SetExcluded(PaymentMethodId paymentMethodId, bool value) + { +#pragma warning disable CS0618 // Type or member is obsolete + var methods = new HashSet(ExcludedPaymentMethods ?? Array.Empty()); + if (value) + methods.Add(paymentMethodId.ToString()); + else + methods.Remove(paymentMethodId.ToString()); + ExcludedPaymentMethods = methods.ToArray(); +#pragma warning restore CS0618 // Type or member is obsolete + } } } diff --git a/BTCPayServer/Models/StoreViewModels/DerivationSchemeViewModel.cs b/BTCPayServer/Models/StoreViewModels/DerivationSchemeViewModel.cs index 7e7d844ed..aee99dcd4 100644 --- a/BTCPayServer/Models/StoreViewModels/DerivationSchemeViewModel.cs +++ b/BTCPayServer/Models/StoreViewModels/DerivationSchemeViewModel.cs @@ -27,6 +27,7 @@ namespace BTCPayServer.Models.StoreViewModels [Display(Name = "Hint address")] public string HintAddress { get; set; } public bool Confirmation { get; set; } + public bool Enabled { get; set; } = true; public string ServerUrl { get; set; } public string StatusMessage { get; internal set; } diff --git a/BTCPayServer/Models/StoreViewModels/LightningNodeViewModel.cs b/BTCPayServer/Models/StoreViewModels/LightningNodeViewModel.cs index d9ba80caf..14c380ca4 100644 --- a/BTCPayServer/Models/StoreViewModels/LightningNodeViewModel.cs +++ b/BTCPayServer/Models/StoreViewModels/LightningNodeViewModel.cs @@ -24,5 +24,6 @@ namespace BTCPayServer.Models.StoreViewModels public string StatusMessage { get; set; } public string InternalLightningNode { get; internal set; } public bool SkipPortTest { get; set; } + public bool Enabled { get; set; } = true; } } diff --git a/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs b/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs index 7e676b6f8..1c8e31c0f 100644 --- a/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs +++ b/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs @@ -19,6 +19,7 @@ namespace BTCPayServer.Models.StoreViewModels public string Crypto { get; set; } public string Value { get; set; } public WalletId WalletId { get; set; } + public bool Enabled { get; set; } } public StoreViewModel() @@ -83,6 +84,7 @@ namespace BTCPayServer.Models.StoreViewModels { public string CryptoCode { get; set; } public string Address { get; set; } + public bool Enabled { get; set; } } public List LightningNodes { diff --git a/BTCPayServer/Payments/IPaymentFilter.cs b/BTCPayServer/Payments/IPaymentFilter.cs new file mode 100644 index 000000000..64582b3e5 --- /dev/null +++ b/BTCPayServer/Payments/IPaymentFilter.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace BTCPayServer.Payments +{ + public interface IPaymentFilter + { + bool Match(PaymentMethodId paymentMethodId); + } + + public class PaymentFilter + { + class NeverPaymentFilter : IPaymentFilter + { + + private static readonly NeverPaymentFilter _Instance = new NeverPaymentFilter(); + public static NeverPaymentFilter Instance + { + get + { + return _Instance; + } + } + public bool Match(PaymentMethodId paymentMethodId) + { + return false; + } + } + class CompositePaymentFilter : IPaymentFilter + { + private readonly IPaymentFilter[] _filters; + + public CompositePaymentFilter(IPaymentFilter[] filters) + { + _filters = filters; + } + public bool Match(PaymentMethodId paymentMethodId) + { + return _filters.Any(f => f.Match(paymentMethodId)); + } + } + class PaymentIdFilter : IPaymentFilter + { + private readonly PaymentMethodId _paymentMethodId; + + public PaymentIdFilter(PaymentMethodId paymentMethodId) + { + _paymentMethodId = paymentMethodId; + } + public bool Match(PaymentMethodId paymentMethodId) + { + return paymentMethodId == _paymentMethodId; + } + } + public static IPaymentFilter Never() + { + return NeverPaymentFilter.Instance; + } + public static IPaymentFilter Any(IPaymentFilter[] filters) + { + if (filters == null) + throw new ArgumentNullException(nameof(filters)); + return new CompositePaymentFilter(filters); + } + public static IPaymentFilter WhereIs(PaymentMethodId paymentMethodId) + { + if (paymentMethodId == null) + throw new ArgumentNullException(nameof(paymentMethodId)); + return new PaymentIdFilter(paymentMethodId); + } + } +} diff --git a/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml b/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml index f4ebba884..6c712e2b1 100644 --- a/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml +++ b/BTCPayServer/Views/Stores/AddDerivationScheme.cshtml @@ -1,7 +1,7 @@ @model DerivationSchemeViewModel @{ Layout = "../Shared/_NavLayout.cshtml"; - ViewData["Title"] = "Add derivation scheme"; + ViewData["Title"] = $"{Model.CryptoCode} Derivation scheme"; ViewData.AddActivePage(BTCPayServer.Views.Stores.StoreNavPages.Index); } @@ -77,7 +77,12 @@ - +
+ + + +
+ } else { @@ -87,6 +92,7 @@ +
@@ -116,7 +122,7 @@ - + } diff --git a/BTCPayServer/Views/Stores/AddLightningNode.cshtml b/BTCPayServer/Views/Stores/AddLightningNode.cshtml index a46c87033..f303dbc09 100644 --- a/BTCPayServer/Views/Stores/AddLightningNode.cshtml +++ b/BTCPayServer/Views/Stores/AddLightningNode.cshtml @@ -55,13 +55,18 @@ - @if(Model.InternalLightningNode != null) + @if (Model.InternalLightningNode != null) {

You can use the internal lightning node by clicking here

} +
+ + + +
diff --git a/BTCPayServer/Views/Stores/UpdateStore.cshtml b/BTCPayServer/Views/Stores/UpdateStore.cshtml index 1301a5e00..91b39c1f2 100644 --- a/BTCPayServer/Views/Stores/UpdateStore.cshtml +++ b/BTCPayServer/Views/Stores/UpdateStore.cshtml @@ -70,6 +70,7 @@ + @@ -79,6 +80,12 @@ + + @@ -115,6 +123,9 @@ + }
Crypto Derivation SchemeStatus Actions
@scheme.Crypto @scheme.Value + @if (!string.IsNullOrWhiteSpace(scheme.Value)) + { + @(scheme.Enabled ? "Enabled" : "Disabled") + } + @if(!string.IsNullOrWhiteSpace(scheme.Value)) { @@ -106,6 +113,7 @@
Crypto AddressStatus Actions
@scheme.CryptoCode @scheme.Address + @(scheme.Enabled ? "Enabled" : "Disabled") + Modify