Merge branch 'netcore/dev' into netcore/feature/users
This commit is contained in:
@@ -43,6 +43,8 @@ If you only see a build.bat-file, you're probably on the wrong branch. If you sw
|
||||
|
||||
You might run into [Powershell quirks](#powershell-quirks).
|
||||
|
||||
If it runs without errors; Hooray! Now you can continue with [the next step](CONTRIBUTING.md#how-do-i-begin) and open the solution and build it.
|
||||
|
||||
### Build Infrastructure
|
||||
|
||||
The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with:
|
||||
|
||||
@@ -28,7 +28,7 @@ This project and everyone participating in it, is governed by the [our Code of C
|
||||
[Working with the code](#working-with-the-code)
|
||||
* [Building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* [Working with the source code](#working-with-the-source-code)
|
||||
* [Making changes after the PR was opened](#making-changes-after-the-pr-was-opened)
|
||||
* [Making changes after the PR is open](#making-changes-after-the-pr-is-open)
|
||||
* [Which branch should I target for my contributions?](#which-branch-should-i-target-for-my-contributions)
|
||||
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
|
||||
|
||||
@@ -65,7 +65,7 @@ Great question! The short version goes like this:
|
||||
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will [happily give feedback](#questions)
|
||||
* **Commit** - done? Yay! 🎉 **Important:** create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `12345`. When you have a branch, commit your changes. Don't commit to `v8/contrib`, create a new branch first.
|
||||
* **Push** - great, now you can push the changes up to your fork on GitHub
|
||||
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress - you can now make use of GitHub's draft pull request status, detailed [here] (https://github.blog/2019-02-14-introducing-draft-pull-requests/)). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
|
||||
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress - you can now make use of GitHub's draft pull request status, detailed [here](https://github.blog/2019-02-14-introducing-draft-pull-requests/)). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
|
||||
|
||||

|
||||
|
||||
|
||||
+12
@@ -100,6 +100,9 @@ src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/canvasdesigner.*.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/navigation.controller.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.controller.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/utilities.js
|
||||
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
|
||||
@@ -164,3 +167,12 @@ build/temp/
|
||||
# eof
|
||||
/src/Umbraco.Web.UI.Client/TESTS-*.xml
|
||||
/src/ApiDocs/api/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Media/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/is-cache/*
|
||||
/src/Umbraco.Tests.Integration/App_Data/*
|
||||
/src/Umbraco.Tests.Integration/TEMP/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/assets/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/js/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/lib/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/views/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/App_Data/TEMP/*
|
||||
|
||||
@@ -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)" />
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
# get NuGet
|
||||
$cache = 4
|
||||
$nuget = "$scriptTemp\nuget.exe"
|
||||
# ensure the correct NuGet-source is used. This one is used by Umbraco
|
||||
$nugetsourceUmbraco = "https://www.myget.org/F/umbracocore/api/v3/index.json"
|
||||
if (-not $local)
|
||||
{
|
||||
$source = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
||||
@@ -61,7 +63,7 @@
|
||||
# get the build system
|
||||
if (-not $local)
|
||||
{
|
||||
$params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease"
|
||||
$params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease", "-Source", $nugetsourceUmbraco
|
||||
&$nuget install Umbraco.Build @params
|
||||
if (-not $?) { throw "Failed to download Umbraco.Build." }
|
||||
}
|
||||
|
||||
+4
-1
@@ -375,11 +375,14 @@
|
||||
|
||||
})
|
||||
|
||||
$nugetsourceUmbraco = "https://api.nuget.org/v3/index.json"
|
||||
|
||||
$ubuild.DefineMethod("RestoreNuGet",
|
||||
{
|
||||
Write-Host "Restore NuGet"
|
||||
Write-Host "Logging to $($this.BuildTemp)\nuget.restore.log"
|
||||
&$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log"
|
||||
$params = "-Source", $nugetsourceUmbraco
|
||||
&$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log" @params
|
||||
if (-not $?) { throw "Failed to restore NuGet packages." }
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Configuration.Models;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using ConnectionStrings = Umbraco.Configuration.Models.ConnectionStrings;
|
||||
using CoreDebugSettings = Umbraco.Configuration.Models.CoreDebugSettings;
|
||||
|
||||
namespace Umbraco.Configuration
|
||||
{
|
||||
public class AspNetCoreConfigsFactory : IConfigsFactory
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public AspNetCoreConfigsFactory(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration ?? throw new System.ArgumentNullException(nameof(configuration));
|
||||
}
|
||||
|
||||
public Configs Create()
|
||||
{
|
||||
var configs = new Configs();
|
||||
|
||||
configs.Add<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>())));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,62 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Configuration;
|
||||
using Umbraco.Configuration.Implementations;
|
||||
using Umbraco.Configuration.Legacy;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
using Umbraco.Core.Configuration.Legacy;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class ConfigsFactory : IConfigsFactory
|
||||
{
|
||||
public IHostingSettings HostingSettings { get; } = new HostingSettings();
|
||||
public ICoreDebugSettings CoreDebugSettings { get; } = new CoreDebugSettings();
|
||||
public IIndexCreatorSettings IndexCreatorSettings { get; } = new IndexCreatorSettings();
|
||||
public INuCacheSettings NuCacheSettings { get; } = new NuCacheSettings();
|
||||
public ITypeFinderSettings TypeFinderSettings { get; } = new TypeFinderSettings();
|
||||
public IRuntimeSettings RuntimeSettings { get; } = new RuntimeSettings();
|
||||
public IActiveDirectorySettings ActiveDirectorySettings { get; } = new ActiveDirectorySettings();
|
||||
public IExceptionFilterSettings ExceptionFilterSettings { get; } = new ExceptionFilterSettings();
|
||||
public ITourSettings TourSettings { get; } = new TourSettings();
|
||||
public ILoggingSettings LoggingSettings { get; } = new LoggingSettings();
|
||||
public IKeepAliveSettings KeepAliveSettings { get; } = new KeepAliveSettings();
|
||||
public IWebRoutingSettings WebRoutingSettings { get; } = new WebRoutingSettings();
|
||||
public IRequestHandlerSettings RequestHandlerSettings { get; } = new RequestHandlerSettings();
|
||||
public ISecuritySettings SecuritySettings { get; } = new SecuritySettings();
|
||||
public IUserPasswordConfiguration UserPasswordConfigurationSettings { get; } = new UserPasswordConfigurationSettings();
|
||||
public IMemberPasswordConfiguration MemberPasswordConfigurationSettings { get; } = new MemberPasswordConfigurationSettings();
|
||||
public IContentSettings ContentSettings { get; } = new ContentSettings();
|
||||
public IGlobalSettings GlobalSettings { get; } = new GlobalSettings();
|
||||
public IHealthChecksSettings HealthChecksSettings { get; } = new HealthChecksSettings();
|
||||
public IConnectionStrings ConnectionStrings { get; } = new ConnectionStrings();
|
||||
public IModelsBuilderConfig ModelsBuilderConfig { get; } = new ModelsBuilderConfig();
|
||||
|
||||
public ICoreDebug CoreDebug { get; } = new CoreDebug();
|
||||
|
||||
public IUmbracoSettingsSection UmbracoSettings { get; }
|
||||
|
||||
public Configs Create(IIOHelper ioHelper)
|
||||
public Configs Create()
|
||||
{
|
||||
var configs = new Configs(section => ConfigurationManager.GetSection(section));
|
||||
configs.Add<IGlobalSettings>(() => new GlobalSettings(ioHelper));
|
||||
configs.Add(() => HostingSettings);
|
||||
var configs = new Configs();
|
||||
|
||||
configs.Add<IUmbracoSettingsSection>("umbracoConfiguration/settings");
|
||||
configs.Add<IHealthChecks>("umbracoConfiguration/HealthChecks");
|
||||
configs.Add<IGlobalSettings>(() => GlobalSettings);
|
||||
configs.Add<IHostingSettings>(() => HostingSettings);
|
||||
configs.Add<IHealthChecksSettings>(() => HealthChecksSettings);
|
||||
configs.Add<ICoreDebugSettings>(() => CoreDebugSettings);
|
||||
configs.Add<IConnectionStrings>(() => ConnectionStrings);
|
||||
configs.Add<IModelsBuilderConfig>(() => ModelsBuilderConfig);
|
||||
configs.Add<IIndexCreatorSettings>(() => IndexCreatorSettings);
|
||||
configs.Add<INuCacheSettings>(() => NuCacheSettings);
|
||||
configs.Add<ITypeFinderSettings>(() => TypeFinderSettings);
|
||||
configs.Add<IRuntimeSettings>(() => RuntimeSettings);
|
||||
configs.Add<IActiveDirectorySettings>(() => ActiveDirectorySettings);
|
||||
configs.Add<IExceptionFilterSettings>(() => ExceptionFilterSettings);
|
||||
configs.Add<ITourSettings>(() => TourSettings);
|
||||
configs.Add<ILoggingSettings>(() => LoggingSettings);
|
||||
configs.Add<IKeepAliveSettings>(() => KeepAliveSettings);
|
||||
configs.Add<IWebRoutingSettings>(() => WebRoutingSettings);
|
||||
configs.Add<IRequestHandlerSettings>(() => RequestHandlerSettings);
|
||||
configs.Add<ISecuritySettings>(() => SecuritySettings);
|
||||
configs.Add<IUserPasswordConfiguration>(() => UserPasswordConfigurationSettings);
|
||||
configs.Add<IMemberPasswordConfiguration>(() => MemberPasswordConfigurationSettings);
|
||||
configs.Add<IContentSettings>(() => ContentSettings);
|
||||
|
||||
// Password configuration is held within IUmbracoSettingsSection from umbracoConfiguration/settings but we'll add explicitly
|
||||
// so it can be independently retrieved in classes that need it.
|
||||
configs.AddPasswordConfigurations();
|
||||
|
||||
configs.Add(() => CoreDebug);
|
||||
configs.Add<IConnectionStrings>(() => new ConnectionStrings(ioHelper));
|
||||
configs.AddCoreConfigs(ioHelper);
|
||||
return configs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class ConnectionStrings : IConnectionStrings
|
||||
{
|
||||
private readonly IIOHelper _ioHelper;
|
||||
|
||||
public ConnectionStrings(IIOHelper ioHelper)
|
||||
{
|
||||
_ioHelper = ioHelper;
|
||||
}
|
||||
|
||||
public ConfigConnectionString this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
var settings = ConfigurationManager.ConnectionStrings[key];
|
||||
if (settings == null) return null;
|
||||
return new ConfigConnectionString(settings.ConnectionString, settings.ProviderName, settings.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveConnectionString(string key)
|
||||
{
|
||||
var fileName = _ioHelper.MapPath(string.Format("{0}/web.config", _ioHelper.Root));
|
||||
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
|
||||
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
|
||||
var setting = appSettings.Descendants("add").FirstOrDefault(s => s.Attribute("key").Value == key);
|
||||
|
||||
if (setting != null)
|
||||
{
|
||||
setting.Remove();
|
||||
xml.Save(fileName, SaveOptions.DisableFormatting);
|
||||
ConfigurationManager.RefreshSection("appSettings");
|
||||
}
|
||||
var settings = ConfigurationManager.ConnectionStrings[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class HealthChecksSection : ConfigurationSection, IHealthChecks
|
||||
public class HealthChecksSection : ConfigurationSection
|
||||
{
|
||||
private const string DisabledChecksKey = "disabledChecks";
|
||||
private const string NotificationSettingsKey = "notificationSettings";
|
||||
@@ -21,14 +20,5 @@ namespace Umbraco.Core.Configuration.HealthChecks
|
||||
get { return ((HealthCheckNotificationSettingsElement)(base[NotificationSettingsKey])); }
|
||||
}
|
||||
|
||||
IEnumerable<IDisabledHealthCheck> IHealthChecks.DisabledChecks
|
||||
{
|
||||
get { return DisabledChecks; }
|
||||
}
|
||||
|
||||
IHealthCheckNotificationSettings IHealthChecks.NotificationSettings
|
||||
{
|
||||
get { return NotificationSettings; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class ActiveDirectorySettings : IActiveDirectorySettings
|
||||
{
|
||||
public ActiveDirectorySettings()
|
||||
{
|
||||
ActiveDirectoryDomain = ConfigurationManager.AppSettings["ActiveDirectoryDomain"];
|
||||
}
|
||||
|
||||
public string ActiveDirectoryDomain { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal abstract class ConfigurationManagerConfigBase
|
||||
{
|
||||
private UmbracoSettingsSection _umbracoSettingsSection;
|
||||
|
||||
protected UmbracoSettingsSection UmbracoSettingsSection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_umbracoSettingsSection is null)
|
||||
{
|
||||
_umbracoSettingsSection = ConfigurationManager.GetSection("umbracoConfiguration/settings") as UmbracoSettingsSection;
|
||||
}
|
||||
return _umbracoSettingsSection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Macros;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class ContentSettings : ConfigurationManagerConfigBase, IContentSettings
|
||||
{
|
||||
public string NotificationEmailAddress => UmbracoSettingsSection.Content.Notifications.NotificationEmailAddress;
|
||||
public bool DisableHtmlEmail => UmbracoSettingsSection.Content.Notifications.DisableHtmlEmail;
|
||||
public IEnumerable<string> ImageFileTypes => UmbracoSettingsSection.Content.Imaging.ImageFileTypes;
|
||||
public IEnumerable<IImagingAutoFillUploadField> ImageAutoFillProperties => UmbracoSettingsSection.Content.Imaging.ImageAutoFillProperties;
|
||||
public bool ResolveUrlsFromTextString => UmbracoSettingsSection.Content.ResolveUrlsFromTextString;
|
||||
public IEnumerable<IContentErrorPage> Error404Collection => UmbracoSettingsSection.Content.Error404Collection;
|
||||
public string PreviewBadge => UmbracoSettingsSection.Content.PreviewBadge;
|
||||
public MacroErrorBehaviour MacroErrorBehaviour => UmbracoSettingsSection.Content.MacroErrors;
|
||||
public IEnumerable<string> DisallowedUploadFiles => UmbracoSettingsSection.Content.DisallowedUploadFiles;
|
||||
public IEnumerable<string> AllowedUploadFiles => UmbracoSettingsSection.Content.AllowedUploadFiles;
|
||||
public bool ShowDeprecatedPropertyEditors => UmbracoSettingsSection.Content.ShowDeprecatedPropertyEditors;
|
||||
public string LoginBackgroundImage => UmbracoSettingsSection.Content.LoginBackgroundImage;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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);
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class ExceptionFilterSettings : IExceptionFilterSettings
|
||||
{
|
||||
public ExceptionFilterSettings()
|
||||
{
|
||||
if (bool.TryParse(ConfigurationManager.AppSettings["Umbraco.Web.DisableModelBindingExceptionFilter"],
|
||||
out var disabled))
|
||||
{
|
||||
Disabled = disabled;
|
||||
}
|
||||
}
|
||||
public bool Disabled { get; }
|
||||
}
|
||||
}
|
||||
+28
-74
@@ -3,59 +3,12 @@ using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net.Mail;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Composing;
|
||||
using Umbraco.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
namespace Umbraco.Core.Configuration.Legacy
|
||||
{
|
||||
public class HostingSettings : IHostingSettings
|
||||
{
|
||||
private bool? _debugMode;
|
||||
|
||||
/// <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
|
||||
|
||||
@@ -64,7 +17,6 @@ namespace Umbraco.Core.Configuration
|
||||
/// </summary>
|
||||
public class GlobalSettings : IGlobalSettings
|
||||
{
|
||||
private readonly IIOHelper _ioHelper;
|
||||
|
||||
// TODO these should not be static
|
||||
private static string _reservedPaths;
|
||||
@@ -74,11 +26,6 @@ namespace Umbraco.Core.Configuration
|
||||
internal const string StaticReservedPaths = "~/app_plugins/,~/install/,~/mini-profiler-resources/,"; //must end with a comma!
|
||||
internal const string StaticReservedUrls = "~/config/splashes/noNodes.aspx,~/.well-known,"; //must end with a comma!
|
||||
|
||||
public GlobalSettings(IIOHelper ioHelper)
|
||||
{
|
||||
_ioHelper = ioHelper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used in unit testing to reset all config items that were set with property setters (i.e. did not come from config)
|
||||
/// </summary>
|
||||
@@ -184,8 +131,8 @@ namespace Umbraco.Core.Configuration
|
||||
if (_reservedPaths != null) return _reservedPaths;
|
||||
|
||||
var reservedPaths = StaticReservedPaths;
|
||||
var umbPath = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path) && !ConfigurationManager.AppSettings[Constants.AppSettings.Path].IsNullOrWhiteSpace()
|
||||
? ConfigurationManager.AppSettings[Constants.AppSettings.Path]
|
||||
var umbPath = ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.UmbracoPath) && !ConfigurationManager.AppSettings[Constants.AppSettings.UmbracoPath].IsNullOrWhiteSpace()
|
||||
? ConfigurationManager.AppSettings[Constants.AppSettings.UmbracoPath]
|
||||
: "~/umbraco";
|
||||
//always add the umbraco path to the list
|
||||
reservedPaths += umbPath.EnsureEndsWith(',');
|
||||
@@ -199,20 +146,6 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to umbraco's root directory (/umbraco by default).
|
||||
/// </summary>
|
||||
/// <value>The path.</value>
|
||||
public string Path
|
||||
{
|
||||
get
|
||||
{
|
||||
return ConfigurationManager.AppSettings.ContainsKey(Constants.AppSettings.Path)
|
||||
? _ioHelper.ResolveUrl(ConfigurationManager.AppSettings[Constants.AppSettings.Path])
|
||||
: string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance.
|
||||
/// </summary>
|
||||
@@ -227,7 +160,7 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
set
|
||||
{
|
||||
SaveSetting(Constants.AppSettings.ConfigurationStatus, value, _ioHelper);
|
||||
SaveSetting(Constants.AppSettings.ConfigurationStatus, value, Current.IOHelper); //TODO remove
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +171,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <param name="value">Value of the setting to be saved.</param>
|
||||
internal static void SaveSetting(string key, string value, IIOHelper ioHelper)
|
||||
{
|
||||
var fileName = ioHelper.MapPath(string.Format("{0}/web.config", ioHelper.Root));
|
||||
var fileName = ioHelper.MapPath("~/web.config");
|
||||
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
|
||||
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
|
||||
@@ -254,7 +187,7 @@ namespace Umbraco.Core.Configuration
|
||||
ConfigurationManager.RefreshSection("appSettings");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time out in minutes.
|
||||
/// </summary>
|
||||
@@ -382,6 +315,10 @@ namespace Umbraco.Core.Configuration
|
||||
private string _databaseFactoryServerVersion;
|
||||
public string DatabaseFactoryServerVersion => GetterWithDefaultValue(Constants.AppSettings.Debug.DatabaseFactoryServerVersion, string.Empty, ref _databaseFactoryServerVersion);
|
||||
|
||||
private string _mainDomLock;
|
||||
|
||||
public string MainDomLock => GetterWithDefaultValue(Constants.AppSettings.MainDomLock, string.Empty, ref _mainDomLock);
|
||||
|
||||
private T GetterWithDefaultValue<T>(string appSettingKey, T defaultValue, ref T backingField)
|
||||
{
|
||||
if (backingField != null) return backingField;
|
||||
@@ -407,5 +344,22 @@ namespace Umbraco.Core.Configuration
|
||||
|
||||
return backingField;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the razor file used when no published content is available.
|
||||
/// </summary>
|
||||
public string NoNodesViewPath
|
||||
{
|
||||
get
|
||||
{
|
||||
var configuredValue = ConfigurationManager.AppSettings[Constants.AppSettings.NoNodesViewPath];
|
||||
if (!string.IsNullOrWhiteSpace(configuredValue))
|
||||
{
|
||||
return configuredValue;
|
||||
}
|
||||
|
||||
return "~/config/splashes/NoNodes.cshtml";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Legacy
|
||||
{
|
||||
public class HealthChecksSettings : IHealthChecksSettings
|
||||
{
|
||||
private HealthChecksSection _healthChecksSection;
|
||||
|
||||
private HealthChecksSection HealthChecksSection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_healthChecksSection is null)
|
||||
{
|
||||
_healthChecksSection = ConfigurationManager.GetSection("umbracoConfiguration/HealthChecks") as HealthChecksSection;
|
||||
}
|
||||
return _healthChecksSection;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IDisabledHealthCheck> DisabledChecks => HealthChecksSection.DisabledChecks;
|
||||
public IHealthCheckNotificationSettings NotificationSettings => HealthChecksSection.NotificationSettings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public string ApplicationVirtualPath => null;
|
||||
|
||||
/// <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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class IndexCreatorSettings : IIndexCreatorSettings
|
||||
{
|
||||
public IndexCreatorSettings()
|
||||
{
|
||||
LuceneDirectoryFactory = ConfigurationManager.AppSettings["Umbraco.Examine.LuceneDirectoryFactory"];
|
||||
}
|
||||
|
||||
public string LuceneDirectoryFactory { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class KeepAliveSettings : ConfigurationManagerConfigBase, IKeepAliveSettings
|
||||
{
|
||||
public bool DisableKeepAliveTask => UmbracoSettingsSection.KeepAlive.DisableKeepAliveTask;
|
||||
public string KeepAlivePingUrl => UmbracoSettingsSection.KeepAlive.KeepAlivePingUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class LoggingSettings : ConfigurationManagerConfigBase, ILoggingSettings
|
||||
{
|
||||
public int MaxLogAge => UmbracoSettingsSection.Logging.MaxLogAge;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class MemberPasswordConfigurationSettings : ConfigurationManagerConfigBase, IMemberPasswordConfiguration
|
||||
{
|
||||
public int RequiredLength => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequiredLength;
|
||||
public bool RequireNonLetterOrDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireNonLetterOrDigit;
|
||||
public bool RequireDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireDigit;
|
||||
public bool RequireLowercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireLowercase;
|
||||
public bool RequireUppercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireUppercase;
|
||||
public bool UseLegacyEncoding=> UmbracoSettingsSection.Security.UserPasswordConfiguration.UseLegacyEncoding;
|
||||
public string HashAlgorithmType=> UmbracoSettingsSection.Security.UserPasswordConfiguration.HashAlgorithmType;
|
||||
public int MaxFailedAccessAttemptsBeforeLockout => UmbracoSettingsSection.Security.UserPasswordConfiguration.MaxFailedAccessAttemptsBeforeLockout;
|
||||
}
|
||||
}
|
||||
+17
-48
@@ -2,18 +2,18 @@
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Web.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.ModelsBuilder.Embedded.Configuration
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the models builder configuration.
|
||||
/// </summary>
|
||||
public class ModelsBuilderConfig : IModelsBuilderConfig
|
||||
{
|
||||
private readonly IIOHelper _ioHelper;
|
||||
|
||||
private const string Prefix = "Umbraco.ModelsBuilder.";
|
||||
private object _modelsModelLock;
|
||||
private bool _modelsModelConfigured;
|
||||
@@ -21,23 +21,21 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
|
||||
private object _flagOutOfDateModelsLock;
|
||||
private bool _flagOutOfDateModelsConfigured;
|
||||
private bool _flagOutOfDateModels;
|
||||
public const string DefaultModelsNamespace = "Umbraco.Web.PublishedModels";
|
||||
|
||||
public string DefaultModelsDirectory => _ioHelper.MapPath("~/App_Data/Models");
|
||||
|
||||
public string DefaultModelsDirectory => "~/App_Data/Models";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModelsBuilderConfig"/> class.
|
||||
/// </summary>
|
||||
public ModelsBuilderConfig(IIOHelper ioHelper)
|
||||
public ModelsBuilderConfig()
|
||||
{
|
||||
_ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
|
||||
|
||||
// giant kill switch, default: false
|
||||
// must be explicitely set to true for anything else to happen
|
||||
Enable = ConfigurationManager.AppSettings[Prefix + "Enable"] == "true";
|
||||
|
||||
// ensure defaults are initialized for tests
|
||||
ModelsNamespace = DefaultModelsNamespace;
|
||||
ModelsNamespace = Constants.ModelsBuilder.DefaultModelsNamespace;
|
||||
ModelsDirectory = DefaultModelsDirectory;
|
||||
DebugLevel = 0;
|
||||
|
||||
@@ -59,12 +57,8 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
|
||||
value = ConfigurationManager.AppSettings[Prefix + "ModelsDirectory"];
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
var root = _ioHelper.MapPath("~/");
|
||||
if (root == null)
|
||||
throw new ConfigurationErrorsException("Could not determine root directory.");
|
||||
|
||||
// GetModelsDirectory will ensure that the path is safe
|
||||
ModelsDirectory = GetModelsDirectory(root, value, AcceptUnsafeModelsDirectory);
|
||||
ModelsDirectory = value;
|
||||
}
|
||||
|
||||
// default: 0
|
||||
@@ -81,7 +75,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModelsBuilderConfig"/> class.
|
||||
/// </summary>
|
||||
public ModelsBuilderConfig(IIOHelper ioHelper,
|
||||
public ModelsBuilderConfig(
|
||||
bool enable = false,
|
||||
ModelsMode modelsMode = ModelsMode.Nothing,
|
||||
string modelsNamespace = null,
|
||||
@@ -91,11 +85,10 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
|
||||
bool acceptUnsafeModelsDirectory = false,
|
||||
int debugLevel = 0)
|
||||
{
|
||||
_ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
|
||||
Enable = enable;
|
||||
_modelsMode = modelsMode;
|
||||
|
||||
ModelsNamespace = string.IsNullOrWhiteSpace(modelsNamespace) ? DefaultModelsNamespace : modelsNamespace;
|
||||
ModelsNamespace = string.IsNullOrWhiteSpace(modelsNamespace) ? Constants.ModelsBuilder.DefaultModelsNamespace : modelsNamespace;
|
||||
EnableFactory = enableFactory;
|
||||
_flagOutOfDateModels = flagOutOfDateModels;
|
||||
ModelsDirectory = string.IsNullOrWhiteSpace(modelsDirectory) ? DefaultModelsDirectory : modelsDirectory;
|
||||
@@ -103,36 +96,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
|
||||
DebugLevel = debugLevel;
|
||||
}
|
||||
|
||||
// internal for tests
|
||||
internal static string GetModelsDirectory(string root, string config, bool acceptUnsafe)
|
||||
{
|
||||
// making sure it is safe, ie under the website root,
|
||||
// unless AcceptUnsafeModelsDirectory and then everything is OK.
|
||||
|
||||
if (!Path.IsPathRooted(root))
|
||||
throw new ConfigurationErrorsException($"Root is not rooted \"{root}\".");
|
||||
|
||||
if (config.StartsWith("~/"))
|
||||
{
|
||||
var dir = Path.Combine(root, config.TrimStart("~/"));
|
||||
|
||||
// sanitize - GetFullPath will take care of any relative
|
||||
// segments in path, eg '../../foo.tmp' - it may throw a SecurityException
|
||||
// if the combined path reaches illegal parts of the filesystem
|
||||
dir = Path.GetFullPath(dir);
|
||||
root = Path.GetFullPath(root);
|
||||
|
||||
if (!dir.StartsWith(root) && !acceptUnsafe)
|
||||
throw new ConfigurationErrorsException($"Invalid models directory \"{config}\".");
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
if (acceptUnsafe)
|
||||
return Path.GetFullPath(config);
|
||||
|
||||
throw new ConfigurationErrorsException($"Invalid models directory \"{config}\".");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the whole models experience is enabled.
|
||||
@@ -174,8 +138,13 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
var section = (CompilationSection)ConfigurationManager.GetSection("system.web/compilation");
|
||||
return section != null && section.Debug;
|
||||
if (ConfigurationManager.GetSection("system.web/compilation") is ConfigurationSection section &&
|
||||
bool.TryParse(section.ElementInformation.Properties["debug"].Value.ToString(), out var isDebug))
|
||||
{
|
||||
return isDebug;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class NuCacheSettings : INuCacheSettings
|
||||
{
|
||||
public NuCacheSettings()
|
||||
{
|
||||
BTreeBlockSize = ConfigurationManager.AppSettings["Umbraco.Web.PublishedCache.NuCache.BTree.BlockSize"];
|
||||
}
|
||||
public string BTreeBlockSize { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class RequestHandlerSettings : ConfigurationManagerConfigBase, IRequestHandlerSettings
|
||||
{
|
||||
public bool AddTrailingSlash => UmbracoSettingsSection?.RequestHandler?.AddTrailingSlash ?? true;
|
||||
public bool ConvertUrlsToAscii => UmbracoSettingsSection?.RequestHandler?.UrlReplacing?.ConvertUrlsToAscii.InvariantEquals("true") ?? false;
|
||||
public bool TryConvertUrlsToAscii => UmbracoSettingsSection?.RequestHandler?.UrlReplacing?.ConvertUrlsToAscii.InvariantEquals("try") ?? false;
|
||||
public IEnumerable<IChar> CharCollection => UmbracoSettingsSection?.RequestHandler?.UrlReplacing?.CharCollection ?? Enumerable.Empty<IChar>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class RuntimeSettings : IRuntimeSettings
|
||||
{
|
||||
public RuntimeSettings()
|
||||
{
|
||||
if (ConfigurationManager.GetSection("system.web/httpRuntime") is ConfigurationSection section)
|
||||
{
|
||||
var maxRequestLengthProperty = section.ElementInformation.Properties["maxRequestLength"];
|
||||
if (maxRequestLengthProperty != null && maxRequestLengthProperty.Value is int requestLength)
|
||||
{
|
||||
MaxRequestLength = requestLength;
|
||||
}
|
||||
|
||||
var maxQueryStringProperty = section.ElementInformation.Properties["maxQueryStringLength"];
|
||||
if (maxQueryStringProperty != null && maxQueryStringProperty.Value is int maxQueryStringLength)
|
||||
{
|
||||
MaxQueryStringLength = maxQueryStringLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
public int? MaxQueryStringLength { get; }
|
||||
public int? MaxRequestLength { get; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class SecuritySettings : ConfigurationManagerConfigBase, ISecuritySettings
|
||||
{
|
||||
public bool KeepUserLoggedIn => UmbracoSettingsSection.Security.KeepUserLoggedIn;
|
||||
public bool HideDisabledUsersInBackoffice => UmbracoSettingsSection.Security.HideDisabledUsersInBackoffice;
|
||||
public bool AllowPasswordReset => UmbracoSettingsSection.Security.AllowPasswordReset;
|
||||
public string AuthCookieName => UmbracoSettingsSection.Security.AuthCookieName;
|
||||
public string AuthCookieDomain => UmbracoSettingsSection.Security.AuthCookieDomain;
|
||||
public bool UsernameIsEmail => UmbracoSettingsSection.Security.UsernameIsEmail;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class TourSettings : ConfigurationManagerConfigBase, ITourSettings
|
||||
{
|
||||
public bool EnableTours => UmbracoSettingsSection.BackOffice.Tours.EnableTours;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class TypeFinderSettings : ITypeFinderSettings
|
||||
{
|
||||
public TypeFinderSettings()
|
||||
{
|
||||
AssembliesAcceptingLoadExceptions = ConfigurationManager.AppSettings[
|
||||
Constants.AppSettings.AssembliesAcceptingLoadExceptions];
|
||||
}
|
||||
|
||||
public string AssembliesAcceptingLoadExceptions { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Umbraco.Core.Configuration;
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class UserPasswordConfigurationSettings : ConfigurationManagerConfigBase, IUserPasswordConfiguration
|
||||
{
|
||||
public int RequiredLength => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequiredLength;
|
||||
public bool RequireNonLetterOrDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireNonLetterOrDigit;
|
||||
public bool RequireDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireDigit;
|
||||
public bool RequireLowercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireLowercase;
|
||||
public bool RequireUppercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireUppercase;
|
||||
public bool UseLegacyEncoding=> UmbracoSettingsSection.Security.UserPasswordConfiguration.UseLegacyEncoding;
|
||||
public string HashAlgorithmType=> UmbracoSettingsSection.Security.UserPasswordConfiguration.HashAlgorithmType;
|
||||
public int MaxFailedAccessAttemptsBeforeLockout => UmbracoSettingsSection.Security.UserPasswordConfiguration.MaxFailedAccessAttemptsBeforeLockout;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class WebRoutingSettings : ConfigurationManagerConfigBase, IWebRoutingSettings
|
||||
{
|
||||
public bool TrySkipIisCustomErrors => UmbracoSettingsSection?.WebRouting?.TrySkipIisCustomErrors ?? false;
|
||||
public bool InternalRedirectPreservesTemplate => UmbracoSettingsSection?.WebRouting?.InternalRedirectPreservesTemplate ?? false;
|
||||
public bool DisableAlternativeTemplates => UmbracoSettingsSection?.WebRouting?.DisableAlternativeTemplates ?? false;
|
||||
public bool ValidateAlternativeTemplates => UmbracoSettingsSection?.WebRouting?.ValidateAlternativeTemplates ?? false;
|
||||
public bool DisableFindContentByIdPath => UmbracoSettingsSection?.WebRouting?.DisableFindContentByIdPath ?? false;
|
||||
public bool DisableRedirectUrlTracking => UmbracoSettingsSection?.WebRouting?.DisableRedirectUrlTracking ?? false;
|
||||
public string UrlProviderMode => UmbracoSettingsSection?.WebRouting?.UrlProviderMode ?? "Auto";
|
||||
public string UmbracoApplicationUrl => UmbracoSettingsSection?.WebRouting?.UmbracoApplicationUrl;
|
||||
}
|
||||
}
|
||||
@@ -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,59 @@
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
public class ConnectionStrings : IConnectionStrings
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public ConnectionStrings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public ConfigConnectionString this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
var connectionString = _configuration.GetConnectionString(key);
|
||||
var provider = ParseProvider(connectionString);
|
||||
return new ConfigConnectionString(connectionString, provider, key);
|
||||
}
|
||||
set => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private string ParseProvider(string connectionString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(connectionString))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var builder = new DbConnectionStringBuilder();
|
||||
|
||||
builder.ConnectionString = connectionString;
|
||||
|
||||
if (builder.TryGetValue("Data Source", out var ds) && ds is string dataSource)
|
||||
{
|
||||
if (dataSource.EndsWith(".sdf"))
|
||||
{
|
||||
return Constants.DbProviderNames.SqlCe;
|
||||
}
|
||||
}
|
||||
|
||||
if (builder.TryGetValue("Server", out var s) && s is string server && builder.TryGetValue("Database", out var db) && db is string database)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(server) && !string.IsNullOrEmpty(database))
|
||||
{
|
||||
return Constants.DbProviderNames.SqlServer;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException("Cannot determine provider name from connection string", nameof(connectionString));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,95 @@
|
||||
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.ConfigGlobalPrefix;
|
||||
|
||||
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);
|
||||
|
||||
// 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,29 @@
|
||||
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);
|
||||
|
||||
public string ApplicationVirtualPath => null;
|
||||
|
||||
/// <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");
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
// Umbraco Cms
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests.Common")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests.Benchmarks")]
|
||||
|
||||
// Allow this to be mocked in our unit tests
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -29,4 +32,10 @@
|
||||
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>Umbraco.Tests.Integration</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -7,6 +7,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
[ConfigurationProperty("tours")]
|
||||
internal TourConfigElement Tours => (TourConfigElement)this["tours"];
|
||||
|
||||
ITourSection IBackOfficeSection.Tours => Tours;
|
||||
ITourSettings IBackOfficeSection.Tours => Tours;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ using Umbraco.Core.Macros;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class ContentElement : UmbracoConfigurationElement, IContentSection
|
||||
internal class ContentElement : UmbracoConfigurationElement, IContentSettings
|
||||
{
|
||||
private const string DefaultPreviewBadge = @"<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>";
|
||||
|
||||
@@ -40,26 +40,26 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
[ConfigurationProperty("loginBackgroundImage")]
|
||||
internal InnerTextConfigurationElement<string> LoginBackgroundImage => GetOptionalTextElement("loginBackgroundImage", string.Empty);
|
||||
|
||||
string IContentSection.NotificationEmailAddress => Notifications.NotificationEmailAddress;
|
||||
string IContentSettings.NotificationEmailAddress => Notifications.NotificationEmailAddress;
|
||||
|
||||
bool IContentSection.DisableHtmlEmail => Notifications.DisableHtmlEmail;
|
||||
bool IContentSettings.DisableHtmlEmail => Notifications.DisableHtmlEmail;
|
||||
|
||||
IEnumerable<string> IContentSection.ImageFileTypes => Imaging.ImageFileTypes;
|
||||
IEnumerable<string> IContentSettings.ImageFileTypes => Imaging.ImageFileTypes;
|
||||
|
||||
IEnumerable<IImagingAutoFillUploadField> IContentSection.ImageAutoFillProperties => Imaging.ImageAutoFillProperties;
|
||||
IEnumerable<IImagingAutoFillUploadField> IContentSettings.ImageAutoFillProperties => Imaging.ImageAutoFillProperties;
|
||||
|
||||
bool IContentSection.ResolveUrlsFromTextString => ResolveUrlsFromTextString;
|
||||
bool IContentSettings.ResolveUrlsFromTextString => ResolveUrlsFromTextString;
|
||||
|
||||
string IContentSection.PreviewBadge => PreviewBadge;
|
||||
string IContentSettings.PreviewBadge => PreviewBadge;
|
||||
|
||||
MacroErrorBehaviour IContentSection.MacroErrorBehaviour => MacroErrors;
|
||||
MacroErrorBehaviour IContentSettings.MacroErrorBehaviour => MacroErrors;
|
||||
|
||||
IEnumerable<string> IContentSection.DisallowedUploadFiles => DisallowedUploadFiles;
|
||||
IEnumerable<string> IContentSettings.DisallowedUploadFiles => DisallowedUploadFiles;
|
||||
|
||||
IEnumerable<string> IContentSection.AllowedUploadFiles => AllowedUploadFiles;
|
||||
IEnumerable<string> IContentSettings.AllowedUploadFiles => AllowedUploadFiles;
|
||||
|
||||
bool IContentSection.ShowDeprecatedPropertyEditors => ShowDeprecatedPropertyEditors;
|
||||
bool IContentSettings.ShowDeprecatedPropertyEditors => ShowDeprecatedPropertyEditors;
|
||||
|
||||
string IContentSection.LoginBackgroundImage => LoginBackgroundImage;
|
||||
string IContentSettings.LoginBackgroundImage => LoginBackgroundImage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class KeepAliveElement : ConfigurationElement, IKeepAliveSection
|
||||
internal class KeepAliveElement : ConfigurationElement, IKeepAliveSettings
|
||||
{
|
||||
[ConfigurationProperty("disableKeepAliveTask", DefaultValue = "false")]
|
||||
public bool DisableKeepAliveTask => (bool)base["disableKeepAliveTask"];
|
||||
|
||||
@@ -3,12 +3,12 @@ using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class LoggingElement : UmbracoConfigurationElement, ILoggingSection
|
||||
internal class LoggingElement : UmbracoConfigurationElement, ILoggingSettings
|
||||
{
|
||||
|
||||
[ConfigurationProperty("maxLogAge")]
|
||||
internal InnerTextConfigurationElement<int> MaxLogAge => GetOptionalTextElement("maxLogAge", -1);
|
||||
|
||||
int ILoggingSection.MaxLogAge => MaxLogAge;
|
||||
int ILoggingSettings.MaxLogAge => MaxLogAge;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class MemberPasswordConfigurationElement : PasswordConfigurationElement, IMemberPasswordConfigurationSection
|
||||
internal class MemberPasswordConfigurationElement : PasswordConfigurationElement, IMemberPasswordConfiguration
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class RequestHandlerElement : UmbracoConfigurationElement, IRequestHandlerSection
|
||||
internal class RequestHandlerElement : UmbracoConfigurationElement, IRequestHandlerSettings
|
||||
{
|
||||
[ConfigurationProperty("addTrailingSlash")]
|
||||
public InnerTextConfigurationElement<bool> AddTrailingSlash => GetOptionalTextElement("addTrailingSlash", true);
|
||||
@@ -85,12 +85,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
return collection;
|
||||
}
|
||||
|
||||
bool IRequestHandlerSection.AddTrailingSlash => AddTrailingSlash;
|
||||
bool IRequestHandlerSettings.AddTrailingSlash => AddTrailingSlash;
|
||||
|
||||
bool IRequestHandlerSection.ConvertUrlsToAscii => UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true");
|
||||
bool IRequestHandlerSettings.ConvertUrlsToAscii => UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true");
|
||||
|
||||
bool IRequestHandlerSection.TryConvertUrlsToAscii => UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try");
|
||||
bool IRequestHandlerSettings.TryConvertUrlsToAscii => UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try");
|
||||
|
||||
IEnumerable<IChar> IRequestHandlerSection.CharCollection => UrlReplacing.CharCollection;
|
||||
IEnumerable<IChar> IRequestHandlerSettings.CharCollection => UrlReplacing.CharCollection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class SecurityElement : UmbracoConfigurationElement, ISecuritySection
|
||||
internal class SecurityElement : UmbracoConfigurationElement, ISecuritySettings
|
||||
{
|
||||
[ConfigurationProperty("keepUserLoggedIn")]
|
||||
internal InnerTextConfigurationElement<bool> KeepUserLoggedIn => GetOptionalTextElement("keepUserLoggedIn", true);
|
||||
@@ -38,14 +38,14 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
[ConfigurationProperty("memberPasswordConfiguration")]
|
||||
public MemberPasswordConfigurationElement MemberPasswordConfiguration => (MemberPasswordConfigurationElement)this["memberPasswordConfiguration"];
|
||||
|
||||
bool ISecuritySection.KeepUserLoggedIn => KeepUserLoggedIn;
|
||||
bool ISecuritySettings.KeepUserLoggedIn => KeepUserLoggedIn;
|
||||
|
||||
bool ISecuritySection.HideDisabledUsersInBackoffice => HideDisabledUsersInBackoffice;
|
||||
bool ISecuritySettings.HideDisabledUsersInBackoffice => HideDisabledUsersInBackoffice;
|
||||
|
||||
/// <summary>
|
||||
/// Used to enable/disable the forgot password functionality on the back office login screen
|
||||
/// </summary>
|
||||
bool ISecuritySection.AllowPasswordReset => AllowPasswordReset;
|
||||
bool ISecuritySettings.AllowPasswordReset => AllowPasswordReset;
|
||||
|
||||
/// <summary>
|
||||
/// A boolean indicating that by default the email address will be the username
|
||||
@@ -54,14 +54,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
/// Even if this is true and the username is different from the email in the database, the username field will still be shown.
|
||||
/// When this is false, the username and email fields will be shown in the user section.
|
||||
/// </remarks>
|
||||
bool ISecuritySection.UsernameIsEmail => UsernameIsEmail;
|
||||
bool ISecuritySettings.UsernameIsEmail => UsernameIsEmail;
|
||||
|
||||
string ISecuritySection.AuthCookieName => AuthCookieName;
|
||||
string ISecuritySettings.AuthCookieName => AuthCookieName;
|
||||
|
||||
string ISecuritySection.AuthCookieDomain => AuthCookieDomain;
|
||||
|
||||
IUserPasswordConfigurationSection ISecuritySection.UserPasswordConfiguration => UserPasswordConfiguration;
|
||||
|
||||
IMemberPasswordConfigurationSection ISecuritySection.MemberPasswordConfiguration => MemberPasswordConfiguration;
|
||||
string ISecuritySettings.AuthCookieDomain => AuthCookieDomain;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class TourConfigElement : UmbracoConfigurationElement, ITourSection
|
||||
internal class TourConfigElement : UmbracoConfigurationElement, ITourSettings
|
||||
{
|
||||
//disabled by default so that upgraders don't get it enabled by default
|
||||
// TODO: we probably just want to disable the initial one from automatically loading ?
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class UmbracoSettingsSection : ConfigurationSection, IUmbracoSettingsSection
|
||||
internal class UmbracoSettingsSection : ConfigurationSection
|
||||
{
|
||||
[ConfigurationProperty("backOffice")]
|
||||
public BackOfficeElement BackOffice => (BackOfficeElement)this["backOffice"];
|
||||
@@ -24,19 +24,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
[ConfigurationProperty("keepAlive")]
|
||||
internal KeepAliveElement KeepAlive => (KeepAliveElement)this["keepAlive"];
|
||||
|
||||
IContentSection IUmbracoSettingsSection.Content => Content;
|
||||
|
||||
ISecuritySection IUmbracoSettingsSection.Security => Security;
|
||||
|
||||
IRequestHandlerSection IUmbracoSettingsSection.RequestHandler => RequestHandler;
|
||||
|
||||
IBackOfficeSection IUmbracoSettingsSection.BackOffice => BackOffice;
|
||||
|
||||
ILoggingSection IUmbracoSettingsSection.Logging => Logging;
|
||||
|
||||
IWebRoutingSection IUmbracoSettingsSection.WebRouting => WebRouting;
|
||||
|
||||
IKeepAliveSection IUmbracoSettingsSection.KeepAlive => KeepAlive;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class UserPasswordConfigurationElement : PasswordConfigurationElement, IUserPasswordConfigurationSection
|
||||
internal class UserPasswordConfigurationElement : PasswordConfigurationElement, IUserPasswordConfiguration
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class WebRoutingElement : ConfigurationElement, IWebRoutingSection
|
||||
internal class WebRoutingElement : ConfigurationElement, IWebRoutingSettings
|
||||
{
|
||||
[ConfigurationProperty("trySkipIisCustomErrors", DefaultValue = "false")]
|
||||
public bool TrySkipIisCustomErrors => (bool) base["trySkipIisCustomErrors"];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
namespace Umbraco.Web.Actions
|
||||
{
|
||||
internal class ActionCollectionBuilder : LazyCollectionBuilderBase<ActionCollectionBuilder, ActionCollection, IAction>
|
||||
public class ActionCollectionBuilder : LazyCollectionBuilderBase<ActionCollectionBuilder, ActionCollection, IAction>
|
||||
{
|
||||
protected override ActionCollectionBuilder This => this;
|
||||
|
||||
|
||||
@@ -6,6 +6,35 @@ namespace Umbraco.Core
|
||||
{
|
||||
public static class AssemblyExtensions
|
||||
{
|
||||
private static string _rootDir = "";
|
||||
|
||||
/// <summary>
|
||||
/// Utility method that returns the path to the root of the application, by getting the path to where the assembly where this
|
||||
/// method is included is present, then traversing until it's past the /bin directory. Ie. this makes it work
|
||||
/// even if the assembly is in a /bin/debug or /bin/release folder
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetRootDirectorySafe(this Assembly executingAssembly)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_rootDir) == false)
|
||||
{
|
||||
return _rootDir;
|
||||
}
|
||||
|
||||
var codeBase = executingAssembly.CodeBase;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
var baseDirectory = Path.GetDirectoryName(path);
|
||||
if (string.IsNullOrEmpty(baseDirectory))
|
||||
throw new Exception("No root directory could be resolved. Please ensure that your Umbraco solution is correctly configured.");
|
||||
|
||||
_rootDir = baseDirectory.Contains("bin")
|
||||
? baseDirectory.Substring(0, baseDirectory.LastIndexOf("bin", StringComparison.OrdinalIgnoreCase) - 1)
|
||||
: baseDirectory;
|
||||
|
||||
return _rootDir;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the file used to load the assembly
|
||||
/// </summary>
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Umbraco.Web.Cache
|
||||
{
|
||||
macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey<IMacro>(payload.Id));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
base.Refresh(json);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Umbraco.Core.Collections
|
||||
if (_items.TryGetValue(key, out value))
|
||||
yield return value;
|
||||
else if (throwOnMissing)
|
||||
throw new Exception(MissingDependencyError);
|
||||
throw new Exception($"{MissingDependencyError} Error in type {typeof(TItem).Name}, with key {key}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,9 +79,12 @@ namespace Umbraco.Core.Composing
|
||||
foreach (var type in types)
|
||||
EnsureType(type, "register");
|
||||
|
||||
// register them
|
||||
// register them - ensuring that each item is registered with the same lifetime as the collection.
|
||||
// NOTE: Previously each one was not registered with the same lifetime which would mean that if there
|
||||
// was a dependency on an individual item, it would resolve a brand new transient instance which isn't what
|
||||
// we would expect to happen. The same item should be resolved from the container as the collection.
|
||||
foreach (var type in types)
|
||||
register.Register(type);
|
||||
register.Register(type, CollectionLifetime);
|
||||
|
||||
_registeredTypes = types;
|
||||
}
|
||||
|
||||
@@ -31,15 +31,16 @@ namespace Umbraco.Core.Composing
|
||||
/// <param name="runtimeState">The runtime state.</param>
|
||||
/// <param name="configs">Optional configs.</param>
|
||||
/// <param name="ioHelper">An IOHelper</param>
|
||||
/// <param name="appCaches"></param>
|
||||
public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs, IIOHelper ioHelper, AppCaches appCaches)
|
||||
{
|
||||
_register = register;
|
||||
TypeLoader = typeLoader;
|
||||
Logger = logger;
|
||||
RuntimeState = runtimeState;
|
||||
Configs = configs;
|
||||
IOHelper = ioHelper;
|
||||
AppCaches = appCaches;
|
||||
_register = register ?? throw new ArgumentNullException(nameof(register));
|
||||
TypeLoader = typeLoader ?? throw new ArgumentNullException(nameof(typeLoader));
|
||||
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
RuntimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState));
|
||||
Configs = configs ?? throw new ArgumentNullException(nameof(configs));
|
||||
IOHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
|
||||
AppCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches));
|
||||
}
|
||||
|
||||
#region Services
|
||||
@@ -135,7 +136,7 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
IFactory factory = null;
|
||||
|
||||
Configs.RegisterWith(_register, () => factory);
|
||||
Configs.RegisterWith(_register);
|
||||
|
||||
// ReSharper disable once AccessToModifiedClosure -- on purpose
|
||||
_register.Register(_ => factory, Lifetime.Singleton);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of scannable assemblies based on an entry point assembly and it's references
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will recursively search through the entry point's assemblies and Umbraco's core assemblies and their references
|
||||
/// to create a list of scannable assemblies based on whether they themselves or their transitive dependencies reference Umbraco core assemblies.
|
||||
/// </remarks>
|
||||
public class DefaultUmbracoAssemblyProvider : IAssemblyProvider
|
||||
{
|
||||
private readonly Assembly _entryPointAssembly;
|
||||
private static readonly string[] UmbracoCoreAssemblyNames = new[]
|
||||
{
|
||||
"Umbraco.Core",
|
||||
"Umbraco.Web",
|
||||
"Umbraco.Infrastructure",
|
||||
"Umbraco.PublishedCache.NuCache",
|
||||
"Umbraco.ModelsBuilder.Embedded",
|
||||
"Umbraco.Examine.Lucene",
|
||||
"Umbraco.Web.Common",
|
||||
"Umbraco.Web.BackOffice",
|
||||
"Umbraco.Web.Website",
|
||||
};
|
||||
|
||||
public DefaultUmbracoAssemblyProvider(Assembly entryPointAssembly)
|
||||
{
|
||||
_entryPointAssembly = entryPointAssembly ?? throw new ArgumentNullException(nameof(entryPointAssembly));
|
||||
}
|
||||
|
||||
// TODO: It would be worth investigating a netcore3 version of this which would use
|
||||
// var allAssemblies = System.Runtime.Loader.AssemblyLoadContext.All.SelectMany(x => x.Assemblies);
|
||||
// that will still only resolve Assemblies that are already loaded but it would also make it possible to
|
||||
// query dynamically generated assemblies once they are added. It would also provide the ability to probe
|
||||
// assembly locations that are not in the same place as the entry point assemblies.
|
||||
|
||||
public IEnumerable<Assembly> Assemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, UmbracoCoreAssemblyNames, true);
|
||||
return finder.Find();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
@@ -21,6 +22,11 @@ namespace Umbraco.Core.Composing
|
||||
public DisableAttribute()
|
||||
{ }
|
||||
|
||||
public DisableAttribute(string fullTypeName, string assemblyName)
|
||||
{
|
||||
DisabledType = Assembly.Load(assemblyName)?.GetType(fullTypeName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DisableAttribute"/> class.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Finds Assemblies from the entry point assemblies, it's dependencies and it's transitive dependencies that reference that targetAssemblyNames
|
||||
/// </summary>
|
||||
/// <remarkes>
|
||||
/// borrowed and modified from here https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/FindAssembliesWithReferencesTo.cs
|
||||
/// </remarkes>
|
||||
internal class FindAssembliesWithReferencesTo
|
||||
{
|
||||
private readonly Assembly[] _referenceAssemblies;
|
||||
private readonly string[] _targetAssemblies;
|
||||
private readonly bool _includeTargets;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="referenceAssemblies">Entry point assemblies</param>
|
||||
/// <param name="targetAssemblyNames">Used to check if the entry point or it's transitive assemblies reference these assembly names</param>
|
||||
/// <param name="includeTargets">If true will also use the target assembly names as entry point assemblies</param>
|
||||
public FindAssembliesWithReferencesTo(Assembly[] referenceAssemblies, string[] targetAssemblyNames, bool includeTargets)
|
||||
{
|
||||
_referenceAssemblies = referenceAssemblies;
|
||||
_targetAssemblies = targetAssemblyNames;
|
||||
_includeTargets = includeTargets;
|
||||
}
|
||||
|
||||
public IEnumerable<Assembly> Find()
|
||||
{
|
||||
var referenceItems = new List<Assembly>();
|
||||
foreach (var assembly in _referenceAssemblies)
|
||||
{
|
||||
referenceItems.Add(assembly);
|
||||
}
|
||||
|
||||
if (_includeTargets)
|
||||
{
|
||||
foreach(var target in _targetAssemblies)
|
||||
{
|
||||
try
|
||||
{
|
||||
referenceItems.Add(Assembly.Load(target));
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
// occurs if we cannot load this ... for example in a test project where we aren't currently referencing Umbraco.Web, etc...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var provider = new ReferenceResolver(_targetAssemblies, referenceItems);
|
||||
var assemblyNames = provider.ResolveAssemblies();
|
||||
return assemblyNames.ToList();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a list of assemblies that can be scanned
|
||||
/// </summary>
|
||||
public interface IAssemblyProvider
|
||||
{
|
||||
IEnumerable<Assembly> Assemblies { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to create a hash value of the current runtime
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is used to detect if the runtime itself has changed, like a DLL has changed or another dynamically compiled
|
||||
/// part of the application has changed. This is used to detect if we need to re-type scan.
|
||||
/// </remarks>
|
||||
public interface IRuntimeHash
|
||||
{
|
||||
string GetHashValue();
|
||||
}
|
||||
}
|
||||
@@ -51,5 +51,14 @@ namespace Umbraco.Core.Composing
|
||||
Type attributeType,
|
||||
IEnumerable<Assembly> assemblies,
|
||||
bool onlyConcreteClasses);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a hash value of the current runtime
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is used to detect if the runtime itself has changed, like a DLL has changed or another dynamically compiled
|
||||
/// part of the application has changed. This is used to detect if we need to re-type scan.
|
||||
/// </remarks>
|
||||
string GetRuntimeHash();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves assemblies that reference one of the specified "targetAssemblies" either directly or transitively.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Borrowed and modified from https://github.com/dotnet/aspnetcore-tooling/blob/master/src/Razor/src/Microsoft.NET.Sdk.Razor/ReferenceResolver.cs
|
||||
/// </remarks>
|
||||
internal class ReferenceResolver
|
||||
{
|
||||
private readonly HashSet<string> _umbracoAssemblies;
|
||||
private readonly IReadOnlyList<Assembly> _assemblies;
|
||||
private readonly Dictionary<Assembly, Classification> _classifications;
|
||||
private readonly List<Assembly> _lookup = new List<Assembly>();
|
||||
|
||||
public ReferenceResolver(IReadOnlyList<string> targetAssemblies, IReadOnlyList<Assembly> entryPointAssemblies)
|
||||
{
|
||||
_umbracoAssemblies = new HashSet<string>(targetAssemblies, StringComparer.Ordinal);
|
||||
_assemblies = entryPointAssemblies;
|
||||
_classifications = new Dictionary<Assembly, Classification>();
|
||||
|
||||
foreach (var item in entryPointAssemblies)
|
||||
{
|
||||
_lookup.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of assemblies that directly reference or transitively reference the targetAssemblies
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This includes all assemblies in the same location as the entry point assemblies
|
||||
/// </remarks>
|
||||
public IEnumerable<Assembly> ResolveAssemblies()
|
||||
{
|
||||
var applicationParts = new List<Assembly>();
|
||||
|
||||
var assemblies = new HashSet<Assembly>(_assemblies);
|
||||
|
||||
// Get the unique directories of the assemblies
|
||||
var assemblyLocations = GetAssemblyFolders(assemblies).ToList();
|
||||
|
||||
// Load in each assembly in the directory of the entry assembly to be included in the search
|
||||
// for Umbraco dependencies/transitive dependencies
|
||||
foreach(var dir in assemblyLocations)
|
||||
{
|
||||
foreach(var dll in Directory.EnumerateFiles(dir, "*.dll"))
|
||||
{
|
||||
var assemblyName = AssemblyName.GetAssemblyName(dll);
|
||||
|
||||
// don't include if this is excluded
|
||||
if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => assemblyName.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)))
|
||||
continue;
|
||||
|
||||
// don't include this item if it's Umbraco
|
||||
// TODO: We should maybe pass an explicit list of these names in?
|
||||
if (assemblyName.FullName.StartsWith("Umbraco."))
|
||||
continue;
|
||||
|
||||
var assembly = Assembly.Load(assemblyName);
|
||||
assemblies.Add(assembly);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in assemblies)
|
||||
{
|
||||
var classification = Resolve(item);
|
||||
if (classification == Classification.ReferencesUmbraco || classification == Classification.IsUmbraco)
|
||||
{
|
||||
applicationParts.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
return applicationParts;
|
||||
}
|
||||
|
||||
|
||||
private IEnumerable<string> GetAssemblyFolders(IEnumerable<Assembly> assemblies)
|
||||
{
|
||||
return assemblies.Select(x => Path.GetDirectoryName(GetAssemblyLocation(x)).ToLowerInvariant()).Distinct();
|
||||
}
|
||||
|
||||
// borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/ApplicationParts/RelatedAssemblyAttribute.cs
|
||||
private string GetAssemblyLocation(Assembly assembly)
|
||||
{
|
||||
if (Uri.TryCreate(assembly.CodeBase, UriKind.Absolute, out var result) &&
|
||||
result.IsFile && string.IsNullOrWhiteSpace(result.Fragment))
|
||||
{
|
||||
return result.LocalPath;
|
||||
}
|
||||
|
||||
return assembly.Location;
|
||||
}
|
||||
|
||||
private Classification Resolve(Assembly assembly)
|
||||
{
|
||||
if (_classifications.TryGetValue(assembly, out var classification))
|
||||
{
|
||||
return classification;
|
||||
}
|
||||
|
||||
// Initialize the dictionary with a value to short-circuit recursive references.
|
||||
classification = Classification.Unknown;
|
||||
_classifications[assembly] = classification;
|
||||
|
||||
if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => assembly.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)))
|
||||
{
|
||||
// if its part of the filter it doesn't reference umbraco
|
||||
classification = Classification.DoesNotReferenceUmbraco;
|
||||
}
|
||||
else if (_umbracoAssemblies.Contains(assembly.GetName().Name))
|
||||
{
|
||||
classification = Classification.IsUmbraco;
|
||||
}
|
||||
else
|
||||
{
|
||||
classification = Classification.DoesNotReferenceUmbraco;
|
||||
foreach (var reference in GetReferences(assembly))
|
||||
{
|
||||
// recurse
|
||||
var referenceClassification = Resolve(reference);
|
||||
|
||||
if (referenceClassification == Classification.IsUmbraco || referenceClassification == Classification.ReferencesUmbraco)
|
||||
{
|
||||
classification = Classification.ReferencesUmbraco;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Assert(classification != Classification.Unknown);
|
||||
_classifications[assembly] = classification;
|
||||
return classification;
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<Assembly> GetReferences(Assembly assembly)
|
||||
{
|
||||
foreach (var referenceName in assembly.GetReferencedAssemblies())
|
||||
{
|
||||
// don't include if this is excluded
|
||||
if (TypeFinder.KnownAssemblyExclusionFilter.Any(f => referenceName.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)))
|
||||
continue;
|
||||
|
||||
var reference = Assembly.Load(referenceName);
|
||||
|
||||
if (!_lookup.Contains(reference))
|
||||
{
|
||||
// A dependency references an item that isn't referenced by this project.
|
||||
// We'll add this reference so that we can calculate the classification.
|
||||
|
||||
_lookup.Add(reference);
|
||||
}
|
||||
yield return reference;
|
||||
}
|
||||
}
|
||||
|
||||
protected enum Classification
|
||||
{
|
||||
Unknown,
|
||||
DoesNotReferenceUmbraco,
|
||||
ReferencesUmbraco,
|
||||
IsUmbraco,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the runtime hash based on file system paths to scan
|
||||
/// </summary>
|
||||
public class RuntimeHash : IRuntimeHash
|
||||
{
|
||||
private readonly IProfilingLogger _logger;
|
||||
private readonly RuntimeHashPaths _paths;
|
||||
|
||||
public RuntimeHash(IProfilingLogger logger, RuntimeHashPaths paths)
|
||||
{
|
||||
_logger = logger;
|
||||
_paths = paths;
|
||||
}
|
||||
|
||||
|
||||
public string GetHashValue()
|
||||
{
|
||||
var allPaths = _paths.GetFolders()
|
||||
.Select(x => ((FileSystemInfo) x, false))
|
||||
.Concat(_paths.GetFiles().Select(x => ((FileSystemInfo) x.Key, x.Value)));
|
||||
|
||||
var hash = GetFileHash(allPaths);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a unique hash for a combination of FileInfo objects.
|
||||
/// </summary>
|
||||
/// <param name="filesAndFolders">A collection of files.</param>
|
||||
/// <returns>The hash.</returns>
|
||||
/// <remarks>Each file is a tuple containing the FileInfo object and a boolean which indicates whether to hash the
|
||||
/// file properties (false) or the file contents (true).</remarks>
|
||||
private string GetFileHash(IEnumerable<(FileSystemInfo fileOrFolder, bool scanFileContent)> filesAndFolders)
|
||||
{
|
||||
using (_logger.DebugDuration<TypeLoader>("Determining hash of code files on disk", "Hash determined"))
|
||||
{
|
||||
// get the distinct file infos to hash
|
||||
var uniqInfos = new HashSet<string>();
|
||||
var uniqContent = new HashSet<string>();
|
||||
|
||||
using var generator = new HashGenerator();
|
||||
|
||||
foreach (var (fileOrFolder, scanFileContent) in filesAndFolders)
|
||||
{
|
||||
if (scanFileContent)
|
||||
{
|
||||
// add each unique file's contents to the hash
|
||||
// normalize the content for cr/lf and case-sensitivity
|
||||
if (uniqContent.Add(fileOrFolder.FullName))
|
||||
{
|
||||
if (File.Exists(fileOrFolder.FullName) == false) continue;
|
||||
var content = RemoveCrLf(File.ReadAllText(fileOrFolder.FullName));
|
||||
generator.AddCaseInsensitiveString(content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// add each unique folder/file to the hash
|
||||
if (uniqInfos.Add(fileOrFolder.FullName))
|
||||
{
|
||||
generator.AddFileSystemItem(fileOrFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
return generator.GenerateHash();
|
||||
}
|
||||
}
|
||||
|
||||
// fast! (yes, according to benchmarks)
|
||||
private static string RemoveCrLf(string s)
|
||||
{
|
||||
var buffer = new char[s.Length];
|
||||
var count = 0;
|
||||
// ReSharper disable once ForCanBeConvertedToForeach - no!
|
||||
for (var i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (s[i] != '\r' && s[i] != '\n')
|
||||
buffer[count++] = s[i];
|
||||
}
|
||||
return new string(buffer, 0, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Paths used to determine the <see cref="IRuntimeHash"/>
|
||||
/// </summary>
|
||||
public sealed class RuntimeHashPaths
|
||||
{
|
||||
private readonly List<DirectoryInfo> _paths = new List<DirectoryInfo>();
|
||||
private readonly Dictionary<FileInfo, bool> _files = new Dictionary<FileInfo, bool>();
|
||||
|
||||
public void AddFolder(DirectoryInfo pathInfo) => _paths.Add(pathInfo);
|
||||
public void AddFile(FileInfo fileInfo, bool scanFileContent = false) => _files.Add(fileInfo, scanFileContent);
|
||||
|
||||
public IEnumerable<DirectoryInfo> GetFolders() => _paths;
|
||||
public IReadOnlyDictionary<FileInfo, bool> GetFiles() => _files;
|
||||
}
|
||||
}
|
||||
@@ -1,106 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
|
||||
/// <inheritdoc cref="ITypeFinder"/>
|
||||
public class TypeFinder : ITypeFinder
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public TypeFinder(ILogger logger, ITypeFinderConfig typeFinderConfig = null)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_assembliesAcceptingLoadExceptions = typeFinderConfig?.AssembliesAcceptingLoadExceptions.Where(x => !x.IsNullOrWhiteSpace()).ToArray() ?? Array.Empty<string>();
|
||||
_allAssemblies = new Lazy<HashSet<Assembly>>(() =>
|
||||
{
|
||||
HashSet<Assembly> assemblies = null;
|
||||
try
|
||||
{
|
||||
//NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have
|
||||
// already been loaded in to the app domain, instead we will look directly into the bin folder and load each one.
|
||||
var binFolder = GetRootDirectorySafe();
|
||||
var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
|
||||
//var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory;
|
||||
//var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList();
|
||||
assemblies = new HashSet<Assembly>();
|
||||
foreach (var a in binAssemblyFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
var assName = AssemblyName.GetAssemblyName(a);
|
||||
var ass = Assembly.Load(assName);
|
||||
assemblies.Add(ass);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e is SecurityException || e is BadImageFormatException)
|
||||
{
|
||||
//swallow these exceptions
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Since we are only loading in the /bin assemblies above, we will also load in anything that's already loaded (which will include gac items)
|
||||
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
assemblies.Add(a);
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
if (e.InnerException is SecurityException == false)
|
||||
throw;
|
||||
}
|
||||
|
||||
return assemblies;
|
||||
});
|
||||
}
|
||||
|
||||
//Lazy access to the all assemblies list
|
||||
private readonly Lazy<HashSet<Assembly>> _allAssemblies;
|
||||
private readonly IAssemblyProvider _assemblyProvider;
|
||||
private readonly IRuntimeHash _runtimeHash;
|
||||
private volatile HashSet<Assembly> _localFilteredAssemblyCache;
|
||||
private readonly object _localFilteredAssemblyCacheLocker = new object();
|
||||
private readonly List<string> _notifiedLoadExceptionAssemblies = new List<string>();
|
||||
private static readonly ConcurrentDictionary<string, Type> TypeNamesCache= new ConcurrentDictionary<string, Type>();
|
||||
private string _rootDir = "";
|
||||
private static readonly ConcurrentDictionary<string, Type> TypeNamesCache = new ConcurrentDictionary<string, Type>();
|
||||
private readonly string[] _assembliesAcceptingLoadExceptions;
|
||||
|
||||
// FIXME - this is only an interim change, once the IIOHelper stuff is merged we should use IIOHelper here
|
||||
private string GetRootDirectorySafe()
|
||||
// used for benchmark tests
|
||||
internal bool QueryWithReferencingAssemblies = true;
|
||||
|
||||
public TypeFinder(ILogger logger, IAssemblyProvider assemblyProvider, IRuntimeHash runtimeHash, ITypeFinderConfig typeFinderConfig = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_rootDir) == false)
|
||||
{
|
||||
return _rootDir;
|
||||
}
|
||||
|
||||
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
var baseDirectory = Path.GetDirectoryName(path);
|
||||
if (string.IsNullOrEmpty(baseDirectory))
|
||||
throw new PanicException("No root directory could be resolved.");
|
||||
|
||||
_rootDir = baseDirectory.Contains("bin")
|
||||
? baseDirectory.Substring(0, baseDirectory.LastIndexOf("bin", StringComparison.OrdinalIgnoreCase) - 1)
|
||||
: baseDirectory;
|
||||
|
||||
return _rootDir;
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_assemblyProvider = assemblyProvider;
|
||||
_runtimeHash = runtimeHash;
|
||||
_assembliesAcceptingLoadExceptions = typeFinderConfig?.AssembliesAcceptingLoadExceptions.Where(x => !x.IsNullOrWhiteSpace()).ToArray() ?? Array.Empty<string>();
|
||||
}
|
||||
|
||||
private bool AcceptsLoadExceptions(Assembly a)
|
||||
@@ -119,22 +50,8 @@ namespace Umbraco.Core.Composing
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// lazily load a reference to all assemblies and only local assemblies.
|
||||
/// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
|
||||
/// loaded in the CLR, not all assemblies.
|
||||
/// See these threads:
|
||||
/// http://issues.umbraco.org/issue/U5-198
|
||||
/// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app
|
||||
/// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl
|
||||
/// </remarks>
|
||||
private IEnumerable<Assembly> GetAllAssemblies()
|
||||
{
|
||||
return _allAssemblies.Value;
|
||||
}
|
||||
|
||||
private IEnumerable<Assembly> GetAllAssemblies() => _assemblyProvider.Assemblies;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Assembly> AssembliesToScan
|
||||
@@ -181,7 +98,10 @@ namespace Umbraco.Core.Composing
|
||||
/// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match
|
||||
/// NOTE this means that "foo." will NOT exclude "foo.dll" but only "foo.*.dll"
|
||||
/// </remarks>
|
||||
private static readonly string[] KnownAssemblyExclusionFilter = {
|
||||
internal static readonly string[] KnownAssemblyExclusionFilter = {
|
||||
"mscorlib,",
|
||||
"netstandard,",
|
||||
"System,",
|
||||
"Antlr3.",
|
||||
"AutoMapper,",
|
||||
"AutoMapper.",
|
||||
@@ -228,7 +148,14 @@ namespace Umbraco.Core.Composing
|
||||
"WebDriver,",
|
||||
"itextsharp,",
|
||||
"mscorlib,",
|
||||
"nunit.framework,",
|
||||
"NUnit,",
|
||||
"NUnit.",
|
||||
"NUnit3.",
|
||||
"Selenium.",
|
||||
"ImageProcessor",
|
||||
"MiniProfiler.",
|
||||
"Owin,",
|
||||
"SQLite",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -283,6 +210,9 @@ namespace Umbraco.Core.Composing
|
||||
return GetClassesWithAttribute(attributeType, assemblyList, onlyConcreteClasses);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetRuntimeHash() => _runtimeHash.GetHashValue();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Type for the string type name
|
||||
/// </summary>
|
||||
@@ -290,6 +220,11 @@ namespace Umbraco.Core.Composing
|
||||
/// <returns></returns>
|
||||
public virtual Type GetTypeByName(string name)
|
||||
{
|
||||
|
||||
//NOTE: This will not find types in dynamic assemblies unless those assemblies are already loaded
|
||||
//into the appdomain.
|
||||
|
||||
|
||||
// This is exactly what the BuildManager does, if the type is an assembly qualified type
|
||||
// name it will find it.
|
||||
if (TypeNameContainsAssembly(name))
|
||||
@@ -340,18 +275,24 @@ namespace Umbraco.Core.Composing
|
||||
var stack = new Stack<Assembly>();
|
||||
stack.Push(attributeType.Assembly);
|
||||
|
||||
if (!QueryWithReferencingAssemblies)
|
||||
{
|
||||
foreach (var a in candidateAssemblies)
|
||||
stack.Push(a);
|
||||
}
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var assembly = stack.Pop();
|
||||
|
||||
Type[] assemblyTypes = null;
|
||||
IReadOnlyList<Type> assemblyTypes = null;
|
||||
if (assembly != attributeType.Assembly || attributeAssemblyIsCandidate)
|
||||
{
|
||||
// get all assembly types that can be assigned to baseType
|
||||
try
|
||||
{
|
||||
assemblyTypes = GetTypesWithFormattedException(assembly)
|
||||
.ToArray(); // in try block
|
||||
.ToList(); // in try block
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
@@ -371,10 +312,13 @@ namespace Umbraco.Core.Composing
|
||||
if (assembly != attributeType.Assembly && assemblyTypes.Where(attributeType.IsAssignableFrom).Any() == false)
|
||||
continue;
|
||||
|
||||
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
|
||||
if (QueryWithReferencingAssemblies)
|
||||
{
|
||||
candidateAssemblies.Remove(referencing);
|
||||
stack.Push(referencing);
|
||||
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
|
||||
{
|
||||
candidateAssemblies.Remove(referencing);
|
||||
stack.Push(referencing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,19 +349,25 @@ namespace Umbraco.Core.Composing
|
||||
var stack = new Stack<Assembly>();
|
||||
stack.Push(baseType.Assembly);
|
||||
|
||||
if (!QueryWithReferencingAssemblies)
|
||||
{
|
||||
foreach (var a in candidateAssemblies)
|
||||
stack.Push(a);
|
||||
}
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var assembly = stack.Pop();
|
||||
|
||||
// get all assembly types that can be assigned to baseType
|
||||
Type[] assemblyTypes = null;
|
||||
IReadOnlyList<Type> assemblyTypes = null;
|
||||
if (assembly != baseType.Assembly || baseTypeAssemblyIsCandidate)
|
||||
{
|
||||
try
|
||||
{
|
||||
assemblyTypes = GetTypesWithFormattedException(assembly)
|
||||
.Where(baseType.IsAssignableFrom)
|
||||
.ToArray(); // in try block
|
||||
.ToList(); // in try block
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
@@ -437,10 +387,13 @@ namespace Umbraco.Core.Composing
|
||||
if (assembly != baseType.Assembly && assemblyTypes.All(x => x.IsSealed))
|
||||
continue;
|
||||
|
||||
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
|
||||
if (QueryWithReferencingAssemblies)
|
||||
{
|
||||
candidateAssemblies.Remove(referencing);
|
||||
stack.Push(referencing);
|
||||
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
|
||||
{
|
||||
candidateAssemblies.Remove(referencing);
|
||||
stack.Push(referencing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,6 +475,5 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user