Use attribute to map notifcations to their string

This commit is contained in:
nicolas.dorier 2020-06-15 17:05:12 +09:00
parent 9070b475ea
commit 7cdfa7d4c5
No known key found for this signature in database
GPG key ID: 6618763EF09186FE
8 changed files with 49 additions and 15 deletions

View file

@ -47,7 +47,7 @@ namespace BTCPayServer.Controllers
.OrderByDescending(a => a.Created)
.Skip(skip).Take(count)
.Where(a => a.ApplicationUserId == userId)
.Select(a => a.ViewModel())
.Select(a => a.ToViewModel())
.ToList(),
Total = _db.Notifications.Where(a => a.ApplicationUserId == userId).Count()
};

View file

@ -30,22 +30,26 @@ namespace BTCPayServer.Models.NotificationViewModels
public static class NotificationViewModelExt
{
public static NotificationViewModel ViewModel(this NotificationData data)
static Dictionary<string, Type> _NotificationTypes;
static NotificationViewModelExt()
{
var baseType = typeof(BaseNotification);
_NotificationTypes = Assembly.GetExecutingAssembly()
.GetTypes()
.Select(t => (t, NotificationType: t.GetCustomAttribute<NotificationAttribute>()?.NotificationType))
.Where(t => t.NotificationType is string)
.ToDictionary(o => o.NotificationType, o => o.t);
}
var fullTypeName = baseType.FullName.Replace(nameof(BaseNotification), data.NotificationType, StringComparison.OrdinalIgnoreCase);
var parsedType = baseType.Assembly.GetType(fullTypeName);
var casted = (BaseNotification)JsonConvert.DeserializeObject(ZipUtils.Unzip(data.Blob), parsedType);
public static NotificationViewModel ToViewModel(this NotificationData data)
{
var casted = (BaseNotification)JsonConvert.DeserializeObject(ZipUtils.Unzip(data.Blob), _NotificationTypes[data.NotificationType]);
var obj = new NotificationViewModel
{
Id = data.Id,
Created = data.Created,
Seen = data.Seen
};
casted.FillViewModel(ref obj);
casted.FillViewModel(obj);
return obj;
}

View file

@ -10,6 +10,6 @@ namespace BTCPayServer.Services.Notifications.Blobs
// IndexViewModel.cs#32
public abstract class BaseNotification
{
public abstract void FillViewModel(ref NotificationViewModel data);
public abstract void FillViewModel(NotificationViewModel data);
}
}

View file

@ -4,9 +4,9 @@ using Newtonsoft.Json;
namespace BTCPayServer.Services.Notifications.Blobs
{
[Notification("newversion")]
internal class NewVersionNotification : BaseNotification
{
internal override string NotificationType => "NewVersionNotification";
public NewVersionNotification()
{
@ -17,7 +17,7 @@ namespace BTCPayServer.Services.Notifications.Blobs
}
public string Version { get; set; }
public override void FillViewModel(ref NotificationViewModel vm)
public override void FillViewModel(NotificationViewModel vm)
{
vm.Body = $"New version {Version} released!";
vm.ActionLink = $"https://github.com/btcpayserver/btcpayserver/releases/tag/v{Version}";

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BTCPayServer.Services.Notifications.Blobs
{
[AttributeUsage(AttributeTargets.Class)]
public class NotificationAttribute : Attribute
{
public NotificationAttribute(string notificationType)
{
NotificationType = notificationType;
}
public string NotificationType { get; }
}
}

View file

@ -55,7 +55,7 @@ namespace BTCPayServer.Services.Notifications
.Where(a => a.ApplicationUserId == userId && !a.Seen)
.OrderByDescending(a => a.Created)
.Take(5)
.Select(a => a.ViewModel())
.Select(a => a.ToViewModel())
.ToList();
}
catch (System.IO.InvalidDataException)

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using BTCPayServer.Data;
using BTCPayServer.Events;
@ -24,6 +26,10 @@ namespace BTCPayServer.Services.Notifications
public async Task SendNotification(NotificationScope scope, BaseNotification notification)
{
if (scope == null)
throw new ArgumentNullException(nameof(scope));
if (notification == null)
throw new ArgumentNullException(nameof(notification));
var users = await GetUsers(scope);
using (var db = _contextFactory.CreateContext())
{
@ -35,7 +41,7 @@ namespace BTCPayServer.Services.Notifications
Id = Guid.NewGuid().ToString(),
Created = DateTimeOffset.UtcNow,
ApplicationUserId = uid,
NotificationType = notification.NotificationType,
NotificationType = GetNotificationTypeString(notification.GetType()),
Blob = ZipUtils.Zip(obj),
Seen = false
};
@ -46,6 +52,14 @@ namespace BTCPayServer.Services.Notifications
}
}
private string GetNotificationTypeString(Type type)
{
var str = type.GetCustomAttribute<NotificationAttribute>()?.NotificationType;
if (str is null)
throw new NotSupportedException($"{type} is not a notification");
return str;
}
private async Task<string[]> GetUsers(NotificationScope scope)
{
if (scope is AdminScope)

View file

@ -2,7 +2,6 @@
@inject BTCPayServer.HostedServices.CssThemeManager themeManager
@{
ViewData["Title"] = "Log in";
Layout = "_LayoutWelcome";
}
@if (TempData.HasStatusMessage())
{