Merge remote-tracking branch 'origin/netcore/netcore' into netcore/feature/migrate-logging

Signed-off-by: Bjarke Berg <mail@bergmania.dk>

# Conflicts:
#	src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs
#	src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs
#	src/Umbraco.Tests.Integration/Implementations/TestHelper.cs
#	src/Umbraco.Tests.Integration/Persistence/Repositories/TemplateRepositoryTest.cs
#	src/Umbraco.Tests.Integration/RuntimeTests.cs
#	src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/ColorListValidatorTest.cs
#	src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/EnsureUniqueValuesValidatorTest.cs
#	src/Umbraco.Tests.UnitTests/Umbraco.Core/PropertyEditors/MultiValuePropertyEditorTests.cs
#	src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs
#	src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/PropertyCacheLevelTests.cs
#	src/Umbraco.Tests/Components/ComponentTests.cs
#	src/Umbraco.Tests/IO/ShadowFileSystemTests.cs
#	src/Umbraco.Tests/Models/VariationTests.cs
#	src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs
#	src/Umbraco.Tests/Persistence/DatabaseContextTests.cs
#	src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs
#	src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs
#	src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs
#	src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs
#	src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs
#	src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs
#	src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs
#	src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs
#	src/Umbraco.Tests/Published/ConvertersTests.cs
#	src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs
#	src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs
#	src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs
#	src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs
#	src/Umbraco.Tests/Routing/UmbracoModuleTests.cs
#	src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs
#	src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs
#	src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs
#	src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs
This commit is contained in:
Bjarke Berg
2020-09-23 07:17:05 +02:00
193 changed files with 1946 additions and 2057 deletions

View File

@@ -29,7 +29,9 @@ namespace Umbraco.Core.Configuration
ConnectionString = connectionString
};
if (builder.TryGetValue("Data Source", out var ds) && ds is string dataSource)
if (
(builder.TryGetValue("Data Source", out var ds)
|| builder.TryGetValue("DataSource", out ds)) && ds is string dataSource)
{
if (dataSource.EndsWith(".sdf"))
{
@@ -37,6 +39,7 @@ namespace Umbraco.Core.Configuration
}
}
if (builder.TryGetValue("Server", out var s) && s is string server && !string.IsNullOrEmpty(server))
{
if (builder.TryGetValue("Database", out var db) && db is string database && !string.IsNullOrEmpty(database))

View File

@@ -39,7 +39,7 @@ namespace Umbraco.Core.Configuration
/// <param name="contentSettings"></param>
/// <param name="propertyTypeAlias">The property type alias.</param>
/// <returns>The auto-fill configuration for the specified property alias, or null.</returns>
public static IImagingAutoFillUploadField GetConfig(this ContentSettings contentSettings, string propertyTypeAlias)
public static ImagingAutoFillUploadField GetConfig(this ContentSettings contentSettings, string propertyTypeAlias)
{
var autoFillConfigs = contentSettings.Imaging.AutoFillImageProperties;
return autoFillConfigs?.FirstOrDefault(x => x.Alias == propertyTypeAlias);

View File

@@ -1,15 +1,30 @@
using System;
using System.ComponentModel.DataAnnotations;
using Umbraco.Core.Configuration.Models.Validation;
namespace Umbraco.Core.Configuration.Models
{
public class ContentErrorPage
public class ContentErrorPage : ValidatableEntryBase
{
//TODO introduce validation, to check only one of key/id/xPath is used.
public int ContentId { get; }
public Guid ContentKey { get; }
public string ContentXPath { get; }
public bool HasContentId { get; }
public bool HasContentKey { get; }
public int ContentId { get; set; }
public Guid ContentKey { get; set; }
public string ContentXPath { get; set; }
public bool HasContentId => ContentId != 0;
public bool HasContentKey => ContentKey != Guid.Empty;
public bool HasContentXPath => !string.IsNullOrEmpty(ContentXPath);
[Required]
public string Culture { get; set; }
internal override bool IsValid()
{
return base.IsValid() &&
((HasContentId ? 1 : 0) + (HasContentKey ? 1 : 0) + (HasContentXPath ? 1 : 0) == 1);
}
}
}

View File

@@ -1,7 +1,4 @@
using System.Collections.Generic;
using Umbraco.Core.Configuration.UmbracoSettings;
namespace Umbraco.Core.Configuration.Models
namespace Umbraco.Core.Configuration.Models
{
public class ContentImagingSettings
{
@@ -17,17 +14,8 @@ namespace Umbraco.Core.Configuration.Models
}
};
public IEnumerable<string> ImageFileTypes { get; set; } = new[] { "jpeg", "jpg", "gif", "bmp", "png", "tiff", "tif" };
public string[] ImageFileTypes { get; set; } = new[] { "jpeg", "jpg", "gif", "bmp", "png", "tiff", "tif" };
public IEnumerable<IImagingAutoFillUploadField> AutoFillImageProperties { get; set; } = DefaultImagingAutoFillUploadField;
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; }
}
public ImagingAutoFillUploadField[] AutoFillImageProperties { get; set; } = DefaultImagingAutoFillUploadField;
}
}

