mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-09 16:04:43 +01:00
Introduce archive pull payment permission and add Show QR code in view pull payment view (#5274)
* Introduce archive pull payment permission * Add show qr option on pull payments * Fix test * update docs * fix test * Minor UI updates * Update wording --------- Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
This commit is contained in:
parent
eaeb7021d5
commit
33198d693d
11 changed files with 131 additions and 99 deletions
|
@ -33,6 +33,7 @@ namespace BTCPayServer.Client
|
||||||
public const string CanManageUsers = "btcpay.server.canmanageusers";
|
public const string CanManageUsers = "btcpay.server.canmanageusers";
|
||||||
public const string CanDeleteUser = "btcpay.user.candeleteuser";
|
public const string CanDeleteUser = "btcpay.user.candeleteuser";
|
||||||
public const string CanManagePullPayments = "btcpay.store.canmanagepullpayments";
|
public const string CanManagePullPayments = "btcpay.store.canmanagepullpayments";
|
||||||
|
public const string CanArchivePullPayments = "btcpay.store.canarchivepullpayments";
|
||||||
public const string CanCreatePullPayments = "btcpay.store.cancreatepullpayments";
|
public const string CanCreatePullPayments = "btcpay.store.cancreatepullpayments";
|
||||||
public const string CanCreateNonApprovedPullPayments = "btcpay.store.cancreatenonapprovedpullpayments";
|
public const string CanCreateNonApprovedPullPayments = "btcpay.store.cancreatenonapprovedpullpayments";
|
||||||
public const string CanViewCustodianAccounts = "btcpay.store.canviewcustodianaccounts";
|
public const string CanViewCustodianAccounts = "btcpay.store.canviewcustodianaccounts";
|
||||||
|
@ -69,6 +70,7 @@ namespace BTCPayServer.Client
|
||||||
yield return CanViewLightningInvoiceInStore;
|
yield return CanViewLightningInvoiceInStore;
|
||||||
yield return CanCreateLightningInvoiceInStore;
|
yield return CanCreateLightningInvoiceInStore;
|
||||||
yield return CanManagePullPayments;
|
yield return CanManagePullPayments;
|
||||||
|
yield return CanArchivePullPayments;
|
||||||
yield return CanCreatePullPayments;
|
yield return CanCreatePullPayments;
|
||||||
yield return CanCreateNonApprovedPullPayments;
|
yield return CanCreateNonApprovedPullPayments;
|
||||||
yield return CanViewCustodianAccounts;
|
yield return CanViewCustodianAccounts;
|
||||||
|
@ -253,7 +255,7 @@ namespace BTCPayServer.Client
|
||||||
Policies.CanUseLightningNodeInStore);
|
Policies.CanUseLightningNodeInStore);
|
||||||
|
|
||||||
PolicyHasChild(policyMap,Policies.CanManageUsers, Policies.CanCreateUser);
|
PolicyHasChild(policyMap,Policies.CanManageUsers, Policies.CanCreateUser);
|
||||||
PolicyHasChild(policyMap,Policies.CanManagePullPayments, Policies.CanCreatePullPayments);
|
PolicyHasChild(policyMap,Policies.CanManagePullPayments, Policies.CanCreatePullPayments, Policies.CanArchivePullPayments);
|
||||||
PolicyHasChild(policyMap,Policies.CanCreatePullPayments, Policies.CanCreateNonApprovedPullPayments);
|
PolicyHasChild(policyMap,Policies.CanCreatePullPayments, Policies.CanCreateNonApprovedPullPayments);
|
||||||
PolicyHasChild(policyMap,Policies.CanModifyPaymentRequests, Policies.CanViewPaymentRequests);
|
PolicyHasChild(policyMap,Policies.CanModifyPaymentRequests, Policies.CanViewPaymentRequests);
|
||||||
PolicyHasChild(policyMap,Policies.CanModifyProfile, Policies.CanViewProfile);
|
PolicyHasChild(policyMap,Policies.CanModifyProfile, Policies.CanViewProfile);
|
||||||
|
|
|
@ -885,7 +885,7 @@ namespace BTCPayServer.Tests
|
||||||
|
|
||||||
TestLogs.LogInformation("Can't archive without knowing the walletId");
|
TestLogs.LogInformation("Can't archive without knowing the walletId");
|
||||||
var ex = await AssertAPIError("missing-permission", async () => await client.ArchivePullPayment("lol", result.Id));
|
var ex = await AssertAPIError("missing-permission", async () => await client.ArchivePullPayment("lol", result.Id));
|
||||||
Assert.Equal("btcpay.store.canmanagepullpayments", ((GreenfieldPermissionAPIError)ex.APIError).MissingPermission);
|
Assert.Equal("btcpay.store.canarchivepullpayments", ((GreenfieldPermissionAPIError)ex.APIError).MissingPermission);
|
||||||
TestLogs.LogInformation("Can't archive without permission");
|
TestLogs.LogInformation("Can't archive without permission");
|
||||||
await AssertAPIError("unauthenticated", async () => await unauthenticated.ArchivePullPayment(storeId, result.Id));
|
await AssertAPIError("unauthenticated", async () => await unauthenticated.ArchivePullPayment(storeId, result.Id));
|
||||||
await client.ArchivePullPayment(storeId, result.Id);
|
await client.ArchivePullPayment(storeId, result.Id);
|
||||||
|
|
|
@ -38,6 +38,7 @@ using OpenQA.Selenium.Support.Extensions;
|
||||||
using OpenQA.Selenium.Support.UI;
|
using OpenQA.Selenium.Support.UI;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
namespace BTCPayServer.Tests
|
namespace BTCPayServer.Tests
|
||||||
{
|
{
|
||||||
|
@ -926,7 +927,8 @@ namespace BTCPayServer.Tests
|
||||||
Policies.CanModifyStoreSettings,
|
Policies.CanModifyStoreSettings,
|
||||||
Policies.CanCreateNonApprovedPullPayments,
|
Policies.CanCreateNonApprovedPullPayments,
|
||||||
Policies.CanCreatePullPayments,
|
Policies.CanCreatePullPayments,
|
||||||
Policies.CanManagePullPayments
|
Policies.CanManagePullPayments,
|
||||||
|
Policies.CanArchivePullPayments,
|
||||||
});
|
});
|
||||||
AssertPermissions(pageSource, false,
|
AssertPermissions(pageSource, false,
|
||||||
new[]
|
new[]
|
||||||
|
@ -1848,6 +1850,7 @@ namespace BTCPayServer.Tests
|
||||||
TestUtils.Eventually(() =>
|
TestUtils.Eventually(() =>
|
||||||
{
|
{
|
||||||
s.Driver.Navigate().Refresh();
|
s.Driver.Navigate().Refresh();
|
||||||
|
s.Driver.WaitWalletTransactionsLoaded();
|
||||||
Assert.Contains("transaction-label", s.Driver.PageSource);
|
Assert.Contains("transaction-label", s.Driver.PageSource);
|
||||||
var labels = s.Driver.FindElements(By.CssSelector("#WalletTransactionsList tr:first-child div.transaction-label"));
|
var labels = s.Driver.FindElements(By.CssSelector("#WalletTransactionsList tr:first-child div.transaction-label"));
|
||||||
Assert.Equal(2, labels.Count);
|
Assert.Equal(2, labels.Count);
|
||||||
|
@ -2017,10 +2020,7 @@ namespace BTCPayServer.Tests
|
||||||
Assert.Contains(bolt, s.Driver.PageSource);
|
Assert.Contains(bolt, s.Driver.PageSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//auto-approve pull payments
|
//auto-approve pull payments
|
||||||
|
|
||||||
s.GoToStore(StoreNavPages.PullPayments);
|
s.GoToStore(StoreNavPages.PullPayments);
|
||||||
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
|
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
|
||||||
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
||||||
|
@ -2050,6 +2050,8 @@ namespace BTCPayServer.Tests
|
||||||
s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success);
|
s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success);
|
||||||
s.Driver.FindElement(By.LinkText("View")).Click();
|
s.Driver.FindElement(By.LinkText("View")).Click();
|
||||||
s.Driver.FindElement(By.CssSelector("#lnurlwithdraw-button")).Click();
|
s.Driver.FindElement(By.CssSelector("#lnurlwithdraw-button")).Click();
|
||||||
|
s.Driver.WaitForElement(By.Id("qr-code-data-input"));
|
||||||
|
|
||||||
var lnurl = new Uri(LNURL.LNURL.Parse(s.Driver.FindElement(By.Id("qr-code-data-input")).GetAttribute("value"), out _).ToString().Replace("https", "http"));
|
var lnurl = new Uri(LNURL.LNURL.Parse(s.Driver.FindElement(By.Id("qr-code-data-input")).GetAttribute("value"), out _).ToString().Replace("https", "http"));
|
||||||
s.Driver.FindElement(By.CssSelector("button[data-bs-dismiss='modal']")).Click();
|
s.Driver.FindElement(By.CssSelector("button[data-bs-dismiss='modal']")).Click();
|
||||||
var info = Assert.IsType<LNURLWithdrawRequest>(await LNURL.LNURL.FetchInformation(lnurl, s.Server.PayTester.HttpClient));
|
var info = Assert.IsType<LNURLWithdrawRequest>(await LNURL.LNURL.FetchInformation(lnurl, s.Server.PayTester.HttpClient));
|
||||||
|
|
|
@ -442,7 +442,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("~/api/v1/stores/{storeId}/pull-payments/{pullPaymentId}")]
|
[HttpDelete("~/api/v1/stores/{storeId}/pull-payments/{pullPaymentId}")]
|
||||||
[Authorize(Policy = Policies.CanManagePullPayments, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
[Authorize(Policy = Policies.CanArchivePullPayments, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
public async Task<IActionResult> ArchivePullPayment(string storeId, string pullPaymentId)
|
public async Task<IActionResult> ArchivePullPayment(string storeId, string pullPaymentId)
|
||||||
{
|
{
|
||||||
using var ctx = _dbContextFactory.CreateContext();
|
using var ctx = _dbContextFactory.CreateContext();
|
||||||
|
|
|
@ -544,6 +544,8 @@ namespace BTCPayServer.Controllers
|
||||||
{$"{Policies.CanViewPaymentRequests}:", ("View your payment requests", "Allows viewing the selected stores' payment requests.")},
|
{$"{Policies.CanViewPaymentRequests}:", ("View your payment requests", "Allows viewing the selected stores' payment requests.")},
|
||||||
{Policies.CanManagePullPayments, ("Manage your pull payments", "Allows viewing, modifying, deleting and creating pull payments on all your stores.")},
|
{Policies.CanManagePullPayments, ("Manage your pull payments", "Allows viewing, modifying, deleting and creating pull payments on all your stores.")},
|
||||||
{$"{Policies.CanManagePullPayments}:", ("Manage selected stores' pull payments", "Allows viewing, modifying, deleting and creating pull payments on the selected stores.")},
|
{$"{Policies.CanManagePullPayments}:", ("Manage selected stores' pull payments", "Allows viewing, modifying, deleting and creating pull payments on the selected stores.")},
|
||||||
|
{Policies.CanArchivePullPayments, ("Archive your pull payments", "Allows deleting pull payments on all your stores.")},
|
||||||
|
{$"{Policies.CanArchivePullPayments}:", ("Archive selected stores' pull payments", "Allows deleting pull payments on the selected stores.")},
|
||||||
{Policies.CanCreatePullPayments, ("Create pull payments", "Allows creating pull payments on all your stores.")},
|
{Policies.CanCreatePullPayments, ("Create pull payments", "Allows creating pull payments on all your stores.")},
|
||||||
{$"{Policies.CanCreatePullPayments}:", ("Create pull payments in selected stores", "Allows creating pull payments on the selected stores.")},
|
{$"{Policies.CanCreatePullPayments}:", ("Create pull payments in selected stores", "Allows creating pull payments on the selected stores.")},
|
||||||
{Policies.CanCreateNonApprovedPullPayments, ("Create non-approved pull payments", "Allows creating pull payments without automatic approval on all your stores.")},
|
{Policies.CanCreateNonApprovedPullPayments, ("Create non-approved pull payments", "Allows creating pull payments without automatic approval on all your stores.")},
|
||||||
|
|
|
@ -256,7 +256,7 @@ namespace BTCPayServer.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("stores/{storeId}/pull-payments/{pullPaymentId}/archive")]
|
[HttpGet("stores/{storeId}/pull-payments/{pullPaymentId}/archive")]
|
||||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
[Authorize(Policy = Policies.CanArchivePullPayments, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public IActionResult ArchivePullPayment(string storeId,
|
public IActionResult ArchivePullPayment(string storeId,
|
||||||
string pullPaymentId)
|
string pullPaymentId)
|
||||||
{
|
{
|
||||||
|
@ -265,11 +265,11 @@ namespace BTCPayServer.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("stores/{storeId}/pull-payments/{pullPaymentId}/archive")]
|
[HttpPost("stores/{storeId}/pull-payments/{pullPaymentId}/archive")]
|
||||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
[Authorize(Policy = Policies.CanArchivePullPayments, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
public async Task<IActionResult> ArchivePullPaymentPost(string storeId,
|
public async Task<IActionResult> ArchivePullPaymentPost(string storeId,
|
||||||
string pullPaymentId)
|
string pullPaymentId)
|
||||||
{
|
{
|
||||||
await _pullPaymentService.Cancel(new HostedServices.PullPaymentHostedService.CancelRequest(pullPaymentId));
|
await _pullPaymentService.Cancel(new PullPaymentHostedService.CancelRequest(pullPaymentId));
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
Message = "Pull payment archived",
|
Message = "Pull payment archived",
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<vc:icon symbol="copy" />
|
<vc:icon symbol="copy" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="note" v-html="note" class="text-muted mt-3"></p>
|
<div v-if="note" v-html="note" class="text-muted mt-3" id="scan-qr-modal-note"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4 text-center" v-if="continueCallback">
|
<div class="mb-4 text-center" v-if="continueCallback">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" v-on:click="continueCallback()">{{ continueTitle || 'Continue' }}</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" v-on:click="continueCallback()">{{ continueTitle || 'Continue' }}</button>
|
||||||
|
@ -34,6 +34,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<style>
|
||||||
|
#scan-qr-modal-note :last-child { margin-bottom: 0; }
|
||||||
|
</style>
|
||||||
<script>
|
<script>
|
||||||
function initQRShow(data) {
|
function initQRShow(data) {
|
||||||
return new Vue({
|
return new Vue({
|
||||||
|
@ -106,7 +109,10 @@ function initQRShow(data) {
|
||||||
},
|
},
|
||||||
showData(data) {
|
showData(data) {
|
||||||
this.modes = { default: { title: 'Default', fragments: [data] } };
|
this.modes = { default: { title: 'Default', fragments: [data] } };
|
||||||
|
this.mode = "default";
|
||||||
|
this.show();
|
||||||
|
},
|
||||||
|
show(){
|
||||||
$(`#${this.modalId}`).modal("show");
|
$(`#${this.modalId}`).modal("show");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
@if (Model.LnurlEndpoint is not null)
|
@if (Model.LnurlEndpoint is not null)
|
||||||
{
|
{
|
||||||
<button type="button" class="input-group-prepend btn btn-outline-secondary" id="lnurlwithdraw-button" data-bs-toggle="modal" data-bs-target="#scan-qr-modal">
|
<button type="button" class="btn btn-secondary" id="lnurlwithdraw-button">
|
||||||
<span class="fa fa-qrcode fa-2x" title="LNURL-Withdraw"></span>
|
<span class="fa fa-qrcode fa-2x" title="LNURL-Withdraw"></span>
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,6 @@
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
|
|
||||||
<main class="flex-grow-1 py-4">
|
<main class="flex-grow-1 py-4">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<partial name="_StatusMessage" model="@(new ViewDataDictionary(ViewData){ { "Margin", "mb-4" } })" />
|
<partial name="_StatusMessage" model="@(new ViewDataDictionary(ViewData){ { "Margin", "mb-4" } })" />
|
||||||
|
@ -105,6 +104,10 @@
|
||||||
<button type="button" class="btn btn-link fw-semibold d-none d-lg-inline-block d-print-none border-0 p-0 ms-4 only-for-js" id="copyLink">
|
<button type="button" class="btn btn-link fw-semibold d-none d-lg-inline-block d-print-none border-0 p-0 ms-4 only-for-js" id="copyLink">
|
||||||
Copy Link
|
Copy Link
|
||||||
</button>
|
</button>
|
||||||
|
<button type="button" class="btn btn-link fw-semibold d-inline-block d-print-none border-0 p-0 ms-4 only-for-js" page-qr>
|
||||||
|
<span class="fa fa-qrcode"></span> Show QR
|
||||||
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@if (!string.IsNullOrEmpty(Model.ResetIn))
|
@if (!string.IsNullOrEmpty(Model.ResetIn))
|
||||||
{
|
{
|
||||||
|
@ -205,25 +208,41 @@
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
<partial name="LayoutFoot" />
|
<partial name="LayoutFoot" />
|
||||||
|
<script src="~/vendor/vue-qrcode/vue-qrcode.min.js" asp-append-version="true"></script>
|
||||||
|
<script src="~/vendor/vuejs/vue.min.js" asp-append-version="true"></script>
|
||||||
|
<partial name="ShowQR" />
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
window.qrApp = initQRShow({});
|
||||||
|
delegate('click', 'button[page-qr]', event => {
|
||||||
|
qrApp.title = "Pull Payment QR";
|
||||||
|
qrApp.note = "Scan this QR code to open this page on your mobile device.";
|
||||||
|
qrApp.showData(window.location.href);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@if (Model.LnurlEndpoint is not null)
|
@if (Model.LnurlEndpoint is not null)
|
||||||
{
|
{
|
||||||
var lnurlUri = LNURL.LNURL.EncodeUri(Model.LnurlEndpoint, "withdrawRequest", false).ToString();
|
var lnurlUri = LNURL.LNURL.EncodeUri(Model.LnurlEndpoint, "withdrawRequest", false).ToString();
|
||||||
var lnurlBech32 = LNURL.LNURL.EncodeUri(Model.LnurlEndpoint, "withdrawRequest", true).ToString();
|
var lnurlBech32 = LNURL.LNURL.EncodeUri(Model.LnurlEndpoint, "withdrawRequest", true).ToString();
|
||||||
var note = "You can scan or open this link with a <a href='https://github.com/fiatjaf/lnurl-rfc#lnurl-documents' target='_blank' rel='noreferrer noopener'>LNURL-Withdraw</a> enabled wallet.";
|
var note = "<p>You can scan or open this link with a <a href='https://github.com/fiatjaf/lnurl-rfc#lnurl-documents' target='_blank' rel='noreferrer noopener'>LNURL-Withdraw</a> enabled wallet.</p>";
|
||||||
if (!Model.AutoApprove)
|
if (!Model.AutoApprove)
|
||||||
{
|
{
|
||||||
note += "<br/><span class='fw-bold'>Please note that this pull payment does not automatically send out funds, and so will process payment after LNURL-withdraw flow is completed.</span>";
|
note += "<p class='fw-semibold'>Please note that this pull payment does not automatically send out funds, but will process the payment after the LNURL-withdraw flow is completed.</p>";
|
||||||
}
|
}
|
||||||
<script src="~/vendor/vue-qrcode/vue-qrcode.min.js" asp-append-version="true"></script>
|
|
||||||
<script src="~/vendor/vuejs/vue.min.js" asp-append-version="true"></script>
|
|
||||||
<partial name="ShowQR"/>
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
const modes = {
|
const modes = {
|
||||||
uri: { title: "URI", fragments: [@Safe.Json(lnurlUri)], showData: true, href: @Safe.Json(lnurlUri) },
|
uri: { title: "URI", fragments: [@Safe.Json(lnurlUri)], showData: true, href: @Safe.Json(lnurlUri) },
|
||||||
bech32: { title: "Bech32", fragments: [@Safe.Json(lnurlBech32)], showData: true, href: @Safe.Json(lnurlBech32) }
|
bech32: { title: "Bech32", fragments: [@Safe.Json(lnurlBech32)], showData: true, href: @Safe.Json(lnurlBech32) }
|
||||||
};
|
};
|
||||||
initQRShow({ title: "LNURL Withdraw", note: @Safe.Json(note), modes })
|
delegate('click', '#lnurlwithdraw-button', () => {
|
||||||
|
qrApp.title = "LNURL Withdraw";
|
||||||
|
qrApp.modes = modes;
|
||||||
|
qrApp.mode = "bech32";
|
||||||
|
qrApp.note = @Safe.Json(note);
|
||||||
|
qrApp.show();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
{
|
{
|
||||||
<a id="@state-view"
|
<a id="@state-view"
|
||||||
asp-action="PullPayments"
|
asp-action="PullPayments"
|
||||||
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
asp-route-storeId="@storeId"
|
||||||
asp-route-pullPaymentState="@state"
|
asp-route-pullPaymentState="@state"
|
||||||
class="nav-link @(state == Model.ActiveState ? "active" : "")" role="tab">@state</a>
|
class="nav-link @(state == Model.ActiveState ? "active" : "")" role="tab">@state</a>
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,8 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
||||||
<table class="table table-hover table-responsive-lg">
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover">
|
||||||
<thead class="thead-inverse">
|
<thead class="thead-inverse">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">
|
<th scope="col">
|
||||||
|
@ -127,7 +128,7 @@
|
||||||
<td>
|
<td>
|
||||||
<a asp-action="EditPullPayment"
|
<a asp-action="EditPullPayment"
|
||||||
asp-controller="UIPullPayment"
|
asp-controller="UIPullPayment"
|
||||||
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
asp-route-storeId="@storeId"
|
||||||
asp-route-pullPaymentId="@pp.Id">
|
asp-route-pullPaymentId="@pp.Id">
|
||||||
@pp.Name
|
@pp.Name
|
||||||
</a>
|
</a>
|
||||||
|
@ -146,16 +147,16 @@
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<a class="pp-payout"
|
<a class="pp-payout"
|
||||||
asp-action="Payouts"
|
asp-action="Payouts"
|
||||||
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
asp-route-storeId="@storeId"
|
||||||
asp-route-pullPaymentId="@pp.Id">
|
asp-route-pullPaymentId="@pp.Id">
|
||||||
Payouts
|
Payouts
|
||||||
</a>
|
</a>
|
||||||
@if (!pp.Archived)
|
@if (!pp.Archived)
|
||||||
{
|
{
|
||||||
<span permission="@Policies.CanModifyStoreSettings"> - </span>
|
<span permission="@Policies.CanArchivePullPayments"> - </span>
|
||||||
<a asp-action="ArchivePullPayment"
|
<a asp-action="ArchivePullPayment"
|
||||||
permission="@Policies.CanModifyStoreSettings"
|
permission="@Policies.CanArchivePullPayments"
|
||||||
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
asp-route-storeId="@storeId"
|
||||||
asp-route-pullPaymentId="@pp.Id"
|
asp-route-pullPaymentId="@pp.Id"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#ConfirmModal"
|
data-bs-target="#ConfirmModal"
|
||||||
|
@ -174,7 +175,7 @@
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
<vc:pager view-model="Model" />
|
<vc:pager view-model="Model" />
|
||||||
|
|
||||||
<partial name="_Confirm" model="@(new ConfirmModel("Archive pull payment", "Do you really want to archive the pull payment?", "Archive"))" />
|
<partial name="_Confirm" model="@(new ConfirmModel("Archive pull payment", "Do you really want to archive the pull payment?", "Archive"))" />
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
"securitySchemes": {
|
"securitySchemes": {
|
||||||
"API_Key": {
|
"API_Key": {
|
||||||
"type": "apiKey",
|
"type": "apiKey",
|
||||||
"description": "BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n* `unrestricted`: Unrestricted access\n* `btcpay.user.candeleteuser`: Delete user\n* `btcpay.user.canviewprofile`: View your profile\n* `btcpay.user.canmodifyprofile`: Manage your profile\n* `btcpay.user.canmanagenotificationsforuser`: Manage your notifications\n* `btcpay.user.canviewnotificationsforuser`: View your notifications\n\nThe following permissions are available if the user is an administrator:\n\n* `btcpay.server.canviewusers`: View users\n* `btcpay.server.cancreateuser`: Create new users\n* `btcpay.server.canmanageusers`: Manage users\n* `btcpay.server.canmodifyserversettings`: Manage your server\n* `btcpay.server.canuseinternallightningnode`: Use the internal lightning node\n* `btcpay.server.canviewlightninginvoiceinternalnode`: View invoices from internal lightning node\n* `btcpay.server.cancreatelightninginvoiceinternalnode`: Create invoices with internal lightning node\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n* `btcpay.store.canmodifystoresettings`: Modify your stores\n* `btcpay.store.canviewcustodianaccounts`: View exchange accounts linked to your stores\n* `btcpay.store.canmanagecustodianaccounts`: Manage exchange accounts linked to your stores\n* `btcpay.store.candeposittocustodianaccount`: Deposit funds to exchange accounts linked to your stores\n* `btcpay.store.canwithdrawfromcustodianaccount`: Withdraw funds from exchange accounts to your store\n* `btcpay.store.cantradecustodianaccount`: Trade funds on your store's exchange accounts\n* `btcpay.store.webhooks.canmodifywebhooks`: Modify stores webhooks\n* `btcpay.store.canviewstoresettings`: View your stores\n* `btcpay.store.cancreateinvoice`: Create an invoice\n* `btcpay.store.canviewinvoices`: View invoices\n* `btcpay.store.canmodifyinvoices`: Modify invoices\n* `btcpay.store.canmodifypaymentrequests`: Modify your payment requests\n* `btcpay.store.canviewpaymentrequests`: View your payment requests\n* `btcpay.store.canmanagepullpayments`: Manage your pull payments\n* `btcpay.store.cancreatepullpayments`: Create pull payments\n* `btcpay.store.cancreatenonapprovedpullpayments`: Create non-approved pull payments\n* `btcpay.store.canuselightningnode`: Use the lightning nodes associated with your stores\n* `btcpay.store.canviewlightninginvoice`: View the lightning invoices associated with your stores\n* `btcpay.store.cancreatelightninginvoice`: Create invoices from the lightning nodes associated with your stores\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n",
|
"description": "BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n* `unrestricted`: Unrestricted access\n* `btcpay.user.candeleteuser`: Delete user\n* `btcpay.user.canviewprofile`: View your profile\n* `btcpay.user.canmodifyprofile`: Manage your profile\n* `btcpay.user.canmanagenotificationsforuser`: Manage your notifications\n* `btcpay.user.canviewnotificationsforuser`: View your notifications\n\nThe following permissions are available if the user is an administrator:\n\n* `btcpay.server.canviewusers`: View users\n* `btcpay.server.cancreateuser`: Create new users\n* `btcpay.server.canmanageusers`: Manage users\n* `btcpay.server.canmodifyserversettings`: Manage your server\n* `btcpay.server.canuseinternallightningnode`: Use the internal lightning node\n* `btcpay.server.canviewlightninginvoiceinternalnode`: View invoices from internal lightning node\n* `btcpay.server.cancreatelightninginvoiceinternalnode`: Create invoices with internal lightning node\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n* `btcpay.store.canmodifystoresettings`: Modify your stores\n* `btcpay.store.canviewcustodianaccounts`: View exchange accounts linked to your stores\n* `btcpay.store.canmanagecustodianaccounts`: Manage exchange accounts linked to your stores\n* `btcpay.store.candeposittocustodianaccount`: Deposit funds to exchange accounts linked to your stores\n* `btcpay.store.canwithdrawfromcustodianaccount`: Withdraw funds from exchange accounts to your store\n* `btcpay.store.cantradecustodianaccount`: Trade funds on your store's exchange accounts\n* `btcpay.store.webhooks.canmodifywebhooks`: Modify stores webhooks\n* `btcpay.store.canviewstoresettings`: View your stores\n* `btcpay.store.cancreateinvoice`: Create an invoice\n* `btcpay.store.canviewinvoices`: View invoices\n* `btcpay.store.canmodifyinvoices`: Modify invoices\n* `btcpay.store.canmodifypaymentrequests`: Modify your payment requests\n* `btcpay.store.canviewpaymentrequests`: View your payment requests\n* `btcpay.store.canmanagepullpayments`: Manage your pull payments\n* `btcpay.store.canarchivepullpayments`: Archive your pull payments\n* `btcpay.store.cancreatepullpayments`: Create pull payments\n* `btcpay.store.cancreatenonapprovedpullpayments`: Create non-approved pull payments\n* `btcpay.store.canuselightningnode`: Use the lightning nodes associated with your stores\n* `btcpay.store.canviewlightninginvoice`: View the lightning invoices associated with your stores\n* `btcpay.store.cancreatelightninginvoice`: Create invoices from the lightning nodes associated with your stores\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n",
|
||||||
"name": "Authorization",
|
"name": "Authorization",
|
||||||
"in": "header"
|
"in": "header"
|
||||||
},
|
},
|
||||||
|
|
|
@ -243,7 +243,7 @@
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"API_Key": [
|
"API_Key": [
|
||||||
"btcpay.store.canmanagepullpayments"
|
"btcpay.store.canarchivepullpayments"
|
||||||
],
|
],
|
||||||
"Basic": []
|
"Basic": []
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue