diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs index b7d791b41..f651a60a6 100644 --- a/BTCPayServer.Tests/GreenfieldAPITests.cs +++ b/BTCPayServer.Tests/GreenfieldAPITests.cs @@ -4122,7 +4122,12 @@ namespace BTCPayServer.Tests var resp = await tester.CustomerLightningD.Pay(inv.BOLT11); Assert.Equal(PayResult.Ok, resp.Result); - + var store = tester.PayTester.GetService(); + Assert.True(await store.InternalNodePayoutAuthorized(admin.StoreId)); + Assert.False(await store.InternalNodePayoutAuthorized("blah")); + await admin.MakeAdmin(false); + Assert.False(await store.InternalNodePayoutAuthorized(admin.StoreId)); + await admin.MakeAdmin(true); var customerInvoice = await tester.CustomerLightningD.CreateInvoice(LightMoney.FromUnit(10, LightMoneyUnit.Satoshi), Guid.NewGuid().ToString(), TimeSpan.FromDays(40)); diff --git a/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutProcessor.cs b/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutProcessor.cs index 3cbe97a70..d604fb77c 100644 --- a/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutProcessor.cs +++ b/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutProcessor.cs @@ -121,12 +121,7 @@ public class LightningAutomatedPayoutProcessor : BaseAutomatedPayoutProcessor
  • - user.StoreRole.ToPermissionSet(PayoutProcessorSettings.StoreId) - .Contains(Policies.CanModifyStoreSettings, PayoutProcessorSettings.StoreId)) - .Select(user => user.Id) - .Select(s => _userService.IsAdminUser(s)))).Any(b => b)) + !await _storeRepository.InternalNodePayoutAuthorized(PayoutProcessorSettings.StoreId)) { return false; } diff --git a/BTCPayServer/Services/Stores/StoreRepository.cs b/BTCPayServer/Services/Stores/StoreRepository.cs index 020bad515..277dd1423 100644 --- a/BTCPayServer/Services/Stores/StoreRepository.cs +++ b/BTCPayServer/Services/Stores/StoreRepository.cs @@ -9,6 +9,7 @@ using BTCPayServer.Client; using BTCPayServer.Data; using BTCPayServer.Events; using BTCPayServer.Migrations; +using Dapper; using Microsoft.EntityFrameworkCore; using NBitcoin; using NBitcoin.DataEncoders; @@ -637,6 +638,23 @@ retry: { return ex.InnerException is Npgsql.PostgresException postgres && postgres.SqlState == "40P01"; } + + public async Task InternalNodePayoutAuthorized(string storeId) + { + using var ctx = _ContextFactory.CreateContext(); + return (await ctx.Database.GetDbConnection().ExecuteScalarAsync(""" + SELECT TRUE + FROM "UserStore" us + JOIN "StoreRoles" sr ON sr."Id" = us."Role" + JOIN "AspNetUserRoles" ur ON us."ApplicationUserId" = ur."UserId" + JOIN "AspNetRoles" r ON ur."RoleId" = r."Id" + WHERE + us."StoreDataId"=@storeId AND + r."NormalizedName"='SERVERADMIN' AND + 'btcpay.store.canmodifystoresettings' = ANY(sr."Permissions") + LIMIT 1; + """, new { storeId })) is true; + } } public record StoreRoleId diff --git a/BTCPayServer/Services/UserService.cs b/BTCPayServer/Services/UserService.cs index 9b8bffb0d..1496c3fb5 100644 --- a/BTCPayServer/Services/UserService.cs +++ b/BTCPayServer/Services/UserService.cs @@ -160,13 +160,6 @@ namespace BTCPayServer.Services return res.Succeeded; } - public async Task IsAdminUser(string userId) - { - using var scope = _serviceProvider.CreateScope(); - var userManager = scope.ServiceProvider.GetRequiredService>(); - return Roles.HasServerAdmin(await userManager.GetRolesAsync(new ApplicationUser() { Id = userId })); - } - public async Task IsAdminUser(ApplicationUser user) { using var scope = _serviceProvider.CreateScope();