Merge branch 'v8/dev' into v8/bugfix/AB10622-be-property-editor-caching

This commit is contained in:
Mole
2021-06-22 10:43:58 +02:00
73 changed files with 17119 additions and 16661 deletions

View File

@@ -16,6 +16,8 @@ namespace Umbraco.Core.Composing
{
protected abstract TBuilder This { get; }
private readonly Dictionary<Type, int> _customWeights = new Dictionary<Type, int>();
/// <summary>
/// Clears all types in the collection.
/// </summary>
@@ -107,6 +109,18 @@ namespace Umbraco.Core.Composing
return This;
}
/// <summary>
/// Changes the default weight of an item
/// </summary>
/// <typeparam name="T">The type of item</typeparam>
/// <param name="weight">The new weight</param>
/// <returns></returns>
public TBuilder SetWeight<T>(int weight) where T : TItem
{
_customWeights[typeof(T)] = weight;
return This;
}
protected override IEnumerable<Type> GetRegisteringTypes(IEnumerable<Type> types)
{
var list = types.ToList();
@@ -118,6 +132,8 @@ namespace Umbraco.Core.Composing
protected virtual int GetWeight(Type type)
{
if (_customWeights.ContainsKey(type))
return _customWeights[type];
var attr = type.GetCustomAttributes(typeof(WeightAttribute), false).OfType<WeightAttribute>().SingleOrDefault();
return attr?.Weight ?? DefaultWeight;
}

View File

@@ -25,7 +25,7 @@ namespace Umbraco.Core
/// <summary>
/// The name of the 'unknown' user.
/// </summary>
public const string UnknownUserName = "SYTEM";
public const string UnknownUserName = "SYSTEM";
public const string AdminGroupAlias = "admin";
public const string EditorGroupAlias = "editor";

View File

@@ -0,0 +1,9 @@
namespace Umbraco.Core.Events
{
/// <summary>
/// Used to notify that an Unattended install has completed
/// </summary>
public class UnattendedInstallEventArgs : System.ComponentModel.CancelEventArgs
{
}
}

View File

@@ -141,14 +141,14 @@ namespace Umbraco.Core.Migrations.Install
//New UDI pickers with newer Ids
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1046, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1046", SortOrder = 2, UniqueId = new Guid("FD1E0DA5-5606-4862-B679-5D0CF3A52A59"), Text = "Content Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = new Guid("1EA2E01F-EBD8-4CE1-8D71-6B1149E63548"), Text = "Member Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "Media Picker (old)", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = new Guid("9DBBCBBB-2327-434A-B355-AF1B84E5010A"), Text = "Multiple Media Picker (old)", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "(Obsolete) Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = new Guid("9DBBCBBB-2327-434A-B355-AF1B84E5010A"), Text = "(Obsolete) Multiple Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1050, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1050", SortOrder = 2, UniqueId = new Guid("B4E3535A-1753-47E2-8568-602CF8CFEE6F"), Text = "Multi URL Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1051, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1051", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.MediaPicker3Guid, Text = "Media Picker 3", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1052, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1052", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.MediaPicker3MultipleGuid, Text = "Multiple Media Picker 3", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1053, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1053", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.MediaPicker3SingleImageGuid, Text = "Image Media Picker 3", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1054, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1054", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.MediaPicker3MultipleImagesGuid, Text = "Multiple Image Media Picker 3", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1051, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1051", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.MediaPicker3Guid, Text = "Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1052, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1052", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.MediaPicker3MultipleGuid, Text = "Multiple Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1053, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1053", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.MediaPicker3SingleImageGuid, Text = "Image Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1054, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1054", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.MediaPicker3MultipleImagesGuid, Text = "Multiple Image Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
}
@@ -350,8 +350,7 @@ namespace Umbraco.Core.Migrations.Install
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1046, EditorAlias = Constants.PropertyEditors.Aliases.ContentPicker, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1047, EditorAlias = Constants.PropertyEditors.Aliases.MemberPicker, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1048, EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1049, EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker, DbType = "Ntext",
Configuration = "{\"multiPicker\":1}" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1049, EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker, DbType = "Ntext", Configuration = "{\"multiPicker\":1}" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1050, EditorAlias = Constants.PropertyEditors.Aliases.MultiUrlPicker, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto

View File

@@ -29,7 +29,7 @@ namespace Umbraco.Core.Models.Entities
/// <inheritdoc />
public virtual bool IsPropertyDirty(string propertyName)
{
return _currentChanges != null && _currentChanges.Any(x => x.Key == propertyName);
return _currentChanges != null && _currentChanges.ContainsKey(propertyName);
}
/// <inheritdoc />
@@ -61,7 +61,7 @@ namespace Umbraco.Core.Models.Entities
/// <inheritdoc />
public virtual bool WasPropertyDirty(string propertyName)
{
return _savedChanges != null && _savedChanges.Any(x => x.Key == propertyName);
return _savedChanges != null && _savedChanges.ContainsKey(propertyName);
}
/// <inheritdoc />

View File

