413 lines
16 KiB
C#
413 lines
16 KiB
C#
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Sarand.BusinessMgr.Net.Core.Web.App;
|
|
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
|
|
using Sarand.BusinessMgr.Net.Standard.Base.App;
|
|
using Sarand.BusinessMgr.Net.Standard.Base.Bus.Control;
|
|
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
|
|
using Sarand.BusinessMgr.Net.Standard.Base.Core;
|
|
using Sarand.BusinessMgr.Net.Standard.Base.Mgr.Control;
|
|
using Sarand.BusinessMgr.Net.Standard.Dbas.App;
|
|
using Sarand.BusinessMgr.Net.Standard.Dbas.Consoles;
|
|
using Sarand.BusinessMgr.Net.Standard.Dbas.Utils;
|
|
using Sarand.BusinessMgr.Web.Control.Consoles;
|
|
using Sarand.Net.Standard.Base.App;
|
|
using Sarand.Net.Standard.Base.Bus;
|
|
using Sarand.Net.Standard.Base.Core;
|
|
using Sarand.Net.Standard.Base.Dbas;
|
|
using Sarand.Net.Standard.Base.IO;
|
|
using Sarand.Net.Standard.Base.Utils;
|
|
using Sarand.Net.Standard.Dbas.Base;
|
|
using Sarand.Net.Standard.Dbas.CodeType;
|
|
using Sarand.Net.Standard.Dbas.Interface;
|
|
using Sarand.Net.Standard.Dbas.ItemOptions;
|
|
using Sarand.Net.Standard.Dbas.Security;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
|
|
namespace Sarand.BusinessMgr.Web.Control.App
|
|
{
|
|
//=======================================================================
|
|
public class SbmApplication_Control : SbmApplication_Web
|
|
{
|
|
//-------------------------------------------------------------------
|
|
// Processing indicators.
|
|
private bool generateDatabaseDefinitions_Control = false;
|
|
private bool generateDatabaseDefinitions_BusMgr = false;
|
|
private bool generateDatabaseDefinitions_Security = false;
|
|
private bool generateDatabaseDefinitions_CodeTypes = false;
|
|
private bool generateDatabaseDefinitions_ItemOptions = false;
|
|
private bool generateDatabaseDefinitions_Interfaces = false;
|
|
|
|
//-------------------------------------------------------------------
|
|
// Data members.
|
|
private static SbmApplication_Control appInstance;
|
|
private PropertySet propertySet;
|
|
private Dictionary<String, Net.Core.Web.App.SbmAppConfig> appConfigs = new Dictionary<string, Net.Core.Web.App.SbmAppConfig>();
|
|
private Dictionary<String, SbmEmailConfig> emailConfigs = new Dictionary<string, SbmEmailConfig>();
|
|
ushort sessionContextIdx_Control = 0;
|
|
// Singular databases.
|
|
private ISacsDatabase controlDatabase = null;
|
|
private ISacsDatabase templateDatabase = null;
|
|
// Core Session contexts - to access Core database via repository configuration.
|
|
private static ushort sessionContextIdx_Next = 101;
|
|
private class CoreInstanceContextData : SacsDisposable
|
|
{
|
|
public CoreInstanceContextData(SbmSessionContext_Web sessionContext, SbmcRepository repository)
|
|
{
|
|
SessionContext = sessionContext;
|
|
ControlRepositoryId = repository.Id;
|
|
RefreshRepository(repository);
|
|
}
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
instanceDataCache?.Dispose();
|
|
instanceDataCache = null;
|
|
}
|
|
public void RefreshRepository(SbmcRepository repository)
|
|
{
|
|
bool contextChanged = false;
|
|
if (ControlOwnerId is null || !ControlOwnerId.Equals(repository.OwnerId))
|
|
{
|
|
ControlOwnerId = repository.OwnerId;
|
|
contextChanged = true;
|
|
}
|
|
if (!RepositoryContexts.Contains(repository.Context))
|
|
{
|
|
RepositoryContexts.Clear();
|
|
RepositoryContexts.Add(repository.Context);
|
|
contextChanged = true;
|
|
}
|
|
// Database.
|
|
SacsDatabaseConsole.OdbcConfig odbcConfig = SbmCoreInstanceConsole_Dbas.GetRepositoryOdbcConfig(repository);
|
|
if (!odbcConfig.ConnectionString.EqualsCI(OdbcConfig?.ConnectionString ?? ""))
|
|
{
|
|
OdbcConfig = odbcConfig;
|
|
contextChanged = true;
|
|
}
|
|
if (contextChanged)
|
|
{
|
|
instanceConfig = null;
|
|
instanceDataCache?.Reset();
|
|
}
|
|
PropertiesPopulated = DateTime.Now;
|
|
}
|
|
public SbmSessionContext_Web SessionContext { get; }
|
|
public SysId ControlOwnerId { get; private set; }
|
|
public SysId ControlRepositoryId { get; init; }
|
|
public HashSet<string> RepositoryContexts { get; } = new HashSet<string>();
|
|
public SacsDatabaseConsole.OdbcConfig OdbcConfig { get; private set; }
|
|
public DateTime PropertiesPopulated { get; private set; } = DateTime.Now;
|
|
// Instance config.
|
|
private SbmInstanceConfig instanceConfig = null;
|
|
public SbmInstanceConfig InstanceConfig
|
|
{
|
|
get
|
|
{
|
|
if (instanceConfig == null)
|
|
instanceConfig = new SbmInstanceConfig_Control(ControlOwnerId, ControlRepositoryId);
|
|
return instanceConfig;
|
|
}
|
|
}
|
|
// Instance data cache.
|
|
private SbmInstanceDataCache instanceDataCache = null;
|
|
public SbmInstanceDataCache InstanceDataCache
|
|
{
|
|
get
|
|
{
|
|
if (instanceDataCache == null)
|
|
instanceDataCache = new SbmInstanceDataCache_Dbas(SessionContext);
|
|
return instanceDataCache;
|
|
}
|
|
}
|
|
}
|
|
private readonly Dictionary<ushort, CoreInstanceContextData> coreInstances = new Dictionary<ushort, CoreInstanceContextData>();
|
|
|
|
//-------------------------------------------------------------------
|
|
// Construction.
|
|
public SbmApplication_Control(IConfiguration configuration)
|
|
{
|
|
appInstance = this;
|
|
InitialiseTemporaryLoggingFolder();
|
|
try
|
|
{
|
|
propertySet = new PropertySet();
|
|
SbmGlobals.System = (SbmGlobals_Web.System = (System_Web = new SbmSystem_Control(this, propertySet)));
|
|
Configuration = configuration;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error($"{GetType().Name}.CTR {ExceptionUtil.GetErrorStateMessage(exc)}");
|
|
throw;
|
|
}
|
|
}
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
if (disposing)
|
|
{
|
|
foreach (var coreInstance in coreInstances.Values)
|
|
coreInstance.Dispose();
|
|
coreInstances.Clear();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Properties.
|
|
|
|
public static SbmApplication_Control Instance { get { return appInstance; } }
|
|
// Application Configuration.
|
|
public override Net.Core.Web.App.SbmAppConfig AppConfig { get { return appConfigs.Values.ToList().getConfigForApplication(); } }
|
|
// Session Configuration.
|
|
public override String SessionCookieName { get { return Sbm.Config.Control.Session.Cookie.Name; } }
|
|
public override List<ushort> GetSessionContextIdxs()
|
|
{
|
|
return coreInstances.Values.Select(item => item.SessionContext.Index).ToList();
|
|
}
|
|
public override SbmSessionContext GetSessionContextByIndex(ushort index)
|
|
{
|
|
return coreInstances.GetValue(index, null)?.SessionContext ?? null;
|
|
}
|
|
public override List<SbmSessionContext> GetSessionContexts()
|
|
{
|
|
return new List<SbmSessionContext>(coreInstances.Values.Select(item => item.SessionContext));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Identify the Core session context by the Repository Id.
|
|
/// <para>If context not yet defined for Repository, load and then return index.</para>
|
|
/// <para>If repository not found, return 0.</para>
|
|
/// </summary>
|
|
public ushort GetCoreSessionIndexForControlRepository(SysId repositoryId)
|
|
{
|
|
using (DisposableCollection<ISacsDisposable> disposables = new DisposableCollection<ISacsDisposable>())
|
|
{
|
|
CoreInstanceContextData sessionContext = coreInstances.Values.FirstOrDefault(item => item.ControlRepositoryId.Equals(repositoryId));
|
|
if (sessionContext != null) return sessionContext.SessionContext.Index;
|
|
// Repository context not yet loaded.
|
|
SbmcInstanceMgr instanceMgr = System.CreateControlInstanceMgr();
|
|
disposables.Add(instanceMgr);
|
|
SbmcRepository repository = instanceMgr.GetRepositoryById(repositoryId);
|
|
if (repository != null)
|
|
{
|
|
// Session context.
|
|
ushort sessionContextIdx = sessionContextIdx_Next++;
|
|
if (sessionContextIdx_Control < 1)
|
|
sessionContextIdx_Control = sessionContextIdx;
|
|
CoreInstanceContextData sessionContextData = new CoreInstanceContextData(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebControl), repository);
|
|
coreInstances.Add(sessionContextData.SessionContext.Index, sessionContextData);
|
|
return sessionContextData.SessionContext.Index;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Refresh the session context properties for the specified repository.
|
|
/// </summary>
|
|
/// <param name="repository"></param>
|
|
public void RefreshInstanceSessionProperties(SbmcRepository repository)
|
|
{
|
|
// Find session context and refresh repository properties.
|
|
CoreInstanceContextData sessionContext = coreInstances.Values.FirstOrDefault(item => item.ControlRepositoryId.Equals(repository.Id));
|
|
if (sessionContext != null)
|
|
sessionContext.RefreshRepository(repository);
|
|
}
|
|
|
|
// Databases.
|
|
public override ISacsDatabase GetControlDatabase() { return controlDatabase; }
|
|
public override ISacsDatabase GetTemplateDatabase() { return templateDatabase; }
|
|
public override HashSet<string> GetRepositoryContexts(SbmSessionContext sessionContext)
|
|
{
|
|
return coreInstances.GetValue(sessionContext.Index, null)?.RepositoryContexts ?? new HashSet<string>();
|
|
}
|
|
public override ISacsDatabase CreateBusMgrDatabase(SbmSessionContext sessionContext)
|
|
{
|
|
ISacsDatabase busMgrDatabase = SacsDatabaseConsole.OpenOdbcDatabase(coreInstances.GetValue(sessionContext.Index, null)?.OdbcConfig);
|
|
if (busMgrDatabase.HasErrorState())
|
|
SaLogger.Warn($"{SysUtil.Fn} BusMgr Database: " + busMgrDatabase.DatabaseName + ". Initialisation error: " + busMgrDatabase.ErrorStateMessage);
|
|
return busMgrDatabase;
|
|
}
|
|
// Instance configuration.
|
|
public override SbmInstanceConfig GetInstanceConfig(SbmSessionContext sessionContext)
|
|
{
|
|
return coreInstances.GetValue(sessionContext.Index, null)?.InstanceConfig;
|
|
}
|
|
// Instance data cache.
|
|
public override SbmInstanceDataCache GetInstanceDataCache(SbmSessionContext sessionContext)
|
|
{
|
|
return coreInstances.GetValue(sessionContext.Index, null)?.InstanceDataCache;
|
|
}
|
|
// Organisation configuration.
|
|
public override SbmOrganisationConfig GetOrganisationConfig(ISbmUserOrganisationContext userContext)
|
|
{
|
|
return new SbmOrganisationConfig_Dbas(userContext, GetInstanceDataCache(userContext.SessionContext));
|
|
}
|
|
// Email configuration.
|
|
public override SbmEmailConfig EmailConfig { get { return emailConfigs.Values.ToList().getConfigForSession(AppConfig); } }
|
|
|
|
//-------------------------------------------------------------------
|
|
// Consoles.
|
|
|
|
public static SbmEmailConsole_Control CreateEmailConsole_Control(SbmEmailConfig emailConfig)
|
|
{
|
|
return new SbmEmailConsole_Control(emailConfig);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Initialisation.
|
|
|
|
/// <summary>Initialise environment - from Startup.</summary>
|
|
internal void InitWebHostEnvironment(IWebHostEnvironment env)
|
|
{
|
|
InitEnvironment(env);
|
|
}
|
|
/// <summary>Initialise environment - from internal (above) or unit tests.</summary>
|
|
protected void InitEnvironment(IWebHostEnvironment env)
|
|
{
|
|
Development = env.IsDevelopment();
|
|
environmentName = env.EnvironmentName;
|
|
SaLogger.LogFilenamePrefix = "Sbm-Web-Ctl";
|
|
SaLogger.IncludeHostInFileMessage = false;
|
|
SaLogger.IncludeUserInFileMessage = false;
|
|
|
|
try
|
|
{
|
|
// Load server configuration.
|
|
var builder = new ConfigurationBuilder()
|
|
.SetBasePath(env.ContentRootPath)
|
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
|
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false)
|
|
.AddJsonFile($"appsettings.machine.{SbmSystem.ComputerName}.json", optional: false, reloadOnChange: false)
|
|
.AddEnvironmentVariables();
|
|
SbmConfiguration = builder.Build();
|
|
|
|
// Application configuration.
|
|
appConfigs = SbmAppConfigHelper.ExtractAppConfigs(SbmConfiguration.GetSection("AppConfigs"));
|
|
emailConfigs = SbmEmailConfigHelper.ExtractEmailConfigs(SbmConfiguration.GetSection("Email").GetSection("Configs"));
|
|
LoggingRootFolder = AppConfig.Logging.RootFolder;
|
|
|
|
// Application instance.
|
|
if (AppConfig.Instance.EqualsCI("Dev")) instanceType = Sbm.InstanceType.Dev;
|
|
else if (AppConfig.Instance.ContainsCI("Q")) instanceType = Sbm.InstanceType.QC;
|
|
else if (AppConfig.Instance.ContainsCI("UAT")) instanceType = Sbm.InstanceType.UAT;
|
|
else if (AppConfig.Instance.EqualsCI("PreProd")) instanceType = Sbm.InstanceType.UAT;
|
|
|
|
// Initialise hard-coded logging path.
|
|
if (StringUtil.IsBlank(LoggingRootFolder))
|
|
{
|
|
if (SbmSystem.ComputerName.EqualsCI("WIN-BPCLM1QUOMT"))
|
|
LoggingRootFolder = @"D:\Sbmonite\Logs\" + (Development ? "Dev" : "Test");
|
|
}
|
|
if (DirectoryUtil.DirectoryExists(LoggingRootFolder))
|
|
{
|
|
SaLogger.LogFolder = Path.Combine(LoggingRootFolder, Sbm.Config.Logging.Folder.WebControl);
|
|
FileUtil.ValidateDirectory(SaLogger.LogFolder, true);
|
|
}
|
|
LogApplicationStart($"{SysUtil.Fn}");
|
|
|
|
// Control database connection.
|
|
SacsDatabaseConsole.OdbcConfig odbcConfig = new SacsDatabaseConsole.OdbcConfig();
|
|
odbcConfig.Location = AppConfig.ControlDatabase.Location;
|
|
odbcConfig.User = AppConfig.ControlDatabase.User;
|
|
odbcConfig.Password = AppConfig.ControlDatabase.Password;
|
|
controlDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig);
|
|
if (controlDatabase.HasErrorState())
|
|
SaLogger.Warn($"{SysUtil.Fn} Control Database initialisation error: " + controlDatabase.ErrorStateMessage);
|
|
|
|
// Template database connection.
|
|
if (AppConfig.TemplateDatabase != null)
|
|
{
|
|
odbcConfig = new SacsDatabaseConsole.OdbcConfig();
|
|
odbcConfig.Location = AppConfig.TemplateDatabase.Location;
|
|
odbcConfig.User = AppConfig.TemplateDatabase.User;
|
|
odbcConfig.Password = AppConfig.TemplateDatabase.Password;
|
|
templateDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig);
|
|
if (templateDatabase.HasErrorState())
|
|
SaLogger.Warn($"{SysUtil.Fn} Template Database initialisation error: " + controlDatabase.ErrorStateMessage);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
SaLogger.Error($"{SysUtil.Fn} " + ExceptionUtil.GetLogMessage(exc));
|
|
}
|
|
|
|
// Occasional startup processing.
|
|
if (generateDatabaseDefinitions_Control)
|
|
GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance.Control, GetControlDatabase());
|
|
if (generateDatabaseDefinitions_BusMgr)
|
|
{
|
|
// Use the 'template' database connection parameters.
|
|
SacsDatabaseConsole.OdbcConfig config = new SacsDatabaseConsole.OdbcConfig();
|
|
config.Location = AppConfig.TemplateDatabase.Location;
|
|
config.User = AppConfig.TemplateDatabase.User;
|
|
config.Password = AppConfig.TemplateDatabase.Password;
|
|
GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance.Core, GetTemplateDatabase());
|
|
}
|
|
if (generateDatabaseDefinitions_Security)
|
|
{
|
|
SaSecurityDbDfnGenerator.Generate(GetTemplateDatabase()?.ConnectionString ?? "");
|
|
}
|
|
if (generateDatabaseDefinitions_CodeTypes)
|
|
{
|
|
SaCodeTypeDbDfnGenerator.Generate(GetTemplateDatabase()?.ConnectionString ?? "");
|
|
}
|
|
if (generateDatabaseDefinitions_ItemOptions)
|
|
{
|
|
SaItemOptionsDbDfnGenerator.Generate(GetTemplateDatabase()?.ConnectionString ?? "");
|
|
}
|
|
if (generateDatabaseDefinitions_Interfaces)
|
|
{
|
|
SaInterfaceDbDfnGenerator.Generate(GetTemplateDatabase()?.ConnectionString ?? "");
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Generate database definition.
|
|
|
|
private void GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance dbInstance, ISacsDatabase db)
|
|
{
|
|
if (!SbmSystem.DebugMode) return;
|
|
if (!StringUtil.EmptyOnNull(EnvironmentName).EqualsCI("Development")) return;
|
|
if (db == null || StringUtil.IsEmpty(db.ConnectionString)) return;
|
|
|
|
// Generate database definitions.
|
|
GenerateDatabaseDefinition(dbInstance, db.ConnectionString);
|
|
}
|
|
|
|
private void GenerateDatabaseDefinition(SbmDbDfnGenerator.DatabaseInstance dbInstance, String connectionString)
|
|
{
|
|
if (!SbmSystem.DebugMode) return;
|
|
if (!StringUtil.EmptyOnNull(EnvironmentName).EqualsCI("Development")) return;
|
|
if (StringUtil.IsEmpty(connectionString)) return;
|
|
|
|
// Generate database definitions.
|
|
SbmDbDfnGenerator.Generate(dbInstance, connectionString);
|
|
//SaUpdateLogDbDfnGenerator.Generate(database.ConnectionString);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Housekeeping.
|
|
|
|
private class HousekeepingConfig
|
|
{
|
|
}
|
|
private HousekeepingConfig housekeepingConfig = new HousekeepingConfig();
|
|
|
|
/// <summary>
|
|
/// Perform periodic application housekeeping.
|
|
/// </summary>
|
|
public override void DoHousekeeping(CancellationToken ct)
|
|
{
|
|
SaLogger.Info($"{SysUtil.Fn} Doing housekeeping.", true);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
}
|
|
//=======================================================================
|
|
}
|