mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Add btcpay.store.cancreateinvoice claim, and use that for the store
This commit is contained in:
parent
e86b4d89ca
commit
fed53661b3
14 changed files with 44 additions and 43 deletions
|
@ -2,9 +2,11 @@
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models.AppViewModels;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
@ -46,7 +48,7 @@ namespace BTCPayServer.Controllers
|
|||
Items = _AppsHelper.Parse(settings.Template, settings.Currency)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Route("/apps/{appId}/pos")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
|
@ -90,6 +92,7 @@ namespace BTCPayServer.Controllers
|
|||
title = settings.Title;
|
||||
}
|
||||
var store = await _AppsHelper.GetStore(app);
|
||||
store.AdditionalClaims.Add(new Claim(Policies.CanCreateInvoice.Key, store.Id));
|
||||
var invoice = await _InvoiceController.CreateInvoiceCore(new NBitpayClient.Invoice()
|
||||
{
|
||||
ItemDesc = title,
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace BTCPayServer.Controllers
|
|||
{
|
||||
[EnableCors("BitpayAPI")]
|
||||
[BitpayAPIConstraint]
|
||||
[Authorize(Policies.CanUseStore.Key, AuthenticationSchemes = Policies.BitpayAuthentication)]
|
||||
[Authorize(Policies.CanCreateInvoice.Key, AuthenticationSchemes = Policies.BitpayAuthentication)]
|
||||
public class InvoiceControllerAPI : Controller
|
||||
{
|
||||
private InvoiceController _InvoiceController;
|
||||
|
|
|
@ -499,7 +499,7 @@ namespace BTCPayServer.Controllers
|
|||
return View(model);
|
||||
}
|
||||
StatusMessage = null;
|
||||
if (!store.HasClaim(Policies.CanModifyStoreSettings.Key))
|
||||
if (!store.HasClaim(Policies.CanCreateInvoice.Key))
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.StoreId), "You need to be owner of this store to create an invoice");
|
||||
return View(model);
|
||||
|
|
|
@ -62,6 +62,8 @@ namespace BTCPayServer.Controllers
|
|||
|
||||
internal async Task<DataWrapper<InvoiceResponse>> CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl)
|
||||
{
|
||||
if (!store.HasClaim(Policies.CanCreateInvoice.Key))
|
||||
throw new UnauthorizedAccessException();
|
||||
InvoiceLogs logs = new InvoiceLogs();
|
||||
logs.Write("Creation of invoice starting");
|
||||
var entity = new InvoiceEntity
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace BTCPayServer.Controllers
|
|||
else
|
||||
{
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
if (!storeBlob.PayButtonEnabled)
|
||||
if (!storeBlob.AnyoneCanInvoice)
|
||||
ModelState.AddModelError("Store", "Store has not enabled Pay Button");
|
||||
}
|
||||
|
||||
|
|
|
@ -399,6 +399,7 @@ namespace BTCPayServer.Controllers
|
|||
vm.StoreName = store.StoreName;
|
||||
vm.StoreWebsite = store.StoreWebsite;
|
||||
vm.NetworkFee = !storeBlob.NetworkFeeDisabled;
|
||||
vm.AnyoneCanCreateInvoice = storeBlob.AnyoneCanInvoice;
|
||||
vm.SpeedPolicy = store.SpeedPolicy;
|
||||
vm.CanDelete = _Repo.CanDeleteStores();
|
||||
AddPaymentMethods(store, storeBlob, vm);
|
||||
|
@ -470,6 +471,7 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
var blob = StoreData.GetStoreBlob();
|
||||
blob.AnyoneCanInvoice = model.AnyoneCanCreateInvoice;
|
||||
blob.NetworkFeeDisabled = !model.NetworkFee;
|
||||
blob.MonitoringExpiration = model.MonitoringExpiration;
|
||||
blob.InvoiceExpiration = model.InvoiceExpiration;
|
||||
|
@ -777,7 +779,7 @@ namespace BTCPayServer.Controllers
|
|||
var store = StoreData;
|
||||
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
if (!storeBlob.PayButtonEnabled)
|
||||
if (!storeBlob.AnyoneCanInvoice)
|
||||
{
|
||||
return View("PayButtonEnable", null);
|
||||
}
|
||||
|
@ -800,7 +802,7 @@ namespace BTCPayServer.Controllers
|
|||
public async Task<IActionResult> PayButton(bool enableStore)
|
||||
{
|
||||
var blob = StoreData.GetStoreBlob();
|
||||
blob.PayButtonEnabled = enableStore;
|
||||
blob.AnyoneCanInvoice = enableStore;
|
||||
if (StoreData.SetStoreBlob(blob))
|
||||
{
|
||||
await _Repo.UpdateStore(StoreData);
|
||||
|
|
|
@ -166,24 +166,25 @@ namespace BTCPayServer.Data
|
|||
public Claim[] GetClaims()
|
||||
{
|
||||
List<Claim> claims = new List<Claim>();
|
||||
claims.AddRange(AdditionalClaims);
|
||||
#pragma warning disable CS0612 // Type or member is obsolete
|
||||
var role = Role;
|
||||
#pragma warning restore CS0612 // Type or member is obsolete
|
||||
if (role == StoreRoles.Owner)
|
||||
{
|
||||
claims.Add(new Claim(Policies.CanModifyStoreSettings.Key, Id));
|
||||
claims.Add(new Claim(Policies.CanUseStore.Key, Id));
|
||||
}
|
||||
if (role == StoreRoles.Guest)
|
||||
|
||||
if(role == StoreRoles.Owner || role == StoreRoles.Guest || GetStoreBlob().AnyoneCanInvoice)
|
||||
{
|
||||
claims.Add(new Claim(Policies.CanUseStore.Key, Id));
|
||||
claims.Add(new Claim(Policies.CanCreateInvoice.Key, Id));
|
||||
}
|
||||
return claims.ToArray();
|
||||
}
|
||||
|
||||
public bool HasClaim(string claim)
|
||||
{
|
||||
return GetClaims().Any(c => c.Type == claim);
|
||||
return GetClaims().Any(c => c.Type == claim && c.Value == Id);
|
||||
}
|
||||
|
||||
public byte[] StoreBlob
|
||||
|
@ -196,6 +197,9 @@ namespace BTCPayServer.Data
|
|||
public List<PairedSINData> PairedSINs { get; set; }
|
||||
public IEnumerable<APIKeyData> APIKeys { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public List<Claim> AdditionalClaims { get; set; } = new List<Claim>();
|
||||
|
||||
#pragma warning disable CS0618
|
||||
public string GetDefaultCrypto(BTCPayNetworkProvider networkProvider = null)
|
||||
{
|
||||
|
@ -302,7 +306,7 @@ namespace BTCPayServer.Data
|
|||
|
||||
public string RateScript { get; set; }
|
||||
|
||||
public bool PayButtonEnabled { get; set; }
|
||||
public bool AnyoneCanInvoice { get; set; }
|
||||
|
||||
|
||||
string _LightningDescriptionTemplate;
|
||||
|
|
|
@ -47,6 +47,9 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||
set;
|
||||
}
|
||||
|
||||
[Display(Name = "Allow anyone to create invoice")]
|
||||
public bool AnyoneCanCreateInvoice { get; set; }
|
||||
|
||||
public List<StoreViewModel.DerivationScheme> DerivationSchemes { get; set; } = new List<StoreViewModel.DerivationScheme>();
|
||||
|
||||
[Display(Name = "Invoice expires if the full amount has not been paid after ... minutes")]
|
||||
|
|
|
@ -88,8 +88,9 @@ namespace BTCPayServer.Security
|
|||
{
|
||||
if (storeId != null)
|
||||
{
|
||||
claims.Add(new Claim(Policies.CanUseStore.Key, storeId));
|
||||
claims.Add(new Claim(Policies.CanCreateInvoice.Key, storeId));
|
||||
var store = await _StoreRepository.FindStore(storeId);
|
||||
store.AdditionalClaims.AddRange(claims);
|
||||
Context.Request.HttpContext.SetStoreData(store);
|
||||
}
|
||||
return AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(new ClaimsIdentity(claims, Policies.BitpayAuthentication)), Policies.BitpayAuthentication));
|
||||
|
|
|
@ -12,9 +12,9 @@ namespace BTCPayServer.Security
|
|||
public const string CookieAuthentication = "Identity.Application";
|
||||
public static AuthorizationOptions AddBTCPayPolicies(this AuthorizationOptions options)
|
||||
{
|
||||
AddClaim(options, CanUseStore.Key);
|
||||
AddClaim(options, CanModifyStoreSettings.Key);
|
||||
AddClaim(options, CanModifyServerSettings.Key);
|
||||
AddClaim(options, CanCreateInvoice.Key);
|
||||
return options;
|
||||
}
|
||||
|
||||
|
@ -27,13 +27,14 @@ namespace BTCPayServer.Security
|
|||
{
|
||||
public const string Key = "btcpay.store.canmodifyserversettings";
|
||||
}
|
||||
public class CanUseStore
|
||||
{
|
||||
public const string Key = "btcpay.store.canusestore";
|
||||
}
|
||||
public class CanModifyStoreSettings
|
||||
{
|
||||
public const string Key = "btcpay.store.canmodifystoresettings";
|
||||
}
|
||||
|
||||
public class CanCreateInvoice
|
||||
{
|
||||
public const string Key = "btcpay.store.cancreateinvoice";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace BTCPayServer.Services.Invoices
|
|||
}
|
||||
context.PendingInvoices.Add(new PendingInvoiceData() { Id = invoice.Id });
|
||||
|
||||
foreach(var log in creationLogs.ToList())
|
||||
foreach (var log in creationLogs.ToList())
|
||||
{
|
||||
context.InvoiceEvents.Add(new InvoiceEventData()
|
||||
{
|
||||
|
@ -249,7 +249,7 @@ namespace BTCPayServer.Services.Invoices
|
|||
{
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
catch(DbUpdateException) { } // Probably the invoice does not exists anymore
|
||||
catch (DbUpdateException) { } // Probably the invoice does not exists anymore
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,7 +441,7 @@ namespace BTCPayServer.Services.Invoices
|
|||
query = query.Where(i => statusSet.Contains(i.Status));
|
||||
}
|
||||
|
||||
if(queryObject.Unusual != null)
|
||||
if (queryObject.Unusual != null)
|
||||
{
|
||||
var unused = queryObject.Unusual.Value;
|
||||
query = query.Where(i => unused == (i.Status == "invalid" || i.ExceptionStatus != null));
|
||||
|
@ -554,7 +554,7 @@ namespace BTCPayServer.Services.Invoices
|
|||
{
|
||||
await context.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch(DbUpdateException) { return null; } // Already exists
|
||||
catch (DbUpdateException) { return null; } // Already exists
|
||||
AddToTextSearch(invoiceId, paymentData.GetSearchTerms());
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -122,25 +122,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<br /><br />
|
||||
<hr />
|
||||
<h3>Disable Pay Button</h3>
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<p>
|
||||
Disabling this feature will cause your currently used Pay Buttons to stop working.
|
||||
Customers trying to use Pay Button to create Invoices will be displayed appropriate message.
|
||||
You can always reenable Pay Buttons at later time.
|
||||
</p>
|
||||
@Html.Hidden("EnableStore", false)
|
||||
<button name="command" type="submit" value="save" class="btn btn-primary">Disable Pay Button</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@section HeadScripts {
|
||||
<link rel="stylesheet" href="~/vendor/highlightjs/default.min.css">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.PayButton, "Please confirm you want to enable Pay Button");
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.PayButton, "Please confirm you want to allow anyone to create invoices in your store");
|
||||
ViewBag.MainTitle = "Pay Button";
|
||||
}
|
||||
|
||||
|
@ -12,10 +12,10 @@
|
|||
<div class="form-group">
|
||||
<p>
|
||||
To start using Pay Buttons you need to explicitly turn on this feature.
|
||||
Once you do so, valid POST requests from any source will allow creation of Invoices on your instance of BtcPayServer.
|
||||
Once you do so, any source will be able to create an invoice on your instance store.
|
||||
</p>
|
||||
@Html.Hidden("EnableStore", true)
|
||||
<button name="command" type="submit" value="save" class="btn btn-primary">Enable Pay Button</button>
|
||||
<button name="command" type="submit" value="save" class="btn btn-primary">Allow anyone to create invoices</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -46,6 +46,10 @@
|
|||
<label asp-for="NetworkFee"></label>
|
||||
<input asp-for="NetworkFee" type="checkbox" class="form-check" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AnyoneCanCreateInvoice"></label>
|
||||
<input asp-for="AnyoneCanCreateInvoice" type="checkbox" class="form-check" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="InvoiceExpiration"></label>
|
||||
<input asp-for="InvoiceExpiration" class="form-control" />
|
||||
|
|
Loading…
Add table
Reference in a new issue