Compare commits

...

10 Commits

16 changed files with 126 additions and 56 deletions

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<Version>1.0.2.84</Version>
<Version>1.0.2.87</Version>
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
</PropertyGroup>
<ItemGroup>

View File

@ -17,6 +17,7 @@ using BTCPayServer.Services.Mails;
using BTCPayServer.Services.Stores;
using BTCPayServer.Logging;
using BTCPayServer.Security;
using System.Globalization;
namespace BTCPayServer.Controllers
{
@ -236,23 +237,25 @@ namespace BTCPayServer.Controllers
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Register(string returnUrl = null)
public async Task<IActionResult> Register(string returnUrl = null, bool logon = true)
{
var policies = await _SettingsRepository.GetSettingAsync<PoliciesSettings>() ?? new PoliciesSettings();
if (policies.LockSubscription)
if (policies.LockSubscription && !User.IsInRole(Roles.ServerAdmin))
return RedirectToAction(nameof(HomeController.Index), "Home");
ViewData["ReturnUrl"] = returnUrl;
ViewData["Logon"] = logon.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null, bool logon = true)
{
ViewData["ReturnUrl"] = returnUrl;
ViewData["Logon"] = logon.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
var policies = await _SettingsRepository.GetSettingAsync<PoliciesSettings>() ?? new PoliciesSettings();
if (policies.LockSubscription)
if (policies.LockSubscription && !User.IsInRole(Roles.ServerAdmin))
return RedirectToAction(nameof(HomeController.Index), "Home");
if (ModelState.IsValid)
{
@ -274,7 +277,8 @@ namespace BTCPayServer.Controllers
await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);
if (!policies.RequiresConfirmedEmail)
{
await _signInManager.SignInAsync(user, isPersistent: false);
if(logon)
await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToLocal(returnUrl);
}
else

View File

@ -19,6 +19,7 @@ using BTCPayServer.Services.Rates;
using System.Globalization;
using System.Text;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Cors;
namespace BTCPayServer.Controllers
{
@ -208,6 +209,7 @@ namespace BTCPayServer.Controllers
[HttpPost]
[Route("{appId}/pos")]
[IgnoreAntiforgeryToken]
[EnableCors(CorsPolicies.All)]
public async Task<IActionResult> ViewPointOfSale(string appId,
decimal amount,
string email,

View File

@ -231,7 +231,11 @@ namespace BTCPayServer.Controllers
{
if (!isDefaultCrypto)
return null;
var paymentMethodTemp = invoice.GetPaymentMethods(_NetworkProvider).First();
var paymentMethodTemp = invoice.GetPaymentMethods(_NetworkProvider)
.Where(c=> paymentMethodId.CryptoCode == c.GetId().CryptoCode)
.FirstOrDefault();
if (paymentMethodTemp == null)
paymentMethodTemp = invoice.GetPaymentMethods(_NetworkProvider).First();
network = paymentMethodTemp.Network;
paymentMethodId = paymentMethodTemp.GetId();
paymentMethodIdStr = paymentMethodId.ToString();

View File

@ -32,6 +32,7 @@ namespace BTCPayServer.Controllers
{
private UserManager<ApplicationUser> _UserManager;
SettingsRepository _SettingsRepository;
private readonly NBXplorerDashboard _dashBoard;
private BTCPayRateProviderFactory _RateProviderFactory;
private StoreRepository _StoreRepository;
LightningConfigurationProvider _LnConfigProvider;
@ -41,12 +42,14 @@ namespace BTCPayServer.Controllers
Configuration.BTCPayServerOptions options,
BTCPayRateProviderFactory rateProviderFactory,
SettingsRepository settingsRepository,
NBXplorerDashboard dashBoard,
LightningConfigurationProvider lnConfigProvider,
Services.Stores.StoreRepository storeRepository)
{
_Options = options;
_UserManager = userManager;
_SettingsRepository = settingsRepository;
_dashBoard = dashBoard;
_RateProviderFactory = rateProviderFactory;
_StoreRepository = storeRepository;
_LnConfigProvider = lnConfigProvider;
@ -407,6 +410,11 @@ namespace BTCPayServer.Controllers
[Route("server/services/lnd-grpc/{cryptoCode}/{index}")]
public IActionResult LNDGRPCServices(string cryptoCode, int index, uint? nonce)
{
if(!_dashBoard.IsFullySynched(cryptoCode, out var unusud))
{
StatusMessage = $"Error: {cryptoCode} is not fully synched";
return RedirectToAction(nameof(Services));
}
var external = GetExternalLNDConnectionString(cryptoCode, index);
if (external == null)
return NotFound();

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BTCPayServer
{
public static class CorsPolicies
{
public const string All = "BTCPAY_ALL";
}
}

View File

@ -137,6 +137,23 @@ namespace BTCPayServer
request.PathBase.ToUriComponent());
}
public static string GetCurrentUrl(this HttpRequest request)
{
return string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent(),
request.PathBase.ToUriComponent(),
request.Path.ToUriComponent());
}
public static string GetCurrentPath(this HttpRequest request)
{
return string.Concat(
request.PathBase.ToUriComponent(),
request.Path.ToUriComponent());
}
public static string GetAbsoluteUri(this HttpRequest request, string redirectUrl)
{
bool isRelative =

View File

@ -157,6 +157,10 @@ namespace BTCPayServer.Hosting
return bundle;
});
services.AddCors(options=>
{
options.AddPolicy(CorsPolicies.All, p=>p.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
});
return services;
}

View File

@ -155,6 +155,7 @@ namespace BTCPayServer.Hosting
app.UseDeveloperExceptionPage();
}
app.UseCors();
app.UsePayServer();
app.UseStaticFiles();
app.UseAuthentication();

View File

@ -16,7 +16,7 @@
<hr class="primary">
</div>
<div class="col-md-4">
<form asp-route-returnUrl="@ViewData["ReturnUrl"]" method="post">
<form asp-route-returnUrl="@ViewData["ReturnUrl"]" asp-route-logon="@ViewData["Logon"]" method="post">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>

View File

@ -56,8 +56,7 @@
<p><strong>Never</strong> trust anything but <code>id</code>, <strong>ignore</strong> the other fields completely, an attacker can spoof those, they are present only for backward compatibility reason:</p>
<p>
<ul>
<li><strong>Build the invoice's url by yourself</strong> do not trust the <code>url</code> field, this can be spoofed to use attacker's server.</li>
<li>Send a <code>GET</code> request to the invoice's url with <code>Content-Type: application/json</code></li>
<li>Send a <code>GET</code> request to <code>https://btcpay.example.com/invoices/{invoiceId}</code> with <code>Content-Type: application/json</code></li>
<li>Verify that the <code>orderId</code> is from your backend, that the <code>price</code> is correct and that <code>status</code> is either <code>confirmed</code> or <code>complete</code></li>
<li>You can then ship your order</li>
</ul>

View File

@ -33,45 +33,52 @@
</div>
</div>
<div class="order-details">
@if (Model.AvailableCryptos.Count > 1)
{
<div class="currency-selection">
<div class="single-item-order__left">
<div style="font-weight: 600;">
{{$t("Pay with")}}
</div>
</div>
<div class="single-item-order__right">
@if (Model.AvailableCryptos.Count > 1)
{
<div class="payment__currencies" onclick="openPaymentMethodDialog()">
<img v-bind:src="srvModel.cryptoImage" />
<span class="clickable_underline">{{srvModel.paymentMethodName}} ({{srvModel.cryptoCode}})</span>
<span v-show="srvModel.isLightning">&#9889;</span>
<span class="clickable_indicator fa fa-angle-right"></span>
</div>
<div id="vexPopupDialog">
<ul class="vexmenu">
@foreach (var crypto in Model.AvailableCryptos)
{
<li class="vexmenuitem">
<a href="@crypto.Link" onclick="return closePaymentMethodDialog('@crypto.PaymentMethodId');">
<img alt="@crypto.PaymentMethodName" src="@crypto.CryptoImage" />
@crypto.PaymentMethodName
@(crypto.IsLightning ? Html.Raw("&#9889;") : null)
<span>@crypto.CryptoCode</span>
</a>
</li>
}
</ul>
</div>
}
<div class="payment__spinner">
<partial name="Checkout-Spinner" />
</div>
<div class="currency-selection">
<div class="single-item-order__left">
<div style="font-weight: 600;">
{{$t("Pay with")}}
</div>
</div>
}
<div class="single-item-order__right">
@if (Model.AvailableCryptos.Count > 1)
{
<div class="payment__currencies cursorPointer" onclick="openPaymentMethodDialog()">
<img v-bind:src="srvModel.cryptoImage" />
<span class="clickable_underline">{{srvModel.paymentMethodName}} ({{srvModel.cryptoCode}})</span>
<span v-show="srvModel.isLightning">&#9889;</span>
<span class="clickable_indicator fa fa-angle-right"></span>
</div>
<div id="vexPopupDialog">
<ul class="vexmenu">
@foreach (var crypto in Model.AvailableCryptos)
{
<li class="vexmenuitem">
<a href="@crypto.Link" onclick="return closePaymentMethodDialog('@crypto.PaymentMethodId');">
<img alt="@crypto.PaymentMethodName" src="@crypto.CryptoImage" />
@crypto.PaymentMethodName
@(crypto.IsLightning ? Html.Raw("&#9889;") : null)
<span>@crypto.CryptoCode</span>
</a>
</li>
}
</ul>
</div>
}
else
{
<div class="payment__currencies">
<img v-bind:src="srvModel.cryptoImage" />
<span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCode}})</span>
<span v-show="srvModel.isLightning">&#9889;</span>
</div>
}
<div class="payment__spinner">
<partial name="Checkout-Spinner" />
</div>
</div>
</div>
<div class="single-item-order buyerTotalLine">
<div class="single-item-order__left">
<div class="single-item-order__left__name">

