btcpayserver/BTCPayServer/Controllers/StoresController.LightningLike.cs

180 lines
7.8 KiB
C#
Raw Normal View History

2020-06-28 21:44:35 -05:00
using System;
using System.Linq;
2020-06-28 17:55:27 +09:00
using System.Threading;
using System.Threading.Tasks;
2020-06-28 17:55:27 +09:00
using BTCPayServer.Data;
using BTCPayServer.Lightning;
using BTCPayServer.Models.StoreViewModels;
using BTCPayServer.Payments;
using BTCPayServer.Payments.Lightning;
2020-06-28 17:55:27 +09:00
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
namespace BTCPayServer.Controllers
{
public partial class StoresController
{
2018-03-23 16:24:57 +09:00
[HttpGet]
[Route("{storeId}/lightning/{cryptoCode}")]
2018-04-30 02:33:42 +09:00
public IActionResult AddLightningNode(string storeId, string cryptoCode)
{
2018-04-30 02:33:42 +09:00
var store = HttpContext.GetStoreData();
if (store == null)
return NotFound();
2018-07-27 13:37:16 +02:00
LightningNodeViewModel vm = new LightningNodeViewModel
{
CryptoCode = cryptoCode,
2019-01-07 09:52:27 +01:00
InternalLightningNode = GetInternalLighningNode(cryptoCode)?.ToString(),
StoreId = storeId
2018-07-27 13:37:16 +02:00
};
SetExistingValues(store, vm);
return View(vm);
}
private void SetExistingValues(StoreData store, LightningNodeViewModel vm)
{
vm.ConnectionString = GetExistingLightningSupportedPaymentMethod(vm.CryptoCode, store)?.GetLightningUrl()?.ToString();
2018-07-27 13:37:16 +02:00
vm.Enabled = !store.GetStoreBlob().IsExcluded(new PaymentMethodId(vm.CryptoCode, PaymentTypes.LightningLike));
}
private LightningSupportedPaymentMethod GetExistingLightningSupportedPaymentMethod(string cryptoCode, StoreData store)
{
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
var existing = store.GetSupportedPaymentMethods(_NetworkProvider)
.OfType<LightningSupportedPaymentMethod>()
.FirstOrDefault(d => d.PaymentId == id);
return existing;
}
private LightningConnectionString GetInternalLighningNode(string cryptoCode)
2018-03-21 02:09:25 +09:00
{
if (_BtcpayServerOptions.InternalLightningByCryptoCode.TryGetValue(cryptoCode, out var connectionString))
2018-03-21 02:09:25 +09:00
{
return CanUseInternalLightning() ? connectionString : null;
}
return null;
}
[HttpPost]
[Route("{storeId}/lightning/{cryptoCode}")]
public async Task<IActionResult> AddLightningNode(string storeId, LightningNodeViewModel vm, string command, string cryptoCode)
{
vm.CryptoCode = cryptoCode;
2018-04-30 02:33:42 +09:00
var store = HttpContext.GetStoreData();
if (store == null)
return NotFound();
var network = vm.CryptoCode == null ? null : _ExplorerProvider.GetNetwork(vm.CryptoCode);
2018-03-21 02:09:25 +09:00
var internalLightning = GetInternalLighningNode(network.CryptoCode);
vm.InternalLightningNode = internalLightning?.ToString();
if (network == null)
{
ModelState.AddModelError(nameof(vm.CryptoCode), "Invalid network");
return View(vm);
}
PaymentMethodId paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.LightningLike);
Payments.Lightning.LightningSupportedPaymentMethod paymentMethod = null;
if (!string.IsNullOrEmpty(vm.ConnectionString))
{
if (!LightningConnectionString.TryParse(vm.ConnectionString, false, out var connectionString, out var error))
{
ModelState.AddModelError(nameof(vm.ConnectionString), $"Invalid URL ({error})");
return View(vm);
}
2020-06-28 17:55:27 +09:00
if (connectionString.ConnectionType == LightningConnectionType.LndGRPC)
{
ModelState.AddModelError(nameof(vm.ConnectionString), $"BTCPay does not support gRPC connections");
return View(vm);
}
bool isInternalNode = connectionString.IsInternalNode(internalLightning);
if (connectionString.BaseUri.Scheme == "http")
{
if (!isInternalNode && !connectionString.AllowInsecure)
{
ModelState.AddModelError(nameof(vm.ConnectionString), "The url must be HTTPS");
return View(vm);
}
}
2020-06-28 17:55:27 +09:00
if (connectionString.MacaroonFilePath != null)
{
2020-06-28 17:55:27 +09:00
if (!CanUseInternalLightning())
{
ModelState.AddModelError(nameof(vm.ConnectionString), "You are not authorized to use macaroonfilepath");
return View(vm);
}
2020-06-28 17:55:27 +09:00
if (!System.IO.File.Exists(connectionString.MacaroonFilePath))
{
ModelState.AddModelError(nameof(vm.ConnectionString), "The macaroonfilepath file does not exist");
return View(vm);
}
2020-06-28 17:55:27 +09:00
if (!System.IO.Path.IsPathRooted(connectionString.MacaroonFilePath))
2018-07-10 12:51:23 +09:00
{
ModelState.AddModelError(nameof(vm.ConnectionString), "The macaroonfilepath should be fully rooted");
return View(vm);
}
}
if (isInternalNode && !CanUseInternalLightning())
{
ModelState.AddModelError(nameof(vm.ConnectionString), "Unauthorized url");
return View(vm);
}
paymentMethod = new Payments.Lightning.LightningSupportedPaymentMethod()
{
CryptoCode = paymentMethodId.CryptoCode
};
paymentMethod.SetLightningUrl(connectionString);
}
2018-06-23 22:03:51 -05:00
2018-07-27 13:37:16 +02:00
switch (command)
{
2018-07-27 13:37:16 +02:00
case "save":
2018-08-08 17:32:16 +09:00
var storeBlob = store.GetStoreBlob();
storeBlob.SetExcluded(paymentMethodId, !vm.Enabled);
storeBlob.Hints.Lightning = false;
2018-08-08 17:32:16 +09:00
store.SetStoreBlob(storeBlob);
store.SetSupportedPaymentMethod(paymentMethodId, paymentMethod);
2018-07-27 13:37:16 +02:00
await _Repo.UpdateStore(store);
TempData[WellKnownTempData.SuccessMessage] = $"Lightning node modified ({network.CryptoCode})";
2018-07-27 13:37:16 +02:00
return RedirectToAction(nameof(UpdateStore), new { storeId = storeId });
case "test" when paymentMethod == null:
ModelState.AddModelError(nameof(vm.ConnectionString), "Missing url parameter");
return View(vm);
2018-07-27 13:37:16 +02:00
case "test":
var handler = _ServiceProvider.GetRequiredService<LightningLikePaymentHandler>();
2018-07-27 13:37:16 +02:00
try
2018-04-09 16:25:31 +09:00
{
var info = await handler.GetNodeInfo(this.Request.IsOnion(), paymentMethod, network);
2018-07-27 13:37:16 +02:00
if (!vm.SkipPortTest)
2018-04-09 16:25:31 +09:00
{
2018-07-27 13:37:16 +02:00
using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(20)))
{
await handler.TestConnection(info, cts.Token);
}
2018-04-09 16:25:31 +09:00
}
TempData[WellKnownTempData.SuccessMessage] = $"Connection to the lightning node succeeded. Your node address: {info}";
2018-07-27 13:37:16 +02:00
}
catch (Exception ex)
{
TempData[WellKnownTempData.ErrorMessage] = ex.Message;
2018-07-27 13:37:16 +02:00
return View(vm);
2018-04-09 16:25:31 +09:00
}
return View(vm);
2018-07-27 13:37:16 +02:00
default:
return View(vm);
}
}
private bool CanUseInternalLightning()
{
2020-07-30 20:43:44 -05:00
return (_BTCPayEnv.IsDeveloping || User.IsInRole(Roles.ServerAdmin) || _CssThemeManager.AllowLightningInternalNodeForAll);
}
}
}