diff --git a/build/azure-pipelines.yml b/build/azure-pipelines.yml index 38d5e7673b..064b7aec0b 100644 --- a/build/azure-pipelines.yml +++ b/build/azure-pipelines.yml @@ -414,7 +414,7 @@ stages: #Update the version in templates also $templatePath = - 'build/templates/UmbracoProject/.template.config/template.json' + 'templates/UmbracoProject/.template.config/template.json' $a = Get-Content $templatePath -raw | ConvertFrom-Json @@ -424,7 +424,7 @@ stages: $templatePath = - 'build/templates/UmbracoPackage/.template.config/template.json' + 'templates/UmbracoPackage/.template.config/template.json' $a = Get-Content $templatePath -raw | ConvertFrom-Json diff --git a/build/build.ps1 b/build/build.ps1 index da4733d432..24fd548c61 100644 --- a/build/build.ps1 +++ b/build/build.ps1 @@ -11,7 +11,7 @@ [Alias("loc")] [switch] $local = $false, - # enable docfx + # enable docfx [Parameter(Mandatory=$false)] [Alias("doc")] [switch] $docfx = $false, @@ -40,7 +40,7 @@ @{ Continue = $continue }) if ($ubuild.OnError()) { return } - Write-Host "Umbraco Cms Build" + Write-Host "Umbraco CMS Build" Write-Host "Umbraco.Build v$($ubuild.BuildVersion)" # ################################################################ @@ -84,7 +84,7 @@ $this.SetEnvVar("NPM_CONFIG_CACHE", $node_npmcache) $this.SetEnvVar("NPM_CONFIG_PREFIX", $node_npmprefix) - $ignore = $this.ClearEnvVar("NODE_NO_HTTP2") + $this.ClearEnvVar("NODE_NO_HTTP2") }) $ubuild.DefineMethod("CompileBelle", @@ -171,11 +171,6 @@ $src = "$($this.SolutionRoot)\src" $log = "$($this.BuildTemp)\build.umbraco.log" - if ($this.BuildEnv.VisualStudio -eq $null) - { - throw "Build environment does not provide VisualStudio." - } - Write-Host "Compile Umbraco" Write-Host "Logging to $log" @@ -255,27 +250,21 @@ $buildConfiguration = "Release" $log = "$($this.BuildTemp)\msbuild.tests.log" - if ($this.BuildEnv.VisualStudio -eq $null) - { - throw "Build environment does not provide VisualStudio." - } - Write-Host "Compile Tests" Write-Host "Logging to $log" # beware of the weird double \\ at the end of paths # see http://edgylogic.com/blog/powershell-and-external-commands-done-right/ - &$this.BuildEnv.VisualStudio.MsBuild "$($this.SolutionRoot)\tests\Umbraco.Tests\Umbraco.Tests.csproj" ` - /p:WarningLevel=0 ` - /p:Configuration=$buildConfiguration ` - /p:Platform=AnyCPU ` - /p:UseWPP_CopyWebApplication=True ` - /p:PipelineDependsOnBuild=False ` - /p:OutDir="$($this.BuildTemp)\tests\\" ` - /p:Verbosity=minimal ` - /t:Build ` - /tv:"$($this.BuildEnv.VisualStudio.ToolsVersion)" ` - /p:UmbracoBuild=True ` + &dotnet msbuild "$($this.SolutionRoot)\tests\Umbraco.Tests\Umbraco.Tests.csproj" ` + -target:Build ` + -property:WarningLevel=0 ` + -property:Configuration=$buildConfiguration ` + -property:Platform=AnyCPU ` + -property:UseWPP_CopyWebApplication=True ` + -property:PipelineDependsOnBuild=False ` + -property:OutDir="$($this.BuildTemp)\tests\\" ` + -property:Verbosity=minimal ` + -property:UmbracoBuild=True ` > $log # copy Umbraco.Persistence.SqlCe files into WebApp @@ -292,10 +281,6 @@ $src = "$($this.SolutionRoot)\src" $tmp = "$($this.BuildTemp)" - $out = "$($this.BuildOutput)" - $templates = "$($this.SolutionRoot)\build\templates" - - $buildConfiguration = "Release" # cleanup build Write-Host "Clean build" @@ -309,7 +294,6 @@ # create directories Write-Host "Create directories" mkdir "$tmp\WebApp\App_Data" > $null - mkdir "$tmp\Templates" > $null #mkdir "$tmp\WebApp\Media" > $null #mkdir "$tmp\WebApp\Views" > $null @@ -332,10 +316,6 @@ { $nugetPackages = [System.Environment]::ExpandEnvironmentVariables("%userprofile%\.nuget\packages") } - #$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x86\native", "*.*", "$tmp\bin\x86") - #$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x64\native", "*.*", "$tmp\bin\amd64") - #$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x86\native", "*.*", "$tmp\WebApp\bin\x86") - #$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x64\native", "*.*", "$tmp\WebApp\bin\amd64") # copy Belle Write-Host "Copy Belle" @@ -343,19 +323,6 @@ $this.CopyFiles("$src\Umbraco.Web.UI\wwwroot\umbraco\js", "*", "$tmp\WebApp\wwwroot\umbraco\js") $this.CopyFiles("$src\Umbraco.Web.UI\wwwroot\umbraco\lib", "*", "$tmp\WebApp\wwwroot\umbraco\lib") $this.CopyFiles("$src\Umbraco.Web.UI\wwwroot\umbraco\views", "*", "$tmp\WebApp\wwwroot\umbraco\views") - - - - # Prepare templates - Write-Host "Copy template files" - $this.CopyFiles("$templates", "*", "$tmp\Templates") - - Write-Host "Copy files for dotnet templates" - $this.CopyFiles("$src\Umbraco.Web.UI", "Program.cs", "$tmp\Templates\UmbracoProject") - $this.CopyFiles("$src\Umbraco.Web.UI", "Startup.cs", "$tmp\Templates\UmbracoProject") - $this.CopyFiles("$src\Umbraco.Web.UI\Views", "*", "$tmp\Templates\UmbracoProject\Views") - - $this.RemoveDirectory("$tmp\Templates\UmbracoProject\bin") }) @@ -389,7 +356,7 @@ { Write-Host "Restore NuGet" Write-Host "Logging to $($this.BuildTemp)\nuget.restore.log" - $params = "-Source", $nugetsourceUmbraco + $params = "-Source", $nugetsourceUmbraco &$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\umbraco-netcore-only.sln" > "$($this.BuildTemp)\nuget.restore.log" @params if (-not $?) { throw "Failed to restore NuGet packages." } }) @@ -397,7 +364,7 @@ $ubuild.DefineMethod("PackageNuGet", { $nuspecs = "$($this.SolutionRoot)\build\NuSpecs" - $templates = "$($this.BuildTemp)\Templates" + $templates = "$($this.SolutionRoot)\templates" Write-Host "Create NuGet packages" diff --git a/build/templates/UmbracoProject/.template.config/icon.png b/build/templates/UmbracoProject/.template.config/icon.png deleted file mode 100644 index 6e94105808..0000000000 Binary files a/build/templates/UmbracoProject/.template.config/icon.png and /dev/null differ diff --git a/build/templates/UmbracoProject/Views/_ViewImports.cshtml b/build/templates/UmbracoProject/Views/_ViewImports.cshtml deleted file mode 100644 index cb9a0b658e..0000000000 --- a/build/templates/UmbracoProject/Views/_ViewImports.cshtml +++ /dev/null @@ -1,8 +0,0 @@ -@using Umbraco.Web.UI -@using Umbraco.Extensions -@using Umbraco.Web.PublishedModels -@using Umbraco.Cms.Core.Models.PublishedContent -@using Microsoft.AspNetCore.Html -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -@addTagHelper *, Smidge -@inject Smidge.SmidgeHelper SmidgeHelper diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 68962caef4..fb29b57d91 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,12 +1,12 @@ - + - 9.4.0 - 9.4.0 - 9.4.0-rc - 9.4.0 + 9.5.0 + 9.5.0 + 9.5.0-rc + 9.5.0 9.0 en-US Umbraco CMS diff --git a/src/JsonSchema/AppSettings.cs b/src/JsonSchema/AppSettings.cs index f9aa6b500c..0851baba2e 100644 --- a/src/JsonSchema/AppSettings.cs +++ b/src/JsonSchema/AppSettings.cs @@ -92,6 +92,8 @@ namespace JsonSchema public ContentDashboardSettings ContentDashboard { get; set; } public HelpPageSettings HelpPage { get; set; } + + public InstallDefaultDataSettings DefaultDataCreation { get; set; } } /// diff --git a/src/Umbraco.Core/Cache/MacroCacheRefresher.cs b/src/Umbraco.Core/Cache/MacroCacheRefresher.cs index 77550b81d1..e1b65e2a32 100644 --- a/src/Umbraco.Core/Cache/MacroCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/MacroCacheRefresher.cs @@ -46,6 +46,11 @@ namespace Umbraco.Cms.Core.Cache { var payloads = Deserialize(json); + Refresh(payloads); + } + + public override void Refresh(JsonPayload[] payloads) + { foreach (var payload in payloads) { foreach (var alias in GetCacheKeysForAlias(payload.Alias)) @@ -55,11 +60,13 @@ namespace Umbraco.Cms.Core.Cache if (macroRepoCache) { macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey(payload.Id)); + macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey(payload.Alias)); // Repository caching of macro definition by alias } } - base.Refresh(json); + base.Refresh(payloads); } + #endregion #region Json diff --git a/src/Umbraco.Core/Configuration/Models/InstallDefaultDataSettings.cs b/src/Umbraco.Core/Configuration/Models/InstallDefaultDataSettings.cs new file mode 100644 index 0000000000..377e893bbf --- /dev/null +++ b/src/Umbraco.Core/Configuration/Models/InstallDefaultDataSettings.cs @@ -0,0 +1,73 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System.Collections.Generic; + +namespace Umbraco.Cms.Core.Configuration.Models +{ + /// + /// An enumeration of options available for control over installation of default Umbraco data. + /// + public enum InstallDefaultDataOption + { + /// + /// Do not install any items of this type (other than Umbraco defined essential ones). + /// + None, + + /// + /// Only install the default data specified in the + /// + Values, + + /// + /// Install all default data, except that specified in the + /// + ExceptValues, + + /// + /// Install all default data. + /// + All + } + + /// + /// Typed configuration options for installation of default data. + /// + public class InstallDefaultDataSettings + { + /// + /// Gets or sets a value indicating whether to create default data on installation. + /// + public InstallDefaultDataOption InstallData { get; set; } = InstallDefaultDataOption.All; + + /// + /// Gets or sets a value indicating which default data (languages, data types, etc.) should be created when is + /// set to or . + /// + /// + /// + /// For languages, the values provided should be the ISO codes for the languages to be included or excluded, e.g. "en-US". + /// If removing the single default language, ensure that a different one is created via some other means (such + /// as a restore from Umbraco Deploy schema data). + /// + /// + /// For data types, the values provided should be the Guid values used by Umbraco for the data type, listed at: + /// + /// Some data types - such as the string label - cannot be excluded from install as they are required for core Umbraco + /// functionality. + /// Otherwise take care not to remove data types required for default Umbraco media and member types, unless you also + /// choose to exclude them. + /// + /// + /// For media types, the values provided should be the Guid values used by Umbraco for the media type, listed at: + /// https://github.com/umbraco/Umbraco-CMS/blob/v9/dev/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs. + /// + /// + /// For member types, the values provided should be the Guid values used by Umbraco for the member type, listed at: + /// https://github.com/umbraco/Umbraco-CMS/blob/v9/dev/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs. + /// + /// + public IList Values { get; set; } = new List(); + } +} diff --git a/src/Umbraco.Core/Constants-Configuration.cs b/src/Umbraco.Core/Constants-Configuration.cs index bdbd13b2a4..8ee6040deb 100644 --- a/src/Umbraco.Core/Constants-Configuration.cs +++ b/src/Umbraco.Core/Constants-Configuration.cs @@ -56,6 +56,21 @@ namespace Umbraco.Cms.Core public const string ConfigPackageMigration = ConfigPrefix + "PackageMigration"; public const string ConfigContentDashboard = ConfigPrefix + "ContentDashboard"; public const string ConfigHelpPage = ConfigPrefix + "HelpPage"; + public const string ConfigInstallDefaultData = ConfigPrefix + "InstallDefaultData"; + + public static class NamedOptions + { + public static class InstallDefaultData + { + public const string Languages = "Languages"; + + public const string DataTypes = "DataTypes"; + + public const string MediaTypes = "MediaTypes"; + + public const string MemberTypes = "MemberTypes"; + } + } } } } diff --git a/src/Umbraco.Core/Constants-DataTypes.cs b/src/Umbraco.Core/Constants-DataTypes.cs index 12445ea589..ba8827cd26 100644 --- a/src/Umbraco.Core/Constants-DataTypes.cs +++ b/src/Umbraco.Core/Constants-DataTypes.cs @@ -211,7 +211,6 @@ namespace Umbraco.Cms.Core /// public static readonly Guid ListViewMembersGuid = new Guid(ListViewMembers); - /// /// Guid for Date Picker with time as string /// diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs index 91e6f71415..6d09d82300 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs @@ -90,6 +90,19 @@ namespace Umbraco.Cms.Core.DependencyInjection .AddUmbracoOptions() .AddUmbracoOptions(); + builder.Services.Configure( + Constants.Configuration.NamedOptions.InstallDefaultData.Languages, + builder.Config.GetSection($"{Constants.Configuration.ConfigInstallDefaultData}:{Constants.Configuration.NamedOptions.InstallDefaultData.Languages}")); + builder.Services.Configure( + Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + builder.Config.GetSection($"{Constants.Configuration.ConfigInstallDefaultData}:{Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes}")); + builder.Services.Configure( + Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, + builder.Config.GetSection($"{Constants.Configuration.ConfigInstallDefaultData}:{Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes}")); + builder.Services.Configure( + Constants.Configuration.NamedOptions.InstallDefaultData.MemberTypes, + builder.Config.GetSection($"{Constants.Configuration.ConfigInstallDefaultData}:{Constants.Configuration.NamedOptions.InstallDefaultData.MemberTypes}")); + builder.Services.Configure(options => options.MergeReplacements(builder.Config)); return builder; diff --git a/src/Umbraco.Core/Persistence/Repositories/IMacroWithAliasRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMacroWithAliasRepository.cs new file mode 100644 index 0000000000..f6cd27ad60 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/IMacroWithAliasRepository.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using Umbraco.Cms.Core.Models; + +namespace Umbraco.Cms.Core.Persistence.Repositories +{ + [Obsolete("This interface will be merged with IMacroRepository in Umbraco 11")] + public interface IMacroWithAliasRepository : IMacroRepository + { + IMacro GetByAlias(string alias); + + IEnumerable GetAllByAlias(string[] aliases); + } +} diff --git a/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs index 42746a9565..e6ca8eaa50 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs @@ -1,14 +1,42 @@ -using System; using System.Collections.Generic; using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Models.Entities; namespace Umbraco.Cms.Core.Persistence.Repositories { public interface ITrackedReferencesRepository { - IEnumerable GetPagedRelationsForItems(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency,out long totalRecords); - IEnumerable GetPagedItemsWithRelations(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency,out long totalRecords); - IEnumerable GetPagedDescendantsInReferences(int parentId, long pageIndex, int pageSize, bool filterMustBeIsDependency,out long totalRecords); + /// + /// Gets a page of items which are in relation with the current item. + /// Basically, shows the items which depend on the current item. + /// + /// The identifier of the entity to retrieve relations for. + /// The page index. + /// The page size. + /// A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true). + /// The total count of the items with reference to the current item. + /// An enumerable list of objects. + IEnumerable GetPagedRelationsForItem(int id, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords); + + /// + /// Gets a page of items used in any kind of relation from selected integer ids. + /// + /// The identifiers of the entities to check for relations. + /// The page index. + /// The page size. + /// A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true). + /// The total count of the items in any kind of relation. + /// An enumerable list of objects. + IEnumerable GetPagedItemsWithRelations(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords); + + /// + /// Gets a page of the descending items that have any references, given a parent id. + /// + /// The unique identifier of the parent to retrieve descendants for. + /// The page index. + /// The page size. + /// A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true). + /// The total count of descending items. + /// An enumerable list of objects. + IEnumerable GetPagedDescendantsInReferences(int parentId, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords); } } diff --git a/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs index 048ad40ac0..4d88431e7c 100644 --- a/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleContentPickerParameterEditor.cs @@ -1,5 +1,5 @@ -using Microsoft.Extensions.Logging; -using Umbraco.Cms.Core.Hosting; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; @@ -28,5 +28,17 @@ namespace Umbraco.Cms.Core.PropertyEditors.ParameterEditors DefaultConfiguration.Add("minNumber",0 ); DefaultConfiguration.Add("maxNumber", 0); } + + protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute); + + internal class MultipleContentPickerParamateterValueEditor : MultiplePickerParamateterValueEditorBase + { + public MultipleContentPickerParamateterValueEditor(ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, IIOHelper ioHelper, DataEditorAttribute attribute, IEntityService entityService) : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute, entityService) + { + } + + public override string UdiEntityType { get; } = Constants.UdiEntityType.Document; + public override UmbracoObjectTypes UmbracoObjectType { get; } = UmbracoObjectTypes.Document; + } } } diff --git a/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs index d8f74b1b28..dfdd6f9b9c 100644 --- a/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultipleMediaPickerParameterEditor.cs @@ -1,5 +1,9 @@ -using Microsoft.Extensions.Logging; -using Umbraco.Cms.Core.Hosting; +using System; +using System.Collections.Generic; +using System.Reflection.Metadata; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Editors; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; @@ -26,5 +30,17 @@ namespace Umbraco.Cms.Core.PropertyEditors.ParameterEditors { DefaultConfiguration.Add("multiPicker", "1"); } + + protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute); + + internal class MultipleMediaPickerPropertyValueEditor : MultiplePickerParamateterValueEditorBase + { + public MultipleMediaPickerPropertyValueEditor(ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, IIOHelper ioHelper, DataEditorAttribute attribute, IEntityService entityService) : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute, entityService) + { + } + + public override string UdiEntityType { get; } = Constants.UdiEntityType.Media; + public override UmbracoObjectTypes UmbracoObjectType { get; } = UmbracoObjectTypes.Media; + } } } diff --git a/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePickerParamateterValueEditorBase.cs b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePickerParamateterValueEditorBase.cs new file mode 100644 index 0000000000..2c4f27b560 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/ParameterEditors/MultiplePickerParamateterValueEditorBase.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Editors; +using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Strings; + +namespace Umbraco.Cms.Core.PropertyEditors.ParameterEditors +{ + internal abstract class MultiplePickerParamateterValueEditorBase : DataValueEditor, IDataValueReference + { + private readonly IEntityService _entityService; + + public MultiplePickerParamateterValueEditorBase( + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + IIOHelper ioHelper, + DataEditorAttribute attribute, + IEntityService entityService) + : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute) + { + _entityService = entityService; + } + + public abstract string UdiEntityType { get; } + public abstract UmbracoObjectTypes UmbracoObjectType { get; } + public IEnumerable GetReferences(object value) + { + var asString = value is string str ? str : value?.ToString(); + + if (string.IsNullOrEmpty(asString)) + { + yield break; + } + + foreach (var udiStr in asString.Split(',')) + { + if (UdiParser.TryParse(udiStr, out Udi udi)) + { + yield return new UmbracoEntityReference(udi); + } + + // this is needed to support the legacy case when the multiple media picker parameter editor stores ints not udis + if (int.TryParse(udiStr, out var id)) + { + Attempt guidAttempt = _entityService.GetKey(id, UmbracoObjectType); + Guid guid = guidAttempt.Success ? guidAttempt.Result : Guid.Empty; + + if (guid != Guid.Empty) + { + yield return new UmbracoEntityReference(new GuidUdi(Constants.UdiEntityType.Media, guid)); + } + + } + } + } + } +} diff --git a/src/Umbraco.Core/Security/LegacyPasswordSecurity.cs b/src/Umbraco.Core/Security/LegacyPasswordSecurity.cs index ca3045a4de..b8c7596b2d 100644 --- a/src/Umbraco.Core/Security/LegacyPasswordSecurity.cs +++ b/src/Umbraco.Core/Security/LegacyPasswordSecurity.cs @@ -8,12 +8,17 @@ namespace Umbraco.Cms.Core.Security { /// - /// Handles password hashing and formatting for legacy hashing algorithms + /// Handles password hashing and formatting for legacy hashing algorithms. /// + /// + /// Should probably be internal. + /// public class LegacyPasswordSecurity { + // TODO: Remove v11 // Used for tests [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("We shouldn't be altering our public API to make test code easier, removing v11")] public string HashPasswordForStorage(string algorithmType, string password) { if (string.IsNullOrWhiteSpace(password)) @@ -24,13 +29,15 @@ namespace Umbraco.Cms.Core.Security return FormatPasswordForStorage(algorithmType, hashed, salt); } + // TODO: Remove v11 // Used for tests [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("We shouldn't be altering our public API to make test code easier, removing v11")] public string FormatPasswordForStorage(string algorithmType, string hashedPassword, string salt) { - if (IsLegacySHA1Algorithm(algorithmType)) + if (!SupportHashAlgorithm(algorithmType)) { - return hashedPassword; + throw new InvalidOperationException($"{algorithmType} is not supported"); } return salt + hashedPassword; @@ -45,10 +52,15 @@ namespace Umbraco.Cms.Core.Security /// public bool VerifyPassword(string algorithm, string password, string dbPassword) { - if (string.IsNullOrWhiteSpace(dbPassword)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(dbPassword)); + if (string.IsNullOrWhiteSpace(dbPassword)) + { + throw new ArgumentException("Value cannot be null or whitespace.", nameof(dbPassword)); + } if (dbPassword.StartsWith(Constants.Security.EmptyPasswordPrefix)) + { return false; + } try { @@ -61,7 +73,6 @@ namespace Umbraco.Cms.Core.Security //This can happen if the length of the password is wrong and a salt cannot be extracted. return false; } - } /// @@ -69,12 +80,13 @@ namespace Umbraco.Cms.Core.Security /// public bool VerifyLegacyHashedPassword(string password, string dbPassword) { - var hashAlgorith = new HMACSHA1 + var hashAlgorithm = new HMACSHA1 { //the legacy salt was actually the password :( Key = Encoding.Unicode.GetBytes(password) }; - var hashed = Convert.ToBase64String(hashAlgorith.ComputeHash(Encoding.Unicode.GetBytes(password))); + + var hashed = Convert.ToBase64String(hashAlgorithm.ComputeHash(Encoding.Unicode.GetBytes(password))); return dbPassword == hashed; } @@ -87,6 +99,8 @@ namespace Umbraco.Cms.Core.Security /// /// // TODO: Do we need this method? We shouldn't be using this class to create new password hashes for storage + // TODO: Remove v11 + [Obsolete("We shouldn't be altering our public API to make test code easier, removing v11")] public string HashNewPassword(string algorithm, string newPassword, out string salt) { salt = GenerateSalt(); @@ -102,15 +116,15 @@ namespace Umbraco.Cms.Core.Security /// public string ParseStoredHashPassword(string algorithm, string storedString, out string salt) { - if (string.IsNullOrWhiteSpace(storedString)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(storedString)); - - // This is for the <= v4 hashing algorithm for which there was no salt - if (IsLegacySHA1Algorithm(algorithm)) + if (string.IsNullOrWhiteSpace(storedString)) { - salt = string.Empty; - return storedString; + throw new ArgumentException("Value cannot be null or whitespace.", nameof(storedString)); } + if (!SupportHashAlgorithm(algorithm)) + { + throw new InvalidOperationException($"{algorithm} is not supported"); + } var saltLen = GenerateSalt(); salt = storedString.Substring(0, saltLen.Length); @@ -133,12 +147,12 @@ namespace Umbraco.Cms.Core.Security /// private string HashPassword(string algorithmType, string pass, string salt) { - if (IsLegacySHA1Algorithm(algorithmType)) + if (!SupportHashAlgorithm(algorithmType)) { - return HashLegacySHA1Password(pass); + throw new InvalidOperationException($"{algorithmType} is not supported"); } - //This is the correct way to implement this (as per the sql membership provider) + // This is the correct way to implement this (as per the sql membership provider) var bytes = Encoding.Unicode.GetBytes(pass); var saltBytes = Convert.FromBase64String(salt); @@ -209,42 +223,17 @@ namespace Umbraco.Cms.Core.Security { // This is for the v6-v8 hashing algorithm if (algorithm.InvariantEquals(Constants.Security.AspNetUmbraco8PasswordHashAlgorithmName)) + { return true; + } - // This is for the <= v4 hashing algorithm - if (IsLegacySHA1Algorithm(algorithm)) + // Default validation value for old machine keys (switched to HMACSHA256 aspnet 4 https://docs.microsoft.com/en-us/aspnet/whitepapers/aspnet4/breaking-changes) + if (algorithm.InvariantEquals("SHA1")) + { return true; + } return false; } - - private bool IsLegacySHA1Algorithm(string algorithm) => algorithm.InvariantEquals(Constants.Security.AspNetUmbraco4PasswordHashAlgorithmName); - - /// - /// Hashes the password with the old v4 algorithm - /// - /// The password. - /// The encoded password. - private string HashLegacySHA1Password(string password) - { - using var hashAlgorithm = GetLegacySHA1Algorithm(password); - var hash = Convert.ToBase64String(hashAlgorithm.ComputeHash(Encoding.Unicode.GetBytes(password))); - return hash; - } - - /// - /// Returns the old v4 algorithm and settings - /// - /// - /// - private HashAlgorithm GetLegacySHA1Algorithm(string password) - { - return new HMACSHA1 - { - //the legacy salt was actually the password :( - Key = Encoding.Unicode.GetBytes(password) - }; - } - } } diff --git a/src/Umbraco.Core/Services/IMacroService.cs b/src/Umbraco.Core/Services/IMacroService.cs index c4bc34997f..e1eb97ac00 100644 --- a/src/Umbraco.Core/Services/IMacroService.cs +++ b/src/Umbraco.Core/Services/IMacroService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using Umbraco.Cms.Core.Models; @@ -17,13 +17,6 @@ namespace Umbraco.Cms.Core.Services /// An object IMacro GetByAlias(string alias); - ///// - ///// Gets a list all available objects - ///// - ///// Optional array of aliases to limit the results - ///// An enumerable list of objects - //IEnumerable GetAll(params string[] aliases); - IEnumerable GetAll(); IEnumerable GetAll(params int[] ids); diff --git a/src/Umbraco.Core/Services/IMacroWithAliasService.cs b/src/Umbraco.Core/Services/IMacroWithAliasService.cs new file mode 100644 index 0000000000..6e72777bfa --- /dev/null +++ b/src/Umbraco.Core/Services/IMacroWithAliasService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using Umbraco.Cms.Core.Models; + +namespace Umbraco.Cms.Core.Services +{ + [Obsolete("This interface will be merged with IMacroService in Umbraco 11")] + public interface IMacroWithAliasService : IMacroService + { + /// + /// Gets a list of available objects by alias. + /// + /// Optional array of aliases to limit the results + /// An enumerable list of objects + IEnumerable GetAll(params string[] aliases); + } +} diff --git a/src/Umbraco.Core/Services/ITrackedReferencesService.cs b/src/Umbraco.Core/Services/ITrackedReferencesService.cs index eee8a324df..dea99c0f6d 100644 --- a/src/Umbraco.Core/Services/ITrackedReferencesService.cs +++ b/src/Umbraco.Core/Services/ITrackedReferencesService.cs @@ -4,12 +4,35 @@ namespace Umbraco.Cms.Core.Services { public interface ITrackedReferencesService { - PagedResult GetPagedRelationsForItems(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency); - + /// + /// Gets a paged result of items which are in relation with the current item. + /// Basically, shows the items which depend on the current item. + /// + /// The identifier of the entity to retrieve relations for. + /// The page index. + /// The page size. + /// A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true). + /// A paged result of objects. + PagedResult GetPagedRelationsForItem(int id, long pageIndex, int pageSize, bool filterMustBeIsDependency); + /// + /// Gets a paged result of the descending items that have any references, given a parent id. + /// + /// The unique identifier of the parent to retrieve descendants for. + /// The page index. + /// The page size. + /// A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true). + /// A paged result of objects. PagedResult GetPagedDescendantsInReferences(int parentId, long pageIndex, int pageSize, bool filterMustBeIsDependency); - + /// + /// Gets a paged result of items used in any kind of relation from selected integer ids. + /// + /// The identifiers of the entities to check for relations. + /// The page index. + /// The page size. + /// A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true). + /// A paged result of objects. PagedResult GetPagedItemsWithRelations(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency); } } diff --git a/src/Umbraco.Core/StaticApplicationLogging.cs b/src/Umbraco.Core/StaticApplicationLogging.cs index 73078b0f42..d7dfc8dd9a 100644 --- a/src/Umbraco.Core/StaticApplicationLogging.cs +++ b/src/Umbraco.Core/StaticApplicationLogging.cs @@ -6,18 +6,14 @@ namespace Umbraco.Cms.Core { public static class StaticApplicationLogging { - private static ILoggerFactory _loggerFactory; + private static ILoggerFactory s_loggerFactory; - public static void Initialize(ILoggerFactory loggerFactory) - { - _loggerFactory = loggerFactory; - } + public static void Initialize(ILoggerFactory loggerFactory) => s_loggerFactory = loggerFactory; public static ILogger Logger => CreateLogger(); - public static ILogger CreateLogger() - { - return _loggerFactory?.CreateLogger() ?? NullLoggerFactory.Instance.CreateLogger(); - } + public static ILogger CreateLogger() => s_loggerFactory?.CreateLogger() ?? NullLoggerFactory.Instance.CreateLogger(); + + public static ILogger CreateLogger(Type type) => s_loggerFactory?.CreateLogger(type) ?? NullLogger.Instance; } } diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs index 966b54633b..13196c1879 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Repositories.cs @@ -1,7 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Persistence.Repositories; -using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement; using Umbraco.Extensions; diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs index 915b815033..157d49fd39 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Services.cs @@ -18,9 +18,9 @@ using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Services.Implement; using Umbraco.Cms.Infrastructure.Packaging; -using Umbraco.Cms.Infrastructure.Persistence; using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement; using Umbraco.Cms.Infrastructure.Services.Implement; +using Umbraco.Cms.Infrastructure.Templates; using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.DependencyInjection @@ -92,6 +92,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection builder.Services.AddUnique(); builder.Services.AddSingleton(); builder.Services.AddUnique(); + builder.Services.AddUnique(); return builder; } diff --git a/src/Umbraco.Infrastructure/HostedServices/RecurringHostedServiceBase.cs b/src/Umbraco.Infrastructure/HostedServices/RecurringHostedServiceBase.cs index c1c7cdf3cf..5247a125bc 100644 --- a/src/Umbraco.Infrastructure/HostedServices/RecurringHostedServiceBase.cs +++ b/src/Umbraco.Infrastructure/HostedServices/RecurringHostedServiceBase.cs @@ -4,10 +4,9 @@ using System; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Umbraco.Cms.Web.Common.DependencyInjection; +using Umbraco.Cms.Core; namespace Umbraco.Cms.Infrastructure.HostedServices { @@ -46,11 +45,8 @@ namespace Umbraco.Cms.Infrastructure.HostedServices // Scheduled for removal in V11 [Obsolete("Please use constructor that takes an ILogger instead")] protected RecurringHostedServiceBase(TimeSpan period, TimeSpan delay) - { - _period = period; - _delay = delay; - _logger = StaticServiceProvider.Instance.GetRequiredService().CreateLogger(GetType()); - } + : this(null, period, delay) + { } /// public Task StartAsync(CancellationToken cancellationToken) @@ -82,7 +78,8 @@ namespace Umbraco.Cms.Infrastructure.HostedServices } catch (Exception ex) { - _logger.LogError(ex, "Unhandled exception in recurring hosted service."); + ILogger logger = _logger ?? StaticApplicationLogging.CreateLogger(GetType()); + logger.LogError(ex, "Unhandled exception in recurring hosted service."); } finally { @@ -108,7 +105,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices { if (disposing) { - _timer?.Dispose(); + _timer?.Dispose(); } _disposedValue = true; diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs index b19802996b..e13764140a 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs @@ -1,8 +1,11 @@ using System; +using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using NPoco; using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Infrastructure.Migrations.Upgrade; using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0; @@ -19,12 +22,25 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install private readonly IDatabase _database; private readonly ILogger _logger; private readonly IUmbracoVersion _umbracoVersion; + private readonly IOptionsMonitor _installDefaultDataSettings; - public DatabaseDataCreator(IDatabase database, ILogger logger, IUmbracoVersion umbracoVersion) + private readonly IDictionary> _entitiesToAlwaysCreate = new Dictionary>() + { + { + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + new List + { + Cms.Core.Constants.DataTypes.Guids.LabelString, + } + } + }; + + public DatabaseDataCreator(IDatabase database, ILogger logger, IUmbracoVersion umbracoVersion, IOptionsMonitor installDefaultDataSettings) { _database = database; _logger = logger; _umbracoVersion = umbracoVersion; + _installDefaultDataSettings = installDefaultDataSettings; } /// @@ -37,54 +53,91 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install _logger.LogInformation("Creating data in {TableName}", tableName); if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.Node)) + { CreateNodeData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.Lock)) + { CreateLockData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.ContentType)) + { CreateContentTypeData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.User)) + { CreateUserData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.UserGroup)) + { CreateUserGroupData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.User2UserGroup)) + { CreateUser2UserGroupData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.UserGroup2App)) + { CreateUserGroup2AppData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup)) + { CreatePropertyTypeGroupData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType)) + { CreatePropertyTypeData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.Language)) + { CreateLanguageData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.ContentChildType)) + { CreateContentChildTypeData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.DataType)) + { CreateDataTypeData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.RelationType)) + { CreateRelationTypeData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.KeyValue)) + { CreateKeyValueData(); + } if (tableName.Equals(Cms.Core.Constants.DatabaseSchema.Tables.LogViewerQuery)) + { CreateLogViewerQueryData(); + } _logger.LogInformation("Done creating table {TableName} data.", tableName); } private void CreateNodeData() + { + CreateNodeDataForDataTypes(); + CreateNodeDataForMediaTypes(); + CreateNodeDataForMemberTypes(); + } + + private void CreateNodeDataForDataTypes() { void InsertDataTypeNodeDto(int id, int sortOrder, string uniqueId, string text) { @@ -100,66 +153,287 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install UniqueId = new Guid(uniqueId), Text = text, NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, - CreateDate = DateTime.Now + CreateDate = DateTime.Now, }; - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, nodeDto); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + uniqueId, + nodeDto, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); } _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -1, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1", SortOrder = 0, UniqueId = new Guid("916724a5-173d-4619-b97e-b9de133dd6f5"), Text = "SYSTEM DATA: umbraco master root", NodeObjectType = Cms.Core.Constants.ObjectTypes.SystemRoot, CreateDate = DateTime.Now }); _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -20, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,-20", SortOrder = 0, UniqueId = new Guid("0F582A79-1E41-4CF0-BFA0-76340651891A"), Text = "Recycle Bin", NodeObjectType = Cms.Core.Constants.ObjectTypes.ContentRecycleBin, CreateDate = DateTime.Now }); _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -21, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,-21", SortOrder = 0, UniqueId = new Guid("BF7C7CBC-952F-4518-97A2-69E9C7B33842"), Text = "Recycle Bin", NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaRecycleBin, CreateDate = DateTime.Now }); + InsertDataTypeNodeDto(Cms.Core.Constants.DataTypes.LabelString, 35, Cms.Core.Constants.DataTypes.Guids.LabelString, "Label (string)"); InsertDataTypeNodeDto(Cms.Core.Constants.DataTypes.LabelInt, 36, Cms.Core.Constants.DataTypes.Guids.LabelInt, "Label (integer)"); InsertDataTypeNodeDto(Cms.Core.Constants.DataTypes.LabelBigint, 36, Cms.Core.Constants.DataTypes.Guids.LabelBigInt, "Label (bigint)"); InsertDataTypeNodeDto(Cms.Core.Constants.DataTypes.LabelDateTime, 37, Cms.Core.Constants.DataTypes.Guids.LabelDateTime, "Label (datetime)"); InsertDataTypeNodeDto(Cms.Core.Constants.DataTypes.LabelTime, 38, Cms.Core.Constants.DataTypes.Guids.LabelTime, "Label (time)"); InsertDataTypeNodeDto(Cms.Core.Constants.DataTypes.LabelDecimal, 39, Cms.Core.Constants.DataTypes.Guids.LabelDecimal, "Label (decimal)"); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Upload, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Upload}", SortOrder = 34, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadGuid, Text = "Upload File", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.UploadVideo, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.UploadVideo}", SortOrder = 35, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadVideoGuid, Text = "Upload Video", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.UploadAudio, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.UploadAudio}", SortOrder = 36, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadAudioGuid, Text = "Upload Audio", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.UploadArticle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.UploadArticle}", SortOrder = 37, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadArticleGuid, Text = "Upload Article", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.UploadVectorGraphics, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.UploadVectorGraphics}", SortOrder = 38, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadVectorGraphicsGuid, Text = "Upload Vector Graphics", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Textarea, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Textarea}", SortOrder = 33, UniqueId = Cms.Core.Constants.DataTypes.Guids.TextareaGuid, Text = "Textarea", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Textbox, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Textbox}", SortOrder = 32, UniqueId = Cms.Core.Constants.DataTypes.Guids.TextstringGuid, Text = "Textstring", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.RichtextEditor, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.RichtextEditor}", SortOrder = 4, UniqueId = Cms.Core.Constants.DataTypes.Guids.RichtextEditorGuid, Text = "Richtext editor", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -51, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-51", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.NumericGuid, Text = "Numeric", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Boolean, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Boolean}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.CheckboxGuid, Text = "True/false", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -43, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-43", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.CheckboxListGuid, Text = "Checkbox list", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DropDownSingle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DropDownSingle}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.DropdownGuid, Text = "Dropdown", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.DatePickerGuid, Text = "Date Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.RadioboxGuid, Text = "Radiobox", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DropDownMultiple, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DropDownMultiple}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.DropdownMultipleGuid, Text = "Dropdown multiple", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ApprovedColorGuid, Text = "Approved Color", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DateTime, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DateTime}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.DatePickerWithTimeGuid, Text = "Date Picker with time", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DefaultContentListView}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ListViewContentGuid, Text = Cms.Core.Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DefaultMediaListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DefaultMediaListView}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ListViewMediaGuid, Text = Cms.Core.Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DefaultMembersListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DefaultMembersListView}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ListViewMembersGuid, Text = Cms.Core.Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"), Text = Cms.Core.Constants.Conventions.MediaTypes.Folder, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"), Text = Cms.Core.Constants.Conventions.MediaTypes.Image, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Cms.Core.Constants.Conventions.MediaTypes.File, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1034, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1034", SortOrder = 2, UniqueId = new Guid("f6c515bb-653c-4bdc-821c-987729ebe327"), Text = Cms.Core.Constants.Conventions.MediaTypes.Video, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1035, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1035", SortOrder = 2, UniqueId = new Guid("a5ddeee0-8fd8-4cee-a658-6f1fcdb00de3"), Text = Cms.Core.Constants.Conventions.MediaTypes.Audio, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1036, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1036", SortOrder = 2, UniqueId = new Guid("a43e3414-9599-4230-a7d3-943a21b20122"), Text = Cms.Core.Constants.Conventions.MediaTypes.Article, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1037, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1037", SortOrder = 2, UniqueId = new Guid("c4b1efcf-a9d5-41c4-9621-e9d273b52a9c"), Text = "Vector Graphics (SVG)", NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.Upload, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Upload, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Upload}", SortOrder = 34, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadGuid, Text = "Upload File", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.UploadVideo, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.UploadVideo, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.UploadVideo}", SortOrder = 35, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadVideoGuid, Text = "Upload Video", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.UploadAudio, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.UploadAudio, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.UploadAudio}", SortOrder = 36, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadAudioGuid, Text = "Upload Audio", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.UploadArticle, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.UploadArticle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.UploadArticle}", SortOrder = 37, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadArticleGuid, Text = "Upload Article", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.UploadVectorGraphics, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.UploadVectorGraphics, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.UploadVectorGraphics}", SortOrder = 38, UniqueId = Cms.Core.Constants.DataTypes.Guids.UploadVectorGraphicsGuid, Text = "Upload Vector Graphics", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.Textarea, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Textarea, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Textarea}", SortOrder = 33, UniqueId = Cms.Core.Constants.DataTypes.Guids.TextareaGuid, Text = "Textarea", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.Textstring, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Textbox, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Textbox}", SortOrder = 32, UniqueId = Cms.Core.Constants.DataTypes.Guids.TextstringGuid, Text = "Textstring", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.RichtextEditor, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.RichtextEditor, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.RichtextEditor}", SortOrder = 4, UniqueId = Cms.Core.Constants.DataTypes.Guids.RichtextEditorGuid, Text = "Richtext editor", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.Numeric, + new NodeDto { NodeId = -51, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-51", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.NumericGuid, Text = "Numeric", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.Checkbox, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Boolean, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Boolean}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.CheckboxGuid, Text = "True/false", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.CheckboxList, + new NodeDto { NodeId = -43, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-43", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.CheckboxListGuid, Text = "Checkbox list", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.Dropdown, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DropDownSingle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DropDownSingle}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.DropdownGuid, Text = "Dropdown", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.DatePicker, + new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.DatePickerGuid, Text = "Date Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.Radiobox, + new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.RadioboxGuid, Text = "Radiobox", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.DropdownMultiple, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DropDownMultiple, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DropDownMultiple}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.DropdownMultipleGuid, Text = "Dropdown multiple", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.ApprovedColor, + new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ApprovedColorGuid, Text = "Approved Color", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.DatePickerWithTime, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DateTime, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DateTime}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.DatePickerWithTimeGuid, Text = "Date Picker with time", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.ListViewContent, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DefaultContentListView}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ListViewContentGuid, Text = Cms.Core.Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.ListViewMedia, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DefaultMediaListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DefaultMediaListView}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ListViewMediaGuid, Text = Cms.Core.Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.ListViewMembers, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.DefaultMembersListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.DefaultMembersListView}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ListViewMembersGuid, Text = Cms.Core.Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.Tags, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Tags, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Tags}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.TagsGuid, Text = "Tags", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.ImageCropper, + new NodeDto { NodeId = Cms.Core.Constants.DataTypes.ImageCropper, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.ImageCropper}", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ImageCropperGuid, Text = "Image Cropper", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.Tags, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.Tags}", SortOrder = 2, UniqueId = new Guid("b6b73142-b9c1-4bf8-a16d-e1c23320b549"), Text = "Tags", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Cms.Core.Constants.DataTypes.ImageCropper, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Cms.Core.Constants.DataTypes.ImageCropper}", SortOrder = 2, UniqueId = new Guid("1df9f033-e6d4-451f-b8d2-e0cbc50a836f"), Text = "Image Cropper", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Cms.Core.Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = Cms.Core.Constants.ObjectTypes.MemberType, CreateDate = DateTime.Now }); + // New UDI pickers with newer Ids + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.ContentPicker, + new NodeDto { NodeId = 1046, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1046", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.ContentPickerGuid, Text = "Content Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.MemberPicker, + new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MemberPickerGuid, Text = "Member Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.MediaPicker, + new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MediaPickerGuid, Text = "Media Picker (legacy)", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.MultipleMediaPicker, + new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MultipleMediaPickerGuid, Text = "Multiple Media Picker (legacy)", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.RelatedLinks, + new NodeDto { NodeId = 1050, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1050", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.RelatedLinksGuid, Text = "Multi URL Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); - //New UDI pickers with newer Ids - _database.Insert(Cms.Core.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 = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.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 = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.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 (legacy)", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.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 (legacy)", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.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 = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.MediaPicker3, + new NodeDto { NodeId = 1051, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1051", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MediaPicker3Guid, Text = "Media Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.MediaPicker3Multiple, + new NodeDto { NodeId = 1052, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1052", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MediaPicker3MultipleGuid, Text = "Multiple Media Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.MediaPicker3SingleImage, + new NodeDto { NodeId = 1053, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1053", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MediaPicker3SingleImageGuid, Text = "Image Media Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.DataTypes, + Cms.Core.Constants.DataTypes.Guids.MediaPicker3MultipleImages, + new NodeDto { NodeId = 1054, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1054", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MediaPicker3MultipleImagesGuid, Text = "Multiple Image Media Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + } - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1051, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1051", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MediaPicker3Guid, Text = "Media Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1052, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1052", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MediaPicker3MultipleGuid, Text = "Multiple Media Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1053, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1053", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MediaPicker3SingleImageGuid, Text = "Image Media Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1054, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1054", SortOrder = 2, UniqueId = Cms.Core.Constants.DataTypes.Guids.MediaPicker3MultipleImagesGuid, Text = "Multiple Image Media Picker", NodeObjectType = Cms.Core.Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + private void CreateNodeDataForMediaTypes() + { + var folderUniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, + folderUniqueId.ToString(), + new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = folderUniqueId, Text = Cms.Core.Constants.Conventions.MediaTypes.Folder, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + var imageUniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, + imageUniqueId.ToString(), + new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = imageUniqueId, Text = Cms.Core.Constants.Conventions.MediaTypes.Image, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + + var fileUniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, + fileUniqueId.ToString(), + new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = fileUniqueId, Text = Cms.Core.Constants.Conventions.MediaTypes.File, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + + var videoUniqueId = new Guid("f6c515bb-653c-4bdc-821c-987729ebe327"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, + videoUniqueId.ToString(), + new NodeDto { NodeId = 1034, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1034", SortOrder = 2, UniqueId = videoUniqueId, Text = Cms.Core.Constants.Conventions.MediaTypes.Video, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + + var audioUniqueId = new Guid("a5ddeee0-8fd8-4cee-a658-6f1fcdb00de3"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, + audioUniqueId.ToString(), + new NodeDto { NodeId = 1035, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1035", SortOrder = 2, UniqueId = audioUniqueId, Text = Cms.Core.Constants.Conventions.MediaTypes.Audio, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + + var articleUniqueId = new Guid("a43e3414-9599-4230-a7d3-943a21b20122"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, + articleUniqueId.ToString(), + new NodeDto { NodeId = 1036, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1036", SortOrder = 2, UniqueId = articleUniqueId, Text = Cms.Core.Constants.Conventions.MediaTypes.Article, NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + + var svgUniqueId = new Guid("c4b1efcf-a9d5-41c4-9621-e9d273b52a9c"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.MediaTypes, + svgUniqueId.ToString(), + new NodeDto { NodeId = 1037, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1037", SortOrder = 2, UniqueId = svgUniqueId, Text = "Vector Graphics (SVG)", NodeObjectType = Cms.Core.Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); + } + + private void CreateNodeDataForMemberTypes() + { + var memberUniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"); + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.MemberTypes, + memberUniqueId.ToString(), + new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = memberUniqueId, Text = Cms.Core.Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = Cms.Core.Constants.ObjectTypes.MemberType, CreateDate = DateTime.Now }, + Cms.Core.Constants.DatabaseSchema.Tables.Node, + "id"); } private void CreateLockData() @@ -182,20 +456,55 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install private void CreateContentTypeData() { - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Cms.Core.Constants.Conventions.MediaTypes.Folder, Icon = Cms.Core.Constants.Icons.MediaFolder, Thumbnail = Cms.Core.Constants.Icons.MediaFolder, IsContainer = false, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Cms.Core.Constants.Conventions.MediaTypes.Image, Icon = Cms.Core.Constants.Icons.MediaImage, Thumbnail = Cms.Core.Constants.Icons.MediaImage, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Cms.Core.Constants.Conventions.MediaTypes.File, Icon = Cms.Core.Constants.Icons.MediaFile, Thumbnail = Cms.Core.Constants.Icons.MediaFile, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 540, NodeId = 1034, Alias = Cms.Core.Constants.Conventions.MediaTypes.VideoAlias, Icon = Cms.Core.Constants.Icons.MediaVideo, Thumbnail = Cms.Core.Constants.Icons.MediaVideo, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 541, NodeId = 1035, Alias = Cms.Core.Constants.Conventions.MediaTypes.AudioAlias, Icon = Cms.Core.Constants.Icons.MediaAudio, Thumbnail = Cms.Core.Constants.Icons.MediaAudio, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 542, NodeId = 1036, Alias = Cms.Core.Constants.Conventions.MediaTypes.ArticleAlias, Icon = Cms.Core.Constants.Icons.MediaArticle, Thumbnail = Cms.Core.Constants.Icons.MediaArticle, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 543, NodeId = 1037, Alias = Cms.Core.Constants.Conventions.MediaTypes.VectorGraphicsAlias, Icon = Cms.Core.Constants.Icons.MediaVectorGraphics, Thumbnail = Cms.Core.Constants.Icons.MediaVectorGraphics, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing }); + // Insert content types only if the corresponding Node record exists (which may or may not have been created depending on configuration + // of media or member types to create). - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Cms.Core.Constants.Conventions.MemberTypes.DefaultAlias, Icon = Cms.Core.Constants.Icons.Member, Thumbnail = Cms.Core.Constants.Icons.Member, Variations = (byte) ContentVariation.Nothing }); + // Media types. + if (_database.Exists(1031)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Cms.Core.Constants.Conventions.MediaTypes.Folder, Icon = Cms.Core.Constants.Icons.MediaFolder, Thumbnail = Cms.Core.Constants.Icons.MediaFolder, IsContainer = false, AllowAtRoot = true, Variations = (byte)ContentVariation.Nothing }); + } + + if (_database.Exists(1032)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Cms.Core.Constants.Conventions.MediaTypes.Image, Icon = Cms.Core.Constants.Icons.MediaImage, Thumbnail = Cms.Core.Constants.Icons.MediaImage, AllowAtRoot = true, Variations = (byte)ContentVariation.Nothing }); + } + + if (_database.Exists(1033)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Cms.Core.Constants.Conventions.MediaTypes.File, Icon = Cms.Core.Constants.Icons.MediaFile, Thumbnail = Cms.Core.Constants.Icons.MediaFile, AllowAtRoot = true, Variations = (byte)ContentVariation.Nothing }); + } + + if (_database.Exists(1034)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 540, NodeId = 1034, Alias = Cms.Core.Constants.Conventions.MediaTypes.VideoAlias, Icon = Cms.Core.Constants.Icons.MediaVideo, Thumbnail = Cms.Core.Constants.Icons.MediaVideo, AllowAtRoot = true, Variations = (byte)ContentVariation.Nothing }); + } + + if (_database.Exists(1035)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 541, NodeId = 1035, Alias = Cms.Core.Constants.Conventions.MediaTypes.AudioAlias, Icon = Cms.Core.Constants.Icons.MediaAudio, Thumbnail = Cms.Core.Constants.Icons.MediaAudio, AllowAtRoot = true, Variations = (byte)ContentVariation.Nothing }); + } + + if (_database.Exists(1036)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 542, NodeId = 1036, Alias = Cms.Core.Constants.Conventions.MediaTypes.ArticleAlias, Icon = Cms.Core.Constants.Icons.MediaArticle, Thumbnail = Cms.Core.Constants.Icons.MediaArticle, AllowAtRoot = true, Variations = (byte)ContentVariation.Nothing }); + } + + if (_database.Exists(1037)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 543, NodeId = 1037, Alias = Cms.Core.Constants.Conventions.MediaTypes.VectorGraphicsAlias, Icon = Cms.Core.Constants.Icons.MediaVectorGraphics, Thumbnail = Cms.Core.Constants.Icons.MediaVectorGraphics, AllowAtRoot = true, Variations = (byte)ContentVariation.Nothing }); + } + + // Member type. + if (_database.Exists(1044)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Cms.Core.Constants.Conventions.MemberTypes.DefaultAlias, Icon = Cms.Core.Constants.Icons.Member, Thumbnail = Cms.Core.Constants.Icons.Member, Variations = (byte)ContentVariation.Nothing }); + } } private void CreateUserData() { - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.User, "id", false, new UserDto { Id = Cms.Core.Constants.Security.SuperUserId, Disabled = false, NoConsole = false, UserName = "Administrator", Login = "admin", Password = "default", Email = "", UserLanguage = "en-US", CreateDate = DateTime.Now, UpdateDate = DateTime.Now }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.User, "id", false, new UserDto { Id = Cms.Core.Constants.Security.SuperUserId, Disabled = false, NoConsole = false, UserName = "Administrator", Login = "admin", Password = "default", Email = string.Empty, UserLanguage = "en-US", CreateDate = DateTime.Now, UpdateDate = DateTime.Now }); } private void CreateUserGroupData() @@ -204,7 +513,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 2, StartMediaId = -1, StartContentId = -1, Alias = Cms.Core.Constants.Security.WriterGroupAlias, Name = "Writers", DefaultPermissions = "CAH:FN", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-edit" }); _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 3, StartMediaId = -1, StartContentId = -1, Alias = Cms.Core.Constants.Security.EditorGroupAlias, Name = "Editors", DefaultPermissions = "CADMOSKTPUZ:5FïN", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-tools" }); _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 4, StartMediaId = -1, StartContentId = -1, Alias = Cms.Core.Constants.Security.TranslatorGroupAlias, Name = "Translators", DefaultPermissions = "AF", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-globe" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 5, StartMediaId = -1, StartContentId = -1, Alias = Cms.Core.Constants.Security.SensitiveDataGroupAlias, Name = "Sensitive data", DefaultPermissions = "", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-lock" }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 5, StartMediaId = -1, StartContentId = -1, Alias = Cms.Core.Constants.Security.SensitiveDataGroupAlias, Name = "Sensitive data", DefaultPermissions = string.Empty, CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-lock" }); } private void CreateUser2UserGroupData() @@ -235,67 +544,136 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install private void CreatePropertyTypeGroupData() { - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 3, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Image), ContentTypeNodeId = 1032, Text = "Image", Alias = "image", SortOrder = 1 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 4, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.File), ContentTypeNodeId = 1033, Text = "File", Alias = "file", SortOrder = 1, }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 52, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Video), ContentTypeNodeId = 1034, Text = "Video", Alias = "video", SortOrder = 1 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 53, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Audio), ContentTypeNodeId = 1035, Text = "Audio", Alias = "audio", SortOrder = 1 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 54, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Article), ContentTypeNodeId = 1036, Text = "Article", Alias = "article", SortOrder = 1 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 55, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.VectorGraphics), ContentTypeNodeId = 1037, Text = "Vector Graphics", Alias = "vectorGraphics", SortOrder = 1 }); - //membership property group - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 11, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Membership), ContentTypeNodeId = 1044, Text = Cms.Core.Constants.Conventions.Member.StandardPropertiesGroupName, Alias = Cms.Core.Constants.Conventions.Member.StandardPropertiesGroupAlias, SortOrder = 1 }); + // Insert property groups only if the corresponding content type node record exists (which may or may not have been created depending on configuration + // of media or member types to create). + + // Media property groups. + if (_database.Exists(1032)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 3, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Image), ContentTypeNodeId = 1032, Text = "Image", Alias = "image", SortOrder = 1 }); + } + + if (_database.Exists(1033)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 4, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.File), ContentTypeNodeId = 1033, Text = "File", Alias = "file", SortOrder = 1, }); + } + + if (_database.Exists(1034)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 52, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Video), ContentTypeNodeId = 1034, Text = "Video", Alias = "video", SortOrder = 1 }); + } + + if (_database.Exists(1035)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 53, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Audio), ContentTypeNodeId = 1035, Text = "Audio", Alias = "audio", SortOrder = 1 }); + } + + if (_database.Exists(1036)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 54, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Article), ContentTypeNodeId = 1036, Text = "Article", Alias = "article", SortOrder = 1 }); + } + + if (_database.Exists(1037)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 55, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.VectorGraphics), ContentTypeNodeId = 1037, Text = "Vector Graphics", Alias = "vectorGraphics", SortOrder = 1 }); + } + + // Membership property group. + if (_database.Exists(1044)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyTypeGroup, "id", false, new PropertyTypeGroupDto { Id = 11, UniqueId = new Guid(Cms.Core.Constants.PropertyTypeGroups.Membership), ContentTypeNodeId = 1044, Text = Cms.Core.Constants.Conventions.Member.StandardPropertiesGroupName, Alias = Cms.Core.Constants.Conventions.Member.StandardPropertiesGroupAlias, SortOrder = 1 }); + } } private void CreatePropertyTypeData() { - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.ImageCropper, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Image", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in pixels", Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in pixels", Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 10, UniqueId = 10.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.Upload, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "File", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 25, UniqueId = 25.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing }); + // Insert property types only if the corresponding property group record exists (which may or may not have been created depending on configuration + // of media or member types to create). - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 40, UniqueId = 40.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.UploadVideo, ContentTypeId = 1034, PropertyTypeGroupId = 52, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Video", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 41, UniqueId = 41.ToGuid(), DataTypeId = -92, ContentTypeId = 1034, PropertyTypeGroupId = 52, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 42, UniqueId = 42.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1034, PropertyTypeGroupId = 52, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing }); + // Media property types. + if (_database.Exists(3)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.ImageCropper, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Image", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in pixels", Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in pixels", Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 10, UniqueId = 10.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + } - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 43, UniqueId = 43.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.UploadAudio, ContentTypeId = 1035, PropertyTypeGroupId = 53, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Audio", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 44, UniqueId = 44.ToGuid(), DataTypeId = -92, ContentTypeId = 1035, PropertyTypeGroupId = 53, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 45, UniqueId = 45.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1035, PropertyTypeGroupId = 53, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing }); + if (_database.Exists(4)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.Upload, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "File", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 25, UniqueId = 25.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte)ContentVariation.Nothing }); + } - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 46, UniqueId = 46.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.UploadArticle, ContentTypeId = 1036, PropertyTypeGroupId = 54, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Article", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 47, UniqueId = 47.ToGuid(), DataTypeId = -92, ContentTypeId = 1036, PropertyTypeGroupId = 54, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 48, UniqueId = 48.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1036, PropertyTypeGroupId = 54, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing }); + if (_database.Exists(52)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 40, UniqueId = 40.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.UploadVideo, ContentTypeId = 1034, PropertyTypeGroupId = 52, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Video", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 41, UniqueId = 41.ToGuid(), DataTypeId = -92, ContentTypeId = 1034, PropertyTypeGroupId = 52, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 42, UniqueId = 42.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1034, PropertyTypeGroupId = 52, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte)ContentVariation.Nothing }); + } - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 49, UniqueId = 49.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.UploadVectorGraphics, ContentTypeId = 1037, PropertyTypeGroupId = 55, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Vector Graphics", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 50, UniqueId = 50.ToGuid(), DataTypeId = -92, ContentTypeId = 1037, PropertyTypeGroupId = 55, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 51, UniqueId = 51.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1037, PropertyTypeGroupId = 55, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing }); + if (_database.Exists(53)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 43, UniqueId = 43.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.UploadAudio, ContentTypeId = 1035, PropertyTypeGroupId = 53, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Audio", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 44, UniqueId = 44.ToGuid(), DataTypeId = -92, ContentTypeId = 1035, PropertyTypeGroupId = 53, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 45, UniqueId = 45.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1035, PropertyTypeGroupId = 53, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte)ContentVariation.Nothing }); + } - //membership property types - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.Textarea, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.Comments, Name = Cms.Core.Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 29, UniqueId = 29.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelInt, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.FailedPasswordAttempts, Name = Cms.Core.Constants.Conventions.Member.FailedPasswordAttemptsLabel, SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 30, UniqueId = 30.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.Boolean, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.IsApproved, Name = Cms.Core.Constants.Conventions.Member.IsApprovedLabel, SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 31, UniqueId = 31.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.Boolean, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.IsLockedOut, Name = Cms.Core.Constants.Conventions.Member.IsLockedOutLabel, SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 32, UniqueId = 32.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.LastLockoutDate, Name = Cms.Core.Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 33, UniqueId = 33.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.LastLoginDate, Name = Cms.Core.Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 34, UniqueId = 34.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.LastPasswordChangeDate, Name = Cms.Core.Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); + if (_database.Exists(54)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 46, UniqueId = 46.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.UploadArticle, ContentTypeId = 1036, PropertyTypeGroupId = 54, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Article", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 47, UniqueId = 47.ToGuid(), DataTypeId = -92, ContentTypeId = 1036, PropertyTypeGroupId = 54, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 48, UniqueId = 48.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1036, PropertyTypeGroupId = 54, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte)ContentVariation.Nothing }); + } + + if (_database.Exists(55)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 49, UniqueId = 49.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.UploadVectorGraphics, ContentTypeId = 1037, PropertyTypeGroupId = 55, Alias = Cms.Core.Constants.Conventions.Media.File, Name = "Vector Graphics", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 50, UniqueId = 50.ToGuid(), DataTypeId = -92, ContentTypeId = 1037, PropertyTypeGroupId = 55, Alias = Cms.Core.Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 51, UniqueId = 51.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelBigint, ContentTypeId = 1037, PropertyTypeGroupId = 55, Alias = Cms.Core.Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte)ContentVariation.Nothing }); + } + + // Membership property types. + if (_database.Exists(11)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.Textarea, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.Comments, Name = Cms.Core.Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 29, UniqueId = 29.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelInt, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.FailedPasswordAttempts, Name = Cms.Core.Constants.Conventions.Member.FailedPasswordAttemptsLabel, SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 30, UniqueId = 30.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.Boolean, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.IsApproved, Name = Cms.Core.Constants.Conventions.Member.IsApprovedLabel, SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 31, UniqueId = 31.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.Boolean, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.IsLockedOut, Name = Cms.Core.Constants.Conventions.Member.IsLockedOutLabel, SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 32, UniqueId = 32.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.LastLockoutDate, Name = Cms.Core.Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 33, UniqueId = 33.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.LastLoginDate, Name = Cms.Core.Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 34, UniqueId = 34.ToGuid(), DataTypeId = Cms.Core.Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Cms.Core.Constants.Conventions.Member.LastPasswordChangeDate, Name = Cms.Core.Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + } } - private void CreateLanguageData() - { - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Language, "id", false, new LanguageDto { Id = 1, IsoCode = "en-US", CultureName = "English (United States)", IsDefault = true }); - } + private void CreateLanguageData() => + ConditionalInsert( + Cms.Core.Constants.Configuration.NamedOptions.InstallDefaultData.Languages, + "en-us", + new LanguageDto { Id = 1, IsoCode = "en-US", CultureName = "English (United States)", IsDefault = true }, + Cms.Core.Constants.DatabaseSchema.Tables.Language, + "id"); private void CreateContentChildTypeData() { + // Insert data if the corresponding Node records exist (which may or may not have been created depending on configuration + // of media types to create). + if (!_database.Exists(1031)) + { + return; + } + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentChildType, "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1031 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentChildType, "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1032 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentChildType, "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1033 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentChildType, "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1034 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentChildType, "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1035 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentChildType, "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1036 }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentChildType, "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = 1037 }); + + for (int i = 1032; i <= 1037; i++) + { + if (_database.Exists(i)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.ContentChildType, "Id", false, new ContentTypeAllowedContentTypeDto { Id = 1031, AllowedId = i }); + } + } } private void CreateDataTypeData() @@ -310,9 +688,14 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install }; if (configuration != null) + { dataTypeDto.Configuration = configuration; + } - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, dataTypeDto); + if (_database.Exists(id)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, dataTypeDto); + } } //layouts for the list view @@ -320,123 +703,288 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install const string listLayout = "{\"name\": \"List\",\"path\": \"views/propertyeditors/listview/layouts/list/list.html\",\"icon\": \"icon-list\", \"isSystem\": 1,\"selected\": true}"; const string layouts = "[" + cardLayout + "," + listLayout + "]"; - // TODO: Check which of the DataTypeIds below doesn't exist in umbracoNode, which results in a foreign key constraint errors. - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.Boolean, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.Boolean, DbType = "Integer" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -51, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.Integer, DbType = "Integer" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -87, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.TinyMce, DbType = "Ntext", - Configuration = "{\"value\":\",code,undo,redo,cut,copy,mcepasteword,stylepicker,bold,italic,bullist,numlist,outdent,indent,mcelink,unlink,mceinsertanchor,mceimage,umbracomacro,mceinserttable,umbracoembed,mcecharmap,|1|1,2,3,|0|500,400|1049,|true|\"}" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.Textbox, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.TextBox, DbType = "Nvarchar" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.Textarea, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.TextArea, DbType = "Ntext" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.Upload, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, DbType = "Nvarchar" }); + // Insert data types only if the corresponding Node record exists (which may or may not have been created depending on configuration + // of data types to create). + if (_database.Exists(Cms.Core.Constants.DataTypes.Boolean)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.Boolean, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.Boolean, DbType = "Integer" }); + } + + if (_database.Exists(-51)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -51, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.Integer, DbType = "Integer" }); + } + + if (_database.Exists(-87)) + { + _database.Insert( + Cms.Core.Constants.DatabaseSchema.Tables.DataType, + "pk", + false, + new DataTypeDto + { + NodeId = -87, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.TinyMce, + DbType = "Ntext", + Configuration = "{\"value\":\",code,undo,redo,cut,copy,mcepasteword,stylepicker,bold,italic,bullist,numlist,outdent,indent,mcelink,unlink,mceinsertanchor,mceimage,umbracomacro,mceinserttable,umbracoembed,mcecharmap,|1|1,2,3,|0|500,400|1049,|true|\"}" + }); + } + + if (_database.Exists(Cms.Core.Constants.DataTypes.Textbox)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.Textbox, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.TextBox, DbType = "Nvarchar" }); + } + + if (_database.Exists(Cms.Core.Constants.DataTypes.Textarea)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.Textarea, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.TextArea, DbType = "Ntext" }); + } + + if (_database.Exists(Cms.Core.Constants.DataTypes.Upload)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.Upload, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, DbType = "Nvarchar" }); + } + InsertDataTypeDto(Cms.Core.Constants.DataTypes.LabelString, Cms.Core.Constants.PropertyEditors.Aliases.Label, "Nvarchar", "{\"umbracoDataValueType\":\"STRING\"}"); InsertDataTypeDto(Cms.Core.Constants.DataTypes.LabelInt, Cms.Core.Constants.PropertyEditors.Aliases.Label, "Integer", "{\"umbracoDataValueType\":\"INT\"}"); InsertDataTypeDto(Cms.Core.Constants.DataTypes.LabelBigint, Cms.Core.Constants.PropertyEditors.Aliases.Label, "Nvarchar", "{\"umbracoDataValueType\":\"BIGINT\"}"); InsertDataTypeDto(Cms.Core.Constants.DataTypes.LabelDateTime, Cms.Core.Constants.PropertyEditors.Aliases.Label, "Date", "{\"umbracoDataValueType\":\"DATETIME\"}"); InsertDataTypeDto(Cms.Core.Constants.DataTypes.LabelDecimal, Cms.Core.Constants.PropertyEditors.Aliases.Label, "Decimal", "{\"umbracoDataValueType\":\"DECIMAL\"}"); InsertDataTypeDto(Cms.Core.Constants.DataTypes.LabelTime, Cms.Core.Constants.PropertyEditors.Aliases.Label, "Date", "{\"umbracoDataValueType\":\"TIME\"}"); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.DateTime, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.DateTime, DbType = "Date" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -37, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ColorPicker, DbType = "Nvarchar" }); + + if (_database.Exists(Cms.Core.Constants.DataTypes.DateTime)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.DateTime, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.DateTime, DbType = "Date" }); + } + + if (_database.Exists(-37)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -37, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ColorPicker, DbType = "Nvarchar" }); + } + InsertDataTypeDto(Cms.Core.Constants.DataTypes.DropDownSingle, Cms.Core.Constants.PropertyEditors.Aliases.DropDownListFlexible, "Nvarchar", "{\"multiple\":false}"); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -40, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.RadioButtonList, DbType = "Nvarchar" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -41, EditorAlias = "Umbraco.DateTime", DbType = "Date", Configuration = "{\"format\":\"YYYY-MM-DD\"}" }); + + if (_database.Exists(-40)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -40, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.RadioButtonList, DbType = "Nvarchar" }); + } + + if (_database.Exists(-41)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -41, EditorAlias = "Umbraco.DateTime", DbType = "Date", Configuration = "{\"format\":\"YYYY-MM-DD\"}" }); + } + InsertDataTypeDto(Cms.Core.Constants.DataTypes.DropDownMultiple, Cms.Core.Constants.PropertyEditors.Aliases.DropDownListFlexible, "Nvarchar", "{\"multiple\":true}"); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -43, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.CheckBoxList, DbType = "Nvarchar" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.Tags, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.Tags, DbType = "Ntext", - Configuration = "{\"group\":\"default\", \"storageType\":\"Json\"}" - }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.ImageCropper, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ImageCropper, DbType = "Ntext" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.DefaultContentListView, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ListView, DbType = "Nvarchar", - Configuration = "{\"pageSize\":100, \"orderBy\":\"updateDate\", \"orderDirection\":\"desc\", \"layouts\":" + layouts + ", \"includeProperties\":[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]}" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.DefaultMediaListView, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ListView, DbType = "Nvarchar", - Configuration = "{\"pageSize\":100, \"orderBy\":\"updateDate\", \"orderDirection\":\"desc\", \"layouts\":" + layouts + ", \"includeProperties\":[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]}" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.DefaultMembersListView, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ListView, DbType = "Nvarchar", - Configuration = "{\"pageSize\":10, \"orderBy\":\"username\", \"orderDirection\":\"asc\", \"includeProperties\":[{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]}" }); - //New UDI pickers with newer Ids - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1046, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ContentPicker, DbType = "Nvarchar" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1047, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MemberPicker, DbType = "Nvarchar" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1048, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker, DbType = "Ntext" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1049, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker, DbType = "Ntext", - Configuration = "{\"multiPicker\":1}" }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1050, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MultiUrlPicker, DbType = "Ntext" }); - - - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + if (_database.Exists(-43)) { - NodeId = Cms.Core.Constants.DataTypes.UploadVideo, - EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, - DbType = "Nvarchar", - Configuration = "{\"fileExtensions\":[{\"id\":0, \"value\":\"mp4\"}, {\"id\":1, \"value\":\"webm\"}, {\"id\":2, \"value\":\"ogv\"}]}" - }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -43, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.CheckBoxList, DbType = "Nvarchar" }); + } - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + if (_database.Exists(Cms.Core.Constants.DataTypes.Tags)) { - NodeId = Cms.Core.Constants.DataTypes.UploadAudio, - EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, - DbType = "Nvarchar", - Configuration = "{\"fileExtensions\":[{\"id\":0, \"value\":\"mp3\"}, {\"id\":1, \"value\":\"weba\"}, {\"id\":2, \"value\":\"oga\"}, {\"id\":3, \"value\":\"opus\"}]}" - }); + _database.Insert( + Cms.Core.Constants.DatabaseSchema.Tables.DataType, + "pk", + false, + new DataTypeDto + { + NodeId = Cms.Core.Constants.DataTypes.Tags, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.Tags, + DbType = "Ntext", + Configuration = "{\"group\":\"default\", \"storageType\":\"Json\"}" + }); + } - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + if (_database.Exists(Cms.Core.Constants.DataTypes.ImageCropper)) { - NodeId = Cms.Core.Constants.DataTypes.UploadArticle, - EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, - DbType = "Nvarchar", - Configuration = "{\"fileExtensions\":[{\"id\":0, \"value\":\"pdf\"}, {\"id\":1, \"value\":\"docx\"}, {\"id\":2, \"value\":\"doc\"}]}" - }); + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Cms.Core.Constants.DataTypes.ImageCropper, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ImageCropper, DbType = "Ntext" }); + } - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + if (_database.Exists(Cms.Core.Constants.DataTypes.DefaultContentListView)) { - NodeId = Cms.Core.Constants.DataTypes.UploadVectorGraphics, - EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, - DbType = "Nvarchar", - Configuration = "{\"fileExtensions\":[{\"id\":0, \"value\":\"svg\"}]}" - }); + _database.Insert( + Cms.Core.Constants.DatabaseSchema.Tables.DataType, + "pk", + false, + new DataTypeDto + { + NodeId = Cms.Core.Constants.DataTypes.DefaultContentListView, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ListView, + DbType = "Nvarchar", + Configuration = "{\"pageSize\":100, \"orderBy\":\"updateDate\", \"orderDirection\":\"desc\", \"layouts\":" + layouts + ", \"includeProperties\":[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]}" + }); + } - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { - NodeId = 1051, - EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker3, - DbType = "Ntext", - Configuration = "{\"multiple\": false, \"validationLimit\":{\"min\":0,\"max\":1}}" - }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { - NodeId = 1052, - EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker3, - DbType = "Ntext", - Configuration = "{\"multiple\": true}" - }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { - NodeId = 1053, - EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker3, - DbType = "Ntext", - Configuration = "{\"filter\":\"" + Cms.Core.Constants.Conventions.MediaTypes.Image + "\", \"multiple\": false, \"validationLimit\":{\"min\":0,\"max\":1}}" - }); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { - NodeId = 1054, - EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker3, - DbType = "Ntext", - Configuration = "{\"filter\":\"" + Cms.Core.Constants.Conventions.MediaTypes.Image + "\", \"multiple\": true}" - }); + if (_database.Exists(Cms.Core.Constants.DataTypes.DefaultMediaListView)) + { + _database.Insert( + Cms.Core.Constants.DatabaseSchema.Tables.DataType, + "pk", + false, + new DataTypeDto + { + NodeId = Cms.Core.Constants.DataTypes.DefaultMediaListView, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ListView, + DbType = "Nvarchar", + Configuration = "{\"pageSize\":100, \"orderBy\":\"updateDate\", \"orderDirection\":\"desc\", \"layouts\":" + layouts + ", \"includeProperties\":[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]}" + }); + } + + if (_database.Exists(Cms.Core.Constants.DataTypes.DefaultMembersListView)) + { + _database.Insert( + Cms.Core.Constants.DatabaseSchema.Tables.DataType, + "pk", + false, + new DataTypeDto + { + NodeId = Cms.Core.Constants.DataTypes.DefaultMembersListView, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ListView, + DbType = "Nvarchar", + Configuration = "{\"pageSize\":10, \"orderBy\":\"username\", \"orderDirection\":\"asc\", \"includeProperties\":[{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]}" + }); + } + + // New UDI pickers with newer Ids + if (_database.Exists(1046)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1046, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.ContentPicker, DbType = "Nvarchar" }); + } + + if (_database.Exists(1047)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1047, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MemberPicker, DbType = "Nvarchar" }); + } + + if (_database.Exists(1048)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1048, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MemberPicker, DbType = "Ntext" }); + } + + if (_database.Exists(1049)) + { + _database.Insert( + Cms.Core.Constants.DatabaseSchema.Tables.DataType, + "pk", + false, + new DataTypeDto + { + NodeId = 1049, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker, + DbType = "Ntext", + Configuration = "{\"multiPicker\":1}" + }); + } + + if (_database.Exists(1050)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1050, EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MultiUrlPicker, DbType = "Ntext" }); + } + + if (_database.Exists(Cms.Core.Constants.DataTypes.UploadVideo)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + { + NodeId = Cms.Core.Constants.DataTypes.UploadVideo, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, + DbType = "Nvarchar", + Configuration = "{\"fileExtensions\":[{\"id\":0, \"value\":\"mp4\"}, {\"id\":1, \"value\":\"webm\"}, {\"id\":2, \"value\":\"ogv\"}]}" + }); + } + + if (_database.Exists(Cms.Core.Constants.DataTypes.UploadAudio)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + { + NodeId = Cms.Core.Constants.DataTypes.UploadAudio, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, + DbType = "Nvarchar", + Configuration = "{\"fileExtensions\":[{\"id\":0, \"value\":\"mp3\"}, {\"id\":1, \"value\":\"weba\"}, {\"id\":2, \"value\":\"oga\"}, {\"id\":3, \"value\":\"opus\"}]}" + }); + } + + if (_database.Exists(Cms.Core.Constants.DataTypes.UploadArticle)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + { + NodeId = Cms.Core.Constants.DataTypes.UploadArticle, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, + DbType = "Nvarchar", + Configuration = "{\"fileExtensions\":[{\"id\":0, \"value\":\"pdf\"}, {\"id\":1, \"value\":\"docx\"}, {\"id\":2, \"value\":\"doc\"}]}" + }); + } + + if (_database.Exists(Cms.Core.Constants.DataTypes.UploadVectorGraphics)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + { + NodeId = Cms.Core.Constants.DataTypes.UploadVectorGraphics, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.UploadField, + DbType = "Nvarchar", + Configuration = "{\"fileExtensions\":[{\"id\":0, \"value\":\"svg\"}]}" + }); + } + + if (_database.Exists(1051)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + { + NodeId = 1051, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker3, + DbType = "Ntext", + Configuration = "{\"multiple\": false, \"validationLimit\":{\"min\":0,\"max\":1}}" + }); + } + + if (_database.Exists(1052)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + { + NodeId = 1052, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker3, + DbType = "Ntext", + Configuration = "{\"multiple\": true}" + }); + } + + if (_database.Exists(1053)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + { + NodeId = 1053, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker3, + DbType = "Ntext", + Configuration = "{\"filter\":\"" + Cms.Core.Constants.Conventions.MediaTypes.Image + "\", \"multiple\": false, \"validationLimit\":{\"min\":0,\"max\":1}}" + }); + } + + if (_database.Exists(1054)) + { + _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto + { + NodeId = 1054, + EditorAlias = Cms.Core.Constants.PropertyEditors.Aliases.MediaPicker3, + DbType = "Ntext", + Configuration = "{\"filter\":\"" + Cms.Core.Constants.Conventions.MediaTypes.Image + "\", \"multiple\": true}" + }); + } } private void CreateRelationTypeData() { - var relationType = new RelationTypeDto { Id = 1, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = Cms.Core.Constants.ObjectTypes.Document, ParentObjectType = Cms.Core.Constants.ObjectTypes.Document, Dual = true, Name = Cms.Core.Constants.Conventions.RelationTypes.RelateDocumentOnCopyName, IsDependency = false}; - relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType); - relationType = new RelationTypeDto { Id = 2, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, ChildObjectType = Cms.Core.Constants.ObjectTypes.Document, ParentObjectType = Cms.Core.Constants.ObjectTypes.Document, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName, IsDependency = false }; - relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType); - relationType = new RelationTypeDto { Id = 3, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias, ChildObjectType = Cms.Core.Constants.ObjectTypes.Media, ParentObjectType = Cms.Core.Constants.ObjectTypes.Media, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName, IsDependency = false }; - relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType); + CreateRelationTypeData(1, Cms.Core.Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, Cms.Core.Constants.Conventions.RelationTypes.RelateDocumentOnCopyName, Cms.Core.Constants.ObjectTypes.Document, Cms.Core.Constants.ObjectTypes.Document, true, false); + CreateRelationTypeData(2, Cms.Core.Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, Cms.Core.Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName, Cms.Core.Constants.ObjectTypes.Document, Cms.Core.Constants.ObjectTypes.Document, false, false); + CreateRelationTypeData(3, Cms.Core.Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias, Cms.Core.Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName, Cms.Core.Constants.ObjectTypes.Media, Cms.Core.Constants.ObjectTypes.Media, false, false); + CreateRelationTypeData(4, Cms.Core.Constants.Conventions.RelationTypes.RelatedMediaAlias, Cms.Core.Constants.Conventions.RelationTypes.RelatedMediaName, null, null, false, true); + CreateRelationTypeData(5, Cms.Core.Constants.Conventions.RelationTypes.RelatedDocumentAlias, Cms.Core.Constants.Conventions.RelationTypes.RelatedDocumentName, null, null, false, true); + } - relationType = new RelationTypeDto { Id = 4, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelatedMediaAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelatedMediaName, IsDependency = true }; + private void CreateRelationTypeData(int id, string alias, string name, Guid? parentObjectType, Guid? childObjectType, bool dual, bool isDependency) + { + var relationType = new RelationTypeDto { Id = id, Alias = alias, ChildObjectType = childObjectType, ParentObjectType = parentObjectType, Dual = dual, Name = name, IsDependency = isDependency }; relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name); - _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType); - relationType = new RelationTypeDto { Id = 5, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelatedDocumentAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelatedDocumentName, IsDependency = true }; - relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name); _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType); } @@ -447,8 +995,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install private void CreateKeyValueData() { - // on install, initialize the umbraco migration plan with the final state - + // On install, initialize the umbraco migration plan with the final state. var upgrader = new Upgrader(new UmbracoPlan(_umbracoVersion)); var stateValueKey = upgrader.StateValueKey; var finalState = upgrader.Plan.FinalState; @@ -458,14 +1005,51 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install private void CreateLogViewerQueryData() { - var defaultData = MigrateLogViewerQueriesFromFileToDb.DefaultLogQueries.ToArray(); + LogViewerQueryDto[] defaultData = MigrateLogViewerQueriesFromFileToDb.DefaultLogQueries.ToArray(); for (int i = 0; i < defaultData.Length; i++) { - var dto = defaultData[i]; + LogViewerQueryDto dto = defaultData[i]; dto.Id = i+1; _database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.LogViewerQuery, "id", false, dto); } } + + private void ConditionalInsert( + string configKey, + string id, + TDto dto, + string tableName, + string primaryKeyName, + bool autoIncrement = false) + { + var alwaysInsert = _entitiesToAlwaysCreate.ContainsKey(configKey) && + _entitiesToAlwaysCreate[configKey].InvariantContains(id.ToString()); + + InstallDefaultDataSettings installDefaultDataSettings = _installDefaultDataSettings.Get(configKey); + + // If there's no configuration, we assume to create. + if (installDefaultDataSettings == null) + { + alwaysInsert = true; + } + + if (!alwaysInsert && installDefaultDataSettings.InstallData == InstallDefaultDataOption.None) + { + return; + } + + if (!alwaysInsert && installDefaultDataSettings.InstallData == InstallDefaultDataOption.Values && !installDefaultDataSettings.Values.InvariantContains(id)) + { + return; + } + + if (!alwaysInsert && installDefaultDataSettings.InstallData == InstallDefaultDataOption.ExceptValues && installDefaultDataSettings.Values.InvariantContains(id)) + { + return; + } + + _database.Insert(tableName, primaryKeyName, autoIncrement, dto); + } } } diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs index 9dab0bd14a..20d01a3f1f 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs @@ -1,9 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using NPoco; using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Notifications; using Umbraco.Cms.Infrastructure.Migrations.Notifications; @@ -11,6 +15,7 @@ using Umbraco.Cms.Infrastructure.Persistence; using Umbraco.Cms.Infrastructure.Persistence.DatabaseModelDefinitions; using Umbraco.Cms.Infrastructure.Persistence.Dtos; using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; using ColumnInfo = Umbraco.Cms.Infrastructure.Persistence.SqlSyntax.ColumnInfo; @@ -88,15 +93,33 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; private readonly IUmbracoVersion _umbracoVersion; + private readonly IOptionsMonitor _defaultDataCreationSettings; - public DatabaseSchemaCreator(IUmbracoDatabase database, ILogger logger, - ILoggerFactory loggerFactory, IUmbracoVersion umbracoVersion, IEventAggregator eventAggregator) + [Obsolete("Please use constructor taking all parameters. Scheduled for removal in V11.")] + public DatabaseSchemaCreator( + IUmbracoDatabase database, + ILogger logger, + ILoggerFactory loggerFactory, + IUmbracoVersion umbracoVersion, + IEventAggregator eventAggregator) + : this (database, logger, loggerFactory, umbracoVersion, eventAggregator, StaticServiceProvider.Instance.GetRequiredService>()) + { + } + + public DatabaseSchemaCreator( + IUmbracoDatabase database, + ILogger logger, + ILoggerFactory loggerFactory, + IUmbracoVersion umbracoVersion, + IEventAggregator eventAggregator, + IOptionsMonitor defaultDataCreationSettings) { _database = database ?? throw new ArgumentNullException(nameof(database)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); _umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion)); _eventAggregator = eventAggregator; + _defaultDataCreationSettings = defaultDataCreationSettings; if (_database?.SqlContext?.SqlSyntax == null) { @@ -153,8 +176,11 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install if (creatingNotification.Cancel == false) { - var dataCreation = new DatabaseDataCreator(_database, - _loggerFactory.CreateLogger(), _umbracoVersion); + var dataCreation = new DatabaseDataCreator( + _database, + _loggerFactory.CreateLogger(), + _umbracoVersion, + _defaultDataCreationSettings); foreach (Type table in OrderedTables) { CreateTable(false, table, dataCreation); @@ -419,9 +445,14 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install where T : new() { Type tableType = typeof(T); - CreateTable(overwrite, tableType, - new DatabaseDataCreator(_database, _loggerFactory.CreateLogger(), - _umbracoVersion)); + CreateTable( + overwrite, + tableType, + new DatabaseDataCreator( + _database, + _loggerFactory.CreateLogger(), + _umbracoVersion, + _defaultDataCreationSettings)); } /// diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreatorFactory.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreatorFactory.cs index a582e1b02a..6511557247 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreatorFactory.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreatorFactory.cs @@ -1,7 +1,12 @@ +using System; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Infrastructure.Persistence; +using Umbraco.Cms.Web.Common.DependencyInjection; namespace Umbraco.Cms.Infrastructure.Migrations.Install { @@ -14,22 +19,35 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install private readonly ILoggerFactory _loggerFactory; private readonly IUmbracoVersion _umbracoVersion; private readonly IEventAggregator _eventAggregator; + private readonly IOptionsMonitor _installDefaultDataSettings; + [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in V11.")] public DatabaseSchemaCreatorFactory( ILogger logger, ILoggerFactory loggerFactory, IUmbracoVersion umbracoVersion, IEventAggregator eventAggregator) + : this(logger, loggerFactory, umbracoVersion, eventAggregator, StaticServiceProvider.Instance.GetRequiredService>()) + { + } + + public DatabaseSchemaCreatorFactory( + ILogger logger, + ILoggerFactory loggerFactory, + IUmbracoVersion umbracoVersion, + IEventAggregator eventAggregator, + IOptionsMonitor installDefaultDataSettings) { _logger = logger; _loggerFactory = loggerFactory; _umbracoVersion = umbracoVersion; _eventAggregator = eventAggregator; + _installDefaultDataSettings = installDefaultDataSettings; } public DatabaseSchemaCreator Create(IUmbracoDatabase database) { - return new DatabaseSchemaCreator(database, _logger, _loggerFactory, _umbracoVersion, _eventAggregator); + return new DatabaseSchemaCreator(database, _logger, _loggerFactory, _umbracoVersion, _eventAggregator, _installDefaultDataSettings); } } } diff --git a/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs b/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs index 6b7c34dc15..47cca58ce2 100644 --- a/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs +++ b/src/Umbraco.Infrastructure/Persistence/NPocoSqlExtensions.cs @@ -659,6 +659,12 @@ namespace Umbraco.Extensions return sql; } + public static Sql SelectDistinct(this Sql sql, params object[] columns) + { + sql.Append("SELECT DISTINCT " + string.Join(", ", columns)); + return sql; + } + //this.Append("SELECT " + string.Join(", ", columns), new object[0]); /// diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MacroRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MacroRepository.cs index 535895e8ed..21638027ea 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MacroRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MacroRepository.cs @@ -18,14 +18,16 @@ using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement { - internal class MacroRepository : EntityRepositoryBase, IMacroRepository + internal class MacroRepository : EntityRepositoryBase, IMacroWithAliasRepository { private readonly IShortStringHelper _shortStringHelper; + private readonly IRepositoryCachePolicy _macroByAliasCachePolicy; public MacroRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IShortStringHelper shortStringHelper) : base(scopeAccessor, cache, logger) { _shortStringHelper = shortStringHelper; + _macroByAliasCachePolicy = new DefaultRepositoryCachePolicy(GlobalIsolatedCache, ScopeAccessor, DefaultOptions); } protected override IMacro PerformGet(int id) @@ -68,6 +70,38 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement return Get(id) != null; } + public IMacro GetByAlias(string alias) + { + return _macroByAliasCachePolicy.Get(alias, PerformGetByAlias, PerformGetAllByAlias); + } + + public IEnumerable GetAllByAlias(string[] aliases) + { + if (aliases.Any() is false) + { + return base.GetMany(); + } + + return _macroByAliasCachePolicy.GetAll(aliases, PerformGetAllByAlias); + } + + private IMacro PerformGetByAlias(string alias) + { + var query = Query().Where(x => x.Alias.Equals(alias)); + return PerformGetByQuery(query).FirstOrDefault(); + } + + private IEnumerable PerformGetAllByAlias(params string[] aliases) + { + if (aliases.Any() is false) + { + return base.GetMany(); + } + + var query = Query().Where(x => aliases.Contains(x.Alias)); + return PerformGetByQuery(query); + } + protected override IEnumerable PerformGetAll(params int[] ids) { return ids.Length > 0 ? ids.Select(Get) : GetAllNoIds(); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs index 6ab29aa47e..5e9a8413b4 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs @@ -60,14 +60,14 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement var urlHash = url.GenerateHash(); Sql sql = GetBaseQuery(false) .Where(x => x.Url == url && x.UrlHash == urlHash && - (x.Culture == culture.ToLower() || x.Culture == string.Empty)) + (x.Culture == culture.ToLower() || x.Culture == null || x.Culture == string.Empty)) .OrderByDescending(x => x.CreateDateUtc); List dtos = Database.Fetch(sql); RedirectUrlDto dto = dtos.FirstOrDefault(f => f.Culture == culture.ToLower()); if (dto == null) { - dto = dtos.FirstOrDefault(f => f.Culture == string.Empty); + dto = dtos.FirstOrDefault(f => string.IsNullOrWhiteSpace(f.Culture)); } return dto == null ? null : Map(dto); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationRepository.cs index a18782ca82..7ba20d1db5 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationRepository.cs @@ -198,22 +198,6 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement }); } - public IEnumerable GetPagedParentEntitiesByChildIds(int[] childIds, long pageIndex, int pageSize, out long totalRecords, int[] relationTypes, params Guid[] entityTypes) - { - return _entityRepository.GetPagedResultsByQuery(Query(), entityTypes, pageIndex, pageSize, out totalRecords, null, null, sql => - { - SqlJoinRelations(sql); - - sql.WhereIn(rel => rel.ChildId, childIds); - sql.WhereAny(s => s.WhereIn(rel => rel.ParentId, childIds), s => s.WhereNotIn(node => node.NodeId, childIds)); - - if (relationTypes != null && relationTypes.Any()) - { - sql.WhereIn(rel => rel.RelationType, relationTypes); - } - }); - } - public IEnumerable GetPagedChildEntitiesByParentId(int parentId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes) { return GetPagedChildEntitiesByParentId(parentId, pageIndex, pageSize, out totalRecords, new int[0], entityTypes); @@ -241,21 +225,6 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement }); } - public IEnumerable GetPagedEntitiesForItemsInRelation(int[] itemIds, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes) - { - return _entityRepository.GetPagedResultsByQuery(Query(), entityTypes, pageIndex, pageSize, out totalRecords, null, null, sql => - { - SqlJoinRelations(sql); - - sql.WhereIn(rel => rel.ChildId, itemIds); - sql.Where((rel, node) => rel.ChildId == node.NodeId); - sql.Where(type => type.IsDependency); - }); - } - - - - public void Save(IEnumerable relations) { foreach (var hasIdentityGroup in relations.GroupBy(r => r.HasIdentity)) @@ -475,8 +444,6 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement [Column(Name = "contentTypeName")] public string ChildContentTypeName { get; set; } - - [Column(Name = "relationTypeName")] public string RelationTypeName { get; set; } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TrackedReferencesRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TrackedReferencesRepository.cs index f5fb945464..478018ed96 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TrackedReferencesRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TrackedReferencesRepository.cs @@ -1,9 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using NPoco; using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Persistence; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Infrastructure.Persistence.Dtos; @@ -20,10 +19,12 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement _scopeAccessor = scopeAccessor; } - public IEnumerable GetPagedItemsWithRelations(int[] ids, long pageIndex, int pageSize, - bool filterMustBeIsDependency, out long totalRecords) + /// + /// Gets a page of items used in any kind of relation from selected integer ids. + /// + public IEnumerable GetPagedItemsWithRelations(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords) { - var sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql().Select( + var sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql().SelectDistinct( "[pn].[id] as nodeId", "[pn].[uniqueId] as nodeKey", "[pn].[text] as nodeName", @@ -36,12 +37,12 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement "[umbracoRelationType].[isDependency] as relationTypeIsDependency", "[umbracoRelationType].[dual] as relationTypeIsBidirectional") .From("r") - .InnerJoin("umbracoRelationType").On((left, right) => left.RelationType == right.Id, aliasLeft: "r", aliasRight:"umbracoRelationType") - .InnerJoin("cn").On((r, cn, rt) => (!rt.Dual && r.ParentId == cn.NodeId) || (rt.Dual && (r.ChildId == cn.NodeId || r.ParentId == cn.NodeId )), aliasLeft: "r", aliasRight:"cn", aliasOther: "umbracoRelationType" ) - .InnerJoin("pn").On((r, pn, cn) => (pn.NodeId == r.ChildId && cn.NodeId == r.ParentId) || (pn.NodeId == r.ParentId && cn.NodeId == r.ChildId), aliasLeft: "r", aliasRight:"pn", aliasOther:"cn" ) - .LeftJoin("c").On((left, right) => left.NodeId == right.NodeId, aliasLeft:"pn", aliasRight:"c") - .LeftJoin("ct").On((left, right) => left.ContentTypeId == right.NodeId, aliasLeft:"c", aliasRight:"ct") - .LeftJoin("ctn").On((left, right) => left.NodeId == right.NodeId, aliasLeft:"ct", aliasRight:"ctn"); + .InnerJoin("umbracoRelationType").On((left, right) => left.RelationType == right.Id, aliasLeft: "r", aliasRight: "umbracoRelationType") + .InnerJoin("cn").On((r, cn, rt) => (!rt.Dual && r.ParentId == cn.NodeId) || (rt.Dual && (r.ChildId == cn.NodeId || r.ParentId == cn.NodeId)), aliasLeft: "r", aliasRight: "cn", aliasOther: "umbracoRelationType") + .InnerJoin("pn").On((r, pn, cn) => (pn.NodeId == r.ChildId && cn.NodeId == r.ParentId) || (pn.NodeId == r.ParentId && cn.NodeId == r.ChildId), aliasLeft: "r", aliasRight: "pn", aliasOther: "cn") + .LeftJoin("c").On((left, right) => left.NodeId == right.NodeId, aliasLeft: "pn", aliasRight: "c") + .LeftJoin("ct").On((left, right) => left.ContentTypeId == right.NodeId, aliasLeft: "c", aliasRight: "ct") + .LeftJoin("ctn").On((left, right) => left.NodeId == right.NodeId, aliasLeft: "ct", aliasRight: "ctn"); if (ids.Any()) { @@ -57,13 +58,15 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement sql = sql.OrderBy(x => x.Alias); var pagedResult = _scopeAccessor.AmbientScope.Database.Page(pageIndex + 1, pageSize, sql); - totalRecords = Convert.ToInt32(pagedResult.TotalItems); + totalRecords = pagedResult.TotalItems; return pagedResult.Items.Select(MapDtoToEntity); } - public IEnumerable GetPagedDescendantsInReferences(int parentId, long pageIndex, int pageSize, bool filterMustBeIsDependency, - out long totalRecords) + /// + /// Gets a page of the descending items that have any references, given a parent id. + /// + public IEnumerable GetPagedDescendantsInReferences(int parentId, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords) { var syntax = _scopeAccessor.AmbientScope.Database.SqlContext.SqlSyntax; @@ -73,13 +76,12 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement .From("node") .Where(x => x.NodeId == parentId, "node"); - // Gets the descendants of the parent node Sql subQuery; if (_scopeAccessor.AmbientScope.Database.DatabaseType.IsSqlCe()) { - // SqlCE do not support nested selects that returns a scalar. So we need to do this in multiple queries + // SqlCE does not support nested selects that returns a scalar. So we need to do this in multiple queries var pathForLike = _scopeAccessor.AmbientScope.Database.ExecuteScalar(subsubQuery); @@ -96,10 +98,8 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement .WhereLike(x => x.Path, subsubQuery); } - - // Get all relations where parent is in the sub query - var sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql().Select( + var sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql().SelectDistinct( "[pn].[id] as nodeId", "[pn].[uniqueId] as nodeKey", "[pn].[text] as nodeName", @@ -112,29 +112,35 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement "[umbracoRelationType].[isDependency] as relationTypeIsDependency", "[umbracoRelationType].[dual] as relationTypeIsBidirectional") .From("r") - .InnerJoin("umbracoRelationType").On((left, right) => left.RelationType == right.Id, aliasLeft: "r", aliasRight:"umbracoRelationType") - .InnerJoin("cn").On((r, cn, rt) => (!rt.Dual && r.ParentId == cn.NodeId) || (rt.Dual && (r.ChildId == cn.NodeId || r.ParentId == cn.NodeId )), aliasLeft: "r", aliasRight:"cn", aliasOther: "umbracoRelationType" ) - .InnerJoin("pn").On((r, pn, cn) => (pn.NodeId == r.ChildId && cn.NodeId == r.ParentId) || (pn.NodeId == r.ParentId && cn.NodeId == r.ChildId), aliasLeft: "r", aliasRight:"pn", aliasOther:"cn" ) - .LeftJoin("c").On((left, right) => left.NodeId == right.NodeId, aliasLeft:"pn", aliasRight:"c") - .LeftJoin("ct").On((left, right) => left.ContentTypeId == right.NodeId, aliasLeft:"c", aliasRight:"ct") - .LeftJoin("ctn").On((left, right) => left.NodeId == right.NodeId, aliasLeft:"ct", aliasRight:"ctn") + .InnerJoin("umbracoRelationType").On((left, right) => left.RelationType == right.Id, aliasLeft: "r", aliasRight: "umbracoRelationType") + .InnerJoin("cn").On((r, cn, rt) => (!rt.Dual && r.ParentId == cn.NodeId) || (rt.Dual && (r.ChildId == cn.NodeId || r.ParentId == cn.NodeId)), aliasLeft: "r", aliasRight: "cn", aliasOther: "umbracoRelationType") + .InnerJoin("pn").On((r, pn, cn) => (pn.NodeId == r.ChildId && cn.NodeId == r.ParentId) || (pn.NodeId == r.ParentId && cn.NodeId == r.ChildId), aliasLeft: "r", aliasRight: "pn", aliasOther: "cn") + .LeftJoin("c").On((left, right) => left.NodeId == right.NodeId, aliasLeft: "pn", aliasRight: "c") + .LeftJoin("ct").On((left, right) => left.ContentTypeId == right.NodeId, aliasLeft: "c", aliasRight: "ct") + .LeftJoin("ctn").On((left, right) => left.NodeId == right.NodeId, aliasLeft: "ct", aliasRight: "ctn") .WhereIn((System.Linq.Expressions.Expression>)(x => x.NodeId), subQuery, "pn"); + if (filterMustBeIsDependency) { sql = sql.Where(rt => rt.IsDependency, "umbracoRelationType"); } + // Ordering is required for paging sql = sql.OrderBy(x => x.Alias); var pagedResult = _scopeAccessor.AmbientScope.Database.Page(pageIndex + 1, pageSize, sql); - totalRecords = Convert.ToInt32(pagedResult.TotalItems); + totalRecords = pagedResult.TotalItems; return pagedResult.Items.Select(MapDtoToEntity); } - public IEnumerable GetPagedRelationsForItems(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords) + /// + /// Gets a page of items which are in relation with the current item. + /// Basically, shows the items which depend on the current item. + /// + public IEnumerable GetPagedRelationsForItem(int id, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords) { - var sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql().Select( + var sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql().SelectDistinct( "[cn].[id] as nodeId", "[cn].[uniqueId] as nodeKey", "[cn].[text] as nodeName", @@ -147,17 +153,14 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement "[umbracoRelationType].[isDependency] as relationTypeIsDependency", "[umbracoRelationType].[dual] as relationTypeIsBidirectional") .From("r") - .InnerJoin("umbracoRelationType").On((left, right) => left.RelationType == right.Id, aliasLeft: "r", aliasRight:"umbracoRelationType") - .InnerJoin("cn").On((r, cn, rt) => (!rt.Dual && r.ParentId == cn.NodeId) || (rt.Dual && (r.ChildId == cn.NodeId || r.ParentId == cn.NodeId )), aliasLeft: "r", aliasRight:"cn", aliasOther: "umbracoRelationType" ) - .InnerJoin("pn").On((r, pn, cn) => (pn.NodeId == r.ChildId && cn.NodeId == r.ParentId) || (pn.NodeId == r.ParentId && cn.NodeId == r.ChildId), aliasLeft: "r", aliasRight:"pn", aliasOther:"cn" ) - .LeftJoin("c").On((left, right) => left.NodeId == right.NodeId, aliasLeft:"cn", aliasRight:"c") - .LeftJoin("ct").On((left, right) => left.ContentTypeId == right.NodeId, aliasLeft:"c", aliasRight:"ct") - .LeftJoin("ctn").On((left, right) => left.NodeId == right.NodeId, aliasLeft:"ct", aliasRight:"ctn"); - - if (ids.Any()) - { - sql = sql.Where(x => ids.Contains(x.NodeId), "pn"); - } + .InnerJoin("umbracoRelationType").On((left, right) => left.RelationType == right.Id, aliasLeft: "r", aliasRight: "umbracoRelationType") + .InnerJoin("cn").On((r, cn, rt) => (!rt.Dual && r.ParentId == cn.NodeId) || (rt.Dual && (r.ChildId == cn.NodeId || r.ParentId == cn.NodeId)), aliasLeft: "r", aliasRight: "cn", aliasOther: "umbracoRelationType") + .InnerJoin("pn").On((r, pn, cn) => (pn.NodeId == r.ChildId && cn.NodeId == r.ParentId) || (pn.NodeId == r.ParentId && cn.NodeId == r.ChildId), aliasLeft: "r", aliasRight: "pn", aliasOther: "cn") + .LeftJoin("c").On((left, right) => left.NodeId == right.NodeId, aliasLeft: "cn", aliasRight: "c") + .LeftJoin("ct").On((left, right) => left.ContentTypeId == right.NodeId, aliasLeft: "c", aliasRight: "ct") + .LeftJoin("ctn").On((left, right) => left.NodeId == right.NodeId, aliasLeft: "ct", aliasRight: "ctn") + .Where(x => x.NodeId == id, "pn") + .Where(x => x.ChildId == id || x.ParentId == id, "r"); // This last Where is purely to help SqlServer make a smarter query plan. More info https://github.com/umbraco/Umbraco-CMS/issues/12190 if (filterMustBeIsDependency) { @@ -168,14 +171,13 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement sql = sql.OrderBy(x => x.Alias); var pagedResult = _scopeAccessor.AmbientScope.Database.Page(pageIndex + 1, pageSize, sql); - totalRecords = Convert.ToInt32(pagedResult.TotalItems); + totalRecords = pagedResult.TotalItems; return pagedResult.Items.Select(MapDtoToEntity); } private RelationItem MapDtoToEntity(RelationItemDto dto) { - var type = ObjectTypes.GetUdiType(dto.ChildNodeObjectType); return new RelationItem() { NodeId = dto.ChildNodeId, diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs index f149757919..c3d8be8f50 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Media; @@ -14,6 +15,8 @@ using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Core.Templates; +using Umbraco.Cms.Infrastructure.Templates; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -37,6 +40,7 @@ namespace Umbraco.Cms.Core.PropertyEditors private readonly RichTextEditorPastedImages _pastedImages; private readonly HtmlLocalLinkParser _localLinkParser; private readonly IImageUrlGenerator _imageUrlGenerator; + private readonly IHtmlMacroParameterParser _macroParameterParser; public GridPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, @@ -45,7 +49,8 @@ namespace Umbraco.Cms.Core.PropertyEditors RichTextEditorPastedImages pastedImages, HtmlLocalLinkParser localLinkParser, IIOHelper ioHelper, - IImageUrlGenerator imageUrlGenerator) + IImageUrlGenerator imageUrlGenerator, + IHtmlMacroParameterParser macroParameterParser) : base(dataValueEditorFactory) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; @@ -54,6 +59,20 @@ namespace Umbraco.Cms.Core.PropertyEditors _pastedImages = pastedImages; _localLinkParser = localLinkParser; _imageUrlGenerator = imageUrlGenerator; + _macroParameterParser = macroParameterParser; + } + + [Obsolete("Use the constructor which takes an IHtmlMacroParameterParser instead")] + public GridPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + HtmlImageSourceParser imageSourceParser, + RichTextEditorPastedImages pastedImages, + HtmlLocalLinkParser localLinkParser, + IIOHelper ioHelper, + IImageUrlGenerator imageUrlGenerator) + : this (dataValueEditorFactory, backOfficeSecurityAccessor, imageSourceParser, pastedImages, localLinkParser, ioHelper, imageUrlGenerator, StaticServiceProvider.Instance.GetRequiredService()) + { } public override IPropertyIndexValueFactory PropertyIndexValueFactory => new GridPropertyIndexValueFactory(); @@ -74,6 +93,7 @@ namespace Umbraco.Cms.Core.PropertyEditors private readonly RichTextPropertyEditor.RichTextPropertyValueEditor _richTextPropertyValueEditor; private readonly MediaPickerPropertyEditor.MediaPickerPropertyValueEditor _mediaPickerPropertyValueEditor; private readonly IImageUrlGenerator _imageUrlGenerator; + private readonly IHtmlMacroParameterParser _macroParameterParser; public GridPropertyValueEditor( IDataValueEditorFactory dataValueEditorFactory, @@ -85,7 +105,8 @@ namespace Umbraco.Cms.Core.PropertyEditors IShortStringHelper shortStringHelper, IImageUrlGenerator imageUrlGenerator, IJsonSerializer jsonSerializer, - IIOHelper ioHelper) + IIOHelper ioHelper, + IHtmlMacroParameterParser macroParameterParser) : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; @@ -96,6 +117,25 @@ namespace Umbraco.Cms.Core.PropertyEditors _mediaPickerPropertyValueEditor = dataValueEditorFactory.Create(attribute); _imageUrlGenerator = imageUrlGenerator; + _macroParameterParser = macroParameterParser; + } + + [Obsolete("Use the constructor which takes an IHtmlMacroParameterParser instead")] + public GridPropertyValueEditor( + IDataValueEditorFactory dataValueEditorFactory, + DataEditorAttribute attribute, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + ILocalizedTextService localizedTextService, + HtmlImageSourceParser imageSourceParser, + RichTextEditorPastedImages pastedImages, + IShortStringHelper shortStringHelper, + IImageUrlGenerator imageUrlGenerator, + IJsonSerializer jsonSerializer, + IIOHelper ioHelper) + : this (dataValueEditorFactory, attribute, backOfficeSecurityAccessor, localizedTextService, + imageSourceParser, pastedImages, shortStringHelper, imageUrlGenerator, jsonSerializer, ioHelper, + StaticServiceProvider.Instance.GetRequiredService()) + { } /// @@ -120,7 +160,7 @@ namespace Umbraco.Cms.Core.PropertyEditors var mediaParent = config?.MediaParentId; var mediaParentId = mediaParent == null ? Guid.Empty : mediaParent.Guid; - var grid = DeserializeGridValue(rawJson, out var rtes, out _); + var grid = DeserializeGridValue(rawJson, out var rtes, out _, out _); var userId = _backOfficeSecurityAccessor?.BackOfficeSecurity?.CurrentUser?.Id ?? Constants.Security.SuperUserId; @@ -154,7 +194,7 @@ namespace Umbraco.Cms.Core.PropertyEditors if (val.IsNullOrWhiteSpace()) return string.Empty; - var grid = DeserializeGridValue(val, out var rtes, out _); + var grid = DeserializeGridValue(val, out var rtes, out _, out _); //process the rte values foreach (var rte in rtes.ToList()) @@ -168,7 +208,7 @@ namespace Umbraco.Cms.Core.PropertyEditors return grid; } - private GridValue DeserializeGridValue(string rawJson, out IEnumerable richTextValues, out IEnumerable mediaValues) + private GridValue DeserializeGridValue(string rawJson, out IEnumerable richTextValues, out IEnumerable mediaValues, out IEnumerable macroValues) { var grid = JsonConvert.DeserializeObject(rawJson); @@ -177,6 +217,9 @@ namespace Umbraco.Cms.Core.PropertyEditors richTextValues = controls.Where(x => x.Editor.Alias.ToLowerInvariant() == "rte"); mediaValues = controls.Where(x => x.Editor.Alias.ToLowerInvariant() == "media"); + // Find all the macros + macroValues = controls.Where(x => x.Editor.Alias.ToLowerInvariant() == "macro"); + return grid; } @@ -192,7 +235,7 @@ namespace Umbraco.Cms.Core.PropertyEditors if (rawJson.IsNullOrWhiteSpace()) yield break; - DeserializeGridValue(rawJson, out var richTextEditorValues, out var mediaValues); + DeserializeGridValue(rawJson, out var richTextEditorValues, out var mediaValues, out var macroValues); foreach (var umbracoEntityReference in richTextEditorValues.SelectMany(x => _richTextPropertyValueEditor.GetReferences(x.Value))) @@ -201,6 +244,9 @@ namespace Umbraco.Cms.Core.PropertyEditors foreach (var umbracoEntityReference in mediaValues.Where(x => x.Value.HasValues) .SelectMany(x => _mediaPickerPropertyValueEditor.GetReferences(x.Value["udi"]))) yield return umbracoEntityReference; + + foreach (var umbracoEntityReference in _macroParameterParser.FindUmbracoEntityReferencesFromGridControlMacros(macroValues)) + yield return umbracoEntityReference; } } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs index 1cfbc3449e..18c3fe0902 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs @@ -3,8 +3,7 @@ using System; using System.Collections.Generic; -using Microsoft.Extensions.Logging; -using Umbraco.Cms.Core.Hosting; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Media; using Umbraco.Cms.Core.Models; @@ -16,6 +15,8 @@ using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Core.Templates; using Umbraco.Cms.Infrastructure.Examine; using Umbraco.Cms.Infrastructure.Macros; +using Umbraco.Cms.Infrastructure.Templates; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors @@ -36,12 +37,13 @@ namespace Umbraco.Cms.Core.PropertyEditors private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly HtmlImageSourceParser _imageSourceParser; private readonly HtmlLocalLinkParser _localLinkParser; + private readonly IHtmlMacroParameterParser _macroParameterParser; private readonly RichTextEditorPastedImages _pastedImages; private readonly IIOHelper _ioHelper; private readonly IImageUrlGenerator _imageUrlGenerator; /// - /// The constructor will setup the property editor based on the attribute if one is found + /// The constructor will setup the property editor based on the attribute if one is found. /// public RichTextPropertyEditor( IDataValueEditorFactory dataValueEditorFactory, @@ -50,7 +52,8 @@ namespace Umbraco.Cms.Core.PropertyEditors HtmlLocalLinkParser localLinkParser, RichTextEditorPastedImages pastedImages, IIOHelper ioHelper, - IImageUrlGenerator imageUrlGenerator) + IImageUrlGenerator imageUrlGenerator, + IHtmlMacroParameterParser macroParameterParser) : base(dataValueEditorFactory) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; @@ -59,6 +62,20 @@ namespace Umbraco.Cms.Core.PropertyEditors _pastedImages = pastedImages; _ioHelper = ioHelper; _imageUrlGenerator = imageUrlGenerator; + _macroParameterParser = macroParameterParser; + } + + [Obsolete("Use the constructor which takes an IHtmlMacroParameterParser instead")] + public RichTextPropertyEditor( + IDataValueEditorFactory dataValueEditorFactory, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + HtmlImageSourceParser imageSourceParser, + HtmlLocalLinkParser localLinkParser, + RichTextEditorPastedImages pastedImages, + IIOHelper ioHelper, + IImageUrlGenerator imageUrlGenerator) + : this (dataValueEditorFactory, backOfficeSecurityAccessor, imageSourceParser, localLinkParser, pastedImages, ioHelper, imageUrlGenerator, StaticServiceProvider.Instance.GetRequiredService()) + { } /// @@ -79,6 +96,7 @@ namespace Umbraco.Cms.Core.PropertyEditors private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly HtmlImageSourceParser _imageSourceParser; private readonly HtmlLocalLinkParser _localLinkParser; + private readonly IHtmlMacroParameterParser _macroParameterParser; private readonly RichTextEditorPastedImages _pastedImages; private readonly IImageUrlGenerator _imageUrlGenerator; private readonly IHtmlSanitizer _htmlSanitizer; @@ -94,7 +112,8 @@ namespace Umbraco.Cms.Core.PropertyEditors IImageUrlGenerator imageUrlGenerator, IJsonSerializer jsonSerializer, IIOHelper ioHelper, - IHtmlSanitizer htmlSanitizer) + IHtmlSanitizer htmlSanitizer, + IHtmlMacroParameterParser macroParameterParser) : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute) { _backOfficeSecurityAccessor = backOfficeSecurityAccessor; @@ -103,6 +122,26 @@ namespace Umbraco.Cms.Core.PropertyEditors _pastedImages = pastedImages; _imageUrlGenerator = imageUrlGenerator; _htmlSanitizer = htmlSanitizer; + _macroParameterParser = macroParameterParser; + } + + [Obsolete("Use the constructor which takes an HtmlMacroParameterParser instead")] + public RichTextPropertyValueEditor( + DataEditorAttribute attribute, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + HtmlImageSourceParser imageSourceParser, + HtmlLocalLinkParser localLinkParser, + RichTextEditorPastedImages pastedImages, + IImageUrlGenerator imageUrlGenerator, + IJsonSerializer jsonSerializer, + IIOHelper ioHelper, + IHtmlSanitizer htmlSanitizer) + : this(attribute, backOfficeSecurityAccessor, localizedTextService, shortStringHelper, imageSourceParser, + localLinkParser, pastedImages, imageUrlGenerator, jsonSerializer, ioHelper, htmlSanitizer, + StaticServiceProvider.Instance.GetRequiredService()) + { } /// @@ -182,6 +221,10 @@ namespace Umbraco.Cms.Core.PropertyEditors yield return new UmbracoEntityReference(udi); //TODO: Detect Macros too ... but we can save that for a later date, right now need to do media refs + //UPDATE: We are getting the Macros in 'FindUmbracoEntityReferencesFromEmbeddedMacros' - perhaps we just return the macro Udis here too or do they need their own relationAlias? + + foreach (var umbracoEntityReference in _macroParameterParser.FindUmbracoEntityReferencesFromEmbeddedMacros(asString)) + yield return umbracoEntityReference; } } diff --git a/src/Umbraco.Infrastructure/Security/MemberPasswordHasher.cs b/src/Umbraco.Infrastructure/Security/MemberPasswordHasher.cs index e470bf0a6c..02aef30217 100644 --- a/src/Umbraco.Infrastructure/Security/MemberPasswordHasher.cs +++ b/src/Umbraco.Infrastructure/Security/MemberPasswordHasher.cs @@ -71,6 +71,7 @@ namespace Umbraco.Cms.Core.Security return result; } } + // We need to check for clear text passwords from members as the first thing. This was possible in v8 :( else if (IsSuccessfulLegacyPassword(hashedPassword, providedPassword)) { @@ -138,7 +139,7 @@ namespace Umbraco.Cms.Core.Security } var result = LegacyPasswordSecurity.VerifyPassword(Constants.Security.AspNetUmbraco8PasswordHashAlgorithmName, providedPassword, hashedPassword); - return result || LegacyPasswordSecurity.VerifyPassword(Constants.Security.AspNetUmbraco4PasswordHashAlgorithmName, providedPassword, hashedPassword); + return result || LegacyPasswordSecurity.VerifyLegacyHashedPassword(providedPassword, hashedPassword); } private static string DecryptLegacyPassword(string encryptedPassword, string algorithmName, string decryptionKey) diff --git a/src/Umbraco.Infrastructure/Security/UmbracoPasswordHasher.cs b/src/Umbraco.Infrastructure/Security/UmbracoPasswordHasher.cs index da08bc8713..2847f13dc4 100644 --- a/src/Umbraco.Infrastructure/Security/UmbracoPasswordHasher.cs +++ b/src/Umbraco.Infrastructure/Security/UmbracoPasswordHasher.cs @@ -1,3 +1,4 @@ +using System; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Models.Membership; @@ -10,7 +11,6 @@ namespace Umbraco.Cms.Core.Security where TUser: UmbracoIdentityUser { private readonly IJsonSerializer _jsonSerializer; - private readonly PasswordHasher _aspnetV2PasswordHasher = new PasswordHasher(new V2PasswordHasherOptions()); public UmbracoPasswordHasher(LegacyPasswordSecurity legacyPasswordSecurity, IJsonSerializer jsonSerializer) { @@ -43,57 +43,64 @@ namespace Umbraco.Cms.Core.Security { if (user is null) { - throw new System.ArgumentNullException(nameof(user)); + throw new ArgumentNullException(nameof(user)); } - if (!user.PasswordConfig.IsNullOrWhiteSpace()) + try { - // check if the (legacy) password security supports this hash algorith and if so then use it - var deserialized = _jsonSerializer.Deserialize(user.PasswordConfig); - if (LegacyPasswordSecurity.SupportHashAlgorithm(deserialized.HashAlgorithm)) + // Best case and most likely scenario, a modern hash supported by ASP.Net identity. + PasswordVerificationResult upstreamResult = base.VerifyHashedPassword(user, hashedPassword, providedPassword); + if (upstreamResult != PasswordVerificationResult.Failed) { - var result = LegacyPasswordSecurity.VerifyPassword(deserialized.HashAlgorithm, providedPassword, hashedPassword); - - //We need to special handle this case, apparently v8 still saves the user algorithm as {"hashAlgorithm":"HMACSHA256"}, when using legacy encoding and hasinging. - if (result == false) - { - result = LegacyPasswordSecurity.VerifyLegacyHashedPassword(providedPassword, hashedPassword); - } - - return result - ? PasswordVerificationResult.SuccessRehashNeeded - : PasswordVerificationResult.Failed; - } - - // We will explicitly detect names here - // The default is PBKDF2.ASPNETCORE.V3: - // PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations. - // The underlying class only lets us change 2 things which is the version: options.CompatibilityMode and the iteration count - // The PBKDF2.ASPNETCORE.V2 settings are: - // PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations. - - switch (deserialized.HashAlgorithm) - { - case Constants.Security.AspNetCoreV3PasswordHashAlgorithmName: - return base.VerifyHashedPassword(user, hashedPassword, providedPassword); - case Constants.Security.AspNetCoreV2PasswordHashAlgorithmName: - var legacyResult = _aspnetV2PasswordHasher.VerifyHashedPassword(user, hashedPassword, providedPassword); - if (legacyResult == PasswordVerificationResult.Success) - return PasswordVerificationResult.SuccessRehashNeeded; - return legacyResult; + return upstreamResult; } } - - // else go the default (v3) - return base.VerifyHashedPassword(user, hashedPassword, providedPassword); - } - - private class V2PasswordHasherOptions : IOptions - { - public PasswordHasherOptions Value => new PasswordHasherOptions + catch (FormatException) { - CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2 - }; + // hash wasn't a valid base64 encoded string, MS concat the salt bytes and hash bytes and base 64 encode both together. + // We however historically base 64 encoded the salt bytes and hash bytes separately then concat the strings so we got 2 sets of padding. + // both salt bytes and hash bytes lengths were not evenly divisible by 3 hence 2 sets of padding. + + // We could check upfront with TryFromBase64String, but not whilst we target netstandard 2.0 + // so might as well just deal with the exception. + } + + // At this point we either have a legacy password or a bad attempt. + + // Check the supported worst case scenario, a "useLegacyEncoding" password - HMACSHA1 but with password used as key so not unique for users sharing same password + // This was the standard for v4. + // Do this first because with useLegacyEncoding the algorithm stored in the database is irrelevant. + if (LegacyPasswordSecurity.VerifyLegacyHashedPassword(providedPassword, hashedPassword)) + { + return PasswordVerificationResult.SuccessRehashNeeded; + } + + // For users we expect to know the historic algorithm. + // NOTE: MemberPasswordHasher subclasses this class to deal with the fact that PasswordConfig wasn't stored. + if (user.PasswordConfig.IsNullOrWhiteSpace()) + { + return PasswordVerificationResult.Failed; + } + + PersistedPasswordSettings deserialized; + try + { + deserialized = _jsonSerializer.Deserialize(user.PasswordConfig); + } + catch + { + return PasswordVerificationResult.Failed; + } + + if (!LegacyPasswordSecurity.SupportHashAlgorithm(deserialized.HashAlgorithm)) + { + return PasswordVerificationResult.Failed; + } + + // Last chance must be HMACSHA256 or SHA1 + return LegacyPasswordSecurity.VerifyPassword(deserialized.HashAlgorithm, providedPassword, hashedPassword) + ? PasswordVerificationResult.SuccessRehashNeeded + : PasswordVerificationResult.Failed; } } } diff --git a/src/Umbraco.Infrastructure/Services/Implement/MacroService.cs b/src/Umbraco.Infrastructure/Services/Implement/MacroService.cs index a79d9fddce..a1d556d805 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/MacroService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/MacroService.cs @@ -13,13 +13,12 @@ namespace Umbraco.Cms.Core.Services.Implement /// /// Represents the Macro Service, which is an easy access to operations involving /// - internal class MacroService : RepositoryService, IMacroService + internal class MacroService : RepositoryService, IMacroWithAliasService { private readonly IMacroRepository _macroRepository; private readonly IAuditRepository _auditRepository; - public MacroService(IScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, - IMacroRepository macroRepository, IAuditRepository auditRepository) + public MacroService(IScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IMacroRepository macroRepository, IAuditRepository auditRepository) : base(provider, loggerFactory, eventMessagesFactory) { _macroRepository = macroRepository; @@ -33,10 +32,14 @@ namespace Umbraco.Cms.Core.Services.Implement /// An object public IMacro GetByAlias(string alias) { + if (_macroRepository is not IMacroWithAliasRepository macroWithAliasRepository) + { + return GetAll().FirstOrDefault(x => x.Alias == alias); + } + using (var scope = ScopeProvider.CreateScope(autoComplete: true)) { - var q = Query().Where(x => x.Alias == alias); - return _macroRepository.Get(q).FirstOrDefault(); + return macroWithAliasRepository.GetByAlias(alias); } } @@ -61,6 +64,20 @@ namespace Umbraco.Cms.Core.Services.Implement } } + public IEnumerable GetAll(params string[] aliases) + { + if (_macroRepository is not IMacroWithAliasRepository macroWithAliasRepository) + { + var hashset = new HashSet(aliases); + return GetAll().Where(x => hashset.Contains(x.Alias)); + } + + using (var scope = ScopeProvider.CreateScope(autoComplete: true)) + { + return macroWithAliasRepository.GetAllByAlias(aliases); + } + } + public IMacro GetById(int id) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) diff --git a/src/Umbraco.Infrastructure/Services/Implement/TrackedReferencesService.cs b/src/Umbraco.Infrastructure/Services/Implement/TrackedReferencesService.cs index 9a4cc8860e..ec22e1095c 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/TrackedReferencesService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/TrackedReferencesService.cs @@ -1,4 +1,3 @@ -using System.Linq; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; @@ -18,22 +17,32 @@ namespace Umbraco.Cms.Core.Services.Implement _entityService = entityService; } - public PagedResult GetPagedRelationsForItems(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency) + /// + /// Gets a paged result of items which are in relation with the current item. + /// Basically, shows the items which depend on the current item. + /// + public PagedResult GetPagedRelationsForItem(int id, long pageIndex, int pageSize, bool filterMustBeIsDependency) { using IScope scope = _scopeProvider.CreateScope(autoComplete: true); - var items = _trackedReferencesRepository.GetPagedRelationsForItems(ids, pageIndex, pageSize, filterMustBeIsDependency, out var totalItems); + var items = _trackedReferencesRepository.GetPagedRelationsForItem(id, pageIndex, pageSize, filterMustBeIsDependency, out var totalItems); - return new PagedResult(totalItems, pageIndex+1, pageSize) { Items = items }; + return new PagedResult(totalItems, pageIndex + 1, pageSize) { Items = items }; } + /// + /// Gets a paged result of items used in any kind of relation from selected integer ids. + /// public PagedResult GetPagedItemsWithRelations(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency) { using IScope scope = _scopeProvider.CreateScope(autoComplete: true); - var items = _trackedReferencesRepository.GetPagedItemsWithRelations(ids, pageIndex, pageSize, filterMustBeIsDependency, out var totalItems); + var items = _trackedReferencesRepository.GetPagedItemsWithRelations(ids, pageIndex, pageSize, filterMustBeIsDependency, out var totalItems); - return new PagedResult(totalItems, pageIndex+1, pageSize) { Items = items }; + return new PagedResult(totalItems, pageIndex + 1, pageSize) { Items = items }; } + /// + /// Gets a paged result of the descending items that have any references, given a parent id. + /// public PagedResult GetPagedDescendantsInReferences(int parentId, long pageIndex, int pageSize, bool filterMustBeIsDependency) { using IScope scope = _scopeProvider.CreateScope(autoComplete: true); @@ -44,7 +53,7 @@ namespace Umbraco.Cms.Core.Services.Implement pageSize, filterMustBeIsDependency, out var totalItems); - return new PagedResult(totalItems, pageIndex+1, pageSize) { Items = items }; + return new PagedResult(totalItems, pageIndex + 1, pageSize) { Items = items }; } } } diff --git a/src/Umbraco.Infrastructure/Templates/HtmlMacroParameterParser.cs b/src/Umbraco.Infrastructure/Templates/HtmlMacroParameterParser.cs new file mode 100644 index 0000000000..6323139137 --- /dev/null +++ b/src/Umbraco.Infrastructure/Templates/HtmlMacroParameterParser.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Editors; +using Umbraco.Cms.Core.PropertyEditors; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Infrastructure.Macros; + +namespace Umbraco.Cms.Infrastructure.Templates +{ + public sealed class HtmlMacroParameterParser : IHtmlMacroParameterParser + { + private readonly IMacroService _macroService; + private readonly ILogger _logger; + private readonly ParameterEditorCollection _parameterEditors; + + public HtmlMacroParameterParser(IMacroService macroService, ILogger logger, ParameterEditorCollection parameterEditors) + { + _macroService = macroService; + _logger = logger; + _parameterEditors = parameterEditors; + } + + /// + /// Parses out media UDIs from an HTML string based on embedded macro parameter values. + /// + /// HTML string + /// + public IEnumerable FindUmbracoEntityReferencesFromEmbeddedMacros(string text) + { + // There may be more than one macro with the same alias on the page so using a tuple + var foundMacros = new List>>(); + + // This legacy ParseMacros() already finds the macros within a Rich Text Editor using regexes + // It seems to lowercase the macro parameter alias - so making the dictionary case insensitive + MacroTagParser.ParseMacros(text, textblock => { }, (macroAlias, macroAttributes) => foundMacros.Add(new Tuple>(macroAlias, new Dictionary(macroAttributes, StringComparer.OrdinalIgnoreCase)))); + foreach (var umbracoEntityReference in GetUmbracoEntityReferencesFromMacros(foundMacros)) + { + yield return umbracoEntityReference; + } + } + + /// + /// Parses out media UDIs from Macro Grid Control parameters. + /// + /// + /// + public IEnumerable FindUmbracoEntityReferencesFromGridControlMacros(IEnumerable macroGridControls) + { + var foundMacros = new List>>(); + + foreach (var macroGridControl in macroGridControls) + { + // Deserialise JSON of Macro Grid Control to a class + var gridMacro = macroGridControl.Value.ToObject(); + // Collect any macro parameters that contain the media udi format + if (gridMacro is not null && gridMacro.MacroParameters is not null && gridMacro.MacroParameters.Any()) + { + foundMacros.Add(new Tuple>(gridMacro.MacroAlias, gridMacro.MacroParameters)); + } + } + + foreach (var umbracoEntityReference in GetUmbracoEntityReferencesFromMacros(foundMacros)) + { + yield return umbracoEntityReference; + } + } + + private IEnumerable GetUmbracoEntityReferencesFromMacros(List>> macros) + { + + if (_macroService is not IMacroWithAliasService macroWithAliasService) + { + yield break; + } + + var uniqueMacroAliases = macros.Select(f => f.Item1).Distinct(); + // TODO: Tracking Macro references + // Here we are finding the used macros' Udis (there should be a Related Macro relation type - but Relations don't accept 'Macro' as an option) + var foundMacroUmbracoEntityReferences = new List(); + // Get all the macro configs in one hit for these unique macro aliases - this is now cached with a custom cache policy + var macroConfigs = macroWithAliasService.GetAll(uniqueMacroAliases.ToArray()); + + foreach (var macro in macros) + { + var macroConfig = macroConfigs.FirstOrDefault(f => f.Alias == macro.Item1); + if (macroConfig is null) + { + continue; + } + foundMacroUmbracoEntityReferences.Add(new UmbracoEntityReference(Udi.Create(Constants.UdiEntityType.Macro, macroConfig.Key))); + // Only do this if the macros actually have parameters + if (macroConfig.Properties is not null && macroConfig.Properties.Keys.Any(f => f != "macroAlias")) + { + foreach (var umbracoEntityReference in GetUmbracoEntityReferencesFromMacroParameters(macro.Item2, macroConfig, _parameterEditors)) + { + yield return umbracoEntityReference; + } + } + } + } + + /// + /// Finds media UDIs in Macro Parameter Values by calling the GetReference method for all the Macro Parameter Editors for a particular macro. + /// + /// The parameters for the macro a dictionary of key/value strings + /// The macro configuration for this particular macro - contains the types of editors used for each parameter + /// A list of all the registered parameter editors used in the Umbraco implmentation - to look up the corresponding property editor for a macro parameter + /// + private IEnumerable GetUmbracoEntityReferencesFromMacroParameters(Dictionary macroParameters, IMacro macroConfig, ParameterEditorCollection parameterEditors) + { + var foundUmbracoEntityReferences = new List(); + foreach (var parameter in macroConfig.Properties) + { + if (macroParameters.TryGetValue(parameter.Alias, out string parameterValue)) + { + var parameterEditorAlias = parameter.EditorAlias; + // Lookup propertyEditor from the registered ParameterEditors with the implmementation to avoid looking up for each parameter + var parameterEditor = parameterEditors.FirstOrDefault(f => string.Equals(f.Alias, parameterEditorAlias, StringComparison.OrdinalIgnoreCase)); + if (parameterEditor is not null) + { + // Get the ParameterValueEditor for this PropertyEditor (where the GetReferences method is implemented) - cast as IDataValueReference to determine if 'it is' implemented for the editor + if (parameterEditor.GetValueEditor() is IDataValueReference parameterValueEditor) + { + foreach (var entityReference in parameterValueEditor.GetReferences(parameterValue)) + { + foundUmbracoEntityReferences.Add(entityReference); + } + } + else + { + _logger.LogInformation("{0} doesn't have a ValueEditor that implements IDataValueReference", parameterEditor.Alias); + } + } + } + } + + return foundUmbracoEntityReferences; + } + + // Poco class to deserialise the Json for a Macro Control + private class GridMacro + { + [JsonProperty("macroAlias")] + public string MacroAlias { get; set; } + + [JsonProperty("macroParamsDictionary")] + public Dictionary MacroParameters { get; set; } + } + } +} diff --git a/src/Umbraco.Infrastructure/Templates/IHtmlMacroParameterParser.cs b/src/Umbraco.Infrastructure/Templates/IHtmlMacroParameterParser.cs new file mode 100644 index 0000000000..6e484cc30a --- /dev/null +++ b/src/Umbraco.Infrastructure/Templates/IHtmlMacroParameterParser.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Editors; + +namespace Umbraco.Cms.Infrastructure.Templates +{ + /// + /// Provides methods to parse referenced entities as Macro parameters. + /// + public interface IHtmlMacroParameterParser + { + /// + /// Parses out media UDIs from an HTML string based on embedded macro parameter values. + /// + /// HTML string + /// + IEnumerable FindUmbracoEntityReferencesFromEmbeddedMacros(string text); + + /// + /// Parses out media UDIs from Macro Grid Control parameters. + /// + /// + /// + IEnumerable FindUmbracoEntityReferencesFromGridControlMacros(IEnumerable macroGridControls); + } +} diff --git a/src/Umbraco.PublishedCache.NuCache/ContentStore.cs b/src/Umbraco.PublishedCache.NuCache/ContentStore.cs index 98fc4a3ffe..ddb8ea9057 100644 --- a/src/Umbraco.PublishedCache.NuCache/ContentStore.cs +++ b/src/Umbraco.PublishedCache.NuCache/ContentStore.cs @@ -443,10 +443,18 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache refreshedIdsA.Contains(x.ContentTypeId) && BuildKit(x, out _))) { - // replacing the node: must preserve the parents + // replacing the node: must preserve the relations var node = GetHead(_contentNodes, kit.Node.Id)?.Value; if (node != null) + { + // Preserve children kit.Node.FirstChildContentId = node.FirstChildContentId; + kit.Node.LastChildContentId = node.LastChildContentId; + + // Also preserve siblings + kit.Node.NextSiblingContentId = node.NextSiblingContentId; + kit.Node.PreviousSiblingContentId = node.PreviousSiblingContentId; + } SetValueLocked(_contentNodes, kit.Node.Id, kit.Node); diff --git a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs index a10d524c03..327884689e 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs @@ -1,9 +1,11 @@ using System; using System.IO; +using System.Web; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Media; using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Web.Common.Attributes; using Umbraco.Extensions; using Constants = Umbraco.Cms.Core.Constants; @@ -53,20 +55,25 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers /// public IActionResult GetResized(string imagePath, int width) { - var ext = Path.GetExtension(imagePath); - + // We have to use HttpUtility to encode the path here, for non-ASCII characters + // We cannot use the WebUtility, as we only want to encode the path, and not the entire string + var encodedImagePath = HttpUtility.UrlPathEncode(imagePath); + + + var ext = Path.GetExtension(encodedImagePath); + // check if imagePath is local to prevent open redirect - if (!Uri.IsWellFormedUriString(imagePath, UriKind.Relative)) + if (!Uri.IsWellFormedUriString(encodedImagePath, UriKind.Relative)) { return Unauthorized(); } - + // we need to check if it is an image by extension if (_imageUrlGenerator.IsSupportedImageFormat(ext) == false) { return NotFound(); } - + // redirect to ImageProcessor thumbnail with rnd generated from last modified time of original media file DateTimeOffset? imageLastModified = null; try @@ -82,7 +89,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers } var rnd = imageLastModified.HasValue ? $"&rnd={imageLastModified:yyyyMMddHHmmss}" : null; - var imageUrl = _imageUrlGenerator.GetImageUrl(new ImageUrlGenerationOptions(imagePath) + var imageUrl = _imageUrlGenerator.GetImageUrl(new ImageUrlGenerationOptions(encodedImagePath) { Width = width, ImageCropMode = ImageCropMode.Max, diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs index d8fa641891..c4328da2d4 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs @@ -1082,7 +1082,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers return new ActionResult(toMove); } - [Obsolete("Please use TrackedReferencesController.GetPagedReferences() instead. Scheduled for removal in V11.")] + [Obsolete("Please use TrackedReferencesController.GetPagedRelationsForItem() instead. Scheduled for removal in V11.")] public PagedResult GetPagedReferences(int id, string entityType, int pageNumber = 1, int pageSize = 100) { if (pageNumber <= 0 || pageSize <= 0) diff --git a/src/Umbraco.Web.BackOffice/Controllers/TrackedReferencesController.cs b/src/Umbraco.Web.BackOffice/Controllers/TrackedReferencesController.cs index 2cef8d61af..aa1a0ee86e 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TrackedReferencesController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TrackedReferencesController.cs @@ -1,12 +1,7 @@ -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Models.ContentEditing; -using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Web.BackOffice.ModelBinders; using Umbraco.Cms.Web.Common.Attributes; @@ -19,28 +14,36 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers public class TrackedReferencesController : BackOfficeNotificationsController { private readonly ITrackedReferencesService _relationService; - private readonly IEntityService _entityService; - public TrackedReferencesController(ITrackedReferencesService relationService, - IEntityService entityService) + public TrackedReferencesController(ITrackedReferencesService relationService) { _relationService = relationService; - _entityService = entityService; } - // Used by info tabs on content, media etc. So this is basically finding childs of relations. - public ActionResult> GetPagedReferences(int id, int pageNumber = 1, - int pageSize = 100, bool filterMustBeIsDependency = false) + /// + /// Gets a page list of tracked references for the current item, so you can see where an item is being used. + /// + /// + /// Used by info tabs on content, media etc. and for the delete and unpublish of single items. + /// This is basically finding parents of relations. + /// + public ActionResult> GetPagedReferences(int id, int pageNumber = 1, int pageSize = 100, bool filterMustBeIsDependency = false) { if (pageNumber <= 0 || pageSize <= 0) { return BadRequest("Both pageNumber and pageSize must be greater than zero"); } - return _relationService.GetPagedRelationsForItems(new []{id}, pageNumber - 1, pageSize, filterMustBeIsDependency); + return _relationService.GetPagedRelationsForItem(id, pageNumber - 1, pageSize, filterMustBeIsDependency); } - // Used on delete, finds + /// + /// Gets a page list of the child nodes of the current item used in any kind of relation. + /// + /// + /// Used when deleting and unpublishing a single item to check if this item has any descending items that are in any kind of relation. + /// This is basically finding the descending items which are children in relations. + /// public ActionResult> GetPagedDescendantsInReferences(int parentId, int pageNumber = 1, int pageSize = 100, bool filterMustBeIsDependency = true) { if (pageNumber <= 0 || pageSize <= 0) @@ -48,12 +51,16 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers return BadRequest("Both pageNumber and pageSize must be greater than zero"); } - return _relationService.GetPagedDescendantsInReferences(parentId, pageNumber - 1, pageSize, filterMustBeIsDependency); - } - // Used by unpublish content. So this is basically finding parents of relations. + /// + /// Gets a page list of the items used in any kind of relation from selected integer ids. + /// + /// + /// Used when bulk deleting content/media and bulk unpublishing content (delete and unpublish on List view). + /// This is basically finding children of relations. + /// [HttpGet] [HttpPost] public ActionResult> GetPagedReferencedItems([FromJsonPath] int[] ids, int pageNumber = 1, int pageSize = 100, bool filterMustBeIsDependency = true) @@ -64,8 +71,6 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers } return _relationService.GetPagedItemsWithRelations(ids, pageNumber - 1, pageSize, filterMustBeIsDependency); - } } - } diff --git a/src/Umbraco.Web.Common/Filters/UmbracoVirtualPageFilterAttribute.cs b/src/Umbraco.Web.Common/Filters/UmbracoVirtualPageFilterAttribute.cs index b2b3ed1d39..7b73b02b70 100644 --- a/src/Umbraco.Web.Common/Filters/UmbracoVirtualPageFilterAttribute.cs +++ b/src/Umbraco.Web.Common/Filters/UmbracoVirtualPageFilterAttribute.cs @@ -2,10 +2,12 @@ using System; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Web; @@ -54,12 +56,14 @@ namespace Umbraco.Cms.Web.Common.Filters { if (content != null) { - IUmbracoContextAccessor umbracoContextAccessor = context.HttpContext.RequestServices.GetRequiredService(); + UriUtility uriUtility = context.HttpContext.RequestServices.GetRequiredService(); + + Uri originalRequestUrl = new Uri(context.HttpContext.Request.GetEncodedUrl()); + Uri cleanedUrl = uriUtility.UriToUmbraco(originalRequestUrl); + IPublishedRouter router = context.HttpContext.RequestServices.GetRequiredService(); - var umbracoContext = umbracoContextAccessor.GetRequiredUmbracoContext(); - - IPublishedRequestBuilder requestBuilder = await router.CreateRequestAsync(umbracoContext.CleanedUmbracoUrl); + IPublishedRequestBuilder requestBuilder = await router.CreateRequestAsync(cleanedUrl); requestBuilder.SetPublishedContent(content); IPublishedRequest publishedRequest = requestBuilder.Build(); diff --git a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs index 539c1c844f..5bddb85bbb 100644 --- a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs +++ b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs @@ -22,7 +22,9 @@ using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Infrastructure.PublishedCache; using Umbraco.Cms.Infrastructure.WebAssets; +using Umbraco.Cms.Web.Common.DependencyInjection; using Umbraco.Cms.Web.Common.Profiler; +using Umbraco.Cms.Web.Common.Routing; using Umbraco.Extensions; namespace Umbraco.Cms.Web.Common.Middleware @@ -53,6 +55,7 @@ namespace Umbraco.Cms.Web.Common.Middleware private readonly IRuntimeState _runtimeState; private readonly IVariationContextAccessor _variationContextAccessor; private readonly IDefaultCultureAccessor _defaultCultureAccessor; + private readonly IOptions _umbracoRequestOptions; private readonly SmidgeOptions _smidgeOptions; private readonly WebProfiler _profiler; @@ -66,6 +69,43 @@ namespace Umbraco.Cms.Web.Common.Middleware private static object s_firstBackOfficeRequestLocker = new object(); #pragma warning restore IDE0044 // Add readonly modifier + /// + /// Initializes a new instance of the class. + /// + // Obsolete, scheduled for removal in V11 + [Obsolete("Use constructor that takes an IOptions")] + public UmbracoRequestMiddleware( + ILogger logger, + IUmbracoContextFactory umbracoContextFactory, + IRequestCache requestCache, + PublishedSnapshotServiceEventHandler publishedSnapshotServiceEventHandler, + IEventAggregator eventAggregator, + IProfiler profiler, + IHostingEnvironment hostingEnvironment, + UmbracoRequestPaths umbracoRequestPaths, + BackOfficeWebAssets backOfficeWebAssets, + IOptions smidgeOptions, + IRuntimeState runtimeState, + IVariationContextAccessor variationContextAccessor, + IDefaultCultureAccessor defaultCultureAccessor) + : this( + logger, + umbracoContextFactory, + requestCache, + publishedSnapshotServiceEventHandler, + eventAggregator, + profiler, + hostingEnvironment, + umbracoRequestPaths, + backOfficeWebAssets, + smidgeOptions, + runtimeState, + variationContextAccessor, + defaultCultureAccessor, + StaticServiceProvider.Instance.GetRequiredService>()) + { + } + /// /// Initializes a new instance of the class. /// @@ -82,7 +122,8 @@ namespace Umbraco.Cms.Web.Common.Middleware IOptions smidgeOptions, IRuntimeState runtimeState, IVariationContextAccessor variationContextAccessor, - IDefaultCultureAccessor defaultCultureAccessor) + IDefaultCultureAccessor defaultCultureAccessor, + IOptions umbracoRequestOptions) { _logger = logger; _umbracoContextFactory = umbracoContextFactory; @@ -95,6 +136,7 @@ namespace Umbraco.Cms.Web.Common.Middleware _runtimeState = runtimeState; _variationContextAccessor = variationContextAccessor; _defaultCultureAccessor = defaultCultureAccessor; + _umbracoRequestOptions = umbracoRequestOptions; _smidgeOptions = smidgeOptions.Value; _profiler = profiler as WebProfiler; // Ignore if not a WebProfiler } @@ -103,7 +145,7 @@ namespace Umbraco.Cms.Web.Common.Middleware public async Task InvokeAsync(HttpContext context, RequestDelegate next) { // do not process if client-side request - if (context.Request.IsClientSideRequest()) + if (context.Request.IsClientSideRequest() && !_umbracoRequestOptions.Value.HandleAsServerSideRequest(context.Request)) { // we need this here because for bundle requests, these are 'client side' requests that we need to handle LazyInitializeBackOfficeServices(context.Request.Path); diff --git a/src/Umbraco.Web.Common/Routing/UmbracoRequestOptions.cs b/src/Umbraco.Web.Common/Routing/UmbracoRequestOptions.cs new file mode 100644 index 0000000000..2b27970cd6 --- /dev/null +++ b/src/Umbraco.Web.Common/Routing/UmbracoRequestOptions.cs @@ -0,0 +1,14 @@ +using System; +using Microsoft.AspNetCore.Http; + +namespace Umbraco.Cms.Web.Common.Routing +{ + public class UmbracoRequestOptions + { + /// + /// Gets the delegate that checks if we're gonna handle a request as a client-side request + /// this returns true by default and can be overwritten in Startup.cs + /// + public Func HandleAsServerSideRequest { get; set; } = x => false; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 83292251da..501ea9f81a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -12,6 +12,7 @@ scope.publishStatus = []; scope.currentVariant = null; scope.currentUrls = []; + scope.loadingReferences = false; scope.disableTemplates = Umbraco.Sys.ServerVariables.features.disabledFeatures.disableTemplates; scope.allowChangeDocumentType = false; @@ -229,6 +230,10 @@ }); } + + function loadReferences(){ + scope.loadingReferences = true; + } function loadRedirectUrls() { scope.loadingRedirectUrls = true; //check if Redirect URL Management is enabled @@ -335,6 +340,7 @@ loadRedirectUrls(); setNodePublishStatus(); formatDatesToLocal(); + loadReferences(); } else { isInfoTab = false; } @@ -352,6 +358,7 @@ loadRedirectUrls(); setNodePublishStatus(); formatDatesToLocal(); + loadReferences(); } updateCurrentUrls(); }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/references/umbtrackedreferences.component.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/references/umbtrackedreferences.component.js index 000e87146c..15c1b4aedf 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/references/umbtrackedreferences.component.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/references/umbtrackedreferences.component.js @@ -16,17 +16,16 @@ function onInit() { - vm.referencesTitle = this.hideNoneDependencies ? "The following items depends on this" : "Referenced by the following items"; - vm.referencedDescendantsTitle = this.hideNoneDependencies ? "The following descending items has dependencies" : "The following descending items are referenced"; - + vm.referencesTitle = this.hideNoneDependencies ? "The following items depend on this" : "Referenced by the following items"; + vm.referencedDescendantsTitle = this.hideNoneDependencies ? "The following descending items have dependencies" : "The following descendant items have dependencies"; localizationService.localize(this.hideNoneDependencies ? "references_labelDependsOnThis" : "references_labelUsedByItems").then(function (value) { vm.referencesTitle = value; }); - + localizationService.localize(this.hideNoneDependencies ? "references_labelDependentDescendants" : "references_labelUsedDescendants").then(function (value) { vm.referencedDescendantsTitle = value; }); - + vm.descendantsOptions = {}; vm.descendantsOptions.filterMustBeIsDependency = this.hideNoneDependencies; vm.hasReferencesInDescendants = false; diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index b6f45ead0e..7e6c6658e5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -1259,7 +1259,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { getPublicAccess: function (contentId) { return umbRequestHelper.resourcePromise( $http.get( - umbRequestHelper.getApiUrl("contentApiBaseUrl", "GetPublicAccess", { + umbRequestHelper.getApiUrl("publicAccessApiBaseUrl", "GetPublicAccess", { contentId: contentId }) ), @@ -1308,7 +1308,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { } return umbRequestHelper.resourcePromise( $http.post( - umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostPublicAccess", publicAccess) + umbRequestHelper.getApiUrl("publicAccessApiBaseUrl", "PostPublicAccess", publicAccess) ), "Failed to update public access for content item with id " + contentId ); diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/trackedreferences.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/trackedreferences.resource.js index cd64c89589..d64951a6d0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/trackedreferences.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/trackedreferences.resource.js @@ -162,7 +162,7 @@ function trackedReferencesResource($q, $http, umbRequestHelper) { $http.post( umbRequestHelper.getApiUrl( "trackedReferencesApiBaseUrl", - "getPagedReferencedItems", + "GetPagedReferencedItems", query), { ids: ids, diff --git a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html index 6f32e89988..c14110437d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html @@ -128,13 +128,13 @@
- +
- Visit umbraco.tv + Watch our free tutorial videos
- The best Umbraco video tutorials + on the Umbraco Learning Base
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html index 6429e39db6..1c7545f9ec 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html @@ -21,7 +21,7 @@ - + diff --git a/src/Umbraco.Web.UI.Client/src/views/components/references/umb-tracked-references-table.html b/src/Umbraco.Web.UI.Client/src/views/components/references/umb-tracked-references-table.html index afc8f9a3e6..d09bc23318 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/references/umb-tracked-references-table.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/references/umb-tracked-references-table.html @@ -7,8 +7,8 @@
-
Node Name
-
Type Name
+
Node Name
+
Type Name
Type
Relation
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/references/umb-tracked-references.html b/src/Umbraco.Web.UI.Client/src/views/components/references/umb-tracked-references.html index fd788cc598..9e08c5fbae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/references/umb-tracked-references.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/references/umb-tracked-references.html @@ -26,11 +26,11 @@
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.protect.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.protect.controller.js index 92efb24e63..6561ed3499 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.protect.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.protect.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function ContentProtectController($scope, $q, contentResource, memberResource, memberGroupResource, navigationService, localizationService, editorService) { + function ContentProtectController($scope, $q, publicAccessResource, memberResource, memberGroupResource, navigationService, localizationService, editorService) { var vm = this; var id = $scope.currentNode.id; @@ -30,7 +30,7 @@ vm.loading = true; // get the current public access protection - contentResource.getPublicAccess(id).then(function (publicAccess) { + publicAccessResource.getPublicAccess(id).then(function (publicAccess) { vm.loading = false; // init the current settings for public access (if any) @@ -94,7 +94,7 @@ vm.buttonState = "busy"; var groups = _.map(vm.groups, function (group) { return encodeURIComponent(group.name); }); var usernames = _.map(vm.members, function (member) { return member.username; }); - contentResource.updatePublicAccess(id, groups, usernames, vm.loginPage.id, vm.errorPage.id).then( + publicAccessResource.updatePublicAccess(id, groups, usernames, vm.loginPage.id, vm.errorPage.id).then( function () { localizationService.localize("publicAccess_paIsProtected", [$scope.currentNode.name]).then(function (value) { vm.success = { @@ -181,11 +181,11 @@ vm.members.push(newMember); } }) - ); + ); }); editorService.close(); navigationService.allowHideDialog(true); - // wait for all the member lookups to complete + // wait for all the member lookups to complete vm.loading = true; $q.all(promises).then(function() { vm.loading = false; @@ -239,7 +239,7 @@ function removeProtectionConfirm() { vm.buttonState = "busy"; - contentResource.removePublicAccess(id).then( + publicAccessResource.removePublicAccess(id).then( function () { localizationService.localize("publicAccess_paIsRemoved", [$scope.currentNode.name]).then(function(value) { vm.success = { diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/settingsdashboardintro.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/settingsdashboardintro.html index 436155de72..b33444177a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/settingsdashboardintro.html +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/settings/settingsdashboardintro.html @@ -17,7 +17,7 @@ Ask a question in the Community Forum
  • - Watch our free tutorial videos on the Umbraco Learning Base + Watch our free tutorial videos on the Umbraco Learning Base
  • Find out about our productivity boosting tools and commercial support diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js index 9331e4227b..0fdc251949 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js @@ -174,13 +174,13 @@ filterCssClass: "not-allowed", select: node => { const filepath = decodeURIComponent(node.id.replace(/\+/g, " ")); - block.view = "~/" + filepath; + block.view = "~/" + filepath.replace("wwwroot/", ""); editorService.close(); }, close: () => editorService.close() }; - editorService.filePicker(filePicker); + editorService.staticFilePicker(filePicker); }); }; diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index 7140d0850a..23277ee296 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -790,6 +790,7 @@ New Next No + Node Name of Off OK @@ -831,6 +832,7 @@ Submit Success Type + Type Name Type to search... under Up @@ -1471,6 +1473,8 @@ To manage your website, simply open the Umbraco backoffice and start adding cont The best Umbraco video tutorials Visit our.umbraco.com Visit umbraco.tv + Watch our free tutorial videos + on the Umbraco Learning Base Default template @@ -2390,6 +2394,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Parent Child Count + Relation Relations Created Comment @@ -2470,18 +2475,13 @@ To manage your website, simply open the Umbraco backoffice and start adding cont References This Data Type has no references. + This item has no references. Used in Document Types Used in Media Types Used in Member Types Used by - Used in Documents - Used in Members - Used in Media Items in use Descendants in use - One or more of this item's descendants is being used in a media item. - One or more of this item's descendants is being used in a content item. - One or more of this item's descendants is being used in a member. This item or its descendants is being used. Deletion can lead to broken links on your website. This item or its descendants is being used. Unpublishing can lead to broken links on your website. Please take the appropriate actions. This item or its descendants is being used. Therefore, deletion has been disabled. @@ -2641,7 +2641,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont tutorial videos on the Umbraco Learning Base + Watch our free tutorial videos on the Umbraco Learning Base ]]> diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index 8111463e68..5e2935b395 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -811,7 +811,7 @@ New Next No - Node Name + Node Name of Off OK @@ -852,7 +852,7 @@ Submit Success Type - Type Name + Type Name Type to search... under Up @@ -1496,6 +1496,8 @@ To manage your website, simply open the Umbraco backoffice and start adding cont The best Umbraco video tutorials Visit our.umbraco.com Visit umbraco.tv + Watch our free tutorial videos + on the Umbraco Learning Base Default template @@ -2561,16 +2563,10 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Referenced by the following Member Types Referenced by Referenced by the following items - The following items depends on this - Referenced by the following Documents - Referenced by the following Members - Referenced by the following Media + The following items depend on this The following items are referenced - The following descending items are referenced - The following descending items has dependencies - One or more of this item's descendants is being referenced in a media item. - One or more of this item's descendants is being referenced in a content item. - One or more of this item's descendants is being referenced in a member. + The following descendant items have dependencies + The following descending items have dependencies This item or its descendants is being referenced. Deletion can lead to broken links on your website. This item or its descendants is being referenced. Unpublishing can lead to broken links on your website. Please take the appropriate actions. This item or its descendants is being referenced. Therefore, deletion has been disabled. @@ -2730,7 +2726,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont tutorial videos on the Umbraco Learning Base + Watch our free tutorial videos on the Umbraco Learning Base ]]> diff --git a/build/templates/Umbraco.Templates.nuspec b/templates/Umbraco.Templates.nuspec similarity index 64% rename from build/templates/Umbraco.Templates.nuspec rename to templates/Umbraco.Templates.nuspec index 21201d8d55..6561a41060 100644 --- a/build/templates/Umbraco.Templates.nuspec +++ b/templates/Umbraco.Templates.nuspec @@ -14,8 +14,15 @@ umbraco - + + + + + + + + + - diff --git a/build/templates/UmbracoPackage/.template.config/dotnetcli.host.json b/templates/UmbracoPackage/.template.config/dotnetcli.host.json similarity index 100% rename from build/templates/UmbracoPackage/.template.config/dotnetcli.host.json rename to templates/UmbracoPackage/.template.config/dotnetcli.host.json diff --git a/build/templates/UmbracoPackage/.template.config/ide.host.json b/templates/UmbracoPackage/.template.config/ide.host.json similarity index 89% rename from build/templates/UmbracoPackage/.template.config/ide.host.json rename to templates/UmbracoPackage/.template.config/ide.host.json index 8d3bae3e3c..aa4eb34552 100644 --- a/build/templates/UmbracoPackage/.template.config/ide.host.json +++ b/templates/UmbracoPackage/.template.config/ide.host.json @@ -1,7 +1,7 @@ { "$schema": "http://json.schemastore.org/vs-2017.3.host", "order" : 0, - "icon": "icon.png", + "icon": "../../icon.png", "description": { "id": "UmbracoPackage", "text": "Umbraco Package - An empty Umbraco CMS package (Plugin)" diff --git a/build/templates/UmbracoPackage/.template.config/template.json b/templates/UmbracoPackage/.template.config/template.json similarity index 98% rename from build/templates/UmbracoPackage/.template.config/template.json rename to templates/UmbracoPackage/.template.config/template.json index 082f9301bf..74de126429 100644 --- a/build/templates/UmbracoPackage/.template.config/template.json +++ b/templates/UmbracoPackage/.template.config/template.json @@ -24,7 +24,7 @@ "version": { "type": "parameter", "datatype": "string", - "defaultValue": "9.4.0-rc", + "defaultValue": "9.5.0-rc", "description": "The version of Umbraco to load using NuGet", "replaces": "UMBRACO_VERSION_FROM_TEMPLATE" }, diff --git a/build/templates/UmbracoPackage/App_Plugins/UmbracoPackage/package.manifest b/templates/UmbracoPackage/App_Plugins/UmbracoPackage/package.manifest similarity index 100% rename from build/templates/UmbracoPackage/App_Plugins/UmbracoPackage/package.manifest rename to templates/UmbracoPackage/App_Plugins/UmbracoPackage/package.manifest diff --git a/build/templates/UmbracoPackage/UmbracoPackage.csproj b/templates/UmbracoPackage/UmbracoPackage.csproj similarity index 100% rename from build/templates/UmbracoPackage/UmbracoPackage.csproj rename to templates/UmbracoPackage/UmbracoPackage.csproj diff --git a/build/templates/UmbracoPackage/build/UmbracoPackage.targets b/templates/UmbracoPackage/build/UmbracoPackage.targets similarity index 100% rename from build/templates/UmbracoPackage/build/UmbracoPackage.targets rename to templates/UmbracoPackage/build/UmbracoPackage.targets diff --git a/build/templates/UmbracoProject/.gitignore b/templates/UmbracoProject/.gitignore similarity index 100% rename from build/templates/UmbracoProject/.gitignore rename to templates/UmbracoProject/.gitignore diff --git a/build/templates/UmbracoProject/.template.config/dotnetcli.host.json b/templates/UmbracoProject/.template.config/dotnetcli.host.json similarity index 100% rename from build/templates/UmbracoProject/.template.config/dotnetcli.host.json rename to templates/UmbracoProject/.template.config/dotnetcli.host.json diff --git a/build/templates/UmbracoProject/.template.config/ide.host.json b/templates/UmbracoProject/.template.config/ide.host.json similarity index 98% rename from build/templates/UmbracoProject/.template.config/ide.host.json rename to templates/UmbracoProject/.template.config/ide.host.json index 1ee7a492aa..d44cb154c1 100644 --- a/build/templates/UmbracoProject/.template.config/ide.host.json +++ b/templates/UmbracoProject/.template.config/ide.host.json @@ -1,7 +1,7 @@ { "$schema": "http://json.schemastore.org/vs-2017.3.host", "order" : 0, - "icon": "icon.png", + "icon": "../../icon.png", "description": { "id": "UmbracoProject", "text": "Umbraco Web Application - An empty Umbraco CMS web application" diff --git a/build/templates/UmbracoProject/.template.config/template.json b/templates/UmbracoProject/.template.config/template.json similarity index 99% rename from build/templates/UmbracoProject/.template.config/template.json rename to templates/UmbracoProject/.template.config/template.json index 810940c4eb..cd8347e206 100644 --- a/build/templates/UmbracoProject/.template.config/template.json +++ b/templates/UmbracoProject/.template.config/template.json @@ -57,7 +57,7 @@ "version": { "type": "parameter", "datatype": "string", - "defaultValue": "9.4.0-rc", + "defaultValue": "9.5.0-rc", "description": "The version of Umbraco to load using NuGet", "replaces": "UMBRACO_VERSION_FROM_TEMPLATE" }, diff --git a/build/templates/UmbracoProject/Properties/launchSettings.json b/templates/UmbracoProject/Properties/launchSettings.json similarity index 100% rename from build/templates/UmbracoProject/Properties/launchSettings.json rename to templates/UmbracoProject/Properties/launchSettings.json diff --git a/build/templates/UmbracoProject/UmbracoProject.csproj b/templates/UmbracoProject/UmbracoProject.csproj similarity index 100% rename from build/templates/UmbracoProject/UmbracoProject.csproj rename to templates/UmbracoProject/UmbracoProject.csproj diff --git a/build/templates/UmbracoProject/appsettings.Development.json b/templates/UmbracoProject/appsettings.Development.json similarity index 100% rename from build/templates/UmbracoProject/appsettings.Development.json rename to templates/UmbracoProject/appsettings.Development.json diff --git a/build/templates/UmbracoProject/appsettings.json b/templates/UmbracoProject/appsettings.json similarity index 100% rename from build/templates/UmbracoProject/appsettings.json rename to templates/UmbracoProject/appsettings.json diff --git a/build/templates/UmbracoPackage/.template.config/icon.png b/templates/icon.png similarity index 100% rename from build/templates/UmbracoPackage/.template.config/icon.png rename to templates/icon.png diff --git a/tests/Umbraco.Tests.Integration.SqlCe/Umbraco.Infrastructure/Persistence/DatabaseBuilderTests.cs b/tests/Umbraco.Tests.Integration.SqlCe/Umbraco.Infrastructure/Persistence/DatabaseBuilderTests.cs index 500d71dddc..20021dbd2c 100644 --- a/tests/Umbraco.Tests.Integration.SqlCe/Umbraco.Infrastructure/Persistence/DatabaseBuilderTests.cs +++ b/tests/Umbraco.Tests.Integration.SqlCe/Umbraco.Infrastructure/Persistence/DatabaseBuilderTests.cs @@ -2,11 +2,13 @@ using System; using System.IO; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Moq; using NPoco; using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Infrastructure.Migrations.Install; using Umbraco.Cms.Infrastructure.Persistence; @@ -67,7 +69,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence using (var database = UmbracoDatabaseFactory.CreateDatabase()) using (var transaction = database.GetTransaction()) { - schemaHelper = new DatabaseSchemaCreator(database, Mock.Of>(), NullLoggerFactory.Instance, new UmbracoVersion(), Mock.Of()); + schemaHelper = new DatabaseSchemaCreator(database, Mock.Of>(), NullLoggerFactory.Instance, new UmbracoVersion(), Mock.Of(), Mock.Of>(x => x.CurrentValue == new InstallDefaultDataSettings())); schemaHelper.InitializeDatabaseSchema(); transaction.Complete(); } diff --git a/tests/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs b/tests/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs index 564c45d5ad..f345c44b42 100644 --- a/tests/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs +++ b/tests/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs @@ -10,9 +10,11 @@ using System.Diagnostics; using System.Linq; using System.Threading; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Moq; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Infrastructure.Migrations.Install; using Umbraco.Cms.Infrastructure.Persistence; @@ -137,7 +139,7 @@ namespace Umbraco.Cms.Tests.Integration.Testing using (NPoco.ITransaction transaction = database.GetTransaction()) { - var schemaCreator = new DatabaseSchemaCreator(database, _loggerFactory.CreateLogger(), _loggerFactory, new UmbracoVersion(), Mock.Of()); + var schemaCreator = new DatabaseSchemaCreator(database, _loggerFactory.CreateLogger(), _loggerFactory, new UmbracoVersion(), Mock.Of(), Mock.Of>(x => x.CurrentValue == new InstallDefaultDataSettings())); schemaCreator.InitializeDatabaseSchema(); transaction.Complete(); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Migrations/AdvancedMigrationTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Migrations/AdvancedMigrationTests.cs index 40dbad176e..2366ddcaee 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Migrations/AdvancedMigrationTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Migrations/AdvancedMigrationTests.cs @@ -6,9 +6,11 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Moq; using NUnit.Framework; using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Migrations; using Umbraco.Cms.Core.Scoping; @@ -56,7 +58,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Migrations upgrader.Execute(MigrationPlanExecutor, ScopeProvider, Mock.Of()); - var helper = new DatabaseSchemaCreator(scope.Database, LoggerFactory.CreateLogger(), LoggerFactory, UmbracoVersion, EventAggregator); + var helper = new DatabaseSchemaCreator(scope.Database, LoggerFactory.CreateLogger(), LoggerFactory, UmbracoVersion, EventAggregator, Mock.Of>()); bool exists = helper.TableExists("umbracoUser"); Assert.IsTrue(exists); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SchemaValidationTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SchemaValidationTest.cs index 13f543c130..59dedd397f 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SchemaValidationTest.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SchemaValidationTest.cs @@ -1,6 +1,9 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Moq; using NUnit.Framework; using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Infrastructure.Migrations.Install; using Umbraco.Cms.Tests.Common.Testing; @@ -22,7 +25,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence using (var scope = ScopeProvider.CreateScope()) { - var schema = new DatabaseSchemaCreator(scope.Database, LoggerFactory.CreateLogger(), LoggerFactory, UmbracoVersion, EventAggregator); + var schema = new DatabaseSchemaCreator(scope.Database, LoggerFactory.CreateLogger(), LoggerFactory, UmbracoVersion, EventAggregator, Mock.Of>(x => x.CurrentValue == new InstallDefaultDataSettings())); result = schema.ValidateSchema(DatabaseSchemaCreator.OrderedTables); } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SqlServerTableByTableTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SqlServerTableByTableTest.cs index 4b3d159ff5..8fa1d7ef38 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SqlServerTableByTableTest.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SqlServerTableByTableTest.cs @@ -1,8 +1,12 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Moq; using NUnit.Framework; using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Events; +using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Infrastructure.Migrations.Install; using Umbraco.Cms.Infrastructure.Persistence.Dtos; using Umbraco.Cms.Tests.Common.Testing; @@ -23,7 +27,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); @@ -36,7 +40,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -50,7 +54,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -65,7 +69,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -79,7 +83,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -94,7 +98,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -108,7 +112,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -124,7 +128,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -138,7 +142,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); @@ -151,7 +155,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -166,7 +170,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -180,7 +184,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -197,7 +201,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -213,7 +217,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -227,7 +231,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); @@ -240,7 +244,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); @@ -253,7 +257,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); @@ -266,7 +270,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); @@ -279,7 +283,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -295,7 +299,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -312,7 +316,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -327,7 +331,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -345,7 +349,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -362,7 +366,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -377,7 +381,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -392,7 +396,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); @@ -405,7 +409,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); @@ -418,7 +422,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -439,7 +443,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); @@ -452,7 +456,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -466,7 +470,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -480,7 +484,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -495,7 +499,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence { using (var scope = ScopeProvider.CreateScope()) { - var helper = new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator); + var helper = CreateDatabaseSchemaCreator(scope); helper.CreateTable(); helper.CreateTable(); @@ -504,5 +508,8 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence scope.Complete(); } } + + private DatabaseSchemaCreator CreateDatabaseSchemaCreator(IScope scope) => + new DatabaseSchemaCreator(scope.Database, _loggerFactory.CreateLogger(), _loggerFactory, UmbracoVersion, EventAggregator, Mock.Of>(x => x.CurrentValue == new InstallDefaultDataSettings())); } } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MacroServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MacroServiceTests.cs index 75dae7515b..621762917d 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MacroServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MacroServiceTests.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; @@ -24,7 +23,8 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class MacroServiceTests : UmbracoIntegrationTest { - private IMacroService MacroService => GetRequiredService(); + [Obsolete("After merging IMacroWithAliasService interface with IMacroService in Umbraco 11, this should go back to just being GetRequiredService()")] + private IMacroWithAliasService MacroService => GetRequiredService() as IMacroWithAliasService; [SetUp] public void SetupTest() @@ -52,6 +52,19 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services Assert.AreEqual("Test1", macro.Name); } + [Test] + public void Can_Get_By_Aliases() + { + // Act + IEnumerable macros = MacroService.GetAll("test1", "test2"); + + // Assert + Assert.IsNotNull(macros); + Assert.AreEqual(2, macros.Count()); + Assert.AreEqual("Test1", macros.ToArray()[0].Name); + Assert.AreEqual("Test2", macros.ToArray()[1].Name); + } + [Test] public void Can_Get_All() { diff --git a/tests/Umbraco.Tests.UnitTests/AutoFixture/Customizations/UmbracoCustomizations.cs b/tests/Umbraco.Tests.UnitTests/AutoFixture/Customizations/UmbracoCustomizations.cs index 672bbd0862..9a4ac2f206 100644 --- a/tests/Umbraco.Tests.UnitTests/AutoFixture/Customizations/UmbracoCustomizations.cs +++ b/tests/Umbraco.Tests.UnitTests/AutoFixture/Customizations/UmbracoCustomizations.cs @@ -12,6 +12,7 @@ using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Infrastructure.Migrations.Install; using Umbraco.Cms.Web.BackOffice.Controllers; using Umbraco.Cms.Web.BackOffice.Install; using Umbraco.Cms.Web.BackOffice.Routing; @@ -34,7 +35,8 @@ namespace Umbraco.Cms.Tests.UnitTests.AutoFixture.Customizations .Customize(new ConstructorCustomization(typeof(MemberController), new GreedyConstructorQuery())) .Customize(new ConstructorCustomization(typeof(BackOfficeController), new GreedyConstructorQuery())) .Customize(new ConstructorCustomization(typeof(BackOfficeUserManager), new GreedyConstructorQuery())) - .Customize(new ConstructorCustomization(typeof(MemberManager), new GreedyConstructorQuery())); + .Customize(new ConstructorCustomization(typeof(MemberManager), new GreedyConstructorQuery())) + .Customize(new ConstructorCustomization(typeof(DatabaseSchemaCreatorFactory), new GreedyConstructorQuery())); // When requesting an IUserStore ensure we actually uses a IUserLockoutStore fixture.Customize>(cc => cc.FromFactory(Mock.Of>)); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs index 4173417582..aaac553bbf 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs @@ -55,7 +55,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components Mock.Of>(x => x.CurrentValue == connectionStrings), new MapperCollection(() => Enumerable.Empty()), TestHelper.DbProviderFactoryCreator, - new DatabaseSchemaCreatorFactory(loggerFactory.CreateLogger(), loggerFactory, new UmbracoVersion(), Mock.Of()), + new DatabaseSchemaCreatorFactory(loggerFactory.CreateLogger(), loggerFactory, new UmbracoVersion(), Mock.Of(), Mock.Of>()), mapperCollection); var fs = new FileSystems(loggerFactory, IOHelper, Options.Create(globalSettings), Mock.Of()); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Security/LegacyPasswordSecurityTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Security/LegacyPasswordSecurityTests.cs index 273823eec3..12c5f50d30 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Security/LegacyPasswordSecurityTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Security/LegacyPasswordSecurityTests.cs @@ -1,10 +1,14 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using System; +using System.Security.Cryptography; +using System.Text; using Moq; using NUnit.Framework; using Umbraco.Cms.Core.Configuration; using Umbraco.Cms.Core.Security; +using Umbraco.Extensions; using Constants = Umbraco.Cms.Core.Constants; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Security @@ -15,7 +19,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Security [Test] public void Check_Password_Hashed_Non_KeyedHashAlgorithm() { - IPasswordConfiguration passwordConfiguration = Mock.Of(x => x.HashAlgorithmType == "SHA256"); + IPasswordConfiguration passwordConfiguration = Mock.Of(x => x.HashAlgorithmType == "SHA1"); var passwordSecurity = new LegacyPasswordSecurity(); var pass = "ThisIsAHashedPassword"; @@ -45,14 +49,12 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Security [Test] public void Check_Password_Legacy_v4_SHA1() { - IPasswordConfiguration passwordConfiguration = Mock.Of(x => x.HashAlgorithmType == Constants.Security.AspNetUmbraco4PasswordHashAlgorithmName); - var passwordSecurity = new LegacyPasswordSecurity(); + const string clearText = "ThisIsAHashedPassword"; + var clearTextUnicodeBytes = Encoding.Unicode.GetBytes(clearText); + using var algorithm = new HMACSHA1(clearTextUnicodeBytes); + var dbPassword = Convert.ToBase64String(algorithm.ComputeHash(clearTextUnicodeBytes)); - var pass = "ThisIsAHashedPassword"; - var hashed = passwordSecurity.HashNewPassword(passwordConfiguration.HashAlgorithmType, pass, out string salt); - var storedPassword = passwordSecurity.FormatPasswordForStorage(passwordConfiguration.HashAlgorithmType, hashed, salt); - - var result = passwordSecurity.VerifyPassword(passwordConfiguration.HashAlgorithmType, "ThisIsAHashedPassword", storedPassword); + var result = new LegacyPasswordSecurity().VerifyLegacyHashedPassword(clearText, dbPassword); Assert.IsTrue(result); } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/UmbracoPasswordHasherTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/UmbracoPasswordHasherTests.cs new file mode 100644 index 0000000000..db4ec3392f --- /dev/null +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Security/UmbracoPasswordHasherTests.cs @@ -0,0 +1,127 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using AutoFixture.NUnit3; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; +using Moq; +using NUnit.Framework; +using Umbraco.Cms.Core.Models.Membership; +using Umbraco.Cms.Core.Security; +using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Tests.UnitTests.AutoFixture; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security +{ + [TestFixture] + public class UmbracoPasswordHasherTests + { + // Technically MD5, HMACSHA384 & HMACSHA512 were also possible but opt in as opposed to historic defaults. + [Test] + [InlineAutoMoqData("HMACSHA256", "Umbraco9Rocks!", "uB/pLEhhe1W7EtWMv/pSgg==1y8+aso9+h3AKRtJXlVYeg2TZKJUr64hccj82ZZ7Ksk=")] // Actually HMACSHA256 + [InlineAutoMoqData("SHA1", "Umbraco9Rocks!", "6tZGfG9NTxJJYp19Fac9og==zzRggqANxhb+CbD/VabEt8cIde8=")] // When SHA1 is set on machine key. + public void VerifyHashedPassword_ValidHashWithoutLegacyEncoding_ReturnsSuccessRehashNeeded( + string algorithm, + string providedPassword, + string hashedPassword, + [Frozen] IJsonSerializer jsonSerializer, + TestUserStub aUser, + UmbracoPasswordHasher sut) + { + Mock.Get(jsonSerializer) + .Setup(x => x.Deserialize(It.IsAny())) + .Returns(new PersistedPasswordSettings{ HashAlgorithm = algorithm }); + + var result = sut.VerifyHashedPassword(aUser, hashedPassword, providedPassword); + + Assert.AreEqual(PasswordVerificationResult.SuccessRehashNeeded, result); + } + + [Test] + [InlineAutoMoqData("HMACSHA1", "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")] + [InlineAutoMoqData("HMACSHA256", "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")] + [InlineAutoMoqData("FOOBARBAZQUX", "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")] + [InlineAutoMoqData("", "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")] + [InlineAutoMoqData(null, "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")] + public void VerifyHashedPassword_ValidHashWithLegacyEncoding_ReturnsSuccessRehashNeeded( + string algorithm, + string providedPassword, + string hashedPassword, + [Frozen] IJsonSerializer jsonSerializer, + TestUserStub aUser, + UmbracoPasswordHasher sut) + { + Mock.Get(jsonSerializer) + .Setup(x => x.Deserialize(It.IsAny())) + .Returns(new PersistedPasswordSettings { HashAlgorithm = algorithm }); + + var result = sut.VerifyHashedPassword(aUser, hashedPassword, providedPassword); + + Assert.AreEqual(PasswordVerificationResult.SuccessRehashNeeded, result); + } + + [Test] + [InlineAutoMoqData("HMACSHA256", "Umbraco9Rocks!", "aB/cDeFaBcDefAbcD/EfaB==1y8+aso9+h3AKRtJXlVYeg2TZKJUr64hccj82ZZ7Ksk=")] + public void VerifyHashedPassword_WithIncorrectPassword_ReturnsFailed( + string algorithm, + string providedPassword, + string hashedPassword, + [Frozen] IJsonSerializer jsonSerializer, + TestUserStub aUser, + UmbracoPasswordHasher sut) + { + Mock.Get(jsonSerializer) + .Setup(x => x.Deserialize(It.IsAny())) + .Returns(new PersistedPasswordSettings { HashAlgorithm = algorithm }); + + var result = sut.VerifyHashedPassword(aUser, hashedPassword, providedPassword); + + Assert.AreEqual(PasswordVerificationResult.Failed, result); + } + + [Test] + [AutoMoqData] + public void VerifyHashedPassword_WithIdentityV1OrV2StyleHash_ReturnsSuccessRehashNeeded( + TestUserStub aUser, + UmbracoPasswordHasher sut) + { + var options = Options.Create(new PasswordHasherOptions + { + CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2 + }); + + var upstreamHasher = new PasswordHasher(options); + + const string password = "Umbraco9Rocks!"; + var identityV1Or2StyleHash = upstreamHasher.HashPassword(aUser, password); + var result = sut.VerifyHashedPassword(aUser, identityV1Or2StyleHash, password); + + Assert.AreEqual(PasswordVerificationResult.SuccessRehashNeeded, result); + } + + [Test] + [AutoMoqData] + public void VerifyHashedPassword_WithIdentityV3StyleHash_ReturnsSuccess( + TestUserStub aUser, + UmbracoPasswordHasher sut) + { + var options = Options.Create(new PasswordHasherOptions + { + CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV3 + }); + + var upstreamHasher = new PasswordHasher(options); + + const string password = "Umbraco9Rocks!"; + var identityV1Or2StyleHash = upstreamHasher.HashPassword(aUser, password); + var result = sut.VerifyHashedPassword(aUser, identityV1Or2StyleHash, password); + + Assert.AreEqual(PasswordVerificationResult.Success, result); + } + + public class TestUserStub : UmbracoIdentityUser + { + public TestUserStub() => PasswordConfig = "not null or empty"; + } + } +} diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs index c25b2fde1e..fdb29f88e6 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.PublishedCache.NuCache/SnapDictionaryTests.cs @@ -323,6 +323,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.PublishedCache.NuCache } [Test] + [Retry(5)] // TODO make this test non-flaky. public async Task EventuallyCollectNulls() { var d = new SnapDictionary();