mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 18:11:36 +01:00
c97b859963
Based on the `ur-registry` upgrade I refactored the `CameraScanner` and `ShowQR` partials: Besides general code changes, the main change is that most of the configuration and result handling now happens on the outer view. Those partials and functions are now generalized and don't know about their purpose (like handling PSBTs): They can be instantiated with simple data (e.g. for displaying a plain QR code) or different modes (like showing a static and the UR version of a QR code) and the result handling is done via callback. The callbacks can now also distinguish between the different results (data as plain string vs. UR-type objects for wallet data or PSBT) and also handle the specific type of data. For instance: Before it wasn't possible to strip the leading derivation path from an xpub when scanning the QR code, because the scanner didn't know about the type of data it was handling. Now that the data is handled in the callback, we can implement that functionality for the scan view only.
127 lines
6.0 KiB
Plaintext
127 lines
6.0 KiB
Plaintext
@namespace BTCPayServer.Client
|
|
@using BTCPayServer.Abstractions.Models
|
|
@model BTCPayServer.Controllers.UIManageController.ApiKeysViewModel
|
|
@{
|
|
ViewData.SetActivePage(ManageNavPages.APIKeys, "API Keys");
|
|
}
|
|
|
|
<div class="row">
|
|
<div class="col-xl-10 col-xxl-constrain">
|
|
<div class="d-flex align-items-center justify-content-between mb-3">
|
|
<h3 class="mb-0">@ViewData["Title"]</h3>
|
|
<a class="btn btn-primary" asp-action="AddApiKey" id="AddApiKey">
|
|
<span class="fa fa-plus"></span>
|
|
Generate Key
|
|
</a>
|
|
</div>
|
|
<p>
|
|
The <a asp-controller="UIHome" asp-action="SwaggerDocs" target="_blank">BTCPay Server Greenfield API</a> offers programmatic access to your instance. You can manage your BTCPay
|
|
Server (e.g. stores, invoices, users) as well as automate workflows and integrations (see <a href="https://docs.btcpayserver.org/Development/GreenFieldExample/" rel="noreferrer noopener">use case examples</a>).
|
|
For that you need the API keys, which can be generated here. Find more information in the <a href="@Url.Action("SwaggerDocs", "UIHome")#section/Authentication" target="_blank" rel="noreferrer noopener">API authentication docs</a>.
|
|
</p>
|
|
|
|
@if (Model.ApiKeyDatas.Any())
|
|
{
|
|
<table class="table table-lg">
|
|
<thead>
|
|
<tr>
|
|
<th>Label</th>
|
|
<th class="w-125px">Key</th>
|
|
<th>Permissions</th>
|
|
<th class="text-end">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@{
|
|
var index = 0;
|
|
}
|
|
@foreach (var keyData in Model.ApiKeyDatas)
|
|
{
|
|
<tr>
|
|
<td>@keyData.Label</td>
|
|
<td>
|
|
<code class="hide-when-js">@keyData.Id</code>
|
|
<a class="only-for-js" data-reveal-btn>Click to reveal</a>
|
|
<div hidden>
|
|
<code data-api-key>@keyData.Id</code>
|
|
<a class="mt-2" data-clipboard-confirm>
|
|
Copy to clipboard
|
|
</a>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
@{
|
|
var permissions = keyData.GetBlob().Permissions;
|
|
}
|
|
@if (!permissions.Any())
|
|
{
|
|
<span class="text-warning">No permissions</span>
|
|
}
|
|
else
|
|
{
|
|
<ul>
|
|
@foreach (var permission in Permission.ToPermissions(permissions).Select(c => c.ToString()).Distinct().ToArray())
|
|
{
|
|
<li>
|
|
<code class="text-break">@permission</code>
|
|
</li>
|
|
}
|
|
</ul>
|
|
}
|
|
</td>
|
|
<td class="text-end">
|
|
<a asp-action="DeleteAPIKey" asp-route-id="@keyData.Id" asp-controller="UIManage" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="Any application using the API key <strong>@(keyData.Label ?? keyData.Id)<strong> will immediately lose access." data-confirm-input="DELETE">Delete</a>
|
|
<span>-</span>
|
|
<button type="button" class="btn btn-link only-for-js p-0" data-qr="@index">Show QR</button>
|
|
</td>
|
|
</tr>
|
|
index++;
|
|
}
|
|
</tbody>
|
|
</table>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
<partial name="_Confirm" model="@(new ConfirmModel("Delete API key", "Any application using the API key will immediately lose access.", "Delete"))" />
|
|
|
|
<partial name="ShowQR" />
|
|
|
|
@section PageHeadContent {
|
|
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true" />
|
|
}
|
|
@section PageFootContent {
|
|
<bundle name="wwwroot/bundles/camera-bundle.min.js"></bundle>
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
$("[data-reveal-btn]").on("click", function (){
|
|
var $revealButton = $(this);
|
|
$revealButton.attr("hidden", "true");
|
|
|
|
var $apiKeyContainer = $revealButton.next("[hidden]");
|
|
$apiKeyContainer.removeAttr("hidden");
|
|
|
|
(function setupCopyToClipboardButton() {
|
|
var $clipboardBtn = $apiKeyContainer.children("[data-clipboard-confirm]");
|
|
var apiKey = $apiKeyContainer.children("[data-api-key]").text().trim();
|
|
$clipboardBtn.attr("data-clipboard", apiKey);
|
|
$clipboardBtn.click(window.copyToClipboard);
|
|
})();
|
|
});
|
|
|
|
const apiKeys = @Safe.Json(Model.ApiKeyDatas.Select(data => new
|
|
{
|
|
ApiKey = data.Id,
|
|
Host = Context.Request.GetAbsoluteRoot()
|
|
}));
|
|
const qrApp = initQRShow({ title: "API Key QR" });
|
|
delegate("click", "button[data-qr]", e => {
|
|
e.preventDefault();
|
|
const { qr } = e.target.dataset;
|
|
const data = apiKeys[qr];
|
|
qrApp.showData(JSON.stringify(data));
|
|
});
|
|
});
|
|
</script>
|
|
}
|