@@ -1,13 +1,17 @@
using System;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Web;
using System.Web.Hosting;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -16,6 +20,9 @@ using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Migrations.Upgrade;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Scoping;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
namespace Umbraco.Core.Runtime
@@ -119,6 +126,9 @@ namespace Umbraco.Core.Runtime
try
{
// Setup event listener
UnattendedInstalled += CoreRuntime_UnattendedInstalled;
// throws if not full-trust
new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted).Demand();
@@ -162,8 +172,7 @@ namespace Umbraco.Core.Runtime
// run handlers
RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory);
// determines if unattended install is enabled and performs it if required
DoUnattendedInstall(databaseFactory);
// register runtime-level services
// there should be none, really - this is here "just in case"
@@ -190,6 +199,13 @@ namespace Umbraco.Core.Runtime
// create the factory
_factory = Current.Factory = composition.CreateFactory();
// determines if unattended install is enabled and performs it if required
DoUnattendedInstall(databaseFactory);
// determine our runtime level (AFTER UNATTENDED INSTALL)
// TODO: Feels kinda weird to call this again
DetermineRuntimeLevel(databaseFactory, ProfilingLogger);
// if level is Run and reason is UpgradeMigrations, that means we need to perform an unattended upgrade
if (_state.Reason == RuntimeLevelReason.UpgradeMigrations && _state.Level == RuntimeLevel.Run)
{
@@ -203,8 +219,6 @@ namespace Umbraco.Core.Runtime
// create & initialize the components
_components = _factory.GetInstance<ComponentCollection>();
_components.Initialize();
}
catch (Exception e)
{
@@ -242,6 +256,93 @@ namespace Umbraco.Core.Runtime
return _factory;
}
private void CoreRuntime_UnattendedInstalled(IRuntime sender, UnattendedInstallEventArgs e)
{
var unattendedName = Environment.GetEnvironmentVariable("UnattendedUserName");
var unattendedEmail = Environment.GetEnvironmentVariable("UnattendedUserEmail");
var unattendedPassword = Environment.GetEnvironmentVariable("UnattendedUserPassword");
var fileExists = false;
var filePath = IOHelper.MapPath("~/App_Data/unattended.user.json");
// No values store in ENV vars - try fallback file of /app_data/unattended.user.json
if (unattendedName.IsNullOrWhiteSpace()
|| unattendedEmail.IsNullOrWhiteSpace()
|| unattendedPassword.IsNullOrWhiteSpace())
{
fileExists = File.Exists(filePath);
if (fileExists == false)
{
return;
}
// Attempt to deserialize JSON
try
{
var fileContents = File.ReadAllText(filePath);
var credentials = JsonConvert.DeserializeObject<UnattendedUserConfig>(fileContents);
unattendedName = credentials.Name;
unattendedEmail = credentials.Email;
unattendedPassword = credentials.Password;
}
catch (Exception ex)
{
throw;
}
}
// ENV Variables & JSON still empty
if (unattendedName.IsNullOrWhiteSpace()
|| unattendedEmail.IsNullOrWhiteSpace()
|| unattendedPassword.IsNullOrWhiteSpace())
{
return;
}
// Update user details
var currentProvider = MembershipProviderExtensions.GetUsersMembershipProvider();
var admin = Current.Services.UserService.GetUserById(Constants.Security.SuperUserId);
if (admin == null)
{
throw new InvalidOperationException("Could not find the super user!");
}
var membershipUser = currentProvider.GetUser(Constants.Security.SuperUserId, true);
if (membershipUser == null)
{
throw new InvalidOperationException($"No user found in membership provider with id of {Constants.Security.SuperUserId}.");
}
try
{
var success = membershipUser.ChangePassword("default", unattendedPassword.Trim());
if (success == false)
{
throw new FormatException("Password must be at least " + currentProvider.MinRequiredPasswordLength + " characters long and contain at least " + currentProvider.MinRequiredNonAlphanumericCharacters + " symbols");
}
}
catch (Exception)
{
throw new FormatException("Password must be at least " + currentProvider.MinRequiredPasswordLength + " characters long and contain at least " + currentProvider.MinRequiredNonAlphanumericCharacters + " symbols");
}
admin.Email = unattendedEmail.Trim();
admin.Name = unattendedName.Trim();
admin.Username = unattendedEmail.Trim();
Current.Services.UserService.Save(admin);
// Delete JSON file if it existed to tidy
if (fileExists)
{
File.Delete(filePath);
}
}
private void DoUnattendedInstall(IUmbracoDatabaseFactory databaseFactory)
{
// unattended install is not enabled
@@ -285,6 +386,11 @@ namespace Umbraco.Core.Runtime
var creator = new DatabaseSchemaCreator(database, Logger);
creator.InitializeDatabaseSchema();
database.CompleteTransaction();
// Emit an event that unattended install completed
// Then this event can be listened for and create an unattended user
UnattendedInstalled?.Invoke(this, new UnattendedInstallEventArgs());
Logger.Info<CoreRuntime>("Unattended install completed.");
}
catch (Exception ex)
@@ -397,6 +503,7 @@ namespace Umbraco.Core.Runtime
public virtual void Terminate()
{
_components?.Terminate();
UnattendedInstalled -= CoreRuntime_UnattendedInstalled;
}
/// <summary>
@@ -404,7 +511,7 @@ namespace Umbraco.Core.Runtime
/// </summary>
public virtual void Compose(Composition composition)
{
// nothing
// Nothing
}
#region Getters
@@ -465,5 +572,23 @@ namespace Umbraco.Core.Runtime
}
#endregion
/// <summary>
/// Event to be used to notify when the Unattended Install has finished
/// </summary>
public static event TypedEventHandler<IRuntime, UnattendedInstallEventArgs> UnattendedInstalled;
[DataContract]
public class UnattendedUserConfig
{
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "email")]
public string Email { get; set; }
[DataMember(Name = "password")]
public string Password { get; set; }
}
}
}

View File

@@ -131,6 +131,7 @@
<Compile Include="Constants-CharArrays.cs" />
<Compile Include="Collections\EventClearingObservableCollection.cs" />
<Compile Include="Constants-SqlTemplates.cs" />
<Compile Include="Events\UnattendedInstallEventArgs.cs" />
<Compile Include="Logging\ILogger2.cs" />
<Compile Include="Logging\Logger2Extensions.cs" />
<Compile Include="Dashboards\ContentDashboardSettings.cs" />