diff --git a/BTCPayServer/Controllers/NotificationsController.cs b/BTCPayServer/Controllers/NotificationsController.cs index a3368699d..f2f49aa37 100644 --- a/BTCPayServer/Controllers/NotificationsController.cs +++ b/BTCPayServer/Controllers/NotificationsController.cs @@ -22,13 +22,13 @@ namespace BTCPayServer.Controllers public class NotificationsController : Controller { private readonly ApplicationDbContext _db; - private readonly EventAggregator _eventAggregator; + private readonly NotificationSender _notificationSender; private readonly UserManager _userManager; - public NotificationsController(ApplicationDbContext db, EventAggregator eventAggregator, UserManager userManager) + public NotificationsController(ApplicationDbContext db, NotificationSender notificationSender, UserManager userManager) { _db = db; - _eventAggregator = eventAggregator; + _notificationSender = notificationSender; _userManager = userManager; } @@ -54,7 +54,7 @@ namespace BTCPayServer.Controllers [HttpGet] public async Task Generate() { - _eventAggregator.NoticeNewVersion("1.0.4.4"); + await _notificationSender.NoticeNewVersionAsync("1.0.4.4"); // waiting for event handler to catch up await Task.Delay(1000); return RedirectToAction(nameof(Index)); diff --git a/BTCPayServer/Events/Notifications/NewVersionNotification.cs b/BTCPayServer/Events/Notifications/NewVersionNotification.cs index 71ff7c447..eae69faaa 100644 --- a/BTCPayServer/Events/Notifications/NewVersionNotification.cs +++ b/BTCPayServer/Events/Notifications/NewVersionNotification.cs @@ -4,7 +4,7 @@ using Newtonsoft.Json; namespace BTCPayServer.Events.Notifications { - internal class NewVersionNotification : NotificationEventBase + internal class NewVersionNotification : NotificationBase { public string Version { get; set; } diff --git a/BTCPayServer/Events/Notifications/NotificationEventBase.cs b/BTCPayServer/Events/Notifications/NotificationBase.cs similarity index 79% rename from BTCPayServer/Events/Notifications/NotificationEventBase.cs rename to BTCPayServer/Events/Notifications/NotificationBase.cs index e67d297d2..0a32bcc28 100644 --- a/BTCPayServer/Events/Notifications/NotificationEventBase.cs +++ b/BTCPayServer/Events/Notifications/NotificationBase.cs @@ -8,17 +8,18 @@ namespace BTCPayServer.Events.Notifications // Make sure to keep all NotificationEventBase classes in same namespace // because of dependent initialization and parsing to view models logic // IndexViewModel.cs#32 - internal abstract class NotificationEventBase + internal abstract class NotificationBase { internal virtual string NotificationType { get { return GetType().Name; } } - public NotificationData ToData() + public NotificationData ToData(string applicationUserId) { var obj = JsonConvert.SerializeObject(this); var data = new NotificationData { - Created = DateTimeOffset.UtcNow, + Id = Guid.NewGuid().ToString(), + ApplicationUserId = applicationUserId, NotificationType = NotificationType, Blob = ZipUtils.Zip(obj), Seen = false diff --git a/BTCPayServer/Events/Notifications/NotificationEvent.cs b/BTCPayServer/Events/Notifications/NotificationEvent.cs new file mode 100644 index 000000000..55235fae0 --- /dev/null +++ b/BTCPayServer/Events/Notifications/NotificationEvent.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BTCPayServer.Events.Notifications +{ + internal class NotificationEvent + { + internal string[] ApplicationUserIds { get; set; } + internal NotificationBase Notification { get; set; } + } +} diff --git a/BTCPayServer/Events/Notifications/NotificationsHelperExt.cs b/BTCPayServer/Events/Notifications/NotificationsHelperExt.cs index 82bf0ee50..0702043d1 100644 --- a/BTCPayServer/Events/Notifications/NotificationsHelperExt.cs +++ b/BTCPayServer/Events/Notifications/NotificationsHelperExt.cs @@ -3,17 +3,36 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using BTCPayServer.Data; +using Microsoft.AspNetCore.Identity; namespace BTCPayServer.Events.Notifications { - public static class NotificationsHelperExt + public class NotificationSender { - public static void NoticeNewVersion(this EventAggregator aggr, string version) + private readonly UserManager _userManager; + private readonly EventAggregator _eventAggregator; + + public NotificationSender(UserManager userManager, EventAggregator eventAggregator) { - aggr.Publish(new NewVersionNotification + _userManager = userManager; + _eventAggregator = eventAggregator; + } + + internal async Task NoticeNewVersionAsync(string version) + { + var admins = await _userManager.GetUsersInRoleAsync(Roles.ServerAdmin); + var adminUids = admins.Select(a => a.Id).ToArray(); + var evt = new NotificationEvent { - Version = version - }); + ApplicationUserIds = adminUids, + Notification = new NewVersionNotification + { + Version = version + } + }; + + _eventAggregator.Publish(evt); } } } diff --git a/BTCPayServer/HostedServices/NotificationDbSaver.cs b/BTCPayServer/HostedServices/NotificationDbSaver.cs index 40dd86dfe..00fb6e20d 100644 --- a/BTCPayServer/HostedServices/NotificationDbSaver.cs +++ b/BTCPayServer/HostedServices/NotificationDbSaver.cs @@ -15,58 +15,32 @@ namespace BTCPayServer.HostedServices { public class NotificationDbSaver : EventHostedServiceBase { - private readonly UserManager _UserManager; private readonly ApplicationDbContextFactory _ContextFactory; - public NotificationDbSaver(UserManager userManager, - ApplicationDbContextFactory contextFactory, + public NotificationDbSaver(ApplicationDbContextFactory contextFactory, EventAggregator eventAggregator) : base(eventAggregator) { - _UserManager = userManager; _ContextFactory = contextFactory; } protected override void SubscribeToEvents() { - SubscribeAllChildrenOfNotificationEventBase(); + Subscribe(); base.SubscribeToEvents(); } - // subscribe all children of NotificationEventBase - public void SubscribeAllChildrenOfNotificationEventBase() - { - var method = this.GetType().GetMethod(nameof(SubscribeHelper)); - var notificationTypes = this.GetType().Assembly.GetTypes().Where(a => typeof(NotificationEventBase).IsAssignableFrom(a)); - foreach (var notif in notificationTypes) - { - var generic = method.MakeGenericMethod(notif); - generic.Invoke(this, null); - } - } - - // we need publicly accessible method for reflection invoke - public void SubscribeHelper() => base.Subscribe(); - protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken) { - if (evt is NotificationEventBase) + var casted = evt as NotificationEvent; + using (var db = _ContextFactory.CreateContext()) { - var data = (evt as NotificationEventBase).ToData(); - - var admins = await _UserManager.GetUsersInRoleAsync(Roles.ServerAdmin); - - using (var db = _ContextFactory.CreateContext()) + foreach (var uid in casted.ApplicationUserIds) { - foreach (var admin in admins) - { - data.Id = Guid.NewGuid().ToString(); - data.ApplicationUserId = admin.Id; - - db.Notifications.Add(data); - } - - await db.SaveChangesAsync(); + var data = casted.Notification.ToData(uid); + db.Notifications.Add(data); } + + await db.SaveChangesAsync(); } } } diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index 7697fc35f..59ff21e31 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -46,6 +46,7 @@ using BTCPayServer.Security.Bitpay; using Serilog; using BTCPayServer.Security.GreenField; using BTCPayServer.Services.Labels; +using BTCPayServer.Events.Notifications; namespace BTCPayServer.Hosting { @@ -202,6 +203,7 @@ namespace BTCPayServer.Hosting services.AddSingleton(); services.AddScoped(); + services.AddScoped(); services.AddSingleton(); services.AddSingleton(); diff --git a/BTCPayServer/Models/NotificationViewModels/IndexViewModel.cs b/BTCPayServer/Models/NotificationViewModels/IndexViewModel.cs index c33553e6f..0196e1551 100644 --- a/BTCPayServer/Models/NotificationViewModels/IndexViewModel.cs +++ b/BTCPayServer/Models/NotificationViewModels/IndexViewModel.cs @@ -29,10 +29,10 @@ namespace BTCPayServer.Models.NotificationViewModels { public static NotificationViewModel ViewModel(this NotificationData data) { - var baseType = typeof(NotificationEventBase); + var baseType = typeof(NotificationBase); - var typeName = baseType.FullName.Replace(nameof(NotificationEventBase), data.NotificationType, StringComparison.OrdinalIgnoreCase); - var instance = Activator.CreateInstance(baseType.Assembly.GetType(typeName)) as NotificationEventBase; + var typeName = baseType.FullName.Replace(nameof(NotificationBase), data.NotificationType, StringComparison.OrdinalIgnoreCase); + var instance = Activator.CreateInstance(baseType.Assembly.GetType(typeName)) as NotificationBase; return instance.ToViewModel(data); }