Moved functionality to write to the connection strings into the configuration area

This commit is contained in:
Bjarke Berg
2020-03-12 16:56:39 +01:00
parent c486444eda
commit 5f13dde1cd
9 changed files with 99 additions and 84 deletions

View File

@@ -4,6 +4,7 @@ using Umbraco.Configuration.Implementations;
using Umbraco.Core.Configuration.HealthChecks;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Configuration
{
@@ -29,7 +30,7 @@ namespace Umbraco.Core.Configuration
public IMemberPasswordConfiguration MemberPasswordConfigurationSettings { get; } = new MemberPasswordConfigurationSettings();
public IContentSettings ContentSettings { get; } = new ContentSettings();
public Configs Create(IIOHelper ioHelper)
public Configs Create(IIOHelper ioHelper, ILogger logger)
{
var configs = new Configs(section => ConfigurationManager.GetSection(section));
configs.Add<IGlobalSettings>(() => new GlobalSettings(ioHelper));
@@ -39,7 +40,7 @@ namespace Umbraco.Core.Configuration
configs.Add(() => CoreDebug);
configs.Add(() => MachineKeyConfig);
configs.Add<IConnectionStrings>(() => new ConnectionStrings(ioHelper));
configs.Add<IConnectionStrings>(() => new ConnectionStrings(ioHelper, logger));
configs.Add<IModelsBuilderConfig>(() => new ModelsBuilderConfig(ioHelper));

View File

@@ -1,18 +1,22 @@
using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Configuration
{
public class ConnectionStrings : IConnectionStrings
{
private readonly IIOHelper _ioHelper;
private readonly ILogger _logger;
public ConnectionStrings(IIOHelper ioHelper)
public ConnectionStrings(IIOHelper ioHelper, ILogger logger)
{
_ioHelper = ioHelper;
_logger = logger;
}
public ConfigConnectionString this[string key]
@@ -41,5 +45,77 @@ namespace Umbraco.Core.Configuration
}
var settings = ConfigurationManager.ConnectionStrings[key];
}
/// <summary>
/// Saves the connection string as a proper .net connection string in web.config.
/// </summary>
/// <remarks>Saves the ConnectionString in the very nasty 'medium trust'-supportive way.</remarks>
/// <param name="connectionString">The connection string.</param>
/// <param name="providerName">The provider name.</param>
public void SaveConnectionString(string connectionString, string providerName)
{
if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
if (string.IsNullOrWhiteSpace(connectionString)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(connectionString));
if (providerName == null) throw new ArgumentNullException(nameof(providerName));
if (string.IsNullOrWhiteSpace(providerName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(providerName));
var fileSource = "web.config";
var fileName = _ioHelper.MapPath(_ioHelper.Root +"/" + fileSource);
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
if (xml.Root == null) throw new Exception($"Invalid {fileSource} file (no root).");
var connectionStrings = xml.Root.DescendantsAndSelf("connectionStrings").FirstOrDefault();
if (connectionStrings == null) throw new Exception($"Invalid {fileSource} file (no connection strings).");
// handle configSource
var configSourceAttribute = connectionStrings.Attribute("configSource");
if (configSourceAttribute != null)
{
fileSource = configSourceAttribute.Value;
fileName = _ioHelper.MapPath(_ioHelper.Root + "/" + fileSource);
if (!File.Exists(fileName))
throw new Exception($"Invalid configSource \"{fileSource}\" (no such file).");
xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
if (xml.Root == null) throw new Exception($"Invalid {fileSource} file (no root).");
connectionStrings = xml.Root.DescendantsAndSelf("connectionStrings").FirstOrDefault();
if (connectionStrings == null) throw new Exception($"Invalid {fileSource} file (no connection strings).");
}
// create or update connection string
var setting = connectionStrings.Descendants("add").FirstOrDefault(s => s.Attribute("name")?.Value == Constants.System.UmbracoConnectionName);
if (setting == null)
{
connectionStrings.Add(new XElement("add",
new XAttribute("name", Constants.System.UmbracoConnectionName),
new XAttribute("connectionString", connectionString),
new XAttribute("providerName", providerName)));
}
else
{
AddOrUpdateAttribute(setting, "connectionString", connectionString);
AddOrUpdateAttribute(setting, "providerName", providerName);
}
// save
_logger.Info<ConnectionStrings>("Saving connection string to {ConfigFile}.", fileSource);
xml.Save(fileName, SaveOptions.DisableFormatting);
_logger.Info<ConnectionStrings>("Saved connection string to {ConfigFile}.", fileSource);
}
private static void AddOrUpdateAttribute(XElement element, string name, string value)
{
var attribute = element.Attribute(name);
if (attribute == null)
element.Add(new XAttribute(name, value));
else
attribute.Value = value;
}
}
}

View File

@@ -1,9 +1,10 @@
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Configuration
{
public interface IConfigsFactory
{
Configs Create(IIOHelper ioHelper);
Configs Create(IIOHelper ioHelper, ILogger logger);
}
}

View File

@@ -8,5 +8,6 @@ namespace Umbraco.Core.Configuration
}
void RemoveConnectionString(string umbracoConnectionName);
void SaveConnectionString(string connectionString, string providerName);
}
}

