mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Allow pull payments for store guests (#3128)
This commit is contained in:
parent
e113c12768
commit
fd75008499
7 changed files with 92 additions and 29 deletions
|
@ -26,7 +26,7 @@ using StoreData = BTCPayServer.Data.StoreData;
|
|||
namespace BTCPayServer.Controllers
|
||||
{
|
||||
[Route("stores/{storeId}/pull-payments")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
[AutoValidateAntiforgeryToken]
|
||||
public class StorePullPaymentsController: Controller
|
||||
{
|
||||
|
@ -60,6 +60,7 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
[HttpGet("new")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
public async Task<IActionResult> NewPullPayment(string storeId)
|
||||
{
|
||||
if (CurrentStore is null)
|
||||
|
@ -86,6 +87,7 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
[HttpPost("new")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
public async Task<IActionResult> NewPullPayment(string storeId, NewPullPaymentModel model)
|
||||
{
|
||||
if (CurrentStore is null)
|
||||
|
@ -217,6 +219,7 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
[HttpGet("{pullPaymentId}/archive")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
public IActionResult ArchivePullPayment(string storeId,
|
||||
string pullPaymentId)
|
||||
{
|
||||
|
@ -224,6 +227,7 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
[HttpPost("{pullPaymentId}/archive")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
public async Task<IActionResult> ArchivePullPaymentPost(string storeId,
|
||||
string pullPaymentId)
|
||||
{
|
||||
|
@ -236,6 +240,7 @@ namespace BTCPayServer.Controllers
|
|||
return RedirectToAction(nameof(PullPayments), new { storeId = storeId });
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
[HttpPost("payouts")]
|
||||
public async Task<IActionResult> PayoutsPost(
|
||||
string storeId, PayoutsModel vm, CancellationToken cancellationToken)
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace BTCPayServer.Security
|
|||
return;
|
||||
}
|
||||
|
||||
string storeId = _HttpContext.GetImplicitStoreId();
|
||||
string storeId = context.Resource is string s? s :_HttpContext.GetImplicitStoreId();
|
||||
if (storeId == null)
|
||||
return;
|
||||
|
||||
|
@ -47,20 +47,20 @@ namespace BTCPayServer.Security
|
|||
|
||||
|
||||
var store = await _storeRepository.FindStore(storeId, userid);
|
||||
if (store == null)
|
||||
return;
|
||||
|
||||
bool success = false;
|
||||
switch (requirement.Policy)
|
||||
{
|
||||
case Policies.CanModifyStoreSettings:
|
||||
if (store.Role == StoreRoles.Owner || isAdmin)
|
||||
if (store != null && (store.Role == StoreRoles.Owner || isAdmin))
|
||||
success = true;
|
||||
break;
|
||||
case Policies.CanViewStoreSettings:
|
||||
if (store != null || isAdmin)
|
||||
success = true;
|
||||
break;
|
||||
case Policies.CanCreateInvoice:
|
||||
if (store.Role == StoreRoles.Owner ||
|
||||
store.Role == StoreRoles.Guest ||
|
||||
isAdmin ||
|
||||
store.GetStoreBlob().AnyoneCanInvoice)
|
||||
if (store != null || isAdmin)
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
|
51
BTCPayServer/Security/PermissionTagHelper.cs
Normal file
51
BTCPayServer/Security/PermissionTagHelper.cs
Normal file
|
@ -0,0 +1,51 @@
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BTCPayServer.Security
|
||||
{
|
||||
[HtmlTargetElement(Attributes = nameof(Permission))]
|
||||
public class PermissionTagHelper : TagHelper
|
||||
{
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly ILogger<PermissionTagHelper> _logger;
|
||||
|
||||
public PermissionTagHelper(IAuthorizationService authorizationService, IHttpContextAccessor httpContextAccessor, ILogger<PermissionTagHelper> logger)
|
||||
{
|
||||
_authorizationService = authorizationService;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string Permission { get; set; }
|
||||
public string PermissionResource { get; set; }
|
||||
|
||||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Permission))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var key = $"{Permission}_{PermissionResource}";
|
||||
if (!_httpContextAccessor.HttpContext.Items.TryGetValue(key,out var cachedResult))
|
||||
{
|
||||
var result = await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User,
|
||||
PermissionResource,
|
||||
Permission);
|
||||
|
||||
cachedResult = result;
|
||||
_httpContextAccessor.HttpContext.Items.Add(key, result);
|
||||
|
||||
}
|
||||
if (!((AuthorizationResult)cachedResult).Succeeded)
|
||||
{
|
||||
output.SuppressOutput();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
@using BTCPayServer.Payments
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Client
|
||||
@model BTCPayServer.Models.WalletViewModels.PayoutsModel
|
||||
|
||||
@inject IEnumerable<IPayoutHandler> PayoutHandlers;
|
||||
|
@ -88,9 +89,9 @@
|
|||
</ul>
|
||||
|
||||
</div>
|
||||
@if (Model.Payouts.Any() && stateActions.Any())
|
||||
@if (Model.Payouts.Any() && stateActions.Any() )
|
||||
{
|
||||
<div class="col-12">
|
||||
<div class="col-12" permission="@Policies.CanModifyStoreSettings" >
|
||||
<div class="dropdown mt-4 ms-xl-auto mt-xl-0">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" id="@Model.PayoutState-actions">
|
||||
Actions
|
||||
|
@ -114,7 +115,7 @@
|
|||
<table class="table table-hover table-responsive-lg">
|
||||
<thead class="thead-inverse">
|
||||
<tr>
|
||||
<th>
|
||||
<th permission="@Policies.CanModifyStoreSettings" >
|
||||
<input id="@Model.PayoutState-selectAllCheckbox" type="checkbox" class="form-check-input selectAll" data-payout-state="@Model.PayoutState.ToString()" />
|
||||
</th>
|
||||
<th style="min-width: 90px;" class="col-md-auto">
|
||||
|
@ -134,7 +135,7 @@
|
|||
{
|
||||
var pp = Model.Payouts[i];
|
||||
<tr class="payout">
|
||||
<td>
|
||||
<td permission="@Policies.CanModifyStoreSettings" >
|
||||
<span>
|
||||
<input type="checkbox" class="selection-item-@Model.PayoutState.ToString() form-check-input" asp-for="Payouts[i].Selected"/>
|
||||
<input type="hidden" asp-for="Payouts[i].PayoutId"/>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Client
|
||||
@model BTCPayServer.Models.WalletViewModels.PullPaymentsModel
|
||||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
|
@ -44,7 +45,7 @@
|
|||
</a>
|
||||
</small>
|
||||
</h4>
|
||||
<a asp-action="NewPullPayment" asp-route-storeId="@Context.GetRouteValue("storeId")" class="btn btn-primary" role="button" id="NewPullPayment">
|
||||
<a permission="@Policies.CanModifyStoreSettings" asp-action="NewPullPayment" asp-route-storeId="@Context.GetRouteValue("storeId")" class="btn btn-primary" role="button" id="NewPullPayment">
|
||||
<span class="fa fa-plus"></span> Create a new pull payment
|
||||
</a>
|
||||
</div>
|
||||
|
@ -88,7 +89,7 @@
|
|||
</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Refunded</th>
|
||||
<th scope="col" class="text-end">Actions</th>
|
||||
<th scope="col" class="text-end" >Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -113,12 +114,15 @@
|
|||
asp-route-pullPaymentId="@pp.Id">
|
||||
View
|
||||
</a> -
|
||||
<a class="pp-payout" asp-action="Payouts"
|
||||
<a class="pp-payout"
|
||||
|
||||
asp-action="Payouts"
|
||||
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
||||
asp-route-pullPaymentId="@pp.Id">
|
||||
Payouts
|
||||
</a> -
|
||||
</a>
|
||||
<a asp-action="ArchivePullPayment"
|
||||
permission="@Policies.CanModifyStoreSettings"
|
||||
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
||||
asp-route-pullPaymentId="@pp.Id"
|
||||
data-bs-toggle="modal"
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
@using BTCPayServer.Client
|
||||
<nav id="sideNav" class="nav flex-column mb-4">
|
||||
<a id="Nav-@(nameof(StoreNavPages.PaymentMethods))" class="nav-link @ViewData.IsActivePage(StoreNavPages.PaymentMethods)" asp-controller="Stores" asp-action="PaymentMethods" asp-route-storeId="@Context.GetRouteValue("storeId")">Payment Methods</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.Rates))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Rates)" asp-controller="Stores" asp-action="Rates" asp-route-storeId="@Context.GetRouteValue("storeId")">Rates</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.CheckoutAppearance))" class="nav-link @ViewData.IsActivePage(StoreNavPages.CheckoutAppearance)" asp-controller="Stores" asp-action="CheckoutAppearance" asp-route-storeId="@Context.GetRouteValue("storeId")">Checkout Appearance</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.GeneralSettings))" class="nav-link @ViewData.IsActivePage(StoreNavPages.GeneralSettings)" asp-controller="Stores" asp-action="GeneralSettings" asp-route-storeId="@Context.GetRouteValue("storeId")">General Settings</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.Tokens))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Tokens)" asp-controller="Stores" asp-action="ListTokens" asp-route-storeId="@Context.GetRouteValue("storeId")">Access Tokens</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.Users))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Users)" asp-controller="Stores" asp-action="StoreUsers" asp-route-storeId="@Context.GetRouteValue("storeId")">Users</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.PayButton))" class="nav-link @ViewData.IsActivePage(StoreNavPages.PayButton)" asp-controller="Stores" asp-action="PayButton" asp-route-storeId="@Context.GetRouteValue("storeId")">Pay Button</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.Integrations))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Integrations)" asp-controller="Stores" asp-action="Integrations" asp-route-storeId="@Context.GetRouteValue("storeId")">Integrations</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.Webhooks))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Webhooks)" asp-controller="Stores" asp-action="Webhooks" asp-route-storeId="@Context.GetRouteValue("storeId")">Webhooks</a>
|
||||
<a permission="@Policies.CanModifyStoreSettings" id="Nav-@(nameof(StoreNavPages.PaymentMethods))" class="nav-link @ViewData.IsActivePage(StoreNavPages.PaymentMethods)" asp-controller="Stores" asp-action="PaymentMethods" asp-route-storeId="@Context.GetRouteValue("storeId")">Payment Methods</a>
|
||||
<a permission="@Policies.CanModifyStoreSettings" id="Nav-@(nameof(StoreNavPages.Rates))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Rates)" asp-controller="Stores" asp-action="Rates" asp-route-storeId="@Context.GetRouteValue("storeId")">Rates</a>
|
||||
<a permission="@Policies.CanModifyStoreSettings" id="Nav-@(nameof(StoreNavPages.CheckoutAppearance))" class="nav-link @ViewData.IsActivePage(StoreNavPages.CheckoutAppearance)" asp-controller="Stores" asp-action="CheckoutAppearance" asp-route-storeId="@Context.GetRouteValue("storeId")">Checkout Appearance</a>
|
||||
<a permission="@Policies.CanModifyStoreSettings" id="Nav-@(nameof(StoreNavPages.GeneralSettings))" class="nav-link @ViewData.IsActivePage(StoreNavPages.GeneralSettings)" asp-controller="Stores" asp-action="GeneralSettings" asp-route-storeId="@Context.GetRouteValue("storeId")">General Settings</a>
|
||||
<a permission="@Policies.CanModifyStoreSettings" id="Nav-@(nameof(StoreNavPages.Tokens))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Tokens)" asp-controller="Stores" asp-action="ListTokens" asp-route-storeId="@Context.GetRouteValue("storeId")">Access Tokens</a>
|
||||
<a permission="@Policies.CanModifyStoreSettings" id="Nav-@(nameof(StoreNavPages.Users))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Users)" asp-controller="Stores" asp-action="StoreUsers" asp-route-storeId="@Context.GetRouteValue("storeId")">Users</a>
|
||||
<a permission="@Policies.CanModifyStoreSettings" id="Nav-@(nameof(StoreNavPages.PayButton))" class="nav-link @ViewData.IsActivePage(StoreNavPages.PayButton)" asp-controller="Stores" asp-action="PayButton" asp-route-storeId="@Context.GetRouteValue("storeId")">Pay Button</a>
|
||||
<a permission="@Policies.CanModifyStoreSettings" id="Nav-@(nameof(StoreNavPages.Integrations))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Integrations)" asp-controller="Stores" asp-action="Integrations" asp-route-storeId="@Context.GetRouteValue("storeId")">Integrations</a>
|
||||
<a permission="@Policies.CanModifyStoreSettings" id="Nav-@(nameof(StoreNavPages.Webhooks))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Webhooks)" asp-controller="Stores" asp-action="Webhooks" asp-route-storeId="@Context.GetRouteValue("storeId")">Webhooks</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.PullPayments))" class="nav-link @ViewData.IsActivePage(StoreNavPages.PullPayments)" asp-action="PullPayments" asp-controller="StorePullPayments" asp-route-storeId="@Context.GetRouteValue("storeId")">Pull Payments</a>
|
||||
<a id="Nav-@(nameof(StoreNavPages.Payouts))" class="nav-link @ViewData.IsActivePage(StoreNavPages.Payouts)" asp-action="Payouts" asp-controller="StorePullPayments" asp-route-storeId="@Context.GetRouteValue("storeId")">Payouts</a>
|
||||
<vc:ui-extension-point location="store-nav" model="@Model" />
|
||||
<vc:ui-extension-point location="store-nav" model="@Model"/>
|
||||
</nav>
|
||||
|
|
|
@ -75,9 +75,10 @@
|
|||
@if (store.IsOwner)
|
||||
{
|
||||
<a asp-action="PaymentMethods" asp-controller="Stores" asp-route-storeId="@store.Id" id="update-store-@store.Id">Settings</a><span> - </span>
|
||||
<a asp-action="DeleteStore" asp-controller="Stores" asp-route-storeId="@store.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The store <strong>@store.Name</strong> will be permanently deleted. This action will also delete all invoices, apps and data associated with the store." data-confirm-input="DELETE">Delete</a><span> - </span>
|
||||
}
|
||||
<a asp-action="DeleteStore" asp-controller="Stores" asp-route-storeId="@store.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The store <strong>@store.Name</strong> will be permanently deleted. This action will also delete all invoices, apps and data associated with the store." data-confirm-input="DELETE">Delete</a>
|
||||
</td>
|
||||
<a asp-action="PullPayments" asp-controller="StorePullPayments" asp-route-storeId="@store.Id" >Pull Payments</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
|
Loading…
Add table
Reference in a new issue