This commit is contained in:
@@ -444,6 +444,7 @@ namespace AyaNova.Api.Controllers
|
|||||||
DBSchemaVersion = AySchema.currentSchema,
|
DBSchemaVersion = AySchema.currentSchema,
|
||||||
ServerLocalTime = DateUtil.ServerDateTimeString(System.DateTime.UtcNow),
|
ServerLocalTime = DateUtil.ServerDateTimeString(System.DateTime.UtcNow),
|
||||||
ServerTimeZone = TimeZoneInfo.Local.Id,
|
ServerTimeZone = TimeZoneInfo.Local.Id,
|
||||||
|
ServerDbId= AyaNova.Core.License.ServerDbId,
|
||||||
License = AyaNova.Core.License.LicenseInfoAsJson
|
License = AyaNova.Core.License.LicenseInfoAsJson
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ namespace AyaNova.Models
|
|||||||
{
|
{
|
||||||
public partial class AyContext : DbContext
|
public partial class AyContext : DbContext
|
||||||
{
|
{
|
||||||
public virtual DbSet<MetricMM> MetricMM { get; set; }
|
public virtual DbSet<SchemaVersion> SchemaVersion { get; set; }
|
||||||
|
public virtual DbSet<MetricMM> MetricMM { get; set; }
|
||||||
public virtual DbSet<MetricDD> MetricDD { get; set; }
|
public virtual DbSet<MetricDD> MetricDD { get; set; }
|
||||||
public virtual DbSet<User> User { get; set; }
|
public virtual DbSet<User> User { get; set; }
|
||||||
public virtual DbSet<UserOptions> UserOptions { get; set; }
|
public virtual DbSet<UserOptions> UserOptions { get; set; }
|
||||||
@@ -127,7 +128,7 @@ namespace AyaNova.Models
|
|||||||
modelBuilder.Entity<PM>().Property(z => z.Serial).UseIdentityByDefaultColumn();
|
modelBuilder.Entity<PM>().Property(z => z.Serial).UseIdentityByDefaultColumn();
|
||||||
//modelBuilder.Entity<PurchaseOrder>().Property(z => z.Serial).UseIdentityByDefaultColumn();
|
//modelBuilder.Entity<PurchaseOrder>().Property(z => z.Serial).UseIdentityByDefaultColumn();
|
||||||
|
|
||||||
|
|
||||||
//modelBuilder.Entity<MetricCPU>().HasNoKey();
|
//modelBuilder.Entity<MetricCPU>().HasNoKey();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
24
server/AyaNova/models/SchemaVersion.cs
Normal file
24
server/AyaNova/models/SchemaVersion.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace AyaNova.Models
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AyaNova Schema version table
|
||||||
|
/// </summary>
|
||||||
|
public class SchemaVersion
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
[Key]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public int Schema { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//ef core requires this
|
||||||
|
public SchemaVersion() { }
|
||||||
|
|
||||||
|
|
||||||
|
}//eoc
|
||||||
|
}//eons
|
||||||
@@ -22,7 +22,7 @@ namespace AyaNova.Util
|
|||||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
||||||
private const int DESIRED_SCHEMA_LEVEL = 11;
|
private const int DESIRED_SCHEMA_LEVEL = 11;
|
||||||
|
|
||||||
internal const long EXPECTED_COLUMN_COUNT = 323;
|
internal const long EXPECTED_COLUMN_COUNT = 324;
|
||||||
internal const long EXPECTED_INDEX_COUNT = 134;
|
internal const long EXPECTED_INDEX_COUNT = 134;
|
||||||
|
|
||||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
||||||
@@ -173,10 +173,10 @@ namespace AyaNova.Util
|
|||||||
using (var cm = ct.Database.GetDbConnection().CreateCommand())
|
using (var cm = ct.Database.GetDbConnection().CreateCommand())
|
||||||
{
|
{
|
||||||
await ct.Database.OpenConnectionAsync();
|
await ct.Database.OpenConnectionAsync();
|
||||||
cm.CommandText = "CREATE TABLE aschemaversion (schema INTEGER NOT NULL);";
|
cm.CommandText = "CREATE TABLE aschemaversion (schema INTEGER NOT NULL, id uuid not null);";
|
||||||
await cm.ExecuteNonQueryAsync();
|
await cm.ExecuteNonQueryAsync();
|
||||||
|
|
||||||
cm.CommandText = "insert into aschemaversion (schema) values (1);";
|
cm.CommandText = $"insert into aschemaversion (schema, id) values (1,'{Guid.NewGuid()}');";
|
||||||
await cm.ExecuteNonQueryAsync();
|
await cm.ExecuteNonQueryAsync();
|
||||||
|
|
||||||
await ct.Database.CloseConnectionAsync();
|
await ct.Database.CloseConnectionAsync();
|
||||||
|
|||||||
@@ -52,15 +52,15 @@ namespace AyaNova.Core
|
|||||||
|
|
||||||
|
|
||||||
//Trial key magic number for development and testing, all other guids will be fully licensed
|
//Trial key magic number for development and testing, all other guids will be fully licensed
|
||||||
private static Guid TEST_TRIAL_KEY_DBID = new Guid("{A6D18A8A-5613-4979-99DA-80D07641A2FE}");
|
// private static Guid TEST_TRIAL_KEY_DBID = new Guid("{A6D18A8A-5613-4979-99DA-80D07641A2FE}");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Current license key, can be empty
|
//Current license key, can be empty
|
||||||
private static AyaNovaLicenseKey _ActiveLicense = new AyaNovaLicenseKey();
|
private static AyaNovaLicenseKey _ActiveLicense = new AyaNovaLicenseKey();
|
||||||
|
|
||||||
//The one and only DBID
|
//The license dbid, separate from teh server dbid
|
||||||
private static Guid DbId { get; set; }
|
private static Guid LicenseDbId { get; set; }
|
||||||
|
|
||||||
#region license classes
|
#region license classes
|
||||||
|
|
||||||
@@ -153,7 +153,6 @@ namespace AyaNova.Core
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return LicenseStatus.Revoked;
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(RegisteredTo) || RegisteredTo == UNLICENSED_TOKEN)
|
if (string.IsNullOrWhiteSpace(RegisteredTo) || RegisteredTo == UNLICENSED_TOKEN)
|
||||||
return LicenseStatus.NONE;
|
return LicenseStatus.NONE;
|
||||||
@@ -287,7 +286,8 @@ namespace AyaNova.Core
|
|||||||
|
|
||||||
#region Exposed properties
|
#region Exposed properties
|
||||||
|
|
||||||
|
//The database id value stored in the schema table
|
||||||
|
internal static Guid ServerDbId { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fetch a summary of the license key for displaying to the end user
|
/// Fetch a summary of the license key for displaying to the end user
|
||||||
@@ -302,7 +302,7 @@ namespace AyaNova.Core
|
|||||||
if (ActiveKey.IsEmpty)
|
if (ActiveKey.IsEmpty)
|
||||||
{
|
{
|
||||||
sb.AppendLine(UNLICENSED_TOKEN);
|
sb.AppendLine(UNLICENSED_TOKEN);
|
||||||
sb.AppendLine($"DB ID: {DbId}");
|
sb.AppendLine($"DB ID: {LicenseDbId}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -311,7 +311,7 @@ namespace AyaNova.Core
|
|||||||
|
|
||||||
sb.AppendLine($"Registered to: {ActiveKey.RegisteredTo}");
|
sb.AppendLine($"Registered to: {ActiveKey.RegisteredTo}");
|
||||||
sb.AppendLine($"Key ID: {ActiveKey.Id}");
|
sb.AppendLine($"Key ID: {ActiveKey.Id}");
|
||||||
sb.AppendLine($"DB ID: {DbId}");
|
sb.AppendLine($"DB ID: {LicenseDbId}");
|
||||||
sb.AppendLine($"Type: {(ActiveKey.RentalLicense ? "Service" : "Perpetual")}");
|
sb.AppendLine($"Type: {(ActiveKey.RentalLicense ? "Service" : "Perpetual")}");
|
||||||
if (ActiveKey.WillExpire)
|
if (ActiveKey.WillExpire)
|
||||||
sb.AppendLine($"License expires: {DateUtil.ServerDateTimeString(ActiveKey.LicenseExpiration)}");
|
sb.AppendLine($"License expires: {DateUtil.ServerDateTimeString(ActiveKey.LicenseExpiration)}");
|
||||||
@@ -347,7 +347,7 @@ namespace AyaNova.Core
|
|||||||
|
|
||||||
if (ActiveKey.IsEmpty)
|
if (ActiveKey.IsEmpty)
|
||||||
{
|
{
|
||||||
return $"UNLICENSED, DB ID: {DbId}";
|
return $"UNLICENSED, DB ID: {LicenseDbId}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -357,7 +357,7 @@ namespace AyaNova.Core
|
|||||||
|
|
||||||
sb.Append($"regto: {ActiveKey.RegisteredTo}, ");
|
sb.Append($"regto: {ActiveKey.RegisteredTo}, ");
|
||||||
sb.Append($"keyid: {ActiveKey.Id}, ");
|
sb.Append($"keyid: {ActiveKey.Id}, ");
|
||||||
sb.Append($"dbid: {DbId}, ");
|
sb.Append($"dbid: {LicenseDbId}, ");
|
||||||
sb.Append($"type: {(ActiveKey.RentalLicense ? "service" : "perpetual")}, ");
|
sb.Append($"type: {(ActiveKey.RentalLicense ? "service" : "perpetual")}, ");
|
||||||
if (ActiveKey.WillExpire)
|
if (ActiveKey.WillExpire)
|
||||||
sb.Append($"exp: {DateUtil.ServerDateTimeString(ActiveKey.LicenseExpiration)}, ");
|
sb.Append($"exp: {DateUtil.ServerDateTimeString(ActiveKey.LicenseExpiration)}, ");
|
||||||
@@ -438,27 +438,16 @@ namespace AyaNova.Core
|
|||||||
/// <returns>Result string</returns>
|
/// <returns>Result string</returns>
|
||||||
internal static async Task<string> RequestTrialAsync(string email, string regto, ILogger log)
|
internal static async Task<string> RequestTrialAsync(string email, string regto, ILogger log)
|
||||||
{
|
{
|
||||||
//BEFORE_RELEASE: DO THE FOLLOWING BEFORE RELEASE:
|
|
||||||
//TODO: TESTING REMOVE BEFORE RELEASE
|
|
||||||
//for test purposes if this route is hit and this code executed then the dbid is temporarily changed to the special trial request
|
|
||||||
//dbid so I can test remotely without hassle
|
|
||||||
//TO USE: just hit the trial key request route once then the license fetch route and it should be easy peasy
|
|
||||||
log.LogCritical("WARNING License::RequestTrial - DEVELOPMENT TEST FORCING TRIAL DB KEY ID. UPDATE BEFORE RELEASE!!");
|
|
||||||
DbId = TEST_TRIAL_KEY_DBID;
|
|
||||||
//TESTING
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Microsoft.AspNetCore.Http.Extensions.QueryBuilder q = new Microsoft.AspNetCore.Http.Extensions.QueryBuilder();
|
Microsoft.AspNetCore.Http.Extensions.QueryBuilder q = new Microsoft.AspNetCore.Http.Extensions.QueryBuilder();
|
||||||
q.Add("dbid", DbId.ToString());
|
q.Add("dbid", LicenseDbId.ToString());
|
||||||
q.Add("email", email);
|
q.Add("email", email);
|
||||||
q.Add("regto", regto);
|
q.Add("regto", regto);
|
||||||
|
|
||||||
log.LogDebug($"Requesting trial license for DBID {DbId.ToString()}");
|
log.LogDebug($"Requesting trial license for DBID {LicenseDbId.ToString()}");
|
||||||
string sUrl = $"{LICENSE_SERVER_URL}rvr" + q.ToQueryString();
|
string sUrl = $"{LICENSE_SERVER_URL}rvr" + q.ToQueryString();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//var res = await _Client.GetStringAsync(sUrl);
|
|
||||||
var res = await ServiceProviderProvider.HttpClientFactory.CreateClient().GetStringAsync(sUrl);
|
var res = await ServiceProviderProvider.HttpClientFactory.CreateClient().GetStringAsync(sUrl);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -467,7 +456,6 @@ namespace AyaNova.Core
|
|||||||
var msg = "E1020 - Error requesting trial license key see log for details";
|
var msg = "E1020 - Error requesting trial license key see log for details";
|
||||||
log.LogError(ex, msg);
|
log.LogError(ex, msg);
|
||||||
return msg;
|
return msg;
|
||||||
// throw new ApplicationException(msg, ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion trial license request handling
|
#endregion trial license request handling
|
||||||
@@ -482,18 +470,9 @@ namespace AyaNova.Core
|
|||||||
/// <returns>Result string</returns>
|
/// <returns>Result string</returns>
|
||||||
internal static async Task FetchKeyAsync(AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, AyContext ct, ILogger log)
|
internal static async Task FetchKeyAsync(AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, AyContext ct, ILogger log)
|
||||||
{
|
{
|
||||||
log.LogDebug($"Fetching license for DBID {DbId.ToString()}");
|
log.LogDebug($"Fetching license for DBID {LicenseDbId.ToString()}");
|
||||||
string sUrl = $"{LICENSE_SERVER_URL}rvf/{DbId.ToString()}";
|
string sUrl = $"{LICENSE_SERVER_URL}rvf/{LicenseDbId.ToString()}";
|
||||||
|
|
||||||
//##########################################################################################################
|
|
||||||
//TODO: RELEASE WARNING: this needs to be dealt with before production release
|
|
||||||
if (ServerBootConfig.AYANOVA_SERVER_TEST_MODE)
|
|
||||||
{
|
|
||||||
log.LogInformation("Server is in test mode, fetching trial key");
|
|
||||||
sUrl = $"{LICENSE_SERVER_URL}rvf/{TEST_TRIAL_KEY_DBID.ToString()}";
|
|
||||||
// log.LogInformation(sUrl);
|
|
||||||
}
|
|
||||||
//##########################################################################################################
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -519,8 +498,8 @@ namespace AyaNova.Core
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialize the key
|
/// Initialize the license
|
||||||
/// Handle if first boot scenario to tag DB ID etc
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static async Task InitializeAsync(AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, AyContext ct, ILogger log)
|
internal static async Task InitializeAsync(AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, AyContext ct, ILogger log)
|
||||||
{
|
{
|
||||||
@@ -528,6 +507,18 @@ namespace AyaNova.Core
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
//First fetch the schema db id for the servers database, the license must match
|
||||||
|
var schema = await ct.SchemaVersion.AsNoTracking().SingleOrDefaultAsync();
|
||||||
|
if (schema == null || schema.Id == Guid.Empty)
|
||||||
|
{
|
||||||
|
//cryptic message deliberately, this is probably caused by someone trying to circumvent licensing
|
||||||
|
var msg = "E1030 - Database integrity check failed (2). Contact support.";
|
||||||
|
apiServerState.SetOpsOnly(msg);
|
||||||
|
log.LogCritical(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ServerDbId = schema.Id;
|
||||||
|
|
||||||
//Fetch key from db as no tracking so doesn't hang round if need to immediately clear and then re-add the key
|
//Fetch key from db as no tracking so doesn't hang round if need to immediately clear and then re-add the key
|
||||||
Models.License ldb = await ct.License.AsNoTracking().SingleOrDefaultAsync();
|
Models.License ldb = await ct.License.AsNoTracking().SingleOrDefaultAsync();
|
||||||
|
|
||||||
@@ -535,7 +526,7 @@ namespace AyaNova.Core
|
|||||||
if (ldb == null)
|
if (ldb == null)
|
||||||
{
|
{
|
||||||
ldb = new Models.License();
|
ldb = new Models.License();
|
||||||
ldb.DbId = Guid.NewGuid();//<--Permanent and unchanging DB ID for this database, the license must match this
|
ldb.DbId = ServerDbId;
|
||||||
ldb.Key = "none";
|
ldb.Key = "none";
|
||||||
ct.License.Add(ldb);
|
ct.License.Add(ldb);
|
||||||
await ct.SaveChangesAsync();
|
await ct.SaveChangesAsync();
|
||||||
@@ -544,7 +535,7 @@ namespace AyaNova.Core
|
|||||||
//ensure DB ID
|
//ensure DB ID
|
||||||
if (ldb.DbId == Guid.Empty)
|
if (ldb.DbId == Guid.Empty)
|
||||||
{
|
{
|
||||||
ldb.DbId = Guid.NewGuid();//<--Permanent and unchanging DB ID for this database, the license must match this
|
ldb.DbId = ServerDbId;
|
||||||
//Convert the no tracking record fetched above to tracking
|
//Convert the no tracking record fetched above to tracking
|
||||||
//this is required because a prior call to initialize before dumping the db would mean the license is still in memory in the context
|
//this is required because a prior call to initialize before dumping the db would mean the license is still in memory in the context
|
||||||
ct.Entry(ldb).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
|
ct.Entry(ldb).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
|
||||||
@@ -552,7 +543,7 @@ namespace AyaNova.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Get it early and set it here so that it can be displayed early to the user even if not licensed
|
//Get it early and set it here so that it can be displayed early to the user even if not licensed
|
||||||
DbId = ldb.DbId;
|
LicenseDbId = ldb.DbId;
|
||||||
|
|
||||||
if (ldb.Key == "none")
|
if (ldb.Key == "none")
|
||||||
{
|
{
|
||||||
@@ -739,6 +730,8 @@ EQIDAQAB
|
|||||||
key.Id = (string)token.SelectToken("Key.Id");
|
key.Id = (string)token.SelectToken("Key.Id");
|
||||||
key.RegisteredTo = (string)token.SelectToken("Key.RegisteredTo");
|
key.RegisteredTo = (string)token.SelectToken("Key.RegisteredTo");
|
||||||
key.DbId = (Guid)token.SelectToken("Key.DBID");
|
key.DbId = (Guid)token.SelectToken("Key.DBID");
|
||||||
|
if (key.DbId != ServerDbId)
|
||||||
|
throw new ApplicationException($"E1020 - License.Parse -> License key does not match this server");
|
||||||
key.LicenseExpiration = (DateTime)token.SelectToken("Key.LicenseExpiration");
|
key.LicenseExpiration = (DateTime)token.SelectToken("Key.LicenseExpiration");
|
||||||
key.MaintenanceExpiration = (DateTime)token.SelectToken("Key.MaintenanceExpiration");
|
key.MaintenanceExpiration = (DateTime)token.SelectToken("Key.MaintenanceExpiration");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user