View File

@@ -28,6 +28,7 @@ namespace Umbraco.Core.Migrations.Install
private readonly IIOHelper _ioHelper;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator;
private readonly IConnectionStrings _connectionStrings;
private DatabaseSchemaResult _databaseSchemaValidationResult;
@@ -44,7 +45,8 @@ namespace Umbraco.Core.Migrations.Install
IKeyValueService keyValueService,
IIOHelper ioHelper,
IUmbracoVersion umbracoVersion,
IDbProviderFactoryCreator dbProviderFactoryCreator)
IDbProviderFactoryCreator dbProviderFactoryCreator,
IConnectionStrings connectionStrings)
{
_scopeProvider = scopeProvider;
_globalSettings = globalSettings;
@@ -56,6 +58,7 @@ namespace Umbraco.Core.Migrations.Install
_ioHelper = ioHelper;
_umbracoVersion = umbracoVersion;
_dbProviderFactoryCreator = dbProviderFactoryCreator;
_connectionStrings = connectionStrings;
}
#region Status
@@ -138,12 +141,12 @@ namespace Umbraco.Core.Migrations.Install
/// </summary>
public void ConfigureEmbeddedDatabaseConnection()
{
ConfigureEmbeddedDatabaseConnection(_databaseFactory, _ioHelper, _logger);
ConfigureEmbeddedDatabaseConnection(_databaseFactory, _ioHelper);
}
private void ConfigureEmbeddedDatabaseConnection(IUmbracoDatabaseFactory factory, IIOHelper ioHelper, ILogger logger)
private void ConfigureEmbeddedDatabaseConnection(IUmbracoDatabaseFactory factory, IIOHelper ioHelper)
{
SaveConnectionString(EmbeddedDatabaseConnectionString, Constants.DbProviderNames.SqlCe, ioHelper, logger);
_connectionStrings.SaveConnectionString(EmbeddedDatabaseConnectionString, Constants.DbProviderNames.SqlCe);
var path = Path.Combine(ioHelper.GetRootDirectorySafe(), "App_Data", "Umbraco.sdf");
if (File.Exists(path) == false)
@@ -166,7 +169,7 @@ namespace Umbraco.Core.Migrations.Install
{
const string providerName = Constants.DbProviderNames.SqlServer;
SaveConnectionString(connectionString, providerName, _ioHelper, _logger);
_connectionStrings.SaveConnectionString(connectionString, providerName);
_databaseFactory.Configure(connectionString, providerName);
}
@@ -182,7 +185,7 @@ namespace Umbraco.Core.Migrations.Install
{
var connectionString = GetDatabaseConnectionString(server, databaseName, user, password, databaseProvider, out var providerName);
SaveConnectionString(connectionString, providerName, _ioHelper, _logger);
_connectionStrings.SaveConnectionString(connectionString, providerName);
_databaseFactory.Configure(connectionString, providerName);
}
@@ -213,7 +216,7 @@ namespace Umbraco.Core.Migrations.Install
public void ConfigureIntegratedSecurityDatabaseConnection(string server, string databaseName)
{
var connectionString = GetIntegratedSecurityDatabaseConnectionString(server, databaseName);
SaveConnectionString(connectionString, Constants.DbProviderNames.SqlServer, _ioHelper, _logger);
_connectionStrings.SaveConnectionString(connectionString, Constants.DbProviderNames.SqlServer);
_databaseFactory.Configure(connectionString, Constants.DbProviderNames.SqlServer);
}
@@ -282,75 +285,8 @@ namespace Umbraco.Core.Migrations.Install
return server.ToLower().StartsWith("tcp:".ToLower());
}
/// <summary>
/// Saves the connection string as a proper .net connection string in web.config.
/// </summary>
/// <remarks>Saves the ConnectionString in the very nasty 'medium trust'-supportive way.</remarks>
/// <param name="connectionString">The connection string.</param>
/// <param name="providerName">The provider name.</param>
/// <param name="logger">A logger.</param>
private static void SaveConnectionString(string connectionString, string providerName, IIOHelper ioHelper, ILogger logger)
{
if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
if (string.IsNullOrWhiteSpace(connectionString)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(connectionString));
if (providerName == null) throw new ArgumentNullException(nameof(providerName));
if (string.IsNullOrWhiteSpace(providerName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(providerName));
var fileSource = "web.config";
var fileName = ioHelper.MapPath(ioHelper.Root +"/" + fileSource);
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
if (xml.Root == null) throw new Exception($"Invalid {fileSource} file (no root).");
var connectionStrings = xml.Root.DescendantsAndSelf("connectionStrings").FirstOrDefault();
if (connectionStrings == null) throw new Exception($"Invalid {fileSource} file (no connection strings).");
// handle configSource
var configSourceAttribute = connectionStrings.Attribute("configSource");
if (configSourceAttribute != null)
{
fileSource = configSourceAttribute.Value;
fileName = ioHelper.MapPath(ioHelper.Root + "/" + fileSource);
if (!File.Exists(fileName))
throw new Exception($"Invalid configSource \"{fileSource}\" (no such file).");
xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
if (xml.Root == null) throw new Exception($"Invalid {fileSource} file (no root).");
connectionStrings = xml.Root.DescendantsAndSelf("connectionStrings").FirstOrDefault();
if (connectionStrings == null) throw new Exception($"Invalid {fileSource} file (no connection strings).");
}
// create or update connection string
var setting = connectionStrings.Descendants("add").FirstOrDefault(s => s.Attribute("name")?.Value == Constants.System.UmbracoConnectionName);
if (setting == null)
{
connectionStrings.Add(new XElement("add",
new XAttribute("name", Constants.System.UmbracoConnectionName),
new XAttribute("connectionString", connectionString),
new XAttribute("providerName", providerName)));
}
else
{
AddOrUpdateAttribute(setting, "connectionString", connectionString);
AddOrUpdateAttribute(setting, "providerName", providerName);
}
// save
logger.Info<DatabaseBuilder>("Saving connection string to {ConfigFile}.", fileSource);
xml.Save(fileName, SaveOptions.DisableFormatting);
logger.Info<DatabaseBuilder>("Saved connection string to {ConfigFile}.", fileSource);
}
private static void AddOrUpdateAttribute(XElement element, string name, string value)
{
var attribute = element.Attribute(name);
if (attribute == null)
element.Add(new XAttribute(name, value));
else
attribute.Value = value;
}
#endregion

View File

@@ -96,7 +96,7 @@ namespace Umbraco.Tests.Runtimes
private static Configs GetConfigs()
{
var configs = new ConfigsFactory().Create(_ioHelper);
var configs = new ConfigsFactory().Create(_ioHelper, _logger);
configs.Add(SettingsForTests.GetDefaultGlobalSettings);
configs.Add(SettingsForTests.GenerateMockContentSettings);
configs.Add(SettingsForTests.GetDefaultHostingSettings);

View File

@@ -50,7 +50,7 @@ namespace Umbraco.Tests.TestHelpers
public static Configs GetConfigs()
{
return GetConfigsFactory().Create(IOHelper);
return GetConfigsFactory().Create(IOHelper, Mock.Of<ILogger>());
}
public static IRuntimeState GetRuntimeState()
{

View File

@@ -43,9 +43,9 @@ namespace Umbraco.Web.BackOffice.AspNetCore
var hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor, hostApplicationLifetime);
var ioHelper = new IOHelper(hostingEnvironment);
var configs = configFactory.Create(ioHelper);
var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, new AspNetCoreSessionIdResolver(httpContextAccessor), () => services.BuildServiceProvider().GetService<IRequestCache>(), coreDebug, ioHelper, new AspNetCoreMarchal());
var configs = configFactory.Create(ioHelper, logger);
var backOfficeInfo = new AspNetCoreBackOfficeInfo(configs.Global());
var profiler = new LogProfiler(logger);

View File

@@ -38,9 +38,9 @@ namespace Umbraco.Web
var hostingEnvironment = new AspNetHostingEnvironment(hostingSettings);
var ioHelper = new IOHelper(hostingEnvironment);
var configs = configFactory.Create(ioHelper);
var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, new AspNetSessionManager(), () => _factory?.GetInstance<IRequestCache>(), coreDebug, ioHelper, new FrameworkMarchal());
var configs = configFactory.Create(ioHelper, logger);
var backOfficeInfo = new AspNetBackOfficeInfo(configs.Global(), ioHelper, logger, configFactory.WebRoutingSettings);
var profiler = new LogProfiler(logger);
Umbraco.Composing.Current.Initialize(logger, configs, ioHelper, hostingEnvironment, backOfficeInfo, profiler);