mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Apply better messages
This commit is contained in:
@@ -106,7 +106,7 @@ namespace BTCPayServer.Controllers.GreenField
|
||||
PaymentMethodId.TryParse(s, out var pmi);
|
||||
return pmi;
|
||||
}).ToArray();
|
||||
var supported = _payoutHandlers.GetSupportedPaymentMethods().ToArray();
|
||||
var supported = (await _payoutHandlers.GetSupportedPaymentMethods(HttpContext.GetStoreData())).ToArray();
|
||||
for (int i = 0; i < paymentMethods.Length; i++)
|
||||
{
|
||||
if (!supported.Contains(paymentMethods[i]))
|
||||
|
||||
@@ -167,13 +167,15 @@ namespace BTCPayServer.Controllers
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> Refund([FromServices]IEnumerable<IPayoutHandler> payoutHandlers, string invoiceId, CancellationToken cancellationToken)
|
||||
{
|
||||
using var ctx = _dbContextFactory.CreateContext();
|
||||
await using var ctx = _dbContextFactory.CreateContext();
|
||||
ctx.ChangeTracker.QueryTrackingBehavior = Microsoft.EntityFrameworkCore.QueryTrackingBehavior.NoTracking;
|
||||
var invoice = await ctx.Invoices.Include(i => i.Payments)
|
||||
.Include(i => i.CurrentRefund)
|
||||
.Include(i => i.StoreData)
|
||||
.ThenInclude(data => data.UserStores)
|
||||
.Include(i => i.CurrentRefund.PullPaymentData)
|
||||
.Where(i => i.Id == invoiceId)
|
||||
.FirstOrDefaultAsync(cancellationToken: cancellationToken);
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
if (invoice is null)
|
||||
return NotFound();
|
||||
if (invoice.CurrentRefund?.PullPaymentDataId is null && GetUserId() is null)
|
||||
@@ -191,7 +193,17 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
var paymentMethods = invoice.GetBlob(_NetworkProvider).GetPaymentMethods();
|
||||
var pmis = paymentMethods.Select(method => method.GetId()).ToList();
|
||||
var options = payoutHandlers.GetSupportedPaymentMethods(pmis);
|
||||
var options = (await payoutHandlers.GetSupportedPaymentMethods(invoice.StoreData)).Where(id => pmis.Contains(id)).ToList();
|
||||
if (!options.Any())
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Error,
|
||||
Message = "There were no payment methods available to provide refunds with for this invoice."
|
||||
});
|
||||
return RedirectToAction(nameof(Invoice), new { invoiceId });
|
||||
}
|
||||
|
||||
var defaultRefund = invoice.Payments
|
||||
.Select(p => p.GetBlob(_NetworkProvider))
|
||||
.Select(p => p?.GetPaymentMethodId())
|
||||
|
||||
@@ -60,12 +60,12 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
|
||||
[HttpGet("new")]
|
||||
public IActionResult NewPullPayment(string storeId)
|
||||
public async Task<IActionResult> NewPullPayment(string storeId)
|
||||
{
|
||||
if (CurrentStore is null)
|
||||
return NotFound();
|
||||
var storeMethods = CurrentStore.GetSupportedPaymentMethods(_btcPayNetworkProvider).Select(method => method.PaymentId).ToList();
|
||||
var paymentMethodOptions = _payoutHandlers.GetSupportedPaymentMethods(storeMethods);
|
||||
|
||||
var paymentMethodOptions = await _payoutHandlers.GetSupportedPaymentMethods(CurrentStore);
|
||||
return View(new NewPullPaymentModel
|
||||
{
|
||||
Name = "",
|
||||
@@ -82,8 +82,7 @@ namespace BTCPayServer.Controllers
|
||||
if (CurrentStore is null)
|
||||
return NotFound();
|
||||
|
||||
var storeMethods = CurrentStore.GetSupportedPaymentMethods(_btcPayNetworkProvider).Select(method => method.PaymentId).ToList();
|
||||
var paymentMethodOptions = _payoutHandlers.GetSupportedPaymentMethods(storeMethods);
|
||||
var paymentMethodOptions = await _payoutHandlers.GetSupportedPaymentMethods(CurrentStore);
|
||||
model.PaymentMethodItems =
|
||||
paymentMethodOptions.Select(id => new SelectListItem(id.ToPrettyString(), id.ToString(), true));
|
||||
model.Name ??= string.Empty;
|
||||
@@ -230,6 +229,8 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
if (vm is null)
|
||||
return NotFound();
|
||||
|
||||
vm.PaymentMethods = await _payoutHandlers.GetSupportedPaymentMethods(HttpContext.GetStoreData());
|
||||
var paymentMethodId = PaymentMethodId.Parse(vm.PaymentMethodId);
|
||||
var handler = _payoutHandlers
|
||||
.FindPayoutHandler(paymentMethodId);
|
||||
@@ -404,9 +405,11 @@ namespace BTCPayServer.Controllers
|
||||
string storeId, string pullPaymentId, string paymentMethodId, PayoutState payoutState,
|
||||
int skip = 0, int count = 50)
|
||||
{
|
||||
var paymentMethods = await _payoutHandlers.GetSupportedPaymentMethods(HttpContext.GetStoreData());
|
||||
var vm = this.ParseListQuery(new PayoutsModel
|
||||
{
|
||||
PaymentMethodId = paymentMethodId?? _payoutHandlers.GetSupportedPaymentMethods().First().ToString(),
|
||||
PaymentMethods = paymentMethods,
|
||||
PaymentMethodId = paymentMethodId??paymentMethods.First().ToString(),
|
||||
PullPaymentId = pullPaymentId,
|
||||
PayoutState = payoutState,
|
||||
Skip = skip,
|
||||
|
||||
@@ -25,6 +25,7 @@ using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NewBlockEvent = BTCPayServer.Events.NewBlockEvent;
|
||||
using PayoutData = BTCPayServer.Data.PayoutData;
|
||||
using StoreData = BTCPayServer.Data.StoreData;
|
||||
|
||||
public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
{
|
||||
@@ -215,11 +216,10 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<PaymentMethodId> GetSupportedPaymentMethods()
|
||||
public Task<IEnumerable<PaymentMethodId>> GetSupportedPaymentMethods(StoreData storeData)
|
||||
{
|
||||
return _btcPayNetworkProvider.GetAll().OfType<BTCPayNetwork>()
|
||||
.Where(network => network.ReadonlyWallet is false)
|
||||
.Select(network => new PaymentMethodId(network.CryptoCode, BitcoinPaymentType.Instance));
|
||||
return Task.FromResult(storeData.GetEnabledPaymentIds(_btcPayNetworkProvider)
|
||||
.Where(id => id.PaymentType == BitcoinPaymentType.Instance));
|
||||
}
|
||||
|
||||
public async Task<IActionResult> InitiatePayment(PaymentMethodId paymentMethodId ,string[] payoutIds)
|
||||
|
||||
@@ -7,6 +7,7 @@ using BTCPayServer.Data;
|
||||
using BTCPayServer.Payments;
|
||||
using PayoutData = BTCPayServer.Data.PayoutData;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using StoreData = BTCPayServer.Data.StoreData;
|
||||
|
||||
public interface IPayoutHandler
|
||||
{
|
||||
@@ -22,6 +23,6 @@ public interface IPayoutHandler
|
||||
Task<decimal> GetMinimumPayoutAmount(PaymentMethodId paymentMethod, IClaimDestination claimDestination);
|
||||
Dictionary<PayoutState, List<(string Action, string Text)>> GetPayoutSpecificActions();
|
||||
Task<StatusMessageModel> DoSpecificAction(string action, string[] payoutIds, string storeId);
|
||||
IEnumerable<PaymentMethodId> GetSupportedPaymentMethods();
|
||||
Task<IEnumerable<PaymentMethodId>> GetSupportedPaymentMethods(StoreData storeData);
|
||||
Task<IActionResult> InitiatePayment(PaymentMethodId paymentMethodId, string[] payoutIds);
|
||||
}
|
||||
|
||||
@@ -4,11 +4,13 @@ using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Services;
|
||||
using LNURL;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -30,6 +32,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly LightningClientFactoryService _lightningClientFactoryService;
|
||||
private readonly IOptions<LightningNetworkOptions> _options;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
|
||||
public LightningLikePayoutController(ApplicationDbContextFactory applicationDbContextFactory,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
@@ -37,7 +40,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
IEnumerable<IPayoutHandler> payoutHandlers,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
LightningClientFactoryService lightningClientFactoryService,
|
||||
IOptions<LightningNetworkOptions> options)
|
||||
IOptions<LightningNetworkOptions> options, IAuthorizationService authorizationService)
|
||||
{
|
||||
_applicationDbContextFactory = applicationDbContextFactory;
|
||||
_userManager = userManager;
|
||||
@@ -46,6 +49,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_lightningClientFactoryService = lightningClientFactoryService;
|
||||
_options = options;
|
||||
_authorizationService = authorizationService;
|
||||
}
|
||||
|
||||
private async Task<List<PayoutData>> GetPayouts(ApplicationDbContext dbContext, PaymentMethodId pmi,
|
||||
@@ -145,12 +149,34 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
}
|
||||
}
|
||||
|
||||
var authorizedForInternalNode = (await _authorizationService.AuthorizeAsync(User, null, new PolicyRequirement(Policies.CanModifyServerSettings))).Succeeded;
|
||||
foreach (var payoutDatas in payouts)
|
||||
{
|
||||
var store = payoutDatas.First().PullPaymentData.StoreData;
|
||||
|
||||
var lightningSupportedPaymentMethod = store.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(method => method.PaymentId == pmi);
|
||||
|
||||
if (lightningSupportedPaymentMethod.IsInternalNode && !authorizedForInternalNode)
|
||||
{
|
||||
foreach (PayoutData payoutData in payoutDatas)
|
||||
{
|
||||
|
||||
var blob = payoutData.GetBlob(_btcPayNetworkJsonSerializerSettings);
|
||||
results.Add(new ResultVM()
|
||||
{
|
||||
PayoutId = payoutData.Id,
|
||||
Result = PayResult.Error,
|
||||
Destination = blob.Destination,
|
||||
Message =
|
||||
$"You are currently using the internal lightning node for this payout's store but you are not a server admin."
|
||||
});
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var client =
|
||||
lightningSupportedPaymentMethod.CreateLightningClient(network, _options.Value,
|
||||
_lightningClientFactoryService);
|
||||
|
||||
@@ -7,8 +7,11 @@ using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Validation;
|
||||
using LNURL;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NBitcoin;
|
||||
|
||||
@@ -24,12 +27,16 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly UserService _userService;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
|
||||
public LightningLikePayoutHandler(BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
IHttpClientFactory httpClientFactory)
|
||||
IHttpClientFactory httpClientFactory, UserService userService, IAuthorizationService authorizationService)
|
||||
{
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_userService = userService;
|
||||
_authorizationService = authorizationService;
|
||||
}
|
||||
|
||||
public bool CanHandle(PaymentMethodId paymentMethod)
|
||||
@@ -129,10 +136,28 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
return Task.FromResult<StatusMessageModel>(null);
|
||||
}
|
||||
|
||||
public IEnumerable<PaymentMethodId> GetSupportedPaymentMethods()
|
||||
public async Task<IEnumerable<PaymentMethodId>> GetSupportedPaymentMethods(StoreData storeData)
|
||||
{
|
||||
return _btcPayNetworkProvider.GetAll().OfType<BTCPayNetwork>().Where(network => network.SupportLightning)
|
||||
.Select(network => new PaymentMethodId(network.CryptoCode, LightningPaymentType.Instance));
|
||||
var result = new List<PaymentMethodId>();
|
||||
var methods = storeData.GetEnabledPaymentMethods(_btcPayNetworkProvider).Where(id => id.PaymentId.PaymentType == LightningPaymentType.Instance).OfType<LightningSupportedPaymentMethod>();
|
||||
foreach (LightningSupportedPaymentMethod supportedPaymentMethod in methods)
|
||||
{
|
||||
if (!supportedPaymentMethod.IsInternalNode)
|
||||
{
|
||||
result.Add(supportedPaymentMethod.PaymentId);
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (UserStore storeDataUserStore in storeData.UserStores)
|
||||
{
|
||||
if (!await _userService.IsAdminUser(storeDataUserStore.ApplicationUserId)) continue;
|
||||
result.Add(supportedPaymentMethod.PaymentId);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Task<IActionResult> InitiatePayment(PaymentMethodId paymentMethodId, string[] payoutIds)
|
||||
|
||||
@@ -52,13 +52,11 @@ namespace BTCPayServer.Data
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<PaymentMethodId> GetSupportedPaymentMethods(
|
||||
this IEnumerable<IPayoutHandler> payoutHandlers, List<PaymentMethodId> paymentMethodIds = null)
|
||||
public static async Task<List<PaymentMethodId>> GetSupportedPaymentMethods(
|
||||
this IEnumerable<IPayoutHandler> payoutHandlers, StoreData storeData)
|
||||
{
|
||||
return payoutHandlers.SelectMany(handler => handler.GetSupportedPaymentMethods())
|
||||
.Where(id => paymentMethodIds is null || paymentMethodIds.Contains(id) ||
|
||||
//TODO: Handle this condition in a cleaner way
|
||||
(id.PaymentType == LightningPaymentType.Instance && paymentMethodIds.Contains(new PaymentMethodId(id.CryptoCode, PaymentTypes.LNURLPay))));
|
||||
return (await Task.WhenAll(payoutHandlers.Select(handler => handler.GetSupportedPaymentMethods(storeData)))).SelectMany(ids => ids).ToList();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,14 +20,18 @@ namespace BTCPayServer.Data
|
||||
}
|
||||
|
||||
public static PaymentMethodId[] GetEnabledPaymentIds(this StoreData storeData, BTCPayNetworkProvider networks)
|
||||
{
|
||||
return GetEnabledPaymentMethods(storeData, networks).Select(method => method.PaymentId).ToArray();
|
||||
}
|
||||
|
||||
public static ISupportedPaymentMethod[] GetEnabledPaymentMethods(this StoreData storeData, BTCPayNetworkProvider networks)
|
||||
{
|
||||
var excludeFilter = storeData.GetStoreBlob().GetExcludedPaymentMethods();
|
||||
var paymentMethodIds = storeData.GetSupportedPaymentMethods(networks)
|
||||
.Select(p => p.PaymentId)
|
||||
.Where(a => !excludeFilter.Match(a))
|
||||
.OrderByDescending(a => a.CryptoCode == "BTC")
|
||||
.ThenBy(a => a.CryptoCode)
|
||||
.ThenBy(a => a.PaymentType == PaymentTypes.LightningLike ? 1 : 0)
|
||||
.Where(a => !excludeFilter.Match(a.PaymentId))
|
||||
.OrderByDescending(a => a.PaymentId.CryptoCode == "BTC")
|
||||
.ThenBy(a => a.PaymentId.CryptoCode)
|
||||
.ThenBy(a => a.PaymentId.PaymentType == PaymentTypes.LightningLike ? 1 : 0)
|
||||
.ToArray();
|
||||
return paymentMethodIds;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace BTCPayServer.Models.WalletViewModels
|
||||
public string PaymentMethodId { get; set; }
|
||||
|
||||
public List<PayoutModel> Payouts { get; set; }
|
||||
public IEnumerable<PaymentMethodId> PaymentMethods { get; set; }
|
||||
public PayoutState PayoutState { get; set; }
|
||||
public string PullPaymentName { get; set; }
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@ namespace BTCPayServer.Services.Stores
|
||||
{
|
||||
if (userId == null)
|
||||
throw new ArgumentNullException(nameof(userId));
|
||||
using (var ctx = _ContextFactory.CreateContext())
|
||||
{
|
||||
await using var ctx = _ContextFactory.CreateContext();
|
||||
return (await ctx
|
||||
.UserStore
|
||||
.Where(us => us.ApplicationUserId == userId && us.StoreDataId == storeId)
|
||||
.Include(store => store.StoreData.UserStores)
|
||||
.Select(us => new
|
||||
{
|
||||
Store = us.StoreData,
|
||||
@@ -53,7 +53,6 @@ namespace BTCPayServer.Services.Stores
|
||||
return us.Store;
|
||||
}).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public class StoreUser
|
||||
{
|
||||
|
||||
@@ -34,6 +34,11 @@ namespace BTCPayServer.Services
|
||||
_storeRepository = storeRepository;
|
||||
}
|
||||
|
||||
public async Task<bool> IsAdminUser(string userId)
|
||||
{
|
||||
return IsRoleAdmin(await _userManager.GetRolesAsync(new ApplicationUser(){Id = userId}));
|
||||
}
|
||||
|
||||
public async Task<bool> IsAdminUser(ApplicationUser user)
|
||||
{
|
||||
return IsRoleAdmin(await _userManager.GetRolesAsync(user));
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
ViewData["NavPartialName"] = "../Stores/_Nav";
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Payouts, $"Manage payouts{(string.IsNullOrEmpty(Model.PullPaymentName) ? string.Empty : " for pull payment " + Model.PullPaymentName)}", Context.GetStoreData().StoreName);
|
||||
|
||||
var paymentMethods = PayoutHandlers.GetSupportedPaymentMethods();
|
||||
|
||||
var stateActions = new List<(string Action, string Text)>();
|
||||
if (PaymentMethodId.TryParse(Model.PaymentMethodId, out var paymentMethodId))
|
||||
{
|
||||
@@ -56,7 +54,7 @@
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<ul class="nav nav-pills bg-tile mb-2" style="border-radius:4px; border: 1px solid var(--btcpay-body-border-medium)">
|
||||
@foreach (var state in paymentMethods)
|
||||
@foreach (var state in Model.PaymentMethods)
|
||||
{
|
||||
<li class="nav-item py-0">
|
||||
<a asp-action="Payouts" asp-route-storeId="@Context.GetRouteValue("storeId")"
|
||||
|
||||
Reference in New Issue
Block a user