Merge pull request #7095 from umbraco/netcore/feature/AB3594_move_exsiting_configuration_to_own_project
Netcore: Move configuration
This commit is contained in:
@@ -5,9 +5,9 @@
|
||||
<sectionGroup name="applicationSettings" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<sectionGroup name="system.web.webPages.razor" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<sectionGroup name="umbracoConfiguration" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing">
|
||||
<section name="settings" type="Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="settings" type="Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Configuration" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="dashBoard" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<section name="HealthChecks" type="Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="HealthChecks" type="Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Configuration" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
|
||||
@@ -27,19 +27,12 @@ namespace Umbraco.Core.Composing
|
||||
/// <param name="logger">A logger.</param>
|
||||
/// <param name="runtimeState">The runtime state.</param>
|
||||
/// <param name="configs">Optional configs.</param>
|
||||
public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs = null)
|
||||
public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs)
|
||||
{
|
||||
_register = register;
|
||||
TypeLoader = typeLoader;
|
||||
Logger = logger;
|
||||
RuntimeState = runtimeState;
|
||||
|
||||
if (configs == null)
|
||||
{
|
||||
configs = new Configs();
|
||||
configs.AddCoreConfigs();
|
||||
}
|
||||
|
||||
Configs = configs;
|
||||
}
|
||||
|
||||
@@ -131,12 +124,14 @@ namespace Umbraco.Core.Composing
|
||||
builder.RegisterWith(_register);
|
||||
_builders.Clear(); // no point keep them around
|
||||
|
||||
Configs.RegisterWith(_register);
|
||||
|
||||
IFactory factory = null;
|
||||
|
||||
Configs.RegisterWith(_register, () => factory);
|
||||
|
||||
// ReSharper disable once AccessToModifiedClosure -- on purpose
|
||||
_register.Register(_ => factory, Lifetime.Singleton);
|
||||
factory = _register.CreateFactory();
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
40
src/Umbraco.Abstractions/ConfigConnectionStringExtensions.cs
Normal file
40
src/Umbraco.Abstractions/ConfigConnectionStringExtensions.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
|
||||
public static class ConfigConnectionStringExtensions
|
||||
{
|
||||
public static bool IsConnectionStringConfigured(this ConfigConnectionString databaseSettings)
|
||||
{
|
||||
var dbIsSqlCe = false;
|
||||
if (databaseSettings?.ProviderName != null)
|
||||
dbIsSqlCe = databaseSettings.ProviderName == Constants.DbProviderNames.SqlCe;
|
||||
var sqlCeDatabaseExists = false;
|
||||
if (dbIsSqlCe)
|
||||
{
|
||||
var parts = databaseSettings.ConnectionString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var dataSourcePart = parts.FirstOrDefault(x => x.InvariantStartsWith("Data Source="));
|
||||
if (dataSourcePart != null)
|
||||
{
|
||||
var datasource = dataSourcePart.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString());
|
||||
var filePath = datasource.Replace("Data Source=", string.Empty);
|
||||
sqlCeDatabaseExists = File.Exists(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
// Either the connection details are not fully specified or it's a SQL CE database that doesn't exist yet
|
||||
if (databaseSettings == null
|
||||
|| string.IsNullOrWhiteSpace(databaseSettings.ConnectionString) || string.IsNullOrWhiteSpace(databaseSettings.ProviderName)
|
||||
|| (dbIsSqlCe && sqlCeDatabaseExists == false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class ConfigConnectionString
|
||||
{
|
||||
public ConfigConnectionString(string connectionString, string providerName, string name)
|
||||
{
|
||||
ConnectionString = connectionString;
|
||||
ProviderName = providerName;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string ConnectionString { get; }
|
||||
public string ProviderName { get; }
|
||||
public string Name { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
@@ -15,8 +13,16 @@ namespace Umbraco.Core.Configuration
|
||||
/// </remarks>
|
||||
public class Configs
|
||||
{
|
||||
private readonly Func<string, object> _configSectionResolver;
|
||||
|
||||
public Configs(Func<string, object> configSectionResolver)
|
||||
{
|
||||
_configSectionResolver = configSectionResolver ?? throw new ArgumentNullException(nameof(configSectionResolver));
|
||||
}
|
||||
|
||||
private readonly Dictionary<Type, Lazy<object>> _configs = new Dictionary<Type, Lazy<object>>();
|
||||
private Dictionary<Type, Action<IRegister>> _registerings = new Dictionary<Type, Action<IRegister>>();
|
||||
private Lazy<IFactory> _factory;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a configuration.
|
||||
@@ -60,7 +66,7 @@ namespace Umbraco.Core.Configuration
|
||||
|
||||
_configs[typeOfConfig] = new Lazy<object>(() =>
|
||||
{
|
||||
if (Current.HasFactory) return Current.Factory.GetInstance<TConfig>();
|
||||
if (!(_factory is null)) return _factory.Value.GetInstance<TConfig>();
|
||||
throw new InvalidOperationException($"Cannot get configuration of type {typeOfConfig} during composition.");
|
||||
});
|
||||
_registerings[typeOfConfig] = register => register.Register(configFactory, Lifetime.Singleton);
|
||||
@@ -75,7 +81,7 @@ namespace Umbraco.Core.Configuration
|
||||
Add(() => GetConfig<TConfig>(sectionName));
|
||||
}
|
||||
|
||||
private static TConfig GetConfig<TConfig>(string sectionName)
|
||||
private TConfig GetConfig<TConfig>(string sectionName)
|
||||
where TConfig : class
|
||||
{
|
||||
// note: need to use SafeCallContext here because ConfigurationManager.GetSection ends up getting AppDomain.Evidence
|
||||
@@ -83,10 +89,9 @@ namespace Umbraco.Core.Configuration
|
||||
|
||||
using (new SafeCallContext())
|
||||
{
|
||||
if ((ConfigurationManager.GetSection(sectionName) is TConfig config))
|
||||
if ((_configSectionResolver(sectionName) is TConfig config))
|
||||
return config;
|
||||
var ex = new ConfigurationErrorsException($"Could not get configuration section \"{sectionName}\" from config files.");
|
||||
Current.Logger.Error<Configs>(ex, "Config error");
|
||||
var ex = new InvalidOperationException($"Could not get configuration section \"{sectionName}\" from config files.");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
@@ -94,12 +99,14 @@ namespace Umbraco.Core.Configuration
|
||||
/// <summary>
|
||||
/// Registers configurations in a register.
|
||||
/// </summary>
|
||||
public void RegisterWith(IRegister register)
|
||||
public void RegisterWith(IRegister register, Func<IFactory> factory)
|
||||
{
|
||||
// do it only once
|
||||
if (_registerings == null)
|
||||
throw new InvalidOperationException("Configurations have already been registered.");
|
||||
|
||||
_factory = new Lazy<IFactory>(factory);
|
||||
|
||||
register.Register(this);
|
||||
|
||||
foreach (var registering in _registerings.Values)
|
||||
@@ -19,6 +19,9 @@ namespace Umbraco.Core
|
||||
public static IGlobalSettings Global(this Configs configs)
|
||||
=> configs.GetConfig<IGlobalSettings>();
|
||||
|
||||
public static IConnectionStrings ConnectionStrings(this Configs configs)
|
||||
=> configs.GetConfig<IConnectionStrings>();
|
||||
|
||||
public static IUmbracoSettingsSection Settings(this Configs configs)
|
||||
=> configs.GetConfig<IUmbracoSettingsSection>();
|
||||
|
||||
@@ -28,25 +31,20 @@ namespace Umbraco.Core
|
||||
public static IGridConfig Grids(this Configs configs)
|
||||
=> configs.GetConfig<IGridConfig>();
|
||||
|
||||
internal static CoreDebug CoreDebug(this Configs configs)
|
||||
=> configs.GetConfig<CoreDebug>();
|
||||
public static ICoreDebug CoreDebug(this Configs configs)
|
||||
=> configs.GetConfig<ICoreDebug>();
|
||||
|
||||
public static void AddCoreConfigs(this Configs configs)
|
||||
public static void AddCoreConfigs(this Configs configs, IIOHelper ioHelper)
|
||||
{
|
||||
var configDir = new DirectoryInfo(Current.IOHelper.MapPath(Constants.SystemDirectories.Config));
|
||||
var configDir = new DirectoryInfo(ioHelper.MapPath(Constants.SystemDirectories.Config));
|
||||
|
||||
configs.Add<IGlobalSettings>(() => new GlobalSettings());
|
||||
configs.Add<IUmbracoSettingsSection>("umbracoConfiguration/settings");
|
||||
configs.Add<IHealthChecks>("umbracoConfiguration/HealthChecks");
|
||||
|
||||
configs.Add(() => new CoreDebug());
|
||||
|
||||
// GridConfig depends on runtime caches, manifest parsers... and cannot be available during composition
|
||||
configs.Add<IGridConfig>(factory => new GridConfig(
|
||||
factory.GetInstance<ILogger>(),
|
||||
factory.GetInstance<AppCaches>(),
|
||||
configDir,
|
||||
factory.GetInstance<ManifestParser>(),
|
||||
factory.GetInstance<IManifestParser>(),
|
||||
factory.GetInstance<IRuntimeState>().Debug));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public static class GlobalSettingsExtensions
|
||||
{
|
||||
private static string _mvcArea;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This returns the string of the MVC Area route.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will return the MVC area that we will route all custom routes through like surface controllers, etc...
|
||||
/// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin
|
||||
/// we will convert the '/' to '-' and use that as the path. its a bit lame but will work.
|
||||
///
|
||||
/// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something
|
||||
/// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco".
|
||||
/// </remarks>
|
||||
public static string GetUmbracoMvcArea(this IGlobalSettings globalSettings, IIOHelper ioHelper)
|
||||
{
|
||||
if (_mvcArea != null) return _mvcArea;
|
||||
|
||||
_mvcArea = GetUmbracoMvcAreaNoCache(globalSettings, ioHelper);
|
||||
|
||||
return _mvcArea;
|
||||
}
|
||||
|
||||
internal static string GetUmbracoMvcAreaNoCache(this IGlobalSettings globalSettings, IIOHelper ioHelper)
|
||||
{
|
||||
if (globalSettings.Path.IsNullOrWhiteSpace())
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified");
|
||||
}
|
||||
|
||||
var path = globalSettings.Path;
|
||||
if (path.StartsWith(ioHelper.Root)) // beware of TrimStart, see U4-2518
|
||||
path = path.Substring(ioHelper.Root.Length);
|
||||
return path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ using Umbraco.Core.Manifest;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
class GridConfig : IGridConfig
|
||||
public class GridConfig : IGridConfig
|
||||
{
|
||||
public GridConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, ManifestParser manifestParser, bool isDebug)
|
||||
public GridConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, IManifestParser manifestParser, bool isDebug)
|
||||
{
|
||||
EditorsConfig = new GridEditorsConfig(logger, appCaches, configFolder, manifestParser, isDebug);
|
||||
}
|
||||
@@ -13,10 +13,10 @@ namespace Umbraco.Core.Configuration.Grid
|
||||
private readonly ILogger _logger;
|
||||
private readonly AppCaches _appCaches;
|
||||
private readonly DirectoryInfo _configFolder;
|
||||
private readonly ManifestParser _manifestParser;
|
||||
private readonly IManifestParser _manifestParser;
|
||||
private readonly bool _isDebug;
|
||||
|
||||
public GridEditorsConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, ManifestParser manifestParser, bool isDebug)
|
||||
public GridEditorsConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, IManifestParser manifestParser, bool isDebug)
|
||||
{
|
||||
_logger = logger;
|
||||
_appCaches = appCaches;
|
||||
@@ -29,9 +29,9 @@ namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
get
|
||||
{
|
||||
List<GridEditor> GetResult()
|
||||
List<IGridEditorConfig> GetResult()
|
||||
{
|
||||
var editors = new List<GridEditor>();
|
||||
var editors = new List<IGridEditorConfig>();
|
||||
var gridConfig = Path.Combine(_configFolder.FullName, "grid.editors.config.js");
|
||||
if (File.Exists(gridConfig))
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace Umbraco.Core.Configuration.Grid
|
||||
//cache the result if debugging is disabled
|
||||
var result = _isDebug
|
||||
? GetResult()
|
||||
: _appCaches.RuntimeCache.GetCacheItem<List<GridEditor>>(typeof(GridEditorsConfig) + ".Editors",GetResult, TimeSpan.FromMinutes(10));
|
||||
: _appCaches.RuntimeCache.GetCacheItem<List<IGridEditorConfig>>(typeof(GridEditorsConfig) + ".Editors",GetResult, TimeSpan.FromMinutes(10));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public enum HealthCheckNotificationVerbosity
|
||||
{
|
||||
|
||||
Summary,
|
||||
Detailed
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public interface IConfigsFactory
|
||||
{
|
||||
Configs Create();
|
||||
}
|
||||
}
|
||||
10
src/Umbraco.Abstractions/Configuration/IConnectionStrings.cs
Normal file
10
src/Umbraco.Abstractions/Configuration/IConnectionStrings.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public interface IConnectionStrings
|
||||
{
|
||||
ConfigConnectionString this[string key]
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/Umbraco.Abstractions/Configuration/ICoreDebug.cs
Normal file
17
src/Umbraco.Abstractions/Configuration/ICoreDebug.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public interface ICoreDebug
|
||||
{
|
||||
/// <summary>
|
||||
/// When set to true, Scope logs the stack trace for any scope that gets disposed without being completed.
|
||||
/// this helps troubleshooting rogue scopes that we forget to complete
|
||||
/// </summary>
|
||||
bool LogUncompletedScopes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// When set to true, the Logger creates a mini dump of w3wp in ~/App_Data/MiniDump whenever it logs
|
||||
/// an error due to a ThreadAbortException that is due to a timeout.
|
||||
/// </summary>
|
||||
bool DumpOnTimeoutThreadAbort { get; }
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,9 @@
|
||||
/// </summary>
|
||||
public interface IGlobalSettings
|
||||
{
|
||||
// fixme: Review this class, it is now just a dumping ground for config options (based basically on whatever might be in appSettings),
|
||||
// our config classes should be named according to what they are configuring.
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reserved urls from web.config.
|
||||
/// </summary>
|
||||
@@ -63,14 +66,39 @@
|
||||
/// </summary>
|
||||
LocalTempStorage LocalTempStorageLocation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the location of temporary files.
|
||||
/// </summary>
|
||||
string LocalTempPath { get; }
|
||||
|
||||
string UmbracoPath { get; }
|
||||
string UmbracoCssPath { get; }
|
||||
string UmbracoScriptsPath { get; }
|
||||
string UmbracoMediaPath { get; }
|
||||
bool DebugMode { get; }
|
||||
|
||||
bool IsSmtpServerConfigured { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the runtime should enter Install level when the database is missing.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>By default, when a database connection string is configured but it is not possible to
|
||||
/// connect to the database, the runtime enters the BootFailed level. If this options is set to true,
|
||||
/// it enters the Install level instead.</para>
|
||||
/// <para>It is then up to the implementor, that is setting this value, to take over the installation
|
||||
/// sequence.</para>
|
||||
/// </remarks>
|
||||
bool InstallMissingDatabase { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the runtime should enter Install level when the database is empty.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>By default, when a database connection string is configured and it is possible to connect to
|
||||
/// the database, but the database is empty, the runtime enters the BootFailed level. If this options
|
||||
/// is set to true, it enters the Install level instead.</para>
|
||||
/// <para>It is then up to the implementor, that is setting this value, to take over the installation
|
||||
/// sequence.</para>
|
||||
/// </remarks>
|
||||
bool InstallEmptyDatabase { get; }
|
||||
bool DisableElectionForSingleServer { get; }
|
||||
string RegisterType { get; }
|
||||
string DatabaseFactoryServerVersion { get; }
|
||||
}
|
||||
}
|
||||
|
||||
56
src/Umbraco.Abstractions/Configuration/IUmbracoVersion.cs
Normal file
56
src/Umbraco.Abstractions/Configuration/IUmbracoVersion.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using Semver;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public interface IUmbracoVersion
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the non-semantic version of the Umbraco code.
|
||||
/// </summary>
|
||||
Version Current { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the semantic version comments of the Umbraco code.
|
||||
/// </summary>
|
||||
string Comment { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly version of the Umbraco code.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The assembly version is the value of the <see cref="AssemblyVersionAttribute"/>.</para>
|
||||
/// <para>Is the one that the CLR checks for compatibility. Therefore, it changes only on
|
||||
/// hard-breaking changes (for instance, on new major versions).</para>
|
||||
/// </remarks>
|
||||
Version AssemblyVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly file version of the Umbraco code.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The assembly version is the value of the <see cref="AssemblyFileVersionAttribute"/>.</para>
|
||||
/// </remarks>
|
||||
Version AssemblyFileVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the semantic version of the Umbraco code.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The semantic version is the value of the <see cref="AssemblyInformationalVersionAttribute"/>.</para>
|
||||
/// <para>It is the full version of Umbraco, including comments.</para>
|
||||
/// </remarks>
|
||||
SemVersion SemanticVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the "local" version of the site.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Three things have a version, really: the executing code, the database model,
|
||||
/// and the site/files. The database model version is entirely managed via migrations,
|
||||
/// and changes during an upgrade. The executing code version changes when new code is
|
||||
/// deployed. The site/files version changes during an upgrade.</para>
|
||||
/// </remarks>
|
||||
SemVersion LocalVersion { get; }
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,19 @@ namespace Umbraco.Core.Configuration
|
||||
/// <summary>
|
||||
/// Represents the version of the executing code.
|
||||
/// </summary>
|
||||
public static class UmbracoVersion
|
||||
public class UmbracoVersion : IUmbracoVersion
|
||||
{
|
||||
static UmbracoVersion()
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
|
||||
public UmbracoVersion(IGlobalSettings globalSettings)
|
||||
:this()
|
||||
{
|
||||
var umbracoCoreAssembly = typeof(UmbracoVersion).Assembly;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public UmbracoVersion()
|
||||
{
|
||||
var umbracoCoreAssembly = typeof(SemVersion).Assembly;
|
||||
|
||||
// gets the value indicated by the AssemblyVersion attribute
|
||||
AssemblyVersion = umbracoCoreAssembly.GetName().Version;
|
||||
@@ -32,12 +40,12 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets the non-semantic version of the Umbraco code.
|
||||
/// </summary>
|
||||
// TODO: rename to Version
|
||||
public static Version Current { get; }
|
||||
public Version Current { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the semantic version comments of the Umbraco code.
|
||||
/// </summary>
|
||||
public static string Comment => SemanticVersion.Prerelease;
|
||||
public string Comment => SemanticVersion.Prerelease;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly version of the Umbraco code.
|
||||
@@ -47,7 +55,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <para>Is the one that the CLR checks for compatibility. Therefore, it changes only on
|
||||
/// hard-breaking changes (for instance, on new major versions).</para>
|
||||
/// </remarks>
|
||||
public static Version AssemblyVersion {get; }
|
||||
public Version AssemblyVersion {get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly file version of the Umbraco code.
|
||||
@@ -55,7 +63,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <remarks>
|
||||
/// <para>The assembly version is the value of the <see cref="AssemblyFileVersionAttribute"/>.</para>
|
||||
/// </remarks>
|
||||
public static Version AssemblyFileVersion { get; }
|
||||
public Version AssemblyFileVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the semantic version of the Umbraco code.
|
||||
@@ -64,7 +72,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <para>The semantic version is the value of the <see cref="AssemblyInformationalVersionAttribute"/>.</para>
|
||||
/// <para>It is the full version of Umbraco, including comments.</para>
|
||||
/// </remarks>
|
||||
public static SemVersion SemanticVersion { get; }
|
||||
public SemVersion SemanticVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the "local" version of the site.
|
||||
@@ -75,21 +83,11 @@ namespace Umbraco.Core.Configuration
|
||||
/// and changes during an upgrade. The executing code version changes when new code is
|
||||
/// deployed. The site/files version changes during an upgrade.</para>
|
||||
/// </remarks>
|
||||
public static SemVersion LocalVersion
|
||||
{
|
||||
public SemVersion LocalVersion {
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings
|
||||
var value = ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus];
|
||||
return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
var value = _globalSettings.ConfigurationStatus;
|
||||
return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null;
|
||||
} }
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ namespace Umbraco.Core.Events
|
||||
public IEnumerable<TEntity> DeletedEntities
|
||||
{
|
||||
get => EventObject;
|
||||
internal set => EventObject = value;
|
||||
set => EventObject = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// A simple/default transient messages factory
|
||||
/// </summary>
|
||||
internal class TransientEventMessagesFactory : IEventMessagesFactory
|
||||
public class TransientEventMessagesFactory : IEventMessagesFactory
|
||||
{
|
||||
public EventMessages Get()
|
||||
{
|
||||
@@ -19,6 +19,7 @@ namespace Umbraco.Core.IO
|
||||
string MapPath(string path, bool useHttpContext);
|
||||
string MapPath(string path);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the current filepath matches a directory where the user is allowed to edit a file.
|
||||
/// </summary>
|
||||
|
||||
@@ -7,6 +7,13 @@ namespace Umbraco.Core.Logging
|
||||
/// </summary>
|
||||
public class DebugDiagnosticsLogger : ILogger
|
||||
{
|
||||
private readonly IMessageTemplates _messageTemplates;
|
||||
|
||||
public DebugDiagnosticsLogger(IMessageTemplates messageTemplates)
|
||||
{
|
||||
_messageTemplates = messageTemplates;
|
||||
}
|
||||
|
||||
public bool IsEnabled(Type reporting, LogLevel level)
|
||||
=> true;
|
||||
|
||||
@@ -31,7 +38,7 @@ namespace Umbraco.Core.Logging
|
||||
/// <inheritdoc/>
|
||||
public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -61,7 +68,7 @@ namespace Umbraco.Core.Logging
|
||||
/// <inheritdoc/>
|
||||
public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -79,7 +86,7 @@ namespace Umbraco.Core.Logging
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, string message, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(message, propertyValues), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -91,7 +98,7 @@ namespace Umbraco.Core.Logging
|
||||
/// <inheritdoc/>
|
||||
public void Warn(Type reporting, Exception exception, string message, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message + Environment.NewLine + exception, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(message + Environment.NewLine + exception, propertyValues), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -103,7 +110,7 @@ namespace Umbraco.Core.Logging
|
||||
/// <inheritdoc/>
|
||||
public void Info(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -115,7 +122,7 @@ namespace Umbraco.Core.Logging
|
||||
/// <inheritdoc/>
|
||||
public void Debug(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -127,7 +134,7 @@ namespace Umbraco.Core.Logging
|
||||
/// <inheritdoc/>
|
||||
public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
|
||||
System.Diagnostics.Debug.WriteLine(_messageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/Umbraco.Abstractions/Logging/IMessageTemplates.cs
Normal file
10
src/Umbraco.Abstractions/Logging/IMessageTemplates.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides tools to support message templates.
|
||||
/// </summary>
|
||||
public interface IMessageTemplates
|
||||
{
|
||||
string Render(string messageTemplate, params object[] args);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Logging
|
||||
/// <summary>
|
||||
/// Implements <see cref="IProfiler"/> by writing profiling results to an <see cref="ILogger"/>.
|
||||
/// </summary>
|
||||
internal class LogProfiler : IProfiler
|
||||
public class LogProfiler : IProfiler
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
internal class VoidProfiler : IProfiler
|
||||
public class VoidProfiler : IProfiler
|
||||
{
|
||||
private readonly VoidDisposable _disposable = new VoidDisposable();
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace Umbraco.Core.Models.Entities
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
|
||||
// just in case
|
||||
if (entity.CreateDate == default)
|
||||
{
|
||||
entity.CreateDate = now;
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Text;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
internal static class NameValueCollectionExtensions
|
||||
public static class NameValueCollectionExtensions
|
||||
{
|
||||
public static IEnumerable<KeyValuePair<string, string>> AsEnumerable(this NameValueCollection nvc)
|
||||
{
|
||||
35
src/Umbraco.Abstractions/Properties/AssemblyInfo.cs
Normal file
35
src/Umbraco.Abstractions/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: Guid("DA322714-FB89-4943-92BD-BB122B82F66B")]
|
||||
|
||||
// Umbraco Cms
|
||||
[assembly: InternalsVisibleTo("Umbraco.Web")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Web.UI")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Examine")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.ModelsBuilder.Embedded")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests.Benchmarks")]
|
||||
|
||||
// Allow this to be mocked in our unit tests
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
|
||||
// Umbraco Deploy
|
||||
[assembly: InternalsVisibleTo("Umbraco.Deploy")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Deploy.UI")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Deploy.Cloud")]
|
||||
|
||||
// Umbraco Forms
|
||||
[assembly: InternalsVisibleTo("Umbraco.Forms.Core")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Forms.Core.Providers")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Forms.Web")]
|
||||
|
||||
// Umbraco Headless
|
||||
[assembly: InternalsVisibleTo("Umbraco.Cloud.Headless")]
|
||||
|
||||
// code analysis
|
||||
// IDE1006 is broken, wants _value syntax for consts, etc - and it's even confusing ppl at MS, kill it
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "~_~")]
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// Marker interface for any editor configuration that supports Ignoring user start nodes
|
||||
/// </summary>
|
||||
internal interface IIgnoreUserStartNodesConfig
|
||||
public interface IIgnoreUserStartNodesConfig
|
||||
{
|
||||
bool IgnoreUserStartNodes { get; set; }
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<RootNamespace>Umbraco.Core</RootNamespace>
|
||||
<AssemblyVersion>9.0.0</AssemblyVersion>
|
||||
<InformationalVersion>9.0.0</InformationalVersion>
|
||||
<FileVersion>9.0.0</FileVersion>
|
||||
<Product>Umbraco CMS</Product>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
34
src/Umbraco.Configuration/ConfigsFactory.cs
Normal file
34
src/Umbraco.Configuration/ConfigsFactory.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class ConfigsFactory : IConfigsFactory
|
||||
{
|
||||
private readonly IIOHelper _ioHelper;
|
||||
|
||||
public ConfigsFactory(IIOHelper ioHelper)
|
||||
{
|
||||
_ioHelper = ioHelper;
|
||||
GlobalSettings = new GlobalSettings(_ioHelper);
|
||||
}
|
||||
|
||||
public IGlobalSettings GlobalSettings { get; }
|
||||
|
||||
public Configs Create()
|
||||
{
|
||||
var configs = new Configs(section => ConfigurationManager.GetSection(section));
|
||||
configs.Add<IGlobalSettings>(() => GlobalSettings);
|
||||
|
||||
configs.Add<IUmbracoSettingsSection>("umbracoConfiguration/settings");
|
||||
configs.Add<IHealthChecks>("umbracoConfiguration/HealthChecks");
|
||||
|
||||
configs.Add<ICoreDebug>(() => new CoreDebug());
|
||||
configs.Add<IConnectionStrings>(() => new ConnectionStrings());
|
||||
configs.AddCoreConfigs(_ioHelper);
|
||||
return configs;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/Umbraco.Configuration/ConnectionStrings.cs
Normal file
21
src/Umbraco.Configuration/ConnectionStrings.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class ConnectionStrings : IConnectionStrings
|
||||
{
|
||||
public ConfigConnectionString this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
var settings = ConfigurationManager.ConnectionStrings[key];
|
||||
|
||||
return new ConfigConnectionString(settings.ConnectionString, settings.ProviderName, settings.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,21 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
internal class CoreDebug
|
||||
public class CoreDebug : ICoreDebug
|
||||
{
|
||||
public CoreDebug()
|
||||
{
|
||||
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
|
||||
var appSettings = ConfigurationManager.AppSettings;
|
||||
LogUncompletedScopes = string.Equals("true", appSettings[Constants.AppSettings.Debug.LogUncompletedScopes], StringComparison.OrdinalIgnoreCase);
|
||||
DumpOnTimeoutThreadAbort = string.Equals("true", appSettings[Constants.AppSettings.Debug.DumpOnTimeoutThreadAbort], StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
// when true, Scope logs the stack trace for any scope that gets disposed without being completed.
|
||||
// this helps troubleshooting rogue scopes that we forget to complete
|
||||
/// <inheritdoc />
|
||||
public bool LogUncompletedScopes { get; }
|
||||
|
||||
// when true, the Logger creates a mini dump of w3wp in ~/App_Data/MiniDump whenever it logs
|
||||
// an error due to a ThreadAbortException that is due to a timeout.
|
||||
/// <inheritdoc />
|
||||
public bool DumpOnTimeoutThreadAbort { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,7 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net.Configuration;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
@@ -19,6 +14,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// </summary>
|
||||
public class GlobalSettings : IGlobalSettings
|
||||
{
|
||||
private readonly IIOHelper _ioHelper;
|
||||
private string _localTempPath;
|
||||
|
||||
// TODO these should not be static
|
||||
@@ -29,6 +25,11 @@ namespace Umbraco.Core.Configuration
|
||||
internal const string StaticReservedPaths = "~/app_plugins/,~/install/,~/mini-profiler-resources/,"; //must end with a comma!
|
||||
internal const string StaticReservedUrls = "~/config/splashes/noNodes.aspx,~/.well-known,"; //must end with a comma!
|
||||
|
||||
public GlobalSettings(IIOHelper ioHelper)
|
||||
{
|
||||
_ioHelper = ioHelper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used in unit testing to reset all config items that were set with property setters (i.e. did not come from config)
|
||||
/// </summary>
|
||||
@@ -47,20 +48,42 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
ResetInternal();
|
||||
}
|
||||
|
||||
public static bool HasSmtpServerConfigured(string appPath)
|
||||
public bool IsSmtpServerConfigured
|
||||
{
|
||||
if (HasSmtpServer.HasValue) return HasSmtpServer.Value;
|
||||
get
|
||||
{
|
||||
var smtpSection = ConfigurationManager.GetSection("system.net/mailSettings/smtp") as ConfigurationSection;
|
||||
if (smtpSection is null) return false;
|
||||
|
||||
var config = WebConfigurationManager.OpenWebConfiguration(appPath);
|
||||
var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings");
|
||||
// note: "noreply@example.com" is/was the sample SMTP from email - we'll regard that as "not configured"
|
||||
if (settings == null || settings.Smtp == null || "noreply@example.com".Equals(settings.Smtp.From, StringComparison.OrdinalIgnoreCase)) return false;
|
||||
if (settings.Smtp.SpecifiedPickupDirectory != null && string.IsNullOrEmpty(settings.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation) == false)
|
||||
return true;
|
||||
if (settings.Smtp.Network != null && string.IsNullOrEmpty(settings.Smtp.Network.Host) == false)
|
||||
return true;
|
||||
return false;
|
||||
var from = smtpSection.ElementInformation.Properties["from"];
|
||||
if (@from != null
|
||||
&& @from.Value is string fromPropValue
|
||||
&& string.IsNullOrEmpty(fromPropValue) == false
|
||||
&& !string.Equals("noreply@example.com", fromPropValue, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var networkSection = ConfigurationManager.GetSection("system.net/mailSettings/smtp/network") as ConfigurationSection;
|
||||
var host = networkSection?.ElementInformation.Properties["host"];
|
||||
if (host != null
|
||||
&& host.Value is string hostPropValue
|
||||
&& string.IsNullOrEmpty(hostPropValue) == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var specifiedPickupDirectorySection = ConfigurationManager.GetSection("system.net/mailSettings/smtp/specifiedPickupDirectory") as ConfigurationSection;
|
||||
var pickupDirectoryLocation = specifiedPickupDirectorySection?.ElementInformation.Properties["pickupDirectoryLocation"];
|
||||
if (pickupDirectoryLocation != null
|
||||
&& pickupDirectoryLocation.Value is string pickupDirectoryLocationPropValue
|
||||
&& string.IsNullOrEmpty(pickupDirectoryLocationPropValue) == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -141,7 +164,7 @@ namespace Umbraco.Core.Configuration
|
||||
get
|
||||
{
|
||||
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path)
|
||||
? Current.IOHelper.ResolveUrl(ConfigurationManager.AppSettings[Constants.AppSettings.Path])
|
||||
? _ioHelper.ResolveUrl(ConfigurationManager.AppSettings[Constants.AppSettings.Path])
|
||||
: string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +183,7 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
set
|
||||
{
|
||||
SaveSetting(Constants.AppSettings.ConfigurationStatus, value);
|
||||
SaveSetting(Constants.AppSettings.ConfigurationStatus, value, _ioHelper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,9 +192,9 @@ namespace Umbraco.Core.Configuration
|
||||
/// </summary>
|
||||
/// <param name="key">Key of the setting to be saved.</param>
|
||||
/// <param name="value">Value of the setting to be saved.</param>
|
||||
internal static void SaveSetting(string key, string value)
|
||||
internal static void SaveSetting(string key, string value, IIOHelper ioHelper)
|
||||
{
|
||||
var fileName = Current.IOHelper.MapPath(string.Format("{0}/web.config", Current.IOHelper.Root));
|
||||
var fileName = ioHelper.MapPath(string.Format("{0}/web.config", ioHelper.Root));
|
||||
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
|
||||
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
|
||||
@@ -191,9 +214,9 @@ namespace Umbraco.Core.Configuration
|
||||
/// Removes a setting from the configuration file.
|
||||
/// </summary>
|
||||
/// <param name="key">Key of the setting to be removed.</param>
|
||||
internal static void RemoveSetting(string key)
|
||||
public static void RemoveSetting(string key, IIOHelper ioHelper)
|
||||
{
|
||||
var fileName = Current.IOHelper.MapPath(string.Format("{0}/web.config", Current.IOHelper.Root));
|
||||
var fileName = ioHelper.MapPath(string.Format("{0}/web.config", ioHelper.Root));
|
||||
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
|
||||
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
|
||||
@@ -207,28 +230,25 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether umbraco is running in [debug mode].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [debug mode]; otherwise, <c>false</c>.</value>
|
||||
public static bool DebugMode
|
||||
public bool DebugMode
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (HttpContext.Current != null)
|
||||
if (ConfigurationManager.GetSection("system.web/compilation") is ConfigurationSection compilation)
|
||||
{
|
||||
return HttpContext.Current.IsDebuggingEnabled;
|
||||
var debugElement = compilation.ElementInformation.Properties["debug"];
|
||||
|
||||
return debugElement != null && (debugElement.Value is bool debug && debug);
|
||||
}
|
||||
//go and get it from config directly
|
||||
var section = ConfigurationManager.GetSection("system.web/compilation") as CompilationSection;
|
||||
return section != null && section.Debug;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
// ignored
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,47 +303,6 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string LocalTempPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_localTempPath != null)
|
||||
return _localTempPath;
|
||||
|
||||
switch (LocalTempStorageLocation)
|
||||
{
|
||||
case LocalTempStorage.AspNetTemp:
|
||||
return _localTempPath = System.IO.Path.Combine(HttpRuntime.CodegenDir, "UmbracoData");
|
||||
|
||||
case LocalTempStorage.EnvironmentTemp:
|
||||
|
||||
// environment temp is unique, we need a folder per site
|
||||
|
||||
// use a hash
|
||||
// combine site name and application id
|
||||
// site name is a Guid on Cloud
|
||||
// application id is eg /LM/W3SVC/123456/ROOT
|
||||
// the combination is unique on one server
|
||||
// and, if a site moves from worker A to B and then back to A...
|
||||
// hopefully it gets a new Guid or new application id?
|
||||
|
||||
var siteName = HostingEnvironment.SiteName;
|
||||
var applicationId = HostingEnvironment.ApplicationID; // ie HttpRuntime.AppDomainAppId
|
||||
|
||||
var hashString = siteName + "::" + applicationId;
|
||||
var hash = hashString.GenerateHash();
|
||||
var siteTemp = System.IO.Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", hash);
|
||||
|
||||
return _localTempPath = siteTemp;
|
||||
|
||||
//case LocalTempStorage.Default:
|
||||
//case LocalTempStorage.Unknown:
|
||||
default:
|
||||
return _localTempPath = Current.IOHelper.MapPath("~/App_Data/TEMP");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default UI language.
|
||||
@@ -391,6 +370,21 @@ namespace Umbraco.Core.Configuration
|
||||
private string _umbracoPath = null;
|
||||
public string UmbracoPath => GetterWithDefaultValue(Constants.AppSettings.UmbracoPath, "~/umbraco", ref _umbracoPath);
|
||||
|
||||
private bool _installMissingDatabase;
|
||||
public bool InstallMissingDatabase => GetterWithDefaultValue("Umbraco.Core.RuntimeState.InstallMissingDatabase", false, ref _installMissingDatabase);
|
||||
|
||||
private bool _installEmptyDatabase;
|
||||
public bool InstallEmptyDatabase => GetterWithDefaultValue("Umbraco.Core.RuntimeState.InstallEmptyDatabase", false, ref _installEmptyDatabase);
|
||||
|
||||
private bool _disableElectionForSingleServer;
|
||||
public bool DisableElectionForSingleServer => GetterWithDefaultValue(Constants.AppSettings.DisableElectionForSingleServer, false, ref _disableElectionForSingleServer);
|
||||
|
||||
private string _registerType;
|
||||
public string RegisterType => GetterWithDefaultValue(Constants.AppSettings.RegisterType, string.Empty, ref _registerType);
|
||||
|
||||
private string _databaseFactoryServerVersion;
|
||||
public string DatabaseFactoryServerVersion => GetterWithDefaultValue(Constants.AppSettings.Debug.DatabaseFactoryServerVersion, string.Empty, ref _databaseFactoryServerVersion);
|
||||
|
||||
private T GetterWithDefaultValue<T>(string appSettingKey, T defaultValue, ref T backingField)
|
||||
{
|
||||
if (backingField != null) return backingField;
|
||||
10
src/Umbraco.Configuration/Properties/AssemblyInfo.cs
Normal file
10
src/Umbraco.Configuration/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Umbraco Cms
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests.Benchmarks")]
|
||||
|
||||
// Allow this to be mocked in our unit tests
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
39
src/Umbraco.Configuration/Umbraco.Configuration.csproj
Normal file
39
src/Umbraco.Configuration/Umbraco.Configuration.csproj
Normal file
@@ -0,0 +1,39 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="obj\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Remove="obj\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="obj\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_UnmanagedRegistrationCache Remove="obj\Umbraco.Configuration.csproj.UnmanagedRegistration.cache" />
|
||||
<_UnmanagedRegistrationCache Remove="obj\Umbraco.Configuration.csproj.UnmanagedRegistration.cache" />
|
||||
<_UnmanagedRegistrationCache Remove="obj\Umbraco.Configuration.csproj.UnmanagedRegistration.cache" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Umbraco.Abstractions\Umbraco.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Umbraco.Core, Version=9.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<HintPath>C:\Users\Bjarke\AppData\Local\Temp\Temporary ASP.NET Files\root\408beac9\de517473\assembly\dl3\77bf709f\48ac59e4_3595d501\Umbraco.Core.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -33,7 +33,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
[ConfigurationProperty("allowedUploadFiles")]
|
||||
internal CommaDelimitedConfigurationElement AllowedUploadFiles => GetOptionalDelimitedElement("allowedUploadFiles", new string[0]);
|
||||
|
||||
|
||||
[ConfigurationProperty("showDeprecatedPropertyEditors")]
|
||||
internal InnerTextConfigurationElement<bool> ShowDeprecatedPropertyEditors => GetOptionalTextElement("showDeprecatedPropertyEditors", false);
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
//set the default
|
||||
GetDefaultImageFileTypes());
|
||||
|
||||
internal static string[] GetDefaultImageFileTypes()
|
||||
public static string[] GetDefaultImageFileTypes()
|
||||
{
|
||||
return new[] {"jpeg", "jpg", "gif", "bmp", "png", "tiff", "tif"};
|
||||
}
|
||||
@@ -49,7 +49,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
}
|
||||
}
|
||||
|
||||
internal static ImagingAutoFillPropertiesCollection GetDefaultImageAutoFillProperties()
|
||||
public static ImagingAutoFillPropertiesCollection GetDefaultImageAutoFillProperties()
|
||||
{
|
||||
return new ImagingAutoFillPropertiesCollection
|
||||
{
|
||||
@@ -38,7 +38,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
}
|
||||
}
|
||||
|
||||
internal static CharCollection GetDefaultCharReplacements()
|
||||
public static CharCollection GetDefaultCharReplacements()
|
||||
{
|
||||
var dictionary = new Dictionary<char, string>()
|
||||
{
|
||||
@@ -2,26 +2,26 @@
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public class UmbracoSettingsSection : ConfigurationSection, IUmbracoSettingsSection
|
||||
internal class UmbracoSettingsSection : ConfigurationSection, IUmbracoSettingsSection
|
||||
{
|
||||
[ConfigurationProperty("backOffice")]
|
||||
internal BackOfficeElement BackOffice => (BackOfficeElement)this["backOffice"];
|
||||
public BackOfficeElement BackOffice => (BackOfficeElement)this["backOffice"];
|
||||
|
||||
[ConfigurationProperty("content")]
|
||||
internal ContentElement Content => (ContentElement)this["content"];
|
||||
public ContentElement Content => (ContentElement)this["content"];
|
||||
|
||||
[ConfigurationProperty("security")]
|
||||
internal SecurityElement Security => (SecurityElement)this["security"];
|
||||
public SecurityElement Security => (SecurityElement)this["security"];
|
||||
|
||||
[ConfigurationProperty("requestHandler")]
|
||||
internal RequestHandlerElement RequestHandler => (RequestHandlerElement)this["requestHandler"];
|
||||
public RequestHandlerElement RequestHandler => (RequestHandlerElement)this["requestHandler"];
|
||||
|
||||
[ConfigurationProperty("logging")]
|
||||
internal LoggingElement Logging => (LoggingElement)this["logging"];
|
||||
public LoggingElement Logging => (LoggingElement)this["logging"];
|
||||
|
||||
|
||||
[ConfigurationProperty("web.routing")]
|
||||
internal WebRoutingElement WebRouting => (WebRoutingElement)this["web.routing"];
|
||||
public WebRoutingElement WebRouting => (WebRoutingElement)this["web.routing"];
|
||||
|
||||
IContentSection IUmbracoSettingsSection.Content => Content;
|
||||
|
||||
33
src/Umbraco.Configuration/UmbracoVersionExtensions.cs
Normal file
33
src/Umbraco.Configuration/UmbracoVersionExtensions.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Configuration;
|
||||
using Semver;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration
|
||||
{
|
||||
public static class UmbracoVersionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the "local" version of the site.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Three things have a version, really: the executing code, the database model,
|
||||
/// and the site/files. The database model version is entirely managed via migrations,
|
||||
/// and changes during an upgrade. The executing code version changes when new code is
|
||||
/// deployed. The site/files version changes during an upgrade.</para>
|
||||
/// </remarks>
|
||||
public static SemVersion LocalVersion(this IUmbracoVersion umbracoVersion)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings
|
||||
var value = ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus];
|
||||
return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Core.Composing
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool HasFactory => _factory != null;
|
||||
public static bool HasFactory => _factory != null;
|
||||
|
||||
/// <summary>
|
||||
/// Resets <see cref="Current"/>. Indented for testing only, and not supported in production code.
|
||||
@@ -93,11 +93,11 @@ namespace Umbraco.Core.Composing
|
||||
/// <para>Unlocks <see cref="Configs"/> so that it is possible to add configurations
|
||||
/// directly to <see cref="Current"/> without having to wire composition.</para>
|
||||
/// </remarks>
|
||||
public static void UnlockConfigs()
|
||||
public static void UnlockConfigs(IConfigsFactory configsFactory)
|
||||
{
|
||||
if (_factory != null)
|
||||
throw new InvalidOperationException("Cannot unlock configs when a factory has been set.");
|
||||
_configs = new Configs();
|
||||
_configs = configsFactory.Create();
|
||||
}
|
||||
|
||||
internal static event EventHandler Resetted;
|
||||
@@ -113,7 +113,7 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
public static ILogger Logger
|
||||
=> _logger ?? (_logger = _factory?.TryGetInstance<ILogger>()
|
||||
?? new DebugDiagnosticsLogger());
|
||||
?? new DebugDiagnosticsLogger(new MessageTemplates()));
|
||||
|
||||
public static IProfiler Profiler
|
||||
=> _profiler ?? (_profiler = _factory?.TryGetInstance<IProfiler>()
|
||||
@@ -207,6 +207,9 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
public static readonly IIOHelper IOHelper = Umbraco.Core.IO.IOHelper.Default;
|
||||
|
||||
public static IUmbracoVersion UmbracoVersion
|
||||
=> Factory.GetInstance<IUmbracoVersion>();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
@@ -21,11 +21,11 @@ namespace Umbraco.Core.Composing
|
||||
/// To override the default LightInjectContainer, add an appSetting named 'Umbraco.Core.RegisterType' with
|
||||
/// a fully qualified type name to a class with a static method "Create" returning an IRegister.
|
||||
/// </remarks>
|
||||
public static IRegister Create()
|
||||
public static IRegister Create(IGlobalSettings globalSettings)
|
||||
{
|
||||
Type type;
|
||||
|
||||
var configuredTypeName = ConfigurationManager.AppSettings[Constants.AppSettings.RegisterType];
|
||||
var configuredTypeName = globalSettings.RegisterType;
|
||||
if (configuredTypeName.IsNullOrWhiteSpace())
|
||||
{
|
||||
// try to get the web LightInject container type,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -22,7 +23,8 @@ namespace Umbraco.Core
|
||||
TypeLoader typeLoader,
|
||||
IRuntimeState state,
|
||||
ITypeFinder typeFinder,
|
||||
IIOHelper ioHelper)
|
||||
IIOHelper ioHelper,
|
||||
IUmbracoVersion umbracoVersion)
|
||||
{
|
||||
composition.RegisterUnique(logger);
|
||||
composition.RegisterUnique(profiler);
|
||||
@@ -35,6 +37,7 @@ namespace Umbraco.Core
|
||||
composition.RegisterUnique(state);
|
||||
composition.RegisterUnique(typeFinder);
|
||||
composition.RegisterUnique(ioHelper);
|
||||
composition.RegisterUnique(umbracoVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using Umbraco.Core.Composing;
|
||||
using System.Web.Hosting;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
|
||||
public static class GlobalSettingsExtensions
|
||||
{
|
||||
private static string _mvcArea;
|
||||
|
||||
private static string _localTempPath;
|
||||
|
||||
/// <summary>
|
||||
/// This returns the string of the MVC Area route.
|
||||
/// Gets the location of temporary files.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will return the MVC area that we will route all custom routes through like surface controllers, etc...
|
||||
/// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin
|
||||
/// we will convert the '/' to '-' and use that as the path. its a bit lame but will work.
|
||||
///
|
||||
/// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something
|
||||
/// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco".
|
||||
/// </remarks>
|
||||
public static string GetUmbracoMvcArea(this IGlobalSettings globalSettings)
|
||||
public static string LocalTempPath(this IGlobalSettings globalSettings, IIOHelper ioHelper)
|
||||
{
|
||||
if (_mvcArea != null) return _mvcArea;
|
||||
|
||||
_mvcArea = GetUmbracoMvcAreaNoCache(globalSettings);
|
||||
if (_localTempPath != null)
|
||||
return _localTempPath;
|
||||
|
||||
return _mvcArea;
|
||||
}
|
||||
|
||||
internal static string GetUmbracoMvcAreaNoCache(this IGlobalSettings globalSettings)
|
||||
{
|
||||
if (globalSettings.Path.IsNullOrWhiteSpace())
|
||||
switch (globalSettings.LocalTempStorageLocation)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified");
|
||||
case LocalTempStorage.AspNetTemp:
|
||||
return _localTempPath = System.IO.Path.Combine(HttpRuntime.CodegenDir, "UmbracoData");
|
||||
|
||||
case LocalTempStorage.EnvironmentTemp:
|
||||
|
||||
// environment temp is unique, we need a folder per site
|
||||
|
||||
// use a hash
|
||||
// combine site name and application id
|
||||
// site name is a Guid on Cloud
|
||||
// application id is eg /LM/W3SVC/123456/ROOT
|
||||
// the combination is unique on one server
|
||||
// and, if a site moves from worker A to B and then back to A...
|
||||
// hopefully it gets a new Guid or new application id?
|
||||
|
||||
var siteName = HostingEnvironment.SiteName;
|
||||
var applicationId = HostingEnvironment.ApplicationID; // ie HttpRuntime.AppDomainAppId
|
||||
|
||||
var hashString = siteName + "::" + applicationId;
|
||||
var hash = hashString.GenerateHash();
|
||||
var siteTemp = System.IO.Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", hash);
|
||||
|
||||
return _localTempPath = siteTemp;
|
||||
|
||||
//case LocalTempStorage.Default:
|
||||
//case LocalTempStorage.Unknown:
|
||||
default:
|
||||
return _localTempPath = ioHelper.MapPath("~/App_Data/TEMP");
|
||||
}
|
||||
|
||||
var path = globalSettings.Path;
|
||||
if (path.StartsWith(Current.IOHelper.Root)) // beware of TrimStart, see U4-2518
|
||||
path = path.Substring(Current.IOHelper.Root.Length);
|
||||
return path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user