From 33211ee15fdf3f556ac22db44f0ffa9798dfb2d4 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 19 Jan 2023 21:43:04 +0000 Subject: [PATCH] --- server/biz/LicenseBiz.cs | 361 +++++++++++++++++------------ server/models/GlobalBizSettings.cs | 4 +- 2 files changed, 209 insertions(+), 156 deletions(-) diff --git a/server/biz/LicenseBiz.cs b/server/biz/LicenseBiz.cs index e7d3905..8961f8d 100644 --- a/server/biz/LicenseBiz.cs +++ b/server/biz/LicenseBiz.cs @@ -87,6 +87,212 @@ namespace Sockeye.Biz return ParseKeySetDTOFields(ret); } + //////////////////////////////////////////////////////////////////////////////////////////////// + //UPDATE + // + internal async Task PutAsync(License putObject) + { + var dbObject = await GetAsync(putObject.Id, false); + if (dbObject == null) + { + AddError(ApiErrorCode.NOT_FOUND, "id"); + return null; + } + if (dbObject.Concurrency != putObject.Concurrency) + { + AddError(ApiErrorCode.CONCURRENCY_CONFLICT); + return null; + } + + putObject.Tags = TagBiz.NormalizeTags(putObject.Tags); + await ValidateAsync(putObject, dbObject); + if (HasErrors) return null; + await GenerateKey(putObject); + if (HasErrors) return null; + + ct.Replace(dbObject, putObject); + try + { + await ct.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!await ExistsAsync(putObject.Id)) + AddError(ApiErrorCode.NOT_FOUND); + else + AddError(ApiErrorCode.CONCURRENCY_CONFLICT); + return null; + } + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, BizType, SockEvent.Modified), ct); + 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.AyaNova7: + if (l.TrialMode) + { + body = ServerGlobalBizSettings.Cache.V7TemporaryTrial; + } + else + { + if (l.Renewal) + { + body = ServerGlobalBizSettings.Cache.V7AddOnKey; + } + else + { + body = ServerGlobalBizSettings.Cache.V7NewKey; + } + } + break; + case ProductGroup.RavenPerpetual: + if (l.TrialMode) + return;//TRIAL REQUEST HAS *ALREADY* NOTIFIED USER NO NEED TO DO ANYTHING HERE + else + {//{newLicense} + /* + Your AyaNova license key is ready to be installed. + AyaNova will fetch it automatically within 24 hours or you can force it to fetch immediately from the License page in AyaNova now. + --- + Registered to: ACCS + Database id: 7ktPA+Eaq+LM4vNMkQdbwBkUMDzzFYXmH+m21n3w5Rk= + Type: Perpetual + Support and updates available until: Sunday, 14 January 2024 + ActiveInternalUsers: 3 + */ + + var licenseInfo = $"Registered to: {l.RegTo}\nDatabase Id: {l.DbId}\nType: Perpetual\nSupport and updates until: {l.MaintenanceExpire.ToLongDateString()}\nUsers:{l.Users}"; + body = ServerGlobalBizSettings.Cache.RavenNewKeyAvailable.Replace("{newLicense}", licenseInfo); + } + break; + case ProductGroup.RavenSubscription: + if (l.TrialMode) + return;//TRIAL REQUEST HAS *ALREADY* NOTIFIED USER NO NEED TO DO ANYTHING HERE + else + {//{newLicense} + /* + Your AyaNova activation key is ready to be installed. +AyaNova will fetch it automatically within 24 hours or you can force it to fetch immediately from the License page in AyaNova now. +--- +Registered to: Sportseffect +Database id: ZAuW3p73DIvtIWk7VxI4fuy5MccqzGw/ZBqtkRKdpss= +Type: Subscription +Available for use until: Tuesday, 14 February 2023 +ActiveInternalUsers: 2 +ActiveCustomerUsers: 250 +MaximumDataGB: 20 + */ + + var licenseInfo = $"Registered to: {l.RegTo}\nDatabase Id: {l.DbId}\nType: Subscription\nAvailable for use until: {((DateTime)l.LicenseExpire).ToLongDateString()}\nUsers:{l.Users}\nCustomer login Users:{l.CustomerUsers}\nMaximum data GB:{l.MaxDataGB}"; + body = ServerGlobalBizSettings.Cache.RavenNewKeyAvailable.Replace("{newLicense}", licenseInfo); + } + break; + default: + throw new System.NotSupportedException($"Product group {l.PGroup} not supported for license notification to {l.RegTo}"); + + } + + + + var notifyDirectSMTP = new Sockeye.Api.Controllers.NotifyController.NotifyDirectSMTP() + { + ToAddress = l.FetchEmail, + Subject = "AyaNova license key", + 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 = "License email to customer failure: SMTP direct message failed"; + await NotifyEventHelper.AddOpsProblemEvent(err, ex); + AddError(ApiErrorCode.API_SERVER_ERROR, null, err + ExceptionUtil.ExtractAllExceptionMessages(ex)); + return; + } + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + //DELETE + // + internal async Task DeleteAsync(long id) + { + using (var transaction = await ct.Database.BeginTransactionAsync()) + { + + License dbObject = await GetAsync(id, false); + if (dbObject == null) + { + AddError(ApiErrorCode.NOT_FOUND); + return false; + } + ValidateCanDeleteAsync(dbObject); + if (HasErrors) + return false; + + { + var IDList = await ct.Review.AsNoTracking().Where(x => x.SockType == SockType.License && x.ObjectId == id).Select(x => x.Id).ToListAsync(); + if (IDList.Count() > 0) + { + ReviewBiz b = new ReviewBiz(ct, UserId, UserTranslationId, CurrentUserRoles); + foreach (long ItemId in IDList) + if (!await b.DeleteAsync(ItemId, transaction)) + { + AddError(ApiErrorCode.CHILD_OBJECT_ERROR, null, $"Review [{ItemId}]: {b.GetErrorsAsString()}"); + return false; + } + } + } + + ct.License.Remove(dbObject); + await ct.SaveChangesAsync(); + + //Log event + await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); + await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct); + await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); + await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + await transaction.CommitAsync(); + await HandlePotentialNotificationEvent(SockEvent.Deleted, dbObject); + + return true; + } + } + + + #region PARSE KEY SET DTO FIELDS //Read the license key text, parse it and set the dto fields accordingly public static License ParseKeySetDTOFields(License l) @@ -484,110 +690,6 @@ namespace Sockeye.Biz #endregion parsekeysetdtofields - //////////////////////////////////////////////////////////////////////////////////////////////// - //UPDATE - // - internal async Task PutAsync(License putObject) - { - var dbObject = await GetAsync(putObject.Id, false); - if (dbObject == null) - { - AddError(ApiErrorCode.NOT_FOUND, "id"); - return null; - } - if (dbObject.Concurrency != putObject.Concurrency) - { - AddError(ApiErrorCode.CONCURRENCY_CONFLICT); - return null; - } - - putObject.Tags = TagBiz.NormalizeTags(putObject.Tags); - await ValidateAsync(putObject, dbObject); - if (HasErrors) return null; - await GenerateKey(putObject); - if (HasErrors) return null; - - ct.Replace(dbObject, putObject); - try - { - await ct.SaveChangesAsync(); - } - catch (DbUpdateConcurrencyException) - { - if (!await ExistsAsync(putObject.Id)) - AddError(ApiErrorCode.NOT_FOUND); - else - AddError(ApiErrorCode.CONCURRENCY_CONFLICT); - return null; - } - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, BizType, SockEvent.Modified), ct); - 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 @@ -618,56 +720,7 @@ namespace Sockeye.Biz } #endregion key gen - //////////////////////////////////////////////////////////////////////////////////////////////// - //DELETE - // - internal async Task DeleteAsync(long id) - { - using (var transaction = await ct.Database.BeginTransactionAsync()) - { - - License dbObject = await GetAsync(id, false); - if (dbObject == null) - { - AddError(ApiErrorCode.NOT_FOUND); - return false; - } - ValidateCanDeleteAsync(dbObject); - if (HasErrors) - return false; - - { - var IDList = await ct.Review.AsNoTracking().Where(x => x.SockType == SockType.License && x.ObjectId == id).Select(x => x.Id).ToListAsync(); - if (IDList.Count() > 0) - { - ReviewBiz b = new ReviewBiz(ct, UserId, UserTranslationId, CurrentUserRoles); - foreach (long ItemId in IDList) - if (!await b.DeleteAsync(ItemId, transaction)) - { - AddError(ApiErrorCode.CHILD_OBJECT_ERROR, null, $"Review [{ItemId}]: {b.GetErrorsAsString()}"); - return false; - } - } - } - - ct.License.Remove(dbObject); - await ct.SaveChangesAsync(); - - //Log event - await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); - await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct); - await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); - await transaction.CommitAsync(); - await HandlePotentialNotificationEvent(SockEvent.Deleted, dbObject); - - return true; - } - } - - - - + //////////////////////////////////////////////////////////////////////////////////////////////// //SEARCH // diff --git a/server/models/GlobalBizSettings.cs b/server/models/GlobalBizSettings.cs index 961d6b3..485c1b5 100644 --- a/server/models/GlobalBizSettings.cs +++ b/server/models/GlobalBizSettings.cs @@ -201,13 +201,13 @@ HOW TO INSTALL YOUR LICENSE KEY 5. Click on the accept button, AyaNova will fetch the license key from our server and install it automatically"; - RavenNewKeyAvailable = @"Your AyaNova key is ready to be installed.\nAyaNova will fetch it automatically within 24 hours or you can force it to fetch immediately from the License page in AyaNova now.\n---\n{newLicense}"; + RavenNewKeyAvailable = @"A new AyaNova license key is available.\nAyaNova will automatically fetch it within 24 hours or you can force it to fetch immediately from the License page in AyaNova now.\n---\n{newLicense}"; ValidateEmail = @"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)"; - RavenTrialApproved = @"Your trial license request has been approved.\r\nThe license will fetch and install automatically shortly or you can fetch it now in the License form menu."; + RavenTrialApproved = @"Your trial license request has been approved.\r\nThe license will be automatically installed shortly or you can fetch it now in the License form menu."; RavenTrialRejected = @"Your trial license request was not approved.\r\n{reason}";