mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
parent
39beacf884
commit
1cb3e5f98c
6 changed files with 104 additions and 93 deletions
|
@ -9,6 +9,7 @@ using BTCPayServer.Client.Models;
|
|||
using BTCPayServer.Controllers;
|
||||
using BTCPayServer.Events;
|
||||
using BTCPayServer.JsonConverters;
|
||||
using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Tests.Logging;
|
||||
|
@ -872,6 +873,96 @@ namespace BTCPayServer.Tests
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
[Fact(Timeout = 60 * 2 * 1000)]
|
||||
[Trait("Integration", "Integration")]
|
||||
[Trait("Lightning", "Lightning")]
|
||||
public async Task CanUseLightningAPI()
|
||||
{
|
||||
using (var tester = ServerTester.Create())
|
||||
{
|
||||
tester.ActivateLightning();
|
||||
await tester.StartAsync();
|
||||
await tester.EnsureChannelsSetup();
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess(true);
|
||||
user.RegisterLightningNode("BTC", LightningConnectionType.CLightning, false);
|
||||
|
||||
var merchant = tester.NewAccount();
|
||||
merchant.GrantAccess(true);
|
||||
merchant.RegisterLightningNode("BTC", LightningConnectionType.LndREST);
|
||||
var merchantClient = await merchant.CreateClient($"{Policies.CanUseLightningNodeInStore}:{merchant.StoreId}");
|
||||
var merchantInvoice = await merchantClient.CreateLightningInvoice(merchant.StoreId, "BTC", new CreateLightningInvoiceRequest(new LightMoney(1_000), "hey", TimeSpan.FromSeconds(60)));
|
||||
tester.PayTester.GetService<BTCPayServerEnvironment>().DevelopmentOverride = false;
|
||||
// The default client is using charge, so we should not be able to query channels
|
||||
var client = await user.CreateClient(Policies.CanUseInternalLightningNode);
|
||||
|
||||
var info = await client.GetLightningNodeInfo("BTC");
|
||||
Assert.Single(info.NodeURIs);
|
||||
Assert.NotEqual(0, info.BlockHeight);
|
||||
|
||||
var err = await Assert.ThrowsAsync<HttpRequestException>(async () => await client.GetLightningNodeChannels("BTC"));
|
||||
Assert.Contains("503", err.Message);
|
||||
// Not permission for the store!
|
||||
err = await Assert.ThrowsAsync<HttpRequestException>(async () => await client.GetLightningNodeChannels(user.StoreId, "BTC"));
|
||||
Assert.Contains("403", err.Message);
|
||||
var invoiceData = await client.CreateLightningInvoice("BTC", new CreateLightningInvoiceRequest()
|
||||
{
|
||||
Amount = LightMoney.Satoshis(1000),
|
||||
Description = "lol",
|
||||
Expiry = TimeSpan.FromSeconds(400),
|
||||
PrivateRouteHints = false
|
||||
});
|
||||
var chargeInvoice = invoiceData;
|
||||
Assert.NotNull(await client.GetLightningInvoice("BTC", invoiceData.Id));
|
||||
|
||||
client = await user.CreateClient($"{Policies.CanUseLightningNodeInStore}:{user.StoreId}");
|
||||
// Not permission for the server
|
||||
err = await Assert.ThrowsAsync<HttpRequestException>(async () => await client.GetLightningNodeChannels("BTC"));
|
||||
Assert.Contains("403", err.Message);
|
||||
|
||||
var data = await client.GetLightningNodeChannels(user.StoreId, "BTC");
|
||||
Assert.Equal(2, data.Count());
|
||||
BitcoinAddress.Create(await client.GetLightningDepositAddress(user.StoreId, "BTC"), Network.RegTest);
|
||||
|
||||
invoiceData = await client.CreateLightningInvoice(user.StoreId, "BTC", new CreateLightningInvoiceRequest()
|
||||
{
|
||||
Amount = LightMoney.Satoshis(1000),
|
||||
Description = "lol",
|
||||
Expiry = TimeSpan.FromSeconds(400),
|
||||
PrivateRouteHints = false
|
||||
});
|
||||
|
||||
Assert.NotNull(await client.GetLightningInvoice(user.StoreId, "BTC", invoiceData.Id));
|
||||
|
||||
await client.PayLightningInvoice(user.StoreId, "BTC", new PayLightningInvoiceRequest()
|
||||
{
|
||||
BOLT11 = merchantInvoice.BOLT11
|
||||
});
|
||||
await Assert.ThrowsAsync<GreenFieldValidationException>(async () => await client.PayLightningInvoice(user.StoreId, "BTC", new PayLightningInvoiceRequest()
|
||||
{
|
||||
BOLT11 = "lol"
|
||||
}));
|
||||
|
||||
var validationErr = await Assert.ThrowsAsync<GreenFieldValidationException>(async () => await client.CreateLightningInvoice(user.StoreId, "BTC", new CreateLightningInvoiceRequest()
|
||||
{
|
||||
Amount = -1,
|
||||
Expiry = TimeSpan.FromSeconds(-1),
|
||||
Description = null
|
||||
}));
|
||||
Assert.Equal(2, validationErr.ValidationErrors.Length);
|
||||
|
||||
var invoice = await merchantClient.GetLightningInvoice(merchant.StoreId, "BTC", merchantInvoice.Id);
|
||||
Assert.NotNull(invoice.PaidAt);
|
||||
Assert.Equal(LightMoney.Satoshis(1000), invoice.Amount);
|
||||
// Amount received might be bigger because of internal implementation shit from lightning
|
||||
Assert.True(LightMoney.Satoshis(1000) <= invoice.AmountReceived);
|
||||
|
||||
info = await client.GetLightningNodeInfo(user.StoreId, "BTC");
|
||||
Assert.Single(info.NodeURIs);
|
||||
Assert.NotEqual(0, info.BlockHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -836,92 +836,6 @@ namespace BTCPayServer.Tests
|
|||
.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact(Timeout = 60 * 2 * 1000)]
|
||||
[Trait("Integration", "Integration")]
|
||||
[Trait("Lightning", "Lightning")]
|
||||
public async Task CanUseLightningAPI()
|
||||
{
|
||||
using (var tester = ServerTester.Create())
|
||||
{
|
||||
tester.ActivateLightning();
|
||||
await tester.StartAsync();
|
||||
await tester.EnsureChannelsSetup();
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess(true);
|
||||
user.RegisterLightningNode("BTC", LightningConnectionType.CLightning, false);
|
||||
|
||||
var merchant = tester.NewAccount();
|
||||
merchant.GrantAccess(true);
|
||||
merchant.RegisterLightningNode("BTC", LightningConnectionType.LndREST);
|
||||
var merchantClient = await merchant.CreateClient($"btcpay.store.canuselightningnode:{merchant.StoreId}");
|
||||
var merchantInvoice = await merchantClient.CreateLightningInvoice(merchant.StoreId, "BTC", new CreateLightningInvoiceRequest(new LightMoney(1_000), "hey", TimeSpan.FromSeconds(60)));
|
||||
|
||||
// The default client is using charge, so we should not be able to query channels
|
||||
var client = await user.CreateClient("btcpay.server.canuseinternallightningnode");
|
||||
var err = await Assert.ThrowsAsync<HttpRequestException>(async () => await client.GetLightningNodeChannels("BTC"));
|
||||
Assert.Contains("503", err.Message);
|
||||
// Not permission for the store!
|
||||
err = await Assert.ThrowsAsync<HttpRequestException>(async () => await client.GetLightningNodeChannels(user.StoreId, "BTC"));
|
||||
Assert.Contains("403", err.Message);
|
||||
var invoiceData = await client.CreateLightningInvoice("BTC", new CreateLightningInvoiceRequest()
|
||||
{
|
||||
Amount = LightMoney.Satoshis(1000),
|
||||
Description = "lol",
|
||||
Expiry = TimeSpan.FromSeconds(400),
|
||||
PrivateRouteHints = false
|
||||
});
|
||||
var chargeInvoice = invoiceData;
|
||||
Assert.NotNull(await client.GetLightningInvoice("BTC", invoiceData.Id));
|
||||
|
||||
client = await user.CreateClient($"btcpay.store.canuselightningnode:{user.StoreId}");
|
||||
// Not permission for the server
|
||||
err = await Assert.ThrowsAsync<HttpRequestException>(async () => await client.GetLightningNodeChannels("BTC"));
|
||||
Assert.Contains("403", err.Message);
|
||||
|
||||
var data = await client.GetLightningNodeChannels(user.StoreId, "BTC");
|
||||
Assert.Equal(2, data.Count());
|
||||
BitcoinAddress.Create(await client.GetLightningDepositAddress(user.StoreId, "BTC"), Network.RegTest);
|
||||
|
||||
invoiceData = await client.CreateLightningInvoice(user.StoreId, "BTC", new CreateLightningInvoiceRequest()
|
||||
{
|
||||
Amount = LightMoney.Satoshis(1000),
|
||||
Description = "lol",
|
||||
Expiry = TimeSpan.FromSeconds(400),
|
||||
PrivateRouteHints = false
|
||||
});
|
||||
|
||||
Assert.NotNull(await client.GetLightningInvoice(user.StoreId, "BTC", invoiceData.Id));
|
||||
|
||||
await client.PayLightningInvoice(user.StoreId, "BTC", new PayLightningInvoiceRequest()
|
||||
{
|
||||
BOLT11 = merchantInvoice.BOLT11
|
||||
});
|
||||
await Assert.ThrowsAsync<GreenFieldValidationException>(async () => await client.PayLightningInvoice(user.StoreId, "BTC", new PayLightningInvoiceRequest()
|
||||
{
|
||||
BOLT11 = "lol"
|
||||
}));
|
||||
|
||||
var validationErr = await Assert.ThrowsAsync<GreenFieldValidationException>(async () => await client.CreateLightningInvoice(user.StoreId, "BTC", new CreateLightningInvoiceRequest()
|
||||
{
|
||||
Amount = -1,
|
||||
Expiry = TimeSpan.FromSeconds(-1),
|
||||
Description = null
|
||||
}));
|
||||
Assert.Equal(2, validationErr.ValidationErrors.Length);
|
||||
|
||||
var invoice = await merchantClient.GetLightningInvoice(merchant.StoreId, "BTC", merchantInvoice.Id);
|
||||
Assert.NotNull(invoice.PaidAt);
|
||||
Assert.Equal(LightMoney.Satoshis(1000), invoice.Amount);
|
||||
// Amount received might be bigger because of internal implementation shit from lightning
|
||||
Assert.True(LightMoney.Satoshis(1000) <= invoice.AmountReceived);
|
||||
|
||||
var info = await client.GetLightningNodeInfo(user.StoreId, "BTC");
|
||||
Assert.Single(info.NodeURIs);
|
||||
Assert.NotEqual(0, info.BlockHeight);
|
||||
}
|
||||
}
|
||||
|
||||
async Task CanSendLightningPaymentCore(ServerTester tester, TestAccount user)
|
||||
{
|
||||
var invoice = await user.BitPay.CreateInvoiceAsync(new Invoice()
|
||||
|
|
|
@ -16,13 +16,14 @@ namespace BTCPayServer.Security.GreenField
|
|||
_applicationDbContextFactory = applicationDbContextFactory;
|
||||
}
|
||||
|
||||
public async Task<APIKeyData> GetKey(string apiKey)
|
||||
public async Task<APIKeyData> GetKey(string apiKey, bool includeUser = false)
|
||||
{
|
||||
using (var context = _applicationDbContextFactory.CreateContext())
|
||||
await using var context = _applicationDbContextFactory.CreateContext();
|
||||
if (includeUser)
|
||||
{
|
||||
return await EntityFrameworkQueryableExtensions.SingleOrDefaultAsync(context.ApiKeys,
|
||||
data => data.Id == apiKey && data.Type != APIKeyType.Legacy);
|
||||
return await context.ApiKeys.Include(data => data.User).SingleOrDefaultAsync(data => data.Id == apiKey && data.Type != APIKeyType.Legacy);
|
||||
}
|
||||
return await context.ApiKeys.SingleOrDefaultAsync(data => data.Id == apiKey && data.Type != APIKeyType.Legacy);
|
||||
}
|
||||
|
||||
public async Task<List<APIKeyData>> GetKeys(APIKeyQuery query)
|
||||
|
|
|
@ -40,15 +40,16 @@ namespace BTCPayServer.Security.GreenField
|
|||
if (!Context.Request.HttpContext.GetAPIKey(out var apiKey) || string.IsNullOrEmpty(apiKey))
|
||||
return AuthenticateResult.NoResult();
|
||||
|
||||
var key = await _apiKeyRepository.GetKey(apiKey);
|
||||
var key = await _apiKeyRepository.GetKey(apiKey, true);
|
||||
|
||||
if (key == null)
|
||||
{
|
||||
return AuthenticateResult.Fail("ApiKey authentication failed");
|
||||
}
|
||||
|
||||
List<Claim> claims = new List<Claim>();
|
||||
claims.Add(new Claim(_identityOptions.CurrentValue.ClaimsIdentity.UserIdClaimType, key.UserId));
|
||||
|
||||
claims.AddRange((await _userManager.GetRolesAsync(key.User)).Select(s => new Claim(_identityOptions.CurrentValue.ClaimsIdentity.RoleClaimType, s)));
|
||||
claims.AddRange(Permission.ToPermissions(key.GetBlob().Permissions).Select(permission =>
|
||||
new Claim(GreenFieldConstants.ClaimTypes.Permission, permission.ToString())));
|
||||
return AuthenticateResult.Success(new AuthenticationTicket(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
|
@ -67,6 +68,7 @@ namespace BTCPayServer.Security.GreenField
|
|||
new Claim(GreenFieldConstants.ClaimTypes.Permission,
|
||||
Permission.Create(Policies.Unrestricted).ToString())
|
||||
};
|
||||
claims.AddRange((await _userManager.GetRolesAsync(user)).Select(s => new Claim(_identityOptions.CurrentValue.ClaimsIdentity.RoleClaimType, s)));
|
||||
|
||||
return AuthenticateResult.Success(new AuthenticationTicket(
|
||||
new ClaimsPrincipal(new ClaimsIdentity(claims, GreenFieldConstants.AuthenticationType)),
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace BTCPayServer.Services
|
|||
{
|
||||
get
|
||||
{
|
||||
return NetworkType == NetworkType.Regtest && Environment.IsDevelopment();
|
||||
return DevelopmentOverride?? NetworkType == NetworkType.Regtest && Environment.IsDevelopment();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,5 +87,7 @@ namespace BTCPayServer.Services
|
|||
}
|
||||
return txt.ToString();
|
||||
}
|
||||
|
||||
public bool? DevelopmentOverride;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue