From 7d8bbb651db48b07b27c91b48ed5a5a4e055eea1 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Tue, 21 Feb 2023 23:15:23 +0000 Subject: [PATCH] --- server/Controllers/RvrController.cs | 16 +- server/Startup.cs | 19 +- server/biz/GlobalBizSettingsBiz.cs | 1495 +++++++++++++------------- server/biz/TrialLicenseRequestBiz.cs | 60 +- server/sockeye.csproj | 4 +- server/util/AySchema.cs | 2 +- server/util/SockeyeVersion.cs | 2 +- 7 files changed, 806 insertions(+), 792 deletions(-) diff --git a/server/Controllers/RvrController.cs b/server/Controllers/RvrController.cs index 81571ad..2d73b8b 100644 --- a/server/Controllers/RvrController.cs +++ b/server/Controllers/RvrController.cs @@ -101,7 +101,7 @@ namespace Sockeye.Api.Controllers TrialLicenseRequest o = await biz.CreateAsync(newObject); if (o == null) { - var msg = ($"Unexpected error (code SE-444 was returned to customer) processing a new trial license request:{biz.GetErrorsAsString}"); + var msg = ($"Unexpected error (code SE-444 was returned to customer) processing a new trial license request:{biz.GetErrorsAsString}"); log.LogError(msg); await NotifyEventHelper.AddOpsProblemEvent(msg); return BadRequest($"E1000 - Error processing request code SE-444 contact support");//don't want to leak any info so need to check sockeye log if get this error @@ -124,7 +124,7 @@ namespace Sockeye.Api.Controllers //is there a valid trial request - var req = await ct.TrialLicenseRequest.AsNoTracking().Where(z => z.EmailConfirmCode == code && z.Status == TrialRequestStatus.AwaitingEmailValidation).FirstOrDefaultAsync(); + var req = await ct.TrialLicenseRequest.AsNoTracking().Where(z => z.EmailConfirmCode == code).FirstOrDefaultAsync();//&& z.Status == TrialRequestStatus.AwaitingEmailValidation if (req == null) { return new ContentResult @@ -135,6 +135,18 @@ namespace Sockeye.Api.Controllers }; } + //Legit code but they already validated email, if so then just return that it's ok so they don't keep thinking something's wrong + //but there's no need to keep processing it, it's done + if (req.EmailValidated) + { + return new ContentResult + { + ContentType = "text/html", + StatusCode = 200, + Content = "

Email validated!

Your request will be reviewed and processed by our staff during business hours. You will receive an email with instructions for starting your AyaNova evaluation.

" + }; + } + TrialLicenseRequestBiz biz = TrialLicenseRequestBiz.GetBiz(ct); var tlr = await biz.GetAsync(req.Id); if (tlr == null) diff --git a/server/Startup.cs b/server/Startup.cs index 8eecb4f..25996af 100644 --- a/server/Startup.cs +++ b/server/Startup.cs @@ -565,9 +565,10 @@ namespace Sockeye if (ServerBootConfig.SOCKEYE_PERMANENTLY_ERASE_DATABASE) { - _newLog.LogWarning("SOCKEYE_PERMANENTLY_ERASE_DATABASE has been set - deleting and recreating database"); - Util.DbUtil.DropAndRecreateDbAsync(_newLog).Wait(); - AySchema.CheckAndUpdateAsync(dbContext, _newLog).Wait(); + throw new InvalidOperationException("SOCKEYE_PERMANENTLY_ERASE_DATABASE has been set - Sockeye must be erased via psql to protect data from accidental deletion"); + // _newLog.LogWarning("SOCKEYE_PERMANENTLY_ERASE_DATABASE has been set - deleting and recreating database"); + // Util.DbUtil.DropAndRecreateDbAsync(_newLog).Wait(); + // AySchema.CheckAndUpdateAsync(dbContext, _newLog).Wait(); } @@ -663,12 +664,12 @@ namespace Sockeye Console.WriteLine("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"); - if (ServerBootConfig.SOCKEYE_PERMANENTLY_ERASE_DATABASE) - { - _newLog.LogWarning("SOCKEYE_PERMANENTLY_ERASE_DATABASE has been set - IMPORTING ROCKFISH"); - GlobalBizSettingsBiz.ImportRockfish(_newLog).Wait(); - _newLog.LogInformation("IMPORT COMPLETED"); - } + // if (ServerBootConfig.SOCKEYE_PERMANENTLY_ERASE_DATABASE) + // { + // _newLog.LogWarning("SOCKEYE_PERMANENTLY_ERASE_DATABASE has been set - IMPORTING ROCKFISH"); + // GlobalBizSettingsBiz.ImportRockfish(_newLog).Wait(); + // _newLog.LogInformation("IMPORT COMPLETED"); + // } } diff --git a/server/biz/GlobalBizSettingsBiz.cs b/server/biz/GlobalBizSettingsBiz.cs index 1d63f3c..d01afff 100644 --- a/server/biz/GlobalBizSettingsBiz.cs +++ b/server/biz/GlobalBizSettingsBiz.cs @@ -126,753 +126,756 @@ namespace Sockeye.Biz + #region Import from rockfish commented out + // //IMPORT FROM ROCKFISH + + // public static async Task ImportRockfish(ILogger log) + // { + // log.LogInformation("Start import from rockfish, authenticating"); + // ApiServerState apiServerState = (ApiServerState)ServiceProviderProvider.Provider.GetService(typeof(ApiServerState)); + + // //get the current server state so can set back to it later + // ApiServerState.ServerState wasServerState = apiServerState.GetState(); + // string wasReason = apiServerState.Reason; + // apiServerState.SetOpsOnly("Migrating from Rockfish"); + // ServerBootConfig.MIGRATING = true; + + // //Authenticate to rockfish + // //string sUrl = $"{LICENSE_SERVER_URL_ROCKFISH}rvr"; + // string URL_ROCKFISH = "https://rockfish.ayanova.com/"; + + // try + // { + // //var content = new StringContent("login=john&password=b43698c255365ee739c05ba0d42855e96c2365c76bb2f9b9eb149cec7b52174c"); + // var content = new StringContent(JsonConvert.SerializeObject(new + // { + // login = "john", + // password = "b43698c255365ee739c05ba0d42855e96c2365c76bb2f9b9eb149cec7b52174c" + // }), Encoding.UTF8, "application/json"); + + // var client = ServiceProviderProvider.HttpClientFactory.CreateClient(); + + // //AUTHENTICATE + // var res = await client.PostAsync($"{URL_ROCKFISH}authenticate?login=john&password=b43698c255365ee739c05ba0d42855e96c2365c76bb2f9b9eb149cec7b52174c", content); + // var responseText = await res.Content.ReadAsStringAsync(); + + // if (!res.IsSuccessStatusCode) + // throw new Exception($"E1020 - Error authenticating to rockfish: {res.ReasonPhrase}"); + + // var responseJson = JObject.Parse(responseText); + + // var authToken = responseJson["token"].Value(); + // var dlKey = responseJson["dlkey"].Value(); + // var userId = responseJson["id"].Value(); + + // var contentType = new MediaTypeWithQualityHeaderValue("application/json"); + // client.DefaultRequestHeaders.Accept.Add(contentType); + // client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken); + + // #region CUSTOMERS + // log.LogInformation("RFImport customers"); + + // res = await client.GetAsync($"{URL_ROCKFISH}api/customer/list"); + // responseText = await res.Content.ReadAsStringAsync(); + // var jaCustomerList = JArray.Parse(responseText); + + // foreach (JObject jCustomerListItem in jaCustomerList) + // { + // res = await client.GetAsync($"{URL_ROCKFISH}api/customer/{jCustomerListItem["id"].Value()}"); + + // var jCustomer = JObject.Parse(await res.Content.ReadAsStringAsync()); + // var CustomerName = jCustomer["name"].Value(); + // //SITES + // res = await client.GetAsync($"{URL_ROCKFISH}api/customer/{jCustomerListItem["id"].Value()}/sites"); + // var jaSiteList = JArray.Parse(await res.Content.ReadAsStringAsync()); + + // bool multiSite = jaSiteList.Count() > 1; + + // foreach (JObject jSite in jaSiteList) + // { + // long CurrentCustomerId = 0; + // using (AyContext ct = ServiceProviderProvider.DBContext) + // { + + // if (multiSite) + // { + // CustomerName = $"{jCustomer["name"].Value()} - {jSite["name"].Value()}"; + // log.LogInformation($"RFImport MULTISITE CUSTOMER: {CustomerName}"); + // } + + + // //Create customer if we don't have one already + // if (await ct.Customer.AnyAsync(z => z.Name == CustomerName)) + // continue;//already have this one so no need to process it again + // { + // //CREATE CUSTOMER + // Customer c = new Customer(); + // c.Active = jCustomerListItem["active"].Value(); + // c.Name = CustomerName; + // c.Country = jSite["country"].Value(); + // c.Region = jSite["stateProvince"].Value(); + // c.DoNotContact = jCustomer["doNotContact"].Value(); + // c.Notes = jCustomer["notes"].Value(); + // c.DbId = jSite["dbId"].Value(); + // if (c.DbId == "v7_no_dbid") + // { + // c.DbId = null; + // c.Tags.Add("v7"); + // } + // else + // c.Tags.Add("raven"); + + // if (jSite["hosted"].Value() == true) + // c.Tags.Add("hosted"); + + // //In rockfish there were support emails that were people allowed to be contacting us on behalf of the customer + // var supportEmail = jCustomer["supportEmail"].Value(); + // if (!string.IsNullOrWhiteSpace(supportEmail)) + // c.Notes += "\nSupport Emails: " + supportEmail; + // //in Rockfish the admin email is the main license related contact and technically the only person responsible to contact us + // //usually the same as the purchase email + // c.EmailAddress = jCustomer["adminEmail"].Value(); + // CustomerBiz biz = CustomerBiz.GetBiz(ct); + // var NewObject = await biz.CreateAsync(c); + // CurrentCustomerId = NewObject.Id; + // }//customer creation + // }//context + + + // //SITE PURCHASES + // res = await client.GetAsync($"{URL_ROCKFISH}api/site/{jSite["id"].Value()}/purchases"); + // var jaPurchaseList = JArray.Parse(await res.Content.ReadAsStringAsync()); + + // foreach (JObject jPurchase in jaPurchaseList) + // { + // using (AyContext ct = ServiceProviderProvider.DBContext) + // { + // //create product if not exist then import + // //Get product id if exists + // var ProductName = jPurchase["name"].Value(); + // bool maybeRenewal = ProductName.ToLowerInvariant().Contains("renew"); + // ProductName = ProductName.Replace("- Renewal", "").Replace(" Renewal", "").Replace(" RENEWAL", "").Replace("CANCELLED ", "").Replace("CANCELED ", ""); + // var p = await ct.Product.AsNoTracking().FirstOrDefaultAsync(z => z.VendorCode == jPurchase["productCode"].Value()); + + + // if (p == null) + // { + + // //Create it here + // p = new Product(); + // p.Name = ProductName; + // p.Active = true;//not entirely true but we can always deactivate there aren't many products + // p.VendorId = 1; + // p.OurCode = p.VendorCode = jPurchase["productCode"].Value(); + // p.PGroup = ProductBiz.ProductGroupFromProductCode(p.OurCode); + + // if (p.VendorCode == "301028468")//subscription yearly + // { + // p.LicenseInterval = new TimeSpan(365, 0, 0, 0); //actual length, in license is where I pad to cover them + // } + + // if (p.VendorCode == "301028467")//subscription monthly + // { + // p.LicenseInterval = new TimeSpan(31, 0, 0, 0);//there is no concept beyond days for timespan so a month is 31 days max + // p.MaintInterval = new TimeSpan(31, 0, 0, 0);//the only product less than one year of maintenance save the ones with no maintenance which can be edited manually later as there are so few of them + // } + // else + // p.MaintInterval = new TimeSpan(365, 0, 0, 0); + + // ProductBiz biz = ProductBiz.GetBiz(ct); + // p = await biz.CreateAsync(p); + // } + + // //Now we can add the sale that we have the product + // if (!await ct.Purchase.AnyAsync(z => z.SalesOrderNumber == jPurchase["salesOrderNumber"].Value())) + // { + // var s = new Purchase(); + // s.VendorId = 1; + // s.ProductId = p.Id; + // s.PGroup = p.PGroup; + // s.CustomerId = CurrentCustomerId; + // s.RegTo = CustomerName; + // s.CancelDate = DateUtil.EpochToDateNullIsNull(jPurchase["cancelDate"].Value()); + // s.CouponCode = jPurchase["couponCode"].Value(); + // s.ExpireDate = DateUtil.EpochToDateNullIsNull(jPurchase["expireDate"].Value()); + // s.Name = p.Name; + // s.Processed = true; + // s.PurchaseDate = DateUtil.EpochToDateNullIsMin(jPurchase["purchaseDate"].Value()); + // s.Quantity = jPurchase["quantity"].Value(); + // s.RenewNoticeSent = jPurchase["renewNoticeSent"].Value(); + // s.SalesOrderNumber = jPurchase["salesOrderNumber"].Value(); + // s.Notes = jPurchase["notes"].Value(); + // s.IsRenewal = maybeRenewal; + // PurchaseBiz biz = PurchaseBiz.GetBiz(ct); + // await biz.CreateAsync(s); + // } + // }//context + // } + + + + // }//site loop + + // }//end of all customers iteration + + // #endregion customers + + // #region VENDOR NOTIFICATIONS + // log.LogInformation("RFImport Vendor notifications"); + // { + + // res = await client.GetAsync($"{URL_ROCKFISH}api/vendor-notifications/list"); + // responseText = await res.Content.ReadAsStringAsync(); + // var jaVendorNotificationList = JArray.Parse(responseText); + + // foreach (JObject jVendorNotificationItem in jaVendorNotificationList.Reverse()) + // { + // /*[] + // "{\n \"creation_date\": \"2022-12-28T20:20:24Z\",\n \ + // "id\": 356247074,\n \ + // "order_notification\": {\n \ + // "purchase\": {\n \"customer_data\": {\n \"billing_contact\": {\n \"address\": {\n \"city\": \"Alpharetta\",\n \"country\": \"USA\",\n \"country_id\": \"US\",\n + // \"postal_code\": \"30009\",\n \"state\": \"Georgia\",\n \"state_id\": \"GA\",\n \"street1\": \"11675 Rainwater Dr., Suite 350\"\n }, + // \n …tart\": \"\",\n \"renewal_type\": \"auto\",\n \"retention_discount_count\": \"\",\n \"retention_discount_percent\": \"\",\n \ + // "start_date\": \"2022-12-28T00:00:00\",\n \"status\": \"ToProcess\",\n \"status_id\": \"TOP\"\n },\n \ + // "vat_pct\": 0.0,\n \"your_product_id\": \"perpetual\"\n }\n ],\n + // \"purchase_origin\": \"online\",\n \"sequential_invoice_no\": \"e5-US-2022-00001637070\"\n }\n }\n}" + + // { + // "id": 25, + // "dtCreated": 1670375661, + // "vendor": "shareit", + // "data": "{\n \"creation_date\": \"2022-12-07T01:14:19Z\",\n \"id\": 354935062,\n \"order_notification\": {\n \"purchase\": {\n \"customer_data\": {\n \"billing_contact\": {\n \"address\": {\n \"city\": \"Abbotsford\",\n \"country\": \"Canada\",\n \"country_id\": \"CA\",\n \"postal_code\": \"V2S 8M1\",\n \"state\": \"British Columbia\",\n \"state_id\": \"BC\",\n \"street1\": \"35355 McKee Rd\"\n },\n \"company\": \"Adtech Systems Inc.\",\n \"email\": \"erling@myadtech.com\",\n \"first_name\": \"Erling\",\n \"last_name\": \"Lassesen\"\n },\n \"customer_payment_data\": {\n \"currency\": \"USD\",\n \"payment_method\": \"PayPal\"\n },\n \"delivery_contact\": {\n \"address\": {\n \"city\": \"Abbotsford\",\n \"country\": \"Canada\",\n \"country_id\": \"CA\",\n \"postal_code\": \"V2S 8M1\",\n \"state\": \"British Columbia\",\n \"state_id\": \"BC\",\n \"street1\": \"35355 McKee Rd\"\n },\n \"company\": \"Adtech Systems Inc.\",\n \"email\": \"erling@myadtech.com\",\n \"first_name\": \"Erling\",\n \"last_name\": \"Lassesen\"\n },\n \"language\": \"English\",\n \"language_iso\": \"en\",\n \"reg_name\": \"Adtech Systems Inc.\",\n \"shopper_id\": \"50862261\",\n \"subscribe_newsletter\": true,\n \"user_id\": \"erling@adtech-systems.com-4\"\n },\n \"is_test\": false,\n \"payment_complete_date\": \"2022-12-07T01:14:19Z\",\n \"payment_status\": \"complete\",\n \"payment_status_id\": \"PCA\",\n \"purchase_date\": \"2022-12-07T01:14:16Z\",\n \"purchase_id\": 833707313,\n \"purchase_item\": [\n {\n \"accounting\": {\n \"currency\": \"USD\",\n \"product_net\": 55.65,\n \"discount\": 0.0,\n \"product_vat\": 6.68,\n \"shipping\": 0.0,\n \"shipping_vat\": 0.0,\n \"eu_vat\": -6.68,\n \"margin_net\": -5.44,\n \"your_revenue\": 50.21\n },\n \"additional_information\": [\n {\n \"additional_id\": \"ADDITIONAL1\",\n \"additional_value\": \"YES\"\n },\n {\n \"additional_id\": \"ADDITIONAL2\",\n \"additional_value\": \"YES\"\n },\n {\n \"additional_id\": \"ADDITIONAL3\",\n \"additional_value\": \"YES\"\n }\n ],\n \"currency\": \"USD\",\n \"delivery_type\": \"Electronically\",\n \"discount\": 0.0,\n \"extended_download_price\": 0.0,\n \"manual_order_price\": 0.0,\n \"notification_no\": 7926,\n \"product_id\": 300740315,\n \"product_name\": \"Single AyaNova schedulable resource 1 year subscription license\",\n \"product_single_price\": 55.65,\n \"purchase_item_key\": [],\n \"quantity\": 1,\n \"running_no\": 1,\n \"shipping_price\": 0.0,\n \"shipping_vat_pct\": 0.0,\n \"subscription\": {\n \"expiration_date\": \"2023-12-07T17:28:16Z\",\n \"id\": \"550286373-1\",\n \"interval\": \"Yearly without end\",\n \"original_notification_no\": \"6872\",\n \"original_purchase_id\": \"550286373\",\n \"original_running_no\": \"1\",\n \"renewal_discount_count\": \"\",\n \"renewal_discount_start\": \"\",\n \"renewal_type\": \"auto\",\n \"retention_discount_count\": \"\",\n \"retention_discount_percent\": \"\",\n \"start_date\": \"2017-12-07T00:00:00\",\n \"status\": \"ToProcess\",\n \"status_id\": \"TOP\"\n },\n \"vat_pct\": 12.0\n }\n ],\n \"purchase_origin\": \"Subscription\",\n \"sequential_invoice_no\": \"e5-DE-2022-00002647549\"\n }\n }\n}", + // "dtProcessed": null, + // "processed": false + // }, + // */ + // using (AyContext ct = ServiceProviderProvider.DBContext) + // { + // var vn = new VendorNotification(); + // vn.Created = DateUtil.EpochToDateNullIsMin(jVendorNotificationItem["dtCreated"].Value()); + // vn.VendorId = 1; + // vn.VendorData = jVendorNotificationItem["data"].Value(); + // vn.Processed = vn.Created;//indicate it's been processed + // ct.VendorNotification.Add(vn); + // await ct.SaveChangesAsync(); + + + // // #if (DEBUG) + // // //Test dev stuff + // // #warning DEV TEST ORDER PROCESSING REMOVE THIS WHEN DONE + // // if (!string.IsNullOrWhiteSpace(vn.VendorData)) + // // await SockBotProcessVendorNotifications.ParseVendorNotificationData(vn, ct, log); + // // #endif + // } + + // }// all vendor notifications loop + // } + // #endregion vendor notifications + + // #region CASES + + // log.LogInformation("RFImport Cases"); + // //case projects to be tags + // List CaseProjectList = new List(); + // { + // res = await client.GetAsync($"{URL_ROCKFISH}api/rfcaseproject"); + // responseText = await res.Content.ReadAsStringAsync(); + + // var jaRFCaseProjectList = JArray.Parse(responseText); + // foreach (JObject jRFCaseProject in jaRFCaseProjectList) + // { + // CaseProjectList.Add(new NameIdItem() { Name = jRFCaseProject["name"].Value(), Id = jRFCaseProject["id"].Value() }); + + // } + + // } + // { + // using (AyContext ct = ServiceProviderProvider.DBContext) + // { + // res = await client.GetAsync($"{URL_ROCKFISH}api/rfcase/list"); + // responseText = await res.Content.ReadAsStringAsync(); + // var jaRFCaseList = JArray.Parse(responseText); + // //some cases are missing the start date so substitute a close other case date (not critical but sb at least in the ballpark for list viewing purposes) + // DateTime dtTempCreated = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc); + // foreach (JObject jRFCase in jaRFCaseList.Reverse()) + // { + + + // var g = new GZCase(); + // g.CaseId = jRFCase["id"].Value(); + // g.Closed = DateUtil.EpochToDateNullIsNull(jRFCase["dtClosed"].Value()); + // //NOTE: closed in rockfish was the date at midnight in GMT + // //so to be in the same day as here need to add a few hours, let's say 8 am for each so add 8 hours + // if (g.Closed != null) + // { + // g.Closed = ((DateTime)g.Closed).AddHours(16); + // } + + // //fuckery to try to insert a at least semi close date when created date is missing + // DateTime? dtTemp = DateUtil.EpochToDateNullIsNull(jRFCase["dtCreated"].Value()); + // if (dtTemp == null) + // { + // dtTemp = dtTempCreated; + // } + // else + // { + // dtTempCreated = (DateTime)dtTemp; + // } + // g.Created = (DateTime)dtTemp; + // g.Name = jRFCase["title"].Value(); + // g.Notes = jRFCase["notes"].Value(); + + // var ver = jRFCase["releaseVersion"].Value(); + // if (!string.IsNullOrWhiteSpace(ver)) + // g.Notes += $"\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\nReleased on version:{ver}"; + + // var releaseNotes = jRFCase["releaseNotes"].Value(); + // if (!string.IsNullOrWhiteSpace(releaseNotes)) + // g.Notes += $"\nRelease notes:{releaseNotes}"; + + // //Project name to tags + // g.Tags.Add(CaseProjectList.FirstOrDefault(z => z.Id == jRFCase["rfCaseProjectId"].Value()).Name.Replace("z_", "legacy-")); + + // //priority to tags + // g.Tags.Add($"{jRFCase["priority"].Value()}-priority"); + + + + // //check for attachments and just add as a note, don't bother with actual transfer of attachment, there aren't a lot and most are way in the past and not required for anything + // //if needed in future can manually xfer it over from the rockfish.sqlite db directly using DB BRowser for sqlite which allows opening the blob from the rfcaseblob table and saving it + // res = await client.GetAsync($"{URL_ROCKFISH}api/rfcase/{g.CaseId}/attachments"); + // responseText = await res.Content.ReadAsStringAsync(); + // try + // { + // var jAttachments = JObject.Parse(responseText); + // if (jAttachments["attach"].Count() > 0) + // { + // g.Notes += "\n********\nRockfish attachments\n"; + // foreach (JObject jAttachmentRecord in jAttachments["attach"]) + // { + // g.Notes += $"File: \"{jAttachmentRecord["name"].Value()}\", rfcaseblob table id: {jAttachmentRecord["id"].Value()}\n"; + + // } + // g.Notes += "\n********\n"; + // } + // } + // catch (Newtonsoft.Json.JsonReaderException jre) + // { + // log.LogError(jre, $"Error parsing attachment check for case {g.CaseId}, response text was {responseText}"); + // throw; + // } + + // GZCaseBiz biz = GZCaseBiz.GetBiz(ct); + // await biz.CreateAsync(g); + + // //attachments example 86400000 + // // /api/rfcase/4360/attachments + // //{"dlkey":"ZFkAUpo1L0Gi3Q9aO5szkA","attach":[{"id":259,"name":"desired weight calcs.txt"}]} + // //{"dlkey":"iR6ncD70CkzkozyT0otA","attach":[]} + + + + + // }// all cases loop + + // //Start next case with a new sequence caseid of 4444 + // using (var command = ct.Database.GetDbConnection().CreateCommand()) + // { + // command.CommandText = $"ALTER SEQUENCE agzcase_caseid_seq RESTART WITH 4444;"; + // await ct.Database.OpenConnectionAsync(); + // await command.ExecuteNonQueryAsync(); + // await ct.Database.CloseConnectionAsync(); + // } + // }//end of db context + // } + + // #endregion cases + + // #region LICENSES + // log.LogInformation("RFImport Licenses"); + // { + + // res = await client.GetAsync($"{URL_ROCKFISH}api/license/list"); + // responseText = await res.Content.ReadAsStringAsync(); + // var jaLicenseList = JArray.Parse(responseText); + // //some cases are missing the start date so substitute a close other case date (not critical but sb at least in the ballpark for list viewing purposes) + // DateTime dtTempCreated = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc); + // foreach (JObject jLicenseListItem in jaLicenseList.Reverse()) + // { + // using (AyContext ct = ServiceProviderProvider.DBContext) + // { + // JObject jLicense = null; + + // try + // { + + // res = await client.GetAsync($"{URL_ROCKFISH}api/license/{jLicenseListItem["id"].Value()}"); + // if (res.StatusCode == System.Net.HttpStatusCode.TooManyRequests) + // { + // await Task.Delay(Sockeye.Util.ServerBootConfig.FAILED_AUTH_DELAY); + // res = await client.GetAsync($"{URL_ROCKFISH}api/license/{jLicenseListItem["id"].Value()}"); + // } + // responseText = await res.Content.ReadAsStringAsync(); + // jLicense = JObject.Parse(responseText); + // } + // catch (Newtonsoft.Json.JsonReaderException jrex) + // { + // log.LogError(jrex, $"Error importing license, response text was:{responseText}"); + // throw; + // } + + // /* + // {"regTo":"PDI Technologies","customerName":"PDI Technologies","dtcreated":1672261044,"email":"jberkel@pdisoftware.com","code":"na","fetched":true,"dtfetched":1672262347,"fetchFrom":null, + // "key":"[KEY\n{\n \"Key\": {\n \"LicenseFormat\": \"8\",\n \"Id\": \"1672261044\",\n \"RegisteredTo\": \"PDI Technologies\",\n \"DBID\": \"R6U37uNUN2hSQideG6Gg+MqoQY8vuUeyHFI6Kv7VDsE=\",\n \"Perpetual\": true,\n \"LicenseExpiration\": \"5555-01-01T00:00:00\",\n \"MaintenanceExpiration\": \"2023-12-28T00:00:00\",\n \"Features\": [\n {\n \"Name\": \"ActiveInternalUsers\",\n \"Count\": 5\n }\n ]\n }\n}\nKEY]\n[SIGNATURE\nkzVs8GH0MSIfsR7ZYQ5x+5wdVDJqpfOYvTfBCx32Vs+zqP7h89uUKI17jTx5rMvkOYX40GyJt0pTWOzltljzf+MaoTzoSvTsSPkWtdVWv8ZGOXUUdaZhzMoTJGxTg0JHka/8S5tLkTiuct3x+voiLAKXuFCp9TSZo4+UnejB6U2Bp6MfdZxLtKVZ/1RLu/h4SnP8ZbczuwbQReB1z4k4IRwjh5GHnUUm6YqZg/04m1X9FEeKQZQfGZk/qZ788jONbLQb4CLnq0/ZmIteeocDDBz59TYaC9BHwHp73y8jyPfEugVfyH2AE0J8ZILiFiozYQ7meP5X4ZOmd1nhTA8MkA==\nSIGNATURE]\n" + // } + // */ + // var l = new License(); + // l.Active = true; + // l.RegTo = jLicense["regTo"].Value(); + + // //try to match customer; rockfish didn't track customer id in the license so this is a bit wishy washy + // Customer cust = null; + // cust = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.Name == jLicense["customerName"].Value()); + // if (cust == null)//email? + // cust = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.EmailAddress.Contains(jLicense["email"].Value())); + // if (cust != null) + // l.CustomerId = cust.Id; + + + + // var KeyText = jLicense["key"].Value(); + + // l.Key = KeyText; + // LicenseBiz.ParseKeySetDTOFields(l); + // if (KeyText.Contains("AyaNovaLicenseKey")) + // { + // //v7 key + // /* + // [KEY + // { + // "AyaNovaLicenseKey": { + // "SchemaVersion": "7", + // "Id": "1517418112", + // "Created": "2018-01-31T09:01:52.1878494-08:00", + // "Sub": "true", + // "RegisteredTo": "Direct Telecom Services", + // "EmailAddress": "chrisw@dts.solutions", + // "FetchCode": "AgYuDnjDyQ", + // "Source": "5246494432", + // "InstallableUntil": "2019-01-31T09:01:52.089767-08:00", + // "TotalScheduleableUsers": "15", + // "Expires": "2019-01-31T00:00:00", + // "RequestedTrial": "False", + // "Plugins": { + // "Plugin": [ + // { + // "Item": "MBI - Minimal browser interface", + // "SubscriptionExpires": "2018-06-13T00:00:00" + // }, + // { + // "Item": "WBI - Web browser interface", + // "SubscriptionExpires": "2018-06-13T00:00:00" + // }, + // { + // "Item": "OutlookSchedule", + // "SubscriptionExpires": "2018-06-13T00:00:00" + // }, + // { + // "Item": "AyaNovaOLI", + // "SubscriptionExpires": "2018-06-13T00:00:00" + // }, + // { + // "Item": "RI - Responsive Interface", + // "SubscriptionExpires": "2018-06-13T00:00:00" + // } + // ] + // } + // } + // } + // KEY] + // [SIGNATURE + // uBjnooIDd6MOiqT/z4tDQfeafkQiWDBtxDHXOxhZ7av1oWS72yPoe8BrAnDZiYbxE4+cHR3C0sPCgEVva5miV1foyi7P6YKkxkKQMxTUR5IssgWVHM59KnO1lR2ndCHWaqH3gHgSsb/sdvYfuHg8luTl1RgjNDZRdQqbPl4NLMcGGW86LoXjpLjsRRxImckBEJFnntd+aXCRmQjXEZWmfxDVW84qa6h+ZCOwL3KYJHuPQDcCmhcpp3MIR3OHoeYhmNG7TWuELsJ4hrsROcqSbEC/CdZD8hoZwtrysu/ZvNZOKchwFsiBaN47+DxK0K/fL/X8CDcG+w3iqgH/x5ipIw== + // SIGNATURE] + + // */ + // string keyNoWS = System.Text.RegularExpressions.Regex.Replace(StringUtil.Extract(KeyText, "[KEY", "KEY]").Trim(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1"); + // var jKey = JObject.Parse(keyNoWS); + + // //In v7 the license expires is an optional property set called "LockDate" + // l.LicenseExpire = null; + // if (jKey["AyaNovaLicenseKey"]["LockDate"] != null) + // l.LicenseExpire = jKey["AyaNovaLicenseKey"]["LockDate"].Value().ToUniversalTime(); + + // l.MaintenanceExpire = jKey["AyaNovaLicenseKey"]["Expires"].Value().ToUniversalTime(); + // //l.Users=jKey["AyaNovaLicenseKey"]["TotalScheduleableUsers"].Value(); + // l.PGroup = ProductGroup.AyaNova7; + // l.FetchCode = jLicense["code"].Value(); + + // } + // else if (KeyText.Contains("AyaNovaLiteLicenseKey")) + // { + // /* + // "[KEY\n{\n \"AyaNovaLiteLicenseKey\": {\n \"SchemaVersion\": \"7\",\n \"Id\": \"1648506791\",\n \"Created\": \"2022-03-28T15:33:11.6010225-07:00\",\n + // \"Sub\": \"true\",\n \"RegisteredTo\": \"Duncan Electric\",\n \"EmailAddress\": \"sandrajod@att.net\",\n + // \"FetchCode\": \"hGAmScqYcU\",\n \"Source\": \"5246494431\",\n \"InstallableUntil\": \"2023-03-28T15:33:11.6009851-07:00\",\n + // \"TotalScheduleableUsers\": \"1\",\n \"Expires\": \"2023-03-29T00:00:00\",\n \"RequestedTrial\": \"False\",\n \"Plugins\": {\n + // \"Plugin\": []\n }\n }\n}\nKEY]\n + // [SIGNATURE\nKuOF/SpBL1d8AFebvm2lipmKeGdbR6WzbhN68fun+ffVGRjXNX1jWI3rbf9P/shs2/M8gHqW/B7T0vVovGqosmNsGtvaYo30TKlZj9Eicr2+zDf7ojwZiBCeEnFzXr9+7aZrsZSvN20Pqof0xf/J4BVp1T66ecuZywMzH0NGsXXZtXhWYhGvLAZAR1X5/j5gqysSdysmV9j8Euz91zs/BRyfdU0uwwrdQzrJzI4V1MFl+/mIkhMUNcJ5bzjisWS2xeyNYCYnGpMF5oaGPaIcEtmTAdf5fPNNvw3sNhPaZgwlzN8FjfK6T0VgS19PcHCMOA1bTAiLLFNk6wkcjGp2Cw==\nSIGNATURE]\n" + // */ + // string keyNoWS = System.Text.RegularExpressions.Regex.Replace(StringUtil.Extract(KeyText, "[KEY", "KEY]").Trim(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1"); + // var jKey = JObject.Parse(keyNoWS); + // //In v7 the license expires is an optional property set called "LockDate" + // l.LicenseExpire = null; + // if (jKey["AyaNovaLiteLicenseKey"]["LockDate"] != null) + // l.LicenseExpire = jKey["AyaNovaLiteLicenseKey"]["LockDate"].Value().ToUniversalTime(); + + // l.MaintenanceExpire = jKey["AyaNovaLiteLicenseKey"]["Expires"].Value().ToUniversalTime(); + + // l.PGroup = ProductGroup.AyaNova7; + // l.FetchCode = jLicense["code"].Value(); + + // l.Tags.Add("lite"); + // } + // else + // { + // //RAVEN KEY + // /* + // {{ + // "Key": { + // "LicenseFormat": "8", + // "Id": "1672261044", + // "RegisteredTo": "PDI Technologies", + // "DBID": "R6U37uNUN2hSQideG6Gg+MqoQY8vuUeyHFI6Kv7VDsE=", + // "Perpetual": true, + // "LicenseExpiration": "5555-01-01T00:00:00", + // "MaintenanceExpiration": "2023-12-28T00:00:00", + // "Features": [ + // { + // "Name": "ActiveInternalUsers", + // "Count": 5 + // } + // ] + // } + // }} + // */ + // string keyNoWS = System.Text.RegularExpressions.Regex.Replace(StringUtil.Extract(KeyText, "[KEY", "KEY]").Trim(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1"); + // var jKey = JObject.Parse(keyNoWS); + // l.DbId = jKey["Key"]["DBID"].Value(); + // l.LicenseExpire = jKey["Key"]["LicenseExpiration"].Value().ToUniversalTime(); + // //if (jKey["Key"]["Perpetual"].Value()) + // if ((bool?)jKey["Key"]["Perpetual"] ?? true) + // l.PGroup = ProductGroup.RavenPerpetual; + // else + // l.PGroup = ProductGroup.RavenSubscription; + // l.MaintenanceExpire = jKey["Key"]["MaintenanceExpiration"].Value().ToUniversalTime(); + // } + + // l.Created = (DateTime)DateUtil.EpochToDateNullIsNull(jLicense["dtcreated"].Value()); + // l.FetchedOn = DateUtil.EpochToDateNullIsNull(jLicense["dtfetched"].Value()); + // l.FetchEmail = jLicense["email"].Value(); + // // l.Key = jLicense["key"].Value(); + + // l.Active = true;//active here means it's been fully prepared and is viable for use, all prior licenses fit this description so all are active + // l.NotificationSent = true;//prevent new notification being sent + // LicenseBiz biz = LicenseBiz.GetBiz(ct); + // await biz.CreateAsync(l, true); + // }//context + + // }// all licenses loop + + + // } + // #endregion licenses + + // #region TRIAL LICENSE REQUESTS + // log.LogInformation("RFImport Raven trial requests"); + // { + + // res = await client.GetAsync($"{URL_ROCKFISH}api/trial/list"); + // responseText = await res.Content.ReadAsStringAsync(); + // var jaTrialRequestList = JArray.Parse(responseText); + + // foreach (JObject jTrialRequestItem in jaTrialRequestList.Reverse()) + // { + // /* + // /api/trial/list + // [ + // { + // "id": 296, + // "dbId": "R6U37uNUN2hSQideG6Gg+MqoQY8vuUeyHFI6Kv7VDsE=", + // "perpetual": true, + // "companyName": "PDI Technologies", + // "contactName": "Jason Berkel", + // "notes": null, + // "email": "jberkel@pdisoftware.com", + // "emailConfirmCode": "296RuWFbzuEps", + // "emailValidated": true, + // "dtRequested": 1672257483, + // "dtProcessed": 1672257587, + // "status": 1, + // "rejectReason": null, + // "key": "[KEY\n{\n \"Key\": {\n \"LicenseFormat\": \"8\",\n \"Id\": \"1672257587\",\n \"RegisteredTo\": \"PDI Technologies\",\n \"DBID\": \"R6U37uNUN2hSQideG6Gg+MqoQY8vuUeyHFI6Kv7VDsE=\",\n \"Perpetual\": true,\n \"LicenseExpiration\": \"2023-01-04T19:59:47.6170429Z\",\n \"MaintenanceExpiration\": \"2023-01-04T19:59:47.6170429Z\",\n \"Features\": [\n {\n \"Name\": \"TrialMode\"\n },\n {\n \"Name\": \"ActiveInternalUsers\",\n \"Count\": 5000\n }\n ]\n }\n}\nKEY]\n[SIGNATURE\ng/9yvrUi18PsllDyc4SJSlngmW3n411OtlFaGl3nK5SznCMf7CFDxH6eRqrvpI4452RblqAquHmsUUwFHIzKjaIj1VF3z1X9RHz7BcPrNX7lvWM8ErJb0jJjylKxvecaalMPXVxR1QLULDBFdVT5Gv0QUIzkFKVSwAF2mLUg1JNut939YoG2u95ABeQNe4SH7WQ3+gcsI/qSLcbzz/PmRMrWqPOzXi7jVbZTigfZLdbSC+DlUbNsCvkSgraEwBBnCpE8ZfCG1oFjdbP64qF1ArY7DbPUuxHNfPSZcDlhQz8D7JIqLTQwEijqvKfLy/KNMSlcfQtv5VBJtlwCP9ggdQ==\nSIGNATURE]\n", + // "dtFetched": 1672257635 + // }, + // */ + + // using (AyContext ct = ServiceProviderProvider.DBContext) + // { + // //Save Key first then can set keyid on tlr + // long? TrialKeyId = null; + // { + // string sKey = jTrialRequestItem["key"].Value(); + // if (!string.IsNullOrWhiteSpace(sKey)) + // { + // License l = new License(); + // l.TrialMode = true; + + // l.Key = sKey; + // //get number of users count and features etc + // LicenseBiz.ParseKeySetDTOFields(l); + + // //Parse key as we need the expiry dates and they are only stored in the key not the trial request + // string keyNoWS = System.Text.RegularExpressions.Regex.Replace(StringUtil.Extract(l.Key, "[KEY", "KEY]").Trim(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1"); + // var jKey = JObject.Parse(keyNoWS); + + + // l.RegTo = jKey["Key"]["RegisteredTo"].Value(); + + // //try to match customer; rockfish didn't track customer id in the license so this is a bit wishy washy + // Customer cust = null; + // cust = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.Name == l.RegTo); + // if (cust == null)//email? + // cust = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.EmailAddress.Contains(jTrialRequestItem["email"].Value())); + // if (cust != null) + // l.CustomerId = cust.Id; + + + // l.DbId = jKey["Key"]["DBID"].Value(); + // l.LicenseExpire = jKey["Key"]["LicenseExpiration"].Value().ToUniversalTime(); + // if ((bool?)jKey["Key"]["Perpetual"] ?? true) + // l.PGroup = ProductGroup.RavenPerpetual; + // else + // l.PGroup = ProductGroup.RavenSubscription; + // l.MaintenanceExpire = jKey["Key"]["MaintenanceExpiration"].Value().ToUniversalTime(); + // l.Created = DateUtil.EpochToDateNullIsMin(jTrialRequestItem["dtProcessed"].Value()); + // l.FetchedOn = DateUtil.EpochToDateNullIsNull(jTrialRequestItem["dtFetched"].Value()); + // l.FetchEmail = jTrialRequestItem["email"].Value(); + + // l.Active = true;//active here means it's been fully prepared and is viable for use, all prior licenses fit this description so all are active + // l.NotificationSent = true;//prevent resending + // //workaround sketchy old testing licenses + // if (l.PGroup == ProductGroup.RavenSubscription) + // { + // if (l.MaxDataGB == null || l.MaxDataGB == 0) + // l.MaxDataGB = 20; + + // if (l.CustomerUsers == null || l.CustomerUsers == 0) + // l.CustomerUsers = 250; + + + // } + + + + // LicenseBiz lbiz = LicenseBiz.GetBiz(ct); + // var newLicenseObject = await lbiz.CreateAsync(l, true); + + // #if (DEBUG) + // if (newLicenseObject == null) + // { + // System.Diagnostics.Debugger.Break(); + // } + // #endif + // TrialKeyId = newLicenseObject.Id; + + // } + // } + + // { + // var tlr = new TrialLicenseRequest(); + // tlr.DbId = jTrialRequestItem["dbId"].Value(); + // tlr.PGroup = (jTrialRequestItem["perpetual"].Value() ? ProductGroup.RavenPerpetual : ProductGroup.RavenSubscription); + // tlr.CompanyName = jTrialRequestItem["companyName"].Value(); + // tlr.ContactName = jTrialRequestItem["contactName"].Value(); + // tlr.Email = jTrialRequestItem["email"].Value(); + // tlr.EmailConfirmCode = jTrialRequestItem["emailConfirmCode"].Value(); + // tlr.EmailValidated = jTrialRequestItem["emailValidated"].Value(); + // tlr.Requested = (DateTime)DateUtil.EpochToDateNullIsNull(jTrialRequestItem["dtRequested"].Value()); + // tlr.Processed = DateUtil.EpochToDateNullIsNull(jTrialRequestItem["dtProcessed"].Value()); + + // /* + // rockfish status differs numerically + // switch (obj.status) { + // case 0: + // return "NEW"; + // case 1: + // return "approved"; + // case 2: + // return "rejected"; + // default: + // return "BAD STATUS: " + obj.status; + // } + + // sockeye: + // New = 0, + // AwaitingEmailValidation = 1, + // AwaitingApproval = 2, + // Approved = 3, + // Rejected = 4 + // */ + // switch (jTrialRequestItem["status"].Value()) + // { + // case 0: + // tlr.Status = TrialRequestStatus.New; + // break; + // case 1: + // tlr.Status = TrialRequestStatus.Approved; + // break; + // case 2: + // tlr.Status = TrialRequestStatus.Rejected; + // break; + // default: + // tlr.Status = TrialRequestStatus.Rejected;//just set unknowns to rejected + // break; + // } + // tlr.RejectReason = jTrialRequestItem["rejectReason"].Value(); + // tlr.LicenseId = TrialKeyId; + // var biz = TrialLicenseRequestBiz.GetBiz(ct); + // await biz.CreateAsync(tlr, true); + // } + + // }//context + // }// all trial requests loop + + + // } + // #endregion trial requests + + // log.LogInformation("RockFish import succeeded"); + // } + // catch (Exception ex) + // { + // var msg = "*** RockFish import FAILED ***"; + // log.LogError(ex, msg); + // } + // finally + // { + // ServerBootConfig.MIGRATING = false; + // log.LogInformation($"Migrate Rockfish: setting server state back to {wasServerState.ToString()}"); + // apiServerState.SetState(wasServerState, wasReason); + // } + + + + // //in the correct order retrieve every object and if it's not already present in sockeye, import it + // //this should be callable any time and it will just update so it can be test live in sync / parallel until ready to switch over + // //await Task.CompletedTask; + + // } + + #endregion import from rockfish - //IMPORT FROM ROCKFISH - - public static async Task ImportRockfish(ILogger log) - { - log.LogInformation("Start import from rockfish, authenticating"); - ApiServerState apiServerState = (ApiServerState)ServiceProviderProvider.Provider.GetService(typeof(ApiServerState)); - - //get the current server state so can set back to it later - ApiServerState.ServerState wasServerState = apiServerState.GetState(); - string wasReason = apiServerState.Reason; - apiServerState.SetOpsOnly("Migrating from Rockfish"); - ServerBootConfig.MIGRATING = true; - - //Authenticate to rockfish - //string sUrl = $"{LICENSE_SERVER_URL_ROCKFISH}rvr"; - string URL_ROCKFISH = "https://rockfish.ayanova.com/"; - - try - { - //var content = new StringContent("login=john&password=b43698c255365ee739c05ba0d42855e96c2365c76bb2f9b9eb149cec7b52174c"); - var content = new StringContent(JsonConvert.SerializeObject(new - { - login = "john", - password = "b43698c255365ee739c05ba0d42855e96c2365c76bb2f9b9eb149cec7b52174c" - }), Encoding.UTF8, "application/json"); - - var client = ServiceProviderProvider.HttpClientFactory.CreateClient(); - - //AUTHENTICATE - var res = await client.PostAsync($"{URL_ROCKFISH}authenticate?login=john&password=b43698c255365ee739c05ba0d42855e96c2365c76bb2f9b9eb149cec7b52174c", content); - var responseText = await res.Content.ReadAsStringAsync(); - - if (!res.IsSuccessStatusCode) - throw new Exception($"E1020 - Error authenticating to rockfish: {res.ReasonPhrase}"); - - var responseJson = JObject.Parse(responseText); - - var authToken = responseJson["token"].Value(); - var dlKey = responseJson["dlkey"].Value(); - var userId = responseJson["id"].Value(); - - var contentType = new MediaTypeWithQualityHeaderValue("application/json"); - client.DefaultRequestHeaders.Accept.Add(contentType); - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken); - - #region CUSTOMERS - log.LogInformation("RFImport customers"); - - res = await client.GetAsync($"{URL_ROCKFISH}api/customer/list"); - responseText = await res.Content.ReadAsStringAsync(); - var jaCustomerList = JArray.Parse(responseText); - - foreach (JObject jCustomerListItem in jaCustomerList) - { - res = await client.GetAsync($"{URL_ROCKFISH}api/customer/{jCustomerListItem["id"].Value()}"); - - var jCustomer = JObject.Parse(await res.Content.ReadAsStringAsync()); - var CustomerName = jCustomer["name"].Value(); - //SITES - res = await client.GetAsync($"{URL_ROCKFISH}api/customer/{jCustomerListItem["id"].Value()}/sites"); - var jaSiteList = JArray.Parse(await res.Content.ReadAsStringAsync()); - - bool multiSite = jaSiteList.Count() > 1; - - foreach (JObject jSite in jaSiteList) - { - long CurrentCustomerId = 0; - using (AyContext ct = ServiceProviderProvider.DBContext) - { - - if (multiSite) - { - CustomerName = $"{jCustomer["name"].Value()} - {jSite["name"].Value()}"; - log.LogInformation($"RFImport MULTISITE CUSTOMER: {CustomerName}"); - } - - - //Create customer if we don't have one already - if (await ct.Customer.AnyAsync(z => z.Name == CustomerName)) - continue;//already have this one so no need to process it again - { - //CREATE CUSTOMER - Customer c = new Customer(); - c.Active = jCustomerListItem["active"].Value(); - c.Name = CustomerName; - c.Country = jSite["country"].Value(); - c.Region = jSite["stateProvince"].Value(); - c.DoNotContact = jCustomer["doNotContact"].Value(); - c.Notes = jCustomer["notes"].Value(); - c.DbId = jSite["dbId"].Value(); - if (c.DbId == "v7_no_dbid") - { - c.DbId = null; - c.Tags.Add("v7"); - } - else - c.Tags.Add("raven"); - - if (jSite["hosted"].Value() == true) - c.Tags.Add("hosted"); - - //In rockfish there were support emails that were people allowed to be contacting us on behalf of the customer - var supportEmail = jCustomer["supportEmail"].Value(); - if (!string.IsNullOrWhiteSpace(supportEmail)) - c.Notes += "\nSupport Emails: " + supportEmail; - //in Rockfish the admin email is the main license related contact and technically the only person responsible to contact us - //usually the same as the purchase email - c.EmailAddress = jCustomer["adminEmail"].Value(); - CustomerBiz biz = CustomerBiz.GetBiz(ct); - var NewObject = await biz.CreateAsync(c); - CurrentCustomerId = NewObject.Id; - }//customer creation - }//context - - - //SITE PURCHASES - res = await client.GetAsync($"{URL_ROCKFISH}api/site/{jSite["id"].Value()}/purchases"); - var jaPurchaseList = JArray.Parse(await res.Content.ReadAsStringAsync()); - - foreach (JObject jPurchase in jaPurchaseList) - { - using (AyContext ct = ServiceProviderProvider.DBContext) - { - //create product if not exist then import - //Get product id if exists - var ProductName = jPurchase["name"].Value(); - bool maybeRenewal = ProductName.ToLowerInvariant().Contains("renew"); - ProductName = ProductName.Replace("- Renewal", "").Replace(" Renewal", "").Replace(" RENEWAL", "").Replace("CANCELLED ", "").Replace("CANCELED ", ""); - var p = await ct.Product.AsNoTracking().FirstOrDefaultAsync(z => z.VendorCode == jPurchase["productCode"].Value()); - - - if (p == null) - { - - //Create it here - p = new Product(); - p.Name = ProductName; - p.Active = true;//not entirely true but we can always deactivate there aren't many products - p.VendorId = 1; - p.OurCode = p.VendorCode = jPurchase["productCode"].Value(); - p.PGroup = ProductBiz.ProductGroupFromProductCode(p.OurCode); - - if (p.VendorCode == "301028468")//subscription yearly - { - p.LicenseInterval = new TimeSpan(365, 0, 0, 0); //actual length, in license is where I pad to cover them - } - - if (p.VendorCode == "301028467")//subscription monthly - { - p.LicenseInterval = new TimeSpan(31, 0, 0, 0);//there is no concept beyond days for timespan so a month is 31 days max - p.MaintInterval = new TimeSpan(31, 0, 0, 0);//the only product less than one year of maintenance save the ones with no maintenance which can be edited manually later as there are so few of them - } - else - p.MaintInterval = new TimeSpan(365, 0, 0, 0); - - ProductBiz biz = ProductBiz.GetBiz(ct); - p = await biz.CreateAsync(p); - } - - //Now we can add the sale that we have the product - if (!await ct.Purchase.AnyAsync(z => z.SalesOrderNumber == jPurchase["salesOrderNumber"].Value())) - { - var s = new Purchase(); - s.VendorId = 1; - s.ProductId = p.Id; - s.PGroup = p.PGroup; - s.CustomerId = CurrentCustomerId; - s.RegTo = CustomerName; - s.CancelDate = DateUtil.EpochToDateNullIsNull(jPurchase["cancelDate"].Value()); - s.CouponCode = jPurchase["couponCode"].Value(); - s.ExpireDate = DateUtil.EpochToDateNullIsNull(jPurchase["expireDate"].Value()); - s.Name = p.Name; - s.Processed = true; - s.PurchaseDate = DateUtil.EpochToDateNullIsMin(jPurchase["purchaseDate"].Value()); - s.Quantity = jPurchase["quantity"].Value(); - s.RenewNoticeSent = jPurchase["renewNoticeSent"].Value(); - s.SalesOrderNumber = jPurchase["salesOrderNumber"].Value(); - s.Notes = jPurchase["notes"].Value(); - s.IsRenewal = maybeRenewal; - PurchaseBiz biz = PurchaseBiz.GetBiz(ct); - await biz.CreateAsync(s); - } - }//context - } - - - - }//site loop - - }//end of all customers iteration - - #endregion customers - - #region VENDOR NOTIFICATIONS - log.LogInformation("RFImport Vendor notifications"); - { - - res = await client.GetAsync($"{URL_ROCKFISH}api/vendor-notifications/list"); - responseText = await res.Content.ReadAsStringAsync(); - var jaVendorNotificationList = JArray.Parse(responseText); - - foreach (JObject jVendorNotificationItem in jaVendorNotificationList.Reverse()) - { - /*[] - "{\n \"creation_date\": \"2022-12-28T20:20:24Z\",\n \ - "id\": 356247074,\n \ - "order_notification\": {\n \ - "purchase\": {\n \"customer_data\": {\n \"billing_contact\": {\n \"address\": {\n \"city\": \"Alpharetta\",\n \"country\": \"USA\",\n \"country_id\": \"US\",\n - \"postal_code\": \"30009\",\n \"state\": \"Georgia\",\n \"state_id\": \"GA\",\n \"street1\": \"11675 Rainwater Dr., Suite 350\"\n }, - \n …tart\": \"\",\n \"renewal_type\": \"auto\",\n \"retention_discount_count\": \"\",\n \"retention_discount_percent\": \"\",\n \ - "start_date\": \"2022-12-28T00:00:00\",\n \"status\": \"ToProcess\",\n \"status_id\": \"TOP\"\n },\n \ - "vat_pct\": 0.0,\n \"your_product_id\": \"perpetual\"\n }\n ],\n - \"purchase_origin\": \"online\",\n \"sequential_invoice_no\": \"e5-US-2022-00001637070\"\n }\n }\n}" - - { - "id": 25, - "dtCreated": 1670375661, - "vendor": "shareit", - "data": "{\n \"creation_date\": \"2022-12-07T01:14:19Z\",\n \"id\": 354935062,\n \"order_notification\": {\n \"purchase\": {\n \"customer_data\": {\n \"billing_contact\": {\n \"address\": {\n \"city\": \"Abbotsford\",\n \"country\": \"Canada\",\n \"country_id\": \"CA\",\n \"postal_code\": \"V2S 8M1\",\n \"state\": \"British Columbia\",\n \"state_id\": \"BC\",\n \"street1\": \"35355 McKee Rd\"\n },\n \"company\": \"Adtech Systems Inc.\",\n \"email\": \"erling@myadtech.com\",\n \"first_name\": \"Erling\",\n \"last_name\": \"Lassesen\"\n },\n \"customer_payment_data\": {\n \"currency\": \"USD\",\n \"payment_method\": \"PayPal\"\n },\n \"delivery_contact\": {\n \"address\": {\n \"city\": \"Abbotsford\",\n \"country\": \"Canada\",\n \"country_id\": \"CA\",\n \"postal_code\": \"V2S 8M1\",\n \"state\": \"British Columbia\",\n \"state_id\": \"BC\",\n \"street1\": \"35355 McKee Rd\"\n },\n \"company\": \"Adtech Systems Inc.\",\n \"email\": \"erling@myadtech.com\",\n \"first_name\": \"Erling\",\n \"last_name\": \"Lassesen\"\n },\n \"language\": \"English\",\n \"language_iso\": \"en\",\n \"reg_name\": \"Adtech Systems Inc.\",\n \"shopper_id\": \"50862261\",\n \"subscribe_newsletter\": true,\n \"user_id\": \"erling@adtech-systems.com-4\"\n },\n \"is_test\": false,\n \"payment_complete_date\": \"2022-12-07T01:14:19Z\",\n \"payment_status\": \"complete\",\n \"payment_status_id\": \"PCA\",\n \"purchase_date\": \"2022-12-07T01:14:16Z\",\n \"purchase_id\": 833707313,\n \"purchase_item\": [\n {\n \"accounting\": {\n \"currency\": \"USD\",\n \"product_net\": 55.65,\n \"discount\": 0.0,\n \"product_vat\": 6.68,\n \"shipping\": 0.0,\n \"shipping_vat\": 0.0,\n \"eu_vat\": -6.68,\n \"margin_net\": -5.44,\n \"your_revenue\": 50.21\n },\n \"additional_information\": [\n {\n \"additional_id\": \"ADDITIONAL1\",\n \"additional_value\": \"YES\"\n },\n {\n \"additional_id\": \"ADDITIONAL2\",\n \"additional_value\": \"YES\"\n },\n {\n \"additional_id\": \"ADDITIONAL3\",\n \"additional_value\": \"YES\"\n }\n ],\n \"currency\": \"USD\",\n \"delivery_type\": \"Electronically\",\n \"discount\": 0.0,\n \"extended_download_price\": 0.0,\n \"manual_order_price\": 0.0,\n \"notification_no\": 7926,\n \"product_id\": 300740315,\n \"product_name\": \"Single AyaNova schedulable resource 1 year subscription license\",\n \"product_single_price\": 55.65,\n \"purchase_item_key\": [],\n \"quantity\": 1,\n \"running_no\": 1,\n \"shipping_price\": 0.0,\n \"shipping_vat_pct\": 0.0,\n \"subscription\": {\n \"expiration_date\": \"2023-12-07T17:28:16Z\",\n \"id\": \"550286373-1\",\n \"interval\": \"Yearly without end\",\n \"original_notification_no\": \"6872\",\n \"original_purchase_id\": \"550286373\",\n \"original_running_no\": \"1\",\n \"renewal_discount_count\": \"\",\n \"renewal_discount_start\": \"\",\n \"renewal_type\": \"auto\",\n \"retention_discount_count\": \"\",\n \"retention_discount_percent\": \"\",\n \"start_date\": \"2017-12-07T00:00:00\",\n \"status\": \"ToProcess\",\n \"status_id\": \"TOP\"\n },\n \"vat_pct\": 12.0\n }\n ],\n \"purchase_origin\": \"Subscription\",\n \"sequential_invoice_no\": \"e5-DE-2022-00002647549\"\n }\n }\n}", - "dtProcessed": null, - "processed": false - }, - */ - using (AyContext ct = ServiceProviderProvider.DBContext) - { - var vn = new VendorNotification(); - vn.Created = DateUtil.EpochToDateNullIsMin(jVendorNotificationItem["dtCreated"].Value()); - vn.VendorId = 1; - vn.VendorData = jVendorNotificationItem["data"].Value(); - vn.Processed = vn.Created;//indicate it's been processed - ct.VendorNotification.Add(vn); - await ct.SaveChangesAsync(); - - - // #if (DEBUG) - // //Test dev stuff - // #warning DEV TEST ORDER PROCESSING REMOVE THIS WHEN DONE - // if (!string.IsNullOrWhiteSpace(vn.VendorData)) - // await SockBotProcessVendorNotifications.ParseVendorNotificationData(vn, ct, log); - // #endif - } - - }// all vendor notifications loop - } - #endregion vendor notifications - - #region CASES - - log.LogInformation("RFImport Cases"); - //case projects to be tags - List CaseProjectList = new List(); - { - res = await client.GetAsync($"{URL_ROCKFISH}api/rfcaseproject"); - responseText = await res.Content.ReadAsStringAsync(); - - var jaRFCaseProjectList = JArray.Parse(responseText); - foreach (JObject jRFCaseProject in jaRFCaseProjectList) - { - CaseProjectList.Add(new NameIdItem() { Name = jRFCaseProject["name"].Value(), Id = jRFCaseProject["id"].Value() }); - - } - - } - { - using (AyContext ct = ServiceProviderProvider.DBContext) - { - res = await client.GetAsync($"{URL_ROCKFISH}api/rfcase/list"); - responseText = await res.Content.ReadAsStringAsync(); - var jaRFCaseList = JArray.Parse(responseText); - //some cases are missing the start date so substitute a close other case date (not critical but sb at least in the ballpark for list viewing purposes) - DateTime dtTempCreated = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc); - foreach (JObject jRFCase in jaRFCaseList.Reverse()) - { - - - var g = new GZCase(); - g.CaseId = jRFCase["id"].Value(); - g.Closed = DateUtil.EpochToDateNullIsNull(jRFCase["dtClosed"].Value()); - //NOTE: closed in rockfish was the date at midnight in GMT - //so to be in the same day as here need to add a few hours, let's say 8 am for each so add 8 hours - if (g.Closed != null) - { - g.Closed = ((DateTime)g.Closed).AddHours(16); - } - - //fuckery to try to insert a at least semi close date when created date is missing - DateTime? dtTemp = DateUtil.EpochToDateNullIsNull(jRFCase["dtCreated"].Value()); - if (dtTemp == null) - { - dtTemp = dtTempCreated; - } - else - { - dtTempCreated = (DateTime)dtTemp; - } - g.Created = (DateTime)dtTemp; - g.Name = jRFCase["title"].Value(); - g.Notes = jRFCase["notes"].Value(); - - var ver = jRFCase["releaseVersion"].Value(); - if (!string.IsNullOrWhiteSpace(ver)) - g.Notes += $"\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\nReleased on version:{ver}"; - - var releaseNotes = jRFCase["releaseNotes"].Value(); - if (!string.IsNullOrWhiteSpace(releaseNotes)) - g.Notes += $"\nRelease notes:{releaseNotes}"; - - //Project name to tags - g.Tags.Add(CaseProjectList.FirstOrDefault(z => z.Id == jRFCase["rfCaseProjectId"].Value()).Name.Replace("z_", "legacy-")); - - //priority to tags - g.Tags.Add($"{jRFCase["priority"].Value()}-priority"); - - - - //check for attachments and just add as a note, don't bother with actual transfer of attachment, there aren't a lot and most are way in the past and not required for anything - //if needed in future can manually xfer it over from the rockfish.sqlite db directly using DB BRowser for sqlite which allows opening the blob from the rfcaseblob table and saving it - res = await client.GetAsync($"{URL_ROCKFISH}api/rfcase/{g.CaseId}/attachments"); - responseText = await res.Content.ReadAsStringAsync(); - try - { - var jAttachments = JObject.Parse(responseText); - if (jAttachments["attach"].Count() > 0) - { - g.Notes += "\n********\nRockfish attachments\n"; - foreach (JObject jAttachmentRecord in jAttachments["attach"]) - { - g.Notes += $"File: \"{jAttachmentRecord["name"].Value()}\", rfcaseblob table id: {jAttachmentRecord["id"].Value()}\n"; - - } - g.Notes += "\n********\n"; - } - } - catch (Newtonsoft.Json.JsonReaderException jre) - { - log.LogError(jre, $"Error parsing attachment check for case {g.CaseId}, response text was {responseText}"); - throw; - } - - GZCaseBiz biz = GZCaseBiz.GetBiz(ct); - await biz.CreateAsync(g); - - //attachments example 86400000 - // /api/rfcase/4360/attachments - //{"dlkey":"ZFkAUpo1L0Gi3Q9aO5szkA","attach":[{"id":259,"name":"desired weight calcs.txt"}]} - //{"dlkey":"iR6ncD70CkzkozyT0otA","attach":[]} - - - - - }// all cases loop - - //Start next case with a new sequence caseid of 4444 - using (var command = ct.Database.GetDbConnection().CreateCommand()) - { - command.CommandText = $"ALTER SEQUENCE agzcase_caseid_seq RESTART WITH 4444;"; - await ct.Database.OpenConnectionAsync(); - await command.ExecuteNonQueryAsync(); - await ct.Database.CloseConnectionAsync(); - } - }//end of db context - } - - #endregion cases - - #region LICENSES - log.LogInformation("RFImport Licenses"); - { - - res = await client.GetAsync($"{URL_ROCKFISH}api/license/list"); - responseText = await res.Content.ReadAsStringAsync(); - var jaLicenseList = JArray.Parse(responseText); - //some cases are missing the start date so substitute a close other case date (not critical but sb at least in the ballpark for list viewing purposes) - DateTime dtTempCreated = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc); - foreach (JObject jLicenseListItem in jaLicenseList.Reverse()) - { - using (AyContext ct = ServiceProviderProvider.DBContext) - { - JObject jLicense = null; - - try - { - - res = await client.GetAsync($"{URL_ROCKFISH}api/license/{jLicenseListItem["id"].Value()}"); - if (res.StatusCode == System.Net.HttpStatusCode.TooManyRequests) - { - await Task.Delay(Sockeye.Util.ServerBootConfig.FAILED_AUTH_DELAY); - res = await client.GetAsync($"{URL_ROCKFISH}api/license/{jLicenseListItem["id"].Value()}"); - } - responseText = await res.Content.ReadAsStringAsync(); - jLicense = JObject.Parse(responseText); - } - catch (Newtonsoft.Json.JsonReaderException jrex) - { - log.LogError(jrex, $"Error importing license, response text was:{responseText}"); - throw; - } - - /* - {"regTo":"PDI Technologies","customerName":"PDI Technologies","dtcreated":1672261044,"email":"jberkel@pdisoftware.com","code":"na","fetched":true,"dtfetched":1672262347,"fetchFrom":null, - "key":"[KEY\n{\n \"Key\": {\n \"LicenseFormat\": \"8\",\n \"Id\": \"1672261044\",\n \"RegisteredTo\": \"PDI Technologies\",\n \"DBID\": \"R6U37uNUN2hSQideG6Gg+MqoQY8vuUeyHFI6Kv7VDsE=\",\n \"Perpetual\": true,\n \"LicenseExpiration\": \"5555-01-01T00:00:00\",\n \"MaintenanceExpiration\": \"2023-12-28T00:00:00\",\n \"Features\": [\n {\n \"Name\": \"ActiveInternalUsers\",\n \"Count\": 5\n }\n ]\n }\n}\nKEY]\n[SIGNATURE\nkzVs8GH0MSIfsR7ZYQ5x+5wdVDJqpfOYvTfBCx32Vs+zqP7h89uUKI17jTx5rMvkOYX40GyJt0pTWOzltljzf+MaoTzoSvTsSPkWtdVWv8ZGOXUUdaZhzMoTJGxTg0JHka/8S5tLkTiuct3x+voiLAKXuFCp9TSZo4+UnejB6U2Bp6MfdZxLtKVZ/1RLu/h4SnP8ZbczuwbQReB1z4k4IRwjh5GHnUUm6YqZg/04m1X9FEeKQZQfGZk/qZ788jONbLQb4CLnq0/ZmIteeocDDBz59TYaC9BHwHp73y8jyPfEugVfyH2AE0J8ZILiFiozYQ7meP5X4ZOmd1nhTA8MkA==\nSIGNATURE]\n" - } - */ - var l = new License(); - l.Active = true; - l.RegTo = jLicense["regTo"].Value(); - - //try to match customer; rockfish didn't track customer id in the license so this is a bit wishy washy - Customer cust = null; - cust = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.Name == jLicense["customerName"].Value()); - if (cust == null)//email? - cust = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.EmailAddress.Contains(jLicense["email"].Value())); - if (cust != null) - l.CustomerId = cust.Id; - - - - var KeyText = jLicense["key"].Value(); - - l.Key = KeyText; - LicenseBiz.ParseKeySetDTOFields(l); - if (KeyText.Contains("AyaNovaLicenseKey")) - { - //v7 key - /* - [KEY - { - "AyaNovaLicenseKey": { - "SchemaVersion": "7", - "Id": "1517418112", - "Created": "2018-01-31T09:01:52.1878494-08:00", - "Sub": "true", - "RegisteredTo": "Direct Telecom Services", - "EmailAddress": "chrisw@dts.solutions", - "FetchCode": "AgYuDnjDyQ", - "Source": "5246494432", - "InstallableUntil": "2019-01-31T09:01:52.089767-08:00", - "TotalScheduleableUsers": "15", - "Expires": "2019-01-31T00:00:00", - "RequestedTrial": "False", - "Plugins": { - "Plugin": [ - { - "Item": "MBI - Minimal browser interface", - "SubscriptionExpires": "2018-06-13T00:00:00" - }, - { - "Item": "WBI - Web browser interface", - "SubscriptionExpires": "2018-06-13T00:00:00" - }, - { - "Item": "OutlookSchedule", - "SubscriptionExpires": "2018-06-13T00:00:00" - }, - { - "Item": "AyaNovaOLI", - "SubscriptionExpires": "2018-06-13T00:00:00" - }, - { - "Item": "RI - Responsive Interface", - "SubscriptionExpires": "2018-06-13T00:00:00" - } - ] - } - } - } - KEY] - [SIGNATURE - uBjnooIDd6MOiqT/z4tDQfeafkQiWDBtxDHXOxhZ7av1oWS72yPoe8BrAnDZiYbxE4+cHR3C0sPCgEVva5miV1foyi7P6YKkxkKQMxTUR5IssgWVHM59KnO1lR2ndCHWaqH3gHgSsb/sdvYfuHg8luTl1RgjNDZRdQqbPl4NLMcGGW86LoXjpLjsRRxImckBEJFnntd+aXCRmQjXEZWmfxDVW84qa6h+ZCOwL3KYJHuPQDcCmhcpp3MIR3OHoeYhmNG7TWuELsJ4hrsROcqSbEC/CdZD8hoZwtrysu/ZvNZOKchwFsiBaN47+DxK0K/fL/X8CDcG+w3iqgH/x5ipIw== - SIGNATURE] - - */ - string keyNoWS = System.Text.RegularExpressions.Regex.Replace(StringUtil.Extract(KeyText, "[KEY", "KEY]").Trim(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1"); - var jKey = JObject.Parse(keyNoWS); - - //In v7 the license expires is an optional property set called "LockDate" - l.LicenseExpire = null; - if (jKey["AyaNovaLicenseKey"]["LockDate"] != null) - l.LicenseExpire = jKey["AyaNovaLicenseKey"]["LockDate"].Value().ToUniversalTime(); - - l.MaintenanceExpire = jKey["AyaNovaLicenseKey"]["Expires"].Value().ToUniversalTime(); - //l.Users=jKey["AyaNovaLicenseKey"]["TotalScheduleableUsers"].Value(); - l.PGroup = ProductGroup.AyaNova7; - l.FetchCode = jLicense["code"].Value(); - - } - else if (KeyText.Contains("AyaNovaLiteLicenseKey")) - { - /* - "[KEY\n{\n \"AyaNovaLiteLicenseKey\": {\n \"SchemaVersion\": \"7\",\n \"Id\": \"1648506791\",\n \"Created\": \"2022-03-28T15:33:11.6010225-07:00\",\n - \"Sub\": \"true\",\n \"RegisteredTo\": \"Duncan Electric\",\n \"EmailAddress\": \"sandrajod@att.net\",\n - \"FetchCode\": \"hGAmScqYcU\",\n \"Source\": \"5246494431\",\n \"InstallableUntil\": \"2023-03-28T15:33:11.6009851-07:00\",\n - \"TotalScheduleableUsers\": \"1\",\n \"Expires\": \"2023-03-29T00:00:00\",\n \"RequestedTrial\": \"False\",\n \"Plugins\": {\n - \"Plugin\": []\n }\n }\n}\nKEY]\n - [SIGNATURE\nKuOF/SpBL1d8AFebvm2lipmKeGdbR6WzbhN68fun+ffVGRjXNX1jWI3rbf9P/shs2/M8gHqW/B7T0vVovGqosmNsGtvaYo30TKlZj9Eicr2+zDf7ojwZiBCeEnFzXr9+7aZrsZSvN20Pqof0xf/J4BVp1T66ecuZywMzH0NGsXXZtXhWYhGvLAZAR1X5/j5gqysSdysmV9j8Euz91zs/BRyfdU0uwwrdQzrJzI4V1MFl+/mIkhMUNcJ5bzjisWS2xeyNYCYnGpMF5oaGPaIcEtmTAdf5fPNNvw3sNhPaZgwlzN8FjfK6T0VgS19PcHCMOA1bTAiLLFNk6wkcjGp2Cw==\nSIGNATURE]\n" - */ - string keyNoWS = System.Text.RegularExpressions.Regex.Replace(StringUtil.Extract(KeyText, "[KEY", "KEY]").Trim(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1"); - var jKey = JObject.Parse(keyNoWS); - //In v7 the license expires is an optional property set called "LockDate" - l.LicenseExpire = null; - if (jKey["AyaNovaLiteLicenseKey"]["LockDate"] != null) - l.LicenseExpire = jKey["AyaNovaLiteLicenseKey"]["LockDate"].Value().ToUniversalTime(); - - l.MaintenanceExpire = jKey["AyaNovaLiteLicenseKey"]["Expires"].Value().ToUniversalTime(); - - l.PGroup = ProductGroup.AyaNova7; - l.FetchCode = jLicense["code"].Value(); - - l.Tags.Add("lite"); - } - else - { - //RAVEN KEY - /* - {{ - "Key": { - "LicenseFormat": "8", - "Id": "1672261044", - "RegisteredTo": "PDI Technologies", - "DBID": "R6U37uNUN2hSQideG6Gg+MqoQY8vuUeyHFI6Kv7VDsE=", - "Perpetual": true, - "LicenseExpiration": "5555-01-01T00:00:00", - "MaintenanceExpiration": "2023-12-28T00:00:00", - "Features": [ - { - "Name": "ActiveInternalUsers", - "Count": 5 - } - ] - } - }} - */ - string keyNoWS = System.Text.RegularExpressions.Regex.Replace(StringUtil.Extract(KeyText, "[KEY", "KEY]").Trim(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1"); - var jKey = JObject.Parse(keyNoWS); - l.DbId = jKey["Key"]["DBID"].Value(); - l.LicenseExpire = jKey["Key"]["LicenseExpiration"].Value().ToUniversalTime(); - //if (jKey["Key"]["Perpetual"].Value()) - if ((bool?)jKey["Key"]["Perpetual"] ?? true) - l.PGroup = ProductGroup.RavenPerpetual; - else - l.PGroup = ProductGroup.RavenSubscription; - l.MaintenanceExpire = jKey["Key"]["MaintenanceExpiration"].Value().ToUniversalTime(); - } - - l.Created = (DateTime)DateUtil.EpochToDateNullIsNull(jLicense["dtcreated"].Value()); - l.FetchedOn = DateUtil.EpochToDateNullIsNull(jLicense["dtfetched"].Value()); - l.FetchEmail = jLicense["email"].Value(); - // l.Key = jLicense["key"].Value(); - - l.Active = true;//active here means it's been fully prepared and is viable for use, all prior licenses fit this description so all are active - l.NotificationSent = true;//prevent new notification being sent - LicenseBiz biz = LicenseBiz.GetBiz(ct); - await biz.CreateAsync(l, true); - }//context - - }// all licenses loop - - - } - #endregion licenses - - #region TRIAL LICENSE REQUESTS - log.LogInformation("RFImport Raven trial requests"); - { - - res = await client.GetAsync($"{URL_ROCKFISH}api/trial/list"); - responseText = await res.Content.ReadAsStringAsync(); - var jaTrialRequestList = JArray.Parse(responseText); - - foreach (JObject jTrialRequestItem in jaTrialRequestList.Reverse()) - { - /* - /api/trial/list - [ - { - "id": 296, - "dbId": "R6U37uNUN2hSQideG6Gg+MqoQY8vuUeyHFI6Kv7VDsE=", - "perpetual": true, - "companyName": "PDI Technologies", - "contactName": "Jason Berkel", - "notes": null, - "email": "jberkel@pdisoftware.com", - "emailConfirmCode": "296RuWFbzuEps", - "emailValidated": true, - "dtRequested": 1672257483, - "dtProcessed": 1672257587, - "status": 1, - "rejectReason": null, - "key": "[KEY\n{\n \"Key\": {\n \"LicenseFormat\": \"8\",\n \"Id\": \"1672257587\",\n \"RegisteredTo\": \"PDI Technologies\",\n \"DBID\": \"R6U37uNUN2hSQideG6Gg+MqoQY8vuUeyHFI6Kv7VDsE=\",\n \"Perpetual\": true,\n \"LicenseExpiration\": \"2023-01-04T19:59:47.6170429Z\",\n \"MaintenanceExpiration\": \"2023-01-04T19:59:47.6170429Z\",\n \"Features\": [\n {\n \"Name\": \"TrialMode\"\n },\n {\n \"Name\": \"ActiveInternalUsers\",\n \"Count\": 5000\n }\n ]\n }\n}\nKEY]\n[SIGNATURE\ng/9yvrUi18PsllDyc4SJSlngmW3n411OtlFaGl3nK5SznCMf7CFDxH6eRqrvpI4452RblqAquHmsUUwFHIzKjaIj1VF3z1X9RHz7BcPrNX7lvWM8ErJb0jJjylKxvecaalMPXVxR1QLULDBFdVT5Gv0QUIzkFKVSwAF2mLUg1JNut939YoG2u95ABeQNe4SH7WQ3+gcsI/qSLcbzz/PmRMrWqPOzXi7jVbZTigfZLdbSC+DlUbNsCvkSgraEwBBnCpE8ZfCG1oFjdbP64qF1ArY7DbPUuxHNfPSZcDlhQz8D7JIqLTQwEijqvKfLy/KNMSlcfQtv5VBJtlwCP9ggdQ==\nSIGNATURE]\n", - "dtFetched": 1672257635 - }, - */ - - using (AyContext ct = ServiceProviderProvider.DBContext) - { - //Save Key first then can set keyid on tlr - long? TrialKeyId = null; - { - string sKey = jTrialRequestItem["key"].Value(); - if (!string.IsNullOrWhiteSpace(sKey)) - { - License l = new License(); - l.TrialMode = true; - - l.Key = sKey; - //get number of users count and features etc - LicenseBiz.ParseKeySetDTOFields(l); - - //Parse key as we need the expiry dates and they are only stored in the key not the trial request - string keyNoWS = System.Text.RegularExpressions.Regex.Replace(StringUtil.Extract(l.Key, "[KEY", "KEY]").Trim(), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1"); - var jKey = JObject.Parse(keyNoWS); - - - l.RegTo = jKey["Key"]["RegisteredTo"].Value(); - - //try to match customer; rockfish didn't track customer id in the license so this is a bit wishy washy - Customer cust = null; - cust = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.Name == l.RegTo); - if (cust == null)//email? - cust = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.EmailAddress.Contains(jTrialRequestItem["email"].Value())); - if (cust != null) - l.CustomerId = cust.Id; - - - l.DbId = jKey["Key"]["DBID"].Value(); - l.LicenseExpire = jKey["Key"]["LicenseExpiration"].Value().ToUniversalTime(); - if ((bool?)jKey["Key"]["Perpetual"] ?? true) - l.PGroup = ProductGroup.RavenPerpetual; - else - l.PGroup = ProductGroup.RavenSubscription; - l.MaintenanceExpire = jKey["Key"]["MaintenanceExpiration"].Value().ToUniversalTime(); - l.Created = DateUtil.EpochToDateNullIsMin(jTrialRequestItem["dtProcessed"].Value()); - l.FetchedOn = DateUtil.EpochToDateNullIsNull(jTrialRequestItem["dtFetched"].Value()); - l.FetchEmail = jTrialRequestItem["email"].Value(); - - l.Active = true;//active here means it's been fully prepared and is viable for use, all prior licenses fit this description so all are active - l.NotificationSent = true;//prevent resending - //workaround sketchy old testing licenses - if (l.PGroup == ProductGroup.RavenSubscription) - { - if (l.MaxDataGB == null || l.MaxDataGB == 0) - l.MaxDataGB = 20; - - if (l.CustomerUsers == null || l.CustomerUsers == 0) - l.CustomerUsers = 250; - - - } - - - - LicenseBiz lbiz = LicenseBiz.GetBiz(ct); - var newLicenseObject = await lbiz.CreateAsync(l, true); - -#if (DEBUG) - if (newLicenseObject == null) - { - System.Diagnostics.Debugger.Break(); - } -#endif - TrialKeyId = newLicenseObject.Id; - - } - } - - { - var tlr = new TrialLicenseRequest(); - tlr.DbId = jTrialRequestItem["dbId"].Value(); - tlr.PGroup = (jTrialRequestItem["perpetual"].Value() ? ProductGroup.RavenPerpetual : ProductGroup.RavenSubscription); - tlr.CompanyName = jTrialRequestItem["companyName"].Value(); - tlr.ContactName = jTrialRequestItem["contactName"].Value(); - tlr.Email = jTrialRequestItem["email"].Value(); - tlr.EmailConfirmCode = jTrialRequestItem["emailConfirmCode"].Value(); - tlr.EmailValidated = jTrialRequestItem["emailValidated"].Value(); - tlr.Requested = (DateTime)DateUtil.EpochToDateNullIsNull(jTrialRequestItem["dtRequested"].Value()); - tlr.Processed = DateUtil.EpochToDateNullIsNull(jTrialRequestItem["dtProcessed"].Value()); - - /* - rockfish status differs numerically - switch (obj.status) { - case 0: - return "NEW"; - case 1: - return "approved"; - case 2: - return "rejected"; - default: - return "BAD STATUS: " + obj.status; - } - - sockeye: - New = 0, - AwaitingEmailValidation = 1, - AwaitingApproval = 2, - Approved = 3, - Rejected = 4 - */ - switch (jTrialRequestItem["status"].Value()) - { - case 0: - tlr.Status = TrialRequestStatus.New; - break; - case 1: - tlr.Status = TrialRequestStatus.Approved; - break; - case 2: - tlr.Status = TrialRequestStatus.Rejected; - break; - default: - tlr.Status = TrialRequestStatus.Rejected;//just set unknowns to rejected - break; - } - tlr.RejectReason = jTrialRequestItem["rejectReason"].Value(); - tlr.LicenseId = TrialKeyId; - var biz = TrialLicenseRequestBiz.GetBiz(ct); - await biz.CreateAsync(tlr, true); - } - - }//context - }// all trial requests loop - - - } - #endregion trial requests - - log.LogInformation("RockFish import succeeded"); - } - catch (Exception ex) - { - var msg = "*** RockFish import FAILED ***"; - log.LogError(ex, msg); - } - finally - { - ServerBootConfig.MIGRATING = false; - log.LogInformation($"Migrate Rockfish: setting server state back to {wasServerState.ToString()}"); - apiServerState.SetState(wasServerState, wasReason); - } - - - - //in the correct order retrieve every object and if it's not already present in sockeye, import it - //this should be callable any time and it will just update so it can be test live in sync / parallel until ready to switch over - //await Task.CompletedTask; - - } ///////////////////////////////////////////////////////////////////// diff --git a/server/biz/TrialLicenseRequestBiz.cs b/server/biz/TrialLicenseRequestBiz.cs index 9839186..3c9ddb6 100644 --- a/server/biz/TrialLicenseRequestBiz.cs +++ b/server/biz/TrialLicenseRequestBiz.cs @@ -41,7 +41,7 @@ namespace Sockeye.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //CREATE // - internal async Task CreateAsync(TrialLicenseRequest newObject, bool importingDoNotNotify = false) + internal async Task CreateAsync(TrialLicenseRequest newObject) { await ValidateAsync(newObject, null); if (HasErrors) @@ -53,8 +53,7 @@ namespace Sockeye.Biz //Process a new request / Generate an email confirm code newObject.EmailConfirmCode = StringUtil.GenFetchCode(); newObject.EmailValidated = false; - if (!importingDoNotNotify) - newObject.Status = TrialRequestStatus.AwaitingEmailValidation; + newObject.Status = TrialRequestStatus.AwaitingEmailValidation; await ct.TrialLicenseRequest.AddAsync(newObject); await ct.SaveChangesAsync(); @@ -63,37 +62,36 @@ namespace Sockeye.Biz await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); - if (!importingDoNotNotify) + + //## ------------------ DEFAULT NOTIFICATIONS TO CUSTOMER ---------------- + //ValidateEmail request message,RavenTrialApproved (which sends pending manual generation message) and RavenTrialRejected messages are sent in this block + // + //Send verification request + 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() { - //## ------------------ DEFAULT NOTIFICATIONS TO CUSTOMER ---------------- - //ValidateEmail request message,RavenTrialApproved (which sends pending manual generation message) and RavenTrialRejected messages are sent in this block - // - //Send verification request - 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 - }; + 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; - } + 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; + } + await HandlePotentialNotificationEvent(SockEvent.Created, newObject); return newObject; @@ -591,7 +589,7 @@ namespace Sockeye.Biz SockType = BizType, ObjectId = o.Id, NotifySubscriptionId = sub.Id, - Name = $"{o.CompanyName} - trial license requested" + Name = o.CompanyName }; await ct.NotifyEvent.AddAsync(n); log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]"); diff --git a/server/sockeye.csproj b/server/sockeye.csproj index c5c2076..e5896bb 100644 --- a/server/sockeye.csproj +++ b/server/sockeye.csproj @@ -4,8 +4,8 @@ true - 8.0.0 - 8.0.0.0 + 8.0.3 + 8.0.3.0 sockeye.ico bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml 1591 diff --git a/server/util/AySchema.cs b/server/util/AySchema.cs index 3f6941c..9564637 100644 --- a/server/util/AySchema.cs +++ b/server/util/AySchema.cs @@ -767,7 +767,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); ////////////////////////////////////////////////// // - // 8.0.14 additions for job feedback + // 8.0.24 additions for job feedback // if (currentSchema < 8) { diff --git a/server/util/SockeyeVersion.cs b/server/util/SockeyeVersion.cs index 617adc0..8952bc8 100644 --- a/server/util/SockeyeVersion.cs +++ b/server/util/SockeyeVersion.cs @@ -5,7 +5,7 @@ namespace Sockeye.Util /// internal static class SockeyeVersion { - public const string VersionString = "8.0.0"; + public const string VersionString = "8.0.3"; public const string FullNameAndVersion = "Sockeye server " + VersionString; public const string CurrentApiVersion="v8"; }//eoc