This commit is contained in:
2020-07-22 23:02:30 +00:00
parent 9dda0623ba
commit 1223fd2f28
7 changed files with 83 additions and 22 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
@@ -37,6 +38,7 @@ namespace AyaNova.Biz
//temporary list to hold translations as required during delivery
private static Dictionary<long, List<NameIdItem>> _transCache = new Dictionary<long, List<NameIdItem>>();
private static Dictionary<long, long> _UserTranslationIdCache = new Dictionary<long, long>();
////////////////////////////////////////////////////////////////////////////////////////////////
// DoSweep
@@ -100,10 +102,22 @@ namespace AyaNova.Biz
//todo: create message here if not already set?
//todo: generate and attach report here?
//All items have an event date, for non time delayed events it's just the moment it was created
//which will predate this moment now if it's pre-existing
var events = await ct.NotifyEvent.Include(z => z.NotifySubscription).ToListAsync();
log.LogTrace($"Found {events.Count} NotifyEvents to examine for potential delivery");
//cache translations
//Get all subscription unique userId's that aren't inapp deliveries
var usersNeedingTranslations = events.Where(z => z.NotifySubscription.DeliveryMethod != NotifyDeliveryMethod.App).Select(z => z.NotifySubscription.UserId).ToList().Distinct();
foreach (long userid in usersNeedingTranslations)
{
long transId = (await ct.UserOptions.SingleAsync(z => z.UserId == userid)).TranslationId;
_UserTranslationIdCache.Add(userid, transId);
await CacheNotifyEventTypeTranslations(transId);
}
//iterate and deliver
foreach (var notifyevent in events)
{
@@ -149,18 +163,29 @@ namespace AyaNova.Biz
finally
{
log.LogTrace("Notify is done setting to not running state and tagging lastRun timestamp");
_UserTranslationIdCache.Clear();
_transCache.Clear();
lastRun = DateTime.UtcNow;
NotifyIsRunning = false;
}
}
//cache any translations required for email notification
private static async Task CacheNotifyEventTypeTranslations(long translationId){
if(_transCache.ContainsKey(translationId)){
//cache any translations required for email notification
private static async Task CacheNotifyEventTypeTranslations(long translationId)
{
if (_transCache.ContainsKey(translationId))
{
return;
}
_transCache.Add(translationId,AyaNova.Api.Controllers.EnumListController.GetEnumList("NotifyEventType",translationId));
_transCache.Add(translationId, await AyaNova.Api.Controllers.EnumListController.GetEnumList("NotifyEventType", translationId));
}
//Used for subject of email and message deliveries
private static string GetTranslatedNotifyEventName(NotifyEventType net, long translationId)
{
return _transCache[translationId][(int)net].Name;
}
private static async Task DeliverInApp(NotifyEvent ne, AyContext ct)
@@ -171,29 +196,44 @@ namespace AyaNova.Biz
await ct.SaveChangesAsync();
}
private static async Task DeliverSMTP(NotifyEvent ne, string toAddress, AyContext ct)
private static async Task DeliverSMTP(NotifyEvent ne, AyContext ct)
{
log.LogTrace($"DeliverSMTP deliving notify event: {ne}");
if (string.IsNullOrWhiteSpace(ne.NotifySubscription.DeliveryAddress))
{
await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.DefaultNotification, $"Error: no email address is set in subscription to deliver email notification for this event:{ne}", null, ne.UserId);
var subject = $"Notification: {ne.EventType.ToString()}";
}
var transid = _UserTranslationIdCache[ne.NotifySubscription.UserId];
var subject = $"AY:{GetTranslatedNotifyEventName(ne.EventType, transid)}:{ne.Name}";
IMailer m = AyaNova.Util.ServiceProviderProvider.Mailer;
try
{
await m.SendEmailAsync(toAddress, subject, "This is a test to confirm notification system is working", ServerGlobalOpsSettingsCache.Notify);
return "ok";
var body = "";
if (ne.ObjectId != 0)
{
body = OpenObjectUrlBuilder(ne.AyaType, ne.ObjectId) + "\n";
}
body += ne.Message;
await m.SendEmailAsync(ne.NotifySubscription.DeliveryAddress, subject, body, ServerGlobalOpsSettingsCache.Notify);
}
catch (Exception ex)
{
return ExceptionUtil.ExtractAllExceptionMessages(ex);
await NotifyEventProcessor.AddOpsProblemEvent("SMTP Notification failed", ex);
await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.DefaultNotification, $"Error: an error prevented delivering the following notification via email. System operator users have been notified:{ne}", null, ne.UserId);
}
finally
{
//remove event no matter what
ct.NotifyEvent.Remove(ne);
await ct.SaveChangesAsync();
}
//todo: //Open question: what to do with failed deliveries?
//we dont' want them piling up but we don't want to just dump them do we?
//it should be only mail ones that fail, not app ones, there's no way for an app delivery to fail as it's just put in a table
//### PLAN if it's an smtp delivery that fails and it's to someone who can be delivered in app then it should send an inapp notification of
//delivery failure and still delete the smtp delivery
//If it's not possible to notify the person via in app of the failed smtp then perhaps it notifies OPS personnel and biz admin personnel
}
//Called from ops notification settings to test smtp setup by delivering to address of choosing
@@ -218,6 +258,20 @@ namespace AyaNova.Biz
}
//Open object url
//### NOTE: If this is required anywhere else, move it to a central BizUtils class in Biz folder callable from here and there
private static string OpenObjectUrlBuilder(AyaType otype, long id)
{
var ServerUrl = ServerGlobalOpsSettingsCache.Notify.AyaNovaServerURL;
if (string.IsNullOrWhiteSpace(ServerUrl))
{
NotifyEventProcessor.AddOpsProblemEvent("Notification system: The OPS Notification setting is empty for AyaNova Server URL. This prevents Notification system from linking events to openable objects.").Wait();
return "OPS ERROR NO SERVER URL CONFIGURED";
}
ServerUrl = ServerUrl.Trim().TrimEnd('/');
return $"{ServerUrl}?type={otype}&id={id}";
}
/////////////////////////////////////////////////////////////////////
}//eoc