View File

@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Configuration.Models.Validation;
using Umbraco.Core.Macros;
namespace Umbraco.Core.Configuration.Models
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Configuration.Models
public bool ResolveUrlsFromTextString { get; set; } = false;
public IEnumerable<ContentErrorPage> Error404Collection { get; set; } = Array.Empty<ContentErrorPage>();
public ContentErrorPage[] Error404Collection { get; set; } = Array.Empty<ContentErrorPage>();
public string PreviewBadge { get; set; } = DefaultPreviewBadge;

View File

@@ -1,4 +1,6 @@
namespace Umbraco.Core.Configuration.Models
using System;
namespace Umbraco.Core.Configuration.Models
{
public class HostingSettings
{

View File

@@ -0,0 +1,23 @@
using System.ComponentModel.DataAnnotations;
using Umbraco.Core.Configuration.Models.Validation;
namespace Umbraco.Core.Configuration.Models
{
public class ImagingAutoFillUploadField : ValidatableEntryBase
{
[Required]
public string Alias { get; set; }
[Required]
public string WidthFieldAlias { get; set; }
[Required]
public string HeightFieldAlias { get; set; }
[Required]
public string LengthFieldAlias { get; set; }
[Required]
public string ExtensionFieldAlias { get; set; }
}
}

View File

@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration.Models
/// <summary>
/// Represents the models builder configuration.
/// </summary>
public class ModelsBuilderConfig
public class ModelsBuilderSettings
{
public static string DefaultModelsDirectory => "~/App_Data/Models";

View File

@@ -2,6 +2,6 @@
{
public class NuCacheSettings
{
public string BTreeBlockSize { get; set; }
public int? BTreeBlockSize { get; set; }
}
}

View File

@@ -1,9 +1,14 @@
using System.Net.Mail;
using System;
using System.ComponentModel.DataAnnotations;
using System.Net.Mail;
using Umbraco.Core.Configuration.Models.Validation;
namespace Umbraco.Core.Configuration.Models
{
public class SmtpSettings
public class SmtpSettings : ValidatableEntryBase
{
[Required]
[EmailAddress]
public string From { get; set; }
public string Host { get; set; }
@@ -12,7 +17,7 @@ namespace Umbraco.Core.Configuration.Models
public string PickupDirectoryLocation { get; set; }
public SmtpDeliveryMethod DeliveryMethod { get; set; }
public SmtpDeliveryMethod DeliveryMethod { get; set; } = SmtpDeliveryMethod.Network;
public string Username { get; set; }

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Configuration.Models.Validation
{
public abstract class ConfigurationValidatorBase
{
public bool ValidateStringIsOneOfValidValues(string configPath, string value, IEnumerable<string> validValues, out string message)
{
if (!validValues.InvariantContains(value))
{
message = $"Configuration entry {configPath} contains an invalid value '{value}', it should be one of the following: '{string.Join(", ", validValues)}'.";
return false;
}
message = string.Empty;
return true;
}
public bool ValidateCollection(string configPath, IEnumerable<ValidatableEntryBase> values, string validationDescription, out string message)
{
if (values.Any(x => !x.IsValid()))
{
message = $"Configuration entry {configPath} contains one or more invalid values. {validationDescription}.";
return false;
}
message = string.Empty;
return true;
}
public bool ValidateOptionalEntry(string configPath, ValidatableEntryBase value, string validationDescription, out string message)
{
if (value != null && !value.IsValid())
{
message = $"Configuration entry {configPath} contains one or more invalid values. {validationDescription}.";
return false;
}
message = string.Empty;
return true;
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Collections.Generic;
using Microsoft.Extensions.Options;
using Umbraco.Core.Macros;
namespace Umbraco.Core.Configuration.Models.Validation
{
public class ContentSettingsValidator : ConfigurationValidatorBase, IValidateOptions<ContentSettings>
{
public ValidateOptionsResult Validate(string name, ContentSettings options)
{
string message;
if (!ValidateError404Collection(options.Error404Collection, out message))
{
return ValidateOptionsResult.Fail(message);
}
if (!ValidateAutoFillImageProperties(options.Imaging.AutoFillImageProperties, out message))
{
return ValidateOptionsResult.Fail(message);
}
return ValidateOptionsResult.Success;
}
private bool ValidateError404Collection(IEnumerable<ContentErrorPage> values, out string message)
{
return ValidateCollection($"{Constants.Configuration.ConfigContent}:{nameof(ContentSettings.Error404Collection)}", values, "Culture and one and only one of ContentId, ContentKey and ContentXPath must be specified for each entry", out message);
}
private bool ValidateAutoFillImageProperties(IEnumerable<ImagingAutoFillUploadField> values, out string message)
{
return ValidateCollection($"{Constants.Configuration.ConfigContent}:{nameof(ContentSettings.Imaging)}:{nameof(ContentSettings.Imaging.AutoFillImageProperties)}", values, "Alias, WidthFieldAlias, HeightFieldAlias, LengthFieldAlias and ExtensionFieldAlias must be specified for each entry", out message);
}
}
}

View File

@@ -0,0 +1,23 @@
using Microsoft.Extensions.Options;
namespace Umbraco.Core.Configuration.Models.Validation
{
public class GlobalSettingsValidator
: ConfigurationValidatorBase, IValidateOptions<GlobalSettings>
{
public ValidateOptionsResult Validate(string name, GlobalSettings options)
{
if (!ValidateSmtpSetting(options.Smtp, out var message))
{
return ValidateOptionsResult.Fail(message);
}
return ValidateOptionsResult.Success;
}
private bool ValidateSmtpSetting(SmtpSettings value, out string message)
{
return ValidateOptionalEntry($"{Constants.Configuration.ConfigGlobal}:{nameof(GlobalSettings.Smtp)}", value, "A valid From email address is required", out message);
}
}
}

View File

@@ -0,0 +1,23 @@
using Microsoft.Extensions.Options;
namespace Umbraco.Core.Configuration.Models.Validation
{
public class RequestHandlerSettingsValidator : ConfigurationValidatorBase, IValidateOptions<RequestHandlerSettings>
{
public ValidateOptionsResult Validate(string name, RequestHandlerSettings options)
{
if (!ValidateConvertUrlsToAscii(options.ConvertUrlsToAscii, out var message))
{
return ValidateOptionsResult.Fail(message);
}
return ValidateOptionsResult.Success;
}
private bool ValidateConvertUrlsToAscii(string value, out string message)
{
var validValues = new[] { "try", "true", "false" };
return ValidateStringIsOneOfValidValues($"{Constants.Configuration.ConfigRequestHandler}:{nameof(RequestHandlerSettings.ConvertUrlsToAscii)}", value, validValues, out message);
}
}
}

View File

@@ -0,0 +1,15 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Umbraco.Core.Configuration.Models.Validation
{
public abstract class ValidatableEntryBase
{
internal virtual bool IsValid()
{
var ctx = new ValidationContext(this);
var results = new List<ValidationResult>();
return Validator.TryValidateObject(this, ctx, results, true);
}
}
}

View File

@@ -16,7 +16,7 @@ namespace Umbraco.Core.Configuration.Models
public bool DisableRedirectUrlTracking { get; set; } = false;
public string UrlProviderMode { get; set; } = UrlMode.Auto.ToString();
public UrlMode UrlProviderMode { get; set; } = UrlMode.Auto;
public string UmbracoApplicationUrl { get; set; }
}

View File

@@ -10,7 +10,7 @@ namespace Umbraco.Core.Configuration
{
private static string _modelsDirectoryAbsolute = null;
public static string ModelsDirectoryAbsolute(this ModelsBuilderConfig modelsBuilderConfig, IHostingEnvironment hostingEnvironment)
public static string ModelsDirectoryAbsolute(this ModelsBuilderSettings modelsBuilderConfig, IHostingEnvironment hostingEnvironment)
{
if (_modelsDirectoryAbsolute is null)
{

View File

@@ -11,11 +11,30 @@
/// ":" is used as marker for nested objects in json. E.g. "Umbraco:CMS:" = {"Umbraco":{"CMS":{....}}
/// </remarks>
public const string ConfigPrefix = "Umbraco:CMS:";
public const string ConfigSecurityPrefix = ConfigPrefix+"Security:";
public const string ConfigGlobalPrefix = ConfigPrefix + "Global:";
public const string ConfigModelsBuilderPrefix = ConfigPrefix+"ModelsBuilder:";
public const string ConfigRuntimeMinification = ConfigPrefix+"RuntimeMinification";
public const string ConfigRuntimeMinificationVersion = ConfigRuntimeMinification+":Version";
public const string ConfigActiveDirectory = ConfigPrefix + "ActiveDirectory";
public const string ConfigContent = ConfigPrefix + "Content";
public const string ConfigCoreDebug = ConfigPrefix + "Core:Debug";
public const string ConfigExceptionFilter = ConfigPrefix + "ExceptionFilter";
public const string ConfigGlobal = ConfigPrefix + "Global";
public const string ConfigHealthChecks = ConfigPrefix + "HealthChecks";
public const string ConfigHosting = ConfigPrefix + "Hosting";
public const string ConfigImaging = ConfigPrefix + "Imaging";
public const string ConfigExamine = ConfigPrefix + "Examine";
public const string ConfigKeepAlive = ConfigPrefix + "KeepAlive";
public const string ConfigLogging = ConfigPrefix + "Logging";
public const string ConfigMemberPassword = ConfigPrefix + "Security:MemberPassword";
public const string ConfigModelsBuilder = ConfigPrefix + "ModelsBuilder";
public const string ConfigNuCache = ConfigPrefix + "NuCache";
public const string ConfigRequestHandler = ConfigPrefix + "RequestHandler";
public const string ConfigRuntime = ConfigPrefix + "Runtime";
public const string ConfigSecurity = ConfigPrefix + "Security";
public const string ConfigTours = ConfigPrefix + "Tours";
public const string ConfigTypeFinder = ConfigPrefix + "TypeFinder";
public const string ConfigWebRouting = ConfigPrefix + "WebRouting";
public const string ConfigUserPassword = ConfigPrefix + "Security:UserPassword";
public const string ConfigRuntimeMinification = ConfigPrefix + "RuntimeMinification";
public const string ConfigRuntimeMinificationVersion = ConfigRuntimeMinification + ":Version";
}
}
}

View File

@@ -390,7 +390,6 @@ namespace Umbraco.Core.Models.PublishedContent
protected override bool IsCOMObjectImpl()
=> false;
public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
throw new NotSupportedException();

View File

@@ -31,16 +31,9 @@ namespace Umbraco.Web.Routing
_urlProviders = urlProviders;
_mediaUrlProviders = mediaUrlProviders;
_variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
var provider = UrlMode.Auto;
Mode = provider;
if (Enum<UrlMode>.TryParse(routingSettings.Value.UrlProviderMode, out provider))
{
Mode = provider;
}
Mode = routingSettings.Value.UrlProviderMode;
}
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IEnumerable<IUrlProvider> _urlProviders;
private readonly IEnumerable<IMediaUrlProvider> _mediaUrlProviders;