diff --git a/.gitignore b/.gitignore
index 12ad3299ad..5390da67dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -164,3 +164,6 @@ build/temp/
# eof
/src/Umbraco.Web.UI.Client/TESTS-*.xml
/src/ApiDocs/api/*
+/src/Umbraco.Web.UI.NetCore/wwwroot/Media/*
+/src/Umbraco.Web.UI.NetCore/wwwroot/is-cache/*
+/src/Umbraco.Tests.Integration/App_Data/*
diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec
index 7199f414b1..969ac5be3d 100644
--- a/build/NuSpecs/UmbracoCms.Web.nuspec
+++ b/build/NuSpecs/UmbracoCms.Web.nuspec
@@ -25,7 +25,7 @@
not want this to happen as the alpha of the next major is, really, the next major already.
-->
-
+
diff --git a/build/build-bootstrap.ps1 b/build/build-bootstrap.ps1
index 71a25bfd7e..82c789ff22 100644
--- a/build/build-bootstrap.ps1
+++ b/build/build-bootstrap.ps1
@@ -22,6 +22,8 @@
# get NuGet
$cache = 4
$nuget = "$scriptTemp\nuget.exe"
+ # ensure the correct NuGet-source is used. This one is used by Umbraco
+ $nugetsourceUmbraco = "https://www.myget.org/F/umbracocore/api/v3/index.json"
if (-not $local)
{
$source = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
@@ -61,7 +63,7 @@
# get the build system
if (-not $local)
{
- $params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease"
+ $params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease", "-Source", $nugetsourceUmbraco
&$nuget install Umbraco.Build @params
if (-not $?) { throw "Failed to download Umbraco.Build." }
}
diff --git a/build/build.ps1 b/build/build.ps1
index ea07e4516f..6e124d1508 100644
--- a/build/build.ps1
+++ b/build/build.ps1
@@ -375,11 +375,14 @@
})
+ $nugetsourceUmbraco = "https://api.nuget.org/v3/index.json"
+
$ubuild.DefineMethod("RestoreNuGet",
{
Write-Host "Restore NuGet"
Write-Host "Logging to $($this.BuildTemp)\nuget.restore.log"
- &$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log"
+ $params = "-Source", $nugetsourceUmbraco
+ &$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log" @params
if (-not $?) { throw "Failed to restore NuGet packages." }
})
diff --git a/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs b/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs
new file mode 100644
index 0000000000..0cacab9e1d
--- /dev/null
+++ b/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs
@@ -0,0 +1,50 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Configuration.Models;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.HealthChecks;
+using Umbraco.Core.Configuration.UmbracoSettings;
+using ConnectionStrings = Umbraco.Configuration.Models.ConnectionStrings;
+using CoreDebugSettings = Umbraco.Configuration.Models.CoreDebugSettings;
+
+namespace Umbraco.Configuration
+{
+ public class AspNetCoreConfigsFactory : IConfigsFactory
+ {
+ private readonly IConfiguration _configuration;
+
+ public AspNetCoreConfigsFactory(IConfiguration configuration)
+ {
+ _configuration = configuration ?? throw new System.ArgumentNullException(nameof(configuration));
+ }
+
+ public Configs Create()
+ {
+ var configs = new Configs();
+
+ configs.Add(() => new TourSettings(_configuration));
+ configs.Add(() => new CoreDebugSettings(_configuration));
+ configs.Add(() => new RequestHandlerSettings(_configuration));
+ configs.Add(() => new SecuritySettings(_configuration));
+ configs.Add(() => new UserPasswordConfigurationSettings(_configuration));
+ configs.Add(() => new MemberPasswordConfigurationSettings(_configuration));
+ configs.Add(() => new KeepAliveSettings(_configuration));
+ configs.Add(() => new ContentSettings(_configuration));
+ configs.Add(() => new HealthChecksSettings(_configuration));
+ configs.Add(() => new LoggingSettings(_configuration));
+ configs.Add(() => new ExceptionFilterSettings(_configuration));
+ configs.Add(() => new ActiveDirectorySettings(_configuration));
+ configs.Add(() => new RuntimeSettings(_configuration));
+ configs.Add(() => new TypeFinderSettings(_configuration));
+ configs.Add(() => new NuCacheSettings(_configuration));
+ configs.Add(() => new WebRoutingSettings(_configuration));
+ configs.Add(() => new IndexCreatorSettings(_configuration));
+ configs.Add(() => new ModelsBuilderConfig(_configuration));
+ configs.Add(() => new HostingSettings(_configuration));
+ configs.Add(() => new GlobalSettings(_configuration));
+ configs.Add(() => new ConnectionStrings(_configuration));
+ configs.Add(() => new ImagingSettings(_configuration));
+
+ return configs;
+ }
+ }
+}
diff --git a/src/Umbraco.Configuration/CaseInsensitiveEnumConfigConverter.cs b/src/Umbraco.Configuration/CaseInsensitiveEnumConfigConverter.cs
deleted file mode 100644
index f07e5133ef..0000000000
--- a/src/Umbraco.Configuration/CaseInsensitiveEnumConfigConverter.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-using System.ComponentModel;
-using System.Globalization;
-using System.Linq;
-using System.Configuration;
-
-namespace Umbraco.Core.Configuration
-{
- ///
- /// A case-insensitive configuration converter for enumerations.
- ///
- /// The type of the enumeration.
- public class CaseInsensitiveEnumConfigConverter : ConfigurationConverterBase
- where T : struct
- {
- public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
- {
- if (data == null)
- throw new ArgumentNullException("data");
-
- //return Enum.Parse(typeof(T), (string)data, true);
-
- T value;
- if (Enum.TryParse((string)data, true, out value))
- return value;
-
- throw new Exception(string.Format("\"{0}\" is not valid {1} value. Valid values are: {2}.",
- data, typeof(T).Name,
- string.Join(", ", Enum.GetValues(typeof(T)).Cast())));
- }
- }
-}
diff --git a/src/Umbraco.Configuration/ConfigsFactory.cs b/src/Umbraco.Configuration/ConfigsFactory.cs
index 3742b7d7fa..be6cee2d0c 100644
--- a/src/Umbraco.Configuration/ConfigsFactory.cs
+++ b/src/Umbraco.Configuration/ConfigsFactory.cs
@@ -1,53 +1,62 @@
-using System.Configuration;
using Umbraco.Configuration;
+using Umbraco.Configuration.Implementations;
+using Umbraco.Configuration.Legacy;
using Umbraco.Core.Configuration.HealthChecks;
+using Umbraco.Core.Configuration.Legacy;
using Umbraco.Core.Configuration.UmbracoSettings;
-using Umbraco.Core.IO;
namespace Umbraco.Core.Configuration
{
public class ConfigsFactory : IConfigsFactory
{
public IHostingSettings HostingSettings { get; } = new HostingSettings();
-
- public ICoreDebug CoreDebug { get; } = new CoreDebug();
- public IMachineKeyConfig MachineKeyConfig { get; } = new MachineKeyConfig();
+ public ICoreDebugSettings CoreDebugSettings { get; } = new CoreDebugSettings();
public IIndexCreatorSettings IndexCreatorSettings { get; } = new IndexCreatorSettings();
public INuCacheSettings NuCacheSettings { get; } = new NuCacheSettings();
public ITypeFinderSettings TypeFinderSettings { get; } = new TypeFinderSettings();
public IRuntimeSettings RuntimeSettings { get; } = new RuntimeSettings();
public IActiveDirectorySettings ActiveDirectorySettings { get; } = new ActiveDirectorySettings();
public IExceptionFilterSettings ExceptionFilterSettings { get; } = new ExceptionFilterSettings();
+ public ITourSettings TourSettings { get; } = new TourSettings();
+ public ILoggingSettings LoggingSettings { get; } = new LoggingSettings();
+ public IKeepAliveSettings KeepAliveSettings { get; } = new KeepAliveSettings();
+ public IWebRoutingSettings WebRoutingSettings { get; } = new WebRoutingSettings();
+ public IRequestHandlerSettings RequestHandlerSettings { get; } = new RequestHandlerSettings();
+ public ISecuritySettings SecuritySettings { get; } = new SecuritySettings();
+ public IUserPasswordConfiguration UserPasswordConfigurationSettings { get; } = new UserPasswordConfigurationSettings();
+ public IMemberPasswordConfiguration MemberPasswordConfigurationSettings { get; } = new MemberPasswordConfigurationSettings();
+ public IContentSettings ContentSettings { get; } = new ContentSettings();
+ public IGlobalSettings GlobalSettings { get; } = new GlobalSettings();
+ public IHealthChecksSettings HealthChecksSettings { get; } = new HealthChecksSettings();
+ public IConnectionStrings ConnectionStrings { get; } = new ConnectionStrings();
+ public IModelsBuilderConfig ModelsBuilderConfig { get; } = new ModelsBuilderConfig();
- public IUmbracoSettingsSection UmbracoSettings { get; }
-
- public Configs Create(IIOHelper ioHelper)
+ public Configs Create()
{
- var configs = new Configs(section => ConfigurationManager.GetSection(section));
- configs.Add(() => new GlobalSettings(ioHelper));
- configs.Add(() => HostingSettings);
-
- configs.Add("umbracoConfiguration/settings");
- configs.Add("umbracoConfiguration/HealthChecks");
-
- // Password configuration is held within IUmbracoSettingsSection from umbracoConfiguration/settings but we'll add explicitly
- // so it can be independently retrieved in classes that need it.
- configs.AddPasswordConfigurations();
-
- configs.Add(() => CoreDebug);
- configs.Add(() => MachineKeyConfig);
- configs.Add(() => new ConnectionStrings(ioHelper));
- configs.Add(() => new ModelsBuilderConfig(ioHelper));
-
+ var configs = new Configs();
+ configs.Add(() => GlobalSettings);
+ configs.Add(() => HostingSettings);
+ configs.Add(() => HealthChecksSettings);
+ configs.Add(() => CoreDebugSettings);
+ configs.Add(() => ConnectionStrings);
+ configs.Add(() => ModelsBuilderConfig);
configs.Add(() => IndexCreatorSettings);
configs.Add(() => NuCacheSettings);
configs.Add(() => TypeFinderSettings);
configs.Add(() => RuntimeSettings);
configs.Add(() => ActiveDirectorySettings);
configs.Add(() => ExceptionFilterSettings);
+ configs.Add(() => TourSettings);
+ configs.Add(() => LoggingSettings);
+ configs.Add(() => KeepAliveSettings);
+ configs.Add(() => WebRoutingSettings);
+ configs.Add(() => RequestHandlerSettings);
+ configs.Add(() => SecuritySettings);
+ configs.Add(() => UserPasswordConfigurationSettings);
+ configs.Add(() => MemberPasswordConfigurationSettings);
+ configs.Add(() => ContentSettings);
- configs.AddCoreConfigs(ioHelper);
return configs;
}
}
diff --git a/src/Umbraco.Configuration/ConnectionStrings.cs b/src/Umbraco.Configuration/ConnectionStrings.cs
deleted file mode 100644
index 6a00974831..0000000000
--- a/src/Umbraco.Configuration/ConnectionStrings.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using System.Configuration;
-using System.Linq;
-using System.Xml.Linq;
-using Umbraco.Core.IO;
-
-namespace Umbraco.Core.Configuration
-{
- public class ConnectionStrings : IConnectionStrings
- {
- private readonly IIOHelper _ioHelper;
-
- public ConnectionStrings(IIOHelper ioHelper)
- {
- _ioHelper = ioHelper;
- }
-
- public ConfigConnectionString this[string key]
- {
- get
- {
- var settings = ConfigurationManager.ConnectionStrings[key];
- if (settings == null) return null;
- return new ConfigConnectionString(settings.ConnectionString, settings.ProviderName, settings.Name);
- }
- }
-
- public void RemoveConnectionString(string key)
- {
- 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();
- var setting = appSettings.Descendants("add").FirstOrDefault(s => s.Attribute("key").Value == key);
-
- if (setting != null)
- {
- setting.Remove();
- xml.Save(fileName, SaveOptions.DisableFormatting);
- ConfigurationManager.RefreshSection("appSettings");
- }
- var settings = ConfigurationManager.ConnectionStrings[key];
- }
- }
-}
diff --git a/src/Umbraco.Configuration/HealthChecks/HealthChecksSection.cs b/src/Umbraco.Configuration/HealthChecks/HealthChecksSection.cs
index 90a7d8c567..373d846567 100644
--- a/src/Umbraco.Configuration/HealthChecks/HealthChecksSection.cs
+++ b/src/Umbraco.Configuration/HealthChecks/HealthChecksSection.cs
@@ -1,10 +1,9 @@
using System;
-using System.Collections.Generic;
using System.Configuration;
namespace Umbraco.Core.Configuration.HealthChecks
{
- public class HealthChecksSection : ConfigurationSection, IHealthChecks
+ public class HealthChecksSection : ConfigurationSection
{
private const string DisabledChecksKey = "disabledChecks";
private const string NotificationSettingsKey = "notificationSettings";
@@ -21,14 +20,5 @@ namespace Umbraco.Core.Configuration.HealthChecks
get { return ((HealthCheckNotificationSettingsElement)(base[NotificationSettingsKey])); }
}
- IEnumerable IHealthChecks.DisabledChecks
- {
- get { return DisabledChecks; }
- }
-
- IHealthCheckNotificationSettings IHealthChecks.NotificationSettings
- {
- get { return NotificationSettings; }
- }
}
}
diff --git a/src/Umbraco.Configuration/ActiveDirectorySettings.cs b/src/Umbraco.Configuration/Legacy/ActiveDirectorySettings.cs
similarity index 90%
rename from src/Umbraco.Configuration/ActiveDirectorySettings.cs
rename to src/Umbraco.Configuration/Legacy/ActiveDirectorySettings.cs
index d85def7f33..ef100afed6 100644
--- a/src/Umbraco.Configuration/ActiveDirectorySettings.cs
+++ b/src/Umbraco.Configuration/Legacy/ActiveDirectorySettings.cs
@@ -1,7 +1,7 @@
using System.Configuration;
using Umbraco.Core.Configuration;
-namespace Umbraco.Configuration
+namespace Umbraco.Configuration.Legacy
{
public class ActiveDirectorySettings : IActiveDirectorySettings
{
diff --git a/src/Umbraco.Configuration/CommaDelimitedConfigurationElement.cs b/src/Umbraco.Configuration/Legacy/CommaDelimitedConfigurationElement.cs
similarity index 100%
rename from src/Umbraco.Configuration/CommaDelimitedConfigurationElement.cs
rename to src/Umbraco.Configuration/Legacy/CommaDelimitedConfigurationElement.cs
diff --git a/src/Umbraco.Configuration/Legacy/ConfigurationManagerConfigBase.cs b/src/Umbraco.Configuration/Legacy/ConfigurationManagerConfigBase.cs
new file mode 100644
index 0000000000..0302a7ea31
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/ConfigurationManagerConfigBase.cs
@@ -0,0 +1,22 @@
+using System.Configuration;
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Implementations
+{
+ internal abstract class ConfigurationManagerConfigBase
+ {
+ private UmbracoSettingsSection _umbracoSettingsSection;
+
+ protected UmbracoSettingsSection UmbracoSettingsSection
+ {
+ get
+ {
+ if (_umbracoSettingsSection is null)
+ {
+ _umbracoSettingsSection = ConfigurationManager.GetSection("umbracoConfiguration/settings") as UmbracoSettingsSection;
+ }
+ return _umbracoSettingsSection;
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Configuration/Legacy/ConnectionStrings.cs b/src/Umbraco.Configuration/Legacy/ConnectionStrings.cs
new file mode 100644
index 0000000000..a02c351118
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/ConnectionStrings.cs
@@ -0,0 +1,17 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration
+{
+ public class ConnectionStrings : IConnectionStrings
+ {
+ public ConfigConnectionString this[string key]
+ {
+ get
+ {
+ var settings = ConfigurationManager.ConnectionStrings[key];
+ if (settings == null) return null;
+ return new ConfigConnectionString(settings.ConnectionString, settings.ProviderName, settings.Name);
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Configuration/Legacy/ContentSettings.cs b/src/Umbraco.Configuration/Legacy/ContentSettings.cs
new file mode 100644
index 0000000000..1c3f543bfe
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/ContentSettings.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using Umbraco.Core.Configuration.UmbracoSettings;
+using Umbraco.Core.Macros;
+
+namespace Umbraco.Configuration.Implementations
+{
+ internal class ContentSettings : ConfigurationManagerConfigBase, IContentSettings
+ {
+ public string NotificationEmailAddress => UmbracoSettingsSection.Content.Notifications.NotificationEmailAddress;
+ public bool DisableHtmlEmail => UmbracoSettingsSection.Content.Notifications.DisableHtmlEmail;
+ public IEnumerable ImageFileTypes => UmbracoSettingsSection.Content.Imaging.ImageFileTypes;
+ public IEnumerable ImageAutoFillProperties => UmbracoSettingsSection.Content.Imaging.ImageAutoFillProperties;
+ public bool ResolveUrlsFromTextString => UmbracoSettingsSection.Content.ResolveUrlsFromTextString;
+ public IEnumerable Error404Collection => UmbracoSettingsSection.Content.Error404Collection;
+ public string PreviewBadge => UmbracoSettingsSection.Content.PreviewBadge;
+ public MacroErrorBehaviour MacroErrorBehaviour => UmbracoSettingsSection.Content.MacroErrors;
+ public IEnumerable DisallowedUploadFiles => UmbracoSettingsSection.Content.DisallowedUploadFiles;
+ public IEnumerable AllowedUploadFiles => UmbracoSettingsSection.Content.AllowedUploadFiles;
+ public bool ShowDeprecatedPropertyEditors => UmbracoSettingsSection.Content.ShowDeprecatedPropertyEditors;
+ public string LoginBackgroundImage => UmbracoSettingsSection.Content.LoginBackgroundImage;
+ }
+}
diff --git a/src/Umbraco.Configuration/CoreDebug.cs b/src/Umbraco.Configuration/Legacy/CoreDebugSettings.cs
similarity index 87%
rename from src/Umbraco.Configuration/CoreDebug.cs
rename to src/Umbraco.Configuration/Legacy/CoreDebugSettings.cs
index 0ff3274565..4902d4489f 100644
--- a/src/Umbraco.Configuration/CoreDebug.cs
+++ b/src/Umbraco.Configuration/Legacy/CoreDebugSettings.cs
@@ -3,9 +3,9 @@ using System.Configuration;
namespace Umbraco.Core.Configuration
{
- public class CoreDebug : ICoreDebug
+ public class CoreDebugSettings : ICoreDebugSettings
{
- public CoreDebug()
+ public CoreDebugSettings()
{
var appSettings = ConfigurationManager.AppSettings;
LogUncompletedScopes = string.Equals("true", appSettings[Constants.AppSettings.Debug.LogUncompletedScopes], StringComparison.OrdinalIgnoreCase);
diff --git a/src/Umbraco.Configuration/ExceptionFilterSettings.cs b/src/Umbraco.Configuration/Legacy/ExceptionFilterSettings.cs
similarity index 92%
rename from src/Umbraco.Configuration/ExceptionFilterSettings.cs
rename to src/Umbraco.Configuration/Legacy/ExceptionFilterSettings.cs
index 628b8755cc..50e2207485 100644
--- a/src/Umbraco.Configuration/ExceptionFilterSettings.cs
+++ b/src/Umbraco.Configuration/Legacy/ExceptionFilterSettings.cs
@@ -1,7 +1,7 @@
using System.Configuration;
using Umbraco.Core.Configuration;
-namespace Umbraco.Configuration
+namespace Umbraco.Configuration.Legacy
{
public class ExceptionFilterSettings : IExceptionFilterSettings
{
diff --git a/src/Umbraco.Configuration/GlobalSettings.cs b/src/Umbraco.Configuration/Legacy/GlobalSettings.cs
similarity index 87%
rename from src/Umbraco.Configuration/GlobalSettings.cs
rename to src/Umbraco.Configuration/Legacy/GlobalSettings.cs
index 56e64fff31..78036f9e42 100644
--- a/src/Umbraco.Configuration/GlobalSettings.cs
+++ b/src/Umbraco.Configuration/Legacy/GlobalSettings.cs
@@ -3,59 +3,12 @@ using System.Configuration;
using System.Linq;
using System.Net.Mail;
using System.Xml.Linq;
+using Umbraco.Composing;
using Umbraco.Configuration;
using Umbraco.Core.IO;
-namespace Umbraco.Core.Configuration
+namespace Umbraco.Core.Configuration.Legacy
{
- public class HostingSettings : IHostingSettings
- {
- private bool? _debugMode;
-
- ///
- public LocalTempStorage LocalTempStorageLocation
- {
- get
- {
- var setting = ConfigurationManager.AppSettings[Constants.AppSettings.LocalTempStorage];
- if (!string.IsNullOrWhiteSpace(setting))
- return Enum.Parse(setting);
-
- return LocalTempStorage.Default;
- }
- }
-
- ///
- /// Gets a value indicating whether umbraco is running in [debug mode].
- ///
- /// true if [debug mode]; otherwise, false.
- public bool DebugMode
- {
- get
- {
- if (!_debugMode.HasValue)
- {
- try
- {
- if (ConfigurationManager.GetSection("system.web/compilation") is ConfigurationSection compilation)
- {
- var debugElement = compilation.ElementInformation.Properties["debug"];
-
- _debugMode = debugElement != null && (debugElement.Value is bool debug && debug);
-
- }
- }
- catch
- {
- _debugMode = false;
- }
- }
-
- return _debugMode.GetValueOrDefault();
- }
- }
- }
-
// TODO: Replace checking for if the app settings exist and returning an empty string, instead return the defaults!
// TODO: need to massively cleanup these configuration classes
@@ -64,7 +17,6 @@ namespace Umbraco.Core.Configuration
///
public class GlobalSettings : IGlobalSettings
{
- private readonly IIOHelper _ioHelper;
// TODO these should not be static
private static string _reservedPaths;
@@ -74,11 +26,6 @@ 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;
- }
-
///
/// Used in unit testing to reset all config items that were set with property setters (i.e. did not come from config)
///
@@ -203,15 +150,7 @@ namespace Umbraco.Core.Configuration
/// Gets the path to umbraco's root directory (/umbraco by default).
///
/// The path.
- public string Path
- {
- get
- {
- return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path)
- ? _ioHelper.ResolveUrl(ConfigurationManager.AppSettings[Constants.AppSettings.Path])
- : string.Empty;
- }
- }
+ public string Path => ConfigurationManager.AppSettings[Constants.AppSettings.Path];
///
/// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance.
@@ -227,7 +166,7 @@ namespace Umbraco.Core.Configuration
}
set
{
- SaveSetting(Constants.AppSettings.ConfigurationStatus, value, _ioHelper);
+ SaveSetting(Constants.AppSettings.ConfigurationStatus, value, Current.IOHelper); //TODO remove
}
}
@@ -254,7 +193,7 @@ namespace Umbraco.Core.Configuration
ConfigurationManager.RefreshSection("appSettings");
}
-
+
///
/// Gets the time out in minutes.
///
@@ -411,5 +350,22 @@ namespace Umbraco.Core.Configuration
return backingField;
}
+
+ ///
+ /// Gets the path to the razor file used when no published content is available.
+ ///
+ public string NoNodesViewPath
+ {
+ get
+ {
+ var configuredValue = ConfigurationManager.AppSettings[Constants.AppSettings.NoNodesViewPath];
+ if (!string.IsNullOrWhiteSpace(configuredValue))
+ {
+ return configuredValue;
+ }
+
+ return "~/config/splashes/NoNodes.cshtml";
+ }
+ }
}
}
diff --git a/src/Umbraco.Configuration/Legacy/HealthChecksSettings.cs b/src/Umbraco.Configuration/Legacy/HealthChecksSettings.cs
new file mode 100644
index 0000000000..23385d1378
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/HealthChecksSettings.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using System.Configuration;
+using Umbraco.Core.Configuration.HealthChecks;
+
+namespace Umbraco.Core.Configuration.Legacy
+{
+ public class HealthChecksSettings : IHealthChecksSettings
+ {
+ private HealthChecksSection _healthChecksSection;
+
+ private HealthChecksSection HealthChecksSection
+ {
+ get
+ {
+ if (_healthChecksSection is null)
+ {
+ _healthChecksSection = ConfigurationManager.GetSection("umbracoConfiguration/HealthChecks") as HealthChecksSection;
+ }
+ return _healthChecksSection;
+ }
+ }
+
+ public IEnumerable DisabledChecks => HealthChecksSection.DisabledChecks;
+ public IHealthCheckNotificationSettings NotificationSettings => HealthChecksSection.NotificationSettings;
+ }
+}
diff --git a/src/Umbraco.Configuration/Legacy/HostingSettings.cs b/src/Umbraco.Configuration/Legacy/HostingSettings.cs
new file mode 100644
index 0000000000..d0d09ea86f
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/HostingSettings.cs
@@ -0,0 +1,52 @@
+using System.Configuration;
+
+namespace Umbraco.Core.Configuration.Legacy
+{
+ public class HostingSettings : IHostingSettings
+ {
+ private bool? _debugMode;
+
+ ///
+ public LocalTempStorage LocalTempStorageLocation
+ {
+ get
+ {
+ var setting = ConfigurationManager.AppSettings[Constants.AppSettings.LocalTempStorage];
+ if (!string.IsNullOrWhiteSpace(setting))
+ return Enum.Parse(setting);
+
+ return LocalTempStorage.Default;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether umbraco is running in [debug mode].
+ ///
+ /// true if [debug mode]; otherwise, false.
+ public bool DebugMode
+ {
+ get
+ {
+ if (!_debugMode.HasValue)
+ {
+ try
+ {
+ if (ConfigurationManager.GetSection("system.web/compilation") is ConfigurationSection compilation)
+ {
+ var debugElement = compilation.ElementInformation.Properties["debug"];
+
+ _debugMode = debugElement != null && (debugElement.Value is bool debug && debug);
+
+ }
+ }
+ catch
+ {
+ _debugMode = false;
+ }
+ }
+
+ return _debugMode.GetValueOrDefault();
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Configuration/IndexCreatorSettings.cs b/src/Umbraco.Configuration/Legacy/IndexCreatorSettings.cs
similarity index 78%
rename from src/Umbraco.Configuration/IndexCreatorSettings.cs
rename to src/Umbraco.Configuration/Legacy/IndexCreatorSettings.cs
index 00d1a29dba..d023d46246 100644
--- a/src/Umbraco.Configuration/IndexCreatorSettings.cs
+++ b/src/Umbraco.Configuration/Legacy/IndexCreatorSettings.cs
@@ -1,13 +1,13 @@
using System.Configuration;
using Umbraco.Core.Configuration;
-namespace Umbraco.Configuration
+namespace Umbraco.Configuration.Legacy
{
public class IndexCreatorSettings : IIndexCreatorSettings
{
public IndexCreatorSettings()
{
- LuceneDirectoryFactory = ConfigurationManager.AppSettings["Umbraco.Examine.LuceneDirectoryFactory"];
+ LuceneDirectoryFactory = ConfigurationManager.AppSettings["Umbraco.Examine.LuceneDirectoryFactory"];
}
public string LuceneDirectoryFactory { get; }
diff --git a/src/Umbraco.Configuration/InnerTextConfigurationElement.cs b/src/Umbraco.Configuration/Legacy/InnerTextConfigurationElement.cs
similarity index 100%
rename from src/Umbraco.Configuration/InnerTextConfigurationElement.cs
rename to src/Umbraco.Configuration/Legacy/InnerTextConfigurationElement.cs
diff --git a/src/Umbraco.Configuration/Legacy/KeepAliveSettings.cs b/src/Umbraco.Configuration/Legacy/KeepAliveSettings.cs
new file mode 100644
index 0000000000..0b8315d447
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/KeepAliveSettings.cs
@@ -0,0 +1,10 @@
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Implementations
+{
+ internal class KeepAliveSettings : ConfigurationManagerConfigBase, IKeepAliveSettings
+ {
+ public bool DisableKeepAliveTask => UmbracoSettingsSection.KeepAlive.DisableKeepAliveTask;
+ public string KeepAlivePingUrl => UmbracoSettingsSection.KeepAlive.KeepAlivePingUrl;
+ }
+}
diff --git a/src/Umbraco.Configuration/Legacy/LoggingSettings.cs b/src/Umbraco.Configuration/Legacy/LoggingSettings.cs
new file mode 100644
index 0000000000..020b0c0e64
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/LoggingSettings.cs
@@ -0,0 +1,9 @@
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Implementations
+{
+ internal class LoggingSettings : ConfigurationManagerConfigBase, ILoggingSettings
+ {
+ public int MaxLogAge => UmbracoSettingsSection.Logging.MaxLogAge;
+ }
+}
diff --git a/src/Umbraco.Configuration/Legacy/MemberPasswordConfigurationSettings.cs b/src/Umbraco.Configuration/Legacy/MemberPasswordConfigurationSettings.cs
new file mode 100644
index 0000000000..e42b02de73
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/MemberPasswordConfigurationSettings.cs
@@ -0,0 +1,16 @@
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Implementations
+{
+ internal class MemberPasswordConfigurationSettings : ConfigurationManagerConfigBase, IMemberPasswordConfiguration
+ {
+ public int RequiredLength => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequiredLength;
+ public bool RequireNonLetterOrDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireNonLetterOrDigit;
+ public bool RequireDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireDigit;
+ public bool RequireLowercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireLowercase;
+ public bool RequireUppercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireUppercase;
+ public bool UseLegacyEncoding=> UmbracoSettingsSection.Security.UserPasswordConfiguration.UseLegacyEncoding;
+ public string HashAlgorithmType=> UmbracoSettingsSection.Security.UserPasswordConfiguration.HashAlgorithmType;
+ public int MaxFailedAccessAttemptsBeforeLockout => UmbracoSettingsSection.Security.UserPasswordConfiguration.MaxFailedAccessAttemptsBeforeLockout;
+ }
+}
diff --git a/src/Umbraco.Configuration/ModelsBuilderConfig.cs b/src/Umbraco.Configuration/Legacy/ModelsBuilderConfig.cs
similarity index 80%
rename from src/Umbraco.Configuration/ModelsBuilderConfig.cs
rename to src/Umbraco.Configuration/Legacy/ModelsBuilderConfig.cs
index 151e9908a1..f6395b23b4 100644
--- a/src/Umbraco.Configuration/ModelsBuilderConfig.cs
+++ b/src/Umbraco.Configuration/Legacy/ModelsBuilderConfig.cs
@@ -6,14 +6,14 @@ using Umbraco.Core.Configuration;
using Umbraco.Core;
using Umbraco.Core.IO;
-namespace Umbraco.Configuration
+namespace Umbraco.Configuration.Legacy
{
///
/// Represents the models builder configuration.
///
public class ModelsBuilderConfig : IModelsBuilderConfig
{
- private readonly IIOHelper _ioHelper;
+
private const string Prefix = "Umbraco.ModelsBuilder.";
private object _modelsModelLock;
private bool _modelsModelConfigured;
@@ -23,15 +23,13 @@ namespace Umbraco.Configuration
private bool _flagOutOfDateModels;
- public string DefaultModelsDirectory => _ioHelper.MapPath("~/App_Data/Models");
+ public string DefaultModelsDirectory => "~/App_Data/Models";
///
/// Initializes a new instance of the class.
///
- public ModelsBuilderConfig(IIOHelper ioHelper)
+ public ModelsBuilderConfig()
{
- _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
-
// giant kill switch, default: false
// must be explicitely set to true for anything else to happen
Enable = ConfigurationManager.AppSettings[Prefix + "Enable"] == "true";
@@ -59,12 +57,8 @@ namespace Umbraco.Configuration
value = ConfigurationManager.AppSettings[Prefix + "ModelsDirectory"];
if (!string.IsNullOrWhiteSpace(value))
{
- var root = _ioHelper.MapPath("~/");
- if (root == null)
- throw new ConfigurationErrorsException("Could not determine root directory.");
-
// GetModelsDirectory will ensure that the path is safe
- ModelsDirectory = GetModelsDirectory(root, value, AcceptUnsafeModelsDirectory);
+ ModelsDirectory = value;
}
// default: 0
@@ -81,7 +75,7 @@ namespace Umbraco.Configuration
///
/// Initializes a new instance of the class.
///
- public ModelsBuilderConfig(IIOHelper ioHelper,
+ public ModelsBuilderConfig(
bool enable = false,
ModelsMode modelsMode = ModelsMode.Nothing,
string modelsNamespace = null,
@@ -91,7 +85,6 @@ namespace Umbraco.Configuration
bool acceptUnsafeModelsDirectory = false,
int debugLevel = 0)
{
- _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
Enable = enable;
_modelsMode = modelsMode;
@@ -103,36 +96,7 @@ namespace Umbraco.Configuration
DebugLevel = debugLevel;
}
- // internal for tests
- internal static string GetModelsDirectory(string root, string config, bool acceptUnsafe)
- {
- // making sure it is safe, ie under the website root,
- // unless AcceptUnsafeModelsDirectory and then everything is OK.
- if (!Path.IsPathRooted(root))
- throw new ConfigurationErrorsException($"Root is not rooted \"{root}\".");
-
- if (config.StartsWith("~/"))
- {
- var dir = Path.Combine(root, config.TrimStart("~/"));
-
- // sanitize - GetFullPath will take care of any relative
- // segments in path, eg '../../foo.tmp' - it may throw a SecurityException
- // if the combined path reaches illegal parts of the filesystem
- dir = Path.GetFullPath(dir);
- root = Path.GetFullPath(root);
-
- if (!dir.StartsWith(root) && !acceptUnsafe)
- throw new ConfigurationErrorsException($"Invalid models directory \"{config}\".");
-
- return dir;
- }
-
- if (acceptUnsafe)
- return Path.GetFullPath(config);
-
- throw new ConfigurationErrorsException($"Invalid models directory \"{config}\".");
- }
///
/// Gets a value indicating whether the whole models experience is enabled.
diff --git a/src/Umbraco.Configuration/NuCacheSettings.cs b/src/Umbraco.Configuration/Legacy/NuCacheSettings.cs
similarity index 89%
rename from src/Umbraco.Configuration/NuCacheSettings.cs
rename to src/Umbraco.Configuration/Legacy/NuCacheSettings.cs
index c3a286d33d..25f52a5c7d 100644
--- a/src/Umbraco.Configuration/NuCacheSettings.cs
+++ b/src/Umbraco.Configuration/Legacy/NuCacheSettings.cs
@@ -1,7 +1,7 @@
using System.Configuration;
using Umbraco.Core.Configuration;
-namespace Umbraco.Configuration
+namespace Umbraco.Configuration.Legacy
{
public class NuCacheSettings : INuCacheSettings
{
diff --git a/src/Umbraco.Configuration/OptionalCommaDelimitedConfigurationElement.cs b/src/Umbraco.Configuration/Legacy/OptionalCommaDelimitedConfigurationElement.cs
similarity index 100%
rename from src/Umbraco.Configuration/OptionalCommaDelimitedConfigurationElement.cs
rename to src/Umbraco.Configuration/Legacy/OptionalCommaDelimitedConfigurationElement.cs
diff --git a/src/Umbraco.Configuration/OptionalInnerTextConfigurationElement.cs b/src/Umbraco.Configuration/Legacy/OptionalInnerTextConfigurationElement.cs
similarity index 100%
rename from src/Umbraco.Configuration/OptionalInnerTextConfigurationElement.cs
rename to src/Umbraco.Configuration/Legacy/OptionalInnerTextConfigurationElement.cs
diff --git a/src/Umbraco.Configuration/RawXmlConfigurationElement.cs b/src/Umbraco.Configuration/Legacy/RawXmlConfigurationElement.cs
similarity index 100%
rename from src/Umbraco.Configuration/RawXmlConfigurationElement.cs
rename to src/Umbraco.Configuration/Legacy/RawXmlConfigurationElement.cs
diff --git a/src/Umbraco.Configuration/Legacy/RequestHandlerSettings.cs b/src/Umbraco.Configuration/Legacy/RequestHandlerSettings.cs
new file mode 100644
index 0000000000..0cd011c863
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/RequestHandlerSettings.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using Umbraco.Core;
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Implementations
+{
+ internal class RequestHandlerSettings : ConfigurationManagerConfigBase, IRequestHandlerSettings
+ {
+ public bool AddTrailingSlash => UmbracoSettingsSection.RequestHandler.AddTrailingSlash;
+ public bool ConvertUrlsToAscii => UmbracoSettingsSection.RequestHandler.UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true");
+ public bool TryConvertUrlsToAscii => UmbracoSettingsSection.RequestHandler.UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try");
+ public IEnumerable CharCollection => UmbracoSettingsSection.RequestHandler.UrlReplacing.CharCollection;
+ }
+}
diff --git a/src/Umbraco.Configuration/RuntimeSettings.cs b/src/Umbraco.Configuration/Legacy/RuntimeSettings.cs
similarity index 96%
rename from src/Umbraco.Configuration/RuntimeSettings.cs
rename to src/Umbraco.Configuration/Legacy/RuntimeSettings.cs
index 6dc8d6f832..200642a819 100644
--- a/src/Umbraco.Configuration/RuntimeSettings.cs
+++ b/src/Umbraco.Configuration/Legacy/RuntimeSettings.cs
@@ -1,7 +1,7 @@
using System.Configuration;
using Umbraco.Core.Configuration;
-namespace Umbraco.Configuration
+namespace Umbraco.Configuration.Legacy
{
public class RuntimeSettings : IRuntimeSettings
{
@@ -24,6 +24,6 @@ namespace Umbraco.Configuration
}
public int? MaxQueryStringLength { get; }
public int? MaxRequestLength { get; }
-
+
}
}
diff --git a/src/Umbraco.Configuration/Legacy/SecuritySettings.cs b/src/Umbraco.Configuration/Legacy/SecuritySettings.cs
new file mode 100644
index 0000000000..b7e39b0608
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/SecuritySettings.cs
@@ -0,0 +1,14 @@
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Implementations
+{
+ internal class SecuritySettings : ConfigurationManagerConfigBase, ISecuritySettings
+ {
+ public bool KeepUserLoggedIn => UmbracoSettingsSection.Security.KeepUserLoggedIn;
+ public bool HideDisabledUsersInBackoffice => UmbracoSettingsSection.Security.HideDisabledUsersInBackoffice;
+ public bool AllowPasswordReset => UmbracoSettingsSection.Security.AllowPasswordReset;
+ public string AuthCookieName => UmbracoSettingsSection.Security.AuthCookieName;
+ public string AuthCookieDomain => UmbracoSettingsSection.Security.AuthCookieDomain;
+ public bool UsernameIsEmail => UmbracoSettingsSection.Security.UsernameIsEmail;
+ }
+}
diff --git a/src/Umbraco.Configuration/SmtpSettings.cs b/src/Umbraco.Configuration/Legacy/SmtpSettings.cs
similarity index 100%
rename from src/Umbraco.Configuration/SmtpSettings.cs
rename to src/Umbraco.Configuration/Legacy/SmtpSettings.cs
diff --git a/src/Umbraco.Configuration/Legacy/TourSettings.cs b/src/Umbraco.Configuration/Legacy/TourSettings.cs
new file mode 100644
index 0000000000..134c3c48d5
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/TourSettings.cs
@@ -0,0 +1,9 @@
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Implementations
+{
+ internal class TourSettings : ConfigurationManagerConfigBase, ITourSettings
+ {
+ public bool EnableTours => UmbracoSettingsSection.BackOffice.Tours.EnableTours;
+ }
+}
diff --git a/src/Umbraco.Configuration/TypeFinderSettings.cs b/src/Umbraco.Configuration/Legacy/TypeFinderSettings.cs
similarity index 91%
rename from src/Umbraco.Configuration/TypeFinderSettings.cs
rename to src/Umbraco.Configuration/Legacy/TypeFinderSettings.cs
index bb3063d7bf..b1009f754b 100644
--- a/src/Umbraco.Configuration/TypeFinderSettings.cs
+++ b/src/Umbraco.Configuration/Legacy/TypeFinderSettings.cs
@@ -1,8 +1,8 @@
using System.Configuration;
-using Umbraco.Core.Configuration;
using Umbraco.Core;
+using Umbraco.Core.Configuration;
-namespace Umbraco.Configuration
+namespace Umbraco.Configuration.Legacy
{
public class TypeFinderSettings : ITypeFinderSettings
{
diff --git a/src/Umbraco.Configuration/UmbracoConfigurationSection.cs b/src/Umbraco.Configuration/Legacy/UmbracoConfigurationSection.cs
similarity index 100%
rename from src/Umbraco.Configuration/UmbracoConfigurationSection.cs
rename to src/Umbraco.Configuration/Legacy/UmbracoConfigurationSection.cs
diff --git a/src/Umbraco.Configuration/Legacy/UserPasswordConfigurationSettings.cs b/src/Umbraco.Configuration/Legacy/UserPasswordConfigurationSettings.cs
new file mode 100644
index 0000000000..51dd645c42
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/UserPasswordConfigurationSettings.cs
@@ -0,0 +1,15 @@
+using Umbraco.Core.Configuration;
+namespace Umbraco.Configuration.Implementations
+{
+ internal class UserPasswordConfigurationSettings : ConfigurationManagerConfigBase, IUserPasswordConfiguration
+ {
+ public int RequiredLength => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequiredLength;
+ public bool RequireNonLetterOrDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireNonLetterOrDigit;
+ public bool RequireDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireDigit;
+ public bool RequireLowercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireLowercase;
+ public bool RequireUppercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireUppercase;
+ public bool UseLegacyEncoding=> UmbracoSettingsSection.Security.UserPasswordConfiguration.UseLegacyEncoding;
+ public string HashAlgorithmType=> UmbracoSettingsSection.Security.UserPasswordConfiguration.HashAlgorithmType;
+ public int MaxFailedAccessAttemptsBeforeLockout => UmbracoSettingsSection.Security.UserPasswordConfiguration.MaxFailedAccessAttemptsBeforeLockout;
+ }
+}
diff --git a/src/Umbraco.Configuration/Legacy/WebRoutingSettings.cs b/src/Umbraco.Configuration/Legacy/WebRoutingSettings.cs
new file mode 100644
index 0000000000..5da3de20a0
--- /dev/null
+++ b/src/Umbraco.Configuration/Legacy/WebRoutingSettings.cs
@@ -0,0 +1,16 @@
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Implementations
+{
+ internal class WebRoutingSettings : ConfigurationManagerConfigBase, IWebRoutingSettings
+ {
+ public bool TrySkipIisCustomErrors => UmbracoSettingsSection.WebRouting.TrySkipIisCustomErrors;
+ public bool InternalRedirectPreservesTemplate => UmbracoSettingsSection.WebRouting.InternalRedirectPreservesTemplate;
+ public bool DisableAlternativeTemplates => UmbracoSettingsSection.WebRouting.DisableAlternativeTemplates;
+ public bool ValidateAlternativeTemplates => UmbracoSettingsSection.WebRouting.ValidateAlternativeTemplates;
+ public bool DisableFindContentByIdPath => UmbracoSettingsSection.WebRouting.DisableFindContentByIdPath;
+ public bool DisableRedirectUrlTracking => UmbracoSettingsSection.WebRouting.DisableRedirectUrlTracking;
+ public string UrlProviderMode => UmbracoSettingsSection.WebRouting.UrlProviderMode;
+ public string UmbracoApplicationUrl => UmbracoSettingsSection.WebRouting.UmbracoApplicationUrl;
+ }
+}
diff --git a/src/Umbraco.Configuration/MachineKeyConfig.cs b/src/Umbraco.Configuration/MachineKeyConfig.cs
deleted file mode 100644
index 4e3401e015..0000000000
--- a/src/Umbraco.Configuration/MachineKeyConfig.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System.Configuration;
-using Umbraco.Core.Configuration;
-
-namespace Umbraco.Configuration
-{
- public class MachineKeyConfig : IMachineKeyConfig
- {
- //TODO all the machineKey stuff should be replaced: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/compatibility/replacing-machinekey?view=aspnetcore-3.1
-
- public bool HasMachineKey
- {
- get
- {
- var machineKeySection =
- ConfigurationManager.GetSection("system.web/machineKey") as ConfigurationSection;
- return !(machineKeySection?.ElementInformation?.Source is null);
- }
- }
- }
-}
diff --git a/src/Umbraco.Configuration/Models/ActiveDirectorySettings.cs b/src/Umbraco.Configuration/Models/ActiveDirectorySettings.cs
new file mode 100644
index 0000000000..015fb17a8e
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/ActiveDirectorySettings.cs
@@ -0,0 +1,19 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class ActiveDirectorySettings : IActiveDirectorySettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "ActiveDirectory:";
+ private readonly IConfiguration _configuration;
+
+ public ActiveDirectorySettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public string ActiveDirectoryDomain => _configuration.GetValue(Prefix+"Domain");
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/ConnectionStrings.cs b/src/Umbraco.Configuration/Models/ConnectionStrings.cs
new file mode 100644
index 0000000000..22a0bde571
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/ConnectionStrings.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Data.Common;
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ public class ConnectionStrings : IConnectionStrings
+ {
+ private readonly IConfiguration _configuration;
+
+ public ConnectionStrings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public ConfigConnectionString this[string key]
+ {
+ get
+ {
+ var connectionString = _configuration.GetConnectionString(key);
+ var provider = ParseProvider(connectionString);
+ return new ConfigConnectionString(connectionString, provider, key);
+ }
+ set => throw new NotImplementedException();
+ }
+
+ private string ParseProvider(string connectionString)
+ {
+ if (string.IsNullOrEmpty(connectionString))
+ {
+ return null;
+ }
+
+ var builder = new DbConnectionStringBuilder();
+
+ builder.ConnectionString = connectionString;
+
+ if (builder.TryGetValue("Data Source", out var ds) && ds is string dataSource)
+ {
+ if (dataSource.EndsWith(".sdf"))
+ {
+ return Constants.DbProviderNames.SqlCe;
+ }
+ }
+
+ if (builder.TryGetValue("Server", out var s) && s is string server && builder.TryGetValue("Database", out var db) && db is string database)
+ {
+ if (!string.IsNullOrEmpty(server) && !string.IsNullOrEmpty(database))
+ {
+ return Constants.DbProviderNames.SqlServer;
+ }
+ }
+
+ throw new ArgumentException("Cannot determine provider name from connection string", nameof(connectionString));
+ }
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/ContentSettings.cs b/src/Umbraco.Configuration/Models/ContentSettings.cs
new file mode 100644
index 0000000000..5bc31814b7
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/ContentSettings.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration.UmbracoSettings;
+using Umbraco.Core.Macros;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class ContentSettings : IContentSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "Content:";
+ private const string NotificationsPrefix = Prefix + "Notifications:";
+ private const string ImagingPrefix = Prefix + "Imaging:";
+ private const string DefaultPreviewBadge =
+ @"";
+
+ private static readonly ImagingAutoFillUploadField[] DefaultImagingAutoFillUploadField =
+ {
+ new ImagingAutoFillUploadField
+ {
+ Alias = "umbracoFile"
+ }
+ };
+
+ private readonly IConfiguration _configuration;
+
+ public ContentSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public string NotificationEmailAddress =>
+ _configuration.GetValue(NotificationsPrefix+"Email");
+
+ public bool DisableHtmlEmail =>
+ _configuration.GetValue(NotificationsPrefix+"DisableHtmlEmail", false);
+
+ public IEnumerable ImageFileTypes => _configuration.GetValue(
+ ImagingPrefix+"ImageFileTypes", new[] { "jpeg", "jpg", "gif", "bmp", "png", "tiff", "tif" });
+
+ public IEnumerable ImageAutoFillProperties =>
+ _configuration.GetValue(ImagingPrefix+"AutoFillImageProperties",
+ DefaultImagingAutoFillUploadField);
+
+
+ public bool ResolveUrlsFromTextString =>
+ _configuration.GetValue(Prefix+"ResolveUrlsFromTextString", false);
+
+ public IEnumerable Error404Collection => _configuration
+ .GetSection(Prefix+"Errors:Error404")
+ .GetChildren()
+ .Select(x => new ContentErrorPage(x));
+
+ public string PreviewBadge => _configuration.GetValue(Prefix+"PreviewBadge", DefaultPreviewBadge);
+
+ public MacroErrorBehaviour MacroErrorBehaviour =>
+ _configuration.GetValue(Prefix+"MacroErrors", MacroErrorBehaviour.Inline);
+
+ public IEnumerable DisallowedUploadFiles => _configuration.GetValue(
+ Prefix+"DisallowedUploadFiles",
+ new[] { "ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd" });
+
+ public IEnumerable AllowedUploadFiles =>
+ _configuration.GetValue(Prefix+"AllowedUploadFiles", Array.Empty());
+
+ public bool ShowDeprecatedPropertyEditors =>
+ _configuration.GetValue(Prefix+"ShowDeprecatedPropertyEditors", false);
+
+ public string LoginBackgroundImage =>
+ _configuration.GetValue(Prefix+"LoginBackgroundImage", string.Empty);
+
+ private class ContentErrorPage : IContentErrorPage
+ {
+ public ContentErrorPage(IConfigurationSection configurationSection)
+ {
+ Culture = configurationSection.Key;
+
+ var value = configurationSection.Value;
+
+ if (int.TryParse(value, out var contentId))
+ {
+ HasContentId = true;
+ ContentId = contentId;
+ }
+ else if (Guid.TryParse(value, out var contentKey))
+ {
+ HasContentKey = true;
+ ContentKey = contentKey;
+ }
+ else
+ {
+ ContentXPath = value;
+ }
+ }
+
+ public int ContentId { get; }
+ public Guid ContentKey { get; }
+ public string ContentXPath { get; }
+ public bool HasContentId { get; }
+ public bool HasContentKey { get; }
+ public string Culture { get; set; }
+ }
+
+ private class ImagingAutoFillUploadField : IImagingAutoFillUploadField
+ {
+ public string Alias { get; set; }
+ public string WidthFieldAlias { get; set; }
+ public string HeightFieldAlias { get; set; }
+ public string LengthFieldAlias { get; set; }
+ public string ExtensionFieldAlias { get; set; }
+ }
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/CoreDebugSettings.cs b/src/Umbraco.Configuration/Models/CoreDebugSettings.cs
new file mode 100644
index 0000000000..6d6c0eaf0d
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/CoreDebugSettings.cs
@@ -0,0 +1,23 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class CoreDebugSettings : ICoreDebugSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "Core:Debug:";
+ private readonly IConfiguration _configuration;
+
+ public CoreDebugSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public bool LogUncompletedScopes =>
+ _configuration.GetValue(Prefix+"LogUncompletedScopes", false);
+
+ public bool DumpOnTimeoutThreadAbort =>
+ _configuration.GetValue(Prefix+"DumpOnTimeoutThreadAbort", false);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/ExceptionFilterSettings.cs b/src/Umbraco.Configuration/Models/ExceptionFilterSettings.cs
new file mode 100644
index 0000000000..581daf9f40
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/ExceptionFilterSettings.cs
@@ -0,0 +1,19 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class ExceptionFilterSettings : IExceptionFilterSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "ExceptionFilter:";
+ private readonly IConfiguration _configuration;
+
+ public ExceptionFilterSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public bool Disabled => _configuration.GetValue(Prefix+"Disabled", false);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/GlobalSettings.cs b/src/Umbraco.Configuration/Models/GlobalSettings.cs
new file mode 100644
index 0000000000..4dc764a974
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/GlobalSettings.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Linq;
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ ///
+ /// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information
+ /// from web.config appsettings
+ ///
+ internal class GlobalSettings : IGlobalSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "Global:";
+
+ 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!
+
+ private readonly IConfiguration _configuration;
+
+ public GlobalSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public string ReservedUrls => _configuration.GetValue(Prefix + "ReservedUrls", StaticReservedUrls);
+ public string ReservedPaths => _configuration.GetValue(Prefix + "ReservedPaths", StaticReservedPaths);
+
+ public string Path => _configuration.GetValue(Prefix + "Path");
+
+ // TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings
+ public string ConfigurationStatus
+ {
+ get => _configuration.GetValue(Prefix + "ConfigurationStatus");
+ set => throw new NotImplementedException("We should remove this and only use the value from database");
+ }
+
+ public int TimeOutInMinutes => _configuration.GetValue(Prefix + "TimeOutInMinutes", 20);
+ public string DefaultUILanguage => _configuration.GetValue(Prefix + "TimeOutInMinutes", "en-US");
+
+ public bool HideTopLevelNodeFromPath =>
+ _configuration.GetValue(Prefix + "HideTopLevelNodeFromPath", false);
+
+ public bool UseHttps => _configuration.GetValue(Prefix + "UseHttps", false);
+ public int VersionCheckPeriod => _configuration.GetValue(Prefix + "VersionCheckPeriod", 7);
+ public string UmbracoPath => _configuration.GetValue(Prefix + "UmbracoPath", "~/umbraco");
+ public string UmbracoCssPath => _configuration.GetValue(Prefix + "UmbracoCssPath", "~/css");
+
+ public string UmbracoScriptsPath =>
+ _configuration.GetValue(Prefix + "UmbracoScriptsPath", "~/scripts");
+
+ public string UmbracoMediaPath => _configuration.GetValue(Prefix + "UmbracoMediaPath", "~/media");
+
+ public bool InstallMissingDatabase =>
+ _configuration.GetValue(Prefix + "InstallMissingDatabase", false);
+
+ public bool InstallEmptyDatabase => _configuration.GetValue(Prefix + "InstallEmptyDatabase", false);
+
+ public bool DisableElectionForSingleServer =>
+ _configuration.GetValue(Prefix + "DisableElectionForSingleServer", false);
+
+ public string RegisterType => _configuration.GetValue(Prefix + "RegisterType", string.Empty);
+
+ public string DatabaseFactoryServerVersion =>
+ _configuration.GetValue(Prefix + "DatabaseFactoryServerVersion", string.Empty);
+
+ public string MainDomLock => _configuration.GetValue(Prefix + "MainDomLock", string.Empty);
+
+ public string NoNodesViewPath =>
+ _configuration.GetValue(Prefix + "NoNodesViewPath", "~/config/splashes/NoNodes.cshtml");
+
+ public bool IsSmtpServerConfigured =>
+ _configuration.GetSection(Constants.Configuration.ConfigPrefix + "Smtp")?.GetChildren().Any() ?? false;
+
+ public ISmtpSettings SmtpSettings =>
+ new SmtpSettingsImpl(_configuration.GetSection(Constants.Configuration.ConfigPrefix + "Smtp"));
+
+ private class SmtpSettingsImpl : ISmtpSettings
+ {
+ private readonly IConfigurationSection _configurationSection;
+
+ public SmtpSettingsImpl(IConfigurationSection configurationSection)
+ {
+ _configurationSection = configurationSection;
+ }
+
+ public string From => _configurationSection.GetValue("From");
+ public string Host => _configurationSection.GetValue("Host");
+ public int Port => _configurationSection.GetValue("Port");
+ public string PickupDirectoryLocation => _configurationSection.GetValue("PickupDirectoryLocation");
+ }
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/HealthChecksSettingsSettings.cs b/src/Umbraco.Configuration/Models/HealthChecksSettingsSettings.cs
new file mode 100644
index 0000000000..1d73051ec8
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/HealthChecksSettingsSettings.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration.HealthChecks;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class HealthChecksSettings : IHealthChecksSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "HealthChecks:";
+ private readonly IConfiguration _configuration;
+
+ public HealthChecksSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public IEnumerable DisabledChecks => _configuration
+ .GetSection(Prefix+"DisabledChecks")
+ .GetChildren()
+ .Select(
+ x => new DisabledHealthCheck
+ {
+ Id = x.GetValue("Id"),
+ DisabledOn = x.GetValue("DisabledOn"),
+ DisabledBy = x.GetValue("DisabledBy")
+ });
+
+ public IHealthCheckNotificationSettings NotificationSettings =>
+ new HealthCheckNotificationSettings(
+ _configuration.GetSection(Prefix+"NotificationSettings"));
+
+ private class DisabledHealthCheck : IDisabledHealthCheck
+ {
+ public Guid Id { get; set; }
+ public DateTime DisabledOn { get; set; }
+ public int DisabledBy { get; set; }
+ }
+
+ private class HealthCheckNotificationSettings : IHealthCheckNotificationSettings
+ {
+ private readonly IConfigurationSection _configurationSection;
+
+ public HealthCheckNotificationSettings(IConfigurationSection configurationSection)
+ {
+ _configurationSection = configurationSection;
+ }
+
+ public bool Enabled => _configurationSection.GetValue("Enabled", false);
+ public string FirstRunTime => _configurationSection.GetValue("FirstRunTime");
+ public int PeriodInHours => _configurationSection.GetValue("PeriodInHours", 24);
+
+ public IReadOnlyDictionary NotificationMethods => _configurationSection
+ .GetSection("NotificationMethods")
+ .GetChildren()
+ .ToDictionary(x => x.Key, x => (INotificationMethod) new NotificationMethod(x.Key, x));
+
+ public IEnumerable DisabledChecks => _configurationSection
+ .GetSection("DisabledChecks").GetChildren().Select(
+ x => new DisabledHealthCheck
+ {
+ Id = x.GetValue("Id"),
+ DisabledOn = x.GetValue("DisabledOn"),
+ DisabledBy = x.GetValue("DisabledBy")
+ });
+ }
+
+ private class NotificationMethod : INotificationMethod
+ {
+ private readonly IConfigurationSection _configurationSection;
+
+ public NotificationMethod(string alias, IConfigurationSection configurationSection)
+ {
+ Alias = alias;
+ _configurationSection = configurationSection;
+ }
+
+ public string Alias { get; }
+ public bool Enabled => _configurationSection.GetValue("Enabled", false);
+
+ public HealthCheckNotificationVerbosity Verbosity =>
+ _configurationSection.GetValue("Verbosity", HealthCheckNotificationVerbosity.Summary);
+
+ public bool FailureOnly => _configurationSection.GetValue("FailureOnly", true);
+
+ public IReadOnlyDictionary Settings => _configurationSection
+ .GetSection("Settings").GetChildren().ToDictionary(x => x.Key,
+ x => (INotificationMethodSettings) new NotificationMethodSettings(x.Key, x.Value));
+ }
+
+ private class NotificationMethodSettings : INotificationMethodSettings
+ {
+ public NotificationMethodSettings(string key, string value)
+ {
+ Key = key;
+ Value = value;
+ }
+
+ public string Key { get; }
+ public string Value { get; }
+ }
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/HostingSettings.cs b/src/Umbraco.Configuration/Models/HostingSettings.cs
new file mode 100644
index 0000000000..4a156cee6a
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/HostingSettings.cs
@@ -0,0 +1,27 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class HostingSettings : IHostingSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "Hosting:";
+ private readonly IConfiguration _configuration;
+
+ public HostingSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ ///
+ public LocalTempStorage LocalTempStorageLocation =>
+ _configuration.GetValue(Prefix+"LocalTempStorage", LocalTempStorage.Default);
+
+ ///
+ /// Gets a value indicating whether umbraco is running in [debug mode].
+ ///
+ /// true if [debug mode]; otherwise, false.
+ public bool DebugMode => _configuration.GetValue(Prefix+":Debug", false);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/ImagingSettings.cs b/src/Umbraco.Configuration/Models/ImagingSettings.cs
new file mode 100644
index 0000000000..4a9501b2ba
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/ImagingSettings.cs
@@ -0,0 +1,26 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class ImagingSettings : IImagingSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "Imaging:";
+ private const string CachePrefix = Prefix + "Cache:";
+ private const string ResizePrefix = Prefix + "Resize:";
+ private readonly IConfiguration _configuration;
+
+ public ImagingSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public int MaxBrowserCacheDays => _configuration.GetValue(CachePrefix + "MaxBrowserCacheDays", 7);
+ public int MaxCacheDays => _configuration.GetValue(CachePrefix + "MaxCacheDays", 365);
+ public uint CachedNameLength => _configuration.GetValue(CachePrefix + "CachedNameLength", (uint) 8);
+ public string CacheFolder => _configuration.GetValue(CachePrefix + "Folder", "../App_Data/Cache");
+ public int MaxResizeWidth => _configuration.GetValue(ResizePrefix + "MaxWidth", 5000);
+ public int MaxResizeHeight => _configuration.GetValue(ResizePrefix + "MaxHeight", 5000);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs b/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs
new file mode 100644
index 0000000000..b4bb000552
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class IndexCreatorSettings : IIndexCreatorSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "Examine:";
+ private readonly IConfiguration _configuration;
+
+ public IndexCreatorSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public string LuceneDirectoryFactory =>
+ _configuration.GetValue(Prefix + "LuceneDirectoryFactory");
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/KeepAliveSettings.cs b/src/Umbraco.Configuration/Models/KeepAliveSettings.cs
new file mode 100644
index 0000000000..04194e1a3c
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/KeepAliveSettings.cs
@@ -0,0 +1,23 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class KeepAliveSettings : IKeepAliveSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "KeepAlive:";
+ private readonly IConfiguration _configuration;
+
+ public KeepAliveSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public bool DisableKeepAliveTask =>
+ _configuration.GetValue(Prefix + "DisableKeepAliveTask", false);
+
+ public string KeepAlivePingUrl => _configuration.GetValue(Prefix + "KeepAlivePingUrl",
+ "{umbracoApplicationUrl}/api/keepalive/ping");
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/LoggingSettings.cs b/src/Umbraco.Configuration/Models/LoggingSettings.cs
new file mode 100644
index 0000000000..b05fe03875
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/LoggingSettings.cs
@@ -0,0 +1,19 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class LoggingSettings : ILoggingSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "Logging:";
+ private readonly IConfiguration _configuration;
+
+ public LoggingSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public int MaxLogAge => _configuration.GetValue(Prefix + "MaxLogAge", -1);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs b/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs
new file mode 100644
index 0000000000..c7b147349e
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs
@@ -0,0 +1,38 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class MemberPasswordConfigurationSettings : IMemberPasswordConfiguration
+ {
+ private const string Prefix = Constants.Configuration.ConfigSecurityPrefix + "MemberPassword:";
+ private readonly IConfiguration _configuration;
+
+ public MemberPasswordConfigurationSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public int RequiredLength =>
+ _configuration.GetValue(Prefix + "RequiredLength", 10);
+
+ public bool RequireNonLetterOrDigit =>
+ _configuration.GetValue(Prefix + "RequireNonLetterOrDigit", false);
+
+ public bool RequireDigit =>
+ _configuration.GetValue(Prefix + "RequireDigit", false);
+
+ public bool RequireLowercase =>
+ _configuration.GetValue(Prefix + "RequireLowercase", false);
+
+ public bool RequireUppercase =>
+ _configuration.GetValue(Prefix + "RequireUppercase", false);
+
+ public string HashAlgorithmType =>
+ _configuration.GetValue(Prefix + "HashAlgorithmType", "HMACSHA256");
+
+ public int MaxFailedAccessAttemptsBeforeLockout =>
+ _configuration.GetValue(Prefix + "MaxFailedAccessAttemptsBeforeLockout", 5);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs b/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs
new file mode 100644
index 0000000000..d111dbba70
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs
@@ -0,0 +1,86 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ ///
+ /// Represents the models builder configuration.
+ ///
+ internal class ModelsBuilderConfig : IModelsBuilderConfig
+ {
+ private const string Prefix = Constants.Configuration.ConfigModelsBuilderPrefix;
+ private readonly IConfiguration _configuration;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ModelsBuilderConfig(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public string DefaultModelsDirectory => "~/App_Data/Models";
+
+ ///
+ /// Gets a value indicating whether the whole models experience is enabled.
+ ///
+ ///
+ /// If this is false then absolutely nothing happens.
+ /// Default value is false which means that unless we have this setting, nothing happens.
+ ///
+ public bool Enable => _configuration.GetValue(Prefix+"Enable", false);
+
+ ///
+ /// Gets the models mode.
+ ///
+ public ModelsMode ModelsMode =>
+ _configuration.GetValue(Prefix+"ModelsMode", ModelsMode.Nothing);
+
+ ///
+ /// Gets the models namespace.
+ ///
+ /// That value could be overriden by other (attribute in user's code...). Return default if no value was supplied.
+ public string ModelsNamespace => _configuration.GetValue(Prefix+"ModelsNamespace");
+
+ ///
+ /// Gets a value indicating whether we should enable the models factory.
+ ///
+ /// Default value is true because no factory is enabled by default in Umbraco.
+ public bool EnableFactory => _configuration.GetValue(Prefix+"EnableFactory", true);
+
+ ///
+ /// Gets a value indicating whether we should flag out-of-date models.
+ ///
+ ///
+ /// Models become out-of-date when data types or content types are updated. When this
+ /// setting is activated the ~/App_Data/Models/ood.txt file is then created. When models are
+ /// generated through the dashboard, the files is cleared. Default value is false.
+ ///
+ public bool FlagOutOfDateModels =>
+ _configuration.GetValue(Prefix+"FlagOutOfDateModels", false) && !ModelsMode.IsLive();
+
+ ///
+ /// Gets the models directory.
+ ///
+ /// Default is ~/App_Data/Models but that can be changed.
+ public string ModelsDirectory =>
+ _configuration.GetValue(Prefix+"ModelsDirectory", "~/App_Data/Models");
+
+ ///
+ /// Gets a value indicating whether to accept an unsafe value for ModelsDirectory.
+ ///
+ ///
+ /// An unsafe value is an absolute path, or a relative path pointing outside
+ /// of the website root.
+ ///
+ public bool AcceptUnsafeModelsDirectory =>
+ _configuration.GetValue(Prefix+"AcceptUnsafeModelsDirectory", false);
+
+ ///
+ /// Gets a value indicating the debug log level.
+ ///
+ /// 0 means minimal (safe on live site), anything else means more and more details (maybe not safe).
+ public int DebugLevel => _configuration.GetValue(Prefix+"DebugLevel", 0);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/NuCacheSettings.cs b/src/Umbraco.Configuration/Models/NuCacheSettings.cs
new file mode 100644
index 0000000000..51b8b1fe08
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/NuCacheSettings.cs
@@ -0,0 +1,19 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class NuCacheSettings : INuCacheSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "NuCache:";
+ private readonly IConfiguration _configuration;
+
+ public NuCacheSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public string BTreeBlockSize => _configuration.GetValue(Prefix+"BTreeBlockSize");
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/RequestHandlerSettings.cs b/src/Umbraco.Configuration/Models/RequestHandlerSettings.cs
new file mode 100644
index 0000000000..ce5cd65c20
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/RequestHandlerSettings.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class RequestHandlerSettings : IRequestHandlerSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "RequestHandler:";
+ private static readonly CharItem[] DefaultCharCollection =
+ {
+ new CharItem { Char = " ", Replacement = "-" },
+ new CharItem { Char = "\"", Replacement = "" },
+ new CharItem { Char = "'", Replacement = "" },
+ new CharItem { Char = "%", Replacement = "" },
+ new CharItem { Char = ".", Replacement = "" },
+ new CharItem { Char = ";", Replacement = "" },
+ new CharItem { Char = "/", Replacement = "" },
+ new CharItem { Char = "\\", Replacement = "" },
+ new CharItem { Char = ":", Replacement = "" },
+ new CharItem { Char = "#", Replacement = "" },
+ new CharItem { Char = "+", Replacement = "plus" },
+ new CharItem { Char = "*", Replacement = "star" },
+ new CharItem { Char = "&", Replacement = "" },
+ new CharItem { Char = "?", Replacement = "" },
+ new CharItem { Char = "æ", Replacement = "ae" },
+ new CharItem { Char = "ä", Replacement = "ae" },
+ new CharItem { Char = "ø", Replacement = "oe" },
+ new CharItem { Char = "ö", Replacement = "oe" },
+ new CharItem { Char = "å", Replacement = "aa" },
+ new CharItem { Char = "ü", Replacement = "ue" },
+ new CharItem { Char = "ß", Replacement = "ss" },
+ new CharItem { Char = "|", Replacement = "-" },
+ new CharItem { Char = "<", Replacement = "" },
+ new CharItem { Char = ">", Replacement = "" }
+ };
+
+ private readonly IConfiguration _configuration;
+
+ public RequestHandlerSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public bool AddTrailingSlash =>
+ _configuration.GetValue(Prefix+"AddTrailingSlash", true);
+
+ public bool ConvertUrlsToAscii => _configuration
+ .GetValue(Prefix+"ConvertUrlsToAscii").InvariantEquals("true");
+
+ public bool TryConvertUrlsToAscii => _configuration
+ .GetValue(Prefix+"ConvertUrlsToAscii").InvariantEquals("try");
+
+
+ //We need to special handle ":", as this character is special in keys
+ public IEnumerable CharCollection
+ {
+ get
+ {
+ var collection = _configuration.GetSection(Prefix + "CharCollection").GetChildren()
+ .Select(x => new CharItem()
+ {
+ Char = x.GetValue("Char"),
+ Replacement = x.GetValue("Replacement"),
+ }).ToArray();
+
+ if (collection.Any() || _configuration.GetSection("Prefix").GetChildren().Any(x =>
+ x.Key.Equals("CharCollection", StringComparison.OrdinalIgnoreCase)))
+ {
+ return collection;
+ }
+
+ return DefaultCharCollection;
+ }
+ }
+
+
+ public class CharItem : IChar
+ {
+ public string Char { get; set; }
+ public string Replacement { get; set; }
+ }
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/RuntimeSettings.cs b/src/Umbraco.Configuration/Models/RuntimeSettings.cs
new file mode 100644
index 0000000000..ef129030b6
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/RuntimeSettings.cs
@@ -0,0 +1,19 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class RuntimeSettings : IRuntimeSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "Runtime:";
+ private readonly IConfiguration _configuration;
+ public RuntimeSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public int? MaxQueryStringLength => _configuration.GetValue(Prefix+"MaxRequestLength");
+ public int? MaxRequestLength => _configuration.GetValue(Prefix+"MaxRequestLength");
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/SecuritySettings.cs b/src/Umbraco.Configuration/Models/SecuritySettings.cs
new file mode 100644
index 0000000000..9244eace96
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/SecuritySettings.cs
@@ -0,0 +1,33 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class SecuritySettings : ISecuritySettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigSecurityPrefix;
+ private readonly IConfiguration _configuration;
+
+ public SecuritySettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public bool KeepUserLoggedIn => _configuration.GetValue(Prefix + "KeepUserLoggedIn", true);
+
+ public bool HideDisabledUsersInBackoffice =>
+ _configuration.GetValue(Prefix + "HideDisabledUsersInBackoffice", false);
+
+ public bool AllowPasswordReset =>
+ _configuration.GetValue(Prefix + "AllowPasswordResetAllowPasswordReset", true);
+
+ public string AuthCookieName =>
+ _configuration.GetValue(Prefix + "AuthCookieName", "UMB_UCONTEXT");
+
+ public string AuthCookieDomain =>
+ _configuration.GetValue(Prefix + "AuthCookieDomain");
+
+ public bool UsernameIsEmail => _configuration.GetValue(Prefix + "UsernameIsEmail", true);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/TourSettings.cs b/src/Umbraco.Configuration/Models/TourSettings.cs
new file mode 100644
index 0000000000..9fe1814ff5
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/TourSettings.cs
@@ -0,0 +1,21 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class TourSettings : ITourSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "Tours:";
+ private readonly IConfiguration _configuration;
+
+ public TourSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public string Type { get; set; }
+
+ public bool EnableTours => _configuration.GetValue(Prefix+"EnableTours", true);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/TypeFinderSettings.cs b/src/Umbraco.Configuration/Models/TypeFinderSettings.cs
new file mode 100644
index 0000000000..8a1f7ac9e0
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/TypeFinderSettings.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class TypeFinderSettings : ITypeFinderSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "TypeFinder:";
+ private readonly IConfiguration _configuration;
+
+ public TypeFinderSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public string AssembliesAcceptingLoadExceptions =>
+ _configuration.GetValue(Prefix+"AssembliesAcceptingLoadExceptions");
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs b/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs
new file mode 100644
index 0000000000..5e68b16203
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs
@@ -0,0 +1,36 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class UserPasswordConfigurationSettings : IUserPasswordConfiguration
+ {
+ private const string Prefix = Constants.Configuration.ConfigSecurityPrefix + "UserPassword:";
+ private readonly IConfiguration _configuration;
+
+ public UserPasswordConfigurationSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public int RequiredLength => _configuration.GetValue(Prefix + "RequiredLength", 10);
+
+ public bool RequireNonLetterOrDigit =>
+ _configuration.GetValue(Prefix + "RequireNonLetterOrDigit", false);
+
+ public bool RequireDigit => _configuration.GetValue(Prefix + "RequireDigit", false);
+
+ public bool RequireLowercase =>
+ _configuration.GetValue(Prefix + "RequireLowercase", false);
+
+ public bool RequireUppercase =>
+ _configuration.GetValue(Prefix + "RequireUppercase", false);
+
+ public string HashAlgorithmType =>
+ _configuration.GetValue(Prefix + "HashAlgorithmType", "HMACSHA256");
+
+ public int MaxFailedAccessAttemptsBeforeLockout =>
+ _configuration.GetValue(Prefix + "MaxFailedAccessAttemptsBeforeLockout", 5);
+ }
+}
diff --git a/src/Umbraco.Configuration/Models/WebRoutingSettings.cs b/src/Umbraco.Configuration/Models/WebRoutingSettings.cs
new file mode 100644
index 0000000000..9ac856ca9f
--- /dev/null
+++ b/src/Umbraco.Configuration/Models/WebRoutingSettings.cs
@@ -0,0 +1,42 @@
+using Microsoft.Extensions.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Configuration.UmbracoSettings;
+using Umbraco.Core.Models.PublishedContent;
+
+namespace Umbraco.Configuration.Models
+{
+ internal class WebRoutingSettings : IWebRoutingSettings
+ {
+ private const string Prefix = Constants.Configuration.ConfigPrefix + "WebRouting:";
+ private readonly IConfiguration _configuration;
+
+ public WebRoutingSettings(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public bool TrySkipIisCustomErrors =>
+ _configuration.GetValue(Prefix + "TrySkipIisCustomErrors", false);
+
+ public bool InternalRedirectPreservesTemplate =>
+ _configuration.GetValue(Prefix + "InternalRedirectPreservesTemplate", false);
+
+ public bool DisableAlternativeTemplates =>
+ _configuration.GetValue(Prefix + "DisableAlternativeTemplates", false);
+
+ public bool ValidateAlternativeTemplates =>
+ _configuration.GetValue(Prefix + "ValidateAlternativeTemplates", false);
+
+ public bool DisableFindContentByIdPath =>
+ _configuration.GetValue(Prefix + "DisableFindContentByIdPath", false);
+
+ public bool DisableRedirectUrlTracking =>
+ _configuration.GetValue(Prefix + "DisableRedirectUrlTracking", false);
+
+ public string UrlProviderMode =>
+ _configuration.GetValue(Prefix + "UrlProviderMode", UrlMode.Auto.ToString());
+
+ public string UmbracoApplicationUrl =>
+ _configuration.GetValue(Prefix + "UmbracoApplicationUrl");
+ }
+}
diff --git a/src/Umbraco.Configuration/Properties/AssemblyInfo.cs b/src/Umbraco.Configuration/Properties/AssemblyInfo.cs
index d10dd929da..b77c087e22 100644
--- a/src/Umbraco.Configuration/Properties/AssemblyInfo.cs
+++ b/src/Umbraco.Configuration/Properties/AssemblyInfo.cs
@@ -4,6 +4,7 @@ using System.Runtime.InteropServices;
// Umbraco Cms
[assembly: InternalsVisibleTo("Umbraco.Tests")]
+[assembly: InternalsVisibleTo("Umbraco.Tests.Common")]
[assembly: InternalsVisibleTo("Umbraco.Tests.Benchmarks")]
// Allow this to be mocked in our unit tests
diff --git a/src/Umbraco.Configuration/Umbraco.Configuration.csproj b/src/Umbraco.Configuration/Umbraco.Configuration.csproj
index 57fca1dfd6..88bb3639d0 100644
--- a/src/Umbraco.Configuration/Umbraco.Configuration.csproj
+++ b/src/Umbraco.Configuration/Umbraco.Configuration.csproj
@@ -22,6 +22,9 @@
+
+
+
diff --git a/src/Umbraco.Configuration/UmbracoSettings/BackOfficeElement.cs b/src/Umbraco.Configuration/UmbracoSettings/BackOfficeElement.cs
index 79bff51d05..46b9bf32a9 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/BackOfficeElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/BackOfficeElement.cs
@@ -7,6 +7,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("tours")]
internal TourConfigElement Tours => (TourConfigElement)this["tours"];
- ITourSection IBackOfficeSection.Tours => Tours;
+ ITourSettings IBackOfficeSection.Tours => Tours;
}
}
diff --git a/src/Umbraco.Configuration/UmbracoSettings/ContentElement.cs b/src/Umbraco.Configuration/UmbracoSettings/ContentElement.cs
index 8e4f0edd8f..28b4314c9a 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/ContentElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/ContentElement.cs
@@ -4,7 +4,7 @@ using Umbraco.Core.Macros;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class ContentElement : UmbracoConfigurationElement, IContentSection
+ internal class ContentElement : UmbracoConfigurationElement, IContentSettings
{
private const string DefaultPreviewBadge = @"";
@@ -40,26 +40,26 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("loginBackgroundImage")]
internal InnerTextConfigurationElement LoginBackgroundImage => GetOptionalTextElement("loginBackgroundImage", string.Empty);
- string IContentSection.NotificationEmailAddress => Notifications.NotificationEmailAddress;
+ string IContentSettings.NotificationEmailAddress => Notifications.NotificationEmailAddress;
- bool IContentSection.DisableHtmlEmail => Notifications.DisableHtmlEmail;
+ bool IContentSettings.DisableHtmlEmail => Notifications.DisableHtmlEmail;
- IEnumerable IContentSection.ImageFileTypes => Imaging.ImageFileTypes;
+ IEnumerable IContentSettings.ImageFileTypes => Imaging.ImageFileTypes;
- IEnumerable IContentSection.ImageAutoFillProperties => Imaging.ImageAutoFillProperties;
+ IEnumerable IContentSettings.ImageAutoFillProperties => Imaging.ImageAutoFillProperties;
- bool IContentSection.ResolveUrlsFromTextString => ResolveUrlsFromTextString;
+ bool IContentSettings.ResolveUrlsFromTextString => ResolveUrlsFromTextString;
- string IContentSection.PreviewBadge => PreviewBadge;
+ string IContentSettings.PreviewBadge => PreviewBadge;
- MacroErrorBehaviour IContentSection.MacroErrorBehaviour => MacroErrors;
+ MacroErrorBehaviour IContentSettings.MacroErrorBehaviour => MacroErrors;
- IEnumerable IContentSection.DisallowedUploadFiles => DisallowedUploadFiles;
+ IEnumerable IContentSettings.DisallowedUploadFiles => DisallowedUploadFiles;
- IEnumerable IContentSection.AllowedUploadFiles => AllowedUploadFiles;
+ IEnumerable IContentSettings.AllowedUploadFiles => AllowedUploadFiles;
- bool IContentSection.ShowDeprecatedPropertyEditors => ShowDeprecatedPropertyEditors;
+ bool IContentSettings.ShowDeprecatedPropertyEditors => ShowDeprecatedPropertyEditors;
- string IContentSection.LoginBackgroundImage => LoginBackgroundImage;
+ string IContentSettings.LoginBackgroundImage => LoginBackgroundImage;
}
}
diff --git a/src/Umbraco.Configuration/UmbracoSettings/KeepAliveElement.cs b/src/Umbraco.Configuration/UmbracoSettings/KeepAliveElement.cs
index 89ba9be54d..2297fb4e20 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/KeepAliveElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/KeepAliveElement.cs
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class KeepAliveElement : ConfigurationElement, IKeepAliveSection
+ internal class KeepAliveElement : ConfigurationElement, IKeepAliveSettings
{
[ConfigurationProperty("disableKeepAliveTask", DefaultValue = "false")]
public bool DisableKeepAliveTask => (bool)base["disableKeepAliveTask"];
diff --git a/src/Umbraco.Configuration/UmbracoSettings/LoggingElement.cs b/src/Umbraco.Configuration/UmbracoSettings/LoggingElement.cs
index 106b6cc134..2fdd61e169 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/LoggingElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/LoggingElement.cs
@@ -3,12 +3,12 @@ using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class LoggingElement : UmbracoConfigurationElement, ILoggingSection
+ internal class LoggingElement : UmbracoConfigurationElement, ILoggingSettings
{
[ConfigurationProperty("maxLogAge")]
internal InnerTextConfigurationElement MaxLogAge => GetOptionalTextElement("maxLogAge", -1);
- int ILoggingSection.MaxLogAge => MaxLogAge;
+ int ILoggingSettings.MaxLogAge => MaxLogAge;
}
}
diff --git a/src/Umbraco.Configuration/UmbracoSettings/MemberPasswordConfigurationElement.cs b/src/Umbraco.Configuration/UmbracoSettings/MemberPasswordConfigurationElement.cs
index 93c7c20159..92cd112630 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/MemberPasswordConfigurationElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/MemberPasswordConfigurationElement.cs
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class MemberPasswordConfigurationElement : PasswordConfigurationElement, IMemberPasswordConfigurationSection
+ internal class MemberPasswordConfigurationElement : PasswordConfigurationElement, IMemberPasswordConfiguration
{
}
}
diff --git a/src/Umbraco.Configuration/UmbracoSettings/RequestHandlerElement.cs b/src/Umbraco.Configuration/UmbracoSettings/RequestHandlerElement.cs
index 80fcb6ca1a..f959a56e71 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/RequestHandlerElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/RequestHandlerElement.cs
@@ -5,7 +5,7 @@ using System.Collections.Generic;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class RequestHandlerElement : UmbracoConfigurationElement, IRequestHandlerSection
+ internal class RequestHandlerElement : UmbracoConfigurationElement, IRequestHandlerSettings
{
[ConfigurationProperty("addTrailingSlash")]
public InnerTextConfigurationElement AddTrailingSlash => GetOptionalTextElement("addTrailingSlash", true);
@@ -85,12 +85,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
return collection;
}
- bool IRequestHandlerSection.AddTrailingSlash => AddTrailingSlash;
+ bool IRequestHandlerSettings.AddTrailingSlash => AddTrailingSlash;
- bool IRequestHandlerSection.ConvertUrlsToAscii => UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true");
+ bool IRequestHandlerSettings.ConvertUrlsToAscii => UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true");
- bool IRequestHandlerSection.TryConvertUrlsToAscii => UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try");
+ bool IRequestHandlerSettings.TryConvertUrlsToAscii => UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try");
- IEnumerable IRequestHandlerSection.CharCollection => UrlReplacing.CharCollection;
+ IEnumerable IRequestHandlerSettings.CharCollection => UrlReplacing.CharCollection;
}
}
diff --git a/src/Umbraco.Configuration/UmbracoSettings/SecurityElement.cs b/src/Umbraco.Configuration/UmbracoSettings/SecurityElement.cs
index 82012cfd0f..aec6809298 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/SecurityElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/SecurityElement.cs
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class SecurityElement : UmbracoConfigurationElement, ISecuritySection
+ internal class SecurityElement : UmbracoConfigurationElement, ISecuritySettings
{
[ConfigurationProperty("keepUserLoggedIn")]
internal InnerTextConfigurationElement KeepUserLoggedIn => GetOptionalTextElement("keepUserLoggedIn", true);
@@ -38,14 +38,14 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("memberPasswordConfiguration")]
public MemberPasswordConfigurationElement MemberPasswordConfiguration => (MemberPasswordConfigurationElement)this["memberPasswordConfiguration"];
- bool ISecuritySection.KeepUserLoggedIn => KeepUserLoggedIn;
+ bool ISecuritySettings.KeepUserLoggedIn => KeepUserLoggedIn;
- bool ISecuritySection.HideDisabledUsersInBackoffice => HideDisabledUsersInBackoffice;
+ bool ISecuritySettings.HideDisabledUsersInBackoffice => HideDisabledUsersInBackoffice;
///
/// Used to enable/disable the forgot password functionality on the back office login screen
///
- bool ISecuritySection.AllowPasswordReset => AllowPasswordReset;
+ bool ISecuritySettings.AllowPasswordReset => AllowPasswordReset;
///
/// A boolean indicating that by default the email address will be the username
@@ -54,14 +54,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
/// Even if this is true and the username is different from the email in the database, the username field will still be shown.
/// When this is false, the username and email fields will be shown in the user section.
///
- bool ISecuritySection.UsernameIsEmail => UsernameIsEmail;
+ bool ISecuritySettings.UsernameIsEmail => UsernameIsEmail;
- string ISecuritySection.AuthCookieName => AuthCookieName;
+ string ISecuritySettings.AuthCookieName => AuthCookieName;
- string ISecuritySection.AuthCookieDomain => AuthCookieDomain;
-
- IUserPasswordConfigurationSection ISecuritySection.UserPasswordConfiguration => UserPasswordConfiguration;
-
- IMemberPasswordConfigurationSection ISecuritySection.MemberPasswordConfiguration => MemberPasswordConfiguration;
+ string ISecuritySettings.AuthCookieDomain => AuthCookieDomain;
}
}
diff --git a/src/Umbraco.Configuration/UmbracoSettings/TourConfigElement.cs b/src/Umbraco.Configuration/UmbracoSettings/TourConfigElement.cs
index dab69f3da0..f75b71fc57 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/TourConfigElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/TourConfigElement.cs
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class TourConfigElement : UmbracoConfigurationElement, ITourSection
+ internal class TourConfigElement : UmbracoConfigurationElement, ITourSettings
{
//disabled by default so that upgraders don't get it enabled by default
// TODO: we probably just want to disable the initial one from automatically loading ?
diff --git a/src/Umbraco.Configuration/UmbracoSettings/UmbracoSettingsSection.cs b/src/Umbraco.Configuration/UmbracoSettings/UmbracoSettingsSection.cs
index e605b86edf..781d00b979 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/UmbracoSettingsSection.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/UmbracoSettingsSection.cs
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class UmbracoSettingsSection : ConfigurationSection, IUmbracoSettingsSection
+ internal class UmbracoSettingsSection : ConfigurationSection
{
[ConfigurationProperty("backOffice")]
public BackOfficeElement BackOffice => (BackOfficeElement)this["backOffice"];
@@ -24,19 +24,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("keepAlive")]
internal KeepAliveElement KeepAlive => (KeepAliveElement)this["keepAlive"];
-
- IContentSection IUmbracoSettingsSection.Content => Content;
-
- ISecuritySection IUmbracoSettingsSection.Security => Security;
-
- IRequestHandlerSection IUmbracoSettingsSection.RequestHandler => RequestHandler;
-
- IBackOfficeSection IUmbracoSettingsSection.BackOffice => BackOffice;
-
- ILoggingSection IUmbracoSettingsSection.Logging => Logging;
-
- IWebRoutingSection IUmbracoSettingsSection.WebRouting => WebRouting;
-
- IKeepAliveSection IUmbracoSettingsSection.KeepAlive => KeepAlive;
}
}
diff --git a/src/Umbraco.Configuration/UmbracoSettings/UserPasswordConfigurationElement.cs b/src/Umbraco.Configuration/UmbracoSettings/UserPasswordConfigurationElement.cs
index 8128f3d8e7..a1d2aa8842 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/UserPasswordConfigurationElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/UserPasswordConfigurationElement.cs
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class UserPasswordConfigurationElement : PasswordConfigurationElement, IUserPasswordConfigurationSection
+ internal class UserPasswordConfigurationElement : PasswordConfigurationElement, IUserPasswordConfiguration
{
}
}
diff --git a/src/Umbraco.Configuration/UmbracoSettings/WebRoutingElement.cs b/src/Umbraco.Configuration/UmbracoSettings/WebRoutingElement.cs
index 7b7102f2e7..206fc213d2 100644
--- a/src/Umbraco.Configuration/UmbracoSettings/WebRoutingElement.cs
+++ b/src/Umbraco.Configuration/UmbracoSettings/WebRoutingElement.cs
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- internal class WebRoutingElement : ConfigurationElement, IWebRoutingSection
+ internal class WebRoutingElement : ConfigurationElement, IWebRoutingSettings
{
[ConfigurationProperty("trySkipIisCustomErrors", DefaultValue = "false")]
public bool TrySkipIisCustomErrors => (bool) base["trySkipIisCustomErrors"];
diff --git a/src/Umbraco.Configuration/UmbracoVersionExtensions.cs b/src/Umbraco.Configuration/UmbracoVersionExtensions.cs
deleted file mode 100644
index 168bb16f57..0000000000
--- a/src/Umbraco.Configuration/UmbracoVersionExtensions.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Configuration;
-using Semver;
-using Umbraco.Core;
-using Umbraco.Core.Configuration;
-
-namespace Umbraco.Configuration
-{
- public static class UmbracoVersionExtensions
- {
- ///
- /// Gets the "local" version of the site.
- ///
- ///
- /// 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.
- ///
- 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;
- }
- }
- }
-}
diff --git a/src/Umbraco.Core/Cache/DeepCloneAppCache.cs b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs
index 452f897372..e70b40160e 100644
--- a/src/Umbraco.Core/Cache/DeepCloneAppCache.cs
+++ b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs
@@ -73,7 +73,7 @@ namespace Umbraco.Core.Cache
var result = SafeLazy.GetSafeLazy(factory);
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
// do not store null values (backward compat), clone / reset to go into the cache
- return value == null ? null : CheckCloneableAndTracksChanges(value);
+ return value == null ? null : CheckCloneableAndTracksChanges(value);
// clone / reset to go into the cache
}, timeout, isSliding, dependentFiles);
@@ -107,9 +107,9 @@ namespace Umbraco.Core.Cache
}
///
- public void ClearOfType(string typeName)
+ public void ClearOfType(Type type)
{
- InnerCache.ClearOfType(typeName);
+ InnerCache.ClearOfType(type);
}
///
diff --git a/src/Umbraco.Core/Cache/DictionaryAppCache.cs b/src/Umbraco.Core/Cache/DictionaryAppCache.cs
index d372916240..04ee3e0afa 100644
--- a/src/Umbraco.Core/Cache/DictionaryAppCache.cs
+++ b/src/Umbraco.Core/Cache/DictionaryAppCache.cs
@@ -71,16 +71,16 @@ namespace Umbraco.Core.Cache
}
///
- public virtual void ClearOfType(string typeName)
+ public virtual void ClearOfType(Type type)
{
- _items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType().ToString().InvariantEquals(typeName));
+ _items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == type);
}
///
public virtual void ClearOfType()
{
var typeOfT = typeof(T);
- _items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT);
+ ClearOfType(typeOfT);
}
///
diff --git a/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs b/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs
index 159f9cd7cb..54009af465 100644
--- a/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs
+++ b/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs
@@ -12,12 +12,6 @@ namespace Umbraco.Core.Cache
///
public class FastDictionaryAppCache : IAppCache
{
- private readonly ITypeFinder _typeFinder;
-
- public FastDictionaryAppCache(ITypeFinder typeFinder)
- {
- _typeFinder = typeFinder ?? throw new ArgumentNullException(nameof(typeFinder));
- }
///
/// Gets the internal items dictionary, for tests only!
@@ -83,9 +77,8 @@ namespace Umbraco.Core.Cache
}
///
- public void ClearOfType(string typeName)
+ public void ClearOfType(Type type)
{
- var type = _typeFinder.GetTypeByName(typeName);
if (type == null) return;
var isInterface = type.IsInterface;
diff --git a/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs b/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs
index f417c5ffd0..bb55762826 100644
--- a/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs
+++ b/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs
@@ -12,13 +12,6 @@ namespace Umbraco.Core.Cache
///
public abstract class FastDictionaryAppCacheBase : IAppCache
{
- private readonly ITypeFinder _typeFinder;
-
- protected FastDictionaryAppCacheBase(ITypeFinder typeFinder)
- {
- _typeFinder = typeFinder ?? throw new ArgumentNullException(nameof(typeFinder));
- }
-
// prefix cache keys so we know which one are ours
protected const string CacheItemPrefix = "umbrtmche";
@@ -121,9 +114,8 @@ namespace Umbraco.Core.Cache
}
///
- public virtual void ClearOfType(string typeName)
+ public virtual void ClearOfType(Type type)
{
- var type = _typeFinder.GetTypeByName(typeName);
if (type == null) return;
var isInterface = type.IsInterface;
try
diff --git a/src/Umbraco.Core/Cache/HttpRequestAppCache.cs b/src/Umbraco.Core/Cache/HttpRequestAppCache.cs
index e698d93ebe..6ce43a7bc9 100644
--- a/src/Umbraco.Core/Cache/HttpRequestAppCache.cs
+++ b/src/Umbraco.Core/Cache/HttpRequestAppCache.cs
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Cache
///
/// Initializes a new instance of the class with a context, for unit tests!
///
- public HttpRequestAppCache(Func requestItems, ITypeFinder typeFinder) : base(typeFinder)
+ public HttpRequestAppCache(Func requestItems) : base()
{
ContextItems = requestItems;
}
diff --git a/src/Umbraco.Core/Cache/IAppCache.cs b/src/Umbraco.Core/Cache/IAppCache.cs
index 674781f6d6..c84ec1135c 100644
--- a/src/Umbraco.Core/Cache/IAppCache.cs
+++ b/src/Umbraco.Core/Cache/IAppCache.cs
@@ -51,14 +51,14 @@ namespace Umbraco.Core.Cache
///
/// Removes items of a specified type from the cache.
///
- /// The name of the type to remove.
+ /// The type to remove.
///
/// If the type is an interface, then all items of a type implementing that interface are
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
/// the specified type are not removed).
/// Performs a case-sensitive search.
///
- void ClearOfType(string typeName);
+ void ClearOfType(Type type);
///
/// Removes items of a specified type from the cache.
diff --git a/src/Umbraco.Core/Cache/NoAppCache.cs b/src/Umbraco.Core/Cache/NoAppCache.cs
index 60bc6fb8b8..cae3a7381e 100644
--- a/src/Umbraco.Core/Cache/NoAppCache.cs
+++ b/src/Umbraco.Core/Cache/NoAppCache.cs
@@ -67,7 +67,7 @@ namespace Umbraco.Core.Cache
{ }
///
- public virtual void ClearOfType(string typeName)
+ public virtual void ClearOfType(Type type)
{ }
///
diff --git a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs
index 208390276a..dc9163affb 100644
--- a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs
+++ b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs
@@ -13,15 +13,13 @@ namespace Umbraco.Core.Cache
///
public class ObjectCacheAppCache : IAppPolicyCache
{
- private readonly ITypeFinder _typeFinder;
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
///
/// Initializes a new instance of the .
///
- public ObjectCacheAppCache(ITypeFinder typeFinder)
+ public ObjectCacheAppCache()
{
- _typeFinder = typeFinder ?? throw new ArgumentNullException(nameof(typeFinder));
// the MemoryCache is created with name "in-memory". That name is
// used to retrieve configuration options. It does not identify the memory cache, i.e.
// each instance of this class has its own, independent, memory cache.
@@ -178,9 +176,8 @@ namespace Umbraco.Core.Cache
}
///
- public virtual void ClearOfType(string typeName)
+ public virtual void ClearOfType(Type type)
{
- var type = _typeFinder.GetTypeByName(typeName);
if (type == null) return;
var isInterface = type.IsInterface;
try
diff --git a/src/Umbraco.Core/Composing/Composition.cs b/src/Umbraco.Core/Composing/Composition.cs
index a186a1f00a..05c7554eab 100644
--- a/src/Umbraco.Core/Composing/Composition.cs
+++ b/src/Umbraco.Core/Composing/Composition.cs
@@ -33,13 +33,13 @@ namespace Umbraco.Core.Composing
/// An IOHelper
public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs, IIOHelper ioHelper, AppCaches appCaches)
{
- _register = register;
- TypeLoader = typeLoader;
- Logger = logger;
- RuntimeState = runtimeState;
- Configs = configs;
- IOHelper = ioHelper;
- AppCaches = appCaches;
+ _register = register ?? throw new ArgumentNullException(nameof(register));
+ TypeLoader = typeLoader ?? throw new ArgumentNullException(nameof(typeLoader));
+ Logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ RuntimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState));
+ Configs = configs ?? throw new ArgumentNullException(nameof(configs));
+ IOHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
+ AppCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches));
}
#region Services
@@ -135,7 +135,7 @@ namespace Umbraco.Core.Composing
IFactory factory = null;
- Configs.RegisterWith(_register, () => factory);
+ Configs.RegisterWith(_register);
// ReSharper disable once AccessToModifiedClosure -- on purpose
_register.Register(_ => factory, Lifetime.Singleton);
diff --git a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs
new file mode 100644
index 0000000000..f7c81d6d7e
--- /dev/null
+++ b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Returns a list of scannable assemblies based on an entry point assembly and it's references
+ ///
+ ///
+ /// This will recursively search through the entry point's assemblies and Umbraco's core assemblies and their references
+ /// to create a list of scannable assemblies based on whether they themselves or their transitive dependencies reference Umbraco core assemblies.
+ ///
+ public class DefaultUmbracoAssemblyProvider : IAssemblyProvider
+ {
+ private readonly Assembly _entryPointAssembly;
+ private static readonly string[] UmbracoCoreAssemblyNames = new[]
+ {
+ "Umbraco.Core",
+ "Umbraco.Web",
+ "Umbraco.Web.BackOffice",
+ "Umbraco.Infrastructure",
+ "Umbraco.PublishedCache.NuCache",
+ "Umbraco.ModelsBuilder.Embedded",
+ "Umbraco.Examine.Lucene",
+ };
+
+ public DefaultUmbracoAssemblyProvider(Assembly entryPointAssembly)
+ {
+ _entryPointAssembly = entryPointAssembly ?? throw new ArgumentNullException(nameof(entryPointAssembly));
+ }
+
+ // TODO: It would be worth investigating a netcore3 version of this which would use
+ // var allAssemblies = System.Runtime.Loader.AssemblyLoadContext.All.SelectMany(x => x.Assemblies);
+ // that will still only resolve Assemblies that are already loaded but it would also make it possible to
+ // query dynamically generated assemblies once they are added. It would also provide the ability to probe
+ // assembly locations that are not in the same place as the entry point assemblies.
+
+ public IEnumerable Assemblies
+ {
+ get
+ {
+ var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, UmbracoCoreAssemblyNames, true);
+ return finder.Find();
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs b/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs
new file mode 100644
index 0000000000..9378941166
--- /dev/null
+++ b/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Finds Assemblies from the entry point assemblies, it's dependencies and it's transitive dependencies that reference that targetAssemblyNames
+ ///
+ ///
+ /// borrowed and modified from here https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/FindAssembliesWithReferencesTo.cs
+ ///
+ internal class FindAssembliesWithReferencesTo
+ {
+ private readonly Assembly[] _referenceAssemblies;
+ private readonly string[] _targetAssemblies;
+ private readonly bool _includeTargets;
+
+ ///
+ /// Constructor
+ ///
+ /// Entry point assemblies
+ /// Used to check if the entry point or it's transitive assemblies reference these assembly names
+ /// If true will also use the target assembly names as entry point assemblies
+ public FindAssembliesWithReferencesTo(Assembly[] referenceAssemblies, string[] targetAssemblyNames, bool includeTargets)
+ {
+ _referenceAssemblies = referenceAssemblies;
+ _targetAssemblies = targetAssemblyNames;
+ _includeTargets = includeTargets;
+ }
+
+ public IEnumerable Find()
+ {
+ var referenceItems = new List();
+ foreach (var assembly in _referenceAssemblies)
+ {
+ referenceItems.Add(assembly);
+ }
+
+ if (_includeTargets)
+ {
+ foreach(var target in _targetAssemblies)
+ {
+ try
+ {
+ referenceItems.Add(Assembly.Load(target));
+ }
+ catch (FileNotFoundException)
+ {
+ // occurs if we cannot load this ... for example in a test project where we aren't currently referencing Umbraco.Web, etc...
+ }
+ }
+ }
+
+ var provider = new ReferenceResolver(_targetAssemblies, referenceItems);
+ var assemblyNames = provider.ResolveAssemblies();
+ return assemblyNames.ToList();
+ }
+
+ }
+}
diff --git a/src/Umbraco.Core/Composing/IAssemblyProvider.cs b/src/Umbraco.Core/Composing/IAssemblyProvider.cs
new file mode 100644
index 0000000000..bde97a9556
--- /dev/null
+++ b/src/Umbraco.Core/Composing/IAssemblyProvider.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Provides a list of assemblies that can be scanned
+ ///
+ public interface IAssemblyProvider
+ {
+ IEnumerable Assemblies { get; }
+ }
+}
diff --git a/src/Umbraco.Core/Composing/ReferenceResolver.cs b/src/Umbraco.Core/Composing/ReferenceResolver.cs
new file mode 100644
index 0000000000..65dba8bf23
--- /dev/null
+++ b/src/Umbraco.Core/Composing/ReferenceResolver.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Resolves assemblies that reference one of the specified "targetAssemblies" either directly or transitively.
+ ///
+ ///
+ /// Borrowed and modified from https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/ReferenceResolver.cs
+ ///
+ internal class ReferenceResolver
+ {
+ private readonly HashSet _umbracoAssemblies;
+ private readonly IReadOnlyList _assemblies;
+ private readonly Dictionary _classifications;
+ private readonly List _lookup = new List();
+
+ public ReferenceResolver(IReadOnlyList targetAssemblies, IReadOnlyList entryPointAssemblies)
+ {
+ _umbracoAssemblies = new HashSet(targetAssemblies, StringComparer.Ordinal);
+ _assemblies = entryPointAssemblies;
+ _classifications = new Dictionary();
+
+ foreach (var item in entryPointAssemblies)
+ {
+ _lookup.Add(item);
+ }
+ }
+
+ ///
+ /// Returns a list of assemblies that directly reference or transitively reference the targetAssemblies
+ ///
+ ///
+ ///
+ /// This includes all assemblies in the same location as the entry point assemblies
+ ///
+ public IEnumerable ResolveAssemblies()
+ {
+ var applicationParts = new List();
+
+ var assemblies = new HashSet(_assemblies);
+
+ // Get the unique directories of the assemblies
+ var assemblyLocations = GetAssemblyFolders(assemblies).ToList();
+
+ // Load in each assembly in the directory of the entry assembly to be included in the search
+ // for Umbraco dependencies/transitive dependencies
+ foreach(var dir in assemblyLocations)
+ {
+ foreach(var dll in Directory.EnumerateFiles(dir, "*.dll"))
+ {
+ var assemblyName = AssemblyName.GetAssemblyName(dll);
+
+ // don't include if this is excluded
+ if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => assemblyName.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)))
+ continue;
+
+ // don't include this item if it's Umbraco
+ // TODO: We should maybe pass an explicit list of these names in?
+ if (assemblyName.FullName.StartsWith("Umbraco."))
+ continue;
+
+ var assembly = Assembly.Load(assemblyName);
+ assemblies.Add(assembly);
+ }
+ }
+
+ foreach (var item in assemblies)
+ {
+ var classification = Resolve(item);
+ if (classification == Classification.ReferencesUmbraco || classification == Classification.IsUmbraco)
+ {
+ applicationParts.Add(item);
+ }
+ }
+
+ return applicationParts;
+ }
+
+
+ private IEnumerable GetAssemblyFolders(IEnumerable assemblies)
+ {
+ return assemblies.Select(x => Path.GetDirectoryName(GetAssemblyLocation(x)).ToLowerInvariant()).Distinct();
+ }
+
+ // borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/ApplicationParts/RelatedAssemblyAttribute.cs
+ private string GetAssemblyLocation(Assembly assembly)
+ {
+ if (Uri.TryCreate(assembly.CodeBase, UriKind.Absolute, out var result) &&
+ result.IsFile && string.IsNullOrWhiteSpace(result.Fragment))
+ {
+ return result.LocalPath;
+ }
+
+ return assembly.Location;
+ }
+
+ private Classification Resolve(Assembly assembly)
+ {
+ if (_classifications.TryGetValue(assembly, out var classification))
+ {
+ return classification;
+ }
+
+ // Initialize the dictionary with a value to short-circuit recursive references.
+ classification = Classification.Unknown;
+ _classifications[assembly] = classification;
+
+ if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => assembly.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)))
+ {
+ // if its part of the filter it doesn't reference umbraco
+ classification = Classification.DoesNotReferenceUmbraco;
+ }
+ else if (_umbracoAssemblies.Contains(assembly.GetName().Name))
+ {
+ classification = Classification.IsUmbraco;
+ }
+ else
+ {
+ classification = Classification.DoesNotReferenceUmbraco;
+ foreach (var reference in GetReferences(assembly))
+ {
+ // recurse
+ var referenceClassification = Resolve(reference);
+
+ if (referenceClassification == Classification.IsUmbraco || referenceClassification == Classification.ReferencesUmbraco)
+ {
+ classification = Classification.ReferencesUmbraco;
+ break;
+ }
+ }
+ }
+
+ Debug.Assert(classification != Classification.Unknown);
+ _classifications[assembly] = classification;
+ return classification;
+ }
+
+ protected virtual IEnumerable GetReferences(Assembly assembly)
+ {
+ foreach (var referenceName in assembly.GetReferencedAssemblies())
+ {
+ // don't include if this is excluded
+ if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => referenceName.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)))
+ continue;
+
+ var reference = Assembly.Load(referenceName);
+
+ if (!_lookup.Contains(reference))
+ {
+ // A dependency references an item that isn't referenced by this project.
+ // We'll add this reference so that we can calculate the classification.
+
+ _lookup.Add(reference);
+ }
+ yield return reference;
+ }
+ }
+
+ protected enum Classification
+ {
+ Unknown,
+ DoesNotReferenceUmbraco,
+ ReferencesUmbraco,
+ IsUmbraco,
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Composing/TypeFinder.cs b/src/Umbraco.Core/Composing/TypeFinder.cs
index 9d88153b0a..79fddad1ca 100644
--- a/src/Umbraco.Core/Composing/TypeFinder.cs
+++ b/src/Umbraco.Core/Composing/TypeFinder.cs
@@ -1,106 +1,35 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
-using System.Configuration;
-using System.IO;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Text;
using Umbraco.Core.Configuration.UmbracoSettings;
-using Umbraco.Core.Exceptions;
-using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Composing
{
+
///
public class TypeFinder : ITypeFinder
{
private readonly ILogger _logger;
-
- public TypeFinder(ILogger logger, ITypeFinderConfig typeFinderConfig = null)
- {
- _logger = logger ?? throw new ArgumentNullException(nameof(logger));
- _assembliesAcceptingLoadExceptions = typeFinderConfig?.AssembliesAcceptingLoadExceptions.Where(x => !x.IsNullOrWhiteSpace()).ToArray() ?? Array.Empty();
- _allAssemblies = new Lazy>(() =>
- {
- HashSet assemblies = null;
- try
- {
- //NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have
- // already been loaded in to the app domain, instead we will look directly into the bin folder and load each one.
- var binFolder = GetRootDirectorySafe();
- var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
- //var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
- //var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
- assemblies = new HashSet();
- foreach (var a in binAssemblyFiles)
- {
- try
- {
- var assName = AssemblyName.GetAssemblyName(a);
- var ass = Assembly.Load(assName);
- assemblies.Add(ass);
- }
- catch (Exception e)
- {
- if (e is SecurityException || e is BadImageFormatException)
- {
- //swallow these exceptions
- }
- else
- {
- throw;
- }
- }
- }
-
- //Since we are only loading in the /bin assemblies above, we will also load in anything that's already loaded (which will include gac items)
- foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
- {
- assemblies.Add(a);
- }
- }
- catch (InvalidOperationException e)
- {
- if (e.InnerException is SecurityException == false)
- throw;
- }
-
- return assemblies;
- });
- }
-
- //Lazy access to the all assemblies list
- private readonly Lazy> _allAssemblies;
+ private readonly IAssemblyProvider _assemblyProvider;
private volatile HashSet _localFilteredAssemblyCache;
private readonly object _localFilteredAssemblyCacheLocker = new object();
private readonly List _notifiedLoadExceptionAssemblies = new List();
- private static readonly ConcurrentDictionary TypeNamesCache= new ConcurrentDictionary();
- private string _rootDir = "";
+ private static readonly ConcurrentDictionary TypeNamesCache = new ConcurrentDictionary();
private readonly string[] _assembliesAcceptingLoadExceptions;
- // FIXME - this is only an interim change, once the IIOHelper stuff is merged we should use IIOHelper here
- private string GetRootDirectorySafe()
+ // used for benchmark tests
+ internal bool QueryWithReferencingAssemblies = true;
+
+ public TypeFinder(ILogger logger, IAssemblyProvider assemblyProvider, ITypeFinderConfig typeFinderConfig = null)
{
- if (string.IsNullOrEmpty(_rootDir) == false)
- {
- return _rootDir;
- }
-
- var codeBase = Assembly.GetExecutingAssembly().CodeBase;
- var uri = new Uri(codeBase);
- var path = uri.LocalPath;
- var baseDirectory = Path.GetDirectoryName(path);
- if (string.IsNullOrEmpty(baseDirectory))
- throw new PanicException("No root directory could be resolved.");
-
- _rootDir = baseDirectory.Contains("bin")
- ? baseDirectory.Substring(0, baseDirectory.LastIndexOf("bin", StringComparison.OrdinalIgnoreCase) - 1)
- : baseDirectory;
-
- return _rootDir;
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _assemblyProvider = assemblyProvider;
+ _assembliesAcceptingLoadExceptions = typeFinderConfig?.AssembliesAcceptingLoadExceptions.Where(x => !x.IsNullOrWhiteSpace()).ToArray() ?? Array.Empty();
}
private bool AcceptsLoadExceptions(Assembly a)
@@ -119,22 +48,8 @@ namespace Umbraco.Core.Composing
});
}
- ///
- /// lazily load a reference to all assemblies and only local assemblies.
- /// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
- ///
- ///
- /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
- /// loaded in the CLR, not all assemblies.
- /// See these threads:
- /// http://issues.umbraco.org/issue/U5-198
- /// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app
- /// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl
- ///
- private IEnumerable GetAllAssemblies()
- {
- return _allAssemblies.Value;
- }
+
+ private IEnumerable GetAllAssemblies() => _assemblyProvider.Assemblies;
///
public IEnumerable AssembliesToScan
@@ -181,7 +96,10 @@ namespace Umbraco.Core.Composing
/// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match
/// NOTE this means that "foo." will NOT exclude "foo.dll" but only "foo.*.dll"
///
- private static readonly string[] KnownAssemblyExclusionFilter = {
+ internal static readonly string[] KnownAssemblyExclusionFilter = {
+ "mscorlib,",
+ "netstandard,",
+ "System,",
"Antlr3.",
"AutoMapper,",
"AutoMapper.",
@@ -228,7 +146,14 @@ namespace Umbraco.Core.Composing
"WebDriver,",
"itextsharp,",
"mscorlib,",
- "nunit.framework,",
+ "NUnit,",
+ "NUnit.",
+ "NUnit3.",
+ "Selenium.",
+ "ImageProcessor",
+ "MiniProfiler.",
+ "Owin,",
+ "SQLite",
};
///
@@ -290,6 +215,11 @@ namespace Umbraco.Core.Composing
///
public virtual Type GetTypeByName(string name)
{
+
+ //NOTE: This will not find types in dynamic assemblies unless those assemblies are already loaded
+ //into the appdomain.
+
+
// This is exactly what the BuildManager does, if the type is an assembly qualified type
// name it will find it.
if (TypeNameContainsAssembly(name))
@@ -340,18 +270,24 @@ namespace Umbraco.Core.Composing
var stack = new Stack();
stack.Push(attributeType.Assembly);
+ if (!QueryWithReferencingAssemblies)
+ {
+ foreach (var a in candidateAssemblies)
+ stack.Push(a);
+ }
+
while (stack.Count > 0)
{
var assembly = stack.Pop();
- Type[] assemblyTypes = null;
+ IReadOnlyList assemblyTypes = null;
if (assembly != attributeType.Assembly || attributeAssemblyIsCandidate)
{
// get all assembly types that can be assigned to baseType
try
{
assemblyTypes = GetTypesWithFormattedException(assembly)
- .ToArray(); // in try block
+ .ToList(); // in try block
}
catch (TypeLoadException ex)
{
@@ -371,10 +307,13 @@ namespace Umbraco.Core.Composing
if (assembly != attributeType.Assembly && assemblyTypes.Where(attributeType.IsAssignableFrom).Any() == false)
continue;
- foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
+ if (QueryWithReferencingAssemblies)
{
- candidateAssemblies.Remove(referencing);
- stack.Push(referencing);
+ foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
+ {
+ candidateAssemblies.Remove(referencing);
+ stack.Push(referencing);
+ }
}
}
@@ -405,19 +344,25 @@ namespace Umbraco.Core.Composing
var stack = new Stack();
stack.Push(baseType.Assembly);
+ if (!QueryWithReferencingAssemblies)
+ {
+ foreach (var a in candidateAssemblies)
+ stack.Push(a);
+ }
+
while (stack.Count > 0)
{
var assembly = stack.Pop();
// get all assembly types that can be assigned to baseType
- Type[] assemblyTypes = null;
+ IReadOnlyList assemblyTypes = null;
if (assembly != baseType.Assembly || baseTypeAssemblyIsCandidate)
{
try
{
assemblyTypes = GetTypesWithFormattedException(assembly)
.Where(baseType.IsAssignableFrom)
- .ToArray(); // in try block
+ .ToList(); // in try block
}
catch (TypeLoadException ex)
{
@@ -437,10 +382,13 @@ namespace Umbraco.Core.Composing
if (assembly != baseType.Assembly && assemblyTypes.All(x => x.IsSealed))
continue;
- foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
+ if (QueryWithReferencingAssemblies)
{
- candidateAssemblies.Remove(referencing);
- stack.Push(referencing);
+ foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
+ {
+ candidateAssemblies.Remove(referencing);
+ stack.Push(referencing);
+ }
}
}
@@ -522,6 +470,5 @@ namespace Umbraco.Core.Composing
#endregion
-
}
}
diff --git a/src/Umbraco.Core/Composing/TypeFinderConfig.cs b/src/Umbraco.Core/Composing/TypeFinderConfig.cs
new file mode 100644
index 0000000000..3dc672b27c
--- /dev/null
+++ b/src/Umbraco.Core/Composing/TypeFinderConfig.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.UmbracoSettings;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// TypeFinder config via appSettings
+ ///
+ internal class TypeFinderConfig : ITypeFinderConfig
+ {
+ private readonly ITypeFinderSettings _settings;
+ private IEnumerable _assembliesAcceptingLoadExceptions;
+
+ public TypeFinderConfig(ITypeFinderSettings settings)
+ {
+ _settings = settings;
+ }
+
+ public IEnumerable AssembliesAcceptingLoadExceptions
+ {
+ get
+ {
+ if (_assembliesAcceptingLoadExceptions != null)
+ return _assembliesAcceptingLoadExceptions;
+
+ var s = _settings.AssembliesAcceptingLoadExceptions;
+ return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s)
+ ? Array.Empty()
+ : s.Split(',').Select(x => x.Trim()).ToArray();
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Composing/TypeHelper.cs b/src/Umbraco.Core/Composing/TypeHelper.cs
index 28eab6a5ec..1987a4059c 100644
--- a/src/Umbraco.Core/Composing/TypeHelper.cs
+++ b/src/Umbraco.Core/Composing/TypeHelper.cs
@@ -82,9 +82,9 @@ namespace Umbraco.Core.Composing
/// If the assembly of the assignTypeFrom Type is in the App_Code assembly, then we return nothing since things cannot
/// reference that assembly, same with the global.asax assembly.
///
- public static Assembly[] GetReferencingAssemblies(Assembly assembly, IEnumerable assemblies)
+ public static IReadOnlyList GetReferencingAssemblies(Assembly assembly, IEnumerable assemblies)
{
- if (assembly.IsAppCodeAssembly() || assembly.IsGlobalAsaxAssembly())
+ if (assembly.IsDynamic || assembly.IsAppCodeAssembly() || assembly.IsGlobalAsaxAssembly())
return EmptyAssemblies;
@@ -92,7 +92,7 @@ namespace Umbraco.Core.Composing
// should only be scanning those assemblies because any other assembly will definitely not
// contain sub type's of the one we're currently looking for
var name = assembly.GetName().Name;
- return assemblies.Where(x => x == assembly || HasReference(x, name)).ToArray();
+ return assemblies.Where(x => x == assembly || HasReference(x, name)).ToList();
}
///
diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs
index 76d00c472d..4d8b5c984c 100644
--- a/src/Umbraco.Core/Composing/TypeLoader.cs
+++ b/src/Umbraco.Core/Composing/TypeLoader.cs
@@ -516,29 +516,29 @@ namespace Umbraco.Core.Composing
#region Get Assembly Attributes
- ///
- /// Gets the assembly attributes of the specified type .
- ///
- /// The attribute type.
- ///
- /// The assembly attributes of the specified type .
- ///
- public IEnumerable GetAssemblyAttributes()
- where T : Attribute
- {
- return AssembliesToScan.SelectMany(a => a.GetCustomAttributes()).ToList();
- }
+ /////
+ ///// Gets the assembly attributes of the specified type .
+ /////
+ ///// The attribute type.
+ /////
+ ///// The assembly attributes of the specified type .
+ /////
+ //public IEnumerable GetAssemblyAttributes()
+ // where T : Attribute
+ //{
+ // return AssembliesToScan.SelectMany(a => a.GetCustomAttributes()).ToList();
+ //}
- ///
- /// Gets all the assembly attributes.
- ///
- ///
- /// All assembly attributes.
- ///
- public IEnumerable GetAssemblyAttributes()
- {
- return AssembliesToScan.SelectMany(a => a.GetCustomAttributes()).ToList();
- }
+ /////
+ ///// Gets all the assembly attributes.
+ /////
+ /////
+ ///// All assembly attributes.
+ /////
+ //public IEnumerable GetAssemblyAttributes()
+ //{
+ // return AssembliesToScan.SelectMany(a => a.GetCustomAttributes()).ToList();
+ //}
///
/// Gets the assembly attributes of the specified .
diff --git a/src/Umbraco.Core/Configuration/Configs.cs b/src/Umbraco.Core/Configuration/Configs.cs
index abb06d525f..821ee308f0 100644
--- a/src/Umbraco.Core/Configuration/Configs.cs
+++ b/src/Umbraco.Core/Configuration/Configs.cs
@@ -13,16 +13,8 @@ namespace Umbraco.Core.Configuration
///
public class Configs
{
- private readonly Func _configSectionResolver;
-
- public Configs(Func configSectionResolver)
- {
- _configSectionResolver = configSectionResolver ?? throw new ArgumentNullException(nameof(configSectionResolver));
- }
-
private readonly Dictionary> _configs = new Dictionary>();
private Dictionary> _registerings = new Dictionary>();
- private Lazy _factory;
///
/// Gets a configuration.
@@ -52,61 +44,15 @@ namespace Umbraco.Core.Configuration
_registerings[typeOfConfig] = register => register.Register(_ => (TConfig) lazyConfigFactory.Value, Lifetime.Singleton);
}
- ///
- /// Adds a configuration, provided by a factory.
- ///
- public void Add(Func configFactory)
- where TConfig : class
- {
- // make sure it is not too late
- if (_registerings == null)
- throw new InvalidOperationException("Configurations have already been registered.");
-
- var typeOfConfig = typeof(TConfig);
-
- _configs[typeOfConfig] = new Lazy
public static class ConfigsExtensions
{
+
+ public static IImagingSettings Imaging(this Configs configs)
+ => configs.GetConfig();
public static IGlobalSettings Global(this Configs configs)
=> configs.GetConfig();
@@ -25,47 +22,28 @@ namespace Umbraco.Core
public static IConnectionStrings ConnectionStrings(this Configs configs)
=> configs.GetConfig();
- public static IUmbracoSettingsSection Settings(this Configs configs)
- => configs.GetConfig();
+ public static IContentSettings Content(this Configs configs)
+ => configs.GetConfig();
- public static IHealthChecks HealthChecks(this Configs configs)
- => configs.GetConfig();
+ public static ISecuritySettings Security(this Configs configs)
+ => configs.GetConfig();
- public static IGridConfig Grids(this Configs configs)
- => configs.GetConfig();
-
- public static ICoreDebug CoreDebug(this Configs configs)
- => configs.GetConfig();
public static IUserPasswordConfiguration UserPasswordConfiguration(this Configs configs)
=> configs.GetConfig();
-
public static IMemberPasswordConfiguration MemberPasswordConfiguration(this Configs configs)
=> configs.GetConfig();
- public static void AddPasswordConfigurations(this Configs configs)
- {
- configs.Add(() =>
- {
- return new UserPasswordConfiguration(configs.Settings().Security.UserPasswordConfiguration);
- });
- configs.Add(() =>
- {
- return new MemberPasswordConfiguration(configs.Settings().Security.MemberPasswordConfiguration);
- });
- }
+ public static IRequestHandlerSettings RequestHandler(this Configs configs)
+ => configs.GetConfig();
- public static void AddCoreConfigs(this Configs configs, IIOHelper ioHelper)
- {
- var configDir = new DirectoryInfo(ioHelper.MapPath(Constants.SystemDirectories.Config));
+ public static IWebRoutingSettings WebRouting(this Configs configs)
+ => configs.GetConfig();
+
+ public static IHealthChecksSettings HealthChecks(this Configs configs)
+ => configs.GetConfig();
+ public static ICoreDebugSettings CoreDebug(this Configs configs)
+ => configs.GetConfig();
- // GridConfig depends on runtime caches, manifest parsers... and cannot be available during composition
- configs.Add(factory => new GridConfig(
- factory.GetInstance(),
- factory.GetInstance(),
- configDir,
- factory.GetInstance(),
- factory.GetInstance().Debug));
- }
}
}
diff --git a/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs b/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs
deleted file mode 100644
index 4d8039dfbb..0000000000
--- a/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using Umbraco.Core.IO;
-
-namespace Umbraco.Core.Configuration
-{
- public static class GlobalSettingsExtensions
- {
- private static string _mvcArea;
-
-
- ///
- /// This returns the string of the MVC Area route.
- ///
- ///
- /// 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".
- ///
- 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();
- }
-
- }
-}
diff --git a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs b/src/Umbraco.Core/Configuration/Grid/GridConfig.cs
index de4f7ccd5a..72c720e3d6 100644
--- a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs
+++ b/src/Umbraco.Core/Configuration/Grid/GridConfig.cs
@@ -1,15 +1,18 @@
using System.IO;
using Umbraco.Core.Cache;
+using Umbraco.Core.Hosting;
+using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
+using Umbraco.Core.Serialization;
namespace Umbraco.Core.Configuration.Grid
{
public class GridConfig : IGridConfig
{
- public GridConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, IManifestParser manifestParser, bool isDebug)
+ public GridConfig(AppCaches appCaches, IIOHelper ioHelper, IManifestParser manifestParser, IJsonSerializer jsonSerializer, IHostingEnvironment hostingEnvironment)
{
- EditorsConfig = new GridEditorsConfig(logger, appCaches, configFolder, manifestParser, isDebug);
+ EditorsConfig = new GridEditorsConfig(appCaches, ioHelper, manifestParser, jsonSerializer, hostingEnvironment.IsDebugMode);
}
public IGridEditorsConfig EditorsConfig { get; }
diff --git a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs b/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs
index a1ebf008fc..410c83ff1a 100644
--- a/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs
+++ b/src/Umbraco.Core/Configuration/Grid/GridEditorsConfig.cs
@@ -1,27 +1,30 @@
using System;
using System.Collections.Generic;
using System.IO;
+using Umbraco.Composing;
using Umbraco.Core.Cache;
+using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Serialization;
namespace Umbraco.Core.Configuration.Grid
{
internal class GridEditorsConfig : IGridEditorsConfig
{
- private readonly ILogger _logger;
private readonly AppCaches _appCaches;
- private readonly DirectoryInfo _configFolder;
+ private readonly IIOHelper _ioHelper;
private readonly IManifestParser _manifestParser;
private readonly bool _isDebug;
+ private readonly IJsonSerializer _jsonSerializer;
- public GridEditorsConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, IManifestParser manifestParser, bool isDebug)
+ public GridEditorsConfig(AppCaches appCaches, IIOHelper ioHelper, IManifestParser manifestParser,IJsonSerializer jsonSerializer, bool isDebug)
{
- _logger = logger;
_appCaches = appCaches;
- _configFolder = configFolder;
+ _ioHelper = ioHelper;
_manifestParser = manifestParser;
+ _jsonSerializer = jsonSerializer;
_isDebug = isDebug;
}
@@ -31,19 +34,20 @@ namespace Umbraco.Core.Configuration.Grid
{
List GetResult()
{
+ var configFolder = new DirectoryInfo(_ioHelper.MapPath(Constants.SystemDirectories.Config));
var editors = new List();
- var gridConfig = Path.Combine(_configFolder.FullName, "grid.editors.config.js");
+ var gridConfig = Path.Combine(configFolder.FullName, "grid.editors.config.js");
if (File.Exists(gridConfig))
{
var sourceString = File.ReadAllText(gridConfig);
try
{
- editors.AddRange(_manifestParser.ParseGridEditors(sourceString));
+ editors.AddRange(_jsonSerializer.Deserialize>(sourceString));
}
catch (Exception ex)
{
- _logger.Error(ex, "Could not parse the contents of grid.editors.config.js into a JSON array '{Json}", sourceString);
+ Current.Logger.Error(ex, "Could not parse the contents of grid.editors.config.js into a JSON array '{Json}", sourceString);
}
}
@@ -63,7 +67,6 @@ namespace Umbraco.Core.Configuration.Grid
return result;
}
-
}
}
}
diff --git a/src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs b/src/Umbraco.Core/Configuration/HealthChecks/IHealthChecksSettings.cs
similarity index 84%
rename from src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs
rename to src/Umbraco.Core/Configuration/HealthChecks/IHealthChecksSettings.cs
index fa98e3b054..785e8d5651 100644
--- a/src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs
+++ b/src/Umbraco.Core/Configuration/HealthChecks/IHealthChecksSettings.cs
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.HealthChecks
{
- public interface IHealthChecks
+ public interface IHealthChecksSettings
{
IEnumerable DisabledChecks { get; }
IHealthCheckNotificationSettings NotificationSettings { get; }
diff --git a/src/Umbraco.Core/Configuration/IConfigManipulator.cs b/src/Umbraco.Core/Configuration/IConfigManipulator.cs
new file mode 100644
index 0000000000..83ab2c0631
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/IConfigManipulator.cs
@@ -0,0 +1,10 @@
+using Umbraco.Core.IO;
+
+namespace Umbraco.Core.Configuration
+{
+ public interface IConfigManipulator
+ {
+ void RemoveConnectionString();
+ void SaveConnectionString(string connectionString, string providerName);
+ }
+}
diff --git a/src/Umbraco.Core/Configuration/IConfigsFactory.cs b/src/Umbraco.Core/Configuration/IConfigsFactory.cs
index 98a24ca37f..dd2459b88c 100644
--- a/src/Umbraco.Core/Configuration/IConfigsFactory.cs
+++ b/src/Umbraco.Core/Configuration/IConfigsFactory.cs
@@ -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();
}
}
diff --git a/src/Umbraco.Core/Configuration/IConnectionStrings.cs b/src/Umbraco.Core/Configuration/IConnectionStrings.cs
index acd2281a1e..0d33378669 100644
--- a/src/Umbraco.Core/Configuration/IConnectionStrings.cs
+++ b/src/Umbraco.Core/Configuration/IConnectionStrings.cs
@@ -6,7 +6,5 @@ namespace Umbraco.Core.Configuration
{
get;
}
-
- void RemoveConnectionString(string umbracoConnectionName);
}
}
diff --git a/src/Umbraco.Core/Configuration/ICoreDebug.cs b/src/Umbraco.Core/Configuration/ICoreDebugSettings.cs
similarity index 93%
rename from src/Umbraco.Core/Configuration/ICoreDebug.cs
rename to src/Umbraco.Core/Configuration/ICoreDebugSettings.cs
index 4ff2a1a300..586e4bc3e4 100644
--- a/src/Umbraco.Core/Configuration/ICoreDebug.cs
+++ b/src/Umbraco.Core/Configuration/ICoreDebugSettings.cs
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Configuration
{
- public interface ICoreDebug
+ public interface ICoreDebugSettings
{
///
/// When set to true, Scope logs the stack trace for any scope that gets disposed without being completed.
diff --git a/src/Umbraco.Core/Configuration/IGlobalSettings.cs b/src/Umbraco.Core/Configuration/IGlobalSettings.cs
index ffc52130cc..3cb211a7a7 100644
--- a/src/Umbraco.Core/Configuration/IGlobalSettings.cs
+++ b/src/Umbraco.Core/Configuration/IGlobalSettings.cs
@@ -21,7 +21,7 @@
string ReservedPaths { get; }
///
- /// Gets the path to umbraco's root directory (/umbraco by default).
+ /// Gets the path to umbraco's root directory.
///
string Path { get; }
@@ -96,5 +96,10 @@
string RegisterType { get; }
string DatabaseFactoryServerVersion { get; }
string MainDomLock { get; }
+
+ ///
+ /// Gets the path to the razor file used when no published content is available.
+ ///
+ string NoNodesViewPath { get; }
}
}
diff --git a/src/Umbraco.Core/Configuration/IImagingSettings.cs b/src/Umbraco.Core/Configuration/IImagingSettings.cs
new file mode 100644
index 0000000000..13e1b30389
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/IImagingSettings.cs
@@ -0,0 +1,12 @@
+namespace Umbraco.Core.Configuration
+{
+ public interface IImagingSettings
+ {
+ int MaxBrowserCacheDays { get;}
+ int MaxCacheDays { get; }
+ uint CachedNameLength { get; }
+ int MaxResizeWidth { get; }
+ int MaxResizeHeight { get; }
+ string CacheFolder { get; }
+ }
+}
diff --git a/src/Umbraco.Core/Configuration/IMachineKeyConfig.cs b/src/Umbraco.Core/Configuration/IMachineKeyConfig.cs
deleted file mode 100644
index 35969e668a..0000000000
--- a/src/Umbraco.Core/Configuration/IMachineKeyConfig.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Umbraco.Core.Configuration
-{
- public interface IMachineKeyConfig
- {
- bool HasMachineKey { get;}
- }
-}
diff --git a/src/Umbraco.Core/Configuration/IModelsBuilderConfig.cs b/src/Umbraco.Core/Configuration/IModelsBuilderConfig.cs
index 6a071ac277..990bde9843 100644
--- a/src/Umbraco.Core/Configuration/IModelsBuilderConfig.cs
+++ b/src/Umbraco.Core/Configuration/IModelsBuilderConfig.cs
@@ -7,7 +7,6 @@
int DebugLevel { get; }
bool EnableFactory { get; }
bool FlagOutOfDateModels { get; }
- bool IsDebug { get; }
string ModelsDirectory { get; }
ModelsMode ModelsMode { get; }
string ModelsNamespace { get; }
diff --git a/src/Umbraco.Core/Configuration/IPasswordConfiguration.cs b/src/Umbraco.Core/Configuration/IPasswordConfiguration.cs
index 98cd1010c0..6a5fd8e73f 100644
--- a/src/Umbraco.Core/Configuration/IPasswordConfiguration.cs
+++ b/src/Umbraco.Core/Configuration/IPasswordConfiguration.cs
@@ -6,13 +6,11 @@
///
public interface IPasswordConfiguration
{
- int RequiredLength { get; }
+ int RequiredLength { get; }
bool RequireNonLetterOrDigit { get; }
bool RequireDigit { get; }
bool RequireLowercase { get; }
bool RequireUppercase { get; }
-
- bool UseLegacyEncoding { get; }
string HashAlgorithmType { get; }
// TODO: This doesn't really belong here
diff --git a/src/Umbraco.Core/Configuration/MemberPasswordConfiguration.cs b/src/Umbraco.Core/Configuration/MemberPasswordConfiguration.cs
index 58c907c31f..8e7cd97f35 100644
--- a/src/Umbraco.Core/Configuration/MemberPasswordConfiguration.cs
+++ b/src/Umbraco.Core/Configuration/MemberPasswordConfiguration.cs
@@ -7,9 +7,9 @@ namespace Umbraco.Core.Configuration
///
public class MemberPasswordConfiguration : PasswordConfiguration, IMemberPasswordConfiguration
{
- public MemberPasswordConfiguration(IMemberPasswordConfigurationSection configSection)
- : base(configSection)
- {
+ public MemberPasswordConfiguration(IMemberPasswordConfiguration configSettings)
+ : base(configSettings)
+ {
}
}
}
diff --git a/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs b/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs
new file mode 100644
index 0000000000..3e3b116395
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs
@@ -0,0 +1,57 @@
+using System.Configuration;
+using System.IO;
+using Umbraco.Core.IO;
+
+namespace Umbraco.Core.Configuration
+{
+ public static class ModelsBuilderConfigExtensions
+ {
+ private static string _modelsDirectoryAbsolute = null;
+
+ public static string ModelsDirectoryAbsolute(this IModelsBuilderConfig modelsBuilderConfig, IIOHelper ioHelper)
+ {
+
+ if (_modelsDirectoryAbsolute is null)
+ {
+ var modelsDirectory = modelsBuilderConfig.ModelsDirectory;
+ var root = ioHelper.MapPath("~/");
+
+ _modelsDirectoryAbsolute = GetModelsDirectory(root, modelsDirectory,
+ modelsBuilderConfig.AcceptUnsafeModelsDirectory);
+ }
+
+ return _modelsDirectoryAbsolute;
+ }
+
+ // internal for tests
+ internal static string GetModelsDirectory(string root, string config, bool acceptUnsafe)
+ {
+ // making sure it is safe, ie under the website root,
+ // unless AcceptUnsafeModelsDirectory and then everything is OK.
+
+ if (!Path.IsPathRooted(root))
+ throw new ConfigurationErrorsException($"Root is not rooted \"{root}\".");
+
+ if (config.StartsWith("~/"))
+ {
+ var dir = Path.Combine(root, config.TrimStart("~/"));
+
+ // sanitize - GetFullPath will take care of any relative
+ // segments in path, eg '../../foo.tmp' - it may throw a SecurityException
+ // if the combined path reaches illegal parts of the filesystem
+ dir = Path.GetFullPath(dir);
+ root = Path.GetFullPath(root);
+
+ if (!dir.StartsWith(root) && !acceptUnsafe)
+ throw new ConfigurationErrorsException($"Invalid models directory \"{config}\".");
+
+ return dir;
+ }
+
+ if (acceptUnsafe)
+ return Path.GetFullPath(config);
+
+ throw new ConfigurationErrorsException($"Invalid models directory \"{config}\".");
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Configuration/PasswordConfiguration.cs b/src/Umbraco.Core/Configuration/PasswordConfiguration.cs
index 9edf1a462e..0c5ed9adb0 100644
--- a/src/Umbraco.Core/Configuration/PasswordConfiguration.cs
+++ b/src/Umbraco.Core/Configuration/PasswordConfiguration.cs
@@ -5,21 +5,20 @@ namespace Umbraco.Core.Configuration
{
public abstract class PasswordConfiguration : IPasswordConfiguration
{
- protected PasswordConfiguration(IPasswordConfigurationSection configSection)
+ protected PasswordConfiguration(IPasswordConfiguration configSettings)
{
- if (configSection == null)
+ if (configSettings == null)
{
- throw new ArgumentNullException(nameof(configSection));
+ throw new ArgumentNullException(nameof(configSettings));
}
- RequiredLength = configSection.RequiredLength;
- RequireNonLetterOrDigit = configSection.RequireNonLetterOrDigit;
- RequireDigit = configSection.RequireDigit;
- RequireLowercase = configSection.RequireLowercase;
- RequireUppercase = configSection.RequireUppercase;
- UseLegacyEncoding = configSection.UseLegacyEncoding;
- HashAlgorithmType = configSection.HashAlgorithmType;
- MaxFailedAccessAttemptsBeforeLockout = configSection.MaxFailedAccessAttemptsBeforeLockout;
+ RequiredLength = configSettings.RequiredLength;
+ RequireNonLetterOrDigit = configSettings.RequireNonLetterOrDigit;
+ RequireDigit = configSettings.RequireDigit;
+ RequireLowercase = configSettings.RequireLowercase;
+ RequireUppercase = configSettings.RequireUppercase;
+ HashAlgorithmType = configSettings.HashAlgorithmType;
+ MaxFailedAccessAttemptsBeforeLockout = configSettings.MaxFailedAccessAttemptsBeforeLockout;
}
public int RequiredLength { get; }
@@ -32,8 +31,6 @@ namespace Umbraco.Core.Configuration
public bool RequireUppercase { get; }
- public bool UseLegacyEncoding { get; }
-
public string HashAlgorithmType { get; }
public int MaxFailedAccessAttemptsBeforeLockout { get; }
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs
index 82cc5928cf..d100eb0a74 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
/// The file extension.
///
/// A value indicating whether the file extension corresponds to an image.
- public static bool IsImageFile(this IContentSection contentConfig, string extension)
+ public static bool IsImageFile(this IContentSettings contentConfig, string extension)
{
if (contentConfig == null) throw new ArgumentNullException(nameof(contentConfig));
if (extension == null) return false;
@@ -24,22 +24,22 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
/// held in settings.
/// Allow upload if extension is whitelisted OR if there is no whitelist and extension is NOT blacklisted.
///
- public static bool IsFileAllowedForUpload(this IContentSection contentSection, string extension)
+ public static bool IsFileAllowedForUpload(this IContentSettings contentSettings, string extension)
{
- return contentSection.AllowedUploadFiles.Any(x => x.InvariantEquals(extension)) ||
- (contentSection.AllowedUploadFiles.Any() == false &&
- contentSection.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false);
+ return contentSettings.AllowedUploadFiles.Any(x => x.InvariantEquals(extension)) ||
+ (contentSettings.AllowedUploadFiles.Any() == false &&
+ contentSettings.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false);
}
///
/// Gets the auto-fill configuration for a specified property alias.
///
- ///
+ ///
/// The property type alias.
/// The auto-fill configuration for the specified property alias, or null.
- public static IImagingAutoFillUploadField GetConfig(this IContentSection contentSection, string propertyTypeAlias)
+ public static IImagingAutoFillUploadField GetConfig(this IContentSettings contentSettings, string propertyTypeAlias)
{
- var autoFillConfigs = contentSection.ImageAutoFillProperties;
+ var autoFillConfigs = contentSettings.ImageAutoFillProperties;
return autoFillConfigs?.FirstOrDefault(x => x.Alias == propertyTypeAlias);
}
}
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IBackOfficeSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IBackOfficeSection.cs
index 36dd6a22ed..85df4540c0 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/IBackOfficeSection.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IBackOfficeSection.cs
@@ -2,6 +2,6 @@
{
public interface IBackOfficeSection
{
- ITourSection Tours { get; }
+ ITourSettings Tours { get; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSettings.cs
similarity index 93%
rename from src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs
rename to src/Umbraco.Core/Configuration/UmbracoSettings/IContentSettings.cs
index 228b0923dc..08f6231309 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSettings.cs
@@ -3,7 +3,7 @@ using Umbraco.Core.Macros;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- public interface IContentSection : IUmbracoConfigurationSection
+ public interface IContentSettings : IUmbracoConfigurationSection
{
string NotificationEmailAddress { get; }
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IKeepAliveSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IKeepAliveSettings.cs
similarity index 68%
rename from src/Umbraco.Core/Configuration/UmbracoSettings/IKeepAliveSection.cs
rename to src/Umbraco.Core/Configuration/UmbracoSettings/IKeepAliveSettings.cs
index 3a0ad258c5..58a8151474 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/IKeepAliveSection.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IKeepAliveSettings.cs
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- public interface IKeepAliveSection : IUmbracoConfigurationSection
+ public interface IKeepAliveSettings : IUmbracoConfigurationSection
{
bool DisableKeepAliveTask { get; }
string KeepAlivePingUrl { get; }
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ILoggingSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ILoggingSettings.cs
similarity index 66%
rename from src/Umbraco.Core/Configuration/UmbracoSettings/ILoggingSection.cs
rename to src/Umbraco.Core/Configuration/UmbracoSettings/ILoggingSettings.cs
index 6c1be8ade5..ee5647ee27 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/ILoggingSection.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ILoggingSettings.cs
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- public interface ILoggingSection : IUmbracoConfigurationSection
+ public interface ILoggingSettings : IUmbracoConfigurationSection
{
int MaxLogAge { get; }
}
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IMemberPasswordConfigurationSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IMemberPasswordConfigurationSection.cs
deleted file mode 100644
index cbbb933857..0000000000
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/IMemberPasswordConfigurationSection.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Umbraco.Core.Configuration.UmbracoSettings
-{
- public interface IMemberPasswordConfigurationSection : IPasswordConfigurationSection
- {
- }
-}
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSettings.cs
similarity index 78%
rename from src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs
rename to src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSettings.cs
index 2393c5af63..11fdaa8310 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSettings.cs
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- public interface IRequestHandlerSection : IUmbracoConfigurationSection
+ public interface IRequestHandlerSettings : IUmbracoConfigurationSection
{
bool AddTrailingSlash { get; }
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySettings.cs
similarity index 78%
rename from src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySection.cs
rename to src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySettings.cs
index a6ed188713..6ab520fefd 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySection.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ISecuritySettings.cs
@@ -1,9 +1,9 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- public interface ISecuritySection : IUmbracoConfigurationSection
+ public interface ISecuritySettings : IUmbracoConfigurationSection
{
bool KeepUserLoggedIn { get; }
-
+
bool HideDisabledUsersInBackoffice { get; }
///
@@ -23,9 +23,5 @@
/// When this is false, the username and email fields will be shown in the user section.
///
bool UsernameIsEmail { get; }
-
- IUserPasswordConfigurationSection UserPasswordConfiguration { get; }
-
- IMemberPasswordConfigurationSection MemberPasswordConfiguration { get; }
}
}
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ITourSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ITourSettings.cs
similarity index 75%
rename from src/Umbraco.Core/Configuration/UmbracoSettings/ITourSection.cs
rename to src/Umbraco.Core/Configuration/UmbracoSettings/ITourSettings.cs
index 938642521e..d3d8293140 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/ITourSection.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ITourSettings.cs
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- public interface ITourSection
+ public interface ITourSettings
{
bool EnableTours { get; }
}
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs
deleted file mode 100644
index acd9c92588..0000000000
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-
-namespace Umbraco.Core.Configuration.UmbracoSettings
-{
- public interface IUmbracoSettingsSection : IUmbracoConfigurationSection
- {
- IBackOfficeSection BackOffice { get; }
-
- IContentSection Content { get; }
-
- ISecuritySection Security { get; }
-
- IRequestHandlerSection RequestHandler { get; }
-
- ILoggingSection Logging { get; }
-
- IWebRoutingSection WebRouting { get; }
-
- IKeepAliveSection KeepAlive { get; }
- }
-}
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IUserPasswordConfigurationSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IUserPasswordConfigurationSection.cs
deleted file mode 100644
index d80dd2b7e5..0000000000
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/IUserPasswordConfigurationSection.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Umbraco.Core.Configuration.UmbracoSettings
-{
- public interface IUserPasswordConfigurationSection : IPasswordConfigurationSection
- {
- }
-}
diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSettings.cs
similarity index 86%
rename from src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSection.cs
rename to src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSettings.cs
index f0a986efe2..f7f6a94d30 100644
--- a/src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSection.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSettings.cs
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
- public interface IWebRoutingSection : IUmbracoConfigurationSection
+ public interface IWebRoutingSettings : IUmbracoConfigurationSection
{
bool TrySkipIisCustomErrors { get; }
diff --git a/src/Umbraco.Core/Configuration/UserPasswordConfiguration.cs b/src/Umbraco.Core/Configuration/UserPasswordConfiguration.cs
index 4cfee5280b..07e6603cee 100644
--- a/src/Umbraco.Core/Configuration/UserPasswordConfiguration.cs
+++ b/src/Umbraco.Core/Configuration/UserPasswordConfiguration.cs
@@ -7,9 +7,9 @@ namespace Umbraco.Core.Configuration
///
public class UserPasswordConfiguration : PasswordConfiguration, IUserPasswordConfiguration
{
- public UserPasswordConfiguration(IUserPasswordConfigurationSection configSection)
- : base(configSection)
- {
+ public UserPasswordConfiguration(IUserPasswordConfiguration configSettings)
+ : base(configSettings)
+ {
}
}
}
diff --git a/src/Umbraco.Core/Configuration/XmlConfigManipulator.cs b/src/Umbraco.Core/Configuration/XmlConfigManipulator.cs
new file mode 100644
index 0000000000..333f9dc6f9
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/XmlConfigManipulator.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Configuration;
+using System.IO;
+using System.Linq;
+using System.Xml.Linq;
+using Umbraco.Composing;
+using Umbraco.Core.IO;
+using Umbraco.Core.Logging;
+
+namespace Umbraco.Core.Configuration
+{
+ public class XmlConfigManipulator : IConfigManipulator
+ {
+ private readonly IIOHelper _ioHelper;
+ private readonly ILogger _logger;
+
+ public XmlConfigManipulator(IIOHelper ioHelper, ILogger logger)
+ {
+ _ioHelper = ioHelper;
+ _logger = logger;
+ }
+
+ public void RemoveConnectionString()
+ {
+ var key = Constants.System.UmbracoConnectionName;
+ 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();
+ var setting = appSettings.Descendants("add").FirstOrDefault(s => s.Attribute("key").Value == key);
+
+ if (setting != null)
+ {
+ setting.Remove();
+ xml.Save(fileName, SaveOptions.DisableFormatting);
+ ConfigurationManager.RefreshSection("appSettings");
+ }
+
+ var settings = ConfigurationManager.ConnectionStrings[key];
+ }
+
+ ///
+ /// Saves the connection string as a proper .net connection string in web.config.
+ ///
+ /// Saves the ConnectionString in the very nasty 'medium trust'-supportive way.
+ /// The connection string.
+ /// The provider name.
+ 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("Saving connection string to {ConfigFile}.", fileSource);
+ xml.Save(fileName, SaveOptions.DisableFormatting);
+ _logger.Info("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;
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Constants-AppSettings.cs b/src/Umbraco.Core/Constants-AppSettings.cs
index 4c47f12ba0..c55b4b0314 100644
--- a/src/Umbraco.Core/Constants-AppSettings.cs
+++ b/src/Umbraco.Core/Constants-AppSettings.cs
@@ -115,6 +115,11 @@ namespace Umbraco.Core
///
public const string DisableElectionForSingleServer = "Umbraco.Core.DisableElectionForSingleServer";
+ ///
+ /// Gets the path to the razor file used when no published content is available.
+ ///
+ public const string NoNodesViewPath = "Umbraco.Core.NoNodesViewPath";
+
///
/// Debug specific web.config AppSetting keys for Umbraco
///
diff --git a/src/Umbraco.Core/Constants-Configuration.cs b/src/Umbraco.Core/Constants-Configuration.cs
new file mode 100644
index 0000000000..c45229d918
--- /dev/null
+++ b/src/Umbraco.Core/Constants-Configuration.cs
@@ -0,0 +1,18 @@
+namespace Umbraco.Core
+{
+ public static partial class Constants
+ {
+ public static class Configuration
+ {
+ ///
+ /// Case insensitive prefix for all configurations
+ ///
+ ///
+ /// ":" is used as marker for nested objects in json. E.g. "Umbraco:CMS:" = {"Umbraco":{"CMS":{....}}
+ ///
+ public const string ConfigPrefix = "Umbraco:CMS:";
+ public const string ConfigSecurityPrefix = ConfigPrefix+"Security:";
+ public const string ConfigModelsBuilderPrefix = ConfigPrefix+"ModelsBuilder:";
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Constants-System.cs b/src/Umbraco.Core/Constants-System.cs
index abb92298f4..837db01b63 100644
--- a/src/Umbraco.Core/Constants-System.cs
+++ b/src/Umbraco.Core/Constants-System.cs
@@ -1,4 +1,4 @@
-namespace Umbraco.Core
+ namespace Umbraco.Core
{
public static partial class Constants
{
diff --git a/src/Umbraco.Core/Constants-Web.cs b/src/Umbraco.Core/Constants-Web.cs
index 5b64319fb0..b1efd782fa 100644
--- a/src/Umbraco.Core/Constants-Web.cs
+++ b/src/Umbraco.Core/Constants-Web.cs
@@ -34,7 +34,11 @@
/// The header name that angular uses to pass in the token to validate the cookie
///
public const string AngularHeadername = "X-UMB-XSRF-TOKEN";
-
+
+ ///
+ /// The route name of the page shown when Umbraco has no published content.
+ ///
+ public const string NoContentRouteName = "umbraco-no-content";
}
}
}
diff --git a/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs
new file mode 100644
index 0000000000..93441f1a47
--- /dev/null
+++ b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs
@@ -0,0 +1,8 @@
+namespace Umbraco.Core.Hosting
+{
+ public interface IApplicationShutdownRegistry
+ {
+ void RegisterObject(IRegisteredObject registeredObject);
+ void UnregisterObject(IRegisteredObject registeredObject);
+ }
+}
diff --git a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs
index 5b97d8e4f3..b12ffbc138 100644
--- a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs
+++ b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs
@@ -19,8 +19,5 @@ namespace Umbraco.Core.Hosting
Version IISVersion { get; }
string MapPath(string path);
string ToAbsolute(string virtualPath, string root);
-
- void RegisterObject(IRegisteredObject registeredObject);
- void UnregisterObject(IRegisteredObject registeredObject);
}
}
diff --git a/src/Umbraco.Core/IO/IIOHelper.cs b/src/Umbraco.Core/IO/IIOHelper.cs
index 11f5c6c565..f478b49de6 100644
--- a/src/Umbraco.Core/IO/IIOHelper.cs
+++ b/src/Umbraco.Core/IO/IIOHelper.cs
@@ -4,6 +4,9 @@ namespace Umbraco.Core.IO
{
public interface IIOHelper
{
+
+ string BackOfficePath { get; }
+
bool ForceNotHosted { get; set; }
char DirSepChar { get; }
diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs
index d5e1335f35..9eddea6477 100644
--- a/src/Umbraco.Core/IO/IOHelper.cs
+++ b/src/Umbraco.Core/IO/IOHelper.cs
@@ -4,6 +4,7 @@ using System.Globalization;
using System.Reflection;
using System.IO;
using System.Linq;
+using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.Strings;
@@ -12,10 +13,22 @@ namespace Umbraco.Core.IO
public class IOHelper : IIOHelper
{
private readonly IHostingEnvironment _hostingEnvironment;
+ private readonly IGlobalSettings _globalSettings;
- public IOHelper(IHostingEnvironment hostingEnvironment)
+ public IOHelper(IHostingEnvironment hostingEnvironment, IGlobalSettings globalSettings)
{
- _hostingEnvironment = hostingEnvironment;
+ _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
+ _globalSettings = globalSettings;
+ }
+
+ public string BackOfficePath
+ {
+ get
+ {
+ var path = _globalSettings.Path;
+
+ return string.IsNullOrEmpty(path) ? string.Empty : ResolveUrl(path);
+ }
}
///
diff --git a/src/Umbraco.Core/IO/IOHelperExtensions.cs b/src/Umbraco.Core/IO/IOHelperExtensions.cs
index 64b57e7dc1..39bd5e6cc9 100644
--- a/src/Umbraco.Core/IO/IOHelperExtensions.cs
+++ b/src/Umbraco.Core/IO/IOHelperExtensions.cs
@@ -5,6 +5,8 @@ namespace Umbraco.Core.IO
{
public static class IOHelperExtensions
{
+ private static string _mvcArea;
+
///
/// Tries to create a directory.
///
@@ -35,5 +37,38 @@ namespace Umbraco.Core.IO
{
return "umbraco-test." + Guid.NewGuid().ToString("N").Substring(0, 8);
}
+
+ ///
+ /// This returns the string of the MVC Area route.
+ ///
+ ///
+ /// 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".
+ ///
+ public static string GetUmbracoMvcArea(this IIOHelper ioHelper)
+ {
+ if (_mvcArea != null) return _mvcArea;
+
+ _mvcArea = GetUmbracoMvcAreaNoCache(ioHelper);
+
+ return _mvcArea;
+ }
+
+ internal static string GetUmbracoMvcAreaNoCache(this IIOHelper ioHelper)
+ {
+ if (ioHelper.BackOfficePath.IsNullOrWhiteSpace())
+ {
+ throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified");
+ }
+
+ var path = ioHelper.BackOfficePath;
+ if (path.StartsWith(ioHelper.Root)) // beware of TrimStart, see U4-2518
+ path = path.Substring(ioHelper.Root.Length);
+ return path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
+ }
}
}
diff --git a/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs b/src/Umbraco.Core/Logging/ConsoleLogger.cs
similarity index 98%
rename from src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs
rename to src/Umbraco.Core/Logging/ConsoleLogger.cs
index 53d6078e4b..275b8d988b 100644
--- a/src/Umbraco.Tests/TestHelpers/ConsoleLogger.cs
+++ b/src/Umbraco.Core/Logging/ConsoleLogger.cs
@@ -1,7 +1,6 @@
using System;
-using Umbraco.Core.Logging;
-namespace Umbraco.Tests.TestHelpers
+namespace Umbraco.Core.Logging
{
public class ConsoleLogger : ILogger
{
diff --git a/src/Umbraco.Core/Logging/ILogger.cs b/src/Umbraco.Core/Logging/ILogger.cs
index 4f49d0b3b4..fe7d798ebf 100644
--- a/src/Umbraco.Core/Logging/ILogger.cs
+++ b/src/Umbraco.Core/Logging/ILogger.cs
@@ -2,6 +2,7 @@
namespace Umbraco.Core.Logging
{
+
///
/// Defines the logging service.
///
diff --git a/src/Umbraco.Core/Manifest/IManifestParser.cs b/src/Umbraco.Core/Manifest/IManifestParser.cs
index eeb0c756f6..3eec7007b3 100644
--- a/src/Umbraco.Core/Manifest/IManifestParser.cs
+++ b/src/Umbraco.Core/Manifest/IManifestParser.cs
@@ -17,7 +17,5 @@ namespace Umbraco.Core.Manifest
/// Parses a manifest.
///
PackageManifest ParseManifest(string text);
-
- IEnumerable ParseGridEditors(string text);
}
}
diff --git a/src/Umbraco.Core/Models/DeepCloneHelper.cs b/src/Umbraco.Core/Models/DeepCloneHelper.cs
index 6470de912b..453b455d4b 100644
--- a/src/Umbraco.Core/Models/DeepCloneHelper.cs
+++ b/src/Umbraco.Core/Models/DeepCloneHelper.cs
@@ -81,9 +81,10 @@ namespace Umbraco.Core.Models
if (propertyInfo.PropertyType.IsGenericType
&& (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
- || propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
+ || propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)
+ || propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IReadOnlyCollection<>)))
{
- //if it is a IEnumerable<>, IList or ICollection<> we'll use a List<>
+ //if it is a IEnumerable<>, IReadOnlyCollection, IList or ICollection<> we'll use a List<> since it implements them all
var genericType = typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GetGenericArguments());
return new ClonePropertyInfo(propertyInfo) { GenericListType = genericType };
}
diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
index 10d5b10955..3e5361a1c1 100644
--- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
+++ b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs
@@ -1,5 +1,6 @@
namespace Umbraco.Net
{
+ // TODO: This shouldn't be in this namespace?
public interface IUmbracoApplicationLifetime
{
///
diff --git a/src/Umbraco.Core/PublishedContentExtensions.cs b/src/Umbraco.Core/PublishedContentExtensions.cs
index 84ee8c314b..03ce0c066a 100644
--- a/src/Umbraco.Core/PublishedContentExtensions.cs
+++ b/src/Umbraco.Core/PublishedContentExtensions.cs
@@ -149,11 +149,11 @@ namespace Umbraco.Core
}
public static bool IsAllowedTemplate(this IPublishedContent content, IContentTypeService contentTypeService,
- IUmbracoSettingsSection umbracoSettingsSection, int templateId)
+ IWebRoutingSettings webRoutingSettings, int templateId)
{
return content.IsAllowedTemplate(contentTypeService,
- umbracoSettingsSection.WebRouting.DisableAlternativeTemplates,
- umbracoSettingsSection.WebRouting.ValidateAlternativeTemplates, templateId);
+ webRoutingSettings.DisableAlternativeTemplates,
+ webRoutingSettings.ValidateAlternativeTemplates, templateId);
}
public static bool IsAllowedTemplate(this IPublishedContent content, IContentTypeService contentTypeService, bool disableAlternativeTemplates, bool validateAlternativeTemplates, int templateId)
diff --git a/src/Umbraco.Core/Routing/AliasUrlProvider.cs b/src/Umbraco.Core/Routing/AliasUrlProvider.cs
index c9cc3d5156..e71de2f6c6 100644
--- a/src/Umbraco.Core/Routing/AliasUrlProvider.cs
+++ b/src/Umbraco.Core/Routing/AliasUrlProvider.cs
@@ -14,13 +14,13 @@ namespace Umbraco.Web.Routing
public class AliasUrlProvider : IUrlProvider
{
private readonly IGlobalSettings _globalSettings;
- private readonly IRequestHandlerSection _requestConfig;
+ private readonly IRequestHandlerSettings _requestConfig;
private readonly ISiteDomainHelper _siteDomainHelper;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly UriUtility _uriUtility;
private readonly IPublishedValueFallback _publishedValueFallback;
- public AliasUrlProvider(IGlobalSettings globalSettings, IRequestHandlerSection requestConfig, ISiteDomainHelper siteDomainHelper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor)
+ public AliasUrlProvider(IGlobalSettings globalSettings, IRequestHandlerSettings requestConfig, ISiteDomainHelper siteDomainHelper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor)
{
_globalSettings = globalSettings;
_requestConfig = requestConfig;
diff --git a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs
index c4bfd5a697..49a6ff6bfe 100644
--- a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs
+++ b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs
@@ -18,11 +18,11 @@ namespace Umbraco.Web.Routing
{
private readonly ILogger _logger;
private readonly IRequestAccessor _requestAccessor;
- private readonly IWebRoutingSection _webRoutingSection;
+ private readonly IWebRoutingSettings _webRoutingSettings;
- public ContentFinderByIdPath(IWebRoutingSection webRoutingSection, ILogger logger, IRequestAccessor requestAccessor)
+ public ContentFinderByIdPath(IWebRoutingSettings webRoutingSettings, ILogger logger, IRequestAccessor requestAccessor)
{
- _webRoutingSection = webRoutingSection ?? throw new System.ArgumentNullException(nameof(webRoutingSection));
+ _webRoutingSettings = webRoutingSettings ?? throw new System.ArgumentNullException(nameof(webRoutingSettings));
_logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
_requestAccessor = requestAccessor;
}
@@ -36,7 +36,7 @@ namespace Umbraco.Web.Routing
{
if (frequest.UmbracoContext != null && frequest.UmbracoContext.InPreviewMode == false
- && _webRoutingSection.DisableFindContentByIdPath)
+ && _webRoutingSettings.DisableFindContentByIdPath)
return false;
IPublishedContent node = null;
diff --git a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs
index 933ab47150..7bcea4681e 100644
--- a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs
+++ b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs
@@ -17,15 +17,16 @@ namespace Umbraco.Web.Routing
public class ContentFinderByUrlAndTemplate : ContentFinderByUrl
{
private readonly IFileService _fileService;
- private readonly IUmbracoSettingsSection _umbracoSettingsSection;
- private readonly IContentTypeService _contentTypeService;
- public ContentFinderByUrlAndTemplate(ILogger logger, IFileService fileService, IUmbracoSettingsSection umbracoSettingsSection, IContentTypeService contentTypeService)
+ private readonly IContentTypeService _contentTypeService;
+ private readonly IWebRoutingSettings _webRoutingSettings;
+
+ public ContentFinderByUrlAndTemplate(ILogger logger, IFileService fileService, IContentTypeService contentTypeService, IWebRoutingSettings webRoutingSettings)
: base(logger)
{
_fileService = fileService;
- _umbracoSettingsSection = umbracoSettingsSection;
_contentTypeService = contentTypeService;
+ _webRoutingSettings = webRoutingSettings;
}
///
@@ -75,7 +76,7 @@ namespace Umbraco.Web.Routing
}
// IsAllowedTemplate deals both with DisableAlternativeTemplates and ValidateAlternativeTemplates settings
- if (!node.IsAllowedTemplate(_contentTypeService, _umbracoSettingsSection, template.Id))
+ if (!node.IsAllowedTemplate(_contentTypeService, _webRoutingSettings, template.Id))
{
Logger.Warn("Alternative template '{TemplateAlias}' is not allowed on node {NodeId}.", template.Alias, node.Id);
frequest.PublishedContent = null; // clear
diff --git a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs
index 81102810e8..f56d96b6b3 100644
--- a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs
+++ b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs
@@ -12,14 +12,14 @@ namespace Umbraco.Web.Routing
///
public class DefaultUrlProvider : IUrlProvider
{
- private readonly IRequestHandlerSection _requestSettings;
+ private readonly IRequestHandlerSettings _requestSettings;
private readonly ILogger _logger;
private readonly IGlobalSettings _globalSettings;
private readonly ISiteDomainHelper _siteDomainHelper;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly UriUtility _uriUtility;
- public DefaultUrlProvider(IRequestHandlerSection requestSettings, ILogger logger, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility)
+ public DefaultUrlProvider(IRequestHandlerSettings requestSettings, ILogger logger, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility)
{
_requestSettings = requestSettings;
_logger = logger;
diff --git a/src/Umbraco.Core/Routing/PublishedRequest.cs b/src/Umbraco.Core/Routing/PublishedRequest.cs
index 9b00e59deb..6e4d0008a9 100644
--- a/src/Umbraco.Core/Routing/PublishedRequest.cs
+++ b/src/Umbraco.Core/Routing/PublishedRequest.cs
@@ -16,7 +16,7 @@ namespace Umbraco.Web.Routing
public class PublishedRequest : IPublishedRequest
{
private readonly IPublishedRouter _publishedRouter;
- private readonly IUmbracoSettingsSection _umbracoSettingsSection;
+ private readonly IWebRoutingSettings _webRoutingSettings;
private bool _readonly; // after prepared
private bool _readonlyUri; // after preparing
@@ -33,11 +33,11 @@ namespace Umbraco.Web.Routing
/// The published router.
/// The Umbraco context.
/// The request Uri.
- internal PublishedRequest(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IUmbracoSettingsSection umbracoSettingsSection, Uri uri = null)
+ internal PublishedRequest(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IWebRoutingSettings webRoutingSettings, Uri uri = null)
{
UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
_publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter));
- _umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection));
+ _webRoutingSettings = webRoutingSettings;
Uri = uri ?? umbracoContext.CleanedUmbracoUrl;
}
@@ -178,7 +178,7 @@ namespace Umbraco.Web.Routing
IsInternalRedirectPublishedContent = isInternalRedirect;
// must restore the template if it's an internal redirect & the config option is set
- if (isInternalRedirect && _umbracoSettingsSection.WebRouting.InternalRedirectPreservesTemplate)
+ if (isInternalRedirect && _webRoutingSettings.InternalRedirectPreservesTemplate)
{
// restore
TemplateModel = template;
diff --git a/src/Umbraco.Core/Routing/PublishedRouter.cs b/src/Umbraco.Core/Routing/PublishedRouter.cs
index f521c3a95a..af4ec60e4d 100644
--- a/src/Umbraco.Core/Routing/PublishedRouter.cs
+++ b/src/Umbraco.Core/Routing/PublishedRouter.cs
@@ -19,13 +19,12 @@ namespace Umbraco.Web.Routing
///
public class PublishedRouter : IPublishedRouter
{
- private readonly IWebRoutingSection _webRoutingSection;
+ private readonly IWebRoutingSettings _webRoutingSettings;
private readonly ContentFinderCollection _contentFinders;
private readonly IContentLastChanceFinder _contentLastChanceFinder;
private readonly IProfilingLogger _profilingLogger;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly ILogger _logger;
- private readonly IUmbracoSettingsSection _umbracoSettingsSection;
private readonly IPublishedUrlProvider _publishedUrlProvider;
private readonly IRequestAccessor _requestAccessor;
private readonly IPublishedValueFallback _publishedValueFallback;
@@ -38,12 +37,11 @@ namespace Umbraco.Web.Routing
/// Initializes a new instance of the class.
///
public PublishedRouter(
- IWebRoutingSection webRoutingSection,
+ IWebRoutingSettings webRoutingSettings,
ContentFinderCollection contentFinders,
IContentLastChanceFinder contentLastChanceFinder,
IVariationContextAccessor variationContextAccessor,
IProfilingLogger proflog,
- IUmbracoSettingsSection umbracoSettingsSection,
IPublishedUrlProvider publishedUrlProvider,
IRequestAccessor requestAccessor,
IPublishedValueFallback publishedValueFallback,
@@ -52,13 +50,12 @@ namespace Umbraco.Web.Routing
IContentTypeService contentTypeService,
IPublicAccessService publicAccessService)
{
- _webRoutingSection = webRoutingSection ?? throw new ArgumentNullException(nameof(webRoutingSection));
+ _webRoutingSettings = webRoutingSettings ?? throw new ArgumentNullException(nameof(webRoutingSettings));
_contentFinders = contentFinders ?? throw new ArgumentNullException(nameof(contentFinders));
_contentLastChanceFinder = contentLastChanceFinder ?? throw new ArgumentNullException(nameof(contentLastChanceFinder));
_profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog));
_variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
_logger = proflog;
- _umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection));
_publishedUrlProvider = publishedUrlProvider;
_requestAccessor = requestAccessor;
_publishedValueFallback = publishedValueFallback;
@@ -71,7 +68,7 @@ namespace Umbraco.Web.Routing
///
public IPublishedRequest CreateRequest(IUmbracoContext umbracoContext, Uri uri = null)
{
- return new PublishedRequest(this, umbracoContext, _umbracoSettingsSection, uri ?? umbracoContext.CleanedUmbracoUrl);
+ return new PublishedRequest(this, umbracoContext, _webRoutingSettings, uri ?? umbracoContext.CleanedUmbracoUrl);
}
#region Request
@@ -628,7 +625,7 @@ namespace Umbraco.Web.Routing
// does not apply
// + optionally, apply the alternate template on internal redirects
var useAltTemplate = request.IsInitialPublishedContent
- || (_webRoutingSection.InternalRedirectPreservesTemplate && request.IsInternalRedirectPublishedContent);
+ || (_webRoutingSettings.InternalRedirectPreservesTemplate && request.IsInternalRedirectPublishedContent);
var altTemplate = useAltTemplate
? _requestAccessor.GetRequestValue(Constants.Conventions.Url.AltTemplate)
: null;
@@ -670,8 +667,8 @@ namespace Umbraco.Web.Routing
if (request.PublishedContent.IsAllowedTemplate(
_fileService,
_contentTypeService,
- _umbracoSettingsSection.WebRouting.DisableAlternativeTemplates,
- _umbracoSettingsSection.WebRouting.ValidateAlternativeTemplates,
+ _webRoutingSettings.DisableAlternativeTemplates,
+ _webRoutingSettings.ValidateAlternativeTemplates,
altTemplate))
{
// allowed, use
diff --git a/src/Umbraco.Core/Routing/UriUtility.cs b/src/Umbraco.Core/Routing/UriUtility.cs
index 11bb1dabfb..0c68580204 100644
--- a/src/Umbraco.Core/Routing/UriUtility.cs
+++ b/src/Umbraco.Core/Routing/UriUtility.cs
@@ -15,6 +15,7 @@ namespace Umbraco.Web
public UriUtility(IHostingEnvironment hostingEnvironment)
{
+ if (hostingEnvironment is null) throw new ArgumentNullException(nameof(hostingEnvironment));
ResetAppDomainAppVirtualPath(hostingEnvironment);
}
@@ -61,7 +62,7 @@ namespace Umbraco.Web
// maps an internal umbraco uri to a public uri
// ie with virtual directory, .aspx if required...
- public Uri UriFromUmbraco(Uri uri, IGlobalSettings globalSettings, IRequestHandlerSection requestConfig)
+ public Uri UriFromUmbraco(Uri uri, IGlobalSettings globalSettings, IRequestHandlerSettings requestConfig)
{
var path = uri.GetSafeAbsolutePath();
diff --git a/src/Umbraco.Core/Routing/UrlProvider.cs b/src/Umbraco.Core/Routing/UrlProvider.cs
index 80169e54e2..fa764cf7ff 100644
--- a/src/Umbraco.Core/Routing/UrlProvider.cs
+++ b/src/Umbraco.Core/Routing/UrlProvider.cs
@@ -24,7 +24,7 @@ namespace Umbraco.Web.Routing
/// The list of media url providers.
/// The current variation accessor.
///
- public UrlProvider(IUmbracoContextAccessor umbracoContextAccessor, IWebRoutingSection routingSettings, UrlProviderCollection urlProviders, MediaUrlProviderCollection mediaUrlProviders, IVariationContextAccessor variationContextAccessor)
+ public UrlProvider(IUmbracoContextAccessor umbracoContextAccessor, IWebRoutingSettings routingSettings, UrlProviderCollection urlProviders, MediaUrlProviderCollection mediaUrlProviders, IVariationContextAccessor variationContextAccessor)
{
if (routingSettings == null) throw new ArgumentNullException(nameof(routingSettings));
diff --git a/src/Umbraco.Core/Runtime/IMainDom.cs b/src/Umbraco.Core/Runtime/IMainDom.cs
index 444fc1c7d0..93a560ff7d 100644
--- a/src/Umbraco.Core/Runtime/IMainDom.cs
+++ b/src/Umbraco.Core/Runtime/IMainDom.cs
@@ -1,4 +1,5 @@
using System;
+using Umbraco.Core.Hosting;
// TODO: Can't change namespace due to breaking changes, change in netcore
namespace Umbraco.Core
@@ -16,10 +17,17 @@ namespace Umbraco.Core
/// Gets a value indicating whether the current domain is the main domain.
///
///
- /// When the first call is made to this there will generally be some logic executed to acquire a distributed lock lease.
+ /// Acquire must be called first else this will always return false
///
bool IsMainDom { get; }
+ ///
+ /// Tries to acquire the MainDom, returns true if successful else false
+ ///
+ ///
+ ///
+ bool Acquire(IApplicationShutdownRegistry hostingEnvironment);
+
///
/// Registers a resource that requires the current AppDomain to be the main domain to function.
///
diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs
index 2c56852095..81db1b700d 100644
--- a/src/Umbraco.Core/Runtime/MainDom.cs
+++ b/src/Umbraco.Core/Runtime/MainDom.cs
@@ -21,7 +21,7 @@ namespace Umbraco.Core.Runtime
#region Vars
private readonly ILogger _logger;
- private readonly IHostingEnvironment _hostingEnvironment;
+ private IApplicationShutdownRegistry _hostingEnvironment;
private readonly IMainDomLock _mainDomLock;
// our own lock for local consistency
@@ -42,17 +42,25 @@ namespace Umbraco.Core.Runtime
#region Ctor
// initializes a new instance of MainDom
- public MainDom(ILogger logger, IHostingEnvironment hostingEnvironment, IMainDomLock systemLock)
+ public MainDom(ILogger logger, IMainDomLock systemLock)
{
- hostingEnvironment.RegisterObject(this);
-
_logger = logger;
- _hostingEnvironment = hostingEnvironment;
_mainDomLock = systemLock;
}
#endregion
+ public bool Acquire(IApplicationShutdownRegistry hostingEnvironment)
+ {
+ _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
+
+ return LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () =>
+ {
+ hostingEnvironment.RegisterObject(this);
+ return Acquire();
+ });
+ }
+
///
/// Registers a resource that requires the current AppDomain to be the main domain to function.
///
@@ -180,10 +188,9 @@ namespace Umbraco.Core.Runtime
/// Gets a value indicating whether the current domain is the main domain.
///
///
- /// The lazy initializer call will only call the Acquire callback when it's not been initialized, else it will just return
- /// the value from _isMainDom which means when we set _isMainDom to false again after being signaled, this will return false;
+ /// Acquire must be called first else this will always return false
///
- public bool IsMainDom => LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () => Acquire());
+ public bool IsMainDom => _isMainDom;
// IRegisteredObject
void IRegisteredObject.Stop(bool immediate)
@@ -193,7 +200,7 @@ namespace Umbraco.Core.Runtime
// The web app is stopping, need to wind down
Dispose(true);
- _hostingEnvironment.UnregisterObject(this);
+ _hostingEnvironment?.UnregisterObject(this);
}
#region IDisposable Support
diff --git a/src/Umbraco.Core/Scheduling/KeepAlive.cs b/src/Umbraco.Core/Scheduling/KeepAlive.cs
index c677c66b83..1c4ef075ae 100644
--- a/src/Umbraco.Core/Scheduling/KeepAlive.cs
+++ b/src/Umbraco.Core/Scheduling/KeepAlive.cs
@@ -11,18 +11,22 @@ namespace Umbraco.Web.Scheduling
{
public class KeepAlive : RecurringTaskBase
{
- private readonly IRuntimeState _runtime;
- private readonly IKeepAliveSection _keepAliveSection;
+ private readonly IRuntimeState _runtimeState;
+ private readonly IMainDom _mainDom;
+ private readonly IKeepAliveSettings _keepAliveSettings;
private readonly IProfilingLogger _logger;
+ private readonly IServerRegistrar _serverRegistrar;
private static HttpClient _httpClient;
public KeepAlive(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds,
- IRuntimeState runtime, IKeepAliveSection keepAliveSection, IProfilingLogger logger)
+ IRuntimeState runtimeState, IMainDom mainDom, IKeepAliveSettings keepAliveSettings, IProfilingLogger logger, IServerRegistrar serverRegistrar)
: base(runner, delayMilliseconds, periodMilliseconds)
{
- _runtime = runtime;
- _keepAliveSection = keepAliveSection;
+ _runtimeState = runtimeState;
+ _mainDom = mainDom;
+ _keepAliveSettings = keepAliveSettings;
_logger = logger;
+ _serverRegistrar = serverRegistrar;
if (_httpClient == null)
_httpClient = new HttpClient();
}
@@ -30,7 +34,7 @@ namespace Umbraco.Web.Scheduling
public override async Task PerformRunAsync(CancellationToken token)
{
// not on replicas nor unknown role servers
- switch (_runtime.ServerRole)
+ switch (_serverRegistrar.GetCurrentServerRole())
{
case ServerRole.Replica:
_logger.Debug("Does not run on replica servers.");
@@ -41,7 +45,7 @@ namespace Umbraco.Web.Scheduling
}
// ensure we do not run if not main domain, but do NOT lock it
- if (_runtime.IsMainDom == false)
+ if (_mainDom.IsMainDom == false)
{
_logger.Debug("Does not run if not MainDom.");
return false; // do NOT repeat, going down
@@ -49,12 +53,12 @@ namespace Umbraco.Web.Scheduling
using (_logger.DebugDuration("Keep alive executing", "Keep alive complete"))
{
- var keepAlivePingUrl = _keepAliveSection.KeepAlivePingUrl;
+ var keepAlivePingUrl = _keepAliveSettings.KeepAlivePingUrl;
try
{
if (keepAlivePingUrl.Contains("{umbracoApplicationUrl}"))
{
- var umbracoAppUrl = _runtime.ApplicationUrl.ToString();
+ var umbracoAppUrl = _runtimeState.ApplicationUrl.ToString();
if (umbracoAppUrl.IsNullOrWhiteSpace())
{
_logger.Warn("No umbracoApplicationUrl for service (yet), skip.");
diff --git a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs
index aefaf605db..90bf4ee9eb 100644
--- a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs
+++ b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs
@@ -14,26 +14,26 @@ namespace Umbraco.Web.Scheduling
{
private readonly DirectoryInfo[] _tempFolders;
private readonly TimeSpan _age;
- private readonly IRuntimeState _runtime;
+ private readonly IMainDom _mainDom;
private readonly IProfilingLogger _logger;
public TempFileCleanup(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds,
IEnumerable tempFolders, TimeSpan age,
- IRuntimeState runtime, IProfilingLogger logger)
+ IMainDom mainDom, IProfilingLogger logger)
: base(runner, delayMilliseconds, periodMilliseconds)
{
//SystemDirectories.TempFileUploads
_tempFolders = tempFolders.ToArray();
_age = age;
- _runtime = runtime;
+ _mainDom = mainDom;
_logger = logger;
}
public override bool PerformRun()
{
// ensure we do not run if not main domain
- if (_runtime.IsMainDom == false)
+ if (_mainDom.IsMainDom == false)
{
_logger.Debug("Does not run if not MainDom.");
return false; // do NOT repeat, going down
diff --git a/src/Umbraco.Core/Services/IRuntime.cs b/src/Umbraco.Core/Services/IRuntime.cs
index e846342dbc..4715068073 100644
--- a/src/Umbraco.Core/Services/IRuntime.cs
+++ b/src/Umbraco.Core/Services/IRuntime.cs
@@ -13,13 +13,15 @@ namespace Umbraco.Core
///
/// The application register.
/// The application factory.
- IFactory Boot(IRegister register);
+ IFactory Configure(IRegister register);
///
/// Gets the runtime state.
///
IRuntimeState State { get; }
+ void Start();
+
///
/// Terminates the runtime.
///
diff --git a/src/Umbraco.Core/Services/IRuntimeState.cs b/src/Umbraco.Core/Services/IRuntimeState.cs
index 38da246cc1..4b5e26651b 100644
--- a/src/Umbraco.Core/Services/IRuntimeState.cs
+++ b/src/Umbraco.Core/Services/IRuntimeState.cs
@@ -25,33 +25,12 @@ namespace Umbraco.Core
///
SemVersion SemanticVersion { get; }
- ///
- /// Gets a value indicating whether the application is running in debug mode.
- ///
- bool Debug { get; }
-
- ///
- /// Gets a value indicating whether the runtime is the current main domain.
- ///
- bool IsMainDom { get; }
-
- ///
- /// Get the server's current role.
- ///
- ServerRole ServerRole { get; }
-
///
/// Gets the Umbraco application url.
///
/// This is eg "http://www.example.com".
Uri ApplicationUrl { get; }
- ///
- /// Gets the Umbraco application virtual path.
- ///
- /// This is either "/" or eg "/virtual".
- string ApplicationVirtualPath { get; }
-
///
/// Gets the runtime level of execution.
///
@@ -77,6 +56,5 @@ namespace Umbraco.Core
///
BootFailedException BootFailedException { get; }
- IMainDom MainDom { get; }
}
}
diff --git a/src/Umbraco.Core/SimpleMainDom.cs b/src/Umbraco.Core/SimpleMainDom.cs
index 87cc7bcff1..e6bdda67d7 100644
--- a/src/Umbraco.Core/SimpleMainDom.cs
+++ b/src/Umbraco.Core/SimpleMainDom.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Umbraco.Core.Hosting;
namespace Umbraco.Core
{
@@ -16,6 +17,9 @@ namespace Umbraco.Core
///
public bool IsMainDom { get; private set; } = true;
+ // always acquire
+ public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) => true;
+
///
public bool Register(Action release, int weight = 100)
=> Register(null, release, weight);
diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs
index 6361186604..c3e7fa85c3 100644
--- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs
+++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Strings
{
#region Ctor, consts and vars
- public DefaultShortStringHelper(IUmbracoSettingsSection settings)
+ public DefaultShortStringHelper(IRequestHandlerSettings settings)
{
_config = new DefaultShortStringHelperConfig().WithDefault(settings);
}
@@ -619,6 +619,6 @@ namespace Umbraco.Core.Strings
return new string(output, 0, opos);
}
- #endregion
+ #endregion
}
}
diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs
index e75e00defb..25ee781ae9 100644
--- a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs
+++ b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs
@@ -30,7 +30,7 @@ namespace Umbraco.Core.Strings
public string DefaultCulture { get; set; } = ""; // invariant
public Dictionary UrlReplaceCharacters { get; set; }
-
+
public DefaultShortStringHelperConfig WithConfig(Config config)
{
return WithConfig(DefaultCulture, CleanStringType.RoleMask, config);
@@ -57,16 +57,16 @@ namespace Umbraco.Core.Strings
/// Sets the default configuration.
///
/// The short string helper.
- public DefaultShortStringHelperConfig WithDefault(IUmbracoSettingsSection umbracoSettings)
+ public DefaultShortStringHelperConfig WithDefault(IRequestHandlerSettings requestHandlerSettings)
{
- UrlReplaceCharacters = umbracoSettings.RequestHandler.CharCollection
+ UrlReplaceCharacters = requestHandlerSettings.CharCollection
.Where(x => string.IsNullOrEmpty(x.Char) == false)
.ToDictionary(x => x.Char, x => x.Replacement);
var urlSegmentConvertTo = CleanStringType.Utf8;
- if (umbracoSettings.RequestHandler.ConvertUrlsToAscii)
+ if (requestHandlerSettings.ConvertUrlsToAscii)
urlSegmentConvertTo = CleanStringType.Ascii;
- if (umbracoSettings.RequestHandler.TryConvertUrlsToAscii)
+ if (requestHandlerSettings.TryConvertUrlsToAscii)
urlSegmentConvertTo = CleanStringType.TryAscii;
return WithConfig(CleanStringType.UrlSegment, new Config
diff --git a/src/Umbraco.Core/Templates/HtmlUrlParser.cs b/src/Umbraco.Core/Templates/HtmlUrlParser.cs
index a2fdb93292..566fce8b87 100644
--- a/src/Umbraco.Core/Templates/HtmlUrlParser.cs
+++ b/src/Umbraco.Core/Templates/HtmlUrlParser.cs
@@ -7,16 +7,16 @@ namespace Umbraco.Web.Templates
{
public sealed class HtmlUrlParser
{
- private readonly IContentSection _contentSection;
+ private readonly IContentSettings _contentSettings;
private readonly IIOHelper _ioHelper;
private readonly IProfilingLogger _logger;
private static readonly Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
- public HtmlUrlParser(IContentSection contentSection, IProfilingLogger logger, IIOHelper ioHelper)
+ public HtmlUrlParser(IContentSettings contentSettings, IProfilingLogger logger, IIOHelper ioHelper)
{
- _contentSection = contentSection;
+ _contentSettings = contentSettings;
_ioHelper = ioHelper;
_logger = logger;
}
@@ -32,7 +32,7 @@ namespace Umbraco.Web.Templates
///
public string EnsureUrls(string text)
{
- if (_contentSection.ResolveUrlsFromTextString == false) return text;
+ if (_contentSettings.ResolveUrlsFromTextString == false) return text;
using (var timer = _logger.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete"))
{
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 7a15e7fbed..c083cccf8f 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -12,6 +12,7 @@
+
diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs
index cf84d7914d..4321aefd7f 100644
--- a/src/Umbraco.Core/UriExtensions.cs
+++ b/src/Umbraco.Core/UriExtensions.cs
@@ -40,7 +40,7 @@ namespace Umbraco.Core
/// But if we've got this far we'll just have to assume it's front-end anyways.
///
///
- internal static bool IsBackOfficeRequest(this Uri url, string applicationPath, IGlobalSettings globalSettings, IIOHelper ioHelper)
+ internal static bool IsBackOfficeRequest(this Uri url, string applicationPath, IIOHelper ioHelper)
{
applicationPath = applicationPath ?? string.Empty;
@@ -49,11 +49,11 @@ namespace Umbraco.Core
var urlPath = fullUrlPath.TrimStart(appPath).EnsureStartsWith('/');
//check if this is in the umbraco back office
- var isUmbracoPath = urlPath.InvariantStartsWith(globalSettings.Path.EnsureStartsWith('/').TrimStart(appPath.EnsureStartsWith('/')).EnsureStartsWith('/'));
+ var isUmbracoPath = urlPath.InvariantStartsWith(ioHelper.BackOfficePath.EnsureStartsWith('/').TrimStart(appPath.EnsureStartsWith('/')).EnsureStartsWith('/'));
//if not, then def not back office
if (isUmbracoPath == false) return false;
- var mvcArea = globalSettings.GetUmbracoMvcArea(ioHelper);
+ var mvcArea = ioHelper.GetUmbracoMvcArea();
//if its the normal /umbraco path
if (urlPath.InvariantEquals("/" + mvcArea)
|| urlPath.InvariantEquals("/" + mvcArea + "/"))
@@ -127,12 +127,12 @@ namespace Umbraco.Core
///
///
///
- internal static bool IsDefaultBackOfficeRequest(this Uri url, IGlobalSettings globalSettings)
+ internal static bool IsDefaultBackOfficeRequest(this Uri url, IIOHelper ioHelper)
{
- if (url.AbsolutePath.InvariantEquals(globalSettings.Path.TrimEnd("/"))
- || url.AbsolutePath.InvariantEquals(globalSettings.Path.EnsureEndsWith('/'))
- || url.AbsolutePath.InvariantEquals(globalSettings.Path.EnsureEndsWith('/') + "Default")
- || url.AbsolutePath.InvariantEquals(globalSettings.Path.EnsureEndsWith('/') + "Default/"))
+ if (url.AbsolutePath.InvariantEquals(ioHelper.BackOfficePath.TrimEnd("/"))
+ || url.AbsolutePath.InvariantEquals(ioHelper.BackOfficePath.EnsureEndsWith('/'))
+ || url.AbsolutePath.InvariantEquals(ioHelper.BackOfficePath.EnsureEndsWith('/') + "Default")
+ || url.AbsolutePath.InvariantEquals(ioHelper.BackOfficePath.EnsureEndsWith('/') + "Default/"))
{
return true;
}
diff --git a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
index d73dc89948..c4e7f264fb 100644
--- a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
+++ b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
@@ -6,8 +6,6 @@ using System.Text.RegularExpressions;
using Examine;
using Umbraco.Core;
using Umbraco.Core.Models;
-using Umbraco.Core.Models.Identity;
-using Umbraco.Core.Persistence;
using Umbraco.Core.Services;
using Umbraco.Web;
using Umbraco.Web.Models.ContentEditing;
diff --git a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs
index 78b9589a2e..70b79fbeb0 100644
--- a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs
+++ b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs
@@ -28,17 +28,18 @@ namespace Umbraco.Web
private readonly IRequestAccessor _requestAccessor;
public BatchedDatabaseServerMessenger(
- IRuntimeState runtime,
+ IMainDom mainDom,
IUmbracoDatabaseFactory databaseFactory,
IScopeProvider scopeProvider,
ISqlContext sqlContext,
IProfilingLogger proflog,
+ IServerRegistrar serverRegistrar,
DatabaseServerMessengerOptions options,
IHostingEnvironment hostingEnvironment,
CacheRefresherCollection cacheRefreshers,
IRequestCache requestCache,
IRequestAccessor requestAccessor)
- : base(runtime, scopeProvider, sqlContext, proflog, true, options, hostingEnvironment, cacheRefreshers)
+ : base(mainDom, scopeProvider, sqlContext, proflog, serverRegistrar, true, options, hostingEnvironment, cacheRefreshers)
{
_databaseFactory = databaseFactory;
_requestCache = requestCache;
diff --git a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
index 2a24e6f318..6c745f3877 100644
--- a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
+++ b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs
@@ -91,7 +91,6 @@ namespace Umbraco.Web.Compose
private readonly BackgroundTaskRunner _processTaskRunner;
private bool _started;
private IBackgroundTask[] _tasks;
- private IndexRebuilder _indexRebuilder;
private readonly IRequestAccessor _requestAccessor;
public DatabaseServerRegistrarAndMessengerComponent(
@@ -100,14 +99,12 @@ namespace Umbraco.Web.Compose
IServerMessenger serverMessenger,
IServerRegistrationService registrationService,
ILogger logger,
- IHostingEnvironment hostingEnvironment,
- IndexRebuilder indexRebuilder,
+ IApplicationShutdownRegistry hostingEnvironment,
IRequestAccessor requestAccessor)
{
_runtime = runtime;
_logger = logger;
_registrationService = registrationService;
- _indexRebuilder = indexRebuilder;
_requestAccessor = requestAccessor;
// create task runner for DatabaseServerRegistrar
diff --git a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs
index d4e22bbfde..a2ee650595 100644
--- a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs
+++ b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Compose
{
public sealed class ManifestWatcherComponent : IComponent
{
- private readonly IRuntimeState _runtimeState;
+ private readonly IHostingEnvironment _hosting;
private readonly ILogger _logger;
private readonly IIOHelper _ioHelper;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
@@ -19,9 +19,9 @@ namespace Umbraco.Core.Compose
// package.manifest chances and restarts the application on any change
private ManifestWatcher _mw;
- public ManifestWatcherComponent(IRuntimeState runtimeState, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime)
+ public ManifestWatcherComponent(IHostingEnvironment hosting, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
- _runtimeState = runtimeState;
+ _hosting = hosting;
_logger = logger;
_ioHelper = ioHelper;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Compose
public void Initialize()
{
- if (_runtimeState.Debug == false) return;
+ if (_hosting.IsDebugMode == false) return;
//if (ApplicationContext.Current.IsConfigured == false || GlobalSettings.DebugMode == false)
// return;
diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Configuration.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Configuration.cs
deleted file mode 100644
index 5c931a225b..0000000000
--- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Configuration.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using Umbraco.Core.Configuration;
-using Umbraco.Configuration;
-using Umbraco.Core.Configuration.UmbracoSettings;
-
-namespace Umbraco.Core.Composing.CompositionExtensions
-{
- ///
- /// Compose configurations.
- ///
- internal static class Configuration
- {
- public static Composition ComposeConfiguration(this Composition composition)
- {
- // common configurations are already registered
- // register others
-
- composition.RegisterUnique(factory => factory.GetInstance().Content);
- composition.RegisterUnique(factory => factory.GetInstance().RequestHandler);
- composition.RegisterUnique(factory => factory.GetInstance().Security);
-
- return composition;
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs b/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs
new file mode 100644
index 0000000000..2099778185
--- /dev/null
+++ b/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs
@@ -0,0 +1,21 @@
+using Microsoft.Extensions.Hosting;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Extends the to enable Umbraco to be used as the service container.
+ ///
+ public static class HostBuilderExtensions
+ {
+ ///
+ /// Assigns a custom service provider factory to use Umbraco's container
+ ///
+ ///
+ ///
+ public static IHostBuilder UseUmbraco(this IHostBuilder builder)
+ => builder.UseUmbraco(new UmbracoServiceProviderFactory());
+
+ public static IHostBuilder UseUmbraco(this IHostBuilder builder, UmbracoServiceProviderFactory umbracoServiceProviderFactory)
+ => builder.UseServiceProviderFactory(umbracoServiceProviderFactory);
+ }
+}
diff --git a/src/Umbraco.Infrastructure/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Infrastructure/Composing/LightInject/LightInjectContainer.cs
index 5200dced90..a6db0b7b2b 100644
--- a/src/Umbraco.Infrastructure/Composing/LightInject/LightInjectContainer.cs
+++ b/src/Umbraco.Infrastructure/Composing/LightInject/LightInjectContainer.cs
@@ -16,11 +16,13 @@ namespace Umbraco.Core.Composing.LightInject
///
/// Initializes a new instance of the with a LightInject container.
///
- protected LightInjectContainer(ServiceContainer container)
+ public LightInjectContainer(ServiceContainer container)
{
- Container = container;
+ Container = ConfigureContainer(container);
}
+ //TODO: The Create methods can die when net framework is gone
+
///
/// Creates a new instance of the class.
///
@@ -33,7 +35,12 @@ namespace Umbraco.Core.Composing.LightInject
protected static ServiceContainer CreateServiceContainer()
{
var container = new ServiceContainer(new ContainerOptions { EnablePropertyInjection = false });
+ ConfigureContainer(container);
+ return container;
+ }
+ private static ServiceContainer ConfigureContainer(ServiceContainer container)
+ {
// note: the block below is disabled, as it is too LightInject-specific
//
// supports annotated constructor injections
@@ -84,7 +91,7 @@ namespace Umbraco.Core.Composing.LightInject
///
/// Gets the LightInject container.
///
- protected ServiceContainer Container { get; }
+ public ServiceContainer Container { get; }
///
///
diff --git a/src/Umbraco.Infrastructure/Composing/RegisterFactory.cs b/src/Umbraco.Infrastructure/Composing/RegisterFactory.cs
index 8f842e14fe..835bd0b9a8 100644
--- a/src/Umbraco.Infrastructure/Composing/RegisterFactory.cs
+++ b/src/Umbraco.Infrastructure/Composing/RegisterFactory.cs
@@ -1,14 +1,22 @@
-using System;
+using LightInject;
+using LightInject.Microsoft.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using System;
using System.Reflection;
+using Umbraco.Core.Composing.LightInject;
using Umbraco.Core.Configuration;
namespace Umbraco.Core.Composing
{
+
///
/// Creates the container.
///
public static class RegisterFactory
{
+ //TODO: This can die when net framework is gone
+
// cannot use typeof().AssemblyQualifiedName on the web container - we don't reference it
// a normal Umbraco site should run on the web container, but an app may run on the core one
private const string CoreLightInjectContainerTypeName = "Umbraco.Core.Composing.LightInject.LightInjectContainer,Umbraco.Core";
diff --git a/src/Umbraco.Infrastructure/Composing/UmbracoServiceProviderFactory.cs b/src/Umbraco.Infrastructure/Composing/UmbracoServiceProviderFactory.cs
new file mode 100644
index 0000000000..6fd0bda61e
--- /dev/null
+++ b/src/Umbraco.Infrastructure/Composing/UmbracoServiceProviderFactory.cs
@@ -0,0 +1,78 @@
+using LightInject;
+using LightInject.Microsoft.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using System;
+using Umbraco.Core.Composing.LightInject;
+
+namespace Umbraco.Core.Composing
+{
+ ///
+ /// Used to create Umbraco's container and cross-wire it up before the applicaton starts
+ ///
+ public class UmbracoServiceProviderFactory : IServiceProviderFactory
+ {
+ public UmbracoServiceProviderFactory(ServiceContainer container)
+ {
+ _container = new LightInjectContainer(container);
+ }
+
+ ///
+ /// Creates an ASP.NET Core compatible service container
+ ///
+ ///
+ public static ServiceContainer CreateServiceContainer() => new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings());
+
+ ///
+ /// Default ctor for use in Host Builder configuration
+ ///
+ public UmbracoServiceProviderFactory()
+ {
+ var container = CreateServiceContainer();
+ UmbracoContainer = _container = new LightInjectContainer(container);
+ IsActive = true;
+ }
+
+ // see here for orig lightinject version https://github.com/seesharper/LightInject.Microsoft.DependencyInjection/blob/412566e3f70625e6b96471db5e1f7cd9e3e1eb18/src/LightInject.Microsoft.DependencyInjection/LightInject.Microsoft.DependencyInjection.cs#L263
+ // we don't really need all that, we're manually creating our container with the correct options and that
+ // is what we'll return in CreateBuilder
+
+ IServiceCollection _services;
+ readonly LightInjectContainer _container;
+
+ internal LightInjectContainer GetContainer() => _container;
+
+ ///
+ /// When the empty ctor is used this returns if this factory is active
+ ///
+ public static bool IsActive { get; private set; }
+
+ ///
+ /// When the empty ctor is used this returns the created IRegister
+ ///
+ public static IRegister UmbracoContainer { get; private set; }
+
+ ///
+ /// Create the container with the required settings for aspnetcore3
+ ///
+ ///
+ ///
+ public IServiceContainer CreateBuilder(IServiceCollection services)
+ {
+ _services = services;
+ return _container.Container;
+ }
+
+ ///
+ /// This cross-wires the container just before the application calls "Configure"
+ ///
+ ///
+ ///
+ public IServiceProvider CreateServiceProvider(IServiceContainer containerBuilder)
+ {
+ var provider = containerBuilder.CreateServiceProvider(_services);
+ return provider;
+ }
+
+ }
+}
diff --git a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs b/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs
index eb74d37590..02e5a6f5ee 100644
--- a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs
+++ b/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs
@@ -1,6 +1,7 @@
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
+using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
@@ -15,6 +16,9 @@ namespace Umbraco.Core
///
/// Registers essential services.
///
+ ///
+ /// These services are all either created by the runtime or used to construct the runtime
+ ///
public static void RegisterEssentials(this Composition composition,
ILogger logger, IProfiler profiler, IProfilingLogger profilingLogger,
IMainDom mainDom,
@@ -25,8 +29,10 @@ namespace Umbraco.Core
ITypeFinder typeFinder,
IIOHelper ioHelper,
IUmbracoVersion umbracoVersion,
- IDbProviderFactoryCreator dbProviderFactoryCreator)
- {
+ IDbProviderFactoryCreator dbProviderFactoryCreator,
+ IHostingEnvironment hostingEnvironment,
+ IBackOfficeInfo backOfficeInfo)
+ {
composition.RegisterUnique(logger);
composition.RegisterUnique(profiler);
composition.RegisterUnique(profilingLogger);
@@ -42,6 +48,8 @@ namespace Umbraco.Core
composition.RegisterUnique(umbracoVersion);
composition.RegisterUnique(dbProviderFactoryCreator);
composition.RegisterUnique(factory => factory.GetInstance().BulkSqlInsertProvider);
+ composition.RegisterUnique(hostingEnvironment);
+ composition.RegisterUnique(backOfficeInfo);
}
}
}
diff --git a/src/Umbraco.Infrastructure/Configuration/JsonConfigManipulator.cs b/src/Umbraco.Infrastructure/Configuration/JsonConfigManipulator.cs
new file mode 100644
index 0000000000..3c78faea37
--- /dev/null
+++ b/src/Umbraco.Infrastructure/Configuration/JsonConfigManipulator.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.Json.Serialization;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Configuration.Json;
+using Microsoft.Extensions.FileProviders;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Umbraco.Core.IO;
+using Umbraco.Core.Serialization;
+
+namespace Umbraco.Core.Configuration
+{
+ public class JsonConfigManipulator : IConfigManipulator
+ {
+ private readonly IConfiguration _configuration;
+
+ public JsonConfigManipulator(IConfiguration configuration)
+ {
+ _configuration = configuration;
+ }
+
+ public string UmbracoConnectionPath { get; } = $"ConnectionStrings:{ Constants.System.UmbracoConnectionName}";
+ public void RemoveConnectionString()
+ {
+ var provider = GetJsonConfigurationProvider(UmbracoConnectionPath);
+
+ var json = GetJson(provider);
+
+ RemoveJsonKey(json, UmbracoConnectionPath);
+
+ SaveJson(provider, json);
+ }
+
+ public void SaveConnectionString(string connectionString, string providerName)
+ {
+ var provider = GetJsonConfigurationProvider();
+
+ var json = GetJson(provider);
+
+ var item = GetConnectionItem(connectionString, providerName);
+
+ json.Merge(item, new JsonMergeSettings());
+
+ SaveJson(provider, json);
+ }
+
+
+ private JToken GetConnectionItem(string connectionString, string providerName)
+ {
+ JTokenWriter writer = new JTokenWriter();
+
+ writer.WriteStartObject();
+ writer.WritePropertyName("ConnectionStrings");
+ writer.WriteStartObject();
+ writer.WritePropertyName(Constants.System.UmbracoConnectionName);
+ writer.WriteValue(connectionString);
+ writer.WriteEndObject();
+ writer.WriteEndObject();
+
+ return writer.Token;
+ }
+
+ private static void RemoveJsonKey(JObject json, string key)
+ {
+ JToken token = json;
+ foreach (var propertyName in key.Split(new[] { ':' }))
+ {
+ token = CaseSelectPropertyValues(token, propertyName);
+ }
+
+ token?.Parent?.Remove();
+ }
+
+ private static void SaveJson(JsonConfigurationProvider provider, JObject json)
+ {
+ if (provider.Source.FileProvider is PhysicalFileProvider physicalFileProvider)
+ {
+ var jsonFilePath = Path.Combine(physicalFileProvider.Root, provider.Source.Path);
+
+ using (var sw = new StreamWriter(jsonFilePath, false))
+ using (var jsonTextWriter = new JsonTextWriter(sw)
+ {
+ Formatting = Formatting.Indented,
+ })
+ {
+ json?.WriteTo(jsonTextWriter);
+ }
+ }
+
+ }
+
+ private static JObject GetJson(JsonConfigurationProvider provider)
+ {
+ if (provider.Source.FileProvider is PhysicalFileProvider physicalFileProvider)
+ {
+ var jsonFilePath = Path.Combine(physicalFileProvider.Root, provider.Source.Path);
+
+ var serializer = new JsonSerializer();
+ using (var sr = new StreamReader(jsonFilePath))
+ using (var jsonTextReader = new JsonTextReader(sr))
+ {
+ return serializer.Deserialize(jsonTextReader);
+ }
+ }
+
+ return null;
+ }
+
+
+
+
+ private JsonConfigurationProvider GetJsonConfigurationProvider(string requiredKey = null)
+ {
+ if (_configuration is IConfigurationRoot configurationRoot)
+ {
+ foreach (var provider in configurationRoot.Providers)
+ {
+ if(provider is JsonConfigurationProvider jsonConfigurationProvider)
+ {
+ if (requiredKey is null || provider.TryGet(requiredKey, out _))
+ {
+ return jsonConfigurationProvider;
+ }
+ }
+ }
+ }
+ throw new InvalidOperationException("Could not find a writable json config source");
+ }
+
+ ///
+ /// Returns the property value when case insensative
+ ///
+ ///
+ /// This method is required because keys are case insensative in IConfiguration.
+ /// JObject[..] do not support case insensative and JObject.Property(...) do not return a new JObject.
+ ///
+ private static JToken CaseSelectPropertyValues(JToken token, string name)
+ {
+ if (token is JObject obj)
+ {
+
+ foreach (var property in obj.Properties())
+ {
+ if (name is null)
+ return property.Value;
+ if (string.Equals(property.Name, name, StringComparison.OrdinalIgnoreCase))
+ return property.Value;
+ }
+ }
+ return null;
+ }
+
+ }
+}
diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
index b27113a0f1..9d36b60d83 100644
--- a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
+++ b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
@@ -18,9 +18,9 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
private readonly IRuntimeState _runtimeState;
private readonly ILogger _logger;
private readonly IGlobalSettings _globalSettings;
- private readonly IUmbracoSettingsSection _umbracoSettingsSection;
+ private readonly IContentSettings _contentSettings;
- public EmailNotificationMethod(ILocalizedTextService textService, IRuntimeState runtimeState, ILogger logger, IGlobalSettings globalSettings, IHealthChecks healthChecks, IUmbracoSettingsSection umbracoSettingsSection) : base(healthChecks)
+ public EmailNotificationMethod(ILocalizedTextService textService, IRuntimeState runtimeState, ILogger logger, IGlobalSettings globalSettings, IHealthChecksSettings healthChecksSettings, IContentSettings contentSettings) : base(healthChecksSettings)
{
var recipientEmail = Settings["recipientEmail"]?.Value;
if (string.IsNullOrWhiteSpace(recipientEmail))
@@ -35,7 +35,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
_runtimeState = runtimeState;
_logger = logger;
_globalSettings = globalSettings;
- _umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection));
+ _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings));
}
public string RecipientEmail { get; }
@@ -74,7 +74,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
private MailMessage CreateMailMessage(string subject, string message)
{
- var to = _umbracoSettingsSection.Content.NotificationEmailAddress;
+ var to = _contentSettings.NotificationEmailAddress;
if (string.IsNullOrWhiteSpace(subject))
subject = "Umbraco Health Check Status";
diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/NotificationMethodBase.cs b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/NotificationMethodBase.cs
index ff6fbe2371..9c3516e712 100644
--- a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/NotificationMethodBase.cs
+++ b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/NotificationMethodBase.cs
@@ -8,7 +8,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
{
public abstract class NotificationMethodBase : IHealthCheckNotificationMethod
{
- protected NotificationMethodBase(IHealthChecks healthCheckConfig)
+ protected NotificationMethodBase(IHealthChecksSettings healthCheckSettingsConfig)
{
var type = GetType();
var attribute = type.GetCustomAttribute();
@@ -18,7 +18,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
return;
}
- var notificationMethods = healthCheckConfig.NotificationSettings.NotificationMethods;
+ var notificationMethods = healthCheckSettingsConfig.NotificationSettings.NotificationMethods;
var notificationMethod = notificationMethods[attribute.Alias];
if (notificationMethod == null)
{
diff --git a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs
index a5b4f71d8e..cf4b174cde 100644
--- a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs
+++ b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs
@@ -9,10 +9,10 @@ using Umbraco.Core.Cookie;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Models;
+using Umbraco.Net;
using Umbraco.Core.Persistence;
using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
-using Umbraco.Net;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install
diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/ConfigureMachineKey.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/ConfigureMachineKey.cs
deleted file mode 100644
index fb8201600c..0000000000
--- a/src/Umbraco.Infrastructure/Intall/InstallSteps/ConfigureMachineKey.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using System.Linq;
-using System.Threading.Tasks;
-using System.Xml.Linq;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.IO;
-using Umbraco.Core.Security;
-using Umbraco.Web.Install.Models;
-
-namespace Umbraco.Web.Install.InstallSteps
-{
- [InstallSetupStep(InstallationType.NewInstall,
- "ConfigureMachineKey", "machinekey", 2,
- "Updating some security settings...",
- PerformsAppRestart = true)]
- public class ConfigureMachineKey : InstallSetupStep
- {
- private readonly IIOHelper _ioHelper;
- private readonly IMachineKeyConfig _machineKeyConfig;
-
- public ConfigureMachineKey(IIOHelper ioHelper, IMachineKeyConfig machineKeyConfig)
- {
- _ioHelper = ioHelper;
- _machineKeyConfig = machineKeyConfig;
- }
-
- public override string View => HasMachineKey() == false ? base.View : "";
-
- ///
- /// Don't display the view or execute if a machine key already exists
- ///
- ///
- private bool HasMachineKey()
- {
- return _machineKeyConfig.HasMachineKey;
- }
-
- ///
- /// The step execution method
- ///
- ///
- ///
- public override Task ExecuteAsync(bool? model)
- {
- if (model.HasValue && model.Value == false) return Task.FromResult(null);
-
- //install the machine key
- var fileName = _ioHelper.MapPath($"{_ioHelper.Root}/web.config");
- var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
-
- // we only want to get the element that is under the root, (there may be more under tags we don't want them)
- var systemWeb = xml.Root.Element("system.web");
-
- // Update appSetting if it exists, or else create a new appSetting for the given key and value
- var machineKey = systemWeb.Descendants("machineKey").FirstOrDefault();
- if (machineKey != null) return Task.FromResult(null);
-
- var generator = new MachineKeyGenerator();
- var generatedSection = generator.GenerateConfigurationBlock();
- systemWeb.Add(XElement.Parse(generatedSection));
-
- xml.Save(fileName, SaveOptions.DisableFormatting);
-
- return Task.FromResult(null);
- }
-
- public override bool RequiresExecution(bool? model)
- {
- return HasMachineKey() == false;
- }
- }
-}
diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseInstallStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseInstallStep.cs
index a7b3dcc218..865df4bc02 100644
--- a/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseInstallStep.cs
+++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseInstallStep.cs
@@ -19,14 +19,16 @@ namespace Umbraco.Web.Install.InstallSteps
private readonly ILogger _logger;
private readonly IIOHelper _ioHelper;
private readonly IConnectionStrings _connectionStrings;
+ private readonly IConfigManipulator _configManipulator;
- public DatabaseInstallStep(DatabaseBuilder databaseBuilder, IRuntimeState runtime, ILogger logger, IIOHelper ioHelper, IConnectionStrings connectionStrings)
+ public DatabaseInstallStep(DatabaseBuilder databaseBuilder, IRuntimeState runtime, ILogger logger, IIOHelper ioHelper, IConnectionStrings connectionStrings, IConfigManipulator configManipulator)
{
_databaseBuilder = databaseBuilder;
_runtime = runtime;
_logger = logger;
_ioHelper = ioHelper;
_connectionStrings = connectionStrings;
+ _configManipulator = configManipulator;
}
public override Task ExecuteAsync(object model)
@@ -43,7 +45,7 @@ namespace Umbraco.Web.Install.InstallSteps
if (result.RequiresUpgrade == false)
{
- HandleConnectionStrings(_logger, _ioHelper, _connectionStrings);
+ HandleConnectionStrings(_logger, _ioHelper, _connectionStrings, _configManipulator);
return Task.FromResult(null);
}
@@ -54,7 +56,7 @@ namespace Umbraco.Web.Install.InstallSteps
}));
}
- internal static void HandleConnectionStrings(ILogger logger, IIOHelper ioHelper, IConnectionStrings connectionStrings)
+ internal static void HandleConnectionStrings(ILogger logger, IIOHelper ioHelper, IConnectionStrings connectionStrings, IConfigManipulator configManipulator)
{
@@ -65,7 +67,7 @@ namespace Umbraco.Web.Install.InstallSteps
// Remove legacy umbracoDbDsn configuration setting if it exists and connectionstring also exists
if (databaseSettings != null)
{
- connectionStrings.RemoveConnectionString(Constants.System.UmbracoConnectionName);
+ configManipulator.RemoveConnectionString();
}
else
{
diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseUpgradeStep.cs
index 3cd3c1ca56..91a718d0f4 100644
--- a/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseUpgradeStep.cs
+++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/DatabaseUpgradeStep.cs
@@ -23,8 +23,17 @@ namespace Umbraco.Web.Install.InstallSteps
private readonly IGlobalSettings _globalSettings;
private readonly IConnectionStrings _connectionStrings;
private readonly IIOHelper _ioHelper;
+ private readonly IConfigManipulator _configManipulator;
- public DatabaseUpgradeStep(DatabaseBuilder databaseBuilder, IRuntimeState runtime, ILogger logger, IUmbracoVersion umbracoVersion, IGlobalSettings globalSettings, IConnectionStrings connectionStrings, IIOHelper ioHelper)
+ public DatabaseUpgradeStep(
+ DatabaseBuilder databaseBuilder,
+ IRuntimeState runtime,
+ ILogger logger,
+ IUmbracoVersion umbracoVersion,
+ IGlobalSettings globalSettings,
+ IConnectionStrings connectionStrings,
+ IIOHelper ioHelper,
+ IConfigManipulator configManipulator)
{
_databaseBuilder = databaseBuilder;
_runtime = runtime;
@@ -33,6 +42,7 @@ namespace Umbraco.Web.Install.InstallSteps
_globalSettings = globalSettings;
_connectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings));
_ioHelper = ioHelper;
+ _configManipulator = configManipulator;
}
public override Task ExecuteAsync(object model)
@@ -55,7 +65,7 @@ namespace Umbraco.Web.Install.InstallSteps
throw new InstallException("The database failed to upgrade. ERROR: " + result.Message);
}
- DatabaseInstallStep.HandleConnectionStrings(_logger, _ioHelper, _connectionStrings);
+ DatabaseInstallStep.HandleConnectionStrings(_logger, _ioHelper, _connectionStrings, _configManipulator);
}
return Task.FromResult(null);
diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs
index cc269408f4..4e14da30b7 100644
--- a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs
+++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs
@@ -2,8 +2,8 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
-using Umbraco.Core.Services;
using Umbraco.Net;
+using Umbraco.Core.Services;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs
index 9dde28e95a..bb77869e28 100644
--- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs
+++ b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Logging.Serilog
///
public class SerilogLogger : ILogger, IDisposable
{
- private readonly ICoreDebug _coreDebug;
+ private readonly ICoreDebugSettings _coreDebugSettings;
private readonly IIOHelper _ioHelper;
private readonly IMarchal _marchal;
@@ -26,9 +26,9 @@ namespace Umbraco.Core.Logging.Serilog
/// Initialize a new instance of the class with a configuration file.
///
///
- public SerilogLogger(ICoreDebug coreDebug, IIOHelper ioHelper, IMarchal marchal, FileInfo logConfigFile)
+ public SerilogLogger(ICoreDebugSettings coreDebugSettings, IIOHelper ioHelper, IMarchal marchal, FileInfo logConfigFile)
{
- _coreDebug = coreDebug;
+ _coreDebugSettings = coreDebugSettings;
_ioHelper = ioHelper;
_marchal = marchal;
@@ -37,9 +37,9 @@ namespace Umbraco.Core.Logging.Serilog
.CreateLogger();
}
- public SerilogLogger(ICoreDebug coreDebug, IIOHelper ioHelper, IMarchal marchal, LoggerConfiguration logConfig)
+ public SerilogLogger(ICoreDebugSettings coreDebugSettings, IIOHelper ioHelper, IMarchal marchal, LoggerConfiguration logConfig)
{
- _coreDebug = coreDebug;
+ _coreDebugSettings = coreDebugSettings;
_ioHelper = ioHelper;
_marchal = marchal;
@@ -51,7 +51,7 @@ namespace Umbraco.Core.Logging.Serilog
/// Creates a logger with some pre-defined configuration and remainder from config file
///
/// Used by UmbracoApplicationBase to get its logger.
- public static SerilogLogger CreateWithDefaultConfiguration(IHostingEnvironment hostingEnvironment, ISessionIdResolver sessionIdResolver, Func requestCacheGetter, ICoreDebug coreDebug, IIOHelper ioHelper, IMarchal marchal)
+ public static SerilogLogger CreateWithDefaultConfiguration(IHostingEnvironment hostingEnvironment, ISessionIdResolver sessionIdResolver, Func requestCacheGetter, ICoreDebugSettings coreDebugSettings, IIOHelper ioHelper, IMarchal marchal)
{
var loggerConfig = new LoggerConfiguration();
loggerConfig
@@ -59,7 +59,7 @@ namespace Umbraco.Core.Logging.Serilog
.ReadFromConfigFile()
.ReadFromUserConfigFile();
- return new SerilogLogger(coreDebug, ioHelper, marchal, loggerConfig);
+ return new SerilogLogger(coreDebugSettings, ioHelper, marchal, loggerConfig);
}
///
@@ -179,7 +179,7 @@ namespace Umbraco.Core.Logging.Serilog
messageTemplate += "\r\nThe thread has been aborted, because the request has timed out.";
// dump if configured, or if stacktrace contains Monitor.ReliableEnter
- dump = _coreDebug.DumpOnTimeoutThreadAbort || IsMonitorEnterThreadAbortException(exception);
+ dump = _coreDebugSettings.DumpOnTimeoutThreadAbort || IsMonitorEnterThreadAbortException(exception);
// dump if it is ok to dump (might have a cap on number of dump...)
dump &= MiniDump.OkToDump(_ioHelper);
diff --git a/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs b/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs
index 2074409ec8..987d3a98fb 100644
--- a/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs
+++ b/src/Umbraco.Infrastructure/Manifest/ManifestParser.cs
@@ -220,11 +220,5 @@ namespace Umbraco.Core.Manifest
return manifest;
}
-
- // purely for tests
- public IEnumerable ParseGridEditors(string text)
- {
- return _jsonSerializer.Deserialize>(text);
- }
}
}
diff --git a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs b/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs
index 4c02111ccd..665693d91f 100644
--- a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs
+++ b/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs
@@ -17,13 +17,13 @@ namespace Umbraco.Web.Media
{
private readonly IMediaFileSystem _mediaFileSystem;
private readonly ILogger _logger;
- private readonly IContentSection _contentSection;
+ private readonly IContentSettings _contentSettings;
- public UploadAutoFillProperties(IMediaFileSystem mediaFileSystem, ILogger logger, IContentSection contentSection)
+ public UploadAutoFillProperties(IMediaFileSystem mediaFileSystem, ILogger logger, IContentSettings contentSettings)
{
_mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
- _contentSection = contentSection ?? throw new ArgumentNullException(nameof(contentSection));
+ _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings));
}
///
@@ -68,7 +68,7 @@ namespace Umbraco.Web.Media
using (var filestream = _mediaFileSystem.OpenFile(filepath))
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
- var size = _contentSection.IsImageFile(extension) ? (Size?)ImageHelper.GetDimensions(filestream) : null;
+ var size = _contentSettings.IsImageFile(extension) ? (Size?)ImageHelper.GetDimensions(filestream) : null;
SetProperties(content, autoFillConfig, size, filestream.Length, extension, culture, segment);
}
}
@@ -102,7 +102,7 @@ namespace Umbraco.Web.Media
else
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
- var size = _contentSection.IsImageFile(extension) ? (Size?)ImageHelper.GetDimensions(filestream) : null;
+ var size = _contentSettings.IsImageFile(extension) ? (Size?)ImageHelper.GetDimensions(filestream) : null;
SetProperties(content, autoFillConfig, size, filestream.Length, extension, culture, segment);
}
}
diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
index 8b1e6d741b..8d5922028c 100644
--- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
+++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
@@ -28,6 +28,7 @@ namespace Umbraco.Core.Migrations.Install
private readonly IIOHelper _ioHelper;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator;
+ private readonly IConfigManipulator _configManipulator;
private DatabaseSchemaResult _databaseSchemaValidationResult;
@@ -44,7 +45,8 @@ namespace Umbraco.Core.Migrations.Install
IKeyValueService keyValueService,
IIOHelper ioHelper,
IUmbracoVersion umbracoVersion,
- IDbProviderFactoryCreator dbProviderFactoryCreator)
+ IDbProviderFactoryCreator dbProviderFactoryCreator,
+ IConfigManipulator configManipulator)
{
_scopeProvider = scopeProvider;
_globalSettings = globalSettings;
@@ -56,6 +58,7 @@ namespace Umbraco.Core.Migrations.Install
_ioHelper = ioHelper;
_umbracoVersion = umbracoVersion;
_dbProviderFactoryCreator = dbProviderFactoryCreator;
+ _configManipulator = configManipulator;
}
#region Status
@@ -138,12 +141,12 @@ namespace Umbraco.Core.Migrations.Install
///
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);
+ _configManipulator.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);
+ _configManipulator.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);
+ _configManipulator.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);
+ _configManipulator.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());
}
- ///
- /// Saves the connection string as a proper .net connection string in web.config.
- ///
- /// Saves the ConnectionString in the very nasty 'medium trust'-supportive way.
- /// The connection string.
- /// The provider name.
- /// A logger.
- 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("Saving connection string to {ConfigFile}.", fileSource);
- xml.Save(fileName, SaveOptions.DisableFormatting);
- logger.Info("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
diff --git a/src/Umbraco.Infrastructure/Models/ContentEditing/UserInvite.cs b/src/Umbraco.Infrastructure/Models/ContentEditing/UserInvite.cs
index f1c6cf6c04..06e4d0748c 100644
--- a/src/Umbraco.Infrastructure/Models/ContentEditing/UserInvite.cs
+++ b/src/Umbraco.Infrastructure/Models/ContentEditing/UserInvite.cs
@@ -33,7 +33,7 @@ namespace Umbraco.Web.Models.ContentEditing
if (UserGroups.Any() == false)
yield return new ValidationResult("A user must be assigned to at least one group", new[] { nameof(UserGroups) });
- if (Current.Configs.Settings().Security.UsernameIsEmail == false && Username.IsNullOrWhiteSpace())
+ if (Current.Configs.Security().UsernameIsEmail == false && Username.IsNullOrWhiteSpace())
yield return new ValidationResult("A username cannot be empty", new[] { nameof(Username) });
}
}
diff --git a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs
index f7a2d6376b..59f63f4f15 100644
--- a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs
+++ b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs
@@ -191,7 +191,7 @@ namespace Umbraco.Web.Models.Mapping
target.Icon = source.Icon;
target.IconFilePath = target.IconIsClass
? string.Empty
- : $"{_globalSettings.Path.EnsureEndsWith("/")}images/umbraco/{source.Icon}";
+ : $"{_ioHelper.BackOfficePath.EnsureEndsWith("/")}images/umbraco/{source.Icon}";
target.Trashed = source.Trashed;
target.Id = source.Id;
@@ -497,7 +497,7 @@ namespace Umbraco.Web.Models.Mapping
target.Icon = source.Icon;
target.IconFilePath = target.IconIsClass
? string.Empty
- : $"{_globalSettings.Path.EnsureEndsWith("/")}images/umbraco/{source.Icon}";
+ : $"{_ioHelper.BackOfficePath.EnsureEndsWith("/")}images/umbraco/{source.Icon}";
target.Id = source.Id;
target.IsContainer = source.IsContainer;
target.IsElement = source.IsElement;
@@ -540,7 +540,7 @@ namespace Umbraco.Web.Models.Mapping
target.Icon = source.Icon;
target.IconFilePath = target.IconIsClass
? string.Empty
- : $"{_globalSettings.Path.EnsureEndsWith("/")}images/umbraco/{source.Icon}";
+ : $"{_ioHelper.BackOfficePath.EnsureEndsWith("/")}images/umbraco/{source.Icon}";
target.Id = source.Id;
target.IsContainer = source.IsContainer;
target.IsElement = source.IsElement;
diff --git a/src/Umbraco.Infrastructure/Models/Mapping/DataTypeMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/DataTypeMapDefinition.cs
index d57809c844..0bd6d54c08 100644
--- a/src/Umbraco.Infrastructure/Models/Mapping/DataTypeMapDefinition.cs
+++ b/src/Umbraco.Infrastructure/Models/Mapping/DataTypeMapDefinition.cs
@@ -15,13 +15,13 @@ namespace Umbraco.Web.Models.Mapping
{
private readonly PropertyEditorCollection _propertyEditors;
private readonly ILogger _logger;
- private readonly IUmbracoSettingsSection _umbracoSettingsSection;
+ private readonly IContentSettings _contentSettings;
- public DataTypeMapDefinition(PropertyEditorCollection propertyEditors, ILogger logger, IUmbracoSettingsSection umbracoSettingsSection)
+ public DataTypeMapDefinition(PropertyEditorCollection propertyEditors, ILogger logger, IContentSettings contentSettings)
{
_propertyEditors = propertyEditors;
_logger = logger;
- _umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection));
+ _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings));
}
private static readonly int[] SystemIds =
@@ -128,9 +128,8 @@ namespace Umbraco.Web.Models.Mapping
private IEnumerable MapAvailableEditors(IDataType source, MapperContext context)
{
- var contentSection = _umbracoSettingsSection.Content;
var properties = _propertyEditors
- .Where(x => !x.IsDeprecated || contentSection.ShowDeprecatedPropertyEditors || source.EditorAlias == x.Alias)
+ .Where(x => !x.IsDeprecated || _contentSettings.ShowDeprecatedPropertyEditors || source.EditorAlias == x.Alias)
.OrderBy(x => x.Name);
return context.MapEnumerable(properties);
}
diff --git a/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs
index f2faaf275d..ba7b5cddf2 100644
--- a/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs
+++ b/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs
@@ -175,6 +175,12 @@ namespace Umbraco.Web.Models.Mapping
target.Name = source.Values.ContainsKey(UmbracoExamineFieldNames.NodeNameFieldName) ? source.Values[UmbracoExamineFieldNames.NodeNameFieldName] : "[no name]";
+ var culture = context.GetCulture();
+ if(culture.IsNullOrWhiteSpace() == false)
+ {
+ target.Name = source.Values.ContainsKey($"nodeName_{culture}") ? source.Values[$"nodeName_{culture}"] : target.Name;
+ }
+
if (source.Values.TryGetValue(UmbracoExamineFieldNames.UmbracoFileFieldName, out var umbracoFile))
{
if (umbracoFile != null)
diff --git a/src/Umbraco.Infrastructure/Models/MediaExtensions.cs b/src/Umbraco.Infrastructure/Models/MediaExtensions.cs
index 41bcfdbc88..ffcc2c2a92 100644
--- a/src/Umbraco.Infrastructure/Models/MediaExtensions.cs
+++ b/src/Umbraco.Infrastructure/Models/MediaExtensions.cs
@@ -27,9 +27,9 @@ namespace Umbraco.Core.Models
///
/// Gets the urls of a media item.
///
- public static string[] GetUrls(this IMedia media, IContentSection contentSection, MediaUrlGeneratorCollection mediaUrlGenerators)
+ public static string[] GetUrls(this IMedia media, IContentSettings contentSettings, MediaUrlGeneratorCollection mediaUrlGenerators)
{
- return contentSection.ImageAutoFillProperties
+ return contentSettings.ImageAutoFillProperties
.Select(field => media.GetUrl(field.Alias, mediaUrlGenerators))
.Where(link => string.IsNullOrWhiteSpace(link) == false)
.ToArray();
diff --git a/src/Umbraco.Infrastructure/Models/Property.cs b/src/Umbraco.Infrastructure/Models/Property.cs
index 36efbad404..798f84cf6f 100644
--- a/src/Umbraco.Infrastructure/Models/Property.cs
+++ b/src/Umbraco.Infrastructure/Models/Property.cs
@@ -98,7 +98,7 @@ namespace Umbraco.Core.Models
///
/// Represents a property value.
///
- public class PropertyValue : IPropertyValue
+ public class PropertyValue : IPropertyValue, IDeepCloneable, IEquatable
{
// TODO: Either we allow change tracking at this class level, or we add some special change tracking collections to the Property
// class to deal with change tracking which variants have changed
@@ -143,6 +143,32 @@ namespace Umbraco.Core.Models
///
public IPropertyValue Clone()
=> new PropertyValue { _culture = _culture, _segment = _segment, PublishedValue = PublishedValue, EditedValue = EditedValue };
+
+ public object DeepClone() => Clone();
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as PropertyValue);
+ }
+
+ public bool Equals(PropertyValue other)
+ {
+ return other != null &&
+ _culture == other._culture &&
+ _segment == other._segment &&
+ EqualityComparer