From 4b81a08c3151950d159b74c035bbd1e4e12e27d3 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 19 Jan 2023 19:48:31 +0000 Subject: [PATCH] --- server/biz/LicenseBiz.cs | 82 ++++++++++++++++++++++++++++++++++------ server/models/License.cs | 4 +- server/util/AySchema.cs | 4 +- 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/server/biz/LicenseBiz.cs b/server/biz/LicenseBiz.cs index 1c58e0f..e7d3905 100644 --- a/server/biz/LicenseBiz.cs +++ b/server/biz/LicenseBiz.cs @@ -51,9 +51,7 @@ namespace Sockeye.Biz if (!importedWithKeyDoNotGenerate)//do not generate is used for initial import only from rockfish, could be removed after the initial import { await GenerateKey(newObject); - if(newObject.Active){//this means it should notify immediately - } } if (HasErrors) return null; newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); @@ -63,6 +61,14 @@ namespace Sockeye.Biz await SearchIndexAsync(newObject, true); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await HandlePotentialNotificationEvent(SockEvent.Created, newObject); + + //NOTIFY? + if (newObject.Active + && !newObject.NotificationSent + && newObject.RegTo != RavenKeyFactory.REVOKED_TOKEN) + {//this means it should notify customer / trialer immediately + await NotifyEndUserKeyIsAvailableAsync(newObject); + } return newObject; } } @@ -481,7 +487,7 @@ namespace Sockeye.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //UPDATE // - internal async Task PutAsync(License putObject, bool importingDoNotNotify = false) + internal async Task PutAsync(License putObject) { var dbObject = await GetAsync(putObject.Id, false); if (dbObject == null) @@ -505,13 +511,6 @@ namespace Sockeye.Biz try { await ct.SaveChangesAsync(); - if (!importingDoNotNotify) - { - //TODO: NOTIFICATION ON NEW KEY - //BUT NOT if REVOKED token is the regto, we don't want them to know, just let AyaNova install it - //this is for non-payment scenarios or chargebacks after license was sent - } - } catch (DbUpdateConcurrencyException) { @@ -525,11 +524,70 @@ namespace Sockeye.Biz await SearchIndexAsync(putObject, false); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); await HandlePotentialNotificationEvent(SockEvent.Modified, putObject, dbObject); + + //NOTIFY? + if (putObject.Active + && !putObject.NotificationSent + && putObject.RegTo != RavenKeyFactory.REVOKED_TOKEN) + {//this means it should notify customer / trialer immediately + await NotifyEndUserKeyIsAvailableAsync(putObject); + } return putObject; } + ///////////////////////////////////////////////////////////////////////////////// + //NOTIFY USER + // + internal async Task NotifyEndUserKeyIsAvailableAsync(License l) + { + + if (!l.NotificationSent && !string.IsNullOrWhiteSpace(l.FetchEmail)) + { + //## ------------------ DEFAULT NOTIFICATIONS TO CUSTOMER ON LICENSE AVAILABLE ---------------- + + string body=string.Empty; + + switch(l.PGroup){ + case ProductGroup.NotSet: + case ProductGroup.Misc: + throw new System.NotSupportedException($"Product group {l.PGroup} not supported for license notification to {l.RegTo}"); + case ProductGroup.AyaNova7: + body=ServerGlobalBizSettings.Cache. + break; + + } + + + var verifyUrl = ServerGlobalOpsSettingsCache.Notify.SockeyeServerURL.Trim().TrimEnd('/') + $"/rvr/verify/{newObject.EmailConfirmCode}"; + var body = ServerGlobalBizSettings.Cache..ValidateEmail.Replace("{verifyUrl}", verifyUrl);//$"Please verify your email address by clicking the link below or copy and pasting into a browser\r\n{verifyUrl}\r\nOnce your email is verified the request will be processed manually during business hours.\r\n(If you did not request this you can ignore this message)"; + + var notifyDirectSMTP = new Sockeye.Api.Controllers.NotifyController.NotifyDirectSMTP() + { + ToAddress = newObject.Email, + Subject = "AyaNova trial request email verification", + TextBody = body + }; + + + IMailer m = Sockeye.Util.ServiceProviderProvider.Mailer; + try + { + await m.SendEmailAsync(notifyDirectSMTP.ToAddress, notifyDirectSMTP.Subject, notifyDirectSMTP.TextBody, ServerGlobalOpsSettingsCache.Notify, null, null, null); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(1, notifyDirectSMTP.ObjectId, notifyDirectSMTP.SockType, SockEvent.DirectSMTP, $"\"{notifyDirectSMTP.Subject}\"->{notifyDirectSMTP.ToAddress}"), ct); + } + catch (Exception ex) + { + var err = "TrialLicenseRequest sending email confirmation request: SMTP direct message failed"; + await NotifyEventHelper.AddOpsProblemEvent(err, ex); + AddError(ApiErrorCode.API_SERVER_ERROR, null, err + ExceptionUtil.ExtractAllExceptionMessages(ex)); + return null; + } + } + + } + #region KEY GEN //////////////////////////////////////////////////////////////////////////////////////////////// //GENERATE @@ -681,7 +739,7 @@ namespace Sockeye.Biz //it is *still* used for notification and will be pre-filled with customer address if not provided so //this is a backstop to ensure the notification message can be sent //(revoked keys are *not* notified for obvious reasons so thats not a requirement here) - if (string.IsNullOrWhiteSpace(proposedObj.FetchEmail) && proposedObj.RegTo!=RavenKeyFactory.REVOKED_TOKEN) + if (string.IsNullOrWhiteSpace(proposedObj.FetchEmail) && proposedObj.RegTo != RavenKeyFactory.REVOKED_TOKEN) { AddError(ApiErrorCode.VALIDATION_REQUIRED, "FetchEmail"); return; @@ -700,7 +758,7 @@ namespace Sockeye.Biz return; } - + //Active state rules for each product group diff --git a/server/models/License.cs b/server/models/License.cs index caccd47..8d34ebd 100644 --- a/server/models/License.cs +++ b/server/models/License.cs @@ -33,7 +33,9 @@ namespace Sockeye.Models public DateTime? LicenseExpire { get; set; } public DateTime MaintenanceExpire { get; set; } - public bool TrialMode { get; set; } = false;//v8 indicates it was requested by user as trial request or manually created as a trial request in UI + public bool Renewal { get; set; } = false;//v8/v7 modifies message and ops indicates it is a renewal of an existing license not a NEW license + + public bool TrialMode { get; set; } = false;//v8/v7 modifies message and ops indicates it was requested by user as trial request or manually created as a trial request in UI //v8 dto props [NotMapped] diff --git a/server/util/AySchema.cs b/server/util/AySchema.cs index afb7417..050d0fc 100644 --- a/server/util/AySchema.cs +++ b/server/util/AySchema.cs @@ -22,7 +22,7 @@ namespace Sockeye.Util //!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImportingAsync WHEN NEW TABLES ADDED!!!! private const int DESIRED_SCHEMA_LEVEL = 17; - internal const long EXPECTED_COLUMN_COUNT = 515; + internal const long EXPECTED_COLUMN_COUNT = 516; internal const long EXPECTED_INDEX_COUNT = 74; internal const long EXPECTED_CHECK_CONSTRAINTS = 241; internal const long EXPECTED_FOREIGN_KEY_CONSTRAINTS = 34; @@ -876,7 +876,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); await ExecQueryAsync("CREATE TABLE alicense (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created TIMESTAMPTZ NOT NULL, active BOOL NOT NULL DEFAULT false, " + "customerid BIGINT REFERENCES acustomer(id), pgroup INTEGER NOT NULL DEFAULT 0, regto TEXT NOT NULL, key TEXT, fetchcode TEXT, fetchemail TEXT, " + "fetchedon TIMESTAMPTZ, dbid TEXT, licenseexpire TIMESTAMPTZ, maintenanceexpire TIMESTAMPTZ NOT NULL, notificationsent BOOL NOT NULL DEFAULT false, " - + "trialmode BOOL NOT NULL DEFAULT false, " + + "renewal BOOL NOT NULL DEFAULT false, trialmode BOOL NOT NULL DEFAULT false, " + "wiki TEXT, tags VARCHAR(255) ARRAY )");