Beispiel #1
0
        /// <summary>
        /// Reloads system settings from the database.
        /// </summary>
        public void ReloadSystemSettings()
        {
            ConfigurationFile configurationFile;
            CategorizedSettingsElementCollection category;

            // Reload the configuration file
            configurationFile = ConfigurationFile.Current;
            configurationFile.Reload();
            AdoDataConnection.ReloadConfigurationSettings();

            // Retrieve the connection string from the config file
            category = configurationFile.Settings["systemSettings"];
            category.Add("ConnectionString", "Data Source=localhost; Initial Catalog=SystemCenter; Integrated Security=SSPI", "Defines the connection to the openXDA database.");
            m_dbConnectionString = category["ConnectionString"].Value;

            // Load system settings from the database
            m_systemSettings = new SystemSettings(LoadSystemSettings());
        }
Beispiel #2
0
        // Attempts to start the web UI and logs startup errors.
        private bool TryStartWebUI()
        {
            // Define set of default anonymous web resources for this site
            const string DefaultAnonymousResourceExpression           = "^/@|^/Scripts/|^/Content/|^/Images/|^/fonts/|^/favicon.ico$";
            const string DefaultAuthFailureRedirectResourceExpression = AuthenticationOptions.DefaultAuthFailureRedirectResourceExpression + "|^/grafana(?!/api/).*$";

            try
            {
                ConfigurationFile.Current.Reload();
                AdoDataConnection.ReloadConfigurationSettings();

                CategorizedSettingsElementCollection systemSettings   = ConfigurationFile.Current.Settings["systemSettings"];
                CategorizedSettingsElementCollection securityProvider = ConfigurationFile.Current.Settings["securityProvider"];

                systemSettings.Add("DataProviderString", "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.SqlClient.SqlConnection; AdapterType=System.Data.SqlClient.SqlDataAdapter", "Configuration database ADO.NET data provider assembly type creation string used when ConfigurationType=Database");
                systemSettings.Add("NodeID", "00000000-0000-0000-0000-000000000000", "Unique Node ID");
                systemSettings.Add("CompanyName", "Grid Protection Alliance", "The name of the company who owns this instance of the openXDA.");
                systemSettings.Add("CompanyAcronym", "GPA", "The acronym representing the company who owns this instance of the openXDA.");
                systemSettings.Add("WebHostURL", "http://+:8989", "The web hosting URL for remote system management.");
                systemSettings.Add("DefaultWebPage", "index.cshtml", "The default web page for the hosted web server.");
                systemSettings.Add("DateFormat", "MM/dd/yyyy", "The default date format to use when rendering timestamps.");
                systemSettings.Add("TimeFormat", "HH:mm.ss.fff", "The default time format to use when rendering timestamps.");
                systemSettings.Add("BootstrapTheme", "Content/bootstrap.min.css", "Path to Bootstrap CSS to use for rendering styles.");

                systemSettings.Add("AuthenticationSchemes", AuthenticationOptions.DefaultAuthenticationSchemes, "Comma separated list of authentication schemes to use for clients accessing the hosted web server, e.g., Basic or NTLM.");
                systemSettings.Add("AuthFailureRedirectResourceExpression", DefaultAuthFailureRedirectResourceExpression, "Expression that will match paths for the resources on the web server that should redirect to the LoginPage when authentication fails.");
                systemSettings.Add("AnonymousResourceExpression", DefaultAnonymousResourceExpression, "Expression that will match paths for the resources on the web server that can be provided without checking credentials.");
                systemSettings.Add("AuthenticationToken", SessionHandler.DefaultAuthenticationToken, "Defines the token used for identifying the authentication token in cookie headers.");
                systemSettings.Add("SessionToken", SessionHandler.DefaultSessionToken, "Defines the token used for identifying the session ID in cookie headers.");
                systemSettings.Add("RequestVerificationToken", AuthenticationOptions.DefaultRequestVerificationToken, "Defines the token used for anti-forgery verification in HTTP request headers.");
                systemSettings.Add("LoginPage", AuthenticationOptions.DefaultLoginPage, "Defines the login page used for redirects on authentication failure. Expects forward slash prefix.");
                systemSettings.Add("AuthTestPage", AuthenticationOptions.DefaultAuthTestPage, "Defines the page name for the web server to test if a user is authenticated. Expects forward slash prefix.");
                systemSettings.Add("Realm", "", "Case-sensitive identifier that defines the protection space for the web based authentication and is used to indicate a scope of protection.");
                systemSettings.Add("ConfigurationCachePath", string.Format("{0}{1}ConfigurationCache{1}", FilePath.GetAbsolutePath(""), Path.DirectorySeparatorChar), "Defines the path used to cache serialized configurations");

                securityProvider.Add("ConnectionString", "Eval(systemSettings.ConnectionString)", "Connection connection string to be used for connection to the backend security datastore.");
                securityProvider.Add("DataProviderString", "Eval(systemSettings.DataProviderString)", "Configuration database ADO.NET data provider assembly type creation string to be used for connection to the backend security datastore.");

                using (AdoDataConnection connection = new AdoDataConnection("securityProvider"))
                {
                    ValidateAccountsAndGroups(connection);
                }

                DefaultWebPage = systemSettings["DefaultWebPage"].Value;

                Model = new AppModel();
                Model.Global.CompanyName            = systemSettings["CompanyName"].Value;
                Model.Global.CompanyAcronym         = systemSettings["CompanyAcronym"].Value;
                Model.Global.ApplicationName        = "openXDA";
                Model.Global.ApplicationDescription = "open eXtensible Disturbance Analytics";
                Model.Global.ApplicationKeywords    = "open source, utility, software, meter, interrogation";
                Model.Global.DateFormat             = systemSettings["DateFormat"].Value;
                Model.Global.TimeFormat             = systemSettings["TimeFormat"].Value;
                Model.Global.DateTimeFormat         = $"{Model.Global.DateFormat} {Model.Global.TimeFormat}";
                Model.Global.BootstrapTheme         = systemSettings["BootstrapTheme"].Value;

                // Attach to default web server events
                WebServer webServer = WebServer.Default;
                webServer.StatusMessage += WebServer_StatusMessage;

                // Define types for Razor pages - self-hosted web service does not use view controllers so
                // we must define configuration types for all paged view model based Razor views here:
                webServer.PagedViewModelTypes.TryAdd("Users.cshtml", new Tuple <Type, Type>(typeof(UserAccount), typeof(SecurityHub)));
                webServer.PagedViewModelTypes.TryAdd("Groups.cshtml", new Tuple <Type, Type>(typeof(SecurityGroup), typeof(SecurityHub)));

                // Parse configured authentication schemes
                if (!Enum.TryParse(systemSettings["AuthenticationSchemes"].ValueAs(AuthenticationOptions.DefaultAuthenticationSchemes.ToString()), true, out AuthenticationSchemes authenticationSchemes))
                {
                    authenticationSchemes = AuthenticationOptions.DefaultAuthenticationSchemes;
                }

                // Initialize web startup configuration
                Startup.AuthenticationOptions.AuthenticationSchemes = authenticationSchemes;
                Startup.AuthenticationOptions.AuthFailureRedirectResourceExpression = systemSettings["AuthFailureRedirectResourceExpression"].ValueAs(DefaultAuthFailureRedirectResourceExpression);
                Startup.AuthenticationOptions.AnonymousResourceExpression           = systemSettings["AnonymousResourceExpression"].ValueAs(DefaultAnonymousResourceExpression);
                Startup.AuthenticationOptions.AuthenticationToken      = systemSettings["AuthenticationToken"].ValueAs(SessionHandler.DefaultAuthenticationToken);
                Startup.AuthenticationOptions.SessionToken             = systemSettings["SessionToken"].ValueAs(SessionHandler.DefaultSessionToken);
                Startup.AuthenticationOptions.RequestVerificationToken = systemSettings["RequestVerificationToken"].ValueAs(AuthenticationOptions.DefaultRequestVerificationToken);
                Startup.AuthenticationOptions.LoginPage    = systemSettings["LoginPage"].ValueAs(AuthenticationOptions.DefaultLoginPage);
                Startup.AuthenticationOptions.AuthTestPage = systemSettings["AuthTestPage"].ValueAs(AuthenticationOptions.DefaultAuthTestPage);
                Startup.AuthenticationOptions.Realm        = systemSettings["Realm"].ValueAs("");
                Startup.AuthenticationOptions.LoginHeader  = $"<h3><img src=\"/Images/{Model.Global.ApplicationName}.png\"/> {Model.Global.ApplicationName}</h3>";

                // Validate that configured authentication test page does not evaluate as an anonymous resource nor a authentication failure redirection resource
                string authTestPage = Startup.AuthenticationOptions.AuthTestPage;

                if (Startup.AuthenticationOptions.IsAnonymousResource(authTestPage))
                {
                    throw new SecurityException($"The configured authentication test page \"{authTestPage}\" evaluates as an anonymous resource. Modify \"AnonymousResourceExpression\" setting so that authorization test page is not a match.");
                }

                if (Startup.AuthenticationOptions.IsAuthFailureRedirectResource(authTestPage))
                {
                    throw new SecurityException($"The configured authentication test page \"{authTestPage}\" evaluates as an authentication failure redirection resource. Modify \"AuthFailureRedirectResourceExpression\" setting so that authorization test page is not a match.");
                }

                if (Startup.AuthenticationOptions.AuthenticationToken == Startup.AuthenticationOptions.SessionToken)
                {
                    throw new InvalidOperationException("Authentication token must be different from session token in order to differentiate the cookie values in the HTTP headers.");
                }


                // Create new web application hosting environment
                m_webAppHost = WebApp.Start <Startup>(systemSettings["WebHostURL"].Value);

                // Initiate pre-compile of base templates
                if (AssemblyInfo.EntryAssembly.Debuggable)
                {
                    RazorEngine <CSharpDebug> .Default.PreCompile(HandleException);

                    RazorEngine <VisualBasicDebug> .Default.PreCompile(HandleException);
                }
                else
                {
                    RazorEngine <CSharp> .Default.PreCompile(HandleException);

                    RazorEngine <VisualBasic> .Default.PreCompile(HandleException);
                }

                return(true);
            }
            catch (TargetInvocationException ex)
            {
                string message;

                // Log the exception
                message = "Failed to start web UI due to exception: " + ex.InnerException.Message;
                HandleException(new InvalidOperationException(message, ex));

                return(false);
            }
            catch (Exception ex)
            {
                string message;

                // Log the exception
                message = "Failed to start web UI due to exception: " + ex.Message;
                HandleException(new InvalidOperationException(message, ex));

                return(false);
            }
        }
