@@ -0,0 +1,98 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ROLAC.API.Data;
|
||||
|
||||
namespace ROLAC.API.Services.Notifications;
|
||||
|
||||
/// <summary>
|
||||
/// Supplies the current SMTP/Line settings from the <c>NotificationSetting</c> singleton row,
|
||||
/// caching a snapshot in memory so send paths don't hit the DB on every message. Registered as a
|
||||
/// singleton; the Settings UI calls <see cref="Reload"/> after an edit so changes take effect
|
||||
/// without restarting the API. Falls back to the "Smtp"/"Line" appsettings sections if the row
|
||||
/// has not been seeded yet.
|
||||
/// </summary>
|
||||
public interface INotificationSettingsService
|
||||
{
|
||||
SmtpOptions GetSmtp();
|
||||
LineOptions GetLine();
|
||||
void Reload();
|
||||
}
|
||||
|
||||
public sealed class NotificationSettingsService : INotificationSettingsService
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly IOptions<SmtpOptions> _smtpFallback;
|
||||
private readonly IOptions<LineOptions> _lineFallback;
|
||||
private readonly object _gate = new();
|
||||
|
||||
private SmtpOptions? _smtp;
|
||||
private LineOptions? _line;
|
||||
|
||||
public NotificationSettingsService(
|
||||
IServiceScopeFactory scopeFactory,
|
||||
IOptions<SmtpOptions> smtpFallback,
|
||||
IOptions<LineOptions> lineFallback)
|
||||
{
|
||||
_scopeFactory = scopeFactory;
|
||||
_smtpFallback = smtpFallback;
|
||||
_lineFallback = lineFallback;
|
||||
}
|
||||
|
||||
public SmtpOptions GetSmtp()
|
||||
{
|
||||
EnsureLoaded();
|
||||
return _smtp!;
|
||||
}
|
||||
|
||||
public LineOptions GetLine()
|
||||
{
|
||||
EnsureLoaded();
|
||||
return _line!;
|
||||
}
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
_smtp = null;
|
||||
_line = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureLoaded()
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
if (_smtp is not null && _line is not null)
|
||||
return;
|
||||
|
||||
using var scope = _scopeFactory.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
var row = db.NotificationSettings.AsNoTracking().OrderBy(s => s.Id).FirstOrDefault();
|
||||
|
||||
if (row is null)
|
||||
{
|
||||
// Not seeded yet — use the appsettings values so sends still work.
|
||||
_smtp = _smtpFallback.Value;
|
||||
_line = _lineFallback.Value;
|
||||
return;
|
||||
}
|
||||
|
||||
_smtp = new SmtpOptions
|
||||
{
|
||||
Host = row.SmtpHost,
|
||||
Port = row.SmtpPort,
|
||||
UseSsl = row.SmtpUseSsl,
|
||||
User = row.SmtpUser,
|
||||
Password = row.SmtpPassword,
|
||||
FromAddress = row.FromAddress,
|
||||
FromName = row.FromName,
|
||||
};
|
||||
_line = new LineOptions
|
||||
{
|
||||
ChannelAccessToken = row.LineChannelAccessToken,
|
||||
ChannelSecret = row.LineChannelSecret,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user