diff --git a/.vscode/launch.json b/.vscode/launch.json index 903dfc74..1c1c2ba2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -102,7 +102,7 @@ "AYANOVA_DATA_PATH": "c:\\temp\\ravendata", "AYANOVA_USE_URLS": "http://*:7575;", //"AYANOVA_PERMANENTLY_ERASE_DATABASE":"true", - //"AYANOVA_REMOVE_LICENSE_FROM_DB":"true", + "AYANOVA_REMOVE_LICENSE_FROM_DB":"true", //"AYANOVA_SERVER_TEST_MODE": "true", "AYANOVA_SERVER_TEST_MODE_TZ_OFFSET": "-8", //"AYANOVA_REPORT_RENDERING_TIMEOUT":"1", diff --git a/devdocs/deploy.md b/devdocs/deploy.md index 82edb241..2358a473 100644 --- a/devdocs/deploy.md +++ b/devdocs/deploy.md @@ -6,7 +6,7 @@ If any packages have been changed in the release do a thorough security scan and ### Bump version numbers: -Search and replace 8.0.3 +Search and replace 8.0.4 webapp,server,launcher, v8migrate (don't change v8migrate unless it has it's own code changes, it's version should be it's own thing other than major release changes etc) Client end ayanova-version.js, diff --git a/devdocs/pricing.md b/devdocs/pricing.md index 13c9df3f..0e3781c2 100644 --- a/devdocs/pricing.md +++ b/devdocs/pricing.md @@ -139,7 +139,7 @@ TWO types makes the most sense after considering options: - One time fee, user can use indefinitely - self installed, hosted and maintained by customer - least profitable for us long term if they don't buy a maint. subscription -- Without maintenance subscription, eligable for Minor updates only to fix bugs no new features so in other words they buy 8.0.3 they can upgrade to any 8.0.X version release, but not 8.1 as it will be new features added that don't break backward compatibility +- Without maintenance subscription, eligable for Minor updates only to fix bugs no new features so in other words they buy 8.0.4 they can upgrade to any 8.0.X version release, but not 8.1 as it will be new features added that don't break backward compatibility - one-time payment, along with the option of a yearly maintenance fee. - This is basically our current model but we allow upgrades for subscribers - **HAS CODE IMPLICATIONS** upgrades need to check if allowed based on version number if no maintenance subscription _not_ on date of build. diff --git a/devdocs/todo.txt b/devdocs/todo.txt index 4d6cedf9..ceeeba77 100644 --- a/devdocs/todo.txt +++ b/devdocs/todo.txt @@ -58,8 +58,20 @@ TODO: I think a different build is the most solid way to do it, it's a pain but actually, I think the existing one is there for just this purpose after all a perpetual never expires so maybe no need to fuck with this aspect Test it out as if a real customer were doing this end to end on a hosted server +todo: review above and ensure all is accounted for before proceeding +todo: figure out new dbid thing, is this becuase it's in the key table or...?? + maybe need a way to know it *was* license before and is not just any old eval or empty? (for that other todo as well ) +TODO: test out perpetual build and license to confirm all ok +todo: test out autofetch code for development work +todo: post rockfish if get to here and all ok +todo: test existing version at server with new key generator for rockfish?? +todo: if all goes well then post to test server and try both ways again and confirm it's ok +TODO: If erase license from AyaNova db using flag it makes a new DBID, it shouldn't. +TODO: If erase license from ayanova db using flag login prompts to trial, it shouldn't + need a way to tell that the data doesn't look like eval data, i.e. not empty and doesn't have sample users maybe? Not sure, could doc around this or in instructions too to users if arises. + todo: ROCKFISH can't make a trial key for users in the UI, only when it's requested from ayanova. I'm really not sure if this is an issue or not but putting it on the list in case add as a feature just in case @@ -1281,6 +1293,6 @@ https://www.ayanova.com/download/next/ayanova-linux-x64-server.zip https://www.ayanova.com/download/next/ayanova-windows-x64-lan-setup.exe Current v8 docs home: https://www.ayanova.com/docs/next -BUILD 8.0.3 CHANGES OF NOTE +BUILD 8.0.4 CHANGES OF NOTE -Allow negative quantities on most work order subitems +Subscription / perpetual license code and stuff diff --git a/dist/install/windows/x64/lan.iss b/dist/install/windows/x64/lan.iss index 8159f632..b1b3b3b3 100644 --- a/dist/install/windows/x64/lan.iss +++ b/dist/install/windows/x64/lan.iss @@ -1,7 +1,7 @@ ; LAN install for internal network use only #define MyAppName "AyaNova server" -#define MyAppVersion "8.0.3" +#define MyAppVersion "8.0.4" #define MyAppPublisher "Ground Zero Tech-Works, Inc." #define MyAppURL "https://ayanova.com/" #define MyAppLauncherExeName "ayanova-launcher.exe" diff --git a/dist/install/windows/x64/standalone.iss b/dist/install/windows/x64/standalone.iss index 0c8ac5fd..685f5e1b 100644 --- a/dist/install/windows/x64/standalone.iss +++ b/dist/install/windows/x64/standalone.iss @@ -3,7 +3,7 @@ ; external to lan requires different config #define MyAppName "AyaNova" -#define MyAppVersion "8.0.3" +#define MyAppVersion "8.0.4" #define MyAppPublisher "Ground Zero Tech-Works, Inc." #define MyAppURL "https://ayanova.com/" #define MyAppLauncherExeName "ayanova-launcher.exe" diff --git a/server/AyaNova/AyaNova.csproj b/server/AyaNova/AyaNova.csproj index ce9be42e..66bdbe62 100644 --- a/server/AyaNova/AyaNova.csproj +++ b/server/AyaNova/AyaNova.csproj @@ -4,8 +4,8 @@ true - 8.0.3 - 8.0.3.0 + 8.0.4 + 8.0.4.0 ayanova.ico bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml 1591 diff --git a/server/AyaNova/Startup.cs b/server/AyaNova/Startup.cs index a6b24da0..835db233 100644 --- a/server/AyaNova/Startup.cs +++ b/server/AyaNova/Startup.cs @@ -603,11 +603,13 @@ namespace AyaNova //Initialize license unless it doesn't exist yet then wait and do it after schema update and fingerprint - //this is necessary to accomodate checking build date against subscription and preventing schema update if they upgrade but are not entitled to + //this is necessary to accomodate checking build date against subscription or perpetual / subscription vs build type and preventing schema update if they upgrade but are not entitled to //so they don't fuck their database - //if there is a build date issue or a license issue it will fail with an exception, log to log file, log to console and not go beyond the license check preserving the db + //if there is a build date issue or a license type mismatch issue it will fail with an exception, log to log file, log to console and not go beyond the license check preserving the db //Note: case 4160 is to build an external license fetcher utility to allow a user to upgrade without uninstalling the newer version by purchasing a new sub and installing the key out of AyaNova - //If they don't want to purchase then they must downgrade + //If they don't want to purchase then they must downgrade HOWEVER they can do the case 4170 thing with the flag AYANOVA_REMOVE_LICENSE_FROM_DB + + //NOTE: AYANOVA_REMOVE_LICENSE_FROM_DB boot flag can be used to work around this issue bool licenseChecked = false; try { @@ -625,11 +627,11 @@ namespace AyaNova } catch (Exception ex) { - //Only re-throw if it's a 1020 error with the text VERSION-TOO-NEW included, any other error allow it to keep doing it's thing below before the second license init + //Only re-throw if it's a 1020 error with the text defined in LICENSE_MISMATCH_TO_BUILD_ERROR included, any other error allow it to keep doing it's thing below before the second license init //our exception is buried inside multiple inner exceptions but it's the innermost so drill down into it while (ex.InnerException != null) ex = ex.InnerException; - if (ex.Message.Contains("1020") && ex.Message.Contains("VERSION-TOO-NEW ")) + if (ex.Message.Contains("1020") && ex.Message.Contains(AyaNova.Core.License.LICENSE_MISMATCH_TO_BUILD_ERROR)) { throw new Exception("AyaNova did not start to protect the integrity of your data, see the console and / or error log for details"); } diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs index 6080a557..74c9ee16 100644 --- a/server/AyaNova/util/AySchema.cs +++ b/server/AyaNova/util/AySchema.cs @@ -20,7 +20,7 @@ namespace AyaNova.Util /////////// CHANGE THIS ON NEW SCHEMA UPDATE //////////////////// //!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImportingAsync WHEN NEW TABLES ADDED!!!! - private const int DESIRED_SCHEMA_LEVEL = 4; + private const int DESIRED_SCHEMA_LEVEL = 5; internal const long EXPECTED_COLUMN_COUNT = 1376; internal const long EXPECTED_INDEX_COUNT = 161; @@ -1345,7 +1345,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); //INTEGRATIONLOG await ExecQueryAsync("CREATE TABLE aintegrationlog (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, integrationid BIGINT NOT NULL REFERENCES aintegration ON DELETE CASCADE, created TIMESTAMPTZ NOT NULL, statustext TEXT NOT NULL)"); - //english translations + //english translations await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'IntegrationList', 'Integrated applications' FROM atranslation t where t.baselanguage = 'en'"); await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'Integration', 'Integrated application' FROM atranslation t where t.baselanguage = 'en'"); await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'IntegrationName', 'Name' FROM atranslation t where t.baselanguage = 'en'"); @@ -1358,7 +1358,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'Integration', 'Application intégrée' FROM atranslation t where t.baselanguage = 'fr'"); await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'IntegrationName', 'Nom' FROM atranslation t where t.baselanguage = 'fr'"); //german translations - await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'IntegrationList', 'Integrierte Anwendungen' FROM atranslation t where t.baselanguage = 'de'"); + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'IntegrationList', 'Integrierte Anwendungen' FROM atranslation t where t.baselanguage = 'de'"); await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'Integration', 'Integrierte Anwendung' FROM atranslation t where t.baselanguage = 'de'"); await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'IntegrationName', 'Name' FROM atranslation t where t.baselanguage = 'de'"); @@ -1480,6 +1480,36 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); await SetSchemaLevelAsync(++currentSchema); } + ////////////////////////////////////////////////// + // + // 8.0.4 Subscription license trans keys + // + if (currentSchema < 5) + { + LogUpdateMessage(log); + //LicenseType, LicenseTypeSubscription, LicenseTypePerpetual + //english translations + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseType', 'License type' FROM atranslation t where t.baselanguage = 'en'"); + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseTypeSubscription', 'Subscription' FROM atranslation t where t.baselanguage = 'en'"); + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseTypePerpetual', 'Perpetual' FROM atranslation t where t.baselanguage = 'en'"); + + //spanish translations + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseType', 'Tipo de licencia' FROM atranslation t where t.baselanguage = 'es'"); + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseTypeSubscription', 'Suscripción' FROM atranslation t where t.baselanguage = 'es'"); + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseTypePerpetual', 'Perpetuo' FROM atranslation t where t.baselanguage = 'es'"); + + //french translations + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseType', 'Type de licence' FROM atranslation t where t.baselanguage = 'fr'"); + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseTypeSubscription', 'Abonnement' FROM atranslation t where t.baselanguage = 'fr'"); + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseTypePerpetual', 'Perpétuel' FROM atranslation t where t.baselanguage = 'fr'"); + + //german translations + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseType', 'Lizenz-Typ' FROM atranslation t where t.baselanguage = 'de'"); + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseTypeSubscription', 'Abonnement' FROM atranslation t where t.baselanguage = 'de'"); + await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'LicenseTypePerpetual', 'Ewig' FROM atranslation t where t.baselanguage = 'de'"); + await SetSchemaLevelAsync(++currentSchema); + } + //######################################### diff --git a/server/AyaNova/util/AyaNovaVersion.cs b/server/AyaNova/util/AyaNovaVersion.cs index 1978c5e3..21943ff4 100644 --- a/server/AyaNova/util/AyaNovaVersion.cs +++ b/server/AyaNova/util/AyaNovaVersion.cs @@ -5,7 +5,7 @@ namespace AyaNova.Util /// internal static class AyaNovaVersion { - public const string VersionString = "8.0.3"; + public const string VersionString = "8.0.4"; public const string FullNameAndVersion = "AyaNova server " + VersionString; public const string CurrentApiVersion="v8"; }//eoc diff --git a/server/AyaNova/util/License.cs b/server/AyaNova/util/License.cs index 4a3eed64..62393822 100644 --- a/server/AyaNova/util/License.cs +++ b/server/AyaNova/util/License.cs @@ -41,8 +41,8 @@ namespace AyaNova.Core private const string LICENSE_SERVER_URL_ROCKFISH = "https://rockfish.ayanova.com/"; #endif -//CRITICAL PROBLEM IF THIS IS TRUE -#if(DEVELOPMENT_TEST_ROCKFISH && !DEBUG) + //CRITICAL PROBLEM IF THIS IS TRUE +#if (DEVELOPMENT_TEST_ROCKFISH && !DEBUG) #error ### HOLDUP: DEVELOPMENT_TEST_ROCKFISH is defined in a RELEASE BUILD!!!! #endif @@ -51,7 +51,7 @@ namespace AyaNova.Core private const string LICENSE_SERVER_URL_EUROPA = "https://europa.ayanova.com/"; private const string LICENSE_SERVER_URL_CALLISTO = "https://callisto.ayanova.com/"; - + internal const string LICENSE_MISMATCH_TO_BUILD_ERROR = "E1020 - Not licensed for this version of AyaNova. Fix: revert to previous version used or contact technical support for options"; //Unlicensed token private const string UNLICENSED_TOKEN = "UNLICENSED"; @@ -417,6 +417,7 @@ namespace AyaNova.Core serverDbId = ServerDbId, licensedTo = ActiveKey.RegisteredTo, dbId = ActiveKey.DbId, + perpetual = ActiveKey.Perpetual, keySerial = ActiveKey.Id, licenseExpiration = ActiveKey.LicenseExpiration, licenseWillExpire = ActiveKey.WillExpire, @@ -902,7 +903,10 @@ EQIDAQAB key.Id = (string)token.SelectToken("Key.Id"); key.RegisteredTo = (string)token.SelectToken("Key.RegisteredTo"); key.DbId = (string)token.SelectToken("Key.DBID"); - key.Perpetual = (bool)token.SelectToken("Key.Perpetual"); + if (token.SelectToken("Key.Perpetual") != null) + key.Perpetual = (bool)token.SelectToken("Key.Perpetual"); + else + key.Perpetual = true; if (key.DbId != ServerDbId) throw new ApplicationException($"E1020 - License.Parse -> License key does not match this server"); @@ -932,11 +936,29 @@ EQIDAQAB //Check if attempting to use a build of AyaNova that is newer than maintenance subscription expiry if (MExBB(Util.FileUtil.GetLinkerTimestampUtc(System.Reflection.Assembly.GetExecutingAssembly()), key)) { - Console.WriteLine("E1020 - Not licensed for this version of AyaNova. Fix: downgrade back to previous version in use or contact technical support for options."); + Console.WriteLine(LICENSE_MISMATCH_TO_BUILD_ERROR); - //NOTE: VERSION-TOO-NEW bit below is checked for in startup.cs DO NOT remove this without fixing the side effects - throw new ApplicationException("E1020 VERSION-TOO-NEW - Not licensed for this version of AyaNova. Fix: downgrade back to previous version in use or contact technical support for options."); + //NOTE: LICENSE_MISMATCH_TO_BUILD_ERROR matched for in startup.cs DO NOT change this without fixing the side effects + throw new ApplicationException(LICENSE_MISMATCH_TO_BUILD_ERROR); } + + //Subscription licenses only for subscription builds and Perpetual licenses only for Perpetual builds +#if (SUBSCRIPTION_BUILD) + if(key.Perpetual){ + Console.WriteLine(LICENSE_MISMATCH_TO_BUILD_ERROR); + //NOTE: LICENSE_MISMATCH_TO_BUILD_ERROR bit below is checked for in startup.cs DO NOT remove this without fixing the side effects + throw new ApplicationException(LICENSE_MISMATCH_TO_BUILD_ERROR); + } +#else + if (!key.Perpetual) + { + Console.WriteLine(LICENSE_MISMATCH_TO_BUILD_ERROR); + //NOTE: LICENSE_MISMATCH_TO_BUILD_ERROR bit below is checked for in startup.cs DO NOT remove this without fixing the side effects + throw new ApplicationException(LICENSE_MISMATCH_TO_BUILD_ERROR); + } + +#endif + //All is well return key return key;