maintenance expiration vs build date checking code
This commit is contained in:
@@ -12,7 +12,12 @@ Updates:
|
|||||||
it should also have some license route fetch prevention i.e. license has updates end date so server won't send if expired? Or something along those lines??
|
it should also have some license route fetch prevention i.e. license has updates end date so server won't send if expired? Or something along those lines??
|
||||||
Or maybe that would be bad if they downgrade and want to put back in the license they paid for (restore from backup?)
|
Or maybe that would be bad if they downgrade and want to put back in the license they paid for (restore from backup?)
|
||||||
|
|
||||||
|
Update scenarios to handle
|
||||||
|
boot with newer version than licensed and no db at all
|
||||||
|
in this case it's ok to do the schema update and install the fresh empty db then fetch the license
|
||||||
|
LICENSE FETCH SHOULD COMPARE DATES BEFORE INSTALLING A FETCHED LICENSE AND BALK IF MISMATCH
|
||||||
|
Boot with newer version and have existing db with outdated schema
|
||||||
|
TODO: it should check the license version *before* the schema update in order to not break anything
|
||||||
|
|
||||||
|
|
||||||
todo: RELEASE FINAL RELEASE
|
todo: RELEASE FINAL RELEASE
|
||||||
@@ -23,7 +28,7 @@ todo: RELEASE FINAL RELEASE
|
|||||||
test carefully once done reversion everything to 8.0.1 for official release
|
test carefully once done reversion everything to 8.0.1 for official release
|
||||||
Post in /next download folder for testing before posting fully
|
Post in /next download folder for testing before posting fully
|
||||||
Re-run the smoke tests and e2e tests before posting 8.0.1 officially
|
Re-run the smoke tests and e2e tests before posting 8.0.1 officially
|
||||||
|
todo: test on every platform every installer and be certain they work as advertised, yes this is a pain but it's necessary
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ theme:
|
|||||||
site_name: AyaNova manual
|
site_name: AyaNova manual
|
||||||
site_dir: '../../../server/AyaNova/wwwroot/docs'
|
site_dir: '../../../server/AyaNova/wwwroot/docs'
|
||||||
strict: true
|
strict: true
|
||||||
copyright: Copyright © 2022 Ground Zero Tech-Works Inc. REV-2022-08-04
|
copyright: Copyright © 2022 Ground Zero Tech-Works Inc. REV-2022-08-05
|
||||||
extra:
|
extra:
|
||||||
generator: false
|
generator: false
|
||||||
# Extensions
|
# Extensions
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
<ApplicationIcon>ayanova.ico</ApplicationIcon>
|
<ApplicationIcon>ayanova.ico</ApplicationIcon>
|
||||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||||
<noWarn>1591</noWarn>
|
<noWarn>1591</noWarn>
|
||||||
|
<Deterministic>False</Deterministic>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- https://andrewlock.net/version-vs-versionsuffix-vs-packageversion-what-do-they-all-mean/ -->
|
<!-- https://andrewlock.net/version-vs-versionsuffix-vs-packageversion-what-do-they-all-mean/ -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -208,6 +208,11 @@ namespace AyaNova
|
|||||||
logger.Info($"AYANOVA SERVER {AyaNovaVersion.VersionString} BOOTING");
|
logger.Info($"AYANOVA SERVER {AyaNovaVersion.VersionString} BOOTING");
|
||||||
|
|
||||||
|
|
||||||
|
#if (DEBUG)
|
||||||
|
logger.Info($"### Linker timestamp is {Util.FileUtil.GetLinkerTimestampUtc(System.Reflection.Assembly.GetExecutingAssembly())}");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
//log configuration
|
//log configuration
|
||||||
logger.Info($"Config {DiagConfig}");
|
logger.Info($"Config {DiagConfig}");
|
||||||
logger.Debug($"Full configuration is {config.GetDebugView()}");
|
logger.Debug($"Full configuration is {config.GetDebugView()}");
|
||||||
@@ -294,7 +299,7 @@ namespace AyaNova
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
logger.Fatal(e, "E1090 - AyaNova server can't start due to unexpected exception during initialization");
|
logger.Fatal(e, "E1090 - AyaNova server can't start due to unexpected exception during initialization");
|
||||||
throw;
|
//throw;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -593,7 +593,35 @@ namespace AyaNova
|
|||||||
//log each item individually from runtime parameters
|
//log each item individually from runtime parameters
|
||||||
|
|
||||||
|
|
||||||
|
//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
|
||||||
|
//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
|
||||||
|
//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
|
||||||
|
var tempSchema = dbContext.SchemaVersion.AsNoTracking().SingleOrDefault();
|
||||||
|
var tempLicense = dbContext.License.AsNoTracking().SingleOrDefault();
|
||||||
|
bool licenseChecked = false;
|
||||||
|
if (tempSchema != null && tempLicense != null && !string.IsNullOrWhiteSpace(tempSchema.Id))
|
||||||
|
{
|
||||||
|
//we have a schema and a license, check it now thus triggering build date vs maintenance expiry check
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AyaNova.Core.License.InitializeAsync(apiServerState, dbContext, _newLog).Wait();
|
||||||
|
licenseChecked = true;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
//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 "))
|
||||||
|
{
|
||||||
|
throw new Exception("AyaNova did not start to protect the integrity of your data, see the console and / or error log for details");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -602,7 +630,6 @@ namespace AyaNova
|
|||||||
AySchema.CheckAndUpdateAsync(dbContext, _newLog).Wait();
|
AySchema.CheckAndUpdateAsync(dbContext, _newLog).Wait();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Check database integrity
|
//Check database integrity
|
||||||
_newLog.LogDebug("DB integrity check");
|
_newLog.LogDebug("DB integrity check");
|
||||||
DbUtil.CheckFingerPrintAsync(AySchema.EXPECTED_COLUMN_COUNT,
|
DbUtil.CheckFingerPrintAsync(AySchema.EXPECTED_COLUMN_COUNT,
|
||||||
@@ -613,8 +640,9 @@ namespace AyaNova
|
|||||||
AySchema.EXPECTED_ROUTINES,
|
AySchema.EXPECTED_ROUTINES,
|
||||||
_newLog).Wait();
|
_newLog).Wait();
|
||||||
|
|
||||||
//Initialize license
|
//Initialize license if not already done (due to there being no db at all yet)
|
||||||
AyaNova.Core.License.InitializeAsync(apiServerState, dbContext, _newLog).Wait();
|
if (!licenseChecked)
|
||||||
|
AyaNova.Core.License.InitializeAsync(apiServerState, dbContext, _newLog).Wait();
|
||||||
|
|
||||||
//Set static global biz settings
|
//Set static global biz settings
|
||||||
_newLog.LogDebug("Global settings");
|
_newLog.LogDebug("Global settings");
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using AyaNova.Models;
|
using AyaNova.Models;
|
||||||
using AyaNova.Biz;
|
using AyaNova.Biz;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace AyaNova.Util
|
namespace AyaNova.Util
|
||||||
{
|
{
|
||||||
@@ -481,7 +482,7 @@ namespace AyaNova.Util
|
|||||||
AttachToAType = attachToObject.AType,
|
AttachToAType = attachToObject.AType,
|
||||||
LastModified = lastModified,
|
LastModified = lastModified,
|
||||||
Size = FileSize,
|
Size = FileSize,
|
||||||
AttachedByUserId=attachedByUserId
|
AttachedByUserId = attachedByUserId
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -828,7 +829,7 @@ namespace AyaNova.Util
|
|||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Linux ~ home folder special handling here
|
//Linux ~ home folder special handling here
|
||||||
if (path.Contains('~'))
|
if (path.Contains('~'))
|
||||||
{
|
{
|
||||||
@@ -841,6 +842,34 @@ namespace AyaNova.Util
|
|||||||
}
|
}
|
||||||
#endregion general utilities
|
#endregion general utilities
|
||||||
|
|
||||||
|
|
||||||
|
#region licensing related utility to qualify upgradability
|
||||||
|
//https://www.meziantou.net/getting-the-date-of-build-of-a-dotnet-assembly-at-runtime.htm
|
||||||
|
public static DateTime GetLinkerTimestampUtc(Assembly assembly)
|
||||||
|
{
|
||||||
|
var location = assembly.Location;
|
||||||
|
return GetLinkerTimestampUtc(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DateTime GetLinkerTimestampUtc(string filePath)
|
||||||
|
{
|
||||||
|
const int peHeaderOffset = 60;
|
||||||
|
const int linkerTimestampOffset = 8;
|
||||||
|
var bytes = new byte[2048];
|
||||||
|
|
||||||
|
using (var file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
|
{
|
||||||
|
file.Read(bytes, 0, bytes.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
var headerPos = BitConverter.ToInt32(bytes, peHeaderOffset);
|
||||||
|
var secondsSince1970 = BitConverter.ToInt32(bytes, headerPos + linkerTimestampOffset);
|
||||||
|
var dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||||
|
return dt.AddSeconds(secondsSince1970);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
}//eoc
|
}//eoc
|
||||||
|
|
||||||
}//eons
|
}//eons
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace AyaNova.Util
|
namespace AyaNova.Util
|
||||||
{
|
{
|
||||||
@@ -63,7 +61,8 @@ namespace AyaNova.Util
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}//eoc
|
}//eoc
|
||||||
|
|
||||||
|
|||||||
@@ -799,7 +799,7 @@ namespace AyaNova.Core
|
|||||||
throw new ApplicationException("E1020 - Can't install a trial key into a non empty AyaNova database. Erase the database first.");
|
throw new ApplicationException("E1020 - Can't install a trial key into a non empty AyaNova database. Erase the database first.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: TECHCOUNT - new license causes exceeding count?
|
//TECHCOUNT - new license causes exceeding count?
|
||||||
long NewTechCount = ParsedNewKey.GetLicenseFeature(SERVICE_TECHS_FEATURE_NAME).Count;
|
long NewTechCount = ParsedNewKey.GetLicenseFeature(SERVICE_TECHS_FEATURE_NAME).Count;
|
||||||
if (await AyaNova.Biz.UserBiz.ActiveCountAsync() > NewTechCount)
|
if (await AyaNova.Biz.UserBiz.ActiveCountAsync() > NewTechCount)
|
||||||
{
|
{
|
||||||
@@ -925,6 +925,15 @@ EQIDAQAB
|
|||||||
|
|
||||||
|
|
||||||
#endregion get values
|
#endregion get values
|
||||||
|
|
||||||
|
//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.");
|
||||||
|
|
||||||
|
//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.");
|
||||||
|
}
|
||||||
//All is well return key
|
//All is well return key
|
||||||
return key;
|
return key;
|
||||||
|
|
||||||
@@ -942,6 +951,12 @@ EQIDAQAB
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Validate Build date against maintenance date in license
|
||||||
|
//MaintenanceExpirationBeforeBuild?
|
||||||
|
internal static bool MExBB(DateTime dtB, AyaNovaLicenseKey k) => k.MaintenanceExpiration < dtB;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}//eoc
|
}//eoc
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user