From 3fea1b441cb04b4dda772f168987c634b1f40113 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 28 Feb 2024 11:27:54 +0000 Subject: [PATCH] Removes more old backoffice files + Smidge! (#15788) * Removes lots of files used by the old backoffice and that is not needed for the management api * A little clean-up --------- Co-authored-by: kjac --- Directory.Packages.props | 2 - .../UmbracoBuilder.BackOffice.cs | 1 - .../UmbracoApplicationBuilder.BackOffice.cs | 1 - ...iceExternalLoginProviderErrorMiddleware.cs | 11 +- .../UmbracoBuilder.Collections.cs | 9 - .../DependencyInjection/UmbracoBuilder.cs | 3 - .../Install/InstallStatusTracker.cs | 157 ---------- .../InstallSteps/FilePermissionsStep.cs | 56 ---- .../InstallSteps/TelemetryIdentifierStep.cs | 47 --- .../Install/InstallSteps/UpgradeStep.cs | 56 ---- .../Install/Models/InstallInstructions.cs | 14 - .../Models/InstallProgressResultModel.cs | 42 --- .../Install/Models/InstallSetup.cs | 23 -- .../Install/Models/InstallSetupResult.cs | 43 --- .../Install/Models/InstallSetupStep.cs | 86 ------ .../Models/InstallSetupStepAttribute.cs | 48 --- .../Install/Models/InstallTrackingItem.cs | 44 --- .../Install/Models/InstallationType.cs | 9 - src/Umbraco.Core/Install/Models/Package.cs | 17 -- src/Umbraco.Core/Install/Models/UserModel.cs | 24 -- .../Installer/NewInstallStepCollection.cs | 1 - src/Umbraco.Core/WebAssets/AssetFile.cs | 20 -- src/Umbraco.Core/WebAssets/AssetType.cs | 7 - src/Umbraco.Core/WebAssets/BundlingOptions.cs | 46 --- src/Umbraco.Core/WebAssets/CssFile.cs | 11 - .../CustomBackOfficeAssetsCollection.cs | 11 - ...CustomBackOfficeAssetsCollectionBuilder.cs | 8 - src/Umbraco.Core/WebAssets/IAssetFile.cs | 8 - .../WebAssets/IRuntimeMinifier.cs | 84 ------ src/Umbraco.Core/WebAssets/JavascriptFile.cs | 11 - .../UmbracoBuilder.CoreServices.cs | 3 +- .../UmbracoBuilder.Installer.cs | 24 +- .../UmbracoBuilder.WebAssets.cs | 14 - .../Install/InstallHelper.cs | 6 - .../Install/InstallStepCollection.cs | 52 ---- .../InstallSteps/CompleteInstallStep.cs | 27 -- .../InstallSteps/DatabaseConfigureStep.cs | 77 ----- .../InstallSteps/DatabaseInstallStep.cs | 51 ---- .../InstallSteps/DatabaseUpgradeStep.cs | 90 ------ .../Install/InstallSteps/NewInstallStep.cs | 274 ------------------ .../Installer/Steps/CreateUserStep.cs | 9 +- .../Manifest/DataEditorConverter.cs | 214 -------------- .../Manifest/ValueValidatorConverter.cs | 31 -- .../Serialization/FuzzyBooleanConverter.cs | 41 --- .../Serialization/JsonReadConverter.cs | 46 --- .../Serialization/JsonToStringConverter.cs | 28 -- .../KnownTypeUdiJsonConverter.cs | 20 -- .../NoTypeConverterJsonConverter.cs | 47 --- .../Serialization/UdiJsonConverter.cs | 20 -- .../Serialization/UdiRangeJsonConverter.cs | 20 -- .../Umbraco.Infrastructure.csproj | 13 - .../BackOfficeJavaScriptInitializer.cs | 79 ----- .../WebAssets/BackOfficeWebAssets.cs | 225 -------------- .../WebAssets/JsInitialize.js | 54 ---- src/Umbraco.Infrastructure/WebAssets/Main.js | 12 - .../WebAssets/PreviewInitialize.js | 14 - .../WebAssets/PropertyEditorAssetAttribute.cs | 24 -- .../WebAssets/Resources.Designer.cs | 153 ---------- .../WebAssets/Resources.resx | 34 --- .../WebAssets/TinyMceInitialize.js | 12 - .../BackOfficeApplicationModelProvider.cs | 51 ---- .../BackOfficeIdentityCultureConvention.cs | 11 - ...racoApiBehaviorApplicationModelProvider.cs | 86 ------ .../UmbracoJsonModelBinderConvention.cs | 58 ---- .../UmbracoBuilderExtensions.cs | 49 ---- ...oApplicationBuilder.RuntimeMinification.cs | 30 -- .../Extensions/UrlHelperExtensions.cs | 10 +- .../AllowHttpJsonConfigrationAttribute.cs | 30 -- .../AngularJsonOnlyConfigurationAttribute.cs | 53 ---- .../Filters/JsonDateTimeFormatAttribute.cs | 53 ---- .../Filters/JsonExceptionFilterAttribute.cs | 54 ---- .../OutgoingNoHyphenGuidFormatAttribute.cs | 76 ----- .../AngularJsonMediaTypeFormatter.cs | 41 --- .../IgnoreRequiredAttributesResolver.cs | 17 -- .../Hosting/UmbracoBackOfficePathGenerator.cs | 4 +- .../Middleware/UmbracoRequestMiddleware.cs | 44 +-- .../ModelBinders/UmbracoJsonModelBinder.cs | 47 --- .../SmidgeHelperAccessor.cs | 28 -- .../RuntimeMinification/SmidgeNuglifyJs.cs | 29 -- .../RuntimeMinification/SmidgeOptionsSetup.cs | 22 -- .../SmidgeRequestHelper.cs | 73 ----- .../SmidgeRuntimeMinifier.cs | 176 ----------- .../UmbracoSmidgeConfigCacheBuster.cs | 81 ------ .../Umbraco.Web.Common.csproj | 2 - .../UmbracoBuilderExtensions.cs | 3 - .../UmbracoTestServerTestBase.cs | 1 - .../Testing/UmbracoIntegrationTest.cs | 1 - .../Umbraco.Core/CoreThings/UdiTests.cs | 26 -- .../JsInitializationTests.cs | 33 --- ...noreRequiredAttributesResolverUnitTests.cs | 40 --- .../UmbracoSmidgeConfigCacheBusterTests.cs | 109 ------- 91 files changed, 23 insertions(+), 3929 deletions(-) delete mode 100644 src/Umbraco.Core/Install/InstallStatusTracker.cs delete mode 100644 src/Umbraco.Core/Install/InstallSteps/FilePermissionsStep.cs delete mode 100644 src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs delete mode 100644 src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs delete mode 100644 src/Umbraco.Core/Install/Models/InstallInstructions.cs delete mode 100644 src/Umbraco.Core/Install/Models/InstallProgressResultModel.cs delete mode 100644 src/Umbraco.Core/Install/Models/InstallSetup.cs delete mode 100644 src/Umbraco.Core/Install/Models/InstallSetupResult.cs delete mode 100644 src/Umbraco.Core/Install/Models/InstallSetupStep.cs delete mode 100644 src/Umbraco.Core/Install/Models/InstallSetupStepAttribute.cs delete mode 100644 src/Umbraco.Core/Install/Models/InstallTrackingItem.cs delete mode 100644 src/Umbraco.Core/Install/Models/InstallationType.cs delete mode 100644 src/Umbraco.Core/Install/Models/Package.cs delete mode 100644 src/Umbraco.Core/Install/Models/UserModel.cs delete mode 100644 src/Umbraco.Core/WebAssets/AssetFile.cs delete mode 100644 src/Umbraco.Core/WebAssets/AssetType.cs delete mode 100644 src/Umbraco.Core/WebAssets/BundlingOptions.cs delete mode 100644 src/Umbraco.Core/WebAssets/CssFile.cs delete mode 100644 src/Umbraco.Core/WebAssets/CustomBackOfficeAssetsCollection.cs delete mode 100644 src/Umbraco.Core/WebAssets/CustomBackOfficeAssetsCollectionBuilder.cs delete mode 100644 src/Umbraco.Core/WebAssets/IAssetFile.cs delete mode 100644 src/Umbraco.Core/WebAssets/IRuntimeMinifier.cs delete mode 100644 src/Umbraco.Core/WebAssets/JavascriptFile.cs delete mode 100644 src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.WebAssets.cs delete mode 100644 src/Umbraco.Infrastructure/Install/InstallStepCollection.cs delete mode 100644 src/Umbraco.Infrastructure/Install/InstallSteps/CompleteInstallStep.cs delete mode 100644 src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs delete mode 100644 src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseInstallStep.cs delete mode 100644 src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs delete mode 100644 src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs delete mode 100644 src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs delete mode 100644 src/Umbraco.Infrastructure/Manifest/ValueValidatorConverter.cs delete mode 100644 src/Umbraco.Infrastructure/Serialization/FuzzyBooleanConverter.cs delete mode 100644 src/Umbraco.Infrastructure/Serialization/JsonReadConverter.cs delete mode 100644 src/Umbraco.Infrastructure/Serialization/JsonToStringConverter.cs delete mode 100644 src/Umbraco.Infrastructure/Serialization/KnownTypeUdiJsonConverter.cs delete mode 100644 src/Umbraco.Infrastructure/Serialization/NoTypeConverterJsonConverter.cs delete mode 100644 src/Umbraco.Infrastructure/Serialization/UdiJsonConverter.cs delete mode 100644 src/Umbraco.Infrastructure/Serialization/UdiRangeJsonConverter.cs delete mode 100644 src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs delete mode 100644 src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs delete mode 100644 src/Umbraco.Infrastructure/WebAssets/JsInitialize.js delete mode 100644 src/Umbraco.Infrastructure/WebAssets/Main.js delete mode 100644 src/Umbraco.Infrastructure/WebAssets/PreviewInitialize.js delete mode 100644 src/Umbraco.Infrastructure/WebAssets/PropertyEditorAssetAttribute.cs delete mode 100644 src/Umbraco.Infrastructure/WebAssets/Resources.Designer.cs delete mode 100644 src/Umbraco.Infrastructure/WebAssets/Resources.resx delete mode 100644 src/Umbraco.Infrastructure/WebAssets/TinyMceInitialize.js delete mode 100644 src/Umbraco.Web.Common/ApplicationModels/BackOfficeApplicationModelProvider.cs delete mode 100644 src/Umbraco.Web.Common/ApplicationModels/BackOfficeIdentityCultureConvention.cs delete mode 100644 src/Umbraco.Web.Common/ApplicationModels/UmbracoApiBehaviorApplicationModelProvider.cs delete mode 100644 src/Umbraco.Web.Common/ApplicationModels/UmbracoJsonModelBinderConvention.cs delete mode 100644 src/Umbraco.Web.Common/Extensions/UmbracoApplicationBuilder.RuntimeMinification.cs delete mode 100644 src/Umbraco.Web.Common/Filters/AllowHttpJsonConfigrationAttribute.cs delete mode 100644 src/Umbraco.Web.Common/Filters/AngularJsonOnlyConfigurationAttribute.cs delete mode 100644 src/Umbraco.Web.Common/Filters/JsonDateTimeFormatAttribute.cs delete mode 100644 src/Umbraco.Web.Common/Filters/JsonExceptionFilterAttribute.cs delete mode 100644 src/Umbraco.Web.Common/Filters/OutgoingNoHyphenGuidFormatAttribute.cs delete mode 100644 src/Umbraco.Web.Common/Formatters/AngularJsonMediaTypeFormatter.cs delete mode 100644 src/Umbraco.Web.Common/Formatters/IgnoreRequiredAttributesResolver.cs delete mode 100644 src/Umbraco.Web.Common/ModelBinders/UmbracoJsonModelBinder.cs delete mode 100644 src/Umbraco.Web.Common/RuntimeMinification/SmidgeHelperAccessor.cs delete mode 100644 src/Umbraco.Web.Common/RuntimeMinification/SmidgeNuglifyJs.cs delete mode 100644 src/Umbraco.Web.Common/RuntimeMinification/SmidgeOptionsSetup.cs delete mode 100644 src/Umbraco.Web.Common/RuntimeMinification/SmidgeRequestHelper.cs delete mode 100644 src/Umbraco.Web.Common/RuntimeMinification/SmidgeRuntimeMinifier.cs delete mode 100644 src/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBuster.cs delete mode 100644 tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/AngularIntegration/JsInitializationTests.cs delete mode 100644 tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Formatters/IgnoreRequiredAttributesResolverUnitTests.cs delete mode 100644 tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBusterTests.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index de21c2431b..976f971f46 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -76,8 +76,6 @@ - - diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilder.BackOffice.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilder.BackOffice.cs index 20ee572dc4..4cc22890cd 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilder.BackOffice.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/UmbracoBuilder.BackOffice.cs @@ -24,7 +24,6 @@ public static partial class UmbracoBuilderExtensions .AddConfiguration() .AddUmbracoCore() .AddWebComponents() - .AddRuntimeMinifier() .AddBackOfficeCore() .AddBackOfficeIdentity() .AddBackOfficeAuthentication() diff --git a/src/Umbraco.Cms.Api.Management/Extensions/UmbracoApplicationBuilder.BackOffice.cs b/src/Umbraco.Cms.Api.Management/Extensions/UmbracoApplicationBuilder.BackOffice.cs index b1e3000884..7105c6bcf3 100644 --- a/src/Umbraco.Cms.Api.Management/Extensions/UmbracoApplicationBuilder.BackOffice.cs +++ b/src/Umbraco.Cms.Api.Management/Extensions/UmbracoApplicationBuilder.BackOffice.cs @@ -38,7 +38,6 @@ public static partial class UmbracoApplicationBuilderExtensions BackOfficeAreaRoutes backOfficeRoutes = app.ApplicationServices.GetRequiredService(); backOfficeRoutes.CreateRoutes(app.EndpointRouteBuilder); - app.UseUmbracoRuntimeMinificationEndpoints(); app.UseUmbracoPreviewEndpoints(); return app; diff --git a/src/Umbraco.Cms.Api.Management/Middleware/BackOfficeExternalLoginProviderErrorMiddleware.cs b/src/Umbraco.Cms.Api.Management/Middleware/BackOfficeExternalLoginProviderErrorMiddleware.cs index 95128b47f7..414d0fcb38 100644 --- a/src/Umbraco.Cms.Api.Management/Middleware/BackOfficeExternalLoginProviderErrorMiddleware.cs +++ b/src/Umbraco.Cms.Api.Management/Middleware/BackOfficeExternalLoginProviderErrorMiddleware.cs @@ -1,8 +1,8 @@ using System.Text; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; -using Newtonsoft.Json; using Umbraco.Cms.Core.Security; +using Umbraco.Cms.Core.Serialization; using Umbraco.Extensions; namespace Umbraco.Cms.Api.Management.Middleware; @@ -18,6 +18,13 @@ namespace Umbraco.Cms.Api.Management.Middleware; /// public class BackOfficeExternalLoginProviderErrorMiddleware : IMiddleware { + private readonly IJsonSerializer _jsonSerializer; + + public BackOfficeExternalLoginProviderErrorMiddleware(IJsonSerializer jsonSerializer) + { + _jsonSerializer = jsonSerializer; + } + public async Task InvokeAsync(HttpContext context, RequestDelegate next) { var shortCircuit = false; @@ -29,7 +36,7 @@ public class BackOfficeExternalLoginProviderErrorMiddleware : IMiddleware { shortCircuit = true; - var serialized = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(errors))); + var serialized = Convert.ToBase64String(Encoding.UTF8.GetBytes(_jsonSerializer.Serialize(errors))); context.Response.Cookies.Append( ViewDataExtensions.TokenExternalSignInError, diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs index d4467fa3ea..bb4a4d98c3 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs @@ -15,8 +15,6 @@ using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Snippets; using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Core.Tour; -using Umbraco.Cms.Core.Trees; -using Umbraco.Cms.Core.WebAssets; using Umbraco.Cms.Core.Webhooks; using Umbraco.Extensions; @@ -97,7 +95,6 @@ public static partial class UmbracoBuilderExtensions .Append() .Append() .Append(); - builder.BackOfficeAssets(); builder.SelectorHandlers().Add(() => builder.TypeLoader.GetTypes()); builder.FilterHandlers().Add(() => builder.TypeLoader.GetTypes()); builder.SortHandlers().Add(() => builder.TypeLoader.GetTypes()); @@ -244,12 +241,6 @@ public static partial class UmbracoBuilderExtensions public static EmbedProvidersCollectionBuilder EmbedProviders(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); - /// - /// Gets the back office custom assets collection builder - /// - public static CustomBackOfficeAssetsCollectionBuilder BackOfficeAssets(this IUmbracoBuilder builder) - => builder.WithCollectionBuilder(); - /// /// Gets the Delivery API selector handler collection builder /// diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs index c211b54c1f..9bc065993e 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs @@ -18,7 +18,6 @@ using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Features; using Umbraco.Cms.Core.Handlers; using Umbraco.Cms.Core.Hosting; -using Umbraco.Cms.Core.Install; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Mail; @@ -187,8 +186,6 @@ namespace Umbraco.Cms.Core.DependencyInjection Services.AddSingleton(); - Services.AddSingleton(); - Services.AddUnique(); Services.AddSingleton(f => f.GetRequiredService().CreateDictionary()); diff --git a/src/Umbraco.Core/Install/InstallStatusTracker.cs b/src/Umbraco.Core/Install/InstallStatusTracker.cs deleted file mode 100644 index f1f92ef46c..0000000000 --- a/src/Umbraco.Core/Install/InstallStatusTracker.cs +++ /dev/null @@ -1,157 +0,0 @@ -using Umbraco.Cms.Core.Collections; -using Umbraco.Cms.Core.Hosting; -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Core.Serialization; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Core.Install; - -/// -/// An internal in-memory status tracker for the current installation -/// -[Obsolete("This will no longer be used with the new backoffice APi, instead all steps run in one go")] -public class InstallStatusTracker -{ - private static ConcurrentHashSet _steps = new(); - private readonly IHostingEnvironment _hostingEnvironment; - private readonly IJsonSerializer _jsonSerializer; - - public InstallStatusTracker(IHostingEnvironment hostingEnvironment, IJsonSerializer jsonSerializer) - { - _hostingEnvironment = hostingEnvironment; - _jsonSerializer = jsonSerializer; - } - - public static IEnumerable GetStatus() => - new List(_steps).OrderBy(x => x.ServerOrder); - - public void Reset() - { - _steps = new ConcurrentHashSet(); - ClearFiles(); - } - - private string GetFile(Guid installId) - { - var file = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + - "Install/" - + "install_" - + installId.ToString("N") - + ".txt"); - return file; - } - - public void ClearFiles() - { - var dir = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + - "Install/"); - if (Directory.Exists(dir)) - { - var files = Directory.GetFiles(dir); - foreach (var f in files) - { - File.Delete(f); - } - } - else - { - Directory.CreateDirectory(dir); - } - } - - public IEnumerable InitializeFromFile(Guid installId) - { - // check if we have our persisted file and read it - var file = GetFile(installId); - if (File.Exists(file)) - { - IEnumerable? deserialized = - _jsonSerializer.Deserialize>( - File.ReadAllText(file)); - if (deserialized is not null) - { - foreach (InstallTrackingItem item in deserialized) - { - _steps.Add(item); - } - } - } - else - { - throw new InvalidOperationException("Cannot initialize from file, the installation file with id " + - installId + " does not exist"); - } - - return new List(_steps); - } - - public IEnumerable Initialize(Guid installId, IEnumerable steps) - { - // if there are no steps in memory - if (_steps.Count == 0) - { - // check if we have our persisted file and read it - var file = GetFile(installId); - if (File.Exists(file)) - { - IEnumerable? deserialized = - _jsonSerializer.Deserialize>( - File.ReadAllText(file)); - if (deserialized is not null) - { - foreach (InstallTrackingItem item in deserialized) - { - _steps.Add(item); - } - } - } - else - { - ClearFiles(); - - // otherwise just create the steps in memory (brand new install) - foreach (InstallSetupStep step in steps.OrderBy(x => x.ServerOrder)) - { - _steps.Add(new InstallTrackingItem(step.Name, step.ServerOrder)); - } - - // save the file - var serialized = _jsonSerializer.Serialize(new List(_steps)); - Directory.CreateDirectory(Path.GetDirectoryName(file)!); - File.WriteAllText(file, serialized); - } - } - else - { - // ensure that the file exists with the current install id - var file = GetFile(installId); - if (File.Exists(file) == false) - { - ClearFiles(); - - // save the correct file - var serialized = _jsonSerializer.Serialize(new List(_steps)); - Directory.CreateDirectory(Path.GetDirectoryName(file)!); - File.WriteAllText(file, serialized); - } - } - - return new List(_steps); - } - - public void SetComplete(Guid installId, string name, IDictionary? additionalData = null) - { - InstallTrackingItem trackingItem = _steps.Single(x => x.Name == name); - if (additionalData != null) - { - trackingItem.AdditionalData = additionalData; - } - - trackingItem.IsComplete = true; - - // save the file - var file = GetFile(installId); - var serialized = _jsonSerializer.Serialize(new List(_steps)); - File.WriteAllText(file, serialized); - } -} diff --git a/src/Umbraco.Core/Install/InstallSteps/FilePermissionsStep.cs b/src/Umbraco.Core/Install/InstallSteps/FilePermissionsStep.cs deleted file mode 100644 index b6a08d55ae..0000000000 --- a/src/Umbraco.Core/Install/InstallSteps/FilePermissionsStep.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Core.Services; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Core.Install.InstallSteps; - -/// -/// Represents a step in the installation that ensure all the required permissions on files and folders are correct. -/// -[Obsolete("Will be replace with a new step with the new backoffice")] -[InstallSetupStep( - InstallationType.NewInstall | InstallationType.Upgrade, - "Permissions", - 0, - "", - PerformsAppRestart = true)] -public class FilePermissionsStep : InstallSetupStep -{ - private readonly IFilePermissionHelper _filePermissionHelper; - private readonly ILocalizedTextService _localizedTextService; - - /// - /// Initializes a new instance of the class. - /// - public FilePermissionsStep( - IFilePermissionHelper filePermissionHelper, - ILocalizedTextService localizedTextService) - { - _filePermissionHelper = filePermissionHelper; - _localizedTextService = localizedTextService; - } - - /// - public override Task ExecuteAsync(object model) - { - // validate file permissions - var permissionsOk = - _filePermissionHelper.RunFilePermissionTestSuite( - out Dictionary> report); - - var translatedErrors = - report.ToDictionary(x => _localizedTextService.Localize("permissions", x.Key), x => x.Value); - if (permissionsOk == false) - { - throw new InstallException("Permission check failed", "permissionsreport", new { errors = translatedErrors }); - } - - return Task.FromResult(null); - } - - /// - public override bool RequiresExecution(object model) => true; -} diff --git a/src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs b/src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs deleted file mode 100644 index 8b00a89ba1..0000000000 --- a/src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs +++ /dev/null @@ -1,47 +0,0 @@ -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.DependencyInjection; -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Core.Telemetry; - -namespace Umbraco.Cms.Core.Install.InstallSteps; - -[Obsolete("Will be replace with a new step with the new backoffice")] -[InstallSetupStep( - InstallationType.NewInstall | InstallationType.Upgrade, - "TelemetryIdConfiguration", - 0, - "", - PerformsAppRestart = false)] -public class TelemetryIdentifierStep : InstallSetupStep -{ - private readonly IOptions _globalSettings; - private readonly ISiteIdentifierService _siteIdentifierService; - - public TelemetryIdentifierStep( - IOptions globalSettings, - ISiteIdentifierService siteIdentifierService) - { - _globalSettings = globalSettings; - _siteIdentifierService = siteIdentifierService; - } - - public override Task ExecuteAsync(object model) - { - _siteIdentifierService.TryCreateSiteIdentifier(out _); - return Task.FromResult(null); - } - - public override bool RequiresExecution(object model) - { - // Verify that Json value is not empty string - // Try & get a value stored in appSettings.json - var backofficeIdentifierRaw = _globalSettings.Value.Id; - - // No need to add Id again if already found - return string.IsNullOrEmpty(backofficeIdentifierRaw); - } -} diff --git a/src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs b/src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs deleted file mode 100644 index c67b1fa5fb..0000000000 --- a/src/Umbraco.Core/Install/InstallSteps/UpgradeStep.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Umbraco.Cms.Core.Configuration; -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Core.Semver; -using Umbraco.Cms.Core.Services; -using Umbraco.Extensions; -namespace Umbraco.Cms.Core.Install.InstallSteps -{ - /// - /// This step is purely here to show the button to commence the upgrade - /// - [Obsolete("Will be replace with a new step with the new backoffice")] - [InstallSetupStep(InstallationType.Upgrade, "Upgrade", "upgrade", 1, "Upgrading Umbraco to the latest and greatest version.")] - public class UpgradeStep : InstallSetupStep - { - public override bool RequiresExecution(object model) => true; - private readonly IUmbracoVersion _umbracoVersion; - private readonly IRuntimeState _runtimeState; - - public UpgradeStep(IUmbracoVersion umbracoVersion, IRuntimeState runtimeState) - { - _umbracoVersion = umbracoVersion; - _runtimeState = runtimeState; - } - - public override Task ExecuteAsync(object model) => Task.FromResult(null); - - public override object ViewModel - { - get - { - string FormatGuidState(string? value) - { - if (string.IsNullOrWhiteSpace(value)) - { - value = "unknown"; - } - else if (Guid.TryParse(value, out Guid currentStateGuid)) - { - value = currentStateGuid.ToString("N").Substring(0, 8); - } - - return value; - } - - var currentState = FormatGuidState(_runtimeState.CurrentMigrationState); - var newState = FormatGuidState(_runtimeState.FinalMigrationState); - var newVersion = _umbracoVersion.SemanticVersion?.ToSemanticStringWithoutBuild(); - var oldVersion = new SemVersion(_umbracoVersion.SemanticVersion?.Major ?? 0).ToString(); //TODO can we find the old version somehow? e.g. from current state - - var reportUrl = $"https://our.umbraco.com/contribute/releases/compare?from={oldVersion}&to={newVersion}¬es=1"; - - return new { oldVersion, newVersion, currentState, newState, reportUrl }; - } - } - } -} diff --git a/src/Umbraco.Core/Install/Models/InstallInstructions.cs b/src/Umbraco.Core/Install/Models/InstallInstructions.cs deleted file mode 100644 index caabf0561c..0000000000 --- a/src/Umbraco.Core/Install/Models/InstallInstructions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Runtime.Serialization; - -namespace Umbraco.Cms.Core.Install.Models; - -[Obsolete("Will no longer be required with the new backoffice API")] -[DataContract(Name = "installInstructions", Namespace = "")] -public class InstallInstructions -{ - [DataMember(Name = "instructions")] - public IDictionary? Instructions { get; set; } - - [DataMember(Name = "installId")] - public Guid InstallId { get; set; } -} diff --git a/src/Umbraco.Core/Install/Models/InstallProgressResultModel.cs b/src/Umbraco.Core/Install/Models/InstallProgressResultModel.cs deleted file mode 100644 index 3b82cac3de..0000000000 --- a/src/Umbraco.Core/Install/Models/InstallProgressResultModel.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Runtime.Serialization; - -namespace Umbraco.Cms.Core.Install.Models; - -/// -/// Returned to the UI for each installation step that is completed -/// -[Obsolete("Will no longer be required with the new backoffice API")] -[DataContract(Name = "result", Namespace = "")] -public class InstallProgressResultModel -{ - public InstallProgressResultModel(bool processComplete, string stepCompleted, string nextStep, string? view = null, object? viewModel = null) - { - ProcessComplete = processComplete; - StepCompleted = stepCompleted; - NextStep = nextStep; - ViewModel = viewModel; - View = view; - } - - /// - /// The UI view to show when this step executes, by default no views are shown for the completion of a step unless - /// explicitly specified. - /// - [DataMember(Name = "view")] - public string? View { get; private set; } - - [DataMember(Name = "complete")] - public bool ProcessComplete { get; set; } - - [DataMember(Name = "stepCompleted")] - public string StepCompleted { get; set; } - - [DataMember(Name = "nextStep")] - public string NextStep { get; set; } - - /// - /// The view model to return to the UI if this step is returning a view (optional) - /// - [DataMember(Name = "model")] - public object? ViewModel { get; private set; } -} diff --git a/src/Umbraco.Core/Install/Models/InstallSetup.cs b/src/Umbraco.Core/Install/Models/InstallSetup.cs deleted file mode 100644 index 8b3ce4bb97..0000000000 --- a/src/Umbraco.Core/Install/Models/InstallSetup.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Runtime.Serialization; - -namespace Umbraco.Cms.Core.Install.Models; - -/// -/// Model containing all the install steps for setting up the UI -/// -[DataContract(Name = "installSetup", Namespace = "")] -[Obsolete("Will no longer be required with the new backoffice API")] -public class InstallSetup -{ - public InstallSetup() - { - Steps = new List(); - InstallId = Guid.NewGuid(); - } - - [DataMember(Name = "installId")] - public Guid InstallId { get; private set; } - - [DataMember(Name = "steps")] - public IEnumerable Steps { get; set; } -} diff --git a/src/Umbraco.Core/Install/Models/InstallSetupResult.cs b/src/Umbraco.Core/Install/Models/InstallSetupResult.cs deleted file mode 100644 index a256a23436..0000000000 --- a/src/Umbraco.Core/Install/Models/InstallSetupResult.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace Umbraco.Cms.Core.Install.Models; - -/// -/// The object returned from each installation step -/// -[Obsolete("Will no longer be required with the new backoffice API")] -public class InstallSetupResult -{ - public InstallSetupResult() - { - } - - public InstallSetupResult(IDictionary savedStepData, string view, object? viewModel = null) - { - ViewModel = viewModel; - SavedStepData = savedStepData; - View = view; - } - - public InstallSetupResult(IDictionary savedStepData) => SavedStepData = savedStepData; - - public InstallSetupResult(string view, object? viewModel = null) - { - ViewModel = viewModel; - View = view; - } - - /// - /// Data that is persisted to the installation file which can be used from other installation steps - /// - public IDictionary? SavedStepData { get; } - - /// - /// The UI view to show when this step executes, by default no views are shown for the completion of a step unless - /// explicitly specified. - /// - public string? View { get; } - - /// - /// The view model to return to the UI if this step is returning a view (optional) - /// - public object? ViewModel { get; } -} diff --git a/src/Umbraco.Core/Install/Models/InstallSetupStep.cs b/src/Umbraco.Core/Install/Models/InstallSetupStep.cs deleted file mode 100644 index 2fe3d9814f..0000000000 --- a/src/Umbraco.Core/Install/Models/InstallSetupStep.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Runtime.Serialization; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Core.Install.Models; - -/// -/// Model to give to the front-end to collect the information for each step -/// -[DataContract(Name = "step", Namespace = "")] -[Obsolete("Will be replaced with IInstallStep in the new backoffice API")] -public abstract class InstallSetupStep : InstallSetupStep -{ - /// - /// Defines the step model type on the server side so we can bind it - /// - [IgnoreDataMember] - public override Type StepType => typeof(T); - - /// - /// The step execution method - /// - /// - /// - public abstract Task ExecuteAsync(T model); - - /// - /// Determines if this step needs to execute based on the current state of the application and/or install process - /// - /// - public abstract bool RequiresExecution(T model); -} - -[DataContract(Name = "step", Namespace = "")] -[Obsolete("Will be replaced with IInstallStep in the new backoffice API")] -public abstract class InstallSetupStep -{ - protected InstallSetupStep() - { - InstallSetupStepAttribute? att = GetType().GetCustomAttribute(false); - if (att == null) - { - throw new InvalidOperationException("Each step must be attributed"); - } - - Name = att.Name; - View = att.View; - ServerOrder = att.ServerOrder; - Description = att.Description; - InstallTypeTarget = att.InstallTypeTarget; - PerformsAppRestart = att.PerformsAppRestart; - } - - [DataMember(Name = "name")] - public string Name { get; private set; } - - [DataMember(Name = "view")] - public virtual string View { get; private set; } - - /// - /// The view model used to render the view, by default is null but can be populated - /// - [DataMember(Name = "model")] - public virtual object? ViewModel { get; private set; } - - [DataMember(Name = "description")] - public string Description { get; private set; } - - [IgnoreDataMember] - public InstallationType InstallTypeTarget { get; } - - [IgnoreDataMember] - public bool PerformsAppRestart { get; } - - /// - /// Defines what order this step needs to execute on the server side since the - /// steps might be shown out of order on the front-end - /// - [DataMember(Name = "serverOrder")] - public int ServerOrder { get; private set; } - - /// - /// Defines the step model type on the server side so we can bind it - /// - [IgnoreDataMember] - public abstract Type StepType { get; } -} diff --git a/src/Umbraco.Core/Install/Models/InstallSetupStepAttribute.cs b/src/Umbraco.Core/Install/Models/InstallSetupStepAttribute.cs deleted file mode 100644 index 63edcf0942..0000000000 --- a/src/Umbraco.Core/Install/Models/InstallSetupStepAttribute.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace Umbraco.Cms.Core.Install.Models; - -[Obsolete("Will no longer be required with the use of IInstallStep in the new backoffice API")] -public sealed class InstallSetupStepAttribute : Attribute -{ - public InstallSetupStepAttribute(InstallationType installTypeTarget, string name, string view, int serverOrder, string description) - { - InstallTypeTarget = installTypeTarget; - Name = name; - View = view; - ServerOrder = serverOrder; - Description = description; - - // default - PerformsAppRestart = false; - } - - public InstallSetupStepAttribute(InstallationType installTypeTarget, string name, int serverOrder, string description) - { - InstallTypeTarget = installTypeTarget; - Name = name; - View = string.Empty; - ServerOrder = serverOrder; - Description = description; - - // default - PerformsAppRestart = false; - } - - public InstallationType InstallTypeTarget { get; } - - public string Name { get; } - - public string View { get; } - - public int ServerOrder { get; } - - public string Description { get; } - - /// - /// A flag to notify the installer that this step performs an app pool restart, this can be handy to know since if the - /// current - /// step is performing a restart, we cannot 'look ahead' to see if the next step can execute since we won't know until - /// the app pool - /// is restarted. - /// - public bool PerformsAppRestart { get; set; } -} diff --git a/src/Umbraco.Core/Install/Models/InstallTrackingItem.cs b/src/Umbraco.Core/Install/Models/InstallTrackingItem.cs deleted file mode 100644 index 70dc08b39c..0000000000 --- a/src/Umbraco.Core/Install/Models/InstallTrackingItem.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace Umbraco.Cms.Core.Install.Models; - -[Obsolete("Will no longer be required with the new backoffice API")] -public class InstallTrackingItem -{ - public InstallTrackingItem(string name, int serverOrder) - { - Name = name; - ServerOrder = serverOrder; - AdditionalData = new Dictionary(); - } - - public string Name { get; set; } - - public int ServerOrder { get; set; } - - public bool IsComplete { get; set; } - - public IDictionary AdditionalData { get; set; } - - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - - if (ReferenceEquals(this, obj)) - { - return true; - } - - if (obj.GetType() != GetType()) - { - return false; - } - - return Equals((InstallTrackingItem)obj); - } - - protected bool Equals(InstallTrackingItem other) => string.Equals(Name, other.Name); - - public override int GetHashCode() => Name.GetHashCode(); -} diff --git a/src/Umbraco.Core/Install/Models/InstallationType.cs b/src/Umbraco.Core/Install/Models/InstallationType.cs deleted file mode 100644 index a2e6c92bad..0000000000 --- a/src/Umbraco.Core/Install/Models/InstallationType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Umbraco.Cms.Core.Install.Models; - -[Obsolete("This will no longer be used with the new backoffice APi, install steps and upgrade steps is instead two different interfaces.")] -[Flags] -public enum InstallationType -{ - NewInstall = 1 << 0, // 1 - Upgrade = 1 << 1, // 2 -} diff --git a/src/Umbraco.Core/Install/Models/Package.cs b/src/Umbraco.Core/Install/Models/Package.cs deleted file mode 100644 index f85e4b1f67..0000000000 --- a/src/Umbraco.Core/Install/Models/Package.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Runtime.Serialization; - -namespace Umbraco.Cms.Core.Install.Models; - -[Obsolete("This is no longer used, instead PackageDefinition and InstalledPackage is used")] -[DataContract(Name = "package")] -public class Package -{ - [DataMember(Name = "name")] - public string? Name { get; set; } - - [DataMember(Name = "thumbnail")] - public string? Thumbnail { get; set; } - - [DataMember(Name = "id")] - public Guid Id { get; set; } -} diff --git a/src/Umbraco.Core/Install/Models/UserModel.cs b/src/Umbraco.Core/Install/Models/UserModel.cs deleted file mode 100644 index debae20806..0000000000 --- a/src/Umbraco.Core/Install/Models/UserModel.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Runtime.Serialization; -using Umbraco.Cms.Core.Models; - -namespace Umbraco.Cms.Core.Install.Models; - -[Obsolete("Will no longer be required with the new backoffice API")] -[DataContract(Name = "user", Namespace = "")] -public class UserModel -{ - [DataMember(Name = "name")] - public string Name { get; set; } = null!; - - [DataMember(Name = "email")] - public string Email { get; set; } = null!; - - [DataMember(Name = "password")] - public string Password { get; set; } = null!; - - [DataMember(Name = "subscribeToNewsLetter")] - public bool SubscribeToNewsLetter { get; set; } - - [DataMember(Name = "telemetryLevel")] - public TelemetryLevel TelemetryLevel { get; set; } -} diff --git a/src/Umbraco.Core/Installer/NewInstallStepCollection.cs b/src/Umbraco.Core/Installer/NewInstallStepCollection.cs index 9322a10177..36ba95f527 100644 --- a/src/Umbraco.Core/Installer/NewInstallStepCollection.cs +++ b/src/Umbraco.Core/Installer/NewInstallStepCollection.cs @@ -1,5 +1,4 @@ using Umbraco.Cms.Core.Composing; -using Umbraco.Cms.Core.Install.Models; namespace Umbraco.Cms.Core.Installer; diff --git a/src/Umbraco.Core/WebAssets/AssetFile.cs b/src/Umbraco.Core/WebAssets/AssetFile.cs deleted file mode 100644 index a0ad298302..0000000000 --- a/src/Umbraco.Core/WebAssets/AssetFile.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Diagnostics; - -namespace Umbraco.Cms.Core.WebAssets; - -/// -/// Represents a dependency file -/// -[DebuggerDisplay("Type: {DependencyType}, File: {FilePath}")] -public class AssetFile : IAssetFile -{ - public AssetFile(AssetType type) => DependencyType = type; - - #region IAssetFile Members - - public string? FilePath { get; set; } - - public AssetType DependencyType { get; } - - #endregion -} diff --git a/src/Umbraco.Core/WebAssets/AssetType.cs b/src/Umbraco.Core/WebAssets/AssetType.cs deleted file mode 100644 index e04caa80a2..0000000000 --- a/src/Umbraco.Core/WebAssets/AssetType.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Umbraco.Cms.Core.WebAssets; - -public enum AssetType -{ - Javascript, - Css, -} diff --git a/src/Umbraco.Core/WebAssets/BundlingOptions.cs b/src/Umbraco.Core/WebAssets/BundlingOptions.cs deleted file mode 100644 index 99236494f3..0000000000 --- a/src/Umbraco.Core/WebAssets/BundlingOptions.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace Umbraco.Cms.Core.WebAssets; - -public struct BundlingOptions : IEquatable -{ - public BundlingOptions(bool optimizeOutput = true, bool enabledCompositeFiles = true) - { - OptimizeOutput = optimizeOutput; - EnabledCompositeFiles = enabledCompositeFiles; - } - - public static BundlingOptions OptimizedAndComposite => new(true); - - public static BundlingOptions OptimizedNotComposite => new(true, false); - - public static BundlingOptions NotOptimizedNotComposite => new(false, false); - - public static BundlingOptions NotOptimizedAndComposite => new(false); - - /// - /// If true, the files in the bundle will be minified - /// - public bool OptimizeOutput { get; } - - /// - /// If true, the files in the bundle will be combined, if false the files - /// will be served as individual files. - /// - public bool EnabledCompositeFiles { get; } - - public static bool operator ==(BundlingOptions left, BundlingOptions right) => left.Equals(right); - - public override bool Equals(object? obj) => obj is BundlingOptions options && Equals(options); - - public bool Equals(BundlingOptions other) => OptimizeOutput == other.OptimizeOutput && - EnabledCompositeFiles == other.EnabledCompositeFiles; - - public override int GetHashCode() - { - var hashCode = 2130304063; - hashCode = (hashCode * -1521134295) + OptimizeOutput.GetHashCode(); - hashCode = (hashCode * -1521134295) + EnabledCompositeFiles.GetHashCode(); - return hashCode; - } - - public static bool operator !=(BundlingOptions left, BundlingOptions right) => !(left == right); -} diff --git a/src/Umbraco.Core/WebAssets/CssFile.cs b/src/Umbraco.Core/WebAssets/CssFile.cs deleted file mode 100644 index 9ba30c83de..0000000000 --- a/src/Umbraco.Core/WebAssets/CssFile.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Umbraco.Cms.Core.WebAssets; - -/// -/// Represents a CSS asset file -/// -public class CssFile : AssetFile -{ - public CssFile(string filePath) - : base(AssetType.Css) => - FilePath = filePath; -} diff --git a/src/Umbraco.Core/WebAssets/CustomBackOfficeAssetsCollection.cs b/src/Umbraco.Core/WebAssets/CustomBackOfficeAssetsCollection.cs deleted file mode 100644 index 523b186c9a..0000000000 --- a/src/Umbraco.Core/WebAssets/CustomBackOfficeAssetsCollection.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Umbraco.Cms.Core.Composing; - -namespace Umbraco.Cms.Core.WebAssets; - -public class CustomBackOfficeAssetsCollection : BuilderCollectionBase -{ - public CustomBackOfficeAssetsCollection(Func> items) - : base(items) - { - } -} diff --git a/src/Umbraco.Core/WebAssets/CustomBackOfficeAssetsCollectionBuilder.cs b/src/Umbraco.Core/WebAssets/CustomBackOfficeAssetsCollectionBuilder.cs deleted file mode 100644 index bdfebf128a..0000000000 --- a/src/Umbraco.Core/WebAssets/CustomBackOfficeAssetsCollectionBuilder.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Umbraco.Cms.Core.Composing; - -namespace Umbraco.Cms.Core.WebAssets; - -public class CustomBackOfficeAssetsCollectionBuilder : OrderedCollectionBuilderBase -{ - protected override CustomBackOfficeAssetsCollectionBuilder This => this; -} diff --git a/src/Umbraco.Core/WebAssets/IAssetFile.cs b/src/Umbraco.Core/WebAssets/IAssetFile.cs deleted file mode 100644 index f3e5516f45..0000000000 --- a/src/Umbraco.Core/WebAssets/IAssetFile.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Umbraco.Cms.Core.WebAssets; - -public interface IAssetFile -{ - string? FilePath { get; set; } - - AssetType DependencyType { get; } -} diff --git a/src/Umbraco.Core/WebAssets/IRuntimeMinifier.cs b/src/Umbraco.Core/WebAssets/IRuntimeMinifier.cs deleted file mode 100644 index 75505eb16e..0000000000 --- a/src/Umbraco.Core/WebAssets/IRuntimeMinifier.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace Umbraco.Cms.Core.WebAssets; - -/// -/// Used for bundling and minifying web assets at runtime -/// -public interface IRuntimeMinifier -{ - /// - /// Returns the cache buster value - /// - string CacheBuster { get; } - - /// - /// Creates a css bundle - /// - /// - /// - /// - /// - /// All files must be absolute paths, relative paths will throw - /// - /// - /// Thrown if any of the paths specified are not absolute - /// - void CreateCssBundle(string bundleName, BundlingOptions bundleOptions, params string[]? filePaths); - - /// - /// Renders the html link tag for the bundle - /// - /// - /// - /// An html encoded string - /// - Task RenderCssHereAsync(string bundleName); - - /// - /// Creates a JS bundle - /// - /// - /// - /// - /// - /// All files must be absolute paths, relative paths will throw - /// - /// - /// Thrown if any of the paths specified are not absolute - /// - void CreateJsBundle(string bundleName, BundlingOptions bundleOptions, params string[]? filePaths); - - /// - /// Renders the html script tag for the bundle - /// - /// - /// - /// An html encoded string - /// - Task RenderJsHereAsync(string bundleName); - - /// - /// Returns the asset paths for the JS bundle name - /// - /// - /// - /// If debug mode is enabled this will return all asset paths (not bundled), else it will return a bundle URL - /// - Task> GetJsAssetPathsAsync(string bundleName); - - /// - /// Returns the asset paths for the css bundle name - /// - /// - /// - /// If debug mode is enabled this will return all asset paths (not bundled), else it will return a bundle URL - /// - Task> GetCssAssetPathsAsync(string bundleName); - - /// - /// Minify the file content, of a given type - /// - /// - /// - /// - Task MinifyAsync(string? fileContent, AssetType assetType); -} diff --git a/src/Umbraco.Core/WebAssets/JavascriptFile.cs b/src/Umbraco.Core/WebAssets/JavascriptFile.cs deleted file mode 100644 index e7f4ea239f..0000000000 --- a/src/Umbraco.Core/WebAssets/JavascriptFile.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Umbraco.Cms.Core.WebAssets; - -/// -/// Represents a JS asset file -/// -public class JavaScriptFile : AssetFile -{ - public JavaScriptFile(string filePath) - : base(AssetType.Javascript) => - FilePath = filePath; -} diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs index 0c8dde608d..138192ac5f 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs @@ -105,8 +105,7 @@ public static partial class UmbracoBuilderExtensions .AddRepositories() .AddServices() .AddCoreMappingProfiles() - .AddFileSystems() - .AddWebAssets(); + .AddFileSystems(); // register persistence mappers - required by database factory so needs to be done here // means the only place the collection can be modified is in a runtime - afterwards it diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs index c63f76b6d8..a5cf808b2e 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs @@ -1,12 +1,6 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; -using Umbraco.Cms.Core.Install.InstallSteps; -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Core.Telemetry; using Umbraco.Cms.Infrastructure.Install; -using Umbraco.Cms.Infrastructure.Install.InstallSteps; using Umbraco.Cms.Infrastructure.Migrations.Notifications; using Umbraco.Cms.Infrastructure.Migrations.PostMigrations; @@ -19,25 +13,9 @@ public static partial class UmbracoBuilderExtensions /// internal static IUmbracoBuilder AddInstaller(this IUmbracoBuilder builder) { - // register the installer steps - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(provider => - { - return new TelemetryIdentifierStep( - provider.GetRequiredService>(), - provider.GetRequiredService()); - }); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - - builder.Services.AddScoped(); - - builder.Services.AddTransient(); builder.Services.AddSingleton(); + // register the installer steps builder.Services.AddTransient(); // Add post migration notification handlers diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.WebAssets.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.WebAssets.cs deleted file mode 100644 index d788f26f88..0000000000 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.WebAssets.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Umbraco.Cms.Core.DependencyInjection; -using Umbraco.Cms.Infrastructure.WebAssets; - -namespace Umbraco.Cms.Infrastructure.DependencyInjection; - -public static partial class UmbracoBuilderExtensions -{ - internal static IUmbracoBuilder AddWebAssets(this IUmbracoBuilder builder) - { - builder.Services.AddSingleton(); - return builder; - } -} diff --git a/src/Umbraco.Infrastructure/Install/InstallHelper.cs b/src/Umbraco.Infrastructure/Install/InstallHelper.cs index 82d4905f12..41daf66913 100644 --- a/src/Umbraco.Infrastructure/Install/InstallHelper.cs +++ b/src/Umbraco.Infrastructure/Install/InstallHelper.cs @@ -29,7 +29,6 @@ namespace Umbraco.Cms.Infrastructure.Install private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory; private readonly IFireAndForgetRunner _fireAndForgetRunner; private readonly IEnumerable _databaseProviderMetadata; - private InstallationType? _installationType; public InstallHelper(DatabaseBuilder databaseBuilder, ILogger logger, @@ -52,9 +51,6 @@ namespace Umbraco.Cms.Infrastructure.Install _umbracoDatabaseFactory = umbracoDatabaseFactory; _fireAndForgetRunner = fireAndForgetRunner; _databaseProviderMetadata = databaseProviderMetadata; - - // We need to initialize the type already, as we can't detect later, if the connection string is added on the fly. - GetInstallationType(); } [Obsolete("Please use constructor that takes an IEnumerable instead, scheduled for removal in Umbraco 12")] @@ -109,8 +105,6 @@ namespace Umbraco.Cms.Infrastructure.Install } - public InstallationType GetInstallationType() => _installationType ??= IsBrandNewInstall ? InstallationType.NewInstall : InstallationType.Upgrade; - public async Task SetInstallStatusAsync(bool isCompleted, string errorMsg) { try diff --git a/src/Umbraco.Infrastructure/Install/InstallStepCollection.cs b/src/Umbraco.Infrastructure/Install/InstallStepCollection.cs deleted file mode 100644 index c07e48705b..0000000000 --- a/src/Umbraco.Infrastructure/Install/InstallStepCollection.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Umbraco.Cms.Core.Install.InstallSteps; -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Infrastructure.Install.InstallSteps; - -namespace Umbraco.Cms.Infrastructure.Install; - -[Obsolete("This will be replaced with an ordered collection with the new backoffice")] -public sealed class InstallStepCollection -{ - private readonly InstallHelper _installHelper; - private readonly IEnumerable _orderedInstallerSteps; - - public InstallStepCollection(InstallHelper installHelper, IEnumerable installerSteps) - { - _installHelper = installHelper; - - // TODO: this is ugly but I have a branch where it's nicely refactored - for now we just want to manage ordering - InstallSetupStep[] a = installerSteps.ToArray(); - _orderedInstallerSteps = new InstallSetupStep[] - { - a.OfType().First(), - a.OfType().First(), - a.OfType().First(), - a.OfType().First(), - a.OfType().First(), - a.OfType().First(), - a.OfType().First(), - - // TODO: Add these back once we have a compatible Starter kit - // a.OfType().First(), - // a.OfType().First(), - // a.OfType().First(), - a.OfType().First(), - }; - } - - /// - /// Get the installer steps - /// - /// - /// - /// The step order returned here is how they will appear on the front-end if they have views assigned - /// - public IEnumerable GetAllSteps() => _orderedInstallerSteps; - - /// - /// Returns the steps that are used only for the current installation type - /// - /// - public IEnumerable GetStepsForCurrentInstallType() => GetAllSteps() - .Where(x => x.InstallTypeTarget.HasFlag(_installHelper.GetInstallationType())); -} diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/CompleteInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/CompleteInstallStep.cs deleted file mode 100644 index c67d1f64b0..0000000000 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/CompleteInstallStep.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Umbraco.Cms.Core.Install.Models; - -namespace Umbraco.Cms.Infrastructure.Install.InstallSteps; - -[Obsolete("Will be replace with a new step with the new backoffice")] -[InstallSetupStep( - InstallationType.NewInstall | InstallationType.Upgrade, - "UmbracoVersion", - 50, - "Installation is complete! Get ready to be redirected to your new CMS.", - PerformsAppRestart = true)] -public class CompleteInstallStep : InstallSetupStep -{ - private readonly InstallHelper _installHelper; - - public CompleteInstallStep(InstallHelper installHelper) => _installHelper = installHelper; - - public override async Task ExecuteAsync(object model) - { - // reports the ended install - await _installHelper.SetInstallStatusAsync(true, string.Empty); - - return null; - } - - public override bool RequiresExecution(object model) => true; -} diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs deleted file mode 100644 index a988a5f475..0000000000 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Cms.Core.Install; -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Infrastructure.Migrations.Install; -using Umbraco.Cms.Infrastructure.Persistence; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Infrastructure.Install.InstallSteps; - -[Obsolete("Will be replace with a new step with the new backoffice")] -[InstallSetupStep(InstallationType.NewInstall, "DatabaseConfigure", "database", 10, "Setting up a database, so Umbraco has a place to store your website", PerformsAppRestart = true)] -public class DatabaseConfigureStep : InstallSetupStep -{ - private readonly IOptionsMonitor _connectionStrings; - private readonly DatabaseBuilder _databaseBuilder; - private readonly IEnumerable _databaseProviderMetadata; - private readonly ILogger _logger; - - public DatabaseConfigureStep( - DatabaseBuilder databaseBuilder, - IOptionsMonitor connectionStrings, - ILogger logger, - IEnumerable databaseProviderMetadata) - { - _databaseBuilder = databaseBuilder; - _connectionStrings = connectionStrings; - _logger = logger; - _databaseProviderMetadata = databaseProviderMetadata; - } - - public override object ViewModel => new {databases = _databaseProviderMetadata.GetAvailable().ToList()}; - - public override string View => ShouldDisplayView() ? base.View : string.Empty; - - public override Task ExecuteAsync(DatabaseModel databaseSettings) - { - if (databaseSettings is null && string.IsNullOrWhiteSpace(_connectionStrings.CurrentValue.ConnectionString) is false) - { - return Task.FromResult(null); - } - - if (!_databaseBuilder.ConfigureDatabaseConnection(databaseSettings!, false)) - { - throw new InstallException("Could not connect to the database"); - } - - return Task.FromResult(null); - } - - public override bool RequiresExecution(DatabaseModel model) => ShouldDisplayView(); - - private bool ShouldDisplayView() - { - // If the connection string is already present in config we don't need to show the settings page and we jump to installing/upgrading. - if (_connectionStrings.CurrentValue.IsConnectionStringConfigured()) - { - try - { - // Since a connection string was present we verify the db can connect and query - _databaseBuilder.ValidateSchema(); - - return false; - } - catch (Exception ex) - { - // Something went wrong, could not connect so probably need to reconfigure - _logger.LogError(ex, "An error occurred, reconfiguring..."); - - return true; - } - } - - return true; - } -} diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseInstallStep.cs deleted file mode 100644 index f328fea676..0000000000 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseInstallStep.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Install; -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Infrastructure.Migrations.Install; - -namespace Umbraco.Cms.Infrastructure.Install.InstallSteps; - -[Obsolete("Will be replace with a new step with the new backoffice")] -[InstallSetupStep(InstallationType.NewInstall | InstallationType.Upgrade, "DatabaseInstall", 11, "")] -public class DatabaseInstallStep : InstallSetupStep -{ - private readonly DatabaseBuilder _databaseBuilder; - private readonly IRuntimeState _runtime; - - public DatabaseInstallStep(IRuntimeState runtime, DatabaseBuilder databaseBuilder) - { - _runtime = runtime; - _databaseBuilder = databaseBuilder; - } - - public override Task ExecuteAsync(object model) - { - if (_runtime.Level == RuntimeLevel.Run) - { - throw new Exception("Umbraco is already configured!"); - } - - if (_runtime.Reason == RuntimeLevelReason.InstallMissingDatabase) - { - _databaseBuilder.CreateDatabase(); - } - - DatabaseBuilder.Result? result = _databaseBuilder.CreateSchemaAndData(); - - if (result?.Success == false) - { - throw new InstallException("The database failed to install. ERROR: " + result.Message); - } - - if (result?.RequiresUpgrade == false) - { - return Task.FromResult(null); - } - - // Upgrade is required, so set the flag for the next step - return Task.FromResult(new InstallSetupResult(new Dictionary { { "upgrade", true } }))!; - } - - public override bool RequiresExecution(object model) => true; -} diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs deleted file mode 100644 index 38ad9e178d..0000000000 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Configuration; -using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Cms.Core.Install; -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Infrastructure.Migrations.Install; -using Umbraco.Cms.Infrastructure.Migrations.PostMigrations; -using Umbraco.Cms.Infrastructure.Migrations.Upgrade; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Infrastructure.Install.InstallSteps -{ - [Obsolete("Will be replace with a new step with the new backoffice")] - [InstallSetupStep(InstallationType.Upgrade | InstallationType.NewInstall, "DatabaseUpgrade", 12, "")] - public class DatabaseUpgradeStep : InstallSetupStep - { - private readonly DatabaseBuilder _databaseBuilder; - private readonly IRuntimeState _runtime; - private readonly ILogger _logger; - private readonly IUmbracoVersion _umbracoVersion; - private readonly IOptionsMonitor _connectionStrings; - - public DatabaseUpgradeStep( - DatabaseBuilder databaseBuilder, - IRuntimeState runtime, - ILogger logger, - IUmbracoVersion umbracoVersion, - IOptionsMonitor connectionStrings) - { - _databaseBuilder = databaseBuilder; - _runtime = runtime; - _logger = logger; - _umbracoVersion = umbracoVersion; - _connectionStrings = connectionStrings; - } - - public override Task ExecuteAsync(object model) - { - InstallTrackingItem[] installSteps = InstallStatusTracker.GetStatus().ToArray(); - InstallTrackingItem previousStep = installSteps.Single(x => x.Name == "DatabaseInstall"); - var upgrade = previousStep.AdditionalData.ContainsKey("upgrade"); - - if (upgrade) - { - _logger.LogInformation("Running 'Upgrade' service"); - - var plan = new UmbracoPlan(_umbracoVersion); - - DatabaseBuilder.Result? result = _databaseBuilder.UpgradeSchemaAndData(plan); - - if (result?.Success == false) - { - throw new InstallException("The database failed to upgrade. ERROR: " + result.Message); - } - } - - return Task.FromResult((InstallSetupResult?)null); - } - - public override bool RequiresExecution(object model) - { - // If it's properly configured (i.e. the versions match) then no upgrade necessary - if (_runtime.Level == RuntimeLevel.Run) - { - return false; - } - - // This step relies on the previous one completed - because it has stored some information we need - InstallTrackingItem[] installSteps = InstallStatusTracker.GetStatus().ToArray(); - if (installSteps.Any(x => x.Name == "DatabaseInstall" && x.AdditionalData.ContainsKey("upgrade")) == false) - { - return false; - } - - if (_connectionStrings.CurrentValue.IsConnectionStringConfigured()) - { - // A connection string was present, determine whether this is an install/upgrade - // Return true (upgrade) if there is an installed version, else false (install) - DatabaseSchemaResult? result = _databaseBuilder.ValidateSchema(); - return result?.DetermineHasInstalledVersion() ?? false; - } - - // No connection string configured, probably a fresh install - return false; - } - } -} diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs deleted file mode 100644 index 2a1ac11f48..0000000000 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs +++ /dev/null @@ -1,274 +0,0 @@ -using System.Collections.Specialized; -using System.Data.Common; -using System.Text; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Cms.Core.DependencyInjection; -using Umbraco.Cms.Core.Install.Models; -using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Models.Membership; -using Umbraco.Cms.Core.Security; -using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Web; -using Umbraco.Cms.Infrastructure.Migrations.Install; -using Umbraco.Cms.Infrastructure.Persistence; -using Umbraco.Extensions; -using Constants = Umbraco.Cms.Core.Constants; -using HttpResponseMessage = System.Net.Http.HttpResponseMessage; - -namespace Umbraco.Cms.Infrastructure.Install.InstallSteps -{ - /// - /// This is the first UI step for a brand new install - /// - /// - /// By default this will show the user view which is the most basic information to configure a new install, but if an install get's interrupted because of an - /// error, etc... and the end-user refreshes the installer then we cannot show the user screen because they've already entered that information so instead we'll - /// display a simple continue installation view. - /// - [Obsolete("Will be replace with a new step with the new backoffice")] - [InstallSetupStep(InstallationType.NewInstall, "User", 20, "")] - public class NewInstallStep : InstallSetupStep - { - private readonly IUserService _userService; - private readonly DatabaseBuilder _databaseBuilder; - private readonly IHttpClientFactory _httpClientFactory; - private readonly UserPasswordConfigurationSettings _passwordConfiguration; - private readonly SecuritySettings _securitySettings; - private readonly IOptionsMonitor _connectionStrings; - private readonly ICookieManager _cookieManager; - private readonly IBackOfficeUserManager _userManager; - private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator; - private readonly IEnumerable _databaseProviderMetadata; - private readonly ILocalizedTextService _localizedTextService; - private readonly IMetricsConsentService _metricsConsentService; - - public NewInstallStep( - IUserService userService, - DatabaseBuilder databaseBuilder, - IHttpClientFactory httpClientFactory, - IOptions passwordConfiguration, - IOptions securitySettings, - IOptionsMonitor connectionStrings, - ICookieManager cookieManager, - IBackOfficeUserManager userManager, - IDbProviderFactoryCreator dbProviderFactoryCreator, - IEnumerable databaseProviderMetadata, - ILocalizedTextService localizedTextService, - IMetricsConsentService metricsConsentService) - { - _userService = userService ?? throw new ArgumentNullException(nameof(userService)); - _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); - _httpClientFactory = httpClientFactory; - _passwordConfiguration = passwordConfiguration.Value ?? throw new ArgumentNullException(nameof(passwordConfiguration)); - _securitySettings = securitySettings.Value ?? throw new ArgumentNullException(nameof(securitySettings)); - _connectionStrings = connectionStrings; - _cookieManager = cookieManager; - _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); - _dbProviderFactoryCreator = dbProviderFactoryCreator ?? throw new ArgumentNullException(nameof(dbProviderFactoryCreator)); - _databaseProviderMetadata = databaseProviderMetadata; - _localizedTextService = localizedTextService; - _metricsConsentService = metricsConsentService; - } - - // Scheduled for removal in V12 - [Obsolete("Please use constructor that takes an IMetricsConsentService and ILocalizedTextService instead")] - public NewInstallStep( - IUserService userService, - DatabaseBuilder databaseBuilder, - IHttpClientFactory httpClientFactory, - IOptions passwordConfiguration, - IOptions securitySettings, - IOptionsMonitor connectionStrings, - ICookieManager cookieManager, - IBackOfficeUserManager userManager, - IDbProviderFactoryCreator dbProviderFactoryCreator, - IEnumerable databaseProviderMetadata) - : this( - userService, - databaseBuilder, - httpClientFactory, - passwordConfiguration, - securitySettings, - connectionStrings, - cookieManager, - userManager, - dbProviderFactoryCreator, - databaseProviderMetadata, - StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService()) - { - } - - public override async Task ExecuteAsync(UserModel user) - { - IUser? admin = _userService.GetUserById(Constants.Security.SuperUserId); - if (admin == null) - { - throw new InvalidOperationException("Could not find the super user!"); - } - admin.Email = user.Email.Trim(); - admin.Name = user.Name.Trim(); - admin.Username = user.Email.Trim(); - - _userService.Save(admin); - - BackOfficeIdentityUser? membershipUser = await _userManager.FindByIdAsync(Constants.Security.SuperUserIdAsString); - if (membershipUser == null) - { - throw new InvalidOperationException( - $"No user found in membership provider with id of {Constants.Security.SuperUserIdAsString}."); - } - - //To change the password here we actually need to reset it since we don't have an old one to use to change - var resetToken = await _userManager.GeneratePasswordResetTokenAsync(membershipUser); - if (string.IsNullOrWhiteSpace(resetToken)) - { - throw new InvalidOperationException("Could not reset password: unable to generate internal reset token"); - } - - IdentityResult resetResult = await _userManager.ChangePasswordWithResetAsync(membershipUser.Id, resetToken, user.Password.Trim()); - if (!resetResult.Succeeded) - { - throw new InvalidOperationException("Could not reset password: " + string.Join(", ", resetResult.Errors.ToErrorMessage())); - } - - _metricsConsentService.SetConsentLevel(user.TelemetryLevel); - - if (user.SubscribeToNewsLetter) - { - var values = new NameValueCollection { { "name", admin.Name }, { "email", admin.Email } }; - var content = new StringContent(JsonConvert.SerializeObject(values), Encoding.UTF8, "application/json"); - - HttpClient httpClient = _httpClientFactory.CreateClient(); - - try - { - HttpResponseMessage response = httpClient.PostAsync("https://shop.umbraco.com/base/Ecom/SubmitEmail/installer.aspx", content).Result; - } - catch { /* fail in silence */ } - } - - return null; - } - - /// - /// Return a custom view model for this step - /// - public override object ViewModel - { - get - { - var quickInstallSettings = _databaseProviderMetadata.GetAvailable(true) - .Select(x => new - { - displayName = x.DisplayName, - defaultDatabaseName = x.DefaultDatabaseName, - }) - .FirstOrDefault(); - - return new - { - minCharLength = _passwordConfiguration.RequiredLength, - minNonAlphaNumericLength = _passwordConfiguration.GetMinNonAlphaNumericChars(), - quickInstallSettings, - customInstallAvailable = !GetInstallState().HasFlag(InstallState.ConnectionStringConfigured), - consentLevels = Enum.GetValues(typeof(TelemetryLevel)).Cast().ToList().Select(level => new - { - level, - description = GetTelemetryLevelDescription(level), - }), - }; - } - } - - public override string View => ShowView() - // the user UI - ? "user" - // continue install UI - : "continueinstall"; - - private string GetTelemetryLevelDescription(TelemetryLevel telemetryLevel) => telemetryLevel switch - { - TelemetryLevel.Minimal => _localizedTextService.Localize("analytics", "minimalLevelDescription"), - TelemetryLevel.Basic => _localizedTextService.Localize("analytics", "basicLevelDescription"), - TelemetryLevel.Detailed => _localizedTextService.Localize("analytics", "detailedLevelDescription"), - _ => throw new ArgumentOutOfRangeException(nameof(telemetryLevel), $"Did not expect telemetry level of {telemetryLevel}") - }; - - private InstallState GetInstallState() - { - InstallState installState = InstallState.Unknown; - - if (_databaseBuilder.IsDatabaseConfigured) - { - installState = (installState | InstallState.HasConnectionString) & ~InstallState.Unknown; - } - - ConnectionStrings? umbracoConnectionString = _connectionStrings.CurrentValue; - var isConnectionStringConfigured = umbracoConnectionString.IsConnectionStringConfigured(); - if (isConnectionStringConfigured) - { - installState = (installState | InstallState.ConnectionStringConfigured) & ~InstallState.Unknown; - - DbProviderFactory? factory = _dbProviderFactoryCreator.CreateFactory(umbracoConnectionString.ProviderName); - var isConnectionAvailable = isConnectionStringConfigured && DbConnectionExtensions.IsConnectionAvailable(umbracoConnectionString.ConnectionString, factory); - if (isConnectionAvailable) - { - installState = (installState | InstallState.CanConnect) & ~InstallState.Unknown; - } - - var isUmbracoInstalled = isConnectionAvailable && _databaseBuilder.IsUmbracoInstalled(); - if (isUmbracoInstalled) - { - installState = (installState | InstallState.UmbracoInstalled) & ~InstallState.Unknown; - } - - var hasSomeNonDefaultUser = isUmbracoInstalled && _databaseBuilder.HasSomeNonDefaultUser(); - if (hasSomeNonDefaultUser) - { - installState = (installState | InstallState.HasNonDefaultUser) & ~InstallState.Unknown; - } - } - - return installState; - } - - private bool ShowView() - { - InstallState installState = GetInstallState(); - - return installState.HasFlag(InstallState.Unknown) || !installState.HasFlag(InstallState.UmbracoInstalled); - } - - public override bool RequiresExecution(UserModel model) - { - InstallState installState = GetInstallState(); - if (installState.HasFlag(InstallState.Unknown)) - { - // In this one case when it's a brand new install and nothing has been configured, make sure the - // back office cookie is cleared so there's no old cookies lying around causing problems - _cookieManager.ExpireCookie(_securitySettings.AuthCookieName); - } - - return installState.HasFlag(InstallState.Unknown) || !installState.HasFlag(InstallState.HasNonDefaultUser); - } - - [Flags] - private enum InstallState : short - { - // This is an easy way to avoid 0 enum assignment and not worry about - // manual calcs. https://www.codeproject.com/Articles/396851/Ending-the-Great-Debate-on-Enum-Flags - Unknown = 1, - HasVersion = 1 << 1, - HasConnectionString = 1 << 2, - ConnectionStringConfigured = 1 << 3, - CanConnect = 1 << 4, - UmbracoInstalled = 1 << 5, - HasNonDefaultUser = 1 << 6 - } - } -} diff --git a/src/Umbraco.Infrastructure/Installer/Steps/CreateUserStep.cs b/src/Umbraco.Infrastructure/Installer/Steps/CreateUserStep.cs index 76e31decca..09a291d527 100644 --- a/src/Umbraco.Infrastructure/Installer/Steps/CreateUserStep.cs +++ b/src/Umbraco.Infrastructure/Installer/Steps/CreateUserStep.cs @@ -3,13 +3,13 @@ using System.Data.Common; using System.Text; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; -using Newtonsoft.Json; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Installer; using Umbraco.Cms.Core.Models.Installer; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Security; +using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Infrastructure.Migrations.Install; @@ -31,6 +31,7 @@ public class CreateUserStep : StepBase, IInstallStep private readonly IBackOfficeUserManager _userManager; private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator; private readonly IMetricsConsentService _metricsConsentService; + private readonly IJsonSerializer _jsonSerializer; public CreateUserStep( IUserService userService, @@ -41,7 +42,8 @@ public class CreateUserStep : StepBase, IInstallStep ICookieManager cookieManager, IBackOfficeUserManager userManager, IDbProviderFactoryCreator dbProviderFactoryCreator, - IMetricsConsentService metricsConsentService) + IMetricsConsentService metricsConsentService, + IJsonSerializer jsonSerializer) { _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); @@ -52,6 +54,7 @@ public class CreateUserStep : StepBase, IInstallStep _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); _dbProviderFactoryCreator = dbProviderFactoryCreator ?? throw new ArgumentNullException(nameof(dbProviderFactoryCreator)); _metricsConsentService = metricsConsentService; + _jsonSerializer = jsonSerializer; } public async Task> ExecuteAsync(InstallData model) @@ -94,7 +97,7 @@ public class CreateUserStep : StepBase, IInstallStep if (model.User.SubscribeToNewsletter) { var values = new NameValueCollection { { "name", admin.Name }, { "email", admin.Email } }; - var content = new StringContent(JsonConvert.SerializeObject(values), Encoding.UTF8, "application/json"); + var content = new StringContent(_jsonSerializer.Serialize(values), Encoding.UTF8, "application/json"); HttpClient httpClient = _httpClientFactory.CreateClient(); diff --git a/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs b/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs deleted file mode 100644 index 02ef9a584f..0000000000 --- a/src/Umbraco.Infrastructure/Manifest/DataEditorConverter.cs +++ /dev/null @@ -1,214 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core.IO; -using Umbraco.Cms.Core.PropertyEditors; -using Umbraco.Cms.Core.Serialization; -using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Strings; -using Umbraco.Cms.Infrastructure.Serialization; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Core.Manifest; - -/// -/// Provides a json read converter for in manifests. -/// -internal class DataEditorConverter : JsonReadConverter -{ - private readonly IDataValueEditorFactory _dataValueEditorFactory; - private readonly IIOHelper _ioHelper; - private readonly IJsonSerializer _jsonSerializer; - private readonly IShortStringHelper _shortStringHelper; - private const string SupportsReadOnly = "supportsReadOnly"; - - [Obsolete($"Use the constructor that does not accept {nameof(ILocalizedTextService)}. Will be removed in V15.")] - public DataEditorConverter( - IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper, - ILocalizedTextService textService, - IShortStringHelper shortStringHelper, - IJsonSerializer jsonSerializer) - : this(dataValueEditorFactory, ioHelper, shortStringHelper, jsonSerializer) - { - } - - /// - /// Initializes a new instance of the class. - /// - public DataEditorConverter( - IDataValueEditorFactory dataValueEditorFactory, - IIOHelper ioHelper, - IShortStringHelper shortStringHelper, - IJsonSerializer jsonSerializer) - { - _dataValueEditorFactory = dataValueEditorFactory; - _ioHelper = ioHelper; - _shortStringHelper = shortStringHelper; - _jsonSerializer = jsonSerializer; - } - - /// - protected override IDataEditor Create(Type objectType, string path, JObject jobject) - => new DataEditor(_dataValueEditorFactory); - - /// - protected override void Deserialize(JObject jobject, IDataEditor target, JsonSerializer serializer) - { - // see Create above, target is either DataEditor (parameter) or ConfiguredDataEditor (property) - if (!(target is DataEditor dataEditor)) - { - throw new Exception("panic."); - } - - if (jobject["isPropertyEditor"] is JToken jtoken && jtoken.Value()) - { - PrepareForPropertyEditor(jobject, dataEditor); - } - else - { - PrepareForParameterEditor(jobject, dataEditor); - } - - base.Deserialize(jobject, target, serializer); - } - - private static JArray RewriteValidators(JObject validation) - { - var jarray = new JArray(); - - foreach (KeyValuePair v in validation) - { - var key = v.Key; - JToken? val = v.Value; - var jo = new JObject { { "type", key }, { "configuration", val } }; - jarray.Add(jo); - } - - return jarray; - } - - private void PrepareForPropertyEditor(JObject jobject, DataEditor target) - { - if (jobject["editor"] == null) - { - throw new InvalidOperationException("Missing 'editor' value."); - } - - if (jobject.Property(SupportsReadOnly) is null) - { - jobject[SupportsReadOnly] = false; - } - - // explicitly assign a value editor of type ValueEditor - // (else the deserializer will try to read it before setting it) - // (and besides it's an interface) - target.ExplicitValueEditor = new DataValueEditor(_shortStringHelper, _jsonSerializer); - - // in the manifest, validators are a simple dictionary eg - // { - // required: true, - // regex: '\\d*' - // } - // and we need to turn this into a list of IPropertyValidator - // so, rewrite the json structure accordingly - if (jobject["editor"]?["validation"] is JObject validation) - { - jobject["editor"]!["validation"] = RewriteValidators(validation); - } - - if (jobject["editor"]?["view"] is JValue view) - { - jobject["editor"]!["view"] = RewriteVirtualUrl(view); - } - - var prevalues = jobject["prevalues"] as JObject; - var defaultConfig = jobject["defaultConfig"] as JObject; - if (prevalues != null || defaultConfig != null) - { - // explicitly assign a configuration editor of type ConfigurationEditor - // (else the deserializer will try to read it before setting it) - // (and besides it's an interface) - target.ExplicitConfigurationEditor = new ConfigurationEditor(); - - var config = new JObject(); - if (prevalues != null) - { - config = prevalues; - - // see note about validators, above - same applies to field validators - if (config["fields"] is JArray jarray) - { - foreach (JToken field in jarray) - { - if (field["validation"] is JObject fvalidation) - { - field["validation"] = RewriteValidators(fvalidation); - } - - if (field["view"] is JValue fview) - { - field["view"] = RewriteVirtualUrl(fview); - } - } - } - } - - // in the manifest, default configuration is at editor level - // move it down to configuration editor level so it can be deserialized properly - if (defaultConfig != null) - { - config["defaultConfig"] = defaultConfig; - jobject.Remove("defaultConfig"); - } - - // in the manifest, configuration is named 'prevalues', rename - // it is important to do this LAST - jobject["config"] = config; - jobject.Remove("prevalues"); - } - } - - private string? RewriteVirtualUrl(JValue view) => _ioHelper.ResolveRelativeOrVirtualUrl(view.Value as string); - - private void PrepareForParameterEditor(JObject jobject, DataEditor target) - { - // in a manifest, a parameter editor looks like: - // - // { - // "alias": "...", - // "name": "...", - // "view": "...", - // "config": { "key1": "value1", "key2": "value2" ... } - // } - // - // the view is at top level, but should be down one level to be properly - // deserialized as a ParameterValueEditor property -> need to move it - if (jobject.Property("view") != null) - { - // explicitly assign a value editor of type ParameterValueEditor - target.ExplicitValueEditor = new DataValueEditor(_shortStringHelper, _jsonSerializer); - - // move the 'view' property - jobject["editor"] = new JObject { ["view"] = jobject["view"] }; - jobject.Property("view")?.Remove(); - } - - if (jobject.Property(SupportsReadOnly) is null) - { - jobject[SupportsReadOnly] = false; - } - - // in the manifest, default configuration is named 'config', rename - if (jobject["config"] is JObject config) - { - jobject["defaultConfig"] = config; - jobject.Remove("config"); - } - - // We need to null check, if view do not exists, then editor do not exists - if (jobject["editor"]?["view"] is JValue view) - { - jobject["editor"]!["view"] = RewriteVirtualUrl(view); - } - } -} diff --git a/src/Umbraco.Infrastructure/Manifest/ValueValidatorConverter.cs b/src/Umbraco.Infrastructure/Manifest/ValueValidatorConverter.cs deleted file mode 100644 index 64f81e7697..0000000000 --- a/src/Umbraco.Infrastructure/Manifest/ValueValidatorConverter.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core.PropertyEditors; -using Umbraco.Cms.Infrastructure.Serialization; - -namespace Umbraco.Cms.Core.Manifest; - -/// -/// Implements a json read converter for . -/// -internal class ValueValidatorConverter : JsonReadConverter -{ - private readonly ManifestValueValidatorCollection _validators; - - /// - /// Initializes a new instance of the class. - /// - public ValueValidatorConverter(ManifestValueValidatorCollection validators) => _validators = validators; - - protected override IValueValidator Create(Type objectType, string path, JObject jObject) - { - var type = jObject["type"]?.Value(); - if (string.IsNullOrWhiteSpace(type)) - { - throw new InvalidOperationException("Could not get the type of the validator."); - } - - return _validators.GetByName(type); - - // jObject["configuration"] is going to be deserialized in a Configuration property, if any - } -} diff --git a/src/Umbraco.Infrastructure/Serialization/FuzzyBooleanConverter.cs b/src/Umbraco.Infrastructure/Serialization/FuzzyBooleanConverter.cs deleted file mode 100644 index c8001dbf34..0000000000 --- a/src/Umbraco.Infrastructure/Serialization/FuzzyBooleanConverter.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Newtonsoft.Json; - -namespace Umbraco.Cms.Infrastructure.Serialization; - -public class FuzzyBooleanConverter : JsonConverter -{ - public override bool CanWrite => false; - - public override bool CanRead => true; - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - throw new NotSupportedException(); - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - var value = reader.Value; - if (value is bool) - { - return value; - } - - switch (value?.ToString()?.ToLower().Trim()) - { - case "true": - case "yes": - case "y": - case "1": - return true; - - case "false": - case "no": - case "n": - case "0": - return false; - } - - return new JsonSerializer().Deserialize(reader, objectType); - } - - public override bool CanConvert(Type objectType) => objectType == typeof(bool); -} diff --git a/src/Umbraco.Infrastructure/Serialization/JsonReadConverter.cs b/src/Umbraco.Infrastructure/Serialization/JsonReadConverter.cs deleted file mode 100644 index 32df71d71a..0000000000 --- a/src/Umbraco.Infrastructure/Serialization/JsonReadConverter.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Umbraco.Cms.Infrastructure.Serialization; - -/// -/// Provides a base class for custom implementations. -/// -/// The type of the converted object. -public abstract class JsonReadConverter : JsonConverter -{ - /// - public override bool CanConvert(Type objectType) => typeof(T).IsAssignableFrom(objectType); - - /// - /// Create an instance of objectType, based properties in the JSON object - /// - /// type of object expected - /// The path of the current json token. - /// contents of JSON object that will be deserialized - /// - protected abstract T Create(Type objectType, string path, JObject jObject); - - /// - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - // Load JObject from stream - var jObject = JObject.Load(reader); - - // Create target object based on JObject - T target = Create(objectType, reader.Path, jObject); - - Deserialize(jObject, target, serializer); - - return target; - } - - /// - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - throw new NotSupportedException("JsonReadConverter instances do not support writing."); - - protected virtual void Deserialize(JObject jobject, T target, JsonSerializer serializer) => - - // Populate the object properties - serializer.Populate(jobject.CreateReader(), target!); -} diff --git a/src/Umbraco.Infrastructure/Serialization/JsonToStringConverter.cs b/src/Umbraco.Infrastructure/Serialization/JsonToStringConverter.cs deleted file mode 100644 index 3dbb925d11..0000000000 --- a/src/Umbraco.Infrastructure/Serialization/JsonToStringConverter.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Umbraco.Cms.Infrastructure.Serialization; - -/// -/// This is used in order to deserialize a json object on a property into a json string since the property's type is -/// 'string' -/// -internal class JsonToStringConverter : JsonConverter -{ - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - throw new NotImplementedException(); - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.ValueType == typeof(string)) - { - return reader.Value; - } - - // Load JObject from stream - var jObject = JObject.Load(reader); - return jObject.ToString(Formatting.None); - } - - public override bool CanConvert(Type objectType) => typeof(string).IsAssignableFrom(objectType); -} diff --git a/src/Umbraco.Infrastructure/Serialization/KnownTypeUdiJsonConverter.cs b/src/Umbraco.Infrastructure/Serialization/KnownTypeUdiJsonConverter.cs deleted file mode 100644 index 9d35c4bb4c..0000000000 --- a/src/Umbraco.Infrastructure/Serialization/KnownTypeUdiJsonConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core; - -namespace Umbraco.Cms.Infrastructure.Serialization; - -public class KnownTypeUdiJsonConverter : JsonConverter -{ - public override bool CanConvert(Type objectType) => typeof(Udi).IsAssignableFrom(objectType); - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - writer.WriteValue(value?.ToString()); - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - var jo = JToken.ReadFrom(reader); - var val = jo.ToObject(); - return val == null ? null : UdiParser.Parse(val, true); - } -} diff --git a/src/Umbraco.Infrastructure/Serialization/NoTypeConverterJsonConverter.cs b/src/Umbraco.Infrastructure/Serialization/NoTypeConverterJsonConverter.cs deleted file mode 100644 index 216c335f26..0000000000 --- a/src/Umbraco.Infrastructure/Serialization/NoTypeConverterJsonConverter.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; - -namespace Umbraco.Cms.Infrastructure.Serialization; - -/// -/// This is required if we want to force JSON.Net to not use .Net TypeConverters during serialization/deserialization -/// -/// -/// -/// In some cases this is required if your model has an explicit type converter, see: -/// http://stackoverflow.com/a/31328131/694494 -/// NOTE: I was going to use this for the ImageCropDataSetConverter to convert to String, which would have worked by -/// putting this attribute: -/// [JsonConverter(typeof(NoTypeConverterJsonConverter{ImageCropDataSet}))] on top of the ImageCropDataSet class, -/// however it turns out we -/// don't require this because to convert to string, we just override ToString(). -/// I'll leave this class here for the future though. -/// -public class NoTypeConverterJsonConverter : JsonConverter -{ - private static readonly IContractResolver _resolver = new NoTypeConverterContractResolver(); - private static readonly JsonSerializerSettings _jsonSerializerSettings = new() { ContractResolver = _resolver }; - - public override bool CanConvert(Type objectType) => typeof(T).IsAssignableFrom(objectType); - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) => - JsonSerializer.CreateDefault(_jsonSerializerSettings).Deserialize(reader, objectType); - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - JsonSerializer.CreateDefault(_jsonSerializerSettings).Serialize(writer, value); - - private class NoTypeConverterContractResolver : DefaultContractResolver - { - protected override JsonContract CreateContract(Type objectType) - { - if (typeof(T).IsAssignableFrom(objectType)) - { - JsonObjectContract contract = CreateObjectContract(objectType); - contract.Converter = null; // Also null out the converter to prevent infinite recursion. - return contract; - } - - return base.CreateContract(objectType); - } - } -} diff --git a/src/Umbraco.Infrastructure/Serialization/UdiJsonConverter.cs b/src/Umbraco.Infrastructure/Serialization/UdiJsonConverter.cs deleted file mode 100644 index 6788ffcd92..0000000000 --- a/src/Umbraco.Infrastructure/Serialization/UdiJsonConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core; - -namespace Umbraco.Cms.Infrastructure.Serialization; - -public class UdiJsonConverter : JsonConverter -{ - public override bool CanConvert(Type objectType) => typeof(Udi).IsAssignableFrom(objectType); - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - writer.WriteValue(value?.ToString()); - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - var jo = JToken.ReadFrom(reader); - var val = jo.ToObject(); - return val == null ? null : UdiParser.Parse(val); - } -} diff --git a/src/Umbraco.Infrastructure/Serialization/UdiRangeJsonConverter.cs b/src/Umbraco.Infrastructure/Serialization/UdiRangeJsonConverter.cs deleted file mode 100644 index 9f98f1462d..0000000000 --- a/src/Umbraco.Infrastructure/Serialization/UdiRangeJsonConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core; - -namespace Umbraco.Cms.Infrastructure.Serialization; - -public class UdiRangeJsonConverter : JsonConverter -{ - public override bool CanConvert(Type objectType) => typeof(UdiRange).IsAssignableFrom(objectType); - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - writer.WriteValue(value?.ToString()); - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - var jo = JToken.ReadFrom(reader); - var val = jo.ToObject(); - return val == null ? null : UdiRange.Parse(val); - } -} diff --git a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj index b6ceb3d2e8..2debba53c9 100644 --- a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj +++ b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj @@ -66,17 +66,4 @@ <_Parameter1>Umbraco.Cms.Infrastructure - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - True - True - Resources.resx - - diff --git a/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs b/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs deleted file mode 100644 index f02648202b..0000000000 --- a/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Text; -using System.Text.RegularExpressions; -using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Cms.Core.Hosting; - -namespace Umbraco.Cms.Infrastructure.WebAssets; - -/// -/// Creates a JavaScript block to initialize the back office -/// -public class BackOfficeJavaScriptInitializer -{ - // deal with javascript functions inside of json (not a supported json syntax) - private const string PrefixJavaScriptObject = "@@@@"; - - private static readonly Regex _jsFunctionParser = new( - $"(\"{PrefixJavaScriptObject}(.*?)\")+", - RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.Compiled); - - // replace tokens in the js main - private static readonly Regex _token = new("(\"##\\w+?##\")", RegexOptions.Compiled); - - /// - /// Gets the JS initialization script to boot the back office application - /// - /// - /// - /// The angular module name to boot - /// - /// - /// - /// - public static string GetJavascriptInitialization(IEnumerable scripts, string angularModule, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) - { - var jarray = new StringBuilder(); - jarray.AppendLine("["); - var first = true; - foreach (var file in scripts) - { - if (first) - { - first = false; - } - else - { - jarray.AppendLine(","); - } - - jarray.Append("\""); - jarray.Append(file); - jarray.Append("\""); - } - - jarray.Append("]"); - - return WriteScript(jarray.ToString(), hostingEnvironment.ToAbsolute(globalSettings.UmbracoPath), angularModule); - } - - /// - /// Parses the JsResources.Main and replaces the replacement tokens accordingly - /// - /// - /// - /// - /// - internal static string WriteScript(string scripts, string umbracoPath, string angularModule) - { - var count = 0; - var replacements = new[] { scripts, umbracoPath, angularModule }; - - // replace, catering for the special syntax when we have - // js function() objects contained in the json - return _token.Replace(Resources.Main, match => - { - var replacement = replacements[count++]; - return _jsFunctionParser.Replace(replacement, "$2"); - }); - } -} diff --git a/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs b/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs deleted file mode 100644 index 8780ebb359..0000000000 --- a/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs +++ /dev/null @@ -1,225 +0,0 @@ -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Cms.Core.Hosting; -using Umbraco.Cms.Core.PropertyEditors; -using Umbraco.Cms.Core.WebAssets; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Infrastructure.WebAssets; - -public class BackOfficeWebAssets -{ - public const string UmbracoPreviewJsBundleName = "umbraco-preview-js"; - public const string UmbracoPreviewCssBundleName = "umbraco-preview-css"; - public const string UmbracoCssBundleName = "umbraco-backoffice-css"; - public const string UmbracoInitCssBundleName = "umbraco-backoffice-init-css"; - public const string UmbracoCoreJsBundleName = "umbraco-backoffice-js"; - public const string UmbracoExtensionsJsBundleName = "umbraco-backoffice-extensions-js"; - public const string UmbracoTinyMceJsBundleName = "umbraco-tinymce-js"; - public const string UmbracoUpgradeCssBundleName = "umbraco-authorize-upgrade-css"; - private readonly CustomBackOfficeAssetsCollection _customBackOfficeAssetsCollection; - private readonly IHostingEnvironment _hostingEnvironment; - private readonly PropertyEditorCollection _propertyEditorCollection; - - private readonly IRuntimeMinifier _runtimeMinifier; - private GlobalSettings _globalSettings; - - public BackOfficeWebAssets( - IRuntimeMinifier runtimeMinifier, - PropertyEditorCollection propertyEditorCollection, - IHostingEnvironment hostingEnvironment, - IOptionsMonitor globalSettings, - CustomBackOfficeAssetsCollection customBackOfficeAssetsCollection) - { - _runtimeMinifier = runtimeMinifier; - _propertyEditorCollection = propertyEditorCollection; - _hostingEnvironment = hostingEnvironment; - _globalSettings = globalSettings.CurrentValue; - _customBackOfficeAssetsCollection = customBackOfficeAssetsCollection; - - globalSettings.OnChange(x => _globalSettings = x); - } - - public void CreateBundles() - { - // Create bundles - _runtimeMinifier.CreateCssBundle( - UmbracoInitCssBundleName, - BundlingOptions.NotOptimizedAndComposite, - FormatPaths( - "assets/css/umbraco.min.css", - "lib/umbraco-ui/uui-css/dist/custom-properties.css", - "lib/umbraco-ui/uui-css/dist/uui-text.css", - "lib/bootstrap-social/bootstrap-social.css", - "lib/font-awesome/css/font-awesome.min.css")); - - _runtimeMinifier.CreateCssBundle( - UmbracoUpgradeCssBundleName, - BundlingOptions.NotOptimizedAndComposite, - FormatPaths( - "assets/css/umbraco.min.css", - "lib/bootstrap-social/bootstrap-social.css", - "lib/font-awesome/css/font-awesome.min.css")); - - _runtimeMinifier.CreateCssBundle( - UmbracoPreviewCssBundleName, - BundlingOptions.NotOptimizedAndComposite, - FormatPaths("assets/css/canvasdesigner.min.css")); - - _runtimeMinifier.CreateJsBundle( - UmbracoPreviewJsBundleName, - BundlingOptions.NotOptimizedAndComposite, - FormatPaths(GetScriptsForPreview())); - - _runtimeMinifier.CreateJsBundle( - UmbracoTinyMceJsBundleName, - BundlingOptions.NotOptimizedAndComposite, - FormatPaths(GetScriptsForTinyMce())); - - _runtimeMinifier.CreateJsBundle( - UmbracoCoreJsBundleName, - BundlingOptions.NotOptimizedAndComposite, - FormatPaths(GetScriptsForBackOfficeCore())); - - // get the property editor assets - var propertyEditorAssets = ScanPropertyEditors() - .GroupBy(x => x.AssetType) - .ToDictionary(x => x.Key, x => x.Select(c => c.FilePath)); - - // get the back office custom assets - var customAssets = _customBackOfficeAssetsCollection.GroupBy(x => x.DependencyType) - .ToDictionary(x => x.Key, x => x.Select(c => c.FilePath)); - - // This bundle includes all scripts from property editor assets, - // custom back office assets, and any scripts found in package manifests - // that have the default bundle options. - IEnumerable jsAssets = - (customAssets.TryGetValue(AssetType.Javascript, out IEnumerable? customScripts) - ? customScripts - : Enumerable.Empty()) - .Union(propertyEditorAssets.TryGetValue(AssetType.Javascript, out IEnumerable? scripts) - ? scripts - : Enumerable.Empty()); - - _runtimeMinifier.CreateJsBundle( - UmbracoExtensionsJsBundleName, - BundlingOptions.OptimizedAndComposite, - FormatPaths( - GetScriptsForBackOfficeExtensions(jsAssets))); - - // This bundle includes all CSS from property editor assets, - // custom back office assets, and any CSS found in package manifests - // that have the default bundle options. - IEnumerable cssAssets = - (customAssets.TryGetValue(AssetType.Css, out IEnumerable? customStyles) - ? customStyles - : Enumerable.Empty()) - .Union(propertyEditorAssets.TryGetValue(AssetType.Css, out IEnumerable? styles) - ? styles - : Enumerable.Empty()); - - _runtimeMinifier.CreateCssBundle( - UmbracoCssBundleName, - BundlingOptions.OptimizedAndComposite, - FormatPaths( - GetStylesheetsForBackOffice(cssAssets))); - } - - /// - /// Returns scripts used to load the back office - /// - /// - private string[] GetScriptsForBackOfficeExtensions(IEnumerable propertyEditorScripts) - { - var scripts = new HashSet(StringComparer.InvariantCultureIgnoreCase); - - foreach (var script in propertyEditorScripts) - { - if (script is not null) - { - scripts.Add(script); - } - } - - return scripts.ToArray(); - } - - /// - /// Returns the list of scripts for back office initialization - /// - /// - private string[]? GetScriptsForBackOfficeCore() - { - JArray? resources = JsonConvert.DeserializeObject(Resources.JsInitialize); - return resources?.Where(x => x.Type == JTokenType.String).Select(x => x.ToString()).ToArray(); - } - - /// - /// Returns stylesheets used to load the back office - /// - /// - private string[] GetStylesheetsForBackOffice(IEnumerable propertyEditorStyles) - { - var stylesheets = new HashSet(StringComparer.InvariantCultureIgnoreCase); - - foreach (var stylesheet in propertyEditorStyles) - { - if (stylesheet is not null) - { - stylesheets.Add(stylesheet); - } - } - - return stylesheets.ToArray(); - } - - /// - /// Returns the scripts used for tinymce - /// - /// - private string[]? GetScriptsForTinyMce() - { - JArray? resources = JsonConvert.DeserializeObject(Resources.TinyMceInitialize); - return resources?.Where(x => x.Type == JTokenType.String).Select(x => x.ToString()).ToArray(); - } - - /// - /// Returns the scripts used for preview - /// - /// - private string[]? GetScriptsForPreview() - { - JArray? resources = JsonConvert.DeserializeObject(Resources.PreviewInitialize); - return resources?.Where(x => x.Type == JTokenType.String).Select(x => x.ToString()).ToArray(); - } - - /// - /// Re-format asset paths to be absolute paths - /// - /// - /// - private string[]? FormatPaths(params string[]? assets) - { - var umbracoPath = _globalSettings.GetUmbracoMvcArea(_hostingEnvironment); - - return assets? - .Where(x => x.IsNullOrWhiteSpace() == false) - .Select(x => !x.StartsWith("/") && Uri.IsWellFormedUriString(x, UriKind.Relative) - - // most declarations with be made relative to the /umbraco folder, so things - // like lib/blah/blah.js so we need to turn them into absolutes here - ? umbracoPath.EnsureStartsWith('/').TrimEnd("/") + x.EnsureStartsWith('/') - : x).ToArray(); - } - - /// - /// Returns the web asset paths to load for property editors that have the - /// attribute applied - /// - /// - private IEnumerable ScanPropertyEditors() => - _propertyEditorCollection - .SelectMany(x => x.GetType().GetCustomAttributes(false)); -} diff --git a/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js b/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js deleted file mode 100644 index 28ec6ad24f..0000000000 --- a/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js +++ /dev/null @@ -1,54 +0,0 @@ -[ - - 'lib/jquery/jquery.min.js', - 'lib/jquery-ui/jquery-ui.min.js', - 'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.min.js', - - 'lib/angular/angular.min.js', - 'lib/underscore/underscore-min.js', - - 'lib/moment/moment.min.js', - 'lib/flatpickr/flatpickr.min.js', - - 'lib/animejs/anime.min.js', - - 'lib/angular-route/angular-route.min.js', - 'lib/angular-cookies/angular-cookies.min.js', - 'lib/angular-aria/angular-aria.min.js', - 'lib/angular-touch/angular-touch.min.js', - 'lib/angular-sanitize/angular-sanitize.min.js', - 'lib/angular-animate/angular-animate.min.js', - 'lib/angular-messages/angular-messages.min.js', - - 'lib/angular-ui-sortable/sortable.min.js', - - 'lib/angular-dynamic-locale/tmhDynamicLocale.min.js', - 'lib/ng-file-upload/ng-file-upload.min.js', - 'lib/angular-local-storage/angular-local-storage.min.js', - - 'lib/chart.js/Chart.min.js', - 'lib/angular-chart.js/angular-chart.min.js', - 'lib/wicg-inert/dist/inert.min.js', - - 'lib/umbraco/Extensions.js', - - 'lib/umbraco/NamespaceManager.js', - 'lib/umbraco/LegacySpeechBubble.js', - - 'lib/umbraco-ui/uui/dist/uui.min.js', - - 'login/login.iife.js', - - 'js/utilities.min.js', - - 'js/app.min.js', - - 'js/umbraco.resources.min.js', - 'js/umbraco.directives.min.js', - 'js/umbraco.filters.min.js', - 'js/umbraco.services.min.js', - 'js/umbraco.interceptors.min.js', - 'js/umbraco.controllers.min.js', - 'js/routes.min.js', - 'js/init.min.js' -] diff --git a/src/Umbraco.Infrastructure/WebAssets/Main.js b/src/Umbraco.Infrastructure/WebAssets/Main.js deleted file mode 100644 index 8aa431376a..0000000000 --- a/src/Umbraco.Infrastructure/WebAssets/Main.js +++ /dev/null @@ -1,12 +0,0 @@ -LazyLoad.js("##JsInitialize##", function () { - //we need to set the legacy UmbClientMgr path - if ((typeof UmbClientMgr) !== "undefined") { - UmbClientMgr.setUmbracoPath('"##UmbracoPath##"'); - } - - jQuery(document).ready(function () { - - angular.bootstrap(document, ['"##AngularModule##"']); - - }); -}); diff --git a/src/Umbraco.Infrastructure/WebAssets/PreviewInitialize.js b/src/Umbraco.Infrastructure/WebAssets/PreviewInitialize.js deleted file mode 100644 index de8cd3669e..0000000000 --- a/src/Umbraco.Infrastructure/WebAssets/PreviewInitialize.js +++ /dev/null @@ -1,14 +0,0 @@ -[ - 'lib/jquery/jquery.min.js', - 'lib/angular/angular.min.js', - 'lib/underscore/underscore-min.js', - 'lib/umbraco/Extensions.js', - 'js/utilities.min.js', - 'js/app.min.js', - 'js/umbraco.resources.min.js', - 'js/umbraco.services.min.js', - 'js/umbraco.interceptors.min.js', - 'ServerVariables', - 'lib/signalr/signalr.min.js', - 'js/umbraco.preview.min.js' -] diff --git a/src/Umbraco.Infrastructure/WebAssets/PropertyEditorAssetAttribute.cs b/src/Umbraco.Infrastructure/WebAssets/PropertyEditorAssetAttribute.cs deleted file mode 100644 index 5894730d3f..0000000000 --- a/src/Umbraco.Infrastructure/WebAssets/PropertyEditorAssetAttribute.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Umbraco.Cms.Core.WebAssets; - -namespace Umbraco.Cms.Infrastructure.WebAssets; - -/// -/// Indicates that the property editor requires this asset be loaded when the back office is loaded -/// -/// -/// This wraps a CDF asset -/// -[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -[Obsolete("Use the BackOfficeAssets collection on IUmbracoBuilder instead. Will be removed in the next major version")] -public class PropertyEditorAssetAttribute : Attribute -{ - public PropertyEditorAssetAttribute(AssetType assetType, string filePath) - { - AssetType = assetType; - FilePath = filePath; - } - - public AssetType AssetType { get; } - - public string FilePath { get; } -} diff --git a/src/Umbraco.Infrastructure/WebAssets/Resources.Designer.cs b/src/Umbraco.Infrastructure/WebAssets/Resources.Designer.cs deleted file mode 100644 index be54e3f199..0000000000 --- a/src/Umbraco.Infrastructure/WebAssets/Resources.Designer.cs +++ /dev/null @@ -1,153 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Cms.Infrastructure.WebAssets { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Umbraco.Cms.Infrastructure.WebAssets.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to [ - /// - /// 'lib/jquery/jquery.min.js', - /// 'lib/jquery-ui/jquery-ui.min.js', - /// 'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.min.js', - /// - /// 'lib/angular/angular.min.js', - /// 'lib/underscore/underscore-min.js', - /// - /// 'lib/moment/moment.min.js', - /// 'lib/flatpickr/flatpickr.min.js', - /// - /// 'lib/animejs/anime.min.js', - /// - /// 'lib/angular-route/angular-route.min.js', - /// 'lib/angular-cookies/angular-cookies.min.js', - /// 'lib/angular-aria/angular-aria.min.js', - /// 'lib/angular-touch/angular-touch.min [rest of string was truncated]";. - /// - internal static string JsInitialize { - get { - return ResourceManager.GetString("JsInitialize", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LazyLoad.js("##JsInitialize##", function () { - /// //we need to set the legacy UmbClientMgr path - /// if ((typeof UmbClientMgr) !== "undefined") { - /// UmbClientMgr.setUmbracoPath('"##UmbracoPath##"'); - /// } - /// - /// jQuery(document).ready(function () { - /// - /// angular.bootstrap(document, ['"##AngularModule##"']); - /// - /// }); - ///}); - ///. - /// - internal static string Main { - get { - return ResourceManager.GetString("Main", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to [ - /// 'lib/jquery/jquery.min.js', - /// 'lib/angular/angular.min.js', - /// 'lib/underscore/underscore-min.js', - /// 'lib/umbraco/Extensions.js', - /// 'js/utilities.min.js', - /// 'js/app.min.js', - /// 'js/umbraco.resources.min.js', - /// 'js/umbraco.services.min.js', - /// 'js/umbraco.interceptors.min.js', - /// 'ServerVariables', - /// 'lib/signalr/signalr.min.js', - /// 'js/umbraco.preview.min.js' - ///] - ///. - /// - internal static string PreviewInitialize { - get { - return ResourceManager.GetString("PreviewInitialize", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to [ - /// 'lib/tinymce/tinymce.min.js', - /// - /// 'lib/tinymce/plugins/anchor/plugin.min.js', - /// 'lib/tinymce/plugins/charmap/plugin.min.js', - /// 'lib/tinymce/plugins/table/plugin.min.js', - /// 'lib/tinymce/plugins/lists/plugin.min.js', - /// 'lib/tinymce/plugins/advlist/plugin.min.js', - /// 'lib/tinymce/plugins/autolink/plugin.min.js', - /// 'lib/tinymce/plugins/directionality/plugin.min.js', - /// 'lib/tinymce/plugins/searchreplace/plugin.min.js' - ///] - ///. - /// - internal static string TinyMceInitialize { - get { - return ResourceManager.GetString("TinyMceInitialize", resourceCulture); - } - } - } -} diff --git a/src/Umbraco.Infrastructure/WebAssets/Resources.resx b/src/Umbraco.Infrastructure/WebAssets/Resources.resx deleted file mode 100644 index 0c0289a6f6..0000000000 --- a/src/Umbraco.Infrastructure/WebAssets/Resources.resx +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - JsInitialize.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - Main.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 - - - PreviewInitialize.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - - TinyMceInitialize.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - - diff --git a/src/Umbraco.Infrastructure/WebAssets/TinyMceInitialize.js b/src/Umbraco.Infrastructure/WebAssets/TinyMceInitialize.js deleted file mode 100644 index d172fdadf8..0000000000 --- a/src/Umbraco.Infrastructure/WebAssets/TinyMceInitialize.js +++ /dev/null @@ -1,12 +0,0 @@ -[ - 'lib/tinymce/tinymce.min.js', - - 'lib/tinymce/plugins/anchor/plugin.min.js', - 'lib/tinymce/plugins/charmap/plugin.min.js', - 'lib/tinymce/plugins/table/plugin.min.js', - 'lib/tinymce/plugins/lists/plugin.min.js', - 'lib/tinymce/plugins/advlist/plugin.min.js', - 'lib/tinymce/plugins/autolink/plugin.min.js', - 'lib/tinymce/plugins/directionality/plugin.min.js', - 'lib/tinymce/plugins/searchreplace/plugin.min.js' -] diff --git a/src/Umbraco.Web.Common/ApplicationModels/BackOfficeApplicationModelProvider.cs b/src/Umbraco.Web.Common/ApplicationModels/BackOfficeApplicationModelProvider.cs deleted file mode 100644 index a4b926ac93..0000000000 --- a/src/Umbraco.Web.Common/ApplicationModels/BackOfficeApplicationModelProvider.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Umbraco.Cms.Web.Common.Attributes; - -namespace Umbraco.Cms.Web.Common.ApplicationModels; - -// TODO: This should just exist in the back office project - -/// -/// An application model provider for all Umbraco Back Office controllers -/// -public class BackOfficeApplicationModelProvider : IApplicationModelProvider -{ - private readonly List _actionModelConventions = new() - { - new BackOfficeIdentityCultureConvention(), - }; - - /// - /// - /// Will execute after - /// - public int Order => 0; - - /// - public void OnProvidersExecuted(ApplicationModelProviderContext context) - { - } - - /// - public void OnProvidersExecuting(ApplicationModelProviderContext context) - { - foreach (ControllerModel controller in context.Result.Controllers) - { - if (!IsBackOfficeController(controller)) - { - continue; - } - - foreach (ActionModel action in controller.Actions) - { - foreach (IActionModelConvention convention in _actionModelConventions) - { - convention.Apply(action); - } - } - } - } - - private bool IsBackOfficeController(ControllerModel controller) - => controller.Attributes.OfType().Any(); -} diff --git a/src/Umbraco.Web.Common/ApplicationModels/BackOfficeIdentityCultureConvention.cs b/src/Umbraco.Web.Common/ApplicationModels/BackOfficeIdentityCultureConvention.cs deleted file mode 100644 index ffc2d33278..0000000000 --- a/src/Umbraco.Web.Common/ApplicationModels/BackOfficeIdentityCultureConvention.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Umbraco.Cms.Web.Common.Filters; - -namespace Umbraco.Cms.Web.Common.ApplicationModels; - -// TODO: This should just exist in the back office project -public class BackOfficeIdentityCultureConvention : IActionModelConvention -{ - /// - public void Apply(ActionModel action) => action.Filters.Add(new BackOfficeCultureFilter()); -} diff --git a/src/Umbraco.Web.Common/ApplicationModels/UmbracoApiBehaviorApplicationModelProvider.cs b/src/Umbraco.Web.Common/ApplicationModels/UmbracoApiBehaviorApplicationModelProvider.cs deleted file mode 100644 index d2165a63ee..0000000000 --- a/src/Umbraco.Web.Common/ApplicationModels/UmbracoApiBehaviorApplicationModelProvider.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Umbraco.Cms.Web.Common.Attributes; - -namespace Umbraco.Cms.Web.Common.ApplicationModels; - -/// -/// An application model provider for Umbraco API controllers to behave like WebApi controllers -/// -/// -/// -/// Conventions will be applied to controllers attributed with -/// -/// -/// This is nearly a copy of aspnetcore's ApiBehaviorApplicationModelProvider which supplies a convention for the -/// [ApiController] attribute, however that convention is too strict for our purposes so we will have our own. -/// Uses UmbracoJsonModelBinder for complex parameters and those with BindingSource of Body, but leaves the rest -/// alone see GH #11554 -/// -/// -/// See https://shazwazza.com/post/custom-body-model-binding-per-controller-in-asp-net-core/ -/// and https://github.com/dotnet/aspnetcore/issues/21724 -/// -/// -public class UmbracoApiBehaviorApplicationModelProvider : IApplicationModelProvider -{ - private readonly List _actionModelConventions; - - /// - /// Initializes a new instance of the class. - /// - public UmbracoApiBehaviorApplicationModelProvider(IModelMetadataProvider modelMetadataProvider) - { - // see see https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-3.1#apicontroller-attribute - // for what these things actually do - // NOTE: we don't have attribute routing requirements and we cannot use ApiVisibilityConvention without attribute routing - _actionModelConventions = new List - { - new ClientErrorResultFilterConvention(), // Ensures the responses without any body is converted into a simple json object with info instead of a string like "Status Code: 404; Not Found" - new ConsumesConstraintForFormFileParameterConvention(), // If an controller accepts files, it must accept multipart/form-data. - - // This ensures that all parameters of type BindingSource.Body and those of complex type are bound - // using our own UmbracoJsonModelBinder - new UmbracoJsonModelBinderConvention(modelMetadataProvider), - }; - - Type defaultErrorType = typeof(ProblemDetails); - var defaultErrorTypeAttribute = new ProducesErrorResponseTypeAttribute(defaultErrorType); - _actionModelConventions.Add(new ApiConventionApplicationModelConvention(defaultErrorTypeAttribute)); - } - - /// - /// - /// Will execute after - /// - public int Order => 0; - - /// - public void OnProvidersExecuted(ApplicationModelProviderContext context) - { - } - - /// - public void OnProvidersExecuting(ApplicationModelProviderContext context) - { - foreach (ControllerModel controller in context.Result.Controllers) - { - if (!IsUmbracoApiController(controller)) - { - continue; - } - - foreach (ActionModel action in controller.Actions) - { - foreach (IActionModelConvention convention in _actionModelConventions) - { - convention.Apply(action); - } - } - } - } - - private static bool IsUmbracoApiController(ICommonModel controller) - => controller.Attributes.OfType().Any(); -} diff --git a/src/Umbraco.Web.Common/ApplicationModels/UmbracoJsonModelBinderConvention.cs b/src/Umbraco.Web.Common/ApplicationModels/UmbracoJsonModelBinderConvention.cs deleted file mode 100644 index 8298820e07..0000000000 --- a/src/Umbraco.Web.Common/ApplicationModels/UmbracoJsonModelBinderConvention.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.Extensions.DependencyInjection; -using Umbraco.Cms.Core.DependencyInjection; -using Umbraco.Cms.Web.Common.ModelBinders; - -namespace Umbraco.Cms.Web.Common.ApplicationModels; - -/// -/// Applies the body model binder to any complex parameter and those with a -/// binding source of type -/// -public class UmbracoJsonModelBinderConvention : IActionModelConvention -{ - private readonly IModelMetadataProvider _modelMetadataProvider; - - public UmbracoJsonModelBinderConvention() - : this(StaticServiceProvider.Instance.GetRequiredService()) - { - } - - public UmbracoJsonModelBinderConvention(IModelMetadataProvider modelMetadataProvider) => - _modelMetadataProvider = modelMetadataProvider; - - /// - public void Apply(ActionModel action) - { - foreach (ParameterModel p in action.Parameters) - { - if (p.BindingInfo == null) - { - if (IsComplexTypeParameter(p)) - { - p.BindingInfo = new BindingInfo - { - BindingSource = BindingSource.Body, - BinderType = typeof(UmbracoJsonModelBinder), - }; - } - - continue; - } - - if (p.BindingInfo.BindingSource == BindingSource.Body) - { - p.BindingInfo.BinderType = typeof(UmbracoJsonModelBinder); - } - } - } - - private bool IsComplexTypeParameter(ParameterModel parameter) - { - // No need for information from attributes on the parameter. Just use its type. - ModelMetadata metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterInfo.ParameterType); - - return metadata.IsComplexType; - } -} diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index c432fbed16..8b322a509d 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -14,11 +14,6 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Serilog.Extensions.Logging; -using Smidge; -using Smidge.Cache; -using Smidge.FileProcessors; -using Smidge.InMemory; -using Smidge.Nuglify; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Blocks; using Umbraco.Cms.Core.Cache; @@ -37,10 +32,8 @@ using Umbraco.Cms.Core.Notifications; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Telemetry; using Umbraco.Cms.Core.Templates; using Umbraco.Cms.Core.Web; -using Umbraco.Cms.Core.WebAssets; using Umbraco.Cms.Infrastructure.BackgroundJobs; using Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs; using Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs.ServerRegistration; @@ -64,7 +57,6 @@ using Umbraco.Cms.Web.Common.ModelBinders; using Umbraco.Cms.Web.Common.Mvc; using Umbraco.Cms.Web.Common.Profiler; using Umbraco.Cms.Web.Common.Repositories; -using Umbraco.Cms.Web.Common.RuntimeMinification; using Umbraco.Cms.Web.Common.Security; using Umbraco.Cms.Web.Common.Templates; using Umbraco.Cms.Web.Common.UmbracoContext; @@ -255,41 +247,6 @@ public static partial class UmbracoBuilderExtensions return builder; } - /// - /// Add runtime minifier support for Umbraco - /// - public static IUmbracoBuilder AddRuntimeMinifier(this IUmbracoBuilder builder) - { - // Add custom ISmidgeFileProvider to include the additional App_Plugins location - // to load assets from. - builder.Services.AddSingleton(f => - { - IWebHostEnvironment hostEnv = f.GetRequiredService(); - - return new SmidgeFileProvider( - hostEnv.WebRootFileProvider, - new GlobPatternFilterFileProvider( - hostEnv.ContentRootFileProvider, - // only include js or css files within App_Plugins - new[] { "/App_Plugins/**/*.js", "/App_Plugins/**/*.css" })); - }); - - builder.Services.AddUnique(); - builder.Services.AddSmidge(builder.Config.GetSection(Constants.Configuration.ConfigRuntimeMinification)); - - // Replace the Smidge request helper, in order to discourage the use of brotli since it's super slow - builder.Services.AddUnique(); - builder.Services.AddSmidgeNuglify(); - builder.Services.AddSmidgeInMemory(false); // it will be enabled based on config/cachebuster - - builder.Services.AddUnique(); - builder.Services.AddSingleton(); - builder.Services.AddTransient(); - builder.Services.ConfigureOptions(); - - return builder; - } - /// /// Adds all web based services required for Umbraco to run /// @@ -309,10 +266,6 @@ public static partial class UmbracoBuilderExtensions builder.Services.AddApiVersioning().AddApiExplorer(); builder.Services.ConfigureOptions(); builder.Services.ConfigureOptions(); - builder.Services.TryAddEnumerable(ServiceDescriptor - .Transient()); - builder.Services.TryAddEnumerable(ServiceDescriptor - .Transient()); builder.Services.TryAddEnumerable(ServiceDescriptor .Transient()); @@ -368,8 +321,6 @@ public static partial class UmbracoBuilderExtensions builder.Services.AddSingleton(); builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddUnique(); builder.Services.AddUnique(); diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoApplicationBuilder.RuntimeMinification.cs b/src/Umbraco.Web.Common/Extensions/UmbracoApplicationBuilder.RuntimeMinification.cs deleted file mode 100644 index 1dcb73dd5d..0000000000 --- a/src/Umbraco.Web.Common/Extensions/UmbracoApplicationBuilder.RuntimeMinification.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Smidge; -using Smidge.Nuglify; -using Umbraco.Cms.Web.Common.ApplicationBuilder; - -namespace Umbraco.Extensions; - -public static partial class UmbracoApplicationBuilderExtensions -{ - /// - /// Enables runtime minification for Umbraco - /// - public static IUmbracoEndpointBuilderContext UseUmbracoRuntimeMinificationEndpoints( - this IUmbracoEndpointBuilderContext app) - { - if (app == null) - { - throw new ArgumentNullException(nameof(app)); - } - - if (!app.RuntimeState.UmbracoCanBoot()) - { - return app; - } - - app.AppBuilder.UseSmidge(); - app.AppBuilder.UseSmidgeNuglify(); - - return app; - } -} diff --git a/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs b/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs index 972dc67e19..aacf8582b2 100644 --- a/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs @@ -14,7 +14,6 @@ using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PropertyEditors.ValueConverters; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Core.Web.Mvc; -using Umbraco.Cms.Core.WebAssets; using Umbraco.Cms.Web.Common.Controllers; using Umbraco.Cms.Web.Common.Security; @@ -244,19 +243,18 @@ public static class UrlHelperExtensions string controllerName, RouteValueDictionary routeVals, IHostingEnvironment hostingEnvironment, - IUmbracoVersion umbracoVersion, - IRuntimeMinifier runtimeMinifier) + IUmbracoVersion umbracoVersion) { var applicationJs = url.Action(actionName, controllerName, routeVals); applicationJs = applicationJs + "?umb__rnd=" + - GetCacheBustHash(hostingEnvironment, umbracoVersion, runtimeMinifier); + GetCacheBustHash(hostingEnvironment, umbracoVersion); return applicationJs; } /// /// /// - public static string GetCacheBustHash(IHostingEnvironment hostingEnvironment, IUmbracoVersion umbracoVersion, IRuntimeMinifier runtimeMinifier) + public static string GetCacheBustHash(IHostingEnvironment hostingEnvironment, IUmbracoVersion umbracoVersion) { // make a hash of umbraco and client dependency version // in case the user bypasses the installer and just bumps the web.config or client dependency config @@ -268,7 +266,7 @@ public static class UrlHelperExtensions } var version = umbracoVersion.SemanticVersion.ToSemanticString(); - return $"{version}.{runtimeMinifier.CacheBuster}".GenerateHash(); + return $"{version}".GenerateHash(); } public static IHtmlContent GetCropUrl(this IUrlHelper urlHelper, IPublishedContent? mediaItem, string cropAlias, bool htmlEncode = true, UrlMode urlMode = UrlMode.Default) diff --git a/src/Umbraco.Web.Common/Filters/AllowHttpJsonConfigrationAttribute.cs b/src/Umbraco.Web.Common/Filters/AllowHttpJsonConfigrationAttribute.cs deleted file mode 100644 index 1809267edd..0000000000 --- a/src/Umbraco.Web.Common/Filters/AllowHttpJsonConfigrationAttribute.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Umbraco.Cms.Web.Common.Formatters; - -namespace Umbraco.Cms.Web.Common.Filters; - -public class AllowHttpJsonConfigrationAttribute : TypeFilterAttribute -{ - /// - /// This filter overwrites AngularJsonOnlyConfigurationAttribute and get the api back to its defualt behavior - /// - public AllowHttpJsonConfigrationAttribute() - : base(typeof(AllowJsonXHRConfigrationFilter)) => - Order = 2; // this value must be more than the AngularJsonOnlyConfigurationAttribute on order to overwrtie it - - private class AllowJsonXHRConfigrationFilter : IResultFilter - { - public void OnResultExecuted(ResultExecutedContext context) - { - } - - public void OnResultExecuting(ResultExecutingContext context) - { - if (context.Result is ObjectResult objectResult) - { - objectResult.Formatters.RemoveType(); - } - } - } -} diff --git a/src/Umbraco.Web.Common/Filters/AngularJsonOnlyConfigurationAttribute.cs b/src/Umbraco.Web.Common/Filters/AngularJsonOnlyConfigurationAttribute.cs deleted file mode 100644 index ee73649bb2..0000000000 --- a/src/Umbraco.Web.Common/Filters/AngularJsonOnlyConfigurationAttribute.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Buffers; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Newtonsoft.Json.Serialization; -using Umbraco.Cms.Web.Common.Formatters; - -namespace Umbraco.Cms.Web.Common.Filters; - -/// -/// Applying this attribute to any controller will ensure that it only contains one json formatter compatible with the -/// angular json vulnerability prevention. -/// -public class AngularJsonOnlyConfigurationAttribute : TypeFilterAttribute -{ - public AngularJsonOnlyConfigurationAttribute() - : base(typeof(AngularJsonOnlyConfigurationFilter)) => - Order = 1; // Must be low, to be overridden by other custom formatters, but higher then all framework stuff. - - private class AngularJsonOnlyConfigurationFilter : IResultFilter - { - private readonly ArrayPool _arrayPool; - private readonly MvcOptions _options; - - public AngularJsonOnlyConfigurationFilter(ArrayPool arrayPool, IOptionsSnapshot options) - { - _arrayPool = arrayPool; - _options = options.Value; - } - - public void OnResultExecuted(ResultExecutedContext context) - { - } - - public void OnResultExecuting(ResultExecutingContext context) - { - if (context.Result is ObjectResult objectResult) - { - var serializerSettings = new JsonSerializerSettings - { - ContractResolver = new DefaultContractResolver(), - Converters = { new VersionConverter() }, - }; - - objectResult.Formatters.Clear(); - objectResult.Formatters.Add( - new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options)); - } - } - } -} diff --git a/src/Umbraco.Web.Common/Filters/JsonDateTimeFormatAttribute.cs b/src/Umbraco.Web.Common/Filters/JsonDateTimeFormatAttribute.cs deleted file mode 100644 index 7e1b08e0e4..0000000000 --- a/src/Umbraco.Web.Common/Filters/JsonDateTimeFormatAttribute.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Buffers; -using System.Globalization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Umbraco.Cms.Web.Common.Formatters; - -namespace Umbraco.Cms.Web.Common.Filters; - -/// -/// Applying this attribute to any controller will ensure that it only contains one json formatter compatible with the angular json vulnerability prevention. -/// -public sealed class JsonDateTimeFormatAttribute : TypeFilterAttribute -{ - /// - /// Initializes a new instance of the class. - /// - public JsonDateTimeFormatAttribute() - : base(typeof(JsonDateTimeFormatFilter)) => - Order = 2; // must be higher than AngularJsonOnlyConfigurationAttribute.Order - - private class JsonDateTimeFormatFilter : IResultFilter - { - private readonly ArrayPool _arrayPool; - private readonly string _format = "yyyy-MM-ddTHH:mm:ss"; - private readonly MvcOptions _options; - - public JsonDateTimeFormatFilter(ArrayPool arrayPool, IOptionsSnapshot options) - { - _arrayPool = arrayPool; - _options = options.Value; - } - - public void OnResultExecuted(ResultExecutedContext context) - { - } - - public void OnResultExecuting(ResultExecutingContext context) - { - if (context.Result is ObjectResult objectResult) - { - var serializerSettings = new JsonSerializerSettings(); - serializerSettings.Converters.Add( - new IsoDateTimeConverter { DateTimeFormat = _format, Culture = CultureInfo.InvariantCulture }); - objectResult.Formatters.Clear(); - objectResult.Formatters.Add( - new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options)); - } - } - } -} diff --git a/src/Umbraco.Web.Common/Filters/JsonExceptionFilterAttribute.cs b/src/Umbraco.Web.Common/Filters/JsonExceptionFilterAttribute.cs deleted file mode 100644 index 90135a92c3..0000000000 --- a/src/Umbraco.Web.Common/Filters/JsonExceptionFilterAttribute.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Net; -using System.Net.Mime; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Newtonsoft.Json; -using Umbraco.Cms.Core.Hosting; - -namespace Umbraco.Cms.Web.Common.Filters; - -public class JsonExceptionFilterAttribute : TypeFilterAttribute -{ - public JsonExceptionFilterAttribute() - : base(typeof(JsonExceptionFilter)) - { - } - - private class JsonExceptionFilter : IExceptionFilter - { - private readonly IHostingEnvironment _hostingEnvironment; - - public JsonExceptionFilter(IHostingEnvironment hostingEnvironment) => _hostingEnvironment = hostingEnvironment; - - public void OnException(ExceptionContext filterContext) - { - if (!filterContext.ExceptionHandled) - { - filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; - - filterContext.Result = new ContentResult - { - StatusCode = (int)HttpStatusCode.InternalServerError, - ContentType = MediaTypeNames.Application.Json, - Content = JsonConvert.SerializeObject( - GetModel(filterContext.Exception), - new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }), - }; - filterContext.ExceptionHandled = true; - } - } - - private object GetModel(Exception ex) - { - var error = new ExceptionViewModel { ExceptionMessage = ex.Message }; - - if (_hostingEnvironment.IsDebugMode) - { - error.ExceptionType = ex.GetType(); - error.StackTrace = ex.StackTrace; - } - - return error; - } - } -} diff --git a/src/Umbraco.Web.Common/Filters/OutgoingNoHyphenGuidFormatAttribute.cs b/src/Umbraco.Web.Common/Filters/OutgoingNoHyphenGuidFormatAttribute.cs deleted file mode 100644 index 0ecb3929d5..0000000000 --- a/src/Umbraco.Web.Common/Filters/OutgoingNoHyphenGuidFormatAttribute.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Buffers; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using Umbraco.Cms.Core; -using Umbraco.Cms.Web.Common.Formatters; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Web.Common.Filters; - -public class OutgoingNoHyphenGuidFormatAttribute : TypeFilterAttribute -{ - public OutgoingNoHyphenGuidFormatAttribute() - : base(typeof(OutgoingNoHyphenGuidFormatFilter)) => - Order = 2; // must be higher than AngularJsonOnlyConfigurationAttribute.Order - - private class OutgoingNoHyphenGuidFormatFilter : IResultFilter - { - private readonly ArrayPool _arrayPool; - private readonly MvcOptions _options; - - public OutgoingNoHyphenGuidFormatFilter(ArrayPool arrayPool, IOptionsSnapshot options) - { - _arrayPool = arrayPool; - _options = options.Value; - } - - public void OnResultExecuted(ResultExecutedContext context) - { - } - - public void OnResultExecuting(ResultExecutingContext context) - { - if (context.Result is ObjectResult objectResult) - { - var serializerSettings = new JsonSerializerSettings(); - serializerSettings.Converters.Add(new GuidNoHyphenConverter()); - - objectResult.Formatters.Clear(); - objectResult.Formatters.Add( - new AngularJsonMediaTypeFormatter(serializerSettings, _arrayPool, _options)); - } - } - - /// - /// A custom converter for GUID's to format without hyphens - /// - private class GuidNoHyphenConverter : JsonConverter - { - public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - switch (reader.TokenType) - { - case JsonToken.Null: - return Guid.Empty; - case JsonToken.String: - Attempt guidAttempt = reader.Value.TryConvertTo(); - if (guidAttempt.Success) - { - return guidAttempt.Result; - } - - throw new FormatException("Could not convert " + reader.Value + " to a GUID"); - default: - throw new ArgumentException("Invalid token type"); - } - } - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) => - writer.WriteValue(Guid.Empty.Equals(value) ? Guid.Empty.ToString("N") : ((Guid?)value)?.ToString("N")); - - public override bool CanConvert(Type objectType) => typeof(Guid) == objectType; - } - } -} diff --git a/src/Umbraco.Web.Common/Formatters/AngularJsonMediaTypeFormatter.cs b/src/Umbraco.Web.Common/Formatters/AngularJsonMediaTypeFormatter.cs deleted file mode 100644 index cea63d516a..0000000000 --- a/src/Umbraco.Web.Common/Formatters/AngularJsonMediaTypeFormatter.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Buffers; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Formatters; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Umbraco.Cms.Infrastructure.Serialization; - -namespace Umbraco.Cms.Web.Common.Formatters; - -/// -/// This will format the JSON output for use with AngularJs's approach to JSON Vulnerability attacks -/// -/// -/// See: http://docs.angularjs.org/api/ng.$http (Security considerations) -/// -public class AngularJsonMediaTypeFormatter : NewtonsoftJsonOutputFormatter -{ - public const string XsrfPrefix = ")]}',\n"; - - public AngularJsonMediaTypeFormatter(JsonSerializerSettings serializerSettings, ArrayPool charPool, MvcOptions mvcOptions) - : base(RegisterJsonConverters(serializerSettings), charPool, mvcOptions) - { - } - - protected static JsonSerializerSettings RegisterJsonConverters(JsonSerializerSettings serializerSettings) - { - serializerSettings.Converters.Add(new StringEnumConverter()); - serializerSettings.Converters.Add(new UdiJsonConverter()); - - return serializerSettings; - } - - protected override JsonWriter CreateJsonWriter(TextWriter writer) - { - JsonWriter jsonWriter = base.CreateJsonWriter(writer); - - jsonWriter.WriteRaw(XsrfPrefix); - - return jsonWriter; - } -} diff --git a/src/Umbraco.Web.Common/Formatters/IgnoreRequiredAttributesResolver.cs b/src/Umbraco.Web.Common/Formatters/IgnoreRequiredAttributesResolver.cs deleted file mode 100644 index cee92be436..0000000000 --- a/src/Umbraco.Web.Common/Formatters/IgnoreRequiredAttributesResolver.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Reflection; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; - -namespace Umbraco.Cms.Web.Common.Formatters; - -public class IgnoreRequiredAttributesResolver : DefaultContractResolver -{ - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - JsonProperty property = base.CreateProperty(member, memberSerialization); - - property.Required = Required.Default; - - return property; - } -} diff --git a/src/Umbraco.Web.Common/Hosting/UmbracoBackOfficePathGenerator.cs b/src/Umbraco.Web.Common/Hosting/UmbracoBackOfficePathGenerator.cs index cff31ddc91..8928f986c7 100644 --- a/src/Umbraco.Web.Common/Hosting/UmbracoBackOfficePathGenerator.cs +++ b/src/Umbraco.Web.Common/Hosting/UmbracoBackOfficePathGenerator.cs @@ -2,7 +2,6 @@ using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Hosting; -using Umbraco.Cms.Core.WebAssets; using Umbraco.Extensions; namespace Umbraco.Cms.Web.Common.Hosting; @@ -16,11 +15,10 @@ public class UmbracoBackOfficePathGenerator : IBackOfficePathGenerator public UmbracoBackOfficePathGenerator( IHostingEnvironment hostingEnvironment, IUmbracoVersion umbracoVersion, - IRuntimeMinifier runtimeMinifier, IOptions globalSettings) { BackOfficePath = globalSettings.Value.GetBackOfficePath(hostingEnvironment); - BackOfficeCacheBustHash = UrlHelperExtensions.GetCacheBustHash(hostingEnvironment, umbracoVersion, runtimeMinifier); + BackOfficeCacheBustHash = UrlHelperExtensions.GetCacheBustHash(hostingEnvironment, umbracoVersion); } /// diff --git a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs index 4783e9d3db..a796e26ec2 100644 --- a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs +++ b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs @@ -3,21 +3,17 @@ using Microsoft.AspNetCore.Http.Extensions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Smidge.Options; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Cache; -using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Notifications; using Umbraco.Cms.Core.PublishedCache; -using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; -using Umbraco.Cms.Infrastructure.WebAssets; using Umbraco.Cms.Web.Common.Profiler; using Umbraco.Cms.Web.Common.Routing; using Umbraco.Extensions; @@ -35,9 +31,8 @@ namespace Umbraco.Cms.Web.Common.Middleware; /// This is responsible for creating and assigning an /// /// -public class UmbracoRequestMiddleware : IMiddleware +internal class UmbracoRequestMiddleware : IMiddleware { - private readonly BackOfficeWebAssets _backOfficeWebAssets; private readonly IDefaultCultureAccessor _defaultCultureAccessor; private readonly IEventAggregator _eventAggregator; private readonly IHostingEnvironment _hostingEnvironment; @@ -48,9 +43,7 @@ public class UmbracoRequestMiddleware : IMiddleware private readonly IUmbracoContextFactory _umbracoContextFactory; private readonly IOptions _umbracoRequestOptions; - private readonly UmbracoRequestPaths _umbracoRequestPaths; private readonly IVariationContextAccessor _variationContextAccessor; - private SmidgeOptions _smidgeOptions; /// /// Initializes a new instance of the class. @@ -62,9 +55,6 @@ public class UmbracoRequestMiddleware : IMiddleware IEventAggregator eventAggregator, IProfiler profiler, IHostingEnvironment hostingEnvironment, - UmbracoRequestPaths umbracoRequestPaths, - BackOfficeWebAssets backOfficeWebAssets, - IOptionsMonitor smidgeOptions, IRuntimeState runtimeState, IVariationContextAccessor variationContextAccessor, IDefaultCultureAccessor defaultCultureAccessor, @@ -75,16 +65,11 @@ public class UmbracoRequestMiddleware : IMiddleware _requestCache = requestCache; _eventAggregator = eventAggregator; _hostingEnvironment = hostingEnvironment; - _umbracoRequestPaths = umbracoRequestPaths; - _backOfficeWebAssets = backOfficeWebAssets; _runtimeState = runtimeState; _variationContextAccessor = variationContextAccessor; _defaultCultureAccessor = defaultCultureAccessor; _umbracoRequestOptions = umbracoRequestOptions; - _smidgeOptions = smidgeOptions.CurrentValue; _profiler = profiler as WebProfiler; // Ignore if not a WebProfiler - - smidgeOptions.OnChange(x => _smidgeOptions = x); } /// @@ -95,7 +80,6 @@ public class UmbracoRequestMiddleware : IMiddleware !_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); await next(context); return; } @@ -123,7 +107,6 @@ public class UmbracoRequestMiddleware : IMiddleware try { - LazyInitializeBackOfficeServices(context.Request.Path); await _eventAggregator.PublishAsync( new UmbracoRequestBeginNotification(umbracoContextReference.UmbracoContext)); } @@ -175,30 +158,6 @@ public class UmbracoRequestMiddleware : IMiddleware _profiler?.UmbracoApplicationEndRequest(context, _runtimeState.Level); } - /// - /// Used to lazily initialize any back office services when the first request to the back office is made - /// - private void LazyInitializeBackOfficeServices(PathString absPath) - { - if (s_firstBackOfficeRequest) - { - return; - } - - if (_umbracoRequestPaths.IsBackOfficeRequest(absPath) - || (absPath.Value?.InvariantStartsWith($"/{_smidgeOptions.UrlOptions.CompositeFilePath}") ?? false) - || (absPath.Value?.InvariantStartsWith($"/{_smidgeOptions.UrlOptions.BundleFilePath}") ?? false) - || _runtimeState.EnableInstaller()) - { - LazyInitializer.EnsureInitialized(ref s_firstBackOfficeRequest, ref s_firstBackOfficeReqestFlag, - ref s_firstBackOfficeRequestLocker, () => - { - _backOfficeWebAssets.CreateBundles(); - return true; - }); - } - } - private Uri? GetApplicationUrlFromCurrentRequest(HttpRequest request) { // We only consider GET and POST. @@ -231,6 +190,5 @@ public class UmbracoRequestMiddleware : IMiddleware #pragma warning disable IDE0044 // Add readonly modifier private static bool s_firstBackOfficeRequest; private static bool s_firstBackOfficeReqestFlag; - private static object s_firstBackOfficeRequestLocker = new(); #pragma warning restore IDE0044 // Add readonly modifier } diff --git a/src/Umbraco.Web.Common/ModelBinders/UmbracoJsonModelBinder.cs b/src/Umbraco.Web.Common/ModelBinders/UmbracoJsonModelBinder.cs deleted file mode 100644 index 6372930898..0000000000 --- a/src/Umbraco.Web.Common/ModelBinders/UmbracoJsonModelBinder.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Buffers; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Formatters; -using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.ObjectPool; -using Newtonsoft.Json; -using Umbraco.Cms.Web.Common.Formatters; - -namespace Umbraco.Cms.Web.Common.ModelBinders; - -/// -/// A custom body model binder that only uses a to bind body action -/// parameters -/// -public class UmbracoJsonModelBinder : BodyModelBinder -{ - public UmbracoJsonModelBinder( - ArrayPool arrayPool, - ObjectPoolProvider objectPoolProvider, - IHttpRequestStreamReaderFactory readerFactory, - ILoggerFactory loggerFactory) - : base(GetNewtonsoftJsonFormatter(loggerFactory, arrayPool, objectPoolProvider), readerFactory, loggerFactory) - { - } - - private static IInputFormatter[] GetNewtonsoftJsonFormatter(ILoggerFactory logger, ArrayPool arrayPool, ObjectPoolProvider objectPoolProvider) - { - var jsonOptions = new MvcNewtonsoftJsonOptions { AllowInputFormatterExceptionMessages = true }; - - JsonSerializerSettings ss = jsonOptions.SerializerSettings; // Just use the defaults as base - - // We need to ignore required attributes when serializing. E.g UserSave.ChangePassword. Otherwise the model is not model bound. - ss.ContractResolver = new IgnoreRequiredAttributesResolver(); - return new IInputFormatter[] - { - new NewtonsoftJsonInputFormatter( - logger.CreateLogger(), - jsonOptions.SerializerSettings, // Just use the defaults - arrayPool, - objectPoolProvider, - new MvcOptions(), // The only option that NewtonsoftJsonInputFormatter uses is SuppressInputFormatterBuffering - jsonOptions), - }; - } -} diff --git a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeHelperAccessor.cs b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeHelperAccessor.cs deleted file mode 100644 index 299be83eae..0000000000 --- a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeHelperAccessor.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Smidge; - -namespace Umbraco.Cms.Web.Common.RuntimeMinification; - -// work around for SmidgeHelper being request/scope lifetime -public sealed class SmidgeHelperAccessor -{ - private readonly IHttpContextAccessor _httpContextAccessor; - - public SmidgeHelperAccessor(IHttpContextAccessor httpContextAccessor) => _httpContextAccessor = httpContextAccessor; - - public SmidgeHelper SmidgeHelper - { - get - { - HttpContext? httpContext = _httpContextAccessor.HttpContext; - if (httpContext == null) - { - throw new InvalidOperationException( - $"Cannot get a {nameof(SmidgeHelper)} instance since there is no current http request"); - } - - return httpContext.RequestServices.GetService()!; - } - } -} diff --git a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeNuglifyJs.cs b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeNuglifyJs.cs deleted file mode 100644 index e10ae0790b..0000000000 --- a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeNuglifyJs.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NUglify.JavaScript; -using Smidge; -using Smidge.Nuglify; - -namespace Umbraco.Cms.Web.Common.RuntimeMinification; - -/// -/// Custom Nuglify Js pre-process to specify custom nuglify options without changing the global defaults -/// -public class SmidgeNuglifyJs : NuglifyJs -{ - public SmidgeNuglifyJs(NuglifySettings settings, ISourceMapDeclaration sourceMapDeclaration, IRequestHelper requestHelper) - : base(GetSettings(settings), sourceMapDeclaration, requestHelper) - { - } - - private static NuglifySettings GetSettings(NuglifySettings defaultSettings) - { - CodeSettings? nuglifyCodeSettings = defaultSettings.JsCodeSettings.CodeSettings.Clone(); - - // Don't rename locals, this will kill a lot of angular stuff because we aren't correctly coding our - // angular injection to handle minification correctly which requires declaring string named versions of all - // dependencies injected (which is a pain). So we just turn this option off. - nuglifyCodeSettings.LocalRenaming = LocalRenaming.KeepAll; - nuglifyCodeSettings.PreserveFunctionNames = true; - - return new NuglifySettings(new NuglifyCodeSettings(nuglifyCodeSettings), defaultSettings.CssCodeSettings); - } -} diff --git a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeOptionsSetup.cs b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeOptionsSetup.cs deleted file mode 100644 index 37701928c6..0000000000 --- a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeOptionsSetup.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.Extensions.Options; -using Smidge.Options; -using Umbraco.Cms.Core.Configuration.Models; - -namespace Umbraco.Cms.Web.Common.RuntimeMinification; - -public class SmidgeOptionsSetup : IConfigureOptions -{ - private readonly IOptions _runtimeMinificatinoSettings; - - public SmidgeOptionsSetup(IOptions runtimeMinificatinoSettings) - => _runtimeMinificatinoSettings = runtimeMinificatinoSettings; - - /// - /// Configures Smidge to use in-memory caching if configured that way or if certain cache busters are used - /// - /// - public void Configure(SmidgeOptions options) - => options.CacheOptions.UseInMemoryCache = _runtimeMinificatinoSettings.Value.UseInMemoryCache || - _runtimeMinificatinoSettings.Value.CacheBuster == - RuntimeMinificationCacheBuster.Timestamp; -} diff --git a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeRequestHelper.cs b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeRequestHelper.cs deleted file mode 100644 index dd055a10c5..0000000000 --- a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeRequestHelper.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; -using Microsoft.Net.Http.Headers; -using Smidge; -using Smidge.Models; - -namespace Umbraco.Cms.Web.Common.RuntimeMinification; - -public class SmidgeRequestHelper : IRequestHelper -{ - private readonly RequestHelper _wrappedRequestHelper; - - public SmidgeRequestHelper(IWebsiteInfo siteInfo) => _wrappedRequestHelper = new RequestHelper(siteInfo); - - /// - public string Content(string path) => _wrappedRequestHelper.Content(path); - - /// - public string Content(IWebFile file) => _wrappedRequestHelper.Content(file); - - /// - public bool IsExternalRequestPath(string path) => _wrappedRequestHelper.IsExternalRequestPath(path); - - /// - /// Overrides the default order of compression from Smidge, since Brotli is super slow (~10 seconds for backoffice.js) - /// - /// - /// - public CompressionType GetClientCompression(IDictionary headers) - { - CompressionType type = CompressionType.None; - - if (headers is not IHeaderDictionary headerDictionary) - { - headerDictionary = new HeaderDictionary(headers.Count); - foreach ((var key, StringValues stringValues) in headers) - { - headerDictionary[key] = stringValues; - } - } - - var acceptEncoding = headerDictionary.GetCommaSeparatedValues(HeaderNames.AcceptEncoding); - if (acceptEncoding.Length > 0) - { - // Prefer in order: GZip, Deflate, Brotli. - for (var i = 0; i < acceptEncoding.Length; i++) - { - var encoding = acceptEncoding[i].Trim(); - - var parsed = CompressionType.Parse(encoding); - - // Not pack200-gzip. - if (parsed == CompressionType.GZip) - { - return CompressionType.GZip; - } - - if (parsed == CompressionType.Deflate) - { - type = CompressionType.Deflate; - } - - // Brotli is typically last in the accept encoding header. - if (type != CompressionType.Deflate && parsed == CompressionType.Brotli) - { - type = CompressionType.Brotli; - } - } - } - - return type; - } -} diff --git a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeRuntimeMinifier.cs b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeRuntimeMinifier.cs deleted file mode 100644 index b06f8d0688..0000000000 --- a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeRuntimeMinifier.cs +++ /dev/null @@ -1,176 +0,0 @@ -using Microsoft.Extensions.Options; -using Smidge; -using Smidge.Cache; -using Smidge.CompositeFiles; -using Smidge.FileProcessors; -using Smidge.Models; -using Smidge.Nuglify; -using Smidge.Options; -using Umbraco.Cms.Core.Configuration; -using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Cms.Core.Hosting; -using Umbraco.Cms.Core.WebAssets; -using CssFile = Smidge.Models.CssFile; -using JavaScriptFile = Smidge.Models.JavaScriptFile; - -namespace Umbraco.Cms.Web.Common.RuntimeMinification; - -public class SmidgeRuntimeMinifier : IRuntimeMinifier -{ - private readonly IBundleManager _bundles; - private readonly CacheBusterResolver _cacheBusterResolver; - private readonly Type _cacheBusterType; - private readonly IConfigManipulator _configManipulator; - private readonly Lazy _cssMinPipeline; - private readonly Lazy _cssNonOptimizedPipeline; - private readonly Lazy _cssOptimizedPipeline; - private readonly IHostingEnvironment _hostingEnvironment; - - // used only for minifying in MinifyAsync not for an actual pipeline - private readonly Lazy _jsMinPipeline; - private readonly Lazy _jsNonOptimizedPipeline; - - // default pipelines for processing js/css files for the back office - private readonly Lazy _jsOptimizedPipeline; - private readonly SmidgeHelperAccessor _smidge; - private ICacheBuster? _cacheBuster; - - public SmidgeRuntimeMinifier( - IBundleManager bundles, - SmidgeHelperAccessor smidge, - IHostingEnvironment hostingEnvironment, - IConfigManipulator configManipulator, - IOptions runtimeMinificationSettings, - CacheBusterResolver cacheBusterResolver) - { - _bundles = bundles; - _smidge = smidge; - _hostingEnvironment = hostingEnvironment; - _configManipulator = configManipulator; - _cacheBusterResolver = cacheBusterResolver; - _jsMinPipeline = new Lazy(() => _bundles.PipelineFactory.Create(typeof(JsMinifier))); - _cssMinPipeline = new Lazy(() => _bundles.PipelineFactory.Create(typeof(NuglifyCss))); - - // replace the default JsMinifier with NuglifyJs and CssMinifier with NuglifyCss in the default pipelines - // for use with our bundles only (not modifying global options) - _jsOptimizedPipeline = new Lazy(() => - bundles.PipelineFactory.DefaultJs().Replace(_bundles.PipelineFactory)); - _jsNonOptimizedPipeline = new Lazy(() => - { - PreProcessPipeline defaultJs = bundles.PipelineFactory.DefaultJs(); - - // remove minification from this pipeline - defaultJs.Processors.RemoveAll(x => x is JsMinifier); - return defaultJs; - }); - _cssOptimizedPipeline = new Lazy(() => - bundles.PipelineFactory.DefaultCss().Replace(_bundles.PipelineFactory)); - _cssNonOptimizedPipeline = new Lazy(() => - { - PreProcessPipeline defaultCss = bundles.PipelineFactory.DefaultCss(); - - // remove minification from this pipeline - defaultCss.Processors.RemoveAll(x => x is CssMinifier); - return defaultCss; - }); - - Type cacheBusterType = runtimeMinificationSettings.Value.CacheBuster switch - { - RuntimeMinificationCacheBuster.AppDomain => typeof(AppDomainLifetimeCacheBuster), - RuntimeMinificationCacheBuster.Version => typeof(UmbracoSmidgeConfigCacheBuster), - RuntimeMinificationCacheBuster.Timestamp => typeof(TimestampCacheBuster), - _ => throw new NotImplementedException(), - }; - - _cacheBusterType = cacheBusterType; - } - - public string CacheBuster => (_cacheBuster ??= _cacheBusterResolver.GetCacheBuster(_cacheBusterType)).GetValue(); - - // only issue with creating bundles like this is that we don't have full control over the bundle options, though that could - public void CreateCssBundle(string bundleName, BundlingOptions bundleOptions, params string[]? filePaths) - { - if (filePaths?.Any(f => !f.StartsWith("/") && !f.StartsWith("~/")) ?? false) - { - throw new InvalidOperationException("All file paths must be absolute"); - } - - if (_bundles.Exists(bundleName)) - { - throw new InvalidOperationException($"The bundle name {bundleName} already exists"); - } - - PreProcessPipeline pipeline = bundleOptions.OptimizeOutput - ? _cssOptimizedPipeline.Value - : _cssNonOptimizedPipeline.Value; - - Bundle bundle = _bundles.Create(bundleName, pipeline, WebFileType.Css, filePaths); - bundle.WithEnvironmentOptions(ConfigureBundleEnvironmentOptions(bundleOptions)); - } - - public async Task RenderCssHereAsync(string bundleName) => - (await _smidge.SmidgeHelper.CssHereAsync(bundleName, _hostingEnvironment.IsDebugMode)).ToString(); - - public void CreateJsBundle(string bundleName, BundlingOptions bundleOptions, params string[]? filePaths) - { - if (filePaths?.Any(f => !f.StartsWith("/") && !f.StartsWith("~/")) ?? false) - { - throw new InvalidOperationException("All file paths must be absolute"); - } - - if (_bundles.Exists(bundleName)) - { - throw new InvalidOperationException($"The bundle name {bundleName} already exists"); - } - - PreProcessPipeline pipeline = bundleOptions.OptimizeOutput - ? _jsOptimizedPipeline.Value - : _jsNonOptimizedPipeline.Value; - - Bundle bundle = _bundles.Create(bundleName, pipeline, WebFileType.Js, filePaths); - bundle.WithEnvironmentOptions(ConfigureBundleEnvironmentOptions(bundleOptions)); - } - - public async Task RenderJsHereAsync(string bundleName) => - (await _smidge.SmidgeHelper.JsHereAsync(bundleName, _hostingEnvironment.IsDebugMode)).ToString(); - - public async Task> GetJsAssetPathsAsync(string bundleName) => - await _smidge.SmidgeHelper.GenerateJsUrlsAsync(bundleName, _hostingEnvironment.IsDebugMode); - - public async Task> GetCssAssetPathsAsync(string bundleName) => - await _smidge.SmidgeHelper.GenerateCssUrlsAsync(bundleName, _hostingEnvironment.IsDebugMode); - - /// - public async Task MinifyAsync(string? fileContent, AssetType assetType) - { - switch (assetType) - { - case AssetType.Javascript: - return await _jsMinPipeline.Value - .ProcessAsync( - new FileProcessContext(fileContent, new JavaScriptFile(), BundleContext.CreateEmpty(CacheBuster))); - case AssetType.Css: - return await _cssMinPipeline.Value - .ProcessAsync(new FileProcessContext(fileContent, new CssFile(), BundleContext.CreateEmpty(CacheBuster))); - default: - throw new NotSupportedException("Unexpected AssetType"); - } - } - - private BundleEnvironmentOptions ConfigureBundleEnvironmentOptions(BundlingOptions bundleOptions) - { - var bundleEnvironmentOptions = new BundleEnvironmentOptions(); - - // auto-invalidate bundle if files change in debug - bundleEnvironmentOptions.DebugOptions.FileWatchOptions.Enabled = true; - - // set cache busters - bundleEnvironmentOptions.DebugOptions.SetCacheBusterType(_cacheBusterType); - bundleEnvironmentOptions.ProductionOptions.SetCacheBusterType(_cacheBusterType); - - // config if the files should be combined - bundleEnvironmentOptions.ProductionOptions.ProcessAsCompositeFile = bundleOptions.EnabledCompositeFiles; - - return bundleEnvironmentOptions; - } -} diff --git a/src/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBuster.cs b/src/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBuster.cs deleted file mode 100644 index c8b58f1518..0000000000 --- a/src/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBuster.cs +++ /dev/null @@ -1,81 +0,0 @@ -using Microsoft.Extensions.Options; -using Smidge; -using Smidge.Cache; -using Umbraco.Cms.Core.Configuration; -using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Web.Common.RuntimeMinification; - -/// -/// Constructs a cache buster string with sensible defaults. -/// -/// -/// -/// Had planned on handling all of this in SmidgeRuntimeMinifier, but that only handles some urls. -/// -/// -/// A lot of the work is delegated e.g. to -/// which doesn't care about the cache buster string in our classes only the value returned by the resolved -/// ICacheBuster. -/// -/// -/// Then I thought fine I'll just use a IConfigureOptions to tweak upstream , but -/// that only cares about the -/// class we instantiate and pass through in -/// -/// -/// -/// So here we are, create our own to ensure we cache bust in a reasonable fashion. -/// -///

-/// -/// Note that this class makes some other bits of code pretty redundant e.g. -/// will -/// concatenate version with CacheBuster value and hash again, but there's no real harm so can think about that -/// later. -/// -///
-internal class UmbracoSmidgeConfigCacheBuster : ICacheBuster -{ - private readonly IEntryAssemblyMetadata _entryAssemblyMetadata; - private readonly IOptions _runtimeMinificationSettings; - private readonly IUmbracoVersion _umbracoVersion; - - private string? _cacheBusterValue; - - public UmbracoSmidgeConfigCacheBuster( - IOptions runtimeMinificationSettings, - IUmbracoVersion umbracoVersion, - IEntryAssemblyMetadata entryAssemblyMetadata) - { - _runtimeMinificationSettings = runtimeMinificationSettings ?? - throw new ArgumentNullException(nameof(runtimeMinificationSettings)); - _umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion)); - _entryAssemblyMetadata = - entryAssemblyMetadata ?? throw new ArgumentNullException(nameof(entryAssemblyMetadata)); - } - - private string CacheBusterValue - { - get - { - if (_cacheBusterValue != null) - { - return _cacheBusterValue; - } - - // Assembly Name adds a bit of uniqueness across sites when version missing from config. - // Adds a bit of security through obscurity that was asked for in standup. - var prefix = _runtimeMinificationSettings.Value.Version ?? _entryAssemblyMetadata.Name; - var umbracoVersion = _umbracoVersion.SemanticVersion.ToString(); - var downstreamVersion = _entryAssemblyMetadata.InformationalVersion; - - _cacheBusterValue = $"{prefix}_{umbracoVersion}_{downstreamVersion}".GenerateHash(); - - return _cacheBusterValue; - } - } - - public string GetValue() => CacheBusterValue; -} diff --git a/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj b/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj index b0b5f2af6a..3b32a9dbab 100644 --- a/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj +++ b/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj @@ -18,8 +18,6 @@ - - diff --git a/tests/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs b/tests/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs index f074b85414..c224ad2f62 100644 --- a/tests/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/tests/Umbraco.Tests.Integration/DependencyInjection/UmbracoBuilderExtensions.cs @@ -18,7 +18,6 @@ using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Runtime; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Sync; -using Umbraco.Cms.Core.WebAssets; using Umbraco.Cms.Infrastructure.Examine; using Umbraco.Cms.Infrastructure.HostedServices; using Umbraco.Cms.Infrastructure.PublishedCache; @@ -47,8 +46,6 @@ public static class UmbracoBuilderExtensions builder.Services.AddUnique(testHelper.MainDom); builder.Services.AddUnique(); - builder.Services.AddUnique(factory => Mock.Of()); - // we don't want persisted nucache files in tests builder.Services.AddTransient(factory => new PublishedSnapshotServiceOptions { IgnoreLocalDb = true }); diff --git a/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index 6ca839ed51..eb91207293 100644 --- a/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/tests/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -249,7 +249,6 @@ namespace Umbraco.Cms.Tests.Integration.TestServerTest .AddUmbracoCore() .AddWebComponents() .AddNuCache() - .AddRuntimeMinifier() .AddBackOfficeCore() .AddBackOfficeAuthentication() .AddBackOfficeIdentity() diff --git a/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index 3c30673414..664fdb5493 100644 --- a/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -150,7 +150,6 @@ public abstract class UmbracoIntegrationTest : UmbracoIntegrationTestBase builder.AddConfiguration() .AddUmbracoCore() .AddWebComponents() - .AddRuntimeMinifier() .AddBackOfficeAuthentication() .AddBackOfficeIdentity() .AddMembersIdentity() diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/UdiTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/UdiTests.cs index 30a8d6a1fa..c5f2b4d1bf 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/UdiTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/UdiTests.cs @@ -227,32 +227,6 @@ public class UdiTests } - [Test] - public void SerializationTest() - { - var settings = new JsonSerializerSettings - { - Converters = new JsonConverter[] { new UdiJsonConverter(), new UdiRangeJsonConverter() }, - }; - - var guid = Guid.NewGuid(); - var udi = new GuidUdi(Constants.UdiEntityType.AnyGuid, guid); - var json = JsonConvert.SerializeObject(udi, settings); - Assert.AreEqual(string.Format("\"umb://any-guid/{0:N}\"", guid), json); - - var dudi = JsonConvert.DeserializeObject(json, settings); - Assert.AreEqual(Constants.UdiEntityType.AnyGuid, dudi.EntityType); - Assert.AreEqual(guid, ((GuidUdi)dudi).Guid); - - var range = new UdiRange(udi, Constants.DeploySelector.ChildrenOfThis); - json = JsonConvert.SerializeObject(range, settings); - Assert.AreEqual(string.Format("\"umb://any-guid/{0:N}?children\"", guid), json); - - var drange = JsonConvert.DeserializeObject(json, settings); - Assert.AreEqual(udi, drange.Udi); - Assert.AreEqual(string.Format("umb://any-guid/{0:N}", guid), drange.Udi.UriValue.ToString()); - Assert.AreEqual(Constants.DeploySelector.ChildrenOfThis, drange.Selector); - } [Test] public void ValidateUdiEntityType() diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/AngularIntegration/JsInitializationTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/AngularIntegration/JsInitializationTests.cs deleted file mode 100644 index 123195df7a..0000000000 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/AngularIntegration/JsInitializationTests.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using NUnit.Framework; -using Umbraco.Cms.Infrastructure.WebAssets; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.AngularIntegration; - -[TestFixture] -public class JsInitializationTests -{ - [Test] - public void Parse_Main() - { - var result = BackOfficeJavaScriptInitializer.WriteScript("[World]", "Hello", "Blah"); - - Assert.AreEqual( - @"LazyLoad.js([World], function () { - //we need to set the legacy UmbClientMgr path - if ((typeof UmbClientMgr) !== ""undefined"") { - UmbClientMgr.setUmbracoPath('Hello'); - } - - jQuery(document).ready(function () { - - angular.bootstrap(document, ['Blah']); - - }); -});".StripWhitespace(), - result.StripWhitespace()); - } -} diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Formatters/IgnoreRequiredAttributesResolverUnitTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Formatters/IgnoreRequiredAttributesResolverUnitTests.cs deleted file mode 100644 index 72a2a27031..0000000000 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Formatters/IgnoreRequiredAttributesResolverUnitTests.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using System.Runtime.Serialization; -using Newtonsoft.Json; -using NUnit.Framework; -using Umbraco.Cms.Web.Common.Formatters; - -namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Formatters; - -[TestFixture] -public class IgnoreRequiredAttributesResolverUnitTests -{ - [Test] - public void Test() - { - const string emptyJsonObject = "{}"; - - Assert.Multiple(() => - { - // Ensure the deserialization throws if using default settings - Assert.Throws(() => - JsonConvert.DeserializeObject(emptyJsonObject)); - - var actual = JsonConvert.DeserializeObject( - emptyJsonObject, - new JsonSerializerSettings { ContractResolver = new IgnoreRequiredAttributesResolver() }); - - Assert.IsNotNull(actual); - Assert.IsNull(actual.Property); - }); - } - - [DataContract(Name = "objectWithRequiredProperty", Namespace = "")] - private class ObjectWithRequiredProperty - { - [DataMember(Name = "property", IsRequired = true)] - public string Property { get; set; } - } -} diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBusterTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBusterTests.cs deleted file mode 100644 index 8615ac6a30..0000000000 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/RuntimeMinification/UmbracoSmidgeConfigCacheBusterTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -using AutoFixture; -using AutoFixture.AutoMoq; -using Microsoft.Extensions.Options; -using Moq; -using NUnit.Framework; -using Umbraco.Cms.Core.Configuration; -using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Cms.Core.Semver; -using Umbraco.Cms.Web.Common.RuntimeMinification; -using Umbraco.Extensions; - -namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.RuntimeMinification; - -/// -/// UmbracoCustomizations kindly configures an IUmbracoVersion so we need to go verbose without AutoMoqData -/// -[TestFixture] -public class UmbracoSmidgeConfigCacheBusterTests -{ - [Test] - public void GetValue_DefaultReleaseSetupWithNoConfiguredVersion_HasSensibleDefaults() - { - var fixture = new Fixture(); - fixture.Customize(new AutoMoqCustomization()); - - var umbracoVersion = fixture.Freeze>(); - var entryAssemblyMetadata = fixture.Freeze>(); - var sut = fixture.Create(); - - umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 4, 5, "beta", "41658f99")); - entryAssemblyMetadata.Setup(x => x.Name).Returns("Bills.Brilliant.Bakery"); - entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.1.2-alpha+41658f99"); - - var result = sut.GetValue(); - - var expected = "Bills.Brilliant.Bakery_9.4.5-beta+41658f99_42.1.2-alpha+41658f99".GenerateHash(); - Assert.AreEqual(expected, result); - } - - [Test] - public void GetValue_DefaultReleaseSetupWithConfiguredVersion_HasSensibleDefaults() - { - var config = Options.Create(new RuntimeMinificationSettings { Version = "1" }); - var fixture = new Fixture(); - fixture.Customize(new AutoMoqCustomization()); - fixture.Inject(config); - - var umbracoVersion = fixture.Freeze>(); - var entryAssemblyMetadata = fixture.Freeze>(); - var sut = fixture.Create(); - - umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 4, 5, "beta", "41658f99")); - entryAssemblyMetadata.Setup(x => x.Name).Returns("Bills.Brilliant.Bakery"); - entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.1.2-alpha+41658f99"); - - var result = sut.GetValue(); - - var expected = "1_9.4.5-beta+41658f99_42.1.2-alpha+41658f99".GenerateHash(); - Assert.AreEqual(expected, result); - } - - [Test] - public void GetValue_DefaultReleaseSetupWithNoConfiguredVersion_ChangesWhenUmbracoVersionChanges() - { - var fixture = new Fixture(); - fixture.Customize(new AutoMoqCustomization()); - - var umbracoVersion = fixture.Freeze>(); - var entryAssemblyMetadata = fixture.Freeze>(); - var sut = fixture.Create(); - - umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 4, 5, "beta", "41658f99")); - entryAssemblyMetadata.Setup(x => x.Name).Returns("Bills.Brilliant.Bakery"); - entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.1.2-alpha+41658f99"); - - var before = sut.GetValue(); - - umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 5, 0, "beta", "41658f99")); - sut = fixture.Create(); - - var after = sut.GetValue(); - - Assert.AreNotEqual(before, after); - } - - [Test] - public void GetValue_DefaultReleaseSetupWithNoConfiguredVersion_ChangesWhenDownstreamVersionChanges() - { - var fixture = new Fixture(); - fixture.Customize(new AutoMoqCustomization()); - - var umbracoVersion = fixture.Freeze>(); - var entryAssemblyMetadata = fixture.Freeze>(); - var sut = fixture.Create(); - - umbracoVersion.Setup(x => x.SemanticVersion).Returns(new SemVersion(9, 4, 5, "beta", "41658f99")); - entryAssemblyMetadata.Setup(x => x.Name).Returns("Bills.Brilliant.Bakery"); - entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.1.2-alpha+41658f99"); - - var before = sut.GetValue(); - - entryAssemblyMetadata.Setup(x => x.InformationalVersion).Returns("42.2.0-rc"); - sut = fixture.Create(); - - var after = sut.GetValue(); - - Assert.AreNotEqual(before, after); - } -}