mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2026-02-01 04:14:28 +01:00
Merge branch 'validate-scope'
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface IBTCPayServerClientFactory
|
||||
{
|
||||
Task<BTCPayServerClient> Create(string userId, params string[] storeIds);
|
||||
Task<BTCPayServerClient> Create(string userId, string[] storeIds, HttpContext httpRequest);
|
||||
}
|
||||
}
|
||||
@@ -169,6 +169,10 @@ namespace BTCPayServer.Tests
|
||||
#endif
|
||||
var conf = confBuilder.Build();
|
||||
_Host = new WebHostBuilder()
|
||||
.UseDefaultServiceProvider(options =>
|
||||
{
|
||||
options.ValidateScopes = true;
|
||||
})
|
||||
.UseConfiguration(conf)
|
||||
.UseContentRoot(FindBTCPayServerDirectory())
|
||||
.UseWebRoot(Path.Combine(FindBTCPayServerDirectory(), "wwwroot"))
|
||||
@@ -284,10 +288,7 @@ namespace BTCPayServer.Tests
|
||||
public string IntegratedLightning { get; internal set; }
|
||||
public bool InContainer { get; internal set; }
|
||||
|
||||
public T GetService<T>()
|
||||
{
|
||||
return _Host.Services.GetRequiredService<T>();
|
||||
}
|
||||
public T GetService<T>() => _Host.Services.GetRequiredService<T>();
|
||||
|
||||
public IServiceProvider ServiceProvider => _Host.Services;
|
||||
|
||||
|
||||
@@ -52,41 +52,6 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
}
|
||||
|
||||
[Fact(Timeout = TestTimeout)]
|
||||
[Trait("Integration", "Integration")]
|
||||
[Trait("Lightning", "Lightning")]
|
||||
public async Task LocalClientTests()
|
||||
{
|
||||
using var tester = CreateServerTester();
|
||||
tester.ActivateLightning();
|
||||
await tester.StartAsync();
|
||||
await tester.EnsureChannelsSetup();
|
||||
var user = tester.NewAccount();
|
||||
await user.GrantAccessAsync();
|
||||
await user.MakeAdmin();
|
||||
user.RegisterLightningNode("BTC", LightningConnectionType.CLightning);
|
||||
var factory = tester.PayTester.GetService<IBTCPayServerClientFactory>();
|
||||
Assert.NotNull(factory);
|
||||
var client = await factory.Create(user.UserId, user.StoreId);
|
||||
await client.GetCurrentUser();
|
||||
await client.GetStores();
|
||||
var store = await client.GetStore(user.StoreId);
|
||||
Assert.NotNull(store);
|
||||
var addr = await client.GetLightningDepositAddress(user.StoreId, "BTC");
|
||||
Assert.NotNull(BitcoinAddress.Create(addr, Network.RegTest));
|
||||
|
||||
await user.CreateStoreAsync();
|
||||
var store1 = user.StoreId;
|
||||
await user.CreateStoreAsync();
|
||||
var store2 = user.StoreId;
|
||||
var store1Client = await factory.Create(null, store1);
|
||||
var store2Client = await factory.Create(null, store2);
|
||||
var store1Res = await store1Client.GetStore(store1);
|
||||
var store2Res = await store2Client.GetStore(store2);
|
||||
Assert.Equal(store1, store1Res.Id);
|
||||
Assert.Equal(store2, store2Res.Id);
|
||||
}
|
||||
|
||||
[Fact(Timeout = TestTimeout)]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task MissingPermissionTest()
|
||||
|
||||
@@ -28,6 +28,7 @@ using ExchangeSharp;
|
||||
using LNURL;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Playwright;
|
||||
using static Microsoft.Playwright.Assertions;
|
||||
using NBitcoin;
|
||||
@@ -200,7 +201,8 @@ namespace BTCPayServer.Tests
|
||||
await s.Page.FillAsync("#Email", changedEmail);
|
||||
await s.ClickPagePrimary();
|
||||
await s.FindAlertMessage();
|
||||
var manager = tester.PayTester.GetService<UserManager<ApplicationUser>>();
|
||||
using var scope = tester.PayTester.ServiceProvider.CreateScope();
|
||||
var manager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
|
||||
Assert.NotNull(await manager.FindByNameAsync(changedEmail));
|
||||
Assert.NotNull(await manager.FindByEmailAsync(changedEmail));
|
||||
}
|
||||
@@ -1242,13 +1244,9 @@ namespace BTCPayServer.Tests
|
||||
await s.LogIn(admin.RegisterDetails.Email, admin.RegisterDetails.Password);
|
||||
await s.GoToHome();
|
||||
|
||||
await TestUtils.EventuallyAsync(async () =>
|
||||
{
|
||||
Assert.Equal("1", await s.Page.Locator("#NotificationsBadge").TextContentAsync());
|
||||
});
|
||||
|
||||
await Expect(s.Page.Locator("#NotificationsBadge")).ToContainTextAsync("1");
|
||||
await s.Page.ClickAsync("#NotificationsHandle");
|
||||
await s.Page.Locator($"#NotificationsList .notification:has-text('New user {unapproved.RegisterDetails.Email} requires approval')").WaitForAsync();
|
||||
await Expect(s.Page.Locator("#NotificationsList .notification")).ToContainTextAsync($"New user {unapproved.RegisterDetails.Email} requires approval");
|
||||
await s.Page.ClickAsync("#NotificationsMarkAllAsSeen");
|
||||
|
||||
await s.GoToServer(ServerNavPages.Policies);
|
||||
@@ -1754,8 +1752,8 @@ namespace BTCPayServer.Tests
|
||||
opening = s.Page.Context.WaitForPageAsync();
|
||||
await s.Page.ClickAsync("text=View");
|
||||
newPage = await opening;
|
||||
await Expect(newPage.Locator("body")).ToContainTextAsync("Description Edit");
|
||||
await Expect(newPage.Locator("body")).ToContainTextAsync("PP1 Edited");
|
||||
await Expect(newPage.GetByTestId("description")).ToContainTextAsync("Description Edit");
|
||||
await Expect(newPage.GetByTestId("title")).ToContainTextAsync("PP1 Edited");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -2288,22 +2286,23 @@ namespace BTCPayServer.Tests
|
||||
await s.FindAlertMessage();
|
||||
Assert.DoesNotContain("Unarchive", await s.Page.Locator("#btn-archive-toggle").InnerTextAsync());
|
||||
await s.GoToInvoices(storeId);
|
||||
await s.Page.WaitForSelectorAsync($"tr[id=invoice_{invoiceId}]");
|
||||
Assert.Contains(invoiceId, await s.Page.ContentAsync());
|
||||
|
||||
// archive via list
|
||||
await s.Page.Locator($".mass-action-select[value=\"{invoiceId}\"]").ClickAsync();
|
||||
await s.Page.Locator("#ArchiveSelected").ClickAsync();
|
||||
Assert.Contains("1 invoice archived", await (await s.FindAlertMessage()).InnerTextAsync());
|
||||
await s.Page.ClickAsync($".mass-action-select[value=\"{invoiceId}\"]");
|
||||
await s.Page.ClickAsync("#ArchiveSelected");
|
||||
await s.FindAlertMessage(partialText: "1 invoice archived");
|
||||
Assert.DoesNotContain(invoiceId, await s.Page.ContentAsync());
|
||||
|
||||
// unarchive via list
|
||||
await s.Page.Locator("#StatusOptionsToggle").ClickAsync();
|
||||
await s.Page.Locator("#StatusOptionsIncludeArchived").ClickAsync();
|
||||
Assert.Contains(invoiceId, await s.Page.ContentAsync());
|
||||
await s.Page.Locator($".mass-action-select[value=\"{invoiceId}\"]").ClickAsync();
|
||||
await s.Page.Locator("#UnarchiveSelected").ClickAsync();
|
||||
Assert.Contains("1 invoice unarchived", await (await s.FindAlertMessage()).InnerTextAsync());
|
||||
Assert.Contains(invoiceId, await s.Page.ContentAsync());
|
||||
await s.Page.ClickAsync($".mass-action-select[value=\"{invoiceId}\"]");
|
||||
await s.Page.ClickAsync("#UnarchiveSelected");
|
||||
await s.FindAlertMessage(partialText: "1 invoice unarchived");
|
||||
await s.Page.WaitForSelectorAsync($"tr[id=invoice_{invoiceId}]");
|
||||
|
||||
// When logout out we should not be able to access store and invoice details
|
||||
await s.GoToUrl("/account");
|
||||
|
||||
@@ -26,6 +26,7 @@ using BTCPayServer.Services.Wallets;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NBitcoin;
|
||||
using NBitcoin.DataEncoders;
|
||||
using NBitcoin.Payment;
|
||||
@@ -58,13 +59,14 @@ namespace BTCPayServer.Tests
|
||||
|
||||
public async Task MakeAdmin(bool isAdmin = true)
|
||||
{
|
||||
var userManager = parent.PayTester.GetService<UserManager<ApplicationUser>>();
|
||||
using var scope = parent.PayTester.ServiceProvider.CreateScope();
|
||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
|
||||
var u = await userManager.FindByIdAsync(UserId);
|
||||
if (isAdmin)
|
||||
await userManager.AddToRoleAsync(u, Roles.ServerAdmin);
|
||||
else
|
||||
await userManager.RemoveFromRoleAsync(u, Roles.ServerAdmin);
|
||||
IsAdmin = true;
|
||||
IsAdmin = isAdmin;
|
||||
}
|
||||
|
||||
public Task<BTCPayServerClient> CreateClient()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,6 @@ namespace BTCPayServer.Controllers
|
||||
public partial class UIInvoiceController : Controller
|
||||
{
|
||||
readonly InvoiceRepository _InvoiceRepository;
|
||||
private readonly WalletRepository _walletRepository;
|
||||
readonly RateFetcher _RateProvider;
|
||||
readonly StoreRepository _StoreRepository;
|
||||
readonly UserManager<ApplicationUser> _UserManager;
|
||||
@@ -71,14 +70,12 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
public UIInvoiceController(
|
||||
InvoiceRepository invoiceRepository,
|
||||
WalletRepository walletRepository,
|
||||
DisplayFormatter displayFormatter,
|
||||
CurrencyNameTable currencyNameTable,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
RateFetcher rateProvider,
|
||||
StoreRepository storeRepository,
|
||||
EventAggregator eventAggregator,
|
||||
ContentSecurityPolicies csp,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
PayoutMethodHandlerDictionary payoutHandlers,
|
||||
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||
@@ -105,7 +102,6 @@ namespace BTCPayServer.Controllers
|
||||
_CurrencyNameTable = currencyNameTable ?? throw new ArgumentNullException(nameof(currencyNameTable));
|
||||
_StoreRepository = storeRepository ?? throw new ArgumentNullException(nameof(storeRepository));
|
||||
_InvoiceRepository = invoiceRepository ?? throw new ArgumentNullException(nameof(invoiceRepository));
|
||||
_walletRepository = walletRepository;
|
||||
_RateProvider = rateProvider ?? throw new ArgumentNullException(nameof(rateProvider));
|
||||
_UserManager = userManager;
|
||||
_EventAggregator = eventAggregator;
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using BTCPayServer.Lightning;
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
{
|
||||
public class BoltInvoiceClaimDestination : ILightningLikeLikeClaimDestination
|
||||
public class BoltInvoiceClaimDestination(string bolt11, BOLT11PaymentRequest paymentRequest) : ILightningLikeLikeClaimDestination
|
||||
{
|
||||
public BoltInvoiceClaimDestination(string bolt11, BOLT11PaymentRequest paymentRequest)
|
||||
{
|
||||
Bolt11 = bolt11 ?? throw new ArgumentNullException(nameof(bolt11));
|
||||
PaymentRequest = paymentRequest;
|
||||
PaymentHash = paymentRequest.Hash;
|
||||
Amount = paymentRequest.MinimumAmount.MilliSatoshi == LightMoney.Zero ? null: paymentRequest.MinimumAmount.ToDecimal(LightMoneyUnit.BTC);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Bolt11;
|
||||
}
|
||||
public string Bolt11 { get; }
|
||||
public BOLT11PaymentRequest PaymentRequest { get; }
|
||||
public uint256 PaymentHash { get; }
|
||||
public string Bolt11 { get; } = bolt11 ?? throw new ArgumentNullException(nameof(bolt11));
|
||||
public BOLT11PaymentRequest PaymentRequest { get; } = paymentRequest;
|
||||
public uint256 PaymentHash { get; } = paymentRequest.Hash;
|
||||
public string Id => PaymentHash.ToString();
|
||||
public decimal? Amount { get; }
|
||||
public decimal? Amount { get; } = paymentRequest.MinimumAmount.MilliSatoshi == LightMoney.Zero ? null: paymentRequest.MinimumAmount.ToDecimal(LightMoneyUnit.BTC);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -14,13 +12,10 @@ using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Bitcoin;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Payouts;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using LNURL;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MimeKit;
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
@@ -32,7 +27,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
public PaymentMethodId PaymentMethodId { get; }
|
||||
|
||||
private readonly IOptions<LightningNetworkOptions> _options;
|
||||
private PaymentMethodHandlerDictionary _paymentHandlers;
|
||||
private readonly PaymentMethodHandlerDictionary _paymentHandlers;
|
||||
|
||||
public BTCPayNetwork Network { get; }
|
||||
public string[] DefaultRateRules => Network.DefaultRateRules;
|
||||
@@ -43,15 +38,13 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
public const string LightningLikePayoutHandlerClearnetNamedClient =
|
||||
nameof(LightningLikePayoutHandlerClearnetNamedClient);
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly UserService _userService;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
|
||||
public LightningLikePayoutHandler(
|
||||
PayoutMethodId payoutMethodId,
|
||||
IOptions<LightningNetworkOptions> options,
|
||||
BTCPayNetwork network,
|
||||
PaymentMethodHandlerDictionary paymentHandlers,
|
||||
IHttpClientFactory httpClientFactory, UserService userService, IAuthorizationService authorizationService)
|
||||
IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_paymentHandlers = paymentHandlers;
|
||||
Network = network;
|
||||
@@ -59,8 +52,6 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
_options = options;
|
||||
PaymentMethodId = PaymentTypes.LN.GetPaymentMethodId(network.CryptoCode);
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_userService = userService;
|
||||
_authorizationService = authorizationService;
|
||||
Currency = network.CryptoCode;
|
||||
}
|
||||
|
||||
@@ -112,7 +103,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
}
|
||||
|
||||
var result =
|
||||
BOLT11PaymentRequest.TryParse(destination, out var invoice, Network.NBitcoinNetwork)
|
||||
BOLT11PaymentRequest.TryParse(destination, out var invoice, Network.NBitcoinNetwork) && invoice is not null
|
||||
? new BoltInvoiceClaimDestination(destination, invoice)
|
||||
: null;
|
||||
|
||||
|
||||
@@ -73,7 +73,6 @@ using BTCPayServer.Payouts;
|
||||
using ExchangeSharp;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.AspNetCore.Mvc.Localization;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BTCPayServer.Hosting
|
||||
@@ -427,7 +426,7 @@ o.GetRequiredService<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
|
||||
services.AddSingleton<PayoutMethodHandlerDictionary>();
|
||||
|
||||
services.AddSingleton<NotificationManager>();
|
||||
services.AddScoped<NotificationSender>();
|
||||
services.AddSingleton<NotificationSender>();
|
||||
|
||||
RegisterExchangeRecommendations(services);
|
||||
services.AddSingleton<DefaultRulesCollection>();
|
||||
@@ -481,10 +480,6 @@ o.GetRequiredService<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
|
||||
services.AddSingleton<EmailSenderFactory>();
|
||||
services.AddSingleton<InvoiceActivator>();
|
||||
|
||||
//create a simple client which hooks up to the http scope
|
||||
services.AddScoped<BTCPayServerClient, LocalBTCPayServerClient>();
|
||||
//also provide a factory that can impersonate user/store id
|
||||
services.AddSingleton<IBTCPayServerClientFactory, BTCPayServerClientFactory>();
|
||||
services.AddPayoutProcesors();
|
||||
services.AddForms();
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Notifications;
|
||||
using BTCPayServer.Services.Notifications.Blobs;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using QRCoder;
|
||||
|
||||
@@ -18,14 +19,12 @@ namespace BTCPayServer.Plugins.Emails.HostedServices;
|
||||
|
||||
public class UserEventHostedService(
|
||||
EventAggregator eventAggregator,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
IServiceScopeFactory serviceScopeFactory,
|
||||
ISettingsAccessor<ServerSettings> serverSettings,
|
||||
NotificationSender notificationSender,
|
||||
Logs logs)
|
||||
: EventHostedServiceBase(eventAggregator, logs)
|
||||
{
|
||||
public UserManager<ApplicationUser> UserManager { get; } = userManager;
|
||||
|
||||
protected override void SubscribeToEvents()
|
||||
{
|
||||
SubscribeAny<UserEvent>();
|
||||
@@ -117,7 +116,9 @@ public class UserEventHostedService(
|
||||
|
||||
private async Task<TriggerEvent> CreateTriggerEvent(string trigger, JObject model, ApplicationUser user)
|
||||
{
|
||||
var admins = await UserManager.GetUsersInRoleAsync(Roles.ServerAdmin);
|
||||
using var scope = serviceScopeFactory.CreateScope();
|
||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
|
||||
var admins = await userManager.GetUsersInRoleAsync(Roles.ServerAdmin);
|
||||
var adminMailboxes = string.Join(", ", admins.Select(a => a.GetMailboxAddress().ToString()).ToArray());
|
||||
model["Admins"] = new JObject()
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@ using BTCPayServer.Services.Rates;
|
||||
using Dapper;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using static BTCPayServer.Data.Subscriptions.SubscriberData;
|
||||
@@ -30,7 +31,7 @@ public class SubscriptionHostedService(
|
||||
EventAggregator eventAggregator,
|
||||
ApplicationDbContextFactory applicationDbContextFactory,
|
||||
SettingsRepository settingsRepository,
|
||||
UIInvoiceController invoiceController,
|
||||
IServiceScopeFactory scopeFactory,
|
||||
CurrencyNameTable currencyNameTable,
|
||||
LinkGenerator linkGenerator,
|
||||
Logs logger) : EventHostedServiceBase(eventAggregator, logger), IPeriodicTask
|
||||
@@ -162,6 +163,8 @@ public class SubscriptionHostedService(
|
||||
|
||||
if (amount > 0)
|
||||
{
|
||||
using var scope = scopeFactory.CreateScope();
|
||||
var invoiceController = scope.ServiceProvider.GetRequiredService<UIInvoiceController>();
|
||||
var request = await invoiceController.CreateInvoiceCoreRaw(new()
|
||||
{
|
||||
Currency = plan.Currency,
|
||||
|
||||
@@ -26,6 +26,10 @@ public class BTCPayServerSecurityStampValidator(
|
||||
ConcurrentDictionary<string, DateTimeOffset> _DisabledUsers = new ConcurrentDictionary<string, DateTimeOffset>();
|
||||
public bool HasAny => !_DisabledUsers.IsEmpty;
|
||||
|
||||
/// <summary>
|
||||
/// Note that you also need to invalidate the security stamp of the user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
public void Add(string user)
|
||||
{
|
||||
_DisabledUsers.TryAdd(user, DateTimeOffset.UtcNow);
|
||||
|
||||
@@ -6,6 +6,7 @@ using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BTCPayServer.Services.Notifications
|
||||
{
|
||||
@@ -13,25 +14,15 @@ namespace BTCPayServer.Services.Notifications
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
}
|
||||
public class NotificationSender
|
||||
public class NotificationSender(ApplicationDbContextFactory contextFactory, IServiceScopeFactory scopeFactory, NotificationManager notificationManager)
|
||||
{
|
||||
private readonly ApplicationDbContextFactory _contextFactory;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly NotificationManager _notificationManager;
|
||||
|
||||
public NotificationSender(ApplicationDbContextFactory contextFactory, UserManager<ApplicationUser> userManager, NotificationManager notificationManager)
|
||||
{
|
||||
_contextFactory = contextFactory;
|
||||
_userManager = userManager;
|
||||
_notificationManager = notificationManager;
|
||||
}
|
||||
|
||||
public async Task SendNotification(INotificationScope scope, BaseNotification notification)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(scope);
|
||||
ArgumentNullException.ThrowIfNull(notification);
|
||||
var users = await GetUsers(scope, notification.Identifier);
|
||||
await using (var db = _contextFactory.CreateContext())
|
||||
await using (var db = contextFactory.CreateContext())
|
||||
{
|
||||
foreach (var uid in users)
|
||||
{
|
||||
@@ -48,7 +39,7 @@ namespace BTCPayServer.Services.Notifications
|
||||
}
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
_notificationManager.InvalidateNotificationCache(users);
|
||||
notificationManager.InvalidateNotificationCache(users);
|
||||
}
|
||||
|
||||
public BaseNotification GetBaseNotification(NotificationData notificationData)
|
||||
@@ -58,7 +49,7 @@ namespace BTCPayServer.Services.Notifications
|
||||
|
||||
private async Task<string[]> GetUsers(INotificationScope scope, string notificationIdentifier)
|
||||
{
|
||||
await using var ctx = _contextFactory.CreateContext();
|
||||
await using var ctx = contextFactory.CreateContext();
|
||||
|
||||
var split = notificationIdentifier.Split('_', StringSplitOptions.None);
|
||||
var terms = new List<string>();
|
||||
@@ -71,8 +62,8 @@ namespace BTCPayServer.Services.Notifications
|
||||
{
|
||||
case AdminScope _:
|
||||
{
|
||||
query = _userManager.GetUsersInRoleAsync(Roles.ServerAdmin).Result.AsQueryable();
|
||||
|
||||
using var s = scopeFactory.CreateScope();
|
||||
query = s.ServiceProvider.GetService<UserManager<ApplicationUser>>().GetUsersInRoleAsync(Roles.ServerAdmin).Result.AsQueryable();
|
||||
break;
|
||||
}
|
||||
case StoreScope s:
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<div class="bg-tile h-100 m-0 p-3 p-sm-5 rounded">
|
||||
@if (!string.IsNullOrWhiteSpace(Model.Title))
|
||||
{
|
||||
<h2 class="h4 mb-3">@Model.Title</h2>
|
||||
<h2 class="h4 mb-3" data-testid="title">@Model.Title</h2>
|
||||
}
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="text-muted text-nowrap" text-translate="true">Start Date</span>
|
||||
@@ -122,7 +122,7 @@
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.Description))
|
||||
{
|
||||
<div class="mt-4">@Safe.Raw(Model.Description)</div>
|
||||
<div class="mt-4" data-testid="description">@Safe.Raw(Model.Description)</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user