mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
141 lines
5.7 KiB
C#
141 lines
5.7 KiB
C#
#nullable enable
|
|
using System.Linq;
|
|
using System.Text.Encodings.Web;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using BTCPayServer.Data;
|
|
using BTCPayServer.Events;
|
|
using BTCPayServer.HostedServices;
|
|
using BTCPayServer.Logging;
|
|
using BTCPayServer.Services;
|
|
using BTCPayServer.Services.Notifications;
|
|
using BTCPayServer.Services.Notifications.Blobs;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Newtonsoft.Json.Linq;
|
|
using QRCoder;
|
|
|
|
namespace BTCPayServer.Plugins.Emails.HostedServices;
|
|
|
|
public class UserEventHostedService(
|
|
EventAggregator eventAggregator,
|
|
UserManager<ApplicationUser> userManager,
|
|
ISettingsAccessor<ServerSettings> serverSettings,
|
|
NotificationSender notificationSender,
|
|
Logs logs)
|
|
: EventHostedServiceBase(eventAggregator, logs)
|
|
{
|
|
public UserManager<ApplicationUser> UserManager { get; } = userManager;
|
|
|
|
protected override void SubscribeToEvents()
|
|
{
|
|
SubscribeAny<UserEvent>();
|
|
}
|
|
|
|
public static string GetQrCodeImg(string data)
|
|
{
|
|
using var qrGenerator = new QRCodeGenerator();
|
|
using var qrCodeData = qrGenerator.CreateQrCode(data, QRCodeGenerator.ECCLevel.Q);
|
|
using var qrCode = new Base64QRCode(qrCodeData);
|
|
var base64 = qrCode.GetGraphic(20);
|
|
return $"<img src='data:image/png;base64,{base64}' alt='{HtmlEncoder.Default.Encode(data)}' width='320' height='320'/>";
|
|
}
|
|
|
|
protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken)
|
|
{
|
|
var user = (evt as UserEvent)?.User;
|
|
if (user is null) return;
|
|
switch (evt)
|
|
{
|
|
case UserEvent.Registered ev:
|
|
var requiresApproval = user is { RequiresApproval: true, Approved: false };
|
|
var requiresEmailConfirmation = user is { RequiresEmailConfirmation: true, EmailConfirmed: false };
|
|
|
|
// send notification if the user does not require email confirmation.
|
|
// inform admins only about qualified users and not annoy them with bot registrations.
|
|
if (requiresApproval && !requiresEmailConfirmation)
|
|
{
|
|
await NotifyAdminsAboutUserRequiringApproval(user, ev.ApprovalLink);
|
|
}
|
|
|
|
// set callback result and send email to user
|
|
if (ev is UserEvent.Invited invited)
|
|
{
|
|
if (invited.SendInvitationEmail)
|
|
EventAggregator.Publish(await CreateTriggerEvent(ServerMailTriggers.InvitePending,
|
|
new JObject()
|
|
{
|
|
["InvitationLink"] = HtmlEncoder.Default.Encode(invited.InvitationLink),
|
|
["InvitationLinkQR"] = GetQrCodeImg(invited.InvitationLink)
|
|
}, user));
|
|
}
|
|
else if (requiresEmailConfirmation)
|
|
{
|
|
EventAggregator.Publish(new UserEvent.ConfirmationEmailRequested(user, ev.ConfirmationEmailLink));
|
|
}
|
|
break;
|
|
case UserEvent.ConfirmationEmailRequested confReq:
|
|
EventAggregator.Publish(await CreateTriggerEvent(ServerMailTriggers.EmailConfirm,
|
|
new JObject()
|
|
{
|
|
["ConfirmLink"] = HtmlEncoder.Default.Encode(confReq.ConfirmLink)
|
|
}, user));
|
|
break;
|
|
|
|
case UserEvent.PasswordResetRequested pwResetEvent:
|
|
EventAggregator.Publish(await CreateTriggerEvent(ServerMailTriggers.PasswordReset,
|
|
new JObject()
|
|
{
|
|
["ResetLink"] = HtmlEncoder.Default.Encode(pwResetEvent.ResetLink)
|
|
}, user));
|
|
break;
|
|
|
|
case UserEvent.Approved approvedEvent:
|
|
if (!user.Approved) break;
|
|
EventAggregator.Publish(await CreateTriggerEvent(ServerMailTriggers.ApprovalConfirmed,
|
|
new JObject()
|
|
{
|
|
["LoginLink"] = HtmlEncoder.Default.Encode(approvedEvent.LoginLink)
|
|
}, user));
|
|
|
|
break;
|
|
|
|
case UserEvent.ConfirmedEmail confirmedEvent when user is { RequiresApproval: true, Approved: false, EmailConfirmed: true }:
|
|
await NotifyAdminsAboutUserRequiringApproval(user, confirmedEvent.ApprovalLink);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private async Task NotifyAdminsAboutUserRequiringApproval(ApplicationUser user, string approvalLink)
|
|
{
|
|
await notificationSender.SendNotification(new AdminScope(), new NewUserRequiresApprovalNotification(user));
|
|
EventAggregator.Publish(await CreateTriggerEvent(ServerMailTriggers.ApprovalRequest,
|
|
new JObject()
|
|
{
|
|
["ApprovalLink"] = HtmlEncoder.Default.Encode(approvalLink)
|
|
}, user));
|
|
}
|
|
|
|
private async Task<TriggerEvent> CreateTriggerEvent(string trigger, JObject model, ApplicationUser user)
|
|
{
|
|
var admins = await UserManager.GetUsersInRoleAsync(Roles.ServerAdmin);
|
|
var adminMailboxes = string.Join(", ", admins.Select(a => a.GetMailboxAddress().ToString()).ToArray());
|
|
model["Admins"] = new JObject()
|
|
{
|
|
["MailboxAddresses"] = adminMailboxes,
|
|
};
|
|
model["User"] = new JObject()
|
|
{
|
|
["Name"] = user.UserName,
|
|
["Email"] = user.Email,
|
|
["MailboxAddress"] = user.GetMailboxAddress().ToString(),
|
|
};
|
|
model["Branding"] = new JObject()
|
|
{
|
|
["ServerName"] = serverSettings.Settings.ServerName ?? "BTCPay Server",
|
|
["ContactUrl"] = serverSettings.Settings.ContactUrl,
|
|
};
|
|
var evt = new TriggerEvent(null, trigger, model, null);
|
|
return evt;
|
|
}
|
|
}
|