View File

@ -7,7 +7,7 @@
<h4>@ViewData["Title"]</h4>
<partial name="_StatusMessage" for="StatusMessage" />
<a asp-controller="Account" asp-action="Register" asp-route-returnUrl="@Context.Request.GetCurrentPath()" asp-route-logon="false" class="btn btn-primary" role="button"><span class="fa fa-plus"></span> Create a new user</a>
<table class="table table-sm table-responsive-md">
<thead>
<tr>

View File

@ -5,7 +5,7 @@
<h4>@ViewData["Title"]</h4>
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
<div class="row">
<div class="col-md-6">
<div asp-validation-summary="All" class="text-danger"></div>

View File

@ -93,18 +93,22 @@
X_X = gdax(X_X);
</code>
</pre>
<p>With <code>DOGE_USD</code> will be expanded to <code>bittrex(DOGE_BTC) * gdax(BTC_USD)</code>. And <code>DOGE_CAD</code> will be expanded to <code>bittrex(DOGE_BTC) * quadrigacx(BTC_CAD)</code>. <br />
However, we advise you to write it that way to increase coverage so that <code>DOGE_BTC</code> is also supported:</p>
<p>
With <code>DOGE_USD</code> will be expanded to <code>bittrex(DOGE_BTC) * gdax(BTC_USD)</code>. And <code>DOGE_CAD</code> will be expanded to <code>bittrex(DOGE_BTC) * quadrigacx(BTC_CAD)</code>. <br />
However, we advise you to write it that way to increase coverage so that <code>DOGE_BTC</code> is also supported:
</p>
<pre>
<code>
<code>
DOGE_X = DOGE_BTC * BTC_X
DOGE_BTC = bittrex(DOGE_BTC)
X_CAD = quadrigacx(X_CAD);
X_X = gdax(X_X);
</code>
</pre>
<p>It is worth noting that the inverses of those pairs are automatically supported as well.<br />
It means that the rule <code>USD_DOGE = 1 / DOGE_USD</code> implicitely exists.</p>
<p>
It is worth noting that the inverses of those pairs are automatically supported as well.<br />
It means that the rule <code>USD_DOGE = 1 / DOGE_USD</code> implicitely exists.
</p>
</div>
<div class="form-group">
@ -133,7 +137,12 @@
}
<div class="form-group">
<label asp-for="Spread"></label>
<input asp-for="Spread" class="form-control" />
<div class="input-group">
<input asp-for="Spread" class="form-control" />
<div class="input-group-prepend">
<span class="input-group-text">%</span>
</div>
</div>
<span asp-validation-for="Spread" class="text-danger"></span>
</div>
<div class="form-group">

View File

@ -40,9 +40,12 @@
display: none;
}
.cursorPointer {
cursor: pointer;
}
.payment__currencies {
font-size: 14px;
cursor: pointer;
}
.payment__currencies img {