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.ItemOptions; using Sarand.Net.Standard.Dbas.Security; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace Sarand.BusinessMgr.Web.Control.App { //======================================================================= public class SbmApplication_Control : SbmApplication_Web { //------------------------------------------------------------------- // Processing indicators. private bool generateDatabaseDefinitions_Control = true; private bool generateDatabaseDefinitions_BusMgr = false; private bool generateDatabaseDefinitions_Security = false; private bool generateDatabaseDefinitions_CodeTypes = false; private bool generateDatabaseDefinitions_ItemOptions = false; //------------------------------------------------------------------- // Data members. private static SbmApplication_Control appInstance; private PropertySet propertySet; private Dictionary appConfigs = new Dictionary(); private Dictionary emailConfigs = new Dictionary(); 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 { public CoreInstanceContextData(SbmSessionContext_Web sessionContext, SysId controlOwnerId, SysId controlRepositoryId) { SessionContext = sessionContext; ControlOwnerId = controlOwnerId; ControlRepositoryId = controlRepositoryId; } public SbmSessionContext_Web SessionContext { get; } public SysId ControlOwnerId { get; } public SysId ControlRepositoryId { get; } public HashSet RepositoryContexts { get; } = new HashSet(); public ISacsDatabase BusMgrDatabase { get; set; } // 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 coreInstances = new Dictionary(); //------------------------------------------------------------------- // 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; } } //------------------------------------------------------------------- // 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 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 GetSessionContexts() { return new List(coreInstances.Values.Select(item => item.SessionContext)); } /// /// Identify the Core session context by the Repository Id. /// If context not yet defined for Repository, load and then return index. /// If repository not found, return 0. /// public ushort GetCoreSessionIndexForControlRepository(SysId ownerId, SysId repositoryId) { using (DisposableCollection disposables = new DisposableCollection()) { 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); disposables.Add(repository); if (repository != null) { // Core database connection. SacsDatabaseConsole.OdbcConfig odbcConfig = SbmCoreInstanceConsole_Dbas.GetRepositoryOdbcConfig(repository); SacsDatabase busMgrDatabase = SacsDatabaseConsole.OpenOdbcDatabase(odbcConfig); if (busMgrDatabase.HasErrorState()) SaLogger.Warn($"{SysUtil.Fn} BusMgr Database: " + busMgrDatabase.DatabaseName + ". Initialisation error: " + busMgrDatabase.ErrorStateMessage); // Session context. ushort sessionContextIdx = sessionContextIdx_Next++; if (sessionContextIdx_Control < 1) sessionContextIdx_Control = sessionContextIdx; CoreInstanceContextData sessionContextData = new CoreInstanceContextData(new SbmSessionContext_Web(sessionContextIdx, Sbm.Application.WebControl), ownerId, repositoryId); sessionContextData.RepositoryContexts.Add(repository.Context); sessionContextData.BusMgrDatabase = busMgrDatabase; coreInstances.Add(sessionContextData.SessionContext.Index, sessionContextData); return sessionContextData.SessionContext.Index; } } return 0; } // Databases. public override ISacsDatabase GetControlDatabase() { return controlDatabase; } public override ISacsDatabase GetTemplateDatabase() { return templateDatabase; } public override HashSet GetRepositoryContexts(SbmSessionContext sessionContext) { return coreInstances.GetValue(sessionContext.Index, null)?.RepositoryContexts ?? new HashSet(); } public override ISacsDatabase GetBusMgrDatabase(SbmSessionContext sessionContext) { return coreInstances.GetValue(sessionContext.Index, null)?.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. /// Initialise environment - from Startup. internal void InitWebHostEnvironment(IWebHostEnvironment env) { InitEnvironment(env); } /// Initialise environment - from internal (above) or unit tests. protected void InitEnvironment(IWebHostEnvironment env) { Development = env.IsDevelopment(); environmentName = env.EnvironmentName; SaLogger.LogFilenamePrefix = "Sbm-Web-Adm"; 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 ?? ""); } } //------------------------------------------------------------------- // 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); } //------------------------------------------------------------------- } //======================================================================= }