Merge branch 'netcore/dev' into netcore/feature/unit-test-project

This commit is contained in:
Bjarke Berg
2020-03-23 13:56:18 +01:00
142 changed files with 1812 additions and 562 deletions
+1 -1
View File
@@ -25,7 +25,7 @@
not want this to happen as the alpha of the next major is, really, the next major already.
-->
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="ClientDependency" version="[1.9.8,1.999999)" />
<dependency id="ClientDependency" version="[1.9.9,1.999999)" />
<dependency id="ClientDependency-Mvc5" version="[1.9.3,1.999999)" />
<dependency id="Examine" version="[1.0.2,1.999999)" />
<dependency id="HtmlAgilityPack" version="[1.8.14,1.999999)" />
@@ -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;
}
public Configs Create()
{
var configs = new Configs();
configs.Add<ITourSettings>(() => new TourSettings(_configuration));
configs.Add<ICoreDebugSettings>(() => new CoreDebugSettings(_configuration));
configs.Add<IRequestHandlerSettings>(() => new RequestHandlerSettings(_configuration));
configs.Add<ISecuritySettings>(() => new SecuritySettings(_configuration));
configs.Add<IUserPasswordConfiguration>(() => new UserPasswordConfigurationSettings(_configuration));
configs.Add<IMemberPasswordConfiguration>(() => new MemberPasswordConfigurationSettings(_configuration));
configs.Add<IKeepAliveSettings>(() => new KeepAliveSettings(_configuration));
configs.Add<IContentSettings>(() => new ContentSettings(_configuration));
configs.Add<IHealthChecksSettings>(() => new HealthChecksSettings(_configuration));
configs.Add<ILoggingSettings>(() => new LoggingSettings(_configuration));
configs.Add<IExceptionFilterSettings>(() => new ExceptionFilterSettings(_configuration));
configs.Add<IActiveDirectorySettings>(() => new ActiveDirectorySettings(_configuration));
configs.Add<IRuntimeSettings>(() => new RuntimeSettings(_configuration));
configs.Add<ITypeFinderSettings>(() => new TypeFinderSettings(_configuration));
configs.Add<INuCacheSettings>(() => new NuCacheSettings(_configuration));
configs.Add<IWebRoutingSettings>(() => new WebRoutingSettings(_configuration));
configs.Add<IIndexCreatorSettings>(() => new IndexCreatorSettings(_configuration));
configs.Add<IModelsBuilderConfig>(() => new ModelsBuilderConfig(_configuration));
configs.Add<IHostingSettings>(() => new HostingSettings(_configuration));
configs.Add<IGlobalSettings>(() => new GlobalSettings(_configuration));
configs.Add<IConnectionStrings>(() => new ConnectionStrings(_configuration));
configs.Add<IImagingSettings>(() => new ImagingSettings(_configuration));
return configs;
}
}
}
@@ -1,32 +0,0 @@
using System;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Configuration;
namespace Umbraco.Core.Configuration
{
/// <summary>
/// A case-insensitive configuration converter for enumerations.
/// </summary>
/// <typeparam name="T">The type of the enumeration.</typeparam>
public class CaseInsensitiveEnumConfigConverter<T> : 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<T>())));
}
}
}
+6 -7
View File
@@ -1,7 +1,8 @@
using Umbraco.Configuration;
using Umbraco.Configuration.Implementations;
using Umbraco.Configuration.Legacy;
using Umbraco.Core.Configuration.HealthChecks;
using Umbraco.Core.Configuration.Implementations;
using Umbraco.Core.Configuration.Legacy;
using Umbraco.Core.Configuration.UmbracoSettings;
namespace Umbraco.Core.Configuration
@@ -9,8 +10,7 @@ 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();
@@ -27,7 +27,7 @@ namespace Umbraco.Core.Configuration
public IMemberPasswordConfiguration MemberPasswordConfigurationSettings { get; } = new MemberPasswordConfigurationSettings();
public IContentSettings ContentSettings { get; } = new ContentSettings();
public IGlobalSettings GlobalSettings { get; } = new GlobalSettings();
public IHealthChecks HealthChecksSettings { get; } = new HealthChecksSettings();
public IHealthChecksSettings HealthChecksSettings { get; } = new HealthChecksSettings();
public IConnectionStrings ConnectionStrings { get; } = new ConnectionStrings();
public IModelsBuilderConfig ModelsBuilderConfig { get; } = new ModelsBuilderConfig();
@@ -37,9 +37,8 @@ namespace Umbraco.Core.Configuration
configs.Add<IGlobalSettings>(() => GlobalSettings);
configs.Add<IHostingSettings>(() => HostingSettings);
configs.Add<IHealthChecks>(() => HealthChecksSettings);
configs.Add<ICoreDebug>(() => CoreDebug);
configs.Add<IMachineKeyConfig>(() => MachineKeyConfig);
configs.Add<IHealthChecksSettings>(() => HealthChecksSettings);
configs.Add<ICoreDebugSettings>(() => CoreDebugSettings);
configs.Add<IConnectionStrings>(() => ConnectionStrings);
configs.Add<IModelsBuilderConfig>(() => ModelsBuilderConfig);
configs.Add<IIndexCreatorSettings>(() => IndexCreatorSettings);
@@ -1,7 +1,7 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
namespace Umbraco.Configuration.Legacy
{
public class ActiveDirectorySettings : IActiveDirectorySettings
{
@@ -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);
}
}
}
}
@@ -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);
@@ -1,7 +1,7 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
namespace Umbraco.Configuration.Legacy
{
public class ExceptionFilterSettings : IExceptionFilterSettings
{
@@ -7,56 +7,8 @@ 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;
/// <inheritdoc />
public LocalTempStorage LocalTempStorageLocation
{
get
{
var setting = ConfigurationManager.AppSettings[Constants.AppSettings.LocalTempStorage];
if (!string.IsNullOrWhiteSpace(setting))
return Enum<LocalTempStorage>.Parse(setting);
return LocalTempStorage.Default;
}
}
/// <summary>
/// Gets a value indicating whether umbraco is running in [debug mode].
/// </summary>
/// <value><c>true</c> if [debug mode]; otherwise, <c>false</c>.</value>
public 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
@@ -2,9 +2,9 @@
using System.Configuration;
using Umbraco.Core.Configuration.HealthChecks;
namespace Umbraco.Core.Configuration.Implementations
namespace Umbraco.Core.Configuration.Legacy
{
public class HealthChecksSettings : IHealthChecks
public class HealthChecksSettings : IHealthChecksSettings
{
private HealthChecksSection _healthChecksSection;
@@ -0,0 +1,52 @@
using System.Configuration;
namespace Umbraco.Core.Configuration.Legacy
{
public class HostingSettings : IHostingSettings
{
private bool? _debugMode;
/// <inheritdoc />
public LocalTempStorage LocalTempStorageLocation
{
get
{
var setting = ConfigurationManager.AppSettings[Constants.AppSettings.LocalTempStorage];
if (!string.IsNullOrWhiteSpace(setting))
return Enum<LocalTempStorage>.Parse(setting);
return LocalTempStorage.Default;
}
}
/// <summary>
/// Gets a value indicating whether umbraco is running in [debug mode].
/// </summary>
/// <value><c>true</c> if [debug mode]; otherwise, <c>false</c>.</value>
public 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();
}
}
}
}
@@ -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; }
@@ -6,7 +6,7 @@ using Umbraco.Core.Configuration;
using Umbraco.Core;
using Umbraco.Core.IO;
namespace Umbraco.Configuration
namespace Umbraco.Configuration.Legacy
{
/// <summary>
/// Represents the models builder configuration.
@@ -1,7 +1,7 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
namespace Umbraco.Configuration.Legacy
{
public class NuCacheSettings : INuCacheSettings
{
@@ -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; }
}
}
@@ -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
{
@@ -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);
}
}
}
}
@@ -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<string>(Prefix+"Domain");
}
}
@@ -0,0 +1,24 @@
using System;
using System.Linq;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration.Models
{
internal class ConnectionStrings : IConnectionStrings
{
private readonly IConfiguration _configuration;
public ConnectionStrings(IConfiguration configuration)
{
_configuration = configuration;
}
public ConfigConnectionString this[string key]
{
get => new ConfigConnectionString(_configuration.GetConnectionString(key), "System.Data.SqlClient", key);
set => throw new NotImplementedException();
}
}
}
@@ -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 =
@"<div id=""umbracoPreviewBadge"" class=""umbraco-preview-badge""><span class=""umbraco-preview-badge__header"">Preview mode</span><a href=""{0}/preview/end?redir={1}"" class=""umbraco-preview-badge__end""><svg viewBox=""0 0 100 100"" xmlns=""http://www.w3.org/2000/svg""><title>Click to end</title><path d=""M5273.1 2400.1v-2c0-2.8-5-4-9.7-4s-9.7 1.3-9.7 4v2a7 7 0 002 4.9l5 4.9c.3.3.4.6.4 1v6.4c0 .4.2.7.6.8l2.9.9c.5.1 1-.2 1-.8v-7.2c0-.4.2-.7.4-1l5.1-5a7 7 0 002-4.9zm-9.7-.1c-4.8 0-7.4-1.3-7.5-1.8.1-.5 2.7-1.8 7.5-1.8s7.3 1.3 7.5 1.8c-.2.5-2.7 1.8-7.5 1.8z""/><path d=""M5268.4 2410.3c-.6 0-1 .4-1 1s.4 1 1 1h4.3c.6 0 1-.4 1-1s-.4-1-1-1h-4.3zM5272.7 2413.7h-4.3c-.6 0-1 .4-1 1s.4 1 1 1h4.3c.6 0 1-.4 1-1s-.4-1-1-1zM5272.7 2417h-4.3c-.6 0-1 .4-1 1s.4 1 1 1h4.3c.6 0 1-.4 1-1 0-.5-.4-1-1-1z""/><path d=""M78.2 13l-8.7 11.7a32.5 32.5 0 11-51.9 25.8c0-10.3 4.7-19.7 12.9-25.8L21.8 13a47 47 0 1056.4 0z""/><path d=""M42.7 2.5h14.6v49.4H42.7z""/></svg></a></div><style type=""text/css"">.umbraco-preview-badge {{position: absolute;top: 1em;right: 1em;display: inline-flex;background: #1b264f;color: #fff;padding: 1em;font-size: 12px;z-index: 99999999;justify-content: center;align-items: center;box-shadow: 0 10px 50px rgba(0, 0, 0, .1), 0 6px 20px rgba(0, 0, 0, .16);line-height: 1;}}.umbraco-preview-badge__header {{font-weight: bold;}}.umbraco-preview-badge__end {{width: 3em;padding: 1em;margin: -1em -1em -1em 2em;display: flex;flex-shrink: 0;align-items: center;align-self: stretch;}}.umbraco-preview-badge__end:hover,.umbraco-preview-badge__end:focus {{background: #f5c1bc;}}.umbraco-preview-badge__end svg {{fill: #fff;width:1em;}}</style>";
private static readonly ImagingAutoFillUploadField[] DefaultImagingAutoFillUploadField =
{
new ImagingAutoFillUploadField
{
Alias = "umbracoFile"
}
};
private readonly IConfiguration _configuration;
public ContentSettings(IConfiguration configuration)
{
_configuration = configuration;
}
public string NotificationEmailAddress =>
_configuration.GetValue<string>(NotificationsPrefix+"Email");
public bool DisableHtmlEmail =>
_configuration.GetValue(NotificationsPrefix+"DisableHtmlEmail", false);
public IEnumerable<string> ImageFileTypes => _configuration.GetValue(
ImagingPrefix+"ImageFileTypes", new[] { "jpeg", "jpg", "gif", "bmp", "png", "tiff", "tif" });
public IEnumerable<IImagingAutoFillUploadField> ImageAutoFillProperties =>
_configuration.GetValue(ImagingPrefix+"AutoFillImageProperties",
DefaultImagingAutoFillUploadField);
public bool ResolveUrlsFromTextString =>
_configuration.GetValue(Prefix+"ResolveUrlsFromTextString", false);
public IEnumerable<IContentErrorPage> 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<string> DisallowedUploadFiles => _configuration.GetValue(
Prefix+"DisallowedUploadFiles",
new[] { "ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd" });
public IEnumerable<string> AllowedUploadFiles =>
_configuration.GetValue(Prefix+"AllowedUploadFiles", Array.Empty<string>());
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; }
}
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -0,0 +1,97 @@
using System;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Umbraco.Core;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration.Models
{
/// <summary>
/// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information
/// from web.config appsettings
/// </summary>
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<string>(Prefix + "Path");
// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings
public string ConfigurationStatus
{
get => _configuration.GetValue<string>(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<string>("From");
public string Host => _configurationSection.GetValue<string>("Host");
public int Port => _configurationSection.GetValue<int>("Port");
public string PickupDirectoryLocation => _configurationSection.GetValue<string>("PickupDirectoryLocation");
}
}
}
@@ -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<IDisabledHealthCheck> DisabledChecks => _configuration
.GetSection(Prefix+"DisabledChecks")
.GetChildren()
.Select(
x => new DisabledHealthCheck
{
Id = x.GetValue<Guid>("Id"),
DisabledOn = x.GetValue<DateTime>("DisabledOn"),
DisabledBy = x.GetValue<int>("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<string>("FirstRunTime");
public int PeriodInHours => _configurationSection.GetValue("PeriodInHours", 24);
public IReadOnlyDictionary<string, INotificationMethod> NotificationMethods => _configurationSection
.GetSection("NotificationMethods")
.GetChildren()
.ToDictionary(x => x.Key, x => (INotificationMethod) new NotificationMethod(x.Key, x));
public IEnumerable<IDisabledHealthCheck> DisabledChecks => _configurationSection
.GetSection("DisabledChecks").GetChildren().Select(
x => new DisabledHealthCheck
{
Id = x.GetValue<Guid>("Id"),
DisabledOn = x.GetValue<DateTime>("DisabledOn"),
DisabledBy = x.GetValue<int>("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<string, INotificationMethodSettings> 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; }
}
}
}
@@ -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;
}
/// <inheritdoc />
public LocalTempStorage LocalTempStorageLocation =>
_configuration.GetValue(Prefix+"LocalTempStorage", LocalTempStorage.Default);
/// <summary>
/// Gets a value indicating whether umbraco is running in [debug mode].
/// </summary>
/// <value><c>true</c> if [debug mode]; otherwise, <c>false</c>.</value>
public bool DebugMode => _configuration.GetValue(Prefix+":Debug", false);
}
}
@@ -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);
}
}
@@ -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<string>(Prefix + "LuceneDirectoryFactory");
}
}
@@ -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");
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -0,0 +1,86 @@
using Microsoft.Extensions.Configuration;
using Umbraco.Core;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration.Models
{
/// <summary>
/// Represents the models builder configuration.
/// </summary>
internal class ModelsBuilderConfig : IModelsBuilderConfig
{
private const string Prefix = Constants.Configuration.ConfigModelsBuilderPrefix;
private readonly IConfiguration _configuration;
/// <summary>
/// Initializes a new instance of the <see cref="ModelsBuilderConfig" /> class.
/// </summary>
public ModelsBuilderConfig(IConfiguration configuration)
{
_configuration = configuration;
}
public string DefaultModelsDirectory => "~/App_Data/Models";
/// <summary>
/// Gets a value indicating whether the whole models experience is enabled.
/// </summary>
/// <remarks>
/// <para>If this is false then absolutely nothing happens.</para>
/// <para>Default value is <c>false</c> which means that unless we have this setting, nothing happens.</para>
/// </remarks>
public bool Enable => _configuration.GetValue(Prefix+"Enable", false);
/// <summary>
/// Gets the models mode.
/// </summary>
public ModelsMode ModelsMode =>
_configuration.GetValue(Prefix+"ModelsMode", ModelsMode.Nothing);
/// <summary>
/// Gets the models namespace.
/// </summary>
/// <remarks>That value could be overriden by other (attribute in user's code...). Return default if no value was supplied.</remarks>
public string ModelsNamespace => _configuration.GetValue<string>(Prefix+"ModelsNamespace");
/// <summary>
/// Gets a value indicating whether we should enable the models factory.
/// </summary>
/// <remarks>Default value is <c>true</c> because no factory is enabled by default in Umbraco.</remarks>
public bool EnableFactory => _configuration.GetValue(Prefix+"EnableFactory", true);
/// <summary>
/// Gets a value indicating whether we should flag out-of-date models.
/// </summary>
/// <remarks>
/// 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 <c>false</c>.
/// </remarks>
public bool FlagOutOfDateModels =>
_configuration.GetValue(Prefix+"FlagOutOfDateModels", false) && !ModelsMode.IsLive();
/// <summary>
/// Gets the models directory.
/// </summary>
/// <remarks>Default is ~/App_Data/Models but that can be changed.</remarks>
public string ModelsDirectory =>
_configuration.GetValue(Prefix+"ModelsDirectory", "~/App_Data/Models");
/// <summary>
/// Gets a value indicating whether to accept an unsafe value for ModelsDirectory.
/// </summary>
/// <remarks>
/// An unsafe value is an absolute path, or a relative path pointing outside
/// of the website root.
/// </remarks>
public bool AcceptUnsafeModelsDirectory =>
_configuration.GetValue(Prefix+"AcceptUnsafeModelsDirectory", false);
/// <summary>
/// Gets a value indicating the debug log level.
/// </summary>
/// <remarks>0 means minimal (safe on live site), anything else means more and more details (maybe not safe).</remarks>
public int DebugLevel => _configuration.GetValue(Prefix+"DebugLevel", 0);
}
}
@@ -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<string>(Prefix+"BTreeBlockSize");
}
}
@@ -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<string>(Prefix+"ConvertUrlsToAscii").InvariantEquals("true");
public bool TryConvertUrlsToAscii => _configuration
.GetValue<string>(Prefix+"ConvertUrlsToAscii").InvariantEquals("try");
//We need to special handle ":", as this character is special in keys
public IEnumerable<IChar> CharCollection
{
get
{
var collection = _configuration.GetSection(Prefix + "CharCollection").GetChildren()
.Select(x => new CharItem()
{
Char = x.GetValue<string>("Char"),
Replacement = x.GetValue<string>("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; }
}
}
}
@@ -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<int?>(Prefix+"MaxRequestLength");
public int? MaxRequestLength => _configuration.GetValue<int?>(Prefix+"MaxRequestLength");
}
}
@@ -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<string>(Prefix + "AuthCookieDomain");
public bool UsernameIsEmail => _configuration.GetValue(Prefix + "UsernameIsEmail", true);
}
}
@@ -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);
}
}
@@ -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<string>(Prefix+"AssembliesAcceptingLoadExceptions");
}
}
@@ -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);
}
}
@@ -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<string>(Prefix + "UmbracoApplicationUrl");
}
}
@@ -22,6 +22,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.2" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.6.0" />
</ItemGroup>
@@ -1,33 +0,0 @@
using System.Configuration;
using Semver;
using Umbraco.Core;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
{
public static class UmbracoVersionExtensions
{
/// <summary>
/// Gets the "local" version of the site.
/// </summary>
/// <remarks>
/// <para>Three things have a version, really: the executing code, the database model,
/// and the site/files. The database model version is entirely managed via migrations,
/// and changes during an upgrade. The executing code version changes when new code is
/// deployed. The site/files version changes during an upgrade.</para>
/// </remarks>
public static SemVersion LocalVersion(this IUmbracoVersion umbracoVersion)
{
try
{
// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings
var value = ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus];
return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null;
}
catch
{
return null;
}
}
}
}
+3 -3
View File
@@ -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
}
/// <inheritdoc />
public void ClearOfType(string typeName)
public void ClearOfType(Type type)
{
InnerCache.ClearOfType(typeName);
InnerCache.ClearOfType(type);
}
/// <inheritdoc />
+3 -3
View File
@@ -71,16 +71,16 @@ namespace Umbraco.Core.Cache
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
public virtual void ClearOfType<T>()
{
var typeOfT = typeof(T);
_items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT);
ClearOfType(typeOfT);
}
/// <inheritdoc />
@@ -12,12 +12,6 @@ namespace Umbraco.Core.Cache
/// </summary>
public class FastDictionaryAppCache : IAppCache
{
private readonly ITypeFinder _typeFinder;
public FastDictionaryAppCache(ITypeFinder typeFinder)
{
_typeFinder = typeFinder ?? throw new ArgumentNullException(nameof(typeFinder));
}
/// <summary>
/// Gets the internal items dictionary, for tests only!
@@ -83,9 +77,8 @@ namespace Umbraco.Core.Cache
}
/// <inheritdoc />
public void ClearOfType(string typeName)
public void ClearOfType(Type type)
{
var type = _typeFinder.GetTypeByName(typeName);
if (type == null) return;
var isInterface = type.IsInterface;
@@ -12,13 +12,6 @@ namespace Umbraco.Core.Cache
/// </summary>
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
}
/// <inheritdoc />
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
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Cache
/// <summary>
/// Initializes a new instance of the <see cref="HttpRequestAppCache"/> class with a context, for unit tests!
/// </summary>
public HttpRequestAppCache(Func<IDictionary> requestItems, ITypeFinder typeFinder) : base(typeFinder)
public HttpRequestAppCache(Func<IDictionary> requestItems) : base()
{
ContextItems = requestItems;
}
+2 -2
View File
@@ -51,14 +51,14 @@ namespace Umbraco.Core.Cache
/// <summary>
/// Removes items of a specified type from the cache.
/// </summary>
/// <param name="typeName">The name of the type to remove.</param>
/// <param name="type">The type to remove.</param>
/// <remarks>
/// <para>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).</para>
/// <para>Performs a case-sensitive search.</para>
/// </remarks>
void ClearOfType(string typeName);
void ClearOfType(Type type);
/// <summary>
/// Removes items of a specified type from the cache.
+1 -1
View File
@@ -67,7 +67,7 @@ namespace Umbraco.Core.Cache
{ }
/// <inheritdoc />
public virtual void ClearOfType(string typeName)
public virtual void ClearOfType(Type type)
{ }
/// <inheritdoc />
@@ -13,15 +13,13 @@ namespace Umbraco.Core.Cache
/// </summary>
public class ObjectCacheAppCache : IAppPolicyCache
{
private readonly ITypeFinder _typeFinder;
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
/// <summary>
/// Initializes a new instance of the <see cref="ObjectCacheAppCache"/>.
/// </summary>
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
}
/// <inheritdoc />
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
@@ -10,6 +10,9 @@ namespace Umbraco.Core
/// </summary>
public static class ConfigsExtensions
{
public static IImagingSettings Imaging(this Configs configs)
=> configs.GetConfig<IImagingSettings>();
public static IGlobalSettings Global(this Configs configs)
=> configs.GetConfig<IGlobalSettings>();
@@ -37,10 +40,10 @@ namespace Umbraco.Core
public static IWebRoutingSettings WebRouting(this Configs configs)
=> configs.GetConfig<IWebRoutingSettings>();
public static IHealthChecks HealthChecks(this Configs configs)
=> configs.GetConfig<IHealthChecks>();
public static ICoreDebug CoreDebug(this Configs configs)
=> configs.GetConfig<ICoreDebug>();
public static IHealthChecksSettings HealthChecks(this Configs configs)
=> configs.GetConfig<IHealthChecksSettings>();
public static ICoreDebugSettings CoreDebug(this Configs configs)
=> configs.GetConfig<ICoreDebugSettings>();
}
}
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.HealthChecks
{
public interface IHealthChecks
public interface IHealthChecksSettings
{
IEnumerable<IDisabledHealthCheck> DisabledChecks { get; }
IHealthCheckNotificationSettings NotificationSettings { get; }
@@ -0,0 +1,10 @@
using Umbraco.Core.IO;
namespace Umbraco.Core.Configuration
{
public interface IConfigManipulator
{
void RemoveConnectionString();
void SaveConnectionString(string connectionString, string providerName);
}
}
@@ -1,5 +1,3 @@
using Umbraco.Core.IO;
namespace Umbraco.Core.Configuration
{
public interface IConnectionStrings
@@ -8,8 +6,5 @@ namespace Umbraco.Core.Configuration
{
get;
}
void RemoveConnectionString(string umbracoConnectionName, IIOHelper ioHelper);
void SaveConnectionString(string connectionString, string providerName, IIOHelper ioHelper);
}
}
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Configuration
{
public interface ICoreDebug
public interface ICoreDebugSettings
{
/// <summary>
/// When set to true, Scope logs the stack trace for any scope that gets disposed without being completed.
@@ -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; }
}
}
@@ -1,7 +0,0 @@
namespace Umbraco.Core.Configuration
{
public interface IMachineKeyConfig
{
bool HasMachineKey { get;}
}
}
@@ -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; }
@@ -6,13 +6,11 @@
/// </summary>
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
@@ -17,7 +17,6 @@ namespace Umbraco.Core.Configuration
RequireDigit = configSettings.RequireDigit;
RequireLowercase = configSettings.RequireLowercase;
RequireUppercase = configSettings.RequireUppercase;
UseLegacyEncoding = configSettings.UseLegacyEncoding;
HashAlgorithmType = configSettings.HashAlgorithmType;
MaxFailedAccessAttemptsBeforeLockout = configSettings.MaxFailedAccessAttemptsBeforeLockout;
}
@@ -32,8 +31,6 @@ namespace Umbraco.Core.Configuration
public bool RequireUppercase { get; }
public bool UseLegacyEncoding { get; }
public string HashAlgorithmType { get; }
public int MaxFailedAccessAttemptsBeforeLockout { get; }
@@ -9,22 +9,21 @@ using Umbraco.Core.Logging;
namespace Umbraco.Core.Configuration
{
public class ConnectionStrings : IConnectionStrings
public class XmlConfigManipulator : IConfigManipulator
{
private readonly IIOHelper _ioHelper;
private readonly ILogger _logger;
public ConfigConnectionString this[string key]
public XmlConfigManipulator(IIOHelper ioHelper, ILogger logger)
{
get
{
var settings = ConfigurationManager.ConnectionStrings[key];
if (settings == null) return null;
return new ConfigConnectionString(settings.ConnectionString, settings.ProviderName, settings.Name);
}
_ioHelper = ioHelper;
_logger = logger;
}
public void RemoveConnectionString(string key, IIOHelper ioHelper)
public void RemoveConnectionString()
{
var fileName = ioHelper.MapPath(string.Format("{0}/web.config", ioHelper.Root));
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();
@@ -36,26 +35,30 @@ namespace Umbraco.Core.Configuration
xml.Save(fileName, SaveOptions.DisableFormatting);
ConfigurationManager.RefreshSection("appSettings");
}
var settings = ConfigurationManager.ConnectionStrings[key];
}
/// <summary>
/// Saves the connection string as a proper .net connection string in web.config.
/// <summary>
/// Saves the connection string as a proper .net connection string in web.config.
/// </summary>
/// <remarks>Saves the ConnectionString in the very nasty 'medium trust'-supportive way.</remarks>
/// <param name="connectionString">The connection string.</param>
/// <param name="providerName">The provider name.</param>
public void SaveConnectionString(string connectionString, string providerName, IIOHelper ioHelper)
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 (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));
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 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).");
@@ -68,7 +71,7 @@ namespace Umbraco.Core.Configuration
if (configSourceAttribute != null)
{
fileSource = configSourceAttribute.Value;
fileName = ioHelper.MapPath(ioHelper.Root + "/" + fileSource);
fileName = _ioHelper.MapPath(_ioHelper.Root + "/" + fileSource);
if (!File.Exists(fileName))
throw new Exception($"Invalid configSource \"{fileSource}\" (no such file).");
@@ -77,11 +80,13 @@ namespace Umbraco.Core.Configuration
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).");
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);
var setting = connectionStrings.Descendants("add").FirstOrDefault(s =>
s.Attribute("name")?.Value == Constants.System.UmbracoConnectionName);
if (setting == null)
{
connectionStrings.Add(new XElement("add",
@@ -96,19 +101,18 @@ namespace Umbraco.Core.Configuration
}
// save
Current.Logger.Info<ConnectionStrings>("Saving connection string to {ConfigFile}.", fileSource);
_logger.Info<XmlConfigManipulator>("Saving connection string to {ConfigFile}.", fileSource);
xml.Save(fileName, SaveOptions.DisableFormatting);
Current.Logger.Info<ConnectionStrings>("Saved connection string to {ConfigFile}.", fileSource);
_logger.Info<XmlConfigManipulator>("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;
}
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;
}
}
}
@@ -0,0 +1,18 @@
namespace Umbraco.Core
{
public static partial class Constants
{
public static class Configuration
{
/// <summary>
/// Case insensitive prefix for all configurations
/// </summary>
/// <remarks>
/// ":" is used as marker for nested objects in json. E.g. "Umbraco:CMS:" = {"Umbraco":{"CMS":{....}}
/// </remarks>
public const string ConfigPrefix = "Umbraco:CMS:";
public const string ConfigSecurityPrefix = ConfigPrefix+"Security:";
public const string ConfigModelsBuilderPrefix = ConfigPrefix+"ModelsBuilder:";
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
namespace Umbraco.Core
 namespace Umbraco.Core
{
public static partial class Constants
{
@@ -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<JObject>(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");
}
/// <summary>
/// Returns the property value when case insensative
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
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;
}
}
}
@@ -20,7 +20,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods
private readonly IGlobalSettings _globalSettings;
private readonly IContentSettings _contentSettings;
public EmailNotificationMethod(ILocalizedTextService textService, IRuntimeState runtimeState, ILogger logger, IGlobalSettings globalSettings, IHealthChecks healthChecks, IContentSettings contentSettings) : 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))
@@ -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<HealthCheckNotificationMethodAttribute>();
@@ -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)
{
@@ -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<bool?>
{
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 : "";
/// <summary>
/// Don't display the view or execute if a machine key already exists
/// </summary>
/// <returns></returns>
private bool HasMachineKey()
{
return _machineKeyConfig.HasMachineKey;
}
/// <summary>
/// The step execution method
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public override Task<InstallSetupResult> ExecuteAsync(bool? model)
{
if (model.HasValue && model.Value == false) return Task.FromResult<InstallSetupResult>(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 <location> 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<InstallSetupResult>(null);
var generator = new MachineKeyGenerator();
var generatedSection = generator.GenerateConfigurationBlock();
systemWeb.Add(XElement.Parse(generatedSection));
xml.Save(fileName, SaveOptions.DisableFormatting);
return Task.FromResult<InstallSetupResult>(null);
}
public override bool RequiresExecution(bool? model)
{
return HasMachineKey() == false;
}
}
}
@@ -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<InstallSetupResult> 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<InstallSetupResult>(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, ioHelper);
configManipulator.RemoveConnectionString();
}
else
{
@@ -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<InstallSetupResult> 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<InstallSetupResult>(null);
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Logging.Serilog
///</summary>
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 <see cref="SerilogLogger"/> class with a configuration file.
/// </summary>
/// <param name="logConfigFile"></param>
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
/// </summary>
/// <remarks>Used by UmbracoApplicationBase to get its logger.</remarks>
public static SerilogLogger CreateWithDefaultConfiguration(IHostingEnvironment hostingEnvironment, ISessionIdResolver sessionIdResolver, Func<IRequestCache> requestCacheGetter, ICoreDebug coreDebug, IIOHelper ioHelper, IMarchal marchal)
public static SerilogLogger CreateWithDefaultConfiguration(IHostingEnvironment hostingEnvironment, ISessionIdResolver sessionIdResolver, Func<IRequestCache> 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);
}
/// <summary>
@@ -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);
@@ -28,7 +28,7 @@ namespace Umbraco.Core.Migrations.Install
private readonly IIOHelper _ioHelper;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator;
private readonly IConnectionStrings _connectionStrings;
private readonly IConfigManipulator _configManipulator;
private DatabaseSchemaResult _databaseSchemaValidationResult;
@@ -46,7 +46,7 @@ namespace Umbraco.Core.Migrations.Install
IIOHelper ioHelper,
IUmbracoVersion umbracoVersion,
IDbProviderFactoryCreator dbProviderFactoryCreator,
IConnectionStrings connectionStrings)
IConfigManipulator configManipulator)
{
_scopeProvider = scopeProvider;
_globalSettings = globalSettings;
@@ -58,7 +58,7 @@ namespace Umbraco.Core.Migrations.Install
_ioHelper = ioHelper;
_umbracoVersion = umbracoVersion;
_dbProviderFactoryCreator = dbProviderFactoryCreator;
_connectionStrings = connectionStrings;
_configManipulator = configManipulator;
}
#region Status
@@ -146,7 +146,7 @@ namespace Umbraco.Core.Migrations.Install
private void ConfigureEmbeddedDatabaseConnection(IUmbracoDatabaseFactory factory, IIOHelper ioHelper)
{
_connectionStrings.SaveConnectionString(EmbeddedDatabaseConnectionString, Constants.DbProviderNames.SqlCe, ioHelper);
_configManipulator.SaveConnectionString(EmbeddedDatabaseConnectionString, Constants.DbProviderNames.SqlCe);
var path = Path.Combine(ioHelper.GetRootDirectorySafe(), "App_Data", "Umbraco.sdf");
if (File.Exists(path) == false)
@@ -169,7 +169,7 @@ namespace Umbraco.Core.Migrations.Install
{
const string providerName = Constants.DbProviderNames.SqlServer;
_connectionStrings.SaveConnectionString(connectionString, providerName, _ioHelper);
_configManipulator.SaveConnectionString(connectionString, providerName);
_databaseFactory.Configure(connectionString, providerName);
}
@@ -185,7 +185,7 @@ namespace Umbraco.Core.Migrations.Install
{
var connectionString = GetDatabaseConnectionString(server, databaseName, user, password, databaseProvider, out var providerName);
_connectionStrings.SaveConnectionString(connectionString, providerName, _ioHelper);
_configManipulator.SaveConnectionString(connectionString, providerName);
_databaseFactory.Configure(connectionString, providerName);
}
@@ -216,7 +216,7 @@ namespace Umbraco.Core.Migrations.Install
public void ConfigureIntegratedSecurityDatabaseConnection(string server, string databaseName)
{
var connectionString = GetIntegratedSecurityDatabaseConnectionString(server, databaseName);
_connectionStrings.SaveConnectionString(connectionString, Constants.DbProviderNames.SqlServer, _ioHelper);
_configManipulator.SaveConnectionString(connectionString, Constants.DbProviderNames.SqlServer);
_databaseFactory.Configure(connectionString, Constants.DbProviderNames.SqlServer);
}
+35 -1
View File
@@ -98,7 +98,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Represents a property value.
/// </summary>
public class PropertyValue : IPropertyValue
public class PropertyValue : IPropertyValue, IEquatable<PropertyValue>
{
// 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,27 @@ namespace Umbraco.Core.Models
/// </summary>
public IPropertyValue Clone()
=> new PropertyValue { _culture = _culture, _segment = _segment, PublishedValue = PublishedValue, EditedValue = EditedValue };
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;
}
public override int GetHashCode()
{
var hashCode = -1254204277;
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(_culture);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(_segment);
return hashCode;
}
}
private static readonly DelegateEqualityComparer<object> PropertyValueComparer = new DelegateEqualityComparer<object>(
@@ -508,6 +529,19 @@ namespace Umbraco.Core.Models
var clonedEntity = (Property)clone;
//manually clone _values, _pvalue, _vvalues
clonedEntity._values = _values?.Select(x => x.Clone()).ToList(); // all values get copied
clonedEntity._pvalue = _pvalue?.Clone();
// the tricky part here is that _values contains ALL values including the values in the _vvalues
// dictionary and they are by reference which is why we have equality overloads on PropertyValue
if (clonedEntity._vvalues != null)
{
clonedEntity._vvalues = new Dictionary<CompositeNStringNStringKey, IPropertyValue>();
foreach (var item in _vvalues)
{
clonedEntity._vvalues[item.Key] = clonedEntity._values.First(x => x.Equals(item.Value));
}
}
//need to manually assign since this is a readonly property
clonedEntity.PropertyType = (PropertyType) PropertyType.DeepClone();
}
@@ -175,6 +175,7 @@ namespace Umbraco.Core.Runtime
// Grid config is not a real config file as we know them
composition.RegisterUnique<IGridConfig, GridConfig>();
}
}
}
@@ -403,9 +403,9 @@ namespace Umbraco.Core.Runtime
// is overridden by the web runtime
return new AppCaches(
new DeepCloneAppCache(new ObjectCacheAppCache(TypeFinder)),
new DeepCloneAppCache(new ObjectCacheAppCache()),
NoAppCache.Instance,
new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache(TypeFinder))));
new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache())));
}
// by default, returns null, meaning that Umbraco should auto-detect the application root path.
@@ -1,6 +1,4 @@
using System.Web;
using Umbraco.Configuration;
using Umbraco.Core;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
@@ -9,9 +7,6 @@ using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Runtime;
using Umbraco.Web.Composing;
using Umbraco.Web.Logging;
using Current = Umbraco.Web.Composing.Current;
namespace Umbraco.Web.Runtime
{
@@ -21,6 +16,8 @@ namespace Umbraco.Web.Runtime
/// <remarks>On top of CoreRuntime, handles all of the web-related runtime aspects of Umbraco.</remarks>
public class WebRuntime : CoreRuntime
{
private readonly IRequestCache _requestCache;
/// <summary>
/// Initializes a new instance of the <see cref="WebRuntime"/> class.
/// </summary>
@@ -33,27 +30,12 @@ namespace Umbraco.Web.Runtime
IHostingEnvironment hostingEnvironment,
IBackOfficeInfo backOfficeInfo,
IDbProviderFactoryCreator dbProviderFactoryCreator,
IMainDom mainDom):
base(configs, umbracoVersion, ioHelper, logger, profiler ,new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom)
IMainDom mainDom,
IRequestCache requestCache,
IUmbracoBootPermissionChecker umbracoBootPermissionChecker):
base(configs, umbracoVersion, ioHelper, logger, profiler ,umbracoBootPermissionChecker, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom)
{
Profiler = GetWebProfiler();
}
private IProfiler GetWebProfiler()
{
// create and start asap to profile boot
if (!State.Debug)
{
// should let it be null, that's how MiniProfiler is meant to work,
// but our own IProfiler expects an instance so let's get one
return new VoidProfiler();
}
var webProfiler = new WebProfiler();
webProfiler.Start();
return webProfiler;
_requestCache = requestCache;
}
/// <inheritdoc/>
@@ -74,7 +56,7 @@ namespace Umbraco.Web.Runtime
NetworkHelper.MachineName);
Logger.Debug<CoreRuntime>("Runtime: {Runtime}", GetType().FullName);
var factory = Current.Factory = base.Boot(register);
var factory = base.Boot(register);
// now (and only now) is the time to switch over to perWebRequest scopes.
// up until that point we may not have a request, and scoped services would
@@ -93,13 +75,13 @@ namespace Umbraco.Web.Runtime
protected override AppCaches GetAppCaches() => new AppCaches(
// we need to have the dep clone runtime cache provider to ensure
// all entities are cached properly (cloned in and cloned out)
new DeepCloneAppCache(new ObjectCacheAppCache(TypeFinder)),
new DeepCloneAppCache(new ObjectCacheAppCache()),
// we need request based cache when running in web-based context
new HttpRequestAppCache(() => HttpContext.Current?.Items, TypeFinder),
_requestCache,
new IsolatedCaches(type =>
// we need to have the dep clone runtime cache provider to ensure
// all entities are cached properly (cloned in and cloned out)
new DeepCloneAppCache(new ObjectCacheAppCache(TypeFinder))));
new DeepCloneAppCache(new ObjectCacheAppCache())));
#endregion
}
@@ -15,18 +15,18 @@ namespace Umbraco.Web.Scheduling
private readonly HealthCheckCollection _healthChecks;
private readonly HealthCheckNotificationMethodCollection _notifications;
private readonly IProfilingLogger _logger;
private readonly IHealthChecks _healthChecksConfig;
private readonly IHealthChecksSettings _healthChecksSettingsConfig;
public HealthCheckNotifier(IBackgroundTaskRunner<RecurringTaskBase> runner, int delayMilliseconds, int periodMilliseconds,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IRuntimeState runtimeState, IProfilingLogger logger, IHealthChecks healthChecksConfig)
IRuntimeState runtimeState, IProfilingLogger logger, IHealthChecksSettings healthChecksSettingsConfig)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_healthChecks = healthChecks;
_notifications = notifications;
_runtimeState = runtimeState;
_logger = logger;
_healthChecksConfig = healthChecksConfig;
_healthChecksSettingsConfig = healthChecksSettingsConfig;
}
public override async Task<bool> PerformRunAsync(CancellationToken token)
@@ -53,7 +53,7 @@ namespace Umbraco.Web.Scheduling
using (_logger.DebugDuration<HealthCheckNotifier>("Health checks executing", "Health checks complete"))
{
var healthCheckConfig = _healthChecksConfig;
var healthCheckConfig = _healthChecksSettingsConfig;
// Don't notify for any checks that are disabled, nor for any disabled
// just for notifications
@@ -34,7 +34,7 @@ namespace Umbraco.Web.Scheduling
private readonly HealthCheckCollection _healthChecks;
private readonly HealthCheckNotificationMethodCollection _notifications;
private readonly IUmbracoContextFactory _umbracoContextFactory;
private readonly IHealthChecks _healthChecksConfig;
private readonly IHealthChecksSettings _healthChecksSettingsConfig;
private readonly IIOHelper _ioHelper;
private readonly IServerMessenger _serverMessenger;
private readonly IRequestAccessor _requestAccessor;
@@ -56,7 +56,7 @@ namespace Umbraco.Web.Scheduling
IContentService contentService, IAuditService auditService,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger,
IHostingEnvironment hostingEnvironment, IHealthChecks healthChecksConfig,
IHostingEnvironment hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig,
IIOHelper ioHelper, IServerMessenger serverMessenger, IRequestAccessor requestAccessor,
ILoggingSettings loggingSettings, IKeepAliveSettings keepAliveSettings)
{
@@ -70,7 +70,7 @@ namespace Umbraco.Web.Scheduling
_healthChecks = healthChecks;
_notifications = notifications;
_healthChecksConfig = healthChecksConfig ?? throw new ArgumentNullException(nameof(healthChecksConfig));
_healthChecksSettingsConfig = healthChecksSettingsConfig ?? throw new ArgumentNullException(nameof(healthChecksSettingsConfig));
_ioHelper = ioHelper;
_serverMessenger = serverMessenger;
_requestAccessor = requestAccessor;
@@ -126,7 +126,7 @@ namespace Umbraco.Web.Scheduling
tasks.Add(RegisterLogScrubber(_loggingSettings));
tasks.Add(RegisterTempFileCleanup());
var healthCheckConfig = _healthChecksConfig;
var healthCheckConfig = _healthChecksSettingsConfig;
if (healthCheckConfig.NotificationSettings.Enabled)
tasks.Add(RegisterHealthCheckNotifier(healthCheckConfig, _healthChecks, _notifications, _logger));
@@ -152,28 +152,28 @@ namespace Umbraco.Web.Scheduling
return task;
}
private IBackgroundTask RegisterHealthCheckNotifier(IHealthChecks healthCheckConfig,
private IBackgroundTask RegisterHealthCheckNotifier(IHealthChecksSettings healthCheckSettingsConfig,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IProfilingLogger logger)
{
// If first run time not set, start with just small delay after application start
int delayInMilliseconds;
if (string.IsNullOrEmpty(healthCheckConfig.NotificationSettings.FirstRunTime))
if (string.IsNullOrEmpty(healthCheckSettingsConfig.NotificationSettings.FirstRunTime))
{
delayInMilliseconds = DefaultDelayMilliseconds;
}
else
{
// Otherwise start at scheduled time
delayInMilliseconds = DateTime.Now.PeriodicMinutesFrom(healthCheckConfig.NotificationSettings.FirstRunTime) * 60 * 1000;
delayInMilliseconds = DateTime.Now.PeriodicMinutesFrom(healthCheckSettingsConfig.NotificationSettings.FirstRunTime) * 60 * 1000;
if (delayInMilliseconds < DefaultDelayMilliseconds)
{
delayInMilliseconds = DefaultDelayMilliseconds;
}
}
var periodInMilliseconds = healthCheckConfig.NotificationSettings.PeriodInHours * 60 * 60 * 1000;
var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _runtime, logger, _healthChecksConfig);
var periodInMilliseconds = healthCheckSettingsConfig.NotificationSettings.PeriodInHours * 60 * 60 * 1000;
var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _runtime, logger, _healthChecksSettingsConfig);
_healthCheckRunner.TryAdd(task);
return task;
}
+10 -10
View File
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Scoping
internal class Scope : IScope
{
private readonly ScopeProvider _scopeProvider;
private readonly ICoreDebug _coreDebug;
private readonly ICoreDebugSettings _coreDebugSettings;
private readonly IMediaFileSystem _mediaFileSystem;
private readonly ILogger _logger;
private readonly ITypeFinder _typeFinder;
@@ -39,7 +39,7 @@ namespace Umbraco.Core.Scoping
// initializes a new scope
private Scope(ScopeProvider scopeProvider,
ICoreDebug coreDebug,
ICoreDebugSettings coreDebugSettings,
IMediaFileSystem mediaFileSystem,
ILogger logger, ITypeFinder typeFinder, FileSystems fileSystems, Scope parent, IScopeContext scopeContext, bool detachable,
IsolationLevel isolationLevel = IsolationLevel.Unspecified,
@@ -50,7 +50,7 @@ namespace Umbraco.Core.Scoping
bool autoComplete = false)
{
_scopeProvider = scopeProvider;
_coreDebug = coreDebug;
_coreDebugSettings = coreDebugSettings;
_mediaFileSystem = mediaFileSystem;
_logger = logger;
_typeFinder = typeFinder;
@@ -118,7 +118,7 @@ namespace Umbraco.Core.Scoping
// initializes a new scope
public Scope(ScopeProvider scopeProvider,
ICoreDebug coreDebug,
ICoreDebugSettings coreDebugSettings,
IMediaFileSystem mediaFileSystem,
ILogger logger, ITypeFinder typeFinder, FileSystems fileSystems, bool detachable, IScopeContext scopeContext,
IsolationLevel isolationLevel = IsolationLevel.Unspecified,
@@ -127,12 +127,12 @@ namespace Umbraco.Core.Scoping
bool? scopeFileSystems = null,
bool callContext = false,
bool autoComplete = false)
: this(scopeProvider, coreDebug, mediaFileSystem, logger, typeFinder, fileSystems, null, scopeContext, detachable, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete)
: this(scopeProvider, coreDebugSettings, mediaFileSystem, logger, typeFinder, fileSystems, null, scopeContext, detachable, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete)
{ }
// initializes a new scope in a nested scopes chain, with its parent
public Scope(ScopeProvider scopeProvider,
ICoreDebug coreDebug,
ICoreDebugSettings coreDebugSettings,
IMediaFileSystem mediaFileSystem,
ILogger logger, ITypeFinder typeFinder, FileSystems fileSystems, Scope parent,
IsolationLevel isolationLevel = IsolationLevel.Unspecified,
@@ -141,7 +141,7 @@ namespace Umbraco.Core.Scoping
bool? scopeFileSystems = null,
bool callContext = false,
bool autoComplete = false)
: this(scopeProvider, coreDebug, mediaFileSystem, logger, typeFinder, fileSystems, parent, null, false, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete)
: this(scopeProvider, coreDebugSettings, mediaFileSystem, logger, typeFinder, fileSystems, parent, null, false, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete)
{ }
public Guid InstanceId { get; } = Guid.NewGuid();
@@ -188,7 +188,7 @@ namespace Umbraco.Core.Scoping
if (ParentScope != null) return ParentScope.IsolatedCaches;
return _isolatedCaches ?? (_isolatedCaches
= new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache(_typeFinder))));
= new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache())));
}
}
@@ -494,9 +494,9 @@ namespace Umbraco.Core.Scoping
private static bool? _logUncompletedScopes;
// caching config
// true if Umbraco.CoreDebug.LogUncompletedScope appSetting is set to "true"
// true if Umbraco.CoreDebugSettings.LogUncompletedScope appSetting is set to "true"
private bool LogUncompletedScopes => (_logUncompletedScopes
?? (_logUncompletedScopes = _coreDebug.LogUncompletedScopes)).Value;
?? (_logUncompletedScopes = _coreDebugSettings.LogUncompletedScopes)).Value;
/// <inheritdoc />
public void ReadLock(params int[] lockIds) => Database.SqlContext.SqlSyntax.ReadLock(Database, lockIds);
@@ -26,14 +26,14 @@ namespace Umbraco.Core.Scoping
private readonly ITypeFinder _typeFinder;
private readonly IRequestCache _requestCache;
private readonly FileSystems _fileSystems;
private readonly ICoreDebug _coreDebug;
private readonly ICoreDebugSettings _coreDebugSettings;
private readonly IMediaFileSystem _mediaFileSystem;
public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, ICoreDebug coreDebug, IMediaFileSystem mediaFileSystem, ILogger logger, ITypeFinder typeFinder, IRequestCache requestCache)
public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, ICoreDebugSettings coreDebugSettings, IMediaFileSystem mediaFileSystem, ILogger logger, ITypeFinder typeFinder, IRequestCache requestCache)
{
DatabaseFactory = databaseFactory;
_fileSystems = fileSystems;
_coreDebug = coreDebug;
_coreDebugSettings = coreDebugSettings;
_mediaFileSystem = mediaFileSystem;
_logger = logger;
_typeFinder = typeFinder;
@@ -255,7 +255,7 @@ namespace Umbraco.Core.Scoping
IEventDispatcher eventDispatcher = null,
bool? scopeFileSystems = null)
{
return new Scope(this, _coreDebug, _mediaFileSystem, _logger, _typeFinder, _fileSystems, true, null, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems);
return new Scope(this, _coreDebugSettings, _mediaFileSystem, _logger, _typeFinder, _fileSystems, true, null, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems);
}
/// <inheritdoc />
@@ -311,13 +311,13 @@ namespace Umbraco.Core.Scoping
{
var ambientContext = AmbientContext;
var newContext = ambientContext == null ? new ScopeContext() : null;
var scope = new Scope(this, _coreDebug, _mediaFileSystem, _logger, _typeFinder, _fileSystems, false, newContext, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete);
var scope = new Scope(this, _coreDebugSettings, _mediaFileSystem, _logger, _typeFinder, _fileSystems, false, newContext, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete);
// assign only if scope creation did not throw!
SetAmbient(scope, newContext ?? ambientContext);
return scope;
}
var nested = new Scope(this, _coreDebug, _mediaFileSystem, _logger, _typeFinder, _fileSystems, ambientScope, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete);
var nested = new Scope(this, _coreDebugSettings, _mediaFileSystem, _logger, _typeFinder, _fileSystems, ambientScope, isolationLevel, repositoryCacheMode, eventDispatcher, scopeFileSystems, callContext, autoComplete);
SetAmbient(nested, AmbientContext);
return nested;
}
@@ -11,6 +11,8 @@
<PackageReference Include="LightInject.Annotation" Version="1.1.0" />
<PackageReference Include="Markdown" Version="2.2.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.2" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" />
<PackageReference Include="MiniProfiler.Shared" Version="4.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
@@ -49,7 +49,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
private readonly IPublishedModelFactory _publishedModelFactory;
private readonly IDefaultCultureAccessor _defaultCultureAccessor;
private readonly UrlSegmentProviderCollection _urlSegmentProviders;
private readonly ITypeFinder _typeFinder;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IShortStringHelper _shortStringHelper;
private readonly IIOHelper _ioHelper;
@@ -88,7 +87,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
IEntityXmlSerializer entitySerializer,
IPublishedModelFactory publishedModelFactory,
UrlSegmentProviderCollection urlSegmentProviders,
ITypeFinder typeFinder,
IHostingEnvironment hostingEnvironment,
IShortStringHelper shortStringHelper,
IIOHelper ioHelper,
@@ -109,7 +107,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
_defaultCultureAccessor = defaultCultureAccessor;
_globalSettings = globalSettings;
_urlSegmentProviders = urlSegmentProviders;
_typeFinder = typeFinder;
_hostingEnvironment = hostingEnvironment;
_shortStringHelper = shortStringHelper;
_ioHelper = ioHelper;
@@ -1207,7 +1204,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
_contentGen = contentSnap.Gen;
_mediaGen = mediaSnap.Gen;
_domainGen = domainSnap.Gen;
elementsCache = _elementsCache = new FastDictionaryAppCache(_typeFinder);
elementsCache = _elementsCache = new FastDictionaryAppCache();
}
}
@@ -2,6 +2,7 @@
using Semver;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Legacy;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Models.PublishedContent;
+1 -1
View File
@@ -93,7 +93,7 @@ namespace Umbraco.Tests.Common
public abstract IDbProviderFactoryCreator DbProviderFactoryCreator { get; }
public abstract IBulkSqlInsertProvider BulkSqlInsertProvider { get; }
public abstract IMarchal Marchal { get; }
public ICoreDebug CoreDebug { get; } = new CoreDebug();
public ICoreDebugSettings CoreDebugSettings { get; } = new CoreDebugSettings();
public IIOHelper IOHelper { get; }
+1 -1
View File
@@ -229,7 +229,7 @@ namespace Umbraco.Tests.Cache
Assert.AreEqual(4, GetTotalItemCount);
//Provider.ClearCacheObjectTypes("umbraco.MacroCacheContent");
AppCache.ClearOfType(typeof(MacroCacheContent).ToString());
AppCache.ClearOfType<MacroCacheContent>();
Assert.AreEqual(1, GetTotalItemCount);
}

Some files were not shown because too many files have changed in this diff Show More