View File

@@ -14,6 +14,7 @@ namespace AyaNova.Models
public NotifyMailSecurity ConnectionSecurity { get; set; }
public int SmtpServerPort { get; set; }
public string NotifyFromAddress { get; set; }
public string AyaNovaServerURL { get; set; }
public GlobalOpsNotificationSettings()
{
@@ -27,6 +28,7 @@ namespace AyaNova.Models
ConnectionSecurity = NotifyMailSecurity.StartTls;
SmtpServerPort = 465;
NotifyFromAddress = "support@ayanova.com";
AyaNovaServerURL="http://localhost:8080";
#else
SmtpServerAddress="mail.example.com";
SmtpAccount="notifydeliverfromaccount@example.com";
@@ -34,6 +36,7 @@ namespace AyaNova.Models
ConnectionSecurity= NotifyMailSecurity.SSLTLS;
SmtpServerPort=587;
NotifyFromAddress="noreply@example.com";
AyaNovaServerURL="https://ayanovaserver.example.com";
#endif
}

View File

@@ -1901,5 +1901,6 @@
"SmtpPassword": "SMTP-Serverkennwort",
"ConnectionSecurity": "SMTP-Verbindungssicherheit",
"SmtpServerPort": "SMTP-Server-Port",
"NotifyFromAddress": "SMTP-Benachrichtigungsadresse"
"NotifyFromAddress": "SMTP-Benachrichtigungsadresse",
"AyaNovaServerUrl": "AyaNova Server URL"
}

View File

@@ -1901,5 +1901,6 @@
"SmtpPassword": "SMTP server password",
"ConnectionSecurity": "SMTP connection security",
"SmtpServerPort": "SMTP server port",
"NotifyFromAddress": "SMTP notify from address"
"NotifyFromAddress": "SMTP notify from address",
"AyaNovaServerUrl": "AyaNova server URL"
}

View File

@@ -1901,5 +1901,6 @@
"SmtpPassword": "Contraseña SMTP",
"ConnectionSecurity": "Seguridad de conexión del servidor SMTP",
"SmtpServerPort": "Puerto SMTP",
"NotifyFromAddress": "Notificación SMTP desde la dirección"
"NotifyFromAddress": "Notificación SMTP desde la dirección",
"AyaNovaServerUrl": "URL del servidor AyaNova"
}

View File

@@ -1901,5 +1901,6 @@
"SmtpPassword": "Mot de passe du serveur SMTP",
"ConnectionSecurity": "Sécurité de la connexion SMTP",
"SmtpServerPort": "Port du serveur SMTP",
"NotifyFromAddress": "Notification SMTP envoyée depuis l'adresse"
"NotifyFromAddress": "Notification SMTP envoyée depuis l'adresse",
"AyaNovaServerUrl": "URL du serveur AyaNova"
}

View File

@@ -22,7 +22,7 @@ namespace AyaNova.Util
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
private const int DESIRED_SCHEMA_LEVEL = 12;
internal const long EXPECTED_COLUMN_COUNT = 382;
internal const long EXPECTED_COLUMN_COUNT = 383;
internal const long EXPECTED_INDEX_COUNT = 139;
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
@@ -237,7 +237,7 @@ namespace AyaNova.Util
"backuptime timestamp, backupsetstokeep int, backupattachments bool)");
await ExecQueryAsync("CREATE TABLE aglobalopsnotificationsettings (id integer NOT NULL PRIMARY KEY, smtpdeliveryactive bool not null, " +
"smtpserveraddress text, smtpaccount text, smtppassword text, connectionsecurity integer not null default 0, smtpserverport integer, notifyfromaddress text)");
"smtpserveraddress text, smtpaccount text, smtppassword text, connectionsecurity integer not null default 0, smtpserverport integer, notifyfromaddress text, ayanovaserverurl text)");
//create aevent biz event log table
await ExecQueryAsync("CREATE TABLE aevent (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created timestamp not null, userid bigint not null," +