Beispiel #3
0
        // Attempts to start the web UI and logs startup errors.
        private bool TryStartWebUI()
        {
            try
            {
                ConfigurationFile.Current.Reload();
                AdoDataConnection.ReloadConfigurationSettings();

                CategorizedSettingsElementCollection systemSettings   = ConfigurationFile.Current.Settings["systemSettings"];
                CategorizedSettingsElementCollection securityProvider = ConfigurationFile.Current.Settings["securityProvider"];

                systemSettings.Add("DataProviderString", "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.SqlClient.SqlConnection; AdapterType=System.Data.SqlClient.SqlDataAdapter", "Configuration database ADO.NET data provider assembly type creation string used when ConfigurationType=Database");
                systemSettings.Add("NodeID", "00000000-0000-0000-0000-000000000000", "Unique Node ID");
                systemSettings.Add("CompanyName", "Grid Protection Alliance", "The name of the company who owns this instance of the openMIC.");
                systemSettings.Add("CompanyAcronym", "GPA", "The acronym representing the company who owns this instance of the openMIC.");
                systemSettings.Add("WebHostURL", "http://+:8989", "The web hosting URL for remote system management.");
                systemSettings.Add("DefaultWebPage", "index.cshtml", "The default web page for the hosted web server.");
                systemSettings.Add("DateFormat", "MM/dd/yyyy", "The default date format to use when rendering timestamps.");
                systemSettings.Add("TimeFormat", "HH:mm.ss.fff", "The default time format to use when rendering timestamps.");
                systemSettings.Add("BootstrapTheme", "Content/bootstrap.min.css", "Path to Bootstrap CSS to use for rendering styles.");

                securityProvider.Add("ConnectionString", "Eval(systemSettings.ConnectionString)", "Connection connection string to be used for connection to the backend security datastore.");
                securityProvider.Add("DataProviderString", "Eval(systemSettings.DataProviderString)", "Configuration database ADO.NET data provider assembly type creation string to be used for connection to the backend security datastore.");

                ValidateAccountsAndGroups(new AdoDataConnection("securityProvider"));

                DefaultWebPage = systemSettings["DefaultWebPage"].Value;

                Model = new AppModel();
                Model.Global.CompanyName            = systemSettings["CompanyName"].Value;
                Model.Global.CompanyAcronym         = systemSettings["CompanyAcronym"].Value;
                Model.Global.ApplicationName        = "openXDA";
                Model.Global.ApplicationDescription = "open eXtensible Disturbance Analytics";
                Model.Global.ApplicationKeywords    = "open source, utility, software, meter, interrogation";
                Model.Global.DateFormat             = systemSettings["DateFormat"].Value;
                Model.Global.TimeFormat             = systemSettings["TimeFormat"].Value;
                Model.Global.DateTimeFormat         = $"{Model.Global.DateFormat} {Model.Global.TimeFormat}";
                Model.Global.BootstrapTheme         = systemSettings["BootstrapTheme"].Value;

                // Attach to default web server events
                WebServer webServer = WebServer.Default;
                webServer.StatusMessage += WebServer_StatusMessage;

                // Define types for Razor pages - self-hosted web service does not use view controllers so
                // we must define configuration types for all paged view model based Razor views here:
                webServer.PagedViewModelTypes.TryAdd("Config/Users.cshtml", new Tuple <Type, Type>(typeof(UserAccount), typeof(SecurityHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/Groups.cshtml", new Tuple <Type, Type>(typeof(SecurityGroup), typeof(SecurityHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/Settings.cshtml", new Tuple <Type, Type>(typeof(Setting), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/XSLTemplate.cshtml", new Tuple <Type, Type>(typeof(XSLTemplate), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Assets/Meters.cshtml", new Tuple <Type, Type>(typeof(Meter), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Assets/Sites.cshtml", new Tuple <Type, Type>(typeof(MeterLocation), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/MeterGroups.cshtml", new Tuple <Type, Type>(typeof(MeterGroup), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/LineGroups.cshtml", new Tuple <Type, Type>(typeof(LineGroup), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/MeterMeterGroupView.cshtml", new Tuple <Type, Type>(typeof(MeterMeterGroup), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/LineLineGroupView.cshtml", new Tuple <Type, Type>(typeof(LineLineGroup), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Assets/Lines.cshtml", new Tuple <Type, Type>(typeof(LineView), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Assets/MeterLines.cshtml", new Tuple <Type, Type>(typeof(MeterLine), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Assets/Channels.cshtml", new Tuple <Type, Type>(typeof(Channel), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/DashSettings.cshtml", new Tuple <Type, Type>(typeof(DashSettings), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/UserDashSettings.cshtml", new Tuple <Type, Type>(typeof(UserDashSettings), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/AlarmSettings.cshtml", new Tuple <Type, Type>(typeof(AlarmRangeLimitView), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/DefaultAlarmSettings.cshtml", new Tuple <Type, Type>(typeof(DefaultAlarmRangeLimitView), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/UserAccountMeterGroupView.cshtml", new Tuple <Type, Type>(typeof(UserAccountMeterGroup), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/EmailTypes.cshtml", new Tuple <Type, Type>(typeof(EmailType), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/EmailGroups.cshtml", new Tuple <Type, Type>(typeof(EmailGroup), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/EmailGroupType.cshtml", new Tuple <Type, Type>(typeof(EmailGroupType), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/EmailGroupMeterGroup.cshtml", new Tuple <Type, Type>(typeof(EmailGroupMeterGroup), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/EmailGroupLineGroup.cshtml", new Tuple <Type, Type>(typeof(EmailGroupLineGroup), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Config/EmailGroupUserAccount.cshtml", new Tuple <Type, Type>(typeof(EmailGroupUserAccount), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/Filters.cshtml", new Tuple <Type, Type>(typeof(WorkbenchFilter), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/Events.cshtml", new Tuple <Type, Type>(typeof(Event), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/Event.cshtml", new Tuple <Type, Type>(typeof(SingleEvent), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/Breaker.cshtml", new Tuple <Type, Type>(typeof(BreakerOperation), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/EventsForDate.cshtml", new Tuple <Type, Type>(typeof(EventForDate), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/EventsForDay.cshtml", new Tuple <Type, Type>(typeof(EventForDay), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/BreakersForDay.cshtml", new Tuple <Type, Type>(typeof(BreakersForDay), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/EventsForMeter.cshtml", new Tuple <Type, Type>(typeof(EventForMeter), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/MeterEventsByLine.cshtml", new Tuple <Type, Type>(typeof(MeterEventsByLine), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/FaultsDetailsByDate.cshtml", new Tuple <Type, Type>(typeof(FaultsDetailsByDate), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/DisturbancesForDay.cshtml", new Tuple <Type, Type>(typeof(DisturbancesForDay), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/DisturbancesForMeter.cshtml", new Tuple <Type, Type>(typeof(DisturbancesForMeter), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/FaultsForMeter.cshtml", new Tuple <Type, Type>(typeof(FaultForMeter), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/SiteSummaryPVM.cshtml", new Tuple <Type, Type>(typeof(SiteSummary), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/AuditLog.cshtml", new Tuple <Type, Type>(typeof(AuditLog), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Workbench/DataFiles.cshtml", new Tuple <Type, Type>(typeof(openXDA.Model.DataFile), typeof(DataHub)));

                // Create new web application hosting environment
                m_webAppHost = WebApp.Start <Startup>(systemSettings["WebHostURL"].Value);

                // Initiate pre-compile of base templates
                if (AssemblyInfo.EntryAssembly.Debuggable)
                {
                    RazorEngine <CSharpDebug> .Default.PreCompile(HandleException);

                    RazorEngine <VisualBasicDebug> .Default.PreCompile(HandleException);
                }
                else
                {
                    RazorEngine <CSharp> .Default.PreCompile(HandleException);

                    RazorEngine <VisualBasic> .Default.PreCompile(HandleException);
                }

                return(true);
            }
            catch (TargetInvocationException ex)
            {
                string message;

                // Log the exception
                message = "Failed to start web UI due to exception: " + ex.InnerException.Message;
                HandleException(new InvalidOperationException(message, ex));

                return(false);
            }
            catch (Exception ex)
            {
                string message;

                // Log the exception
                message = "Failed to start web UI due to exception: " + ex.Message;
                HandleException(new InvalidOperationException(message, ex));

                return(false);
            }
        }
Beispiel #4
0
        // Attempts to start the web UI and logs startup errors.
        private bool TryStartWebUI()
        {
            try
            {
                ConfigurationFile.Current.Reload();
                AdoDataConnection.ReloadConfigurationSettings();

                CategorizedSettingsElementCollection systemSettings   = ConfigurationFile.Current.Settings["systemSettings"];
                CategorizedSettingsElementCollection securityProvider = ConfigurationFile.Current.Settings["securityProvider"];
                systemSettings.Add("ConnectionString", "Data Source=localhost; Initial Catalog=openXDA; Integrated Security=SSPI", "Configuration database ADO.NET data provider assembly type creation string used when ConfigurationType=Database");
                systemSettings.Add("DataProviderString", "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.SqlClient.SqlConnection; AdapterType=System.Data.SqlClient.SqlDataAdapter", "Configuration database ADO.NET data provider assembly type creation string used when ConfigurationType=Database");
                systemSettings.Add("NodeID", "00000000-0000-0000-0000-000000000000", "Unique Node ID");
                systemSettings.Add("CompanyName", "Grid Protection Alliance", "The name of the company who owns this instance of the openMIC.");
                systemSettings.Add("CompanyAcronym", "GPA", "The acronym representing the company who owns this instance of the openMIC.");
                systemSettings.Add("WebHostURL", "https://+:8790", "The web hosting URL for remote system management.");
                systemSettings.Add("DefaultWebPage", "index.cshtml", "The default web page for the hosted web server.");
                systemSettings.Add("DateFormat", "MM/dd/yyyy", "The default date format to use when rendering timestamps.");
                systemSettings.Add("TimeFormat", "HH:mm.ss.fff", "The default time format to use when rendering timestamps.");
                systemSettings.Add("BootstrapTheme", "Content/bootstrap.min.css", "Path to Bootstrap CSS to use for rendering styles.");

                securityProvider.Add("ConnectionString", "Eval(systemSettings.ConnectionString)", "Connection connection string to be used for connection to the backend security datastore.");
                securityProvider.Add("DataProviderString", "Eval(systemSettings.DataProviderString)", "Configuration database ADO.NET data provider assembly type creation string to be used for connection to the backend security datastore.");
                systemSettings.Add("DefaultCorsOrigins", "", "Comma-separated list of allowed origins (including http:// prefix) that define the default CORS policy. Use '*' to allow all or empty string to disable CORS.");
                systemSettings.Add("DefaultCorsHeaders", "*", "Comma-separated list of supported headers that define the default CORS policy. Use '*' to allow all or empty string to allow none.");
                systemSettings.Add("DefaultCorsMethods", "*", "Comma-separated list of supported methods that define the default CORS policy. Use '*' to allow all or empty string to allow none.");
                systemSettings.Add("DefaultCorsSupportsCredentials", true, "Boolean flag for the default CORS policy indicating whether the resource supports user credentials in the request.");


                DefaultWebPage = systemSettings["DefaultWebPage"].Value;

                Model = new AppModel();
                Model.Global.CompanyName                    = systemSettings["CompanyName"].Value;
                Model.Global.CompanyAcronym                 = systemSettings["CompanyAcronym"].Value;
                Model.Global.ApplicationName                = "openEAS";
                Model.Global.ApplicationDescription         = "open eXtensible Disturbance Analytics";
                Model.Global.ApplicationKeywords            = "open source, utility, software, meter, interrogation";
                Model.Global.DateFormat                     = systemSettings["DateFormat"].Value;
                Model.Global.TimeFormat                     = systemSettings["TimeFormat"].Value;
                Model.Global.DateTimeFormat                 = $"{Model.Global.DateFormat} {Model.Global.TimeFormat}";
                Model.Global.BootstrapTheme                 = systemSettings["BootstrapTheme"].Value;
                Model.Global.DefaultCorsOrigins             = systemSettings["DefaultCorsOrigins"].Value;
                Model.Global.DefaultCorsHeaders             = systemSettings["DefaultCorsHeaders"].Value;
                Model.Global.DefaultCorsMethods             = systemSettings["DefaultCorsMethods"].Value;
                Model.Global.DefaultCorsSupportsCredentials = systemSettings["DefaultCorsSupportsCredentials"].ValueAsBoolean(true);


                // Attach to default web server events
                WebServer webServer = WebServer.Default;
                webServer.StatusMessage      += WebServer_StatusMessage;
                webServer.ExecutionException += LoggedExceptionHandler;


                // Define types for Razor pages - self-hosted web service does not use view controllers so
                // we must define configuration types for all paged view model based Razor views here:
                webServer.PagedViewModelTypes.TryAdd("Result.cshtml", new Tuple <Type, Type>(typeof(OpenEASResult), typeof(DataHub)));
                webServer.PagedViewModelTypes.TryAdd("Users.cshtml", new Tuple <Type, Type>(typeof(UserAccount), typeof(SecurityHub)));
                webServer.PagedViewModelTypes.TryAdd("Groups.cshtml", new Tuple <Type, Type>(typeof(SecurityGroup), typeof(SecurityHub)));

                // Create new web application hosting environment
                m_webAppHost = WebApp.Start <Startup>(systemSettings["WebHostURL"].Value);

                // Initiate pre-compile of base templates
                if (AssemblyInfo.EntryAssembly.Debuggable)
                {
                    RazorEngine <CSharpDebug> .Default.PreCompile(HandleException);

                    RazorEngine <VisualBasicDebug> .Default.PreCompile(HandleException);
                }
                else
                {
                    RazorEngine <CSharp> .Default.PreCompile(HandleException);

                    RazorEngine <VisualBasic> .Default.PreCompile(HandleException);
                }

                return(true);
            }
            catch (TargetInvocationException ex)
            {
                string message;

                // Log the exception
                message = "Failed to start web UI due to exception: " + ex.InnerException.Message;
                HandleException(new InvalidOperationException(message, ex));

                return(false);
            }
            catch (Exception ex)
            {
                string message;

                // Log the exception
                message = "Failed to start web UI due to exception: " + ex.Message;
                HandleException(new InvalidOperationException(message, ex));

                return(false);
            }
        }