diff --git a/src/Umbraco.Core/Builder/IUmbracoBuilder.cs b/src/Umbraco.Core/Builder/IUmbracoBuilder.cs new file mode 100644 index 0000000000..4659be55f1 --- /dev/null +++ b/src/Umbraco.Core/Builder/IUmbracoBuilder.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Umbraco.Core.Composing; + +namespace Umbraco.Core.Builder +{ + public interface IUmbracoBuilder + { + IServiceCollection Services { get; } + IConfiguration Config { get; } + TypeLoader TypeLoader { get; } + ILoggerFactory BuilderLoggerFactory { get; } + TBuilder WithCollectionBuilder() where TBuilder : ICollectionBuilder, new(); + void Build(); + } +} diff --git a/src/Umbraco.Core/Builder/UmbracoBuilder.cs b/src/Umbraco.Core/Builder/UmbracoBuilder.cs new file mode 100644 index 0000000000..9514b0de59 --- /dev/null +++ b/src/Umbraco.Core/Builder/UmbracoBuilder.cs @@ -0,0 +1,59 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Umbraco.Core.Builder; +using Umbraco.Core.Composing; + +namespace Umbraco.Web.Common.Builder +{ + public class UmbracoBuilder : IUmbracoBuilder + { + public IServiceCollection Services { get; } + public IConfiguration Config { get; } + public TypeLoader TypeLoader { get; } + public ILoggerFactory BuilderLoggerFactory { get; } + + private readonly Dictionary _builders = new Dictionary(); + + public UmbracoBuilder(IServiceCollection services, IConfiguration config, TypeLoader typeLoader) + : this(services, config, typeLoader, NullLoggerFactory.Instance) + { } + + public UmbracoBuilder(IServiceCollection services, IConfiguration config, TypeLoader typeLoader, ILoggerFactory loggerFactory) + { + Services = services; + Config = config; + BuilderLoggerFactory = loggerFactory; + TypeLoader = typeLoader; + } + + /// + /// Gets a collection builder (and registers the collection). + /// + /// The type of the collection builder. + /// The collection builder. + public TBuilder WithCollectionBuilder() + where TBuilder : ICollectionBuilder, new() + { + var typeOfBuilder = typeof(TBuilder); + + if (_builders.TryGetValue(typeOfBuilder, out var o)) + return (TBuilder)o; + + var builder = new TBuilder(); + _builders[typeOfBuilder] = builder; + return builder; + } + + public void Build() + { + foreach (var builder in _builders.Values) + builder.RegisterWith(Services); + + _builders.Clear(); + } + } +} diff --git a/src/Umbraco.Core/Cache/AppCaches.cs b/src/Umbraco.Core/Cache/AppCaches.cs index 8930320447..2d482756c1 100644 --- a/src/Umbraco.Core/Cache/AppCaches.cs +++ b/src/Umbraco.Core/Cache/AppCaches.cs @@ -64,5 +64,13 @@ namespace Umbraco.Core.Cache /// search through all keys on a global scale. /// public IsolatedCaches IsolatedCaches { get; } + + public static AppCaches Create(IRequestCache requestCache) + { + return new AppCaches( + new DeepCloneAppCache(new ObjectCacheAppCache()), + requestCache, + new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); + } } } diff --git a/src/Umbraco.Core/Composing/ComponentComposer.cs b/src/Umbraco.Core/Composing/ComponentComposer.cs index 72f9dfe5e2..8092b58c79 100644 --- a/src/Umbraco.Core/Composing/ComponentComposer.cs +++ b/src/Umbraco.Core/Composing/ComponentComposer.cs @@ -1,4 +1,6 @@  +using Umbraco.Core.Builder; + namespace Umbraco.Core.Composing { /// @@ -9,9 +11,9 @@ namespace Umbraco.Core.Composing where TComponent : IComponent { /// - public virtual void Compose(Composition composition) + public virtual void Compose(IUmbracoBuilder builder) { - composition.Components().Append(); + builder.Components().Append(); } // note: thanks to this class, a component that does not compose anything can be diff --git a/src/Umbraco.Core/Composing/Composers.cs b/src/Umbraco.Core/Composing/Composers.cs index 31c02a08fe..caef92f90a 100644 --- a/src/Umbraco.Core/Composing/Composers.cs +++ b/src/Umbraco.Core/Composing/Composers.cs @@ -6,6 +6,7 @@ using System.Text; using Umbraco.Core.Collections; using Umbraco.Core.Logging; using Microsoft.Extensions.Logging; +using Umbraco.Core.Builder; namespace Umbraco.Core.Composing { @@ -16,9 +17,8 @@ namespace Umbraco.Core.Composing /// public class Composers { - private readonly Composition _composition; + private readonly IUmbracoBuilder _builder; private readonly ILogger _logger; - private readonly IProfilingLogger _profileLogger; private readonly IEnumerable _composerTypes; private readonly IEnumerable _enableDisableAttributes; @@ -27,7 +27,7 @@ namespace Umbraco.Core.Composing /// /// Initializes a new instance of the class. /// - /// The composition. + /// The composition. /// The types. /// The and/or attributes. /// The logger. @@ -39,13 +39,12 @@ namespace Umbraco.Core.Composing /// enableDisableAttributes /// or /// logger - public Composers(Composition composition, IEnumerable composerTypes, IEnumerable enableDisableAttributes, ILogger logger, IProfilingLogger profileLogger) + public Composers(IUmbracoBuilder builder, IEnumerable composerTypes, IEnumerable enableDisableAttributes, ILogger logger) { - _composition = composition ?? throw new ArgumentNullException(nameof(composition)); + _builder = builder ?? throw new ArgumentNullException(nameof(builder)); _composerTypes = composerTypes ?? throw new ArgumentNullException(nameof(composerTypes)); _enableDisableAttributes = enableDisableAttributes ?? throw new ArgumentNullException(nameof(enableDisableAttributes)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _profileLogger = profileLogger; } private class EnableInfo @@ -60,27 +59,19 @@ namespace Umbraco.Core.Composing public void Compose() { // make sure it is there - _composition.WithCollectionBuilder(); + _builder.WithCollectionBuilder(); IEnumerable orderedComposerTypes; - using (_profileLogger.DebugDuration("Preparing composer types.", "Prepared composer types.")) - { - orderedComposerTypes = PrepareComposerTypes(); - } + orderedComposerTypes = PrepareComposerTypes(); var composers = InstantiateComposers(orderedComposerTypes); - using (_profileLogger.DebugDuration($"Composing composers. (log when >{LogThresholdMilliseconds}ms)", "Composed composers.")) + + foreach (var composer in composers) { - foreach (var composer in composers) - { - var componentType = composer.GetType(); - using (_profileLogger.DebugDuration($"Composing {componentType.FullName}.", $"Composed {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) - { - composer.Compose(_composition); - } - } + var componentType = composer.GetType(); + composer.Compose(_builder); } } @@ -359,13 +350,10 @@ namespace Umbraco.Core.Composing var ctor = type.GetConstructor(Array.Empty()); if (ctor == null) throw new InvalidOperationException($"Composer {type.FullName} does not have a parameter-less constructor."); - return (IComposer) ctor.Invoke(Array.Empty()); + return (IComposer)ctor.Invoke(Array.Empty()); } - using (_profileLogger.DebugDuration("Instantiating composers.", "Instantiated composers.")) - { - return types.Select(InstantiateComposer).ToArray(); - } + return types.Select(InstantiateComposer).ToArray(); } } } diff --git a/src/Umbraco.Core/Composing/Composition.cs b/src/Umbraco.Core/Composing/Composition.cs deleted file mode 100644 index fcadf7dd1b..0000000000 --- a/src/Umbraco.Core/Composing/Composition.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core.Cache; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; - -namespace Umbraco.Core.Composing -{ - /// - /// Represents a composition. - /// - /// Although a composition exposes the application's service container, people should use the - /// extension methods (such as PropertyEditors() or SetPublishedContentModelFactory()) and - /// avoid accessing the container. This is because everything needs to be properly registered and with - /// the proper lifecycle. These methods will take care of it. Directly registering into the container - /// may cause issues. - public class Composition - { - public TypeLoader TypeLoader { get; } - public IRuntimeState RuntimeState { get; } - public IProfilingLogger Logger { get; } - public IIOHelper IOHelper { get; } - public AppCaches AppCaches { get; } - public IServiceCollection Services { get; } - - private readonly Dictionary _builders = new Dictionary(); - - public Composition(IServiceCollection services, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, IIOHelper ioHelper, AppCaches appCaches) - { - Services = services ?? throw new ArgumentNullException(nameof(services)); - TypeLoader = typeLoader ?? throw new ArgumentNullException(nameof(typeLoader)); - Logger = logger ?? throw new ArgumentNullException(nameof(logger)); - RuntimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState)); - IOHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); - AppCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches)); - } - - public void RegisterBuilders() - { - foreach (var builder in _builders.Values) - builder.RegisterWith(Services); - _builders.Clear(); // no point keep them around - } - - /// - /// Gets a collection builder (and registers the collection). - /// - /// The type of the collection builder. - /// The collection builder. - public TBuilder WithCollectionBuilder() - where TBuilder: ICollectionBuilder, new() - { - var typeOfBuilder = typeof(TBuilder); - - if (_builders.TryGetValue(typeOfBuilder, out var o)) - return (TBuilder) o; - - var builder = new TBuilder(); - _builders[typeOfBuilder] = builder; - return builder; - } - } -} diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs index b3dc4301c3..ff99142c2c 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs @@ -1,5 +1,6 @@ using System; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Web.PublishedCache; @@ -10,32 +11,32 @@ namespace Umbraco.Infrastructure.PublishedCache /// /// Sets the published snapshot service. /// - /// The composition. + /// The builder. /// A function creating a published snapshot service. - public static void SetPublishedSnapshotService(this Composition composition, Func factory) + public static void SetPublishedSnapshotService(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the published snapshot service. /// /// The type of the published snapshot service. - /// The composition. - public static void SetPublishedSnapshotService(this Composition composition) + /// The builder. + public static void SetPublishedSnapshotService(this IUmbracoBuilder builder) where T : class, IPublishedSnapshotService { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } /// /// Sets the published snapshot service. /// - /// The composition. + /// The builder. /// A published snapshot service. - public static void SetPublishedSnapshotService(this Composition composition, IPublishedSnapshotService service) + public static void SetPublishedSnapshotService(this IUmbracoBuilder builder, IPublishedSnapshotService service) { - composition.Services.AddUnique(_ => service); + builder.Services.AddUnique(service); } } } diff --git a/src/Umbraco.Core/Composing/IComposer.cs b/src/Umbraco.Core/Composing/IComposer.cs index b73a745b61..6ba21eff4e 100644 --- a/src/Umbraco.Core/Composing/IComposer.cs +++ b/src/Umbraco.Core/Composing/IComposer.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Core.Composing +using Umbraco.Core.Builder; + +namespace Umbraco.Core.Composing { /// /// Represents a composer. @@ -8,6 +10,6 @@ /// /// Compose. /// - void Compose(Composition composition); + void Compose(IUmbracoBuilder builder); } } diff --git a/src/Umbraco.Core/Composing/RuntimeHashPaths.cs b/src/Umbraco.Core/Composing/RuntimeHashPaths.cs index 8b5af064af..c5a994c9a6 100644 --- a/src/Umbraco.Core/Composing/RuntimeHashPaths.cs +++ b/src/Umbraco.Core/Composing/RuntimeHashPaths.cs @@ -11,7 +11,12 @@ namespace Umbraco.Core.Composing private readonly List _paths = new List(); private readonly Dictionary _files = new Dictionary(); - public void AddFolder(DirectoryInfo pathInfo) => _paths.Add(pathInfo); + public RuntimeHashPaths AddFolder(DirectoryInfo pathInfo) + { + _paths.Add(pathInfo); + return this; + } + public void AddFile(FileInfo fileInfo, bool scanFileContent = false) => _files.Add(fileInfo, scanFileContent); public IEnumerable GetFolders() => _paths; diff --git a/src/Umbraco.Core/Composing/TypeFinderConfig.cs b/src/Umbraco.Core/Composing/TypeFinderConfig.cs index 302d45b4e8..ef862fd49d 100644 --- a/src/Umbraco.Core/Composing/TypeFinderConfig.cs +++ b/src/Umbraco.Core/Composing/TypeFinderConfig.cs @@ -15,9 +15,9 @@ namespace Umbraco.Core.Composing private readonly TypeFinderSettings _settings; private IEnumerable _assembliesAcceptingLoadExceptions; - public TypeFinderConfig(IOptionsMonitor settings) + public TypeFinderConfig(IOptions settings) { - _settings = settings.CurrentValue; + _settings = settings.Value; } public IEnumerable AssembliesAcceptingLoadExceptions diff --git a/src/Umbraco.Core/CompositionExtensions.cs b/src/Umbraco.Core/CompositionExtensions.cs index 218e2a04e3..d6c73478bf 100644 --- a/src/Umbraco.Core/CompositionExtensions.cs +++ b/src/Umbraco.Core/CompositionExtensions.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Composing; +using Umbraco.Core.Builder; +using Umbraco.Core.Composing; using Umbraco.Core.HealthCheck; using Umbraco.Core.Manifest; using Umbraco.Core.PropertyEditors; @@ -20,82 +21,82 @@ namespace Umbraco.Core /// /// Gets the actions collection builder. /// - /// The composition. + /// The builder. /// - public static ActionCollectionBuilder Actions(this Composition composition) - => composition.WithCollectionBuilder(); + public static ActionCollectionBuilder Actions(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the content apps collection builder. /// - /// The composition. + /// The builder. /// - public static ContentAppFactoryCollectionBuilder ContentApps(this Composition composition) - => composition.WithCollectionBuilder(); + public static ContentAppFactoryCollectionBuilder ContentApps(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the content finders collection builder. /// - /// The composition. + /// The builder. /// - public static ContentFinderCollectionBuilder ContentFinders(this Composition composition) - => composition.WithCollectionBuilder(); + public static ContentFinderCollectionBuilder ContentFinders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the editor validators collection builder. /// - /// The composition. + /// The builder. /// - public static EditorValidatorCollectionBuilder EditorValidators(this Composition composition) - => composition.WithCollectionBuilder(); + public static EditorValidatorCollectionBuilder EditorValidators(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the health checks collection builder. /// - /// The composition. - public static HealthCheckCollectionBuilder HealthChecks(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static HealthCheckCollectionBuilder HealthChecks(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the TourFilters collection builder. /// - public static TourFilterCollectionBuilder TourFilters(this Composition composition) - => composition.WithCollectionBuilder(); + public static TourFilterCollectionBuilder TourFilters(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the url providers collection builder. /// - /// The composition. - public static UrlProviderCollectionBuilder UrlProviders(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static UrlProviderCollectionBuilder UrlProviders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the media url providers collection builder. /// - /// The composition. - public static MediaUrlProviderCollectionBuilder MediaUrlProviders(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static MediaUrlProviderCollectionBuilder MediaUrlProviders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the backoffice sections/applications collection builder. /// - /// The composition. - public static SectionCollectionBuilder Sections(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static SectionCollectionBuilder Sections(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the components collection builder. /// - public static ComponentCollectionBuilder Components(this Composition composition) - => composition.WithCollectionBuilder(); + public static ComponentCollectionBuilder Components(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the backoffice dashboards collection builder. /// - /// The composition. - public static DashboardCollectionBuilder Dashboards(this Composition composition) - => composition.WithCollectionBuilder() + /// The builder. + public static DashboardCollectionBuilder Dashboards(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder() .Add() .Add() .Add() @@ -112,10 +113,10 @@ namespace Umbraco.Core /// /// Gets the content finders collection builder. /// - /// The composition. + /// The builder. /// - public static MediaUrlGeneratorCollectionBuilder MediaUrlGenerators(this Composition composition) - => composition.WithCollectionBuilder(); + public static MediaUrlGeneratorCollectionBuilder MediaUrlGenerators(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); #endregion } diff --git a/src/Umbraco.Core/ContentApps/ContentAppFactoryCollection.cs b/src/Umbraco.Core/ContentApps/ContentAppFactoryCollection.cs index 7884126dc8..738da5ef60 100644 --- a/src/Umbraco.Core/ContentApps/ContentAppFactoryCollection.cs +++ b/src/Umbraco.Core/ContentApps/ContentAppFactoryCollection.cs @@ -5,24 +5,25 @@ using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; namespace Umbraco.Web.ContentApps { public class ContentAppFactoryCollection : BuilderCollectionBase { private readonly ILogger _logger; - private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; - public ContentAppFactoryCollection(IEnumerable items, ILogger logger, IUmbracoContextAccessor umbracoContextAccessor) + public ContentAppFactoryCollection(IEnumerable items, ILogger logger, IBackOfficeSecurityAccessor backOfficeSecurityAccessor) : base(items) { _logger = logger; - _umbracoContextAccessor = umbracoContextAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; } private IEnumerable GetCurrentUserGroups() { - var currentUser = _umbracoContextAccessor.UmbracoContext?.Security?.CurrentUser; + var currentUser = _backOfficeSecurityAccessor?.BackOfficeSecurity?.CurrentUser; return currentUser == null ? Enumerable.Empty() : currentUser.Groups; diff --git a/src/Umbraco.Core/ContentApps/ContentAppFactoryCollectionBuilder.cs b/src/Umbraco.Core/ContentApps/ContentAppFactoryCollectionBuilder.cs index 0f0e09042b..138c426043 100644 --- a/src/Umbraco.Core/ContentApps/ContentAppFactoryCollectionBuilder.cs +++ b/src/Umbraco.Core/ContentApps/ContentAppFactoryCollectionBuilder.cs @@ -9,6 +9,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Manifest; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Models.Identity; +using Umbraco.Core.Security; namespace Umbraco.Web.ContentApps { @@ -21,8 +22,8 @@ namespace Umbraco.Web.ContentApps { // get the logger factory just-in-time - see note below for manifest parser var loggerFactory = factory.GetRequiredService(); - var umbracoContextAccessor = factory.GetRequiredService(); - return new ContentAppFactoryCollection(CreateItems(factory), loggerFactory.CreateLogger(), umbracoContextAccessor); + var backOfficeSecurityAccessor = factory.GetRequiredService(); + return new ContentAppFactoryCollection(CreateItems(factory), loggerFactory.CreateLogger(), backOfficeSecurityAccessor); } protected override IEnumerable CreateItems(IServiceProvider factory) diff --git a/src/Umbraco.Core/IUmbracoContext.cs b/src/Umbraco.Core/IUmbracoContext.cs index 312135169a..681dedbfd2 100644 --- a/src/Umbraco.Core/IUmbracoContext.cs +++ b/src/Umbraco.Core/IUmbracoContext.cs @@ -15,11 +15,6 @@ namespace Umbraco.Web /// DateTime ObjectCreated { get; } - /// - /// Gets the BackofficeSecurity class - /// - IBackOfficeSecurity Security { get; } - /// /// Gets the uri that is handled by ASP.NET after server-side rewriting took place. /// diff --git a/src/Umbraco.Core/Logging/ProfilingLogger.cs b/src/Umbraco.Core/Logging/ProfilingLogger.cs index 7bf04e3d77..520e14e17d 100644 --- a/src/Umbraco.Core/Logging/ProfilingLogger.cs +++ b/src/Umbraco.Core/Logging/ProfilingLogger.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Logging /// /// Initializes a new instance of the class. /// - public ProfilingLogger(ILogger logger, IProfiler profiler) + public ProfilingLogger(ILogger logger, IProfiler profiler) { Logger = logger ?? throw new ArgumentNullException(nameof(logger)); Profiler = profiler ?? throw new ArgumentNullException(nameof(profiler)); diff --git a/src/Umbraco.Core/Services/IRuntimeState.cs b/src/Umbraco.Core/Services/IRuntimeState.cs index fd817f1986..ef826014be 100644 --- a/src/Umbraco.Core/Services/IRuntimeState.cs +++ b/src/Umbraco.Core/Services/IRuntimeState.cs @@ -55,5 +55,7 @@ namespace Umbraco.Core /// void DetermineRuntimeLevel(); + void Configure(RuntimeLevel level, RuntimeLevelReason reason); + } } diff --git a/src/Umbraco.Core/StaticApplicationLogging.cs b/src/Umbraco.Core/StaticApplicationLogging.cs index a1e06bc1f8..84cdc3c2d2 100644 --- a/src/Umbraco.Core/StaticApplicationLogging.cs +++ b/src/Umbraco.Core/StaticApplicationLogging.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core public static ILogger CreateLogger() { - return _loggerFactory?.CreateLogger() ?? new NullLogger(); + return _loggerFactory?.CreateLogger() ?? NullLoggerFactory.Instance.CreateLogger(); } } } diff --git a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs index 24800fa98a..9551dc8b90 100644 --- a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs +++ b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs @@ -6,6 +6,7 @@ using System.Text.RegularExpressions; using Examine; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web; using Umbraco.Web.Models.ContentEditing; @@ -16,19 +17,19 @@ namespace Umbraco.Examine { private readonly IExamineManager _examineManager; private readonly ILocalizationService _languageService; - private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly IEntityService _entityService; private readonly IUmbracoTreeSearcherFields _treeSearcherFields; public BackOfficeExamineSearcher(IExamineManager examineManager, ILocalizationService languageService, - IUmbracoContextAccessor umbracoContextAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IEntityService entityService, IUmbracoTreeSearcherFields treeSearcherFields) { _examineManager = examineManager; _languageService = languageService; - _umbracoContextAccessor = umbracoContextAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _entityService = entityService; _treeSearcherFields = treeSearcherFields; } @@ -47,7 +48,7 @@ namespace Umbraco.Examine query = "\"" + g.ToString() + "\""; } - var currentUser = _umbracoContextAccessor.UmbracoContext?.Security?.CurrentUser; + var currentUser = _backOfficeSecurityAccessor?.BackOfficeSecurity?.CurrentUser; switch (entityType) { diff --git a/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs b/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs index 5df99d86fb..a9bf887c16 100644 --- a/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs +++ b/src/Umbraco.Examine.Lucene/ExamineLuceneComposer.cs @@ -1,5 +1,6 @@ using System.Runtime.InteropServices; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; namespace Umbraco.Examine @@ -8,18 +9,18 @@ namespace Umbraco.Examine [ComposeAfter(typeof(ICoreComposer))] public sealed class ExamineLuceneComposer : ComponentComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); if(!isWindows) return; - base.Compose(composition); + base.Compose(builder); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs index 603819534f..bb9140634c 100644 --- a/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs +++ b/src/Umbraco.Infrastructure/Cache/DistributedCacheBinderComposer.cs @@ -1,4 +1,5 @@ using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; namespace Umbraco.Web.Cache @@ -9,11 +10,11 @@ namespace Umbraco.Web.Cache [ComposeBefore(typeof(ICoreComposer))] // runs before every other IUmbracoCoreComponent! public sealed class DistributedCacheBinderComposer : ComponentComposer, ICoreComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); - composition.Services.AddUnique(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs index 49dab2d1db..6f0a52d033 100644 --- a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs @@ -1,6 +1,7 @@ using System; using Microsoft.Extensions.DependencyInjection; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.Services.Changes; using Umbraco.Core.Sync; @@ -62,12 +63,12 @@ namespace Umbraco.Web.Compose }; } - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); - composition.SetDatabaseServerMessengerCallbacks(GetCallbacks); - composition.SetServerMessenger(); + builder.SetDatabaseServerMessengerCallbacks(GetCallbacks); + builder.SetServerMessenger(); } } diff --git a/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs b/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs index 81a41cf575..8c26e0e688 100644 --- a/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Web.Actions; @@ -183,7 +184,7 @@ namespace Umbraco.Web.Compose /// public sealed class Notifier { - private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly IRequestAccessor _requestAccessor; private readonly INotificationService _notificationService; private readonly IUserService _userService; @@ -194,15 +195,15 @@ namespace Umbraco.Web.Compose /// /// Constructor /// - /// + /// + /// /// /// /// /// - /// /// public Notifier( - IUmbracoContextAccessor umbracoContextAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IRequestAccessor requestAccessor, INotificationService notificationService, IUserService userService, @@ -210,7 +211,7 @@ namespace Umbraco.Web.Compose IOptions globalSettings, ILogger logger) { - _umbracoContextAccessor = umbracoContextAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _requestAccessor = requestAccessor; _notificationService = notificationService; _userService = userService; @@ -221,7 +222,7 @@ namespace Umbraco.Web.Compose public void Notify(IAction action, params IContent[] entities) { - var user = _umbracoContextAccessor.UmbracoContext?.Security?.CurrentUser; + var user = _backOfficeSecurityAccessor?.BackOfficeSecurity?.CurrentUser; //if there is no current user, then use the admin if (user == null) diff --git a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs index 44a5d58daa..e68d6dabf8 100644 --- a/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs +++ b/src/Umbraco.Infrastructure/Compose/NotificationsComposer.cs @@ -1,15 +1,16 @@ using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; namespace Umbraco.Web.Compose { public sealed class NotificationsComposer : ComponentComposer, ICoreComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); - composition.Services.AddUnique(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs index 823f8618ad..04f715c7c0 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Core.BackOffice; +using Umbraco.Core.Builder; using Umbraco.Core.Mapping; using Umbraco.Web.Models.Mapping; @@ -11,13 +12,13 @@ namespace Umbraco.Core.Composing.CompositionExtensions /// /// Registers the core Umbraco mapper definitions /// - /// + /// /// - public static Composition ComposeCoreMappingProfiles(this Composition composition) + public static IUmbracoBuilder ComposeCoreMappingProfiles(this IUmbracoBuilder builder) { - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.WithCollectionBuilder() + builder.WithCollectionBuilder() .Add() .Add() .Add() @@ -37,10 +38,10 @@ namespace Umbraco.Core.Composing.CompositionExtensions .Add() ; - composition.Services.AddTransient(); - composition.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); - return composition; + return builder; } } } diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs index a4286bd719..1f539782c7 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Umbraco.Core.Builder; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; @@ -33,21 +34,21 @@ namespace Umbraco.Core.Composing.CompositionExtensions * */ - public static Composition ComposeFileSystems(this Composition composition) + public static IUmbracoBuilder ComposeFileSystems(this IUmbracoBuilder builder) { // register FileSystems, which manages all filesystems // it needs to be registered (not only the interface) because it provides additional // functionality eg for scoping, and is injected in the scope provider - whereas the // interface is really for end-users to get access to filesystems. - composition.Services.AddUnique(factory => factory.CreateInstance(factory)); + builder.Services.AddUnique(factory => factory.CreateInstance(factory)); // register IFileSystems, which gives access too all filesystems - composition.Services.AddUnique(factory => factory.GetRequiredService()); + builder.Services.AddUnique(factory => factory.GetRequiredService()); // register the scheme for media paths - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.SetMediaFileSystem(factory => + builder.SetMediaFileSystem(factory => { var ioHelper = factory.GetRequiredService(); var hostingEnvironment = factory.GetRequiredService(); @@ -59,7 +60,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions return new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, rootPath, rootUrl); }); - return composition; + return builder; } } } diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs index 7e64b0698c..e4272a44f3 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Installer.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Web.Install; using Umbraco.Web.Install.InstallSteps; @@ -9,28 +10,28 @@ namespace Umbraco.Web.Composing.CompositionExtensions { public static class Installer { - public static Composition ComposeInstaller(this Composition composition) + public static IUmbracoBuilder ComposeInstaller(this IUmbracoBuilder builder) { // register the installer steps - composition.Services.AddScoped(); - composition.Services.AddScoped(); - composition.Services.AddScoped(); - composition.Services.AddScoped(); - composition.Services.AddScoped(); - composition.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); // TODO: Add these back once we have a compatible Starter kit // composition.Services.AddScoped(); // composition.Services.AddScoped(); // composition.Services.AddScoped(); - composition.Services.AddScoped(); + builder.Services.AddScoped(); - composition.Services.AddTransient(); - composition.Services.AddUnique(); + builder.Services.AddTransient(); + builder.Services.AddUnique(); - return composition; + return builder; } } } diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs index 8d15b5761a..ba4195faf0 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Builder; +using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; namespace Umbraco.Core.Composing.CompositionExtensions @@ -8,50 +9,50 @@ namespace Umbraco.Core.Composing.CompositionExtensions /// internal static class Repositories { - public static Composition ComposeRepositories(this Composition composition) + public static IUmbracoBuilder ComposeRepositories(this IUmbracoBuilder builder) { // repositories - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); - return composition; + return builder; } } } diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs index c6106b2191..f657236cad 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs @@ -4,6 +4,7 @@ using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; +using Umbraco.Core.Builder; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; @@ -19,64 +20,64 @@ namespace Umbraco.Core.Composing.CompositionExtensions { internal static class Services { - public static Composition ComposeServices(this Composition composition) + public static IUmbracoBuilder ComposeServices(this IUmbracoBuilder builder) { // register a transient messages factory, which will be replaced by the web // boot manager when running in a web context - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register the service context - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register the special idk map - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register the services - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddTransient(SourcesFactory); - composition.Services.AddUnique(factory => new LocalizedTextService( + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddTransient(SourcesFactory); + builder.Services.AddUnique(factory => new LocalizedTextService( factory.GetRequiredService>(), factory.GetRequiredService>())); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(factory => CreatePackageRepository(factory, "createdPackages.config")); - composition.Services.AddUnique(factory => CreatePackageRepository(factory, "installedPackages.config")); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(factory => CreatePackageRepository(factory, "createdPackages.config")); + builder.Services.AddUnique(factory => CreatePackageRepository(factory, "installedPackages.config")); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); - return composition; + return builder; } /// diff --git a/src/Umbraco.Infrastructure/CompositionExtensions.cs b/src/Umbraco.Infrastructure/CompositionExtensions.cs index 3a7537d346..d7a1c1125b 100644 --- a/src/Umbraco.Infrastructure/CompositionExtensions.cs +++ b/src/Umbraco.Infrastructure/CompositionExtensions.cs @@ -1,5 +1,6 @@ using System; using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core.Builder; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Dictionary; @@ -27,80 +28,80 @@ namespace Umbraco.Core /// /// Gets the cache refreshers collection builder. /// - /// The composition. - public static CacheRefresherCollectionBuilder CacheRefreshers(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static CacheRefresherCollectionBuilder CacheRefreshers(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the mappers collection builder. /// - /// The composition. - public static MapperCollectionBuilder Mappers(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static MapperCollectionBuilder Mappers(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the package actions collection builder. /// - /// The composition. - internal static PackageActionCollectionBuilder PackageActions(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + internal static PackageActionCollectionBuilder PackageActions(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the data editor collection builder. /// - /// The composition. - public static DataEditorCollectionBuilder DataEditors(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static DataEditorCollectionBuilder DataEditors(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the data value reference factory collection builder. /// - /// The composition. - public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the property value converters collection builder. /// - /// The composition. - public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static PropertyValueConverterCollectionBuilder PropertyValueConverters(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the url segment providers collection builder. /// - /// The composition. - public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static UrlSegmentProviderCollectionBuilder UrlSegmentProviders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the validators collection builder. /// - /// The composition. - internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the manifest filter collection builder. /// - /// The composition. - public static ManifestFilterCollectionBuilder ManifestFilters(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static ManifestFilterCollectionBuilder ManifestFilters(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the backoffice OEmbed Providers collection builder. /// - /// The composition. - public static EmbedProvidersCollectionBuilder OEmbedProviders(this Composition composition) - => composition.WithCollectionBuilder(); + /// The builder. + public static EmbedProvidersCollectionBuilder OEmbedProviders(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); /// /// Gets the back office searchable tree collection builder /// - /// + /// /// - public static SearchableTreeCollectionBuilder SearchableTrees(this Composition composition) - => composition.WithCollectionBuilder(); + public static SearchableTreeCollectionBuilder SearchableTrees(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); #endregion @@ -110,189 +111,189 @@ namespace Umbraco.Core /// Sets the culture dictionary factory. /// /// The type of the factory. - /// The composition. - public static void SetCultureDictionaryFactory(this Composition composition) + /// The builder. + public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder) where T : class, ICultureDictionaryFactory { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } /// /// Sets the culture dictionary factory. /// - /// The composition. + /// The builder. /// A function creating a culture dictionary factory. - public static void SetCultureDictionaryFactory(this Composition composition, Func factory) + public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the culture dictionary factory. /// - /// The composition. + /// The builder. /// A factory. - public static void SetCultureDictionaryFactory(this Composition composition, ICultureDictionaryFactory factory) + public static void SetCultureDictionaryFactory(this IUmbracoBuilder builder, ICultureDictionaryFactory factory) { - composition.Services.AddUnique(_ => factory); + builder.Services.AddUnique(factory); } /// /// Sets the published content model factory. /// /// The type of the factory. - /// The composition. - public static void SetPublishedContentModelFactory(this Composition composition) + /// The builder. + public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder) where T : class, IPublishedModelFactory { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } /// /// Sets the published content model factory. /// - /// The composition. + /// The builder. /// A function creating a published content model factory. - public static void SetPublishedContentModelFactory(this Composition composition, Func factory) + public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the published content model factory. /// - /// The composition. + /// The builder. /// A published content model factory. - public static void SetPublishedContentModelFactory(this Composition composition, IPublishedModelFactory factory) + public static void SetPublishedContentModelFactory(this IUmbracoBuilder builder, IPublishedModelFactory factory) { - composition.Services.AddUnique(_ => factory); + builder.Services.AddUnique(factory); } /// /// Sets the server registrar. /// /// The type of the server registrar. - /// The composition. - public static void SetServerRegistrar(this Composition composition) + /// The builder. + public static void SetServerRegistrar(this IUmbracoBuilder builder) where T : class, IServerRegistrar { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } /// /// Sets the server registrar. /// - /// The composition. + /// The builder. /// A function creating a server registrar. - public static void SetServerRegistrar(this Composition composition, Func factory) + public static void SetServerRegistrar(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the server registrar. /// - /// The composition. + /// The builder. /// A server registrar. - public static void SetServerRegistrar(this Composition composition, IServerRegistrar registrar) + public static void SetServerRegistrar(this IUmbracoBuilder builder, IServerRegistrar registrar) { - composition.Services.AddUnique(_ => registrar); + builder.Services.AddUnique(registrar); } /// /// Sets the server messenger. /// /// The type of the server registrar. - /// The composition. - public static void SetServerMessenger(this Composition composition) + /// The builder. + public static void SetServerMessenger(this IUmbracoBuilder builder) where T : class, IServerMessenger { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } /// /// Sets the server messenger. /// - /// The composition. + /// The builder. /// A function creating a server messenger. - public static void SetServerMessenger(this Composition composition, Func factory) + public static void SetServerMessenger(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the server messenger. /// - /// The composition. + /// The builder. /// A server messenger. - public static void SetServerMessenger(this Composition composition, IServerMessenger registrar) + public static void SetServerMessenger(this IUmbracoBuilder builder, IServerMessenger registrar) { - composition.Services.AddUnique(_ => registrar); + builder.Services.AddUnique(registrar); } /// /// Sets the database server messenger options. /// - /// The composition. + /// The builder. /// A function creating the options. /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. - public static void SetDatabaseServerMessengerCallbacks(this Composition composition, Func factory) + public static void SetDatabaseServerMessengerCallbacks(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the database server messenger options. /// - /// The composition. + /// The builder. /// Options. /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. - public static void SetDatabaseServerMessengerOptions(this Composition composition, DatabaseServerMessengerCallbacks options) + public static void SetDatabaseServerMessengerOptions(this IUmbracoBuilder builder, DatabaseServerMessengerCallbacks options) { - composition.Services.AddUnique(_ => options); + builder.Services.AddUnique(options); } /// /// Sets the short string helper. /// /// The type of the short string helper. - /// The composition. - public static void SetShortStringHelper(this Composition composition) + /// The builder. + public static void SetShortStringHelper(this IUmbracoBuilder builder) where T : class, IShortStringHelper { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } /// /// Sets the short string helper. /// - /// The composition. + /// The builder. /// A function creating a short string helper. - public static void SetShortStringHelper(this Composition composition, Func factory) + public static void SetShortStringHelper(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the short string helper. /// - /// A composition. + /// A builder. /// A short string helper. - public static void SetShortStringHelper(this Composition composition, IShortStringHelper helper) + public static void SetShortStringHelper(this IUmbracoBuilder builder, IShortStringHelper helper) { - composition.Services.AddUnique(_ => helper); + builder.Services.AddUnique(helper); } /// /// Sets the underlying media filesystem. /// - /// A composition. + /// A builder. /// A filesystem factory. /// /// Using this helper will ensure that your IFileSystem implementation is wrapped by the ShadowWrapper /// - public static void SetMediaFileSystem(this Composition composition, Func filesystemFactory) - => composition.Services.AddUnique(factory => + public static void SetMediaFileSystem(this IUmbracoBuilder builder, Func filesystemFactory) + => builder.Services.AddUnique(factory => { var fileSystems = factory.GetRequiredService(); return fileSystems.GetFileSystem(filesystemFactory(factory)); @@ -302,31 +303,31 @@ namespace Umbraco.Core /// Sets the log viewer. /// /// The type of the log viewer. - /// The composition. - public static void SetLogViewer(this Composition composition) + /// The builder. + public static void SetLogViewer(this IUmbracoBuilder builder) where T : class, ILogViewer { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } /// /// Sets the log viewer. /// - /// The composition. + /// The builder. /// A function creating a log viewer. - public static void SetLogViewer(this Composition composition, Func factory) + public static void SetLogViewer(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the log viewer. /// - /// A composition. + /// A builder. /// A log viewer. - public static void SetLogViewer(this Composition composition, ILogViewer viewer) + public static void SetLogViewer(this IUmbracoBuilder builder, ILogViewer viewer) { - composition.Services.AddUnique(_ => viewer); + builder.Services.AddUnique(viewer); } #endregion diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs index 59c9b47400..c7f222f0ca 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogComposer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.Logging.Serilog.Enrichers; using Umbraco.Infrastructure.Logging.Serilog.Enrichers; @@ -10,12 +11,12 @@ namespace Umbraco.Infrastructure.Logging.Serilog { public class SerilogComposer : ICoreComposer { - public void Compose(Composition composition) + public void Compose(IUmbracoBuilder builder) { - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerComposer.cs b/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerComposer.cs index e65e05de0f..856b6e892d 100644 --- a/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerComposer.cs +++ b/src/Umbraco.Infrastructure/Logging/Viewer/LogViewerComposer.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; namespace Umbraco.Core.Logging.Viewer @@ -8,11 +9,11 @@ namespace Umbraco.Core.Logging.Viewer // ReSharper disable once UnusedMember.Global public class LogViewerComposer : ICoreComposer { - public void Compose(Composition composition) + public void Compose(IUmbracoBuilder builder) { - composition.Services.AddUnique(); - composition.SetLogViewer(); - composition.Services.AddUnique(factory => + builder.Services.AddUnique(); + builder.SetLogViewer(); + builder.Services.AddUnique(factory => { return new SerilogJsonLogViewer(factory.GetRequiredService>(), diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/DataTypes/PreValueMigratorComposer.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/DataTypes/PreValueMigratorComposer.cs index 19e0845703..08c890e5b0 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/DataTypes/PreValueMigratorComposer.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_8_0_0/DataTypes/PreValueMigratorComposer.cs @@ -1,15 +1,16 @@ -using Umbraco.Core.Composing; +using Umbraco.Core.Builder; +using Umbraco.Core.Composing; namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0.DataTypes { public class PreValueMigratorComposer : ICoreComposer { - public void Compose(Composition composition) + public void Compose(IUmbracoBuilder builder) { // do NOT add DefaultPreValueMigrator to this list! // it will be automatically used if nothing matches - composition.WithCollectionBuilder() + builder.WithCollectionBuilder() .Append() .Append() .Append() diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs index 65933399a3..7b98bd150e 100644 --- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs @@ -24,7 +24,7 @@ namespace Umbraco.Core.Persistence /// // TODO: these comments are not true anymore // TODO: this class needs not be disposable! - internal class UmbracoDatabaseFactory : DisposableObjectSlim, IUmbracoDatabaseFactory + public class UmbracoDatabaseFactory : DisposableObjectSlim, IUmbracoDatabaseFactory { private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator; private readonly GlobalSettings _globalSettings; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs index c34ce59fe6..e6db6a4328 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Media; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Templates; @@ -28,7 +29,7 @@ namespace Umbraco.Web.PropertyEditors Group = Constants.PropertyEditors.Groups.RichContent)] public class GridPropertyEditor : DataEditor { - private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly IIOHelper _ioHelper; private readonly HtmlImageSourceParser _imageSourceParser; private readonly RichTextEditorPastedImages _pastedImages; @@ -37,7 +38,7 @@ namespace Umbraco.Web.PropertyEditors public GridPropertyEditor( ILoggerFactory loggerFactory, - IUmbracoContextAccessor umbracoContextAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, @@ -49,7 +50,7 @@ namespace Umbraco.Web.PropertyEditors IImageUrlGenerator imageUrlGenerator) : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) { - _umbracoContextAccessor = umbracoContextAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _ioHelper = ioHelper; _imageSourceParser = imageSourceParser; _pastedImages = pastedImages; @@ -63,13 +64,13 @@ namespace Umbraco.Web.PropertyEditors /// Overridden to ensure that the value is validated /// /// - protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _umbracoContextAccessor, DataTypeService, LocalizationService, LocalizedTextService, _imageSourceParser, _pastedImages, _localLinkParser, ShortStringHelper, _imageUrlGenerator); + protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute, _backOfficeSecurityAccessor, DataTypeService, LocalizationService, LocalizedTextService, _imageSourceParser, _pastedImages, _localLinkParser, ShortStringHelper, _imageUrlGenerator); protected override IConfigurationEditor CreateConfigurationEditor() => new GridConfigurationEditor(_ioHelper); internal class GridPropertyValueEditor : DataValueEditor, IDataValueReference { - private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly HtmlImageSourceParser _imageSourceParser; private readonly RichTextEditorPastedImages _pastedImages; private readonly RichTextPropertyEditor.RichTextPropertyValueEditor _richTextPropertyValueEditor; @@ -78,7 +79,7 @@ namespace Umbraco.Web.PropertyEditors public GridPropertyValueEditor( DataEditorAttribute attribute, - IUmbracoContextAccessor umbracoContextAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, @@ -89,10 +90,10 @@ namespace Umbraco.Web.PropertyEditors IImageUrlGenerator imageUrlGenerator) : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) { - _umbracoContextAccessor = umbracoContextAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _imageSourceParser = imageSourceParser; _pastedImages = pastedImages; - _richTextPropertyValueEditor = new RichTextPropertyEditor.RichTextPropertyValueEditor(attribute, umbracoContextAccessor, dataTypeService, localizationService, localizedTextService, shortStringHelper, imageSourceParser, localLinkParser, pastedImages, imageUrlGenerator); + _richTextPropertyValueEditor = new RichTextPropertyEditor.RichTextPropertyValueEditor(attribute, backOfficeSecurityAccessor, dataTypeService, localizationService, localizedTextService, shortStringHelper, imageSourceParser, localLinkParser, pastedImages, imageUrlGenerator); _mediaPickerPropertyValueEditor = new MediaPickerPropertyEditor.MediaPickerPropertyValueEditor(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute); _imageUrlGenerator = imageUrlGenerator; } @@ -121,7 +122,7 @@ namespace Umbraco.Web.PropertyEditors var grid = DeserializeGridValue(rawJson, out var rtes, out _); - var userId = _umbracoContextAccessor.UmbracoContext?.Security?.CurrentUser?.Id ?? Constants.Security.SuperUserId; + var userId = _backOfficeSecurityAccessor?.BackOfficeSecurity?.CurrentUser?.Id ?? Constants.Security.SuperUserId; // Process the rte values foreach (var rte in rtes) diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs index bf867ce648..049f020db4 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Media; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Examine; @@ -28,7 +29,7 @@ namespace Umbraco.Web.PropertyEditors Icon = "icon-browser-window")] public class RichTextPropertyEditor : DataEditor { - private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly HtmlImageSourceParser _imageSourceParser; private readonly HtmlLocalLinkParser _localLinkParser; private readonly RichTextEditorPastedImages _pastedImages; @@ -40,7 +41,7 @@ namespace Umbraco.Web.PropertyEditors /// public RichTextPropertyEditor( ILoggerFactory loggerFactory, - IUmbracoContextAccessor umbracoContextAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService, HtmlImageSourceParser imageSourceParser, @@ -52,7 +53,7 @@ namespace Umbraco.Web.PropertyEditors IImageUrlGenerator imageUrlGenerator) : base(loggerFactory, dataTypeService, localizationService, localizedTextService, shortStringHelper) { - _umbracoContextAccessor = umbracoContextAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _imageSourceParser = imageSourceParser; _localLinkParser = localLinkParser; _pastedImages = pastedImages; @@ -64,7 +65,7 @@ namespace Umbraco.Web.PropertyEditors /// Create a custom value editor /// /// - protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _umbracoContextAccessor, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, _imageSourceParser, _localLinkParser, _pastedImages, _imageUrlGenerator); + protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute, _backOfficeSecurityAccessor, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, _imageSourceParser, _localLinkParser, _pastedImages, _imageUrlGenerator); protected override IConfigurationEditor CreateConfigurationEditor() => new RichTextConfigurationEditor(_ioHelper); @@ -75,7 +76,7 @@ namespace Umbraco.Web.PropertyEditors /// internal class RichTextPropertyValueEditor : DataValueEditor, IDataValueReference { - private IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly HtmlImageSourceParser _imageSourceParser; private readonly HtmlLocalLinkParser _localLinkParser; private readonly RichTextEditorPastedImages _pastedImages; @@ -83,7 +84,7 @@ namespace Umbraco.Web.PropertyEditors public RichTextPropertyValueEditor( DataEditorAttribute attribute, - IUmbracoContextAccessor umbracoContextAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, @@ -94,7 +95,7 @@ namespace Umbraco.Web.PropertyEditors IImageUrlGenerator imageUrlGenerator) : base(dataTypeService, localizationService,localizedTextService, shortStringHelper, attribute) { - _umbracoContextAccessor = umbracoContextAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _imageSourceParser = imageSourceParser; _localLinkParser = localLinkParser; _pastedImages = pastedImages; @@ -146,7 +147,7 @@ namespace Umbraco.Web.PropertyEditors if (editorValue.Value == null) return null; - var userId = _umbracoContextAccessor.UmbracoContext?.Security?.CurrentUser?.Id ?? Constants.Security.SuperUserId; + var userId = _backOfficeSecurityAccessor?.BackOfficeSecurity?.CurrentUser?.Id ?? Constants.Security.SuperUserId; var config = editorValue.DataTypeConfiguration as RichTextConfiguration; var mediaParent = config?.MediaParentId; diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index 0328e782f8..a4a2417602 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -59,9 +59,11 @@ using Umbraco.Web.Trees; using IntegerValidator = Umbraco.Core.PropertyEditors.Validators.IntegerValidator; using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter; using Microsoft.Extensions.Logging; +using Umbraco.Core.Builder; using Umbraco.Core.Configuration.HealthChecks; using Umbraco.Core.HealthCheck; using Umbraco.Core.HealthCheck.Checks; +using Umbraco.Core.Security; namespace Umbraco.Core.Runtime { @@ -69,12 +71,12 @@ namespace Umbraco.Core.Runtime [ComposeBefore(typeof(ICoreComposer))] public class CoreInitialComposer : ComponentComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); // composers - composition + builder .ComposeRepositories() .ComposeServices() .ComposeCoreMappingProfiles() @@ -83,27 +85,27 @@ namespace Umbraco.Core.Runtime // 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 // has been frozen and it is too late - composition.Mappers().AddCoreMappers(); + builder.Mappers().AddCoreMappers(); // register the scope provider - composition.Services.AddUnique(); // implements both IScopeProvider and IScopeAccessor - composition.Services.AddUnique(f => f.GetRequiredService()); - composition.Services.AddUnique(f => f.GetRequiredService()); + builder.Services.AddUnique(); // implements both IScopeProvider and IScopeAccessor + builder.Services.AddUnique(f => f.GetRequiredService()); + builder.Services.AddUnique(f => f.GetRequiredService()); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); // register database builder // *not* a singleton, don't want to keep it around - composition.Services.AddTransient(); + builder.Services.AddTransient(); // register manifest parser, will be injected in collection builders where needed - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register our predefined validators - composition.ManifestValueValidators() + builder.ManifestValueValidators() .Add() .Add() .Add() @@ -112,25 +114,25 @@ namespace Umbraco.Core.Runtime .Add(); // register the manifest filter collection builder (collection is empty by default) - composition.ManifestFilters(); + builder.ManifestFilters(); // properties and parameters derive from data editors - composition.DataEditors() - .Add(() => composition.TypeLoader.GetDataEditors()); + builder.DataEditors() + .Add(() => builder.TypeLoader.GetDataEditors()); - composition.MediaUrlGenerators() + builder.MediaUrlGenerators() .Add() .Add(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); // Used to determine if a datatype/editor should be storing/tracking // references to media item/s - composition.DataValueReferenceFactories(); + builder.DataValueReferenceFactories(); // register a server registrar, by default it's the db registrar - composition.Services.AddUnique(f => + builder.Services.AddUnique(f => { var globalSettings = f.GetRequiredService>().Value; @@ -146,7 +148,7 @@ namespace Umbraco.Core.Runtime // by default we'll use the database server messenger with default options (no callbacks), // this will be overridden by the db thing in the corresponding components in the web // project - composition.Services.AddUnique(factory + builder.Services.AddUnique(factory => new DatabaseServerMessenger( factory.GetRequiredService(), factory.GetRequiredService(), @@ -161,107 +163,107 @@ namespace Umbraco.Core.Runtime factory.GetRequiredService>() )); - composition.CacheRefreshers() - .Add(() => composition.TypeLoader.GetCacheRefreshers()); + builder.CacheRefreshers() + .Add(() => builder.TypeLoader.GetCacheRefreshers()); - composition.PackageActions() - .Add(() => composition.TypeLoader.GetPackageActions()); + builder.PackageActions() + .Add(() => builder.TypeLoader.GetPackageActions()); - composition.PropertyValueConverters() - .Append(composition.TypeLoader.GetTypes()); + builder.PropertyValueConverters() + .Append(builder.TypeLoader.GetTypes()); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(factory + builder.Services.AddUnique(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetRequiredService>().Value))); - composition.UrlSegmentProviders() + builder.UrlSegmentProviders() .Append(); - composition.Services.AddUnique(factory => new MigrationBuilder(factory)); + builder.Services.AddUnique(factory => new MigrationBuilder(factory)); // by default, register a noop factory - composition.Services.AddUnique(); + builder.Services.AddUnique(); // by default - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.SetCultureDictionaryFactory(); - composition.Services.AddSingleton(f => f.GetRequiredService().CreateDictionary()); - composition.Services.AddUnique(); + builder.SetCultureDictionaryFactory(); + builder.Services.AddSingleton(f => f.GetRequiredService().CreateDictionary()); + builder.Services.AddUnique(); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards - composition.Dashboards() - .Add(composition.TypeLoader.GetTypes()); + builder.Dashboards() + .Add(builder.TypeLoader.GetTypes()); // will be injected in controllers when needed to invoke rest endpoints on Our - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); // Grid config is not a real config file as we know them - composition.Services.AddUnique(); + builder.Services.AddUnique(); // Config manipulator - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register the umbraco context factory // composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be // discovered when CoreBootManager configures the converters. We HAVE to remove one of them // here because there cannot be two converters for one property editor - and we want the full // RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter. // (the limited one, defined in Core, is there for tests) - same for others - composition.PropertyValueConverters() + builder.PropertyValueConverters() .Remove() .Remove() .Remove(); - composition.UrlProviders() + builder.UrlProviders() .Append() .Append(); - composition.MediaUrlProviders() + builder.MediaUrlProviders() .Append(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register properties fallback - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Actions() - .Add(() => composition.TypeLoader.GetTypes()); + builder.Actions() + .Add(() => builder.TypeLoader.GetTypes()); - composition.EditorValidators() - .Add(() => composition.TypeLoader.GetTypes()); + builder.EditorValidators() + .Add(() => builder.TypeLoader.GetTypes()); - composition.TourFilters(); + builder.TourFilters(); // replace with web implementation - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register OEmbed providers - no type scanning - all explicit opt-in of adding types // note: IEmbedProvider is not IDiscoverable - think about it if going for type scanning - composition.OEmbedProviders() + builder.OEmbedProviders() .Append() .Append() .Append() @@ -278,7 +280,7 @@ namespace Umbraco.Core.Runtime .Append(); // register back office sections in the order we want them rendered - composition.Sections() + builder.Sections() .Append() .Append() .Append() @@ -289,7 +291,7 @@ namespace Umbraco.Core.Runtime .Append(); // register known content apps - composition.ContentApps() + builder.ContentApps() .Append() .Append() .Append() @@ -299,18 +301,18 @@ namespace Umbraco.Core.Runtime .Append(); // register published router - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register *all* checks, except those marked [HideFromTypeFinder] of course - composition.HealthChecks() - .Add(() => composition.TypeLoader.GetTypes()); + builder.HealthChecks() + .Add(() => builder.TypeLoader.GetTypes()); - composition.WithCollectionBuilder() - .Add(() => composition.TypeLoader.GetTypes()); + builder.WithCollectionBuilder() + .Add(() => builder.TypeLoader.GetTypes()); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.ContentFinders() + builder.ContentFinders() // all built-in finders in the correct order, // devs can then modify this list on application startup .Append() @@ -320,63 +322,66 @@ namespace Umbraco.Core.Runtime .Append() .Append(); - composition.Services.AddScoped(); + builder.Services.AddScoped(); - composition.SearchableTrees() - .Add(() => composition.TypeLoader.GetTypes()); + builder.SearchableTrees() + .Add(() => builder.TypeLoader.GetTypes()); // replace some services - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register distributed cache - composition.Services.AddUnique(f => new DistributedCache(f.GetRequiredService(), f.GetRequiredService())); + builder.Services.AddUnique(f => new DistributedCache(f.GetRequiredService(), f.GetRequiredService())); - composition.Services.AddScoped(); + builder.Services.AddScoped(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddScoped(factory => + builder.Services.AddUnique(); + builder.Services.AddScoped(factory => { var umbCtx = factory.GetRequiredService(); return new PublishedContentQuery(umbCtx.UmbracoContext.PublishedSnapshot, factory.GetRequiredService(), factory.GetRequiredService()); }); - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register the http context and umbraco context accessors // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when // we have no http context, eg when booting Umbraco or in background threads, so instead // let's use an hybrid accessor that can fall back to a ThreadStatic context. - composition.Services.AddUnique(); + builder.Services.AddUnique(); // register accessors for cultures - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddSingleton(); + builder.Services.AddSingleton(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); // Register noop versions for examine to be overridden by examine - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(factory => new LegacyPasswordSecurity()); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index a0c1718c07..cb02a90ebe 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -1,51 +1,67 @@ using System; +using Microsoft.Extensions.Logging; +using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; -namespace Umbraco.Core.Runtime +namespace Umbraco.Infrastructure.Runtime { public class CoreRuntime : IRuntime { public IRuntimeState State { get; } + private readonly ILogger _logger; private readonly ComponentCollection _components; - private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker; private readonly IApplicationShutdownRegistry _applicationShutdownRegistry; private readonly IProfilingLogger _profilingLogger; private readonly IMainDom _mainDom; + private readonly IUmbracoDatabaseFactory _databaseFactory; public CoreRuntime( + ILogger logger, IRuntimeState state, ComponentCollection components, - IUmbracoBootPermissionChecker umbracoBootPermissionChecker, IApplicationShutdownRegistry applicationShutdownRegistry, IProfilingLogger profilingLogger, - IMainDom mainDom) + IMainDom mainDom, + IUmbracoDatabaseFactory databaseFactory) { State = state; + _logger = logger; _components = components; - _umbracoBootPermissionChecker = umbracoBootPermissionChecker; _applicationShutdownRegistry = applicationShutdownRegistry; _profilingLogger = profilingLogger; _mainDom = mainDom; + _databaseFactory = databaseFactory; } public void Start() { + AppDomain.CurrentDomain.UnhandledException += (_, args) => + { + var exception = (Exception)args.ExceptionObject; + var isTerminating = args.IsTerminating; // always true? + + var msg = "Unhandled exception in AppDomain"; + if (isTerminating) msg += " (terminating)"; + msg += "."; + _logger.LogError(exception, msg); + }; + + DetermineRuntimeLevel(); + if (State.Level <= RuntimeLevel.BootFailed) throw new InvalidOperationException($"Cannot start the runtime if the runtime level is less than or equal to {RuntimeLevel.BootFailed}"); - // throws if not full-trust - _umbracoBootPermissionChecker.ThrowIfNotPermissions(); - var hostingEnvironmentLifetime = _applicationShutdownRegistry; if (hostingEnvironmentLifetime == null) throw new InvalidOperationException($"An instance of {typeof(IApplicationShutdownRegistry)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}"); // acquire the main domain - if this fails then anything that should be registered with MainDom will not operate - AcquireMainDom(_mainDom, _applicationShutdownRegistry); + AcquireMainDom(); // create & initialize the components _components.Initialize(); @@ -53,16 +69,16 @@ namespace Umbraco.Core.Runtime public void Terminate() { - _components?.Terminate(); + _components.Terminate(); } - private void AcquireMainDom(IMainDom mainDom, IApplicationShutdownRegistry applicationShutdownRegistry) + private void AcquireMainDom() { using (var timer = _profilingLogger.DebugDuration("Acquiring MainDom.", "Acquired.")) { try { - mainDom.Acquire(applicationShutdownRegistry); + _mainDom.Acquire(_applicationShutdownRegistry); } catch { @@ -71,5 +87,29 @@ namespace Umbraco.Core.Runtime } } } + + private void DetermineRuntimeLevel() + { + using var timer = _profilingLogger.DebugDuration("Determining runtime level.", "Determined."); + + try + { + State.DetermineRuntimeLevel(); + + _logger.LogDebug("Runtime level: {RuntimeLevel} - {RuntimeLevelReason}", State.Level, State.Reason); + + if (State.Level == RuntimeLevel.Upgrade) + { + _logger.LogDebug("Configure database factory for upgrades."); + _databaseFactory.ConfigureForUpgrade(); + } + } + catch + { + State.Configure(RuntimeLevel.BootFailed, RuntimeLevelReason.BootFailedOnException); + timer?.Fail(); + throw; + } + } } } diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntimeBootstrapper.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntimeBootstrapper.cs deleted file mode 100644 index 9b576324bd..0000000000 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntimeBootstrapper.cs +++ /dev/null @@ -1,376 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Umbraco.Core.Cache; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Events; -using Umbraco.Core.Exceptions; -using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Mappers; - -namespace Umbraco.Core.Runtime -{ - /// - /// Bootstraps the Core Umbraco runtime. - /// - /// Does not handle any of the web-related aspects of Umbraco (startup, etc). It - /// should be possible to use this runtime in console apps. - public class CoreRuntimeBootstrapper - { - // runtime state, this instance will get replaced again once the essential services are available to run the check - private RuntimeState _state = RuntimeState.Booting(); - private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker; - private readonly GlobalSettings _globalSettings; - private readonly ConnectionStrings _connectionStrings; - - public CoreRuntimeBootstrapper( - GlobalSettings globalSettings, - ConnectionStrings connectionStrings, - IUmbracoVersion umbracoVersion, - IIOHelper ioHelper, - ILoggerFactory loggerFactory, - IProfiler profiler, - IUmbracoBootPermissionChecker umbracoBootPermissionChecker, - IHostingEnvironment hostingEnvironment, - IBackOfficeInfo backOfficeInfo, - IDbProviderFactoryCreator dbProviderFactoryCreator, - IMainDom mainDom, - ITypeFinder typeFinder, - AppCaches appCaches) - { - _globalSettings = globalSettings; - _connectionStrings = connectionStrings; - - IOHelper = ioHelper; - AppCaches = appCaches; - UmbracoVersion = umbracoVersion; - Profiler = profiler; - HostingEnvironment = hostingEnvironment; - BackOfficeInfo = backOfficeInfo; - DbProviderFactoryCreator = dbProviderFactoryCreator; - - RuntimeLoggerFactory = loggerFactory; - _umbracoBootPermissionChecker = umbracoBootPermissionChecker; - - Logger = loggerFactory.CreateLogger(); - MainDom = mainDom; - TypeFinder = typeFinder; - } - - /// - /// Gets the logger. - /// - private ILogger Logger { get; } - - public ILoggerFactory RuntimeLoggerFactory { get; } - - protected IBackOfficeInfo BackOfficeInfo { get; } - - public IDbProviderFactoryCreator DbProviderFactoryCreator { get; } - - /// - /// Gets the profiler. - /// - protected IProfiler Profiler { get; } - - /// - /// Gets the profiling logger. - /// - public IProfilingLogger ProfilingLogger { get; private set; } - - /// - /// Gets the - /// - protected ITypeFinder TypeFinder { get; } - - /// - /// Gets the - /// - protected IIOHelper IOHelper { get; } - - protected IHostingEnvironment HostingEnvironment { get; } - public AppCaches AppCaches { get; } - public IUmbracoVersion UmbracoVersion { get; } - - /// - public IRuntimeState State => _state; - - public IMainDom MainDom { get; } - - /// - public virtual void Configure(IServiceCollection services) - { - if (services is null) throw new ArgumentNullException(nameof(services)); - - - // create and register the essential services - // ie the bare minimum required to boot - - // the boot loader boots using a container scope, so anything that is PerScope will - // be disposed after the boot loader has booted, and anything else will remain. - // note that this REQUIRES that perWebRequestScope has NOT been enabled yet, else - // the container will fail to create a scope since there is no http context when - // the application starts. - // the boot loader is kept in the runtime for as long as Umbraco runs, and components - // are NOT disposed - which is not a big deal as long as they remain lightweight - // objects. - - var umbracoVersion = new UmbracoVersion(); - var profilingLogger = ProfilingLogger = new ProfilingLogger(Logger, Profiler); - using (var timer = profilingLogger.TraceDuration( - $"Booting Umbraco {umbracoVersion.SemanticVersion.ToSemanticString()}.", - "Booted.", - "Boot failed.")) - { - - Logger.LogInformation("Booting site '{HostingSiteName}', app '{HostingApplicationId}', path '{HostingPhysicalPath}', server '{MachineName}'.", - HostingEnvironment?.SiteName, - HostingEnvironment?.ApplicationId, - HostingEnvironment?.ApplicationPhysicalPath, - NetworkHelper.MachineName); - Logger.LogDebug("Runtime: {Runtime}", GetType().FullName); - - AppDomain.CurrentDomain.SetData("DataDirectory", HostingEnvironment?.MapPathContentRoot(Constants.SystemDirectories.Data)); - - // application environment - ConfigureUnhandledException(); - Configure(services, timer); - } - } - - /// - /// Configure the runtime within a timer. - /// - private void Configure(IServiceCollection services, DisposableTimer timer) - { - if (services is null) throw new ArgumentNullException(nameof(services)); - if (timer is null) throw new ArgumentNullException(nameof(timer)); - - Composition composition = null; - - try - { - // run handlers - OnRuntimeBoot(); - - // type finder/loader - var typeLoader = new TypeLoader(TypeFinder, AppCaches.RuntimeCache, - new DirectoryInfo(HostingEnvironment.LocalTempPath), - RuntimeLoggerFactory.CreateLogger(), ProfilingLogger); - - services.AddUnique(Logger); - services.AddUnique(RuntimeLoggerFactory); - services.AddUnique(_umbracoBootPermissionChecker); - services.AddUnique(Profiler); - services.AddUnique(ProfilingLogger); - services.AddUnique(MainDom); - services.AddUnique(AppCaches); - services.AddUnique(AppCaches.RequestCache); - services.AddUnique(typeLoader); - services.AddUnique(TypeFinder); - services.AddUnique(IOHelper); - services.AddUnique(UmbracoVersion); - services.AddUnique(DbProviderFactoryCreator); - services.AddUnique(HostingEnvironment); - services.AddUnique(BackOfficeInfo); - services.AddUnique(); - - // NOTE: This instance of IUmbracoDatabaseFactory is only used to determine runtime state. - var bootstrapDatabaseFactory = CreateBootstrapDatabaseFactory(); - - // after bootstrapping we let the container wire up for us. - services.AddUnique(); - services.AddUnique(factory => factory.GetRequiredService().SqlContext); - services.AddUnique(factory => factory.GetRequiredService().BulkSqlInsertProvider); - - // re-create the state object with the essential services - _state = new RuntimeState(_globalSettings, UmbracoVersion, bootstrapDatabaseFactory, RuntimeLoggerFactory.CreateLogger()); - services.AddUnique(_state); - - - // create the composition - composition = new Composition(services, typeLoader, ProfilingLogger, _state, IOHelper, AppCaches); - - // run handlers - OnRuntimeEssentials(composition, AppCaches, typeLoader, bootstrapDatabaseFactory); - - try - { - // determine our runtime level - DetermineRuntimeLevel(bootstrapDatabaseFactory); - } - finally - { - // always run composers - RunComposers(typeLoader, composition); - } - - } - catch (Exception e) - { - var bfe = e as BootFailedException ?? new BootFailedException("Boot failed.", e); - - if (_state != null) - { - _state.Level = RuntimeLevel.BootFailed; - _state.BootFailedException = bfe; - } - - timer?.Fail(exception: bfe); // be sure to log the exception - even if we repeat ourselves - - Debugger.Break(); - - // throwing here can cause w3wp to hard-crash and we want to avoid it. - // instead, we're logging the exception and setting level to BootFailed. - // various parts of Umbraco such as UmbracoModule and UmbracoDefaultOwinStartup - // understand this and will nullify themselves, while UmbracoModule will - // throw a BootFailedException for every requests. - } - finally - { - composition?.RegisterBuilders(); - } - } - - protected virtual void ConfigureUnhandledException() - { - //take care of unhandled exceptions - there is nothing we can do to - // prevent the launch process to go down but at least we can try - // and log the exception - AppDomain.CurrentDomain.UnhandledException += (_, args) => - { - var exception = (Exception)args.ExceptionObject; - var isTerminating = args.IsTerminating; // always true? - - var msg = "Unhandled exception in AppDomain"; - if (isTerminating) msg += " (terminating)"; - msg += "."; - Logger.LogError(exception, msg); - }; - } - - private void RunComposers(TypeLoader typeLoader, Composition composition) - { - // get composers, and compose - var composerTypes = ResolveComposerTypes(typeLoader); - - IEnumerable enableDisableAttributes; - using (ProfilingLogger.DebugDuration("Scanning enable/disable composer attributes")) - { - enableDisableAttributes = typeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute)); - } - - var composers = new Composers(composition, composerTypes, enableDisableAttributes, RuntimeLoggerFactory.CreateLogger(), ProfilingLogger); - composers.Compose(); - } - - - private void DetermineRuntimeLevel(IUmbracoDatabaseFactory databaseFactory) - { - using var timer = ProfilingLogger.DebugDuration("Determining runtime level.", "Determined."); - - try - { - _state.DetermineRuntimeLevel(); - - Logger.LogDebug("Runtime level: {RuntimeLevel} - {RuntimeLevelReason}", _state.Level, _state.Reason); - - if (_state.Level == RuntimeLevel.Upgrade) - { - Logger.LogDebug("Configure database factory for upgrades."); - databaseFactory.ConfigureForUpgrade(); - } - } - catch - { - _state.Level = RuntimeLevel.BootFailed; - _state.Reason = RuntimeLevelReason.BootFailedOnException; - timer?.Fail(); - throw; - } - } - - private IEnumerable ResolveComposerTypes(TypeLoader typeLoader) - { - using (var timer = ProfilingLogger.TraceDuration("Resolving composer types.", "Resolved.")) - { - try - { - return GetComposerTypes(typeLoader); - } - catch - { - timer?.Fail(); - throw; - } - } - } - - #region Getters - - // getters can be implemented by runtimes inheriting from CoreRuntime - - /// - /// Gets all composer types. - /// - protected virtual IEnumerable GetComposerTypes(TypeLoader typeLoader) - => typeLoader.GetTypes(); - - /// - /// Returns the application path of the site/solution - /// - /// - /// - /// By default is null which means it's not running in any virtual folder. If the site is running in a virtual folder, this - /// can be overridden and the virtual path returned (i.e. /mysite/) - /// - protected virtual string GetApplicationRootPath() - => null; - - /// - /// Creates the database factory. - /// - /// This is strictly internal, for tests only. - protected internal virtual IUmbracoDatabaseFactory CreateBootstrapDatabaseFactory() - => new UmbracoDatabaseFactory( - RuntimeLoggerFactory.CreateLogger(), - RuntimeLoggerFactory, - Options.Create(_globalSettings), - Options.Create(_connectionStrings), - new Lazy(() => new MapperCollection(Enumerable.Empty())), - DbProviderFactoryCreator); - - - #endregion - - #region Events - - protected void OnRuntimeBoot() - { - RuntimeOptions.DoRuntimeBoot(ProfilingLogger); - RuntimeBooting?.Invoke(this, ProfilingLogger); - } - - protected void OnRuntimeEssentials(Composition composition, AppCaches appCaches, TypeLoader typeLoader, IUmbracoDatabaseFactory databaseFactory) - { - RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory); - RuntimeEssentials?.Invoke(this, new RuntimeEssentialsEventArgs(composition, appCaches, typeLoader, databaseFactory)); - } - - public event TypedEventHandler RuntimeBooting; - public event TypedEventHandler RuntimeEssentials; - - #endregion - - } -} diff --git a/src/Umbraco.Infrastructure/Runtime/RuntimeEssentialsEventArgs.cs b/src/Umbraco.Infrastructure/Runtime/RuntimeEssentialsEventArgs.cs deleted file mode 100644 index 78d068cb9c..0000000000 --- a/src/Umbraco.Infrastructure/Runtime/RuntimeEssentialsEventArgs.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using Umbraco.Core.Cache; -using Umbraco.Core.Composing; -using Umbraco.Core.Persistence; - -namespace Umbraco.Core.Runtime -{ - public class RuntimeEssentialsEventArgs : EventArgs - { - public RuntimeEssentialsEventArgs(Composition composition, AppCaches appCaches, TypeLoader typeLoader, IUmbracoDatabaseFactory databaseFactory) - { - Composition = composition; - AppCaches = appCaches; - TypeLoader = typeLoader; - DatabaseFactory = databaseFactory; - } - - public Composition Composition { get; } - public AppCaches AppCaches { get; } - public TypeLoader TypeLoader { get; } - public IUmbracoDatabaseFactory DatabaseFactory { get; } - } -} diff --git a/src/Umbraco.Infrastructure/RuntimeOptions.cs b/src/Umbraco.Infrastructure/RuntimeOptions.cs deleted file mode 100644 index 23abd474a4..0000000000 --- a/src/Umbraco.Infrastructure/RuntimeOptions.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using Umbraco.Core.Cache; -using Umbraco.Core.Composing; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; - -namespace Umbraco.Core -{ - /// - /// Provides static options for the runtime. - /// - /// - /// These options can be configured in PreApplicationStart or via appSettings. - /// - public static class RuntimeOptions - { - private static List> _onBoot; - private static List> _onEssentials; - - /// - /// Executes the RuntimeBoot handlers. - /// - internal static void DoRuntimeBoot(IProfilingLogger logger) - { - if (_onBoot == null) - return; - - foreach (var action in _onBoot) - action(logger); - } - - /// - /// Executes the RuntimeEssentials handlers. - /// - internal static void DoRuntimeEssentials(Composition composition, AppCaches appCaches, TypeLoader typeLoader, IUmbracoDatabaseFactory databaseFactory) - { - if (_onEssentials== null) - return; - - foreach (var action in _onEssentials) - action(composition, appCaches, typeLoader, databaseFactory); - } - - /// - /// Registers a RuntimeBoot handler. - /// - /// - /// A RuntimeBoot handler runs when the runtime boots, right after the - /// loggers have been created, but before anything else. - /// - public static void OnRuntimeBoot(Action action) - { - if (_onBoot == null) - _onBoot = new List>(); - _onBoot.Add(action); - } - - /// - /// Registers a RuntimeEssentials handler. - /// - /// - /// A RuntimeEssentials handler runs after the runtime has created a few - /// essential things (AppCaches, a TypeLoader, and a database factory) but - /// before anything else. - /// - public static void OnRuntimeEssentials(Action action) - { - if (_onEssentials == null) - _onEssentials = new List>(); - _onEssentials.Add(action); - } - } -} diff --git a/src/Umbraco.Infrastructure/RuntimeState.cs b/src/Umbraco.Infrastructure/RuntimeState.cs index cb2358d083..505cf045c3 100644 --- a/src/Umbraco.Infrastructure/RuntimeState.cs +++ b/src/Umbraco.Infrastructure/RuntimeState.cs @@ -2,6 +2,7 @@ using System.Threading; using Semver; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Exceptions; @@ -32,9 +33,9 @@ namespace Umbraco.Core /// /// Initializes a new instance of the class. /// - public RuntimeState(GlobalSettings globalSettings, IUmbracoVersion umbracoVersion, IUmbracoDatabaseFactory databaseFactory, ILogger logger) + public RuntimeState(IOptions globalSettings, IUmbracoVersion umbracoVersion, IUmbracoDatabaseFactory databaseFactory, ILogger logger) { - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _umbracoVersion = umbracoVersion; _databaseFactory = databaseFactory; _logger = logger; @@ -160,6 +161,12 @@ namespace Umbraco.Core Reason = RuntimeLevelReason.UpgradeMigrations; } + public void Configure(RuntimeLevel level, RuntimeLevelReason reason) + { + Level = level; + Reason = reason; + } + private bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) { var upgrader = new Upgrader(new UmbracoPlan(_umbracoVersion)); diff --git a/src/Umbraco.Infrastructure/Search/ExamineComposer.cs b/src/Umbraco.Infrastructure/Search/ExamineComposer.cs index e8ee269aac..87deb21bde 100644 --- a/src/Umbraco.Infrastructure/Search/ExamineComposer.cs +++ b/src/Umbraco.Infrastructure/Search/ExamineComposer.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -16,21 +17,21 @@ namespace Umbraco.Web.Search /// public sealed class ExamineComposer : ComponentComposer, ICoreComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); // populators are not a collection: one cannot remove ours, and can only add more // the container can inject IEnumerable and get them all - composition.Services.AddSingleton(); - composition.Services.AddSingleton(); - composition.Services.AddSingleton(); - composition.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); - composition.Services.AddSingleton(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(factory => + builder.Services.AddSingleton(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(factory => new ContentValueSetBuilder( factory.GetRequiredService(), factory.GetRequiredService(), @@ -38,7 +39,7 @@ namespace Umbraco.Web.Search factory.GetRequiredService(), factory.GetRequiredService(), true)); - composition.Services.AddUnique(factory => + builder.Services.AddUnique(factory => new ContentValueSetBuilder( factory.GetRequiredService(), factory.GetRequiredService(), @@ -46,9 +47,9 @@ namespace Umbraco.Web.Search factory.GetRequiredService(), factory.GetRequiredService(), false)); - composition.Services.AddUnique, MediaValueSetBuilder>(); - composition.Services.AddUnique, MemberValueSetBuilder>(); - composition.Services.AddUnique(); + builder.Services.AddUnique, MediaValueSetBuilder>(); + builder.Services.AddUnique, MemberValueSetBuilder>(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Infrastructure/WebAssets/WebAssetsComposer.cs b/src/Umbraco.Infrastructure/WebAssets/WebAssetsComposer.cs index b907d07627..6a048daca4 100644 --- a/src/Umbraco.Infrastructure/WebAssets/WebAssetsComposer.cs +++ b/src/Umbraco.Infrastructure/WebAssets/WebAssetsComposer.cs @@ -1,14 +1,15 @@ using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; namespace Umbraco.Web.WebAssets { public sealed class WebAssetsComposer : ComponentComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); - composition.Services.AddUnique(); + base.Compose(builder); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs index aa8f91c508..324b5f0df7 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs @@ -7,23 +7,24 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.ModelsBuilder.Embedded.Building; using Umbraco.Core.Configuration.Models; using Microsoft.Extensions.Options; +using Umbraco.Core.Builder; namespace Umbraco.ModelsBuilder.Embedded.Compose { [ComposeBefore(typeof(IPublishedCacheComposer))] public sealed class ModelsBuilderComposer : ICoreComposer { - public void Compose(Composition composition) + public void Compose(IUmbracoBuilder builder) { - composition.Components().Append(); - composition.Services.AddSingleton(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Components().Append(); + builder.Services.AddSingleton(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(factory => + builder.Services.AddUnique(); + builder.Services.AddUnique(factory => { var config = factory.GetRequiredService>().Value; if (config.ModelsMode == ModelsMode.PureLive) diff --git a/src/Umbraco.PublishedCache.NuCache/NuCacheComposer.cs b/src/Umbraco.PublishedCache.NuCache/NuCacheComposer.cs index ea8863dbd7..eb1b4b3d5f 100644 --- a/src/Umbraco.PublishedCache.NuCache/NuCacheComposer.cs +++ b/src/Umbraco.PublishedCache.NuCache/NuCacheComposer.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Scoping; @@ -11,21 +12,21 @@ namespace Umbraco.Web.PublishedCache.NuCache { public class NuCacheComposer : ComponentComposer, IPublishedCacheComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); // register the NuCache database data source - composition.Services.AddTransient(); + builder.Services.AddTransient(); // register the NuCache published snapshot service // must register default options, required in the service ctor - composition.Services.AddTransient(factory => new PublishedSnapshotServiceOptions()); - composition.SetPublishedSnapshotService(); + builder.Services.AddTransient(factory => new PublishedSnapshotServiceOptions()); + builder.SetPublishedSnapshotService(); // replace this service since we want to improve the content/media // mapping lookups if we are using nucache. - composition.Services.AddUnique(factory => + builder.Services.AddUnique(factory => { var idkSvc = new IdKeyMap(factory.GetRequiredService()); var publishedSnapshotService = factory.GetRequiredService() as PublishedSnapshotService; diff --git a/src/Umbraco.TestData/LoadTestController.cs b/src/Umbraco.TestData/LoadTestController.cs index fbb031c6db..ed9e0b456e 100644 --- a/src/Umbraco.TestData/LoadTestController.cs +++ b/src/Umbraco.TestData/LoadTestController.cs @@ -11,6 +11,7 @@ using System.Diagnostics; using Umbraco.Core.Composing; using System.Configuration; using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core.Builder; using Umbraco.Core.Strings; // see https://github.com/Shazwazza/UmbracoScripts/tree/master/src/LoadTesting @@ -362,14 +363,14 @@ namespace Umbraco.TestData public class TestComposer : ComponentComposer, IUserComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true") return; - composition.Services.AddScoped(typeof(LoadTestController)); + builder.Services.AddScoped(typeof(LoadTestController)); } } } diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index 7eafdc6271..fd9ffe5d26 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -66,7 +66,7 @@ namespace Umbraco.Tests.Integration.Implementations _hostingLifetime = new AspNetCoreApplicationShutdownRegistry(Mock.Of()); ConsoleLoggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); - ProfilingLogger = new ProfilingLogger(ConsoleLoggerFactory.CreateLogger("ProfilingLogger"), Profiler); + ProfilingLogger = new ProfilingLogger(ConsoleLoggerFactory.CreateLogger(), Profiler); } diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index eec62b9331..89006ef245 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; @@ -9,9 +10,11 @@ using Moq; using NUnit.Framework; using Microsoft.Extensions.Logging; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Runtime; @@ -20,6 +23,7 @@ using Umbraco.Tests.Common; using Umbraco.Tests.Integration.Extensions; using Umbraco.Tests.Integration.Implementations; using Umbraco.Tests.Integration.Testing; +using Umbraco.Web.Common.Builder; namespace Umbraco.Tests.Integration { @@ -41,68 +45,6 @@ namespace Umbraco.Tests.Integration MyComposer.Reset(); } - /// - /// Manually configure the containers/dependencies and call Boot on Core runtime - /// - [Test] - public void Boot_Core_Runtime() - { - var services = new ServiceCollection().AddLazySupport(); - - // Special case since we are not using the Generic Host, we need to manually add an AspNetCore service to the container - services.AddTransient(x => Mock.Of()); - - var testHelper = new TestHelper(); - - var globalSettings = new GlobalSettings(); - var connectionStrings = new ConnectionStrings(); - - // TODO: found these registration were necessary here (as we haven't called the HostBuilder?), as dependencies for ComponentCollection - // are not resolved. Need to check this if these explicit registrations are the best way to handle this. - - services.AddTransient(x => Options.Create(globalSettings)); - services.AddTransient(x => Options.Create(connectionStrings)); - services.AddTransient(x => Options.Create(new ContentSettings())); - services.AddTransient(x => Options.Create(new CoreDebugSettings())); - services.AddTransient(x => Options.Create(new NuCacheSettings())); - services.AddTransient(x => Options.Create(new RequestHandlerSettings())); - services.AddTransient(x => Options.Create(new UserPasswordConfigurationSettings())); - services.AddTransient(x => Options.Create(new WebRoutingSettings())); - services.AddTransient(x => Options.Create(new ModelsBuilderSettings())); - services.AddTransient(x => Options.Create(new RouteOptions())); - services.AddTransient(x => Options.Create(new IndexCreatorSettings())); - services.AddRouting(); // LinkGenerator - services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); - - // Create the core runtime - var bootstrapper = new CoreRuntimeBootstrapper(globalSettings, connectionStrings, testHelper.GetUmbracoVersion(), - testHelper.IOHelper, testHelper.ConsoleLoggerFactory, testHelper.Profiler, testHelper.UmbracoBootPermissionChecker, - testHelper.GetHostingEnvironment(), testHelper.GetBackOfficeInfo(), testHelper.DbProviderFactoryCreator, - testHelper.MainDom, testHelper.GetTypeFinder(), AppCaches.NoCache); - - bootstrapper.Configure(services); - - Assert.IsTrue(bootstrapper.MainDom.IsMainDom); - Assert.IsNull(bootstrapper.State.BootFailedException); - Assert.AreEqual(RuntimeLevel.Install, bootstrapper.State.Level); - Assert.IsTrue(MyComposer.IsComposed); - Assert.IsFalse(MyComponent.IsInit); - Assert.IsFalse(MyComponent.IsTerminated); - - var container = services.BuildServiceProvider(); - - var runtime = container.GetRequiredService(); - - runtime.Start(); - - Assert.IsTrue(MyComponent.IsInit); - Assert.IsFalse(MyComponent.IsTerminated); - - runtime.Terminate(); - - Assert.IsTrue(MyComponent.IsTerminated); - } - /// /// Calling AddUmbracoCore to configure the container /// @@ -120,8 +62,19 @@ namespace Umbraco.Tests.Integration services.AddRequiredNetCoreServices(testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(hostContext.Configuration); - services.AddUmbracoCore(webHostEnvironment, GetType().Assembly, AppCaches.NoCache, testHelper.GetLoggingConfiguration(), hostContext.Configuration); + var typeLoader = services.AddTypeLoader( + GetType().Assembly, + webHostEnvironment, + testHelper.GetHostingEnvironment(), + testHelper.ConsoleLoggerFactory, + AppCaches.NoCache, + hostContext.Configuration, + testHelper.Profiler); + + var builder = new UmbracoBuilder(services, hostContext.Configuration, typeLoader, testHelper.ConsoleLoggerFactory); + builder.Services.AddUnique(AppCaches.NoCache); + builder.AddConfiguration(); + builder.AddUmbracoCore(); }); var host = await hostBuilder.StartAsync(); @@ -133,7 +86,6 @@ namespace Umbraco.Tests.Integration Assert.IsFalse(mainDom.IsMainDom); // We haven't "Started" the runtime yet Assert.IsNull(runtimeState.BootFailedException); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); Assert.IsFalse(MyComponent.IsInit); // We haven't "Started" the runtime yet await host.StopAsync(); @@ -157,10 +109,23 @@ namespace Umbraco.Tests.Integration var webHostEnvironment = testHelper.GetWebHostEnvironment(); services.AddSingleton(testHelper.DbProviderFactoryCreator); services.AddRequiredNetCoreServices(testHelper, webHostEnvironment); - + // Add it! - services.AddUmbracoConfiguration(hostContext.Configuration); - services.AddUmbracoCore(webHostEnvironment, GetType().Assembly, AppCaches.NoCache, testHelper.GetLoggingConfiguration(),hostContext.Configuration); + + var typeLoader = services.AddTypeLoader( + GetType().Assembly, + webHostEnvironment, + testHelper.GetHostingEnvironment(), + testHelper.ConsoleLoggerFactory, + AppCaches.NoCache, + hostContext.Configuration, + testHelper.Profiler); + + var builder = new UmbracoBuilder(services, hostContext.Configuration, typeLoader, testHelper.ConsoleLoggerFactory); + builder.Services.AddUnique(AppCaches.NoCache); + builder.AddConfiguration() + .AddUmbracoCore() + .Build(); services.AddRouting(); // LinkGenerator }); @@ -177,7 +142,6 @@ namespace Umbraco.Tests.Integration Assert.IsTrue(mainDom.IsMainDom); Assert.IsNull(runtimeState.BootFailedException); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); Assert.IsTrue(MyComponent.IsInit); await host.StopAsync(); @@ -187,9 +151,9 @@ namespace Umbraco.Tests.Integration public class MyComposer : IUserComposer { - public void Compose(Composition composition) + public void Compose(IUmbracoBuilder builder) { - composition.Components().Append(); + builder.Components().Append(); IsComposed = true; } diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs index 171914ecd6..897bc38c2f 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs @@ -1,9 +1,10 @@ -using System; +using Moq; +using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Cache; +using Umbraco.Core.Logging; using Umbraco.Core.Runtime; -using Umbraco.Extensions; using Umbraco.Tests.Integration.Implementations; -using Umbraco.Tests.Integration.Testing; using Umbraco.Web.Common.Builder; namespace Umbraco.Tests.Integration.TestServerTest @@ -15,39 +16,15 @@ namespace Umbraco.Tests.Integration.TestServerTest /// /// /// - public static IUmbracoBuilder WithTestCore(this IUmbracoBuilder builder, TestHelper testHelper, - Action dbInstallEventHandler) + public static IUmbracoBuilder AddTestCore(this IUmbracoBuilder builder, TestHelper testHelper) { - return builder.AddWith(nameof(global::Umbraco.Web.Common.Builder.UmbracoBuilderExtensions.WithCore), - () => - { - builder.Services.AddUmbracoCore( - builder.WebHostEnvironment, - typeof(UmbracoBuilderExtensions).Assembly, - AppCaches.NoCache, // Disable caches in integration tests - testHelper.GetLoggingConfiguration(), - builder.Config, - // TODO: Yep that's extremely ugly - (globalSettings, connectionStrings, umbVersion, ioHelper, loggerFactory, profiler, hostingEnv, backOfficeInfo, typeFinder, appCaches, dbProviderFactoryCreator) => - { - var runtime = UmbracoIntegrationTest.CreateTestRuntime( - globalSettings, - connectionStrings, - umbVersion, - ioHelper, - loggerFactory, - profiler, - hostingEnv, - backOfficeInfo, - typeFinder, - appCaches, - dbProviderFactoryCreator, - testHelper.MainDom, // SimpleMainDom - dbInstallEventHandler); // DB Installation event handler + builder.AddUmbracoCore(); - return runtime; - }); - }); + builder.Services.AddUnique(AppCaches.NoCache); + builder.Services.AddUnique(Mock.Of()); + builder.Services.AddUnique(testHelper.MainDom); + + return builder; } } } diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index 792b5cd5c1..f6ece372ea 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -21,6 +21,9 @@ using Umbraco.Web; using Umbraco.Web.Common.Builder; using Umbraco.Web.Common.Controllers; using Microsoft.Extensions.Hosting; +using Umbraco.Core.Cache; +using Umbraco.Core.Persistence; +using Umbraco.Core.Runtime; using Umbraco.Web.BackOffice.Controllers; namespace Umbraco.Tests.Integration.TestServerTest @@ -70,6 +73,7 @@ namespace Umbraco.Tests.Integration.TestServerTest // call startup builder.Configure(app => { + UseTestLocalDb(app.ApplicationServices); Services = app.ApplicationServices; Configure(app); }); @@ -126,21 +130,25 @@ namespace Umbraco.Tests.Integration.TestServerTest public override void ConfigureServices(IServiceCollection services) { - var umbracoBuilder = services.AddUmbraco(TestHelper.GetWebHostEnvironment(), Configuration); - umbracoBuilder - .WithConfiguration() - .WithTestCore(TestHelper, UseTestLocalDb) // This is the important one! - .WithWebComponents() - .WithRuntimeMinifier() - .WithBackOffice() - .WithBackOfficeIdentity() - .WithPreview() + var typeLoader = services.AddTypeLoader(GetType().Assembly, TestHelper.GetWebHostEnvironment(), TestHelper.GetHostingEnvironment(), + TestHelper.ConsoleLoggerFactory, AppCaches.NoCache, Configuration, TestHelper.Profiler); + + var builder = new UmbracoBuilder(services, Configuration, typeLoader); + + builder + .AddConfiguration() + .AddTestCore(TestHelper) // This is the important one! + .AddWebComponents() + .AddRuntimeMinifier() + .AddBackOffice() + .AddBackOfficeIdentity() + .AddPreviewSupport() //.WithMiniProfiler() // we don't want this running in tests - .WithMvcAndRazor(mvcBuilding: mvcBuilder => + .AddMvcAndRazor(mvcBuilding: mvcBuilder => { mvcBuilder.AddApplicationPart(typeof(ContentController).Assembly); }) - .WithWebServer() + .AddWebServer() .Build(); } diff --git a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs index a0a4f4f886..c556d4d29d 100644 --- a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs +++ b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; @@ -37,27 +38,25 @@ namespace Umbraco.Tests.Integration.Testing /// public class IntegrationTestComposer : ComponentComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); - composition.Components().Remove(); - composition.Services.AddUnique(); - composition.Services.AddUnique(factory => Mock.Of()); + builder.Components().Remove(); + builder.Services.AddUnique(); + builder.Services.AddUnique(factory => Mock.Of()); // we don't want persisted nucache files in tests - composition.Services.AddTransient(factory => new PublishedSnapshotServiceOptions { IgnoreLocalDb = true }); + builder.Services.AddTransient(factory => new PublishedSnapshotServiceOptions { IgnoreLocalDb = true }); // ensure all lucene indexes are using RAM directory (no file system) - composition.Services.AddUnique(); + builder.Services.AddUnique(); // replace this service so that it can lookup the correct file locations - composition.Services.AddUnique(GetLocalizedTextService); - - composition.Services.AddUnique(); - composition.Services.AddUnique(); - + builder.Services.AddUnique(GetLocalizedTextService); + builder.Services.AddUnique(); + builder.Services.AddUnique(); } /// diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index 1232fba287..b61e61f20c 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -26,12 +26,15 @@ using System.Collections.Generic; using Microsoft.Extensions.Configuration; using System.Data.SqlClient; using System.Data.Common; +using System.Diagnostics; using System.IO; using Umbraco.Core.Configuration.Models; using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Serilog; +using Umbraco.Core.Builder; +using Umbraco.Web.Common.Builder; using ConnectionStrings = Umbraco.Core.Configuration.Models.ConnectionStrings; namespace Umbraco.Tests.Integration.Testing @@ -109,25 +112,27 @@ namespace Umbraco.Tests.Integration.Testing private ILoggerFactory CreateLoggerFactory() { - ILoggerFactory factory; - var testOptions = TestOptionAttributeBase.GetTestOptions(); - switch (testOptions.Logger) + try { - case UmbracoTestOptions.Logger.Mock: - factory = NullLoggerFactory.Instance; - break; - case UmbracoTestOptions.Logger.Serilog: - factory = Microsoft.Extensions.Logging.LoggerFactory.Create(builder => { builder.AddSerilog(); }); - break; - case UmbracoTestOptions.Logger.Console: - factory = Microsoft.Extensions.Logging.LoggerFactory.Create(builder => { builder.AddConsole(); }); - break; - default: - throw new NotSupportedException($"Logger option {testOptions.Logger} is not supported."); + var testOptions = TestOptionAttributeBase.GetTestOptions(); + switch (testOptions.Logger) + { + case UmbracoTestOptions.Logger.Mock: + return NullLoggerFactory.Instance; + case UmbracoTestOptions.Logger.Serilog: + return Microsoft.Extensions.Logging.LoggerFactory.Create(builder => { builder.AddSerilog(); }); + case UmbracoTestOptions.Logger.Console: + return Microsoft.Extensions.Logging.LoggerFactory.Create(builder => { builder.AddConsole(); }); + } + } + catch + { + // ignored } - return factory; + return NullLoggerFactory.Instance; } + /// /// Create the Generic Host and execute startup ConfigureServices/Configure calls /// @@ -156,95 +161,7 @@ namespace Umbraco.Tests.Integration.Testing }); return hostBuilder; } - - /// - /// Creates a instance for testing and registers an event handler for database install - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public CoreRuntimeBootstrapper CreateTestRuntime( - GlobalSettings globalSettings, - ConnectionStrings connectionStrings, - IUmbracoVersion umbracoVersion, IIOHelper ioHelper, - ILoggerFactory loggerFactory, IProfiler profiler, Core.Hosting.IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo, - ITypeFinder typeFinder, AppCaches appCaches, IDbProviderFactoryCreator dbProviderFactoryCreator) - { - var runtime = CreateTestRuntime( - globalSettings, - connectionStrings, - umbracoVersion, - ioHelper, - loggerFactory, - profiler, - hostingEnvironment, - backOfficeInfo, - typeFinder, - appCaches, - dbProviderFactoryCreator, - TestHelper.MainDom, // SimpleMainDom - UseTestLocalDb // DB Installation event handler - ); - - return runtime; - } - - /// - /// Creates a instance for testing and registers an event handler for database install - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// The event handler used for DB installation - /// - /// - public static CoreRuntimeBootstrapper CreateTestRuntime( - GlobalSettings globalSettings, - ConnectionStrings connectionStrings, - IUmbracoVersion umbracoVersion, IIOHelper ioHelper, - ILoggerFactory loggerFactory, IProfiler profiler, Core.Hosting.IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo, - ITypeFinder typeFinder, AppCaches appCaches, IDbProviderFactoryCreator dbProviderFactoryCreator, - IMainDom mainDom, Action eventHandler) - { - var runtime = new CoreRuntimeBootstrapper( - globalSettings, - connectionStrings, - umbracoVersion, - ioHelper, - loggerFactory, - profiler, - Mock.Of(), - hostingEnvironment, - backOfficeInfo, - dbProviderFactoryCreator, - mainDom, - typeFinder, - appCaches); - - runtime.RuntimeEssentials += (sender, args) => eventHandler(sender, args); - - return runtime; - } - + #endregion #region IStartup @@ -256,25 +173,38 @@ namespace Umbraco.Tests.Integration.Testing services.AddRequiredNetCoreServices(TestHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(Configuration); - services.AddUmbracoCore( - webHostEnvironment, + var typeLoader = services.AddTypeLoader( GetType().Assembly, - GetAppCaches(), - TestHelper.GetLoggingConfiguration(), + webHostEnvironment, + TestHelper.GetHostingEnvironment(), + TestHelper.ConsoleLoggerFactory, + AppCaches.NoCache, Configuration, - CreateTestRuntime); + TestHelper.Profiler); + var builder = new UmbracoBuilder(services, Configuration, typeLoader, TestHelper.ConsoleLoggerFactory); + + + builder.Services.AddLogger(TestHelper.GetHostingEnvironment(), TestHelper.GetLoggingConfiguration(), Configuration); + + builder.AddConfiguration() + .AddUmbracoCore(); + + builder.Services.AddUnique(GetAppCaches()); + builder.Services.AddUnique(Mock.Of()); + builder.Services.AddUnique(TestHelper.MainDom); services.AddSignalR(); - services.AddUmbracoWebComponents(Configuration); - services.AddUmbracoRuntimeMinifier(Configuration); - services.AddUmbracoBackOffice(); - services.AddUmbracoBackOfficeIdentity(); + builder.AddWebComponents(); + builder.AddRuntimeMinifier(); + builder.AddBackOffice(); + builder.AddBackOfficeIdentity(); services.AddMvc(); + builder.Build(); + CustomTestSetup(services); } @@ -286,6 +216,8 @@ namespace Umbraco.Tests.Integration.Testing public virtual void Configure(IApplicationBuilder app) { + UseTestLocalDb(app.ApplicationServices); + //get the currently set options var testOptions = TestOptionAttributeBase.GetTestOptions(); if (testOptions.Boot) @@ -306,6 +238,7 @@ namespace Umbraco.Tests.Integration.Testing protected void TerminateCoreRuntime() { Services.GetRequiredService().Terminate(); + StaticApplicationLogging.Initialize(null); } #endregion @@ -315,24 +248,15 @@ namespace Umbraco.Tests.Integration.Testing private static readonly object _dbLocker = new object(); private static LocalDbTestDatabase _dbInstance; - /// - /// Event handler for the to install the database - /// - /// - /// - protected void UseTestLocalDb(CoreRuntimeBootstrapper runtimeBootstrapper, RuntimeEssentialsEventArgs args) + protected void UseTestLocalDb(IServiceProvider serviceProvider) { - // This will create a db, install the schema and ensure the app is configured to run - InstallTestLocalDb(args.DatabaseFactory, runtimeBootstrapper.RuntimeLoggerFactory, runtimeBootstrapper.State, TestHelper.WorkingDirectory); - TestDBConnectionString = args.DatabaseFactory.ConnectionString; - InMemoryConfiguration["ConnectionStrings:" + Constants.System.UmbracoConnectionName] = TestDBConnectionString; + var state = serviceProvider.GetRequiredService(); + var databaseFactory = serviceProvider.GetRequiredService(); - // Re-configure IOptions now that we have a test db - // This is what will be resolved first time IUmbracoDatabaseFactory is resolved from container (e.g. post CoreRuntime bootstrap) - args.Composition.Services.Configure((x) => - { - x.UmbracoConnectionString = new ConfigConnectionString(Constants.System.UmbracoConnectionName, TestDBConnectionString); - }); + // This will create a db, install the schema and ensure the app is configured to run + InstallTestLocalDb(databaseFactory, TestHelper.ConsoleLoggerFactory, state, TestHelper.WorkingDirectory); + TestDBConnectionString = databaseFactory.ConnectionString; + InMemoryConfiguration["ConnectionStrings:" + Constants.System.UmbracoConnectionName] = TestDBConnectionString; } /// diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationRepositoryTest.cs index 511d20588f..56bacb93a9 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/RelationRepositoryTest.cs @@ -8,21 +8,18 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; -using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Integration.Testing; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositories { [TestFixture] - [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] + [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, Boot = true)] public class RelationRepositoryTest : UmbracoIntegrationTest { private RelationType _relateContent; diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs index 2976aca085..5542f926e1 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Scoping/ScopedRepositoryTests.cs @@ -44,6 +44,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Scoping return result; } + [TearDown] public void Teardown() { diff --git a/src/Umbraco.Tests.UnitTests/TestHelpers/BaseUsingSqlSyntax.cs b/src/Umbraco.Tests.UnitTests/TestHelpers/BaseUsingSqlSyntax.cs index bf3f14004a..4093dfb892 100644 --- a/src/Umbraco.Tests.UnitTests/TestHelpers/BaseUsingSqlSyntax.cs +++ b/src/Umbraco.Tests.UnitTests/TestHelpers/BaseUsingSqlSyntax.cs @@ -1,4 +1,5 @@ using System; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Moq; using NPoco; @@ -11,6 +12,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Tests.UnitTests.TestHelpers; +using Umbraco.Web.Common.Builder; namespace Umbraco.Tests.TestHelpers { @@ -32,7 +34,8 @@ namespace Umbraco.Tests.TestHelpers var container = TestHelper.GetServiceCollection(); var typeLoader = TestHelper.GetMockedTypeLoader(); - var composition = new Composition(container, typeLoader, Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(container, Mock.Of(), TestHelper.GetMockedTypeLoader()); + composition.WithCollectionBuilder() .AddCoreMappers(); diff --git a/src/Umbraco.Tests.UnitTests/TestHelpers/CompositionExtensions.cs b/src/Umbraco.Tests.UnitTests/TestHelpers/CompositionExtensions.cs index 6a4f228070..7bbfed4e85 100644 --- a/src/Umbraco.Tests.UnitTests/TestHelpers/CompositionExtensions.cs +++ b/src/Umbraco.Tests.UnitTests/TestHelpers/CompositionExtensions.cs @@ -1,5 +1,6 @@ using System; using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; namespace Umbraco.Tests.UnitTests.TestHelpers @@ -7,10 +8,10 @@ namespace Umbraco.Tests.UnitTests.TestHelpers public static class CompositionExtensions { [Obsolete("This extension method exists only to ease migration, please refactor")] - public static IServiceProvider CreateServiceProvider(this Composition composition) + public static IServiceProvider CreateServiceProvider(this IUmbracoBuilder builder) { - composition.RegisterBuilders(); - return composition.Services.BuildServiceProvider(); + builder.Build(); + return builder.Services.BuildServiceProvider(); } } } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs index f9cfef38c3..4cc2a54327 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; @@ -9,6 +10,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; @@ -19,6 +21,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; +using Umbraco.Web.Common.Builder; namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components { @@ -49,7 +52,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components mock.Setup(x => x.GetService(typeof (ILogger))).Returns(logger); mock.Setup(x => x.GetService(typeof(ILogger))).Returns(loggerFactory.CreateLogger); mock.Setup(x => x.GetService(typeof(ILoggerFactory))).Returns(loggerFactory); - mock.Setup(x => x.GetService(typeof (IProfilingLogger))).Returns(new ProfilingLogger(logger, Mock.Of())); + mock.Setup(x => x.GetService(typeof (IProfilingLogger))).Returns(new ProfilingLogger(loggerFactory.CreateLogger(), Mock.Of())); mock.Setup(x => x.GetService(typeof (IUmbracoDatabaseFactory))).Returns(f); mock.Setup(x => x.GetService(typeof (IScopeProvider))).Returns(p); @@ -74,11 +77,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void Boot1A() { var register = MockRegister(); - var typeLoader = MockTypeLoader(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = TypeArray(); - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); // 2 is Core and requires 4 // 3 is User @@ -94,7 +96,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components if (type == typeof(Composer1)) return new Composer1(); if (type == typeof(Composer5)) return new Composer5(); if (type == typeof(Component5)) return new Component5(new SomeResource()); - if (type == typeof(IProfilingLogger)) return new ProfilingLogger(Mock.Of(), Mock.Of()); + if (type == typeof(IProfilingLogger)) return new ProfilingLogger(Mock.Of>(), Mock.Of()); if (type == typeof(ILogger)) return Mock.Of>(); throw new NotSupportedException(type.FullName); }); @@ -115,10 +117,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void Boot1B() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(x=>x.Level == RuntimeLevel.Run), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = TypeArray(); - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); // 2 is Core and requires 4 // 3 is User - stays with RuntimeLevel.Run @@ -131,10 +133,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void Boot2() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = TypeArray(); - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); // 21 is required by 20 // => reorder components accordingly @@ -146,10 +148,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void Boot3() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = TypeArray(); - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); // i23 requires 22 // 24, 25 implement i23 @@ -163,10 +165,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void BrokenRequire() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = TypeArray(); - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); try { @@ -186,10 +188,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void BrokenRequired() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = TypeArray(); - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); // 2 is Core and requires 4 // 13 is required by 1 @@ -218,15 +220,15 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components if (type == typeof(Composer5a)) return new Composer5a(); if (type == typeof(Component5)) return new Component5(new SomeResource()); if (type == typeof(Component5a)) return new Component5a(); - if (type == typeof(IProfilingLogger)) return new ProfilingLogger(Mock.Of(), Mock.Of()); + if (type == typeof(IProfilingLogger)) return new ProfilingLogger(Mock.Of>(), Mock.Of()); if (type == typeof(ILogger)) return Mock.Of>(); throw new NotSupportedException(type.FullName); }); }); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = new[] { typeof(Composer1), typeof(Composer5), typeof(Composer5a) }; - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Assert.IsEmpty(Composed); composers.Compose(); @@ -249,10 +251,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void Requires1() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = new[] { typeof(Composer6), typeof(Composer7), typeof(Composer8) }; - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); composers.Compose(); Assert.AreEqual(2, Composed.Count); @@ -264,10 +266,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void Requires2A() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) }; - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); composers.Compose(); Assert.AreEqual(3, Composed.Count); @@ -281,10 +283,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components var register = MockRegister(); var typeLoader = MockTypeLoader(); var factory = MockFactory(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(x=>x.Level == RuntimeLevel.Run), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) }; - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); composers.Compose(); var builder = composition.WithCollectionBuilder(); @@ -300,35 +302,35 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void WeakDependencies() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = new[] { typeof(Composer10) }; - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); composers.Compose(); Assert.AreEqual(1, Composed.Count); Assert.AreEqual(typeof(Composer10), Composed[0]); types = new[] { typeof(Composer11) }; - composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); Assert.Throws(() => composers.Compose()); Console.WriteLine("throws:"); - composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); var requirements = composers.GetRequirements(false); Console.WriteLine(Composers.GetComposersReport(requirements)); types = new[] { typeof(Composer2) }; - composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); Assert.Throws(() => composers.Compose()); Console.WriteLine("throws:"); - composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); requirements = composers.GetRequirements(false); Console.WriteLine(Composers.GetComposersReport(requirements)); types = new[] { typeof(Composer12) }; - composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); composers.Compose(); Assert.AreEqual(1, Composed.Count); @@ -339,10 +341,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void DisableMissing() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = new[] { typeof(Composer6), typeof(Composer8) }; // 8 disables 7 which is not in the list - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>()); Composed.Clear(); composers.Compose(); Assert.AreEqual(2, Composed.Count); @@ -354,17 +356,17 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public void AttributesPriorities() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), Mock.Of(), IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); var types = new[] { typeof(Composer26) }; var enableDisableAttributes = new[] { new DisableComposerAttribute(typeof(Composer26)) }; - var composers = new Composers(composition, types, enableDisableAttributes, Mock.Of>(), Mock.Of()); + var composers = new Composers(composition, types, enableDisableAttributes, Mock.Of>()); Composed.Clear(); composers.Compose(); Assert.AreEqual(0, Composed.Count); // 26 gone types = new[] { typeof(Composer26), typeof(Composer27) }; // 26 disabled by assembly attribute, enabled by 27 - composers = new Composers(composition, types, enableDisableAttributes, Mock.Of>(), Mock.Of()); + composers = new Composers(composition, types, enableDisableAttributes, Mock.Of>()); Composed.Clear(); composers.Compose(); Assert.AreEqual(2, Composed.Count); // both @@ -380,12 +382,12 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components var typeLoader = new TypeLoader(typeFinder, AppCaches.Disabled.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), Mock.Of>(), Mock.Of()); var register = MockRegister(); - var composition = new Composition(register, typeLoader, Mock.Of(), - Mock.Of(), IOHelper, AppCaches.NoCache); + var builder = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); + var allComposers = typeLoader.GetTypes().ToList(); var types = allComposers.Where(x => x.FullName.StartsWith("Umbraco.Core.") || x.FullName.StartsWith("Umbraco.Web")).ToList(); - var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of>(), Mock.Of()); + var composers = new Composers(builder, types, Enumerable.Empty(), Mock.Of>()); var requirements = composers.GetRequirements(); var report = Composers.GetComposersReport(requirements); Console.WriteLine(report); @@ -399,7 +401,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public class TestComposerBase : IComposer { - public virtual void Compose(Composition composition) + public virtual void Compose(IUmbracoBuilder builder) { Composed.Add(GetType()); } @@ -420,20 +422,20 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Components public class Composer5 : TestComposerBase { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); - composition.Components().Append(); + base.Compose(builder); + builder.Components().Append(); } } [ComposeAfter(typeof(Composer5))] public class Composer5a : TestComposerBase { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); - composition.Components().Append(); + base.Compose(builder); + builder.Components().Append(); } } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/CollectionBuildersTests.cs index cb8a88c3ec..6bc33605ac 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/CollectionBuildersTests.cs @@ -1,28 +1,31 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.UnitTests.TestHelpers; +using Umbraco.Web.Common.Builder; namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing { [TestFixture] public class CollectionBuildersTests { - private Composition _composition; + private IUmbracoBuilder _composition; [SetUp] public void Setup() { var register = TestHelper.GetServiceCollection(); - _composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + _composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); } [TearDown] diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/ComposingTestBase.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/ComposingTestBase.cs index fb6e95c875..66d55cda39 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/ComposingTestBase.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/ComposingTestBase.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing [SetUp] public void Initialize() { - ProfilingLogger = new ProfilingLogger(Mock.Of(), Mock.Of()); + ProfilingLogger = new ProfilingLogger(Mock.Of>(), Mock.Of()); var typeFinder = TestHelper.GetTypeFinder(); var ioHelper = TestHelper.IOHelper; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/LazyCollectionBuilderTests.cs index e0a8c28518..c756023151 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/LazyCollectionBuilderTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; @@ -10,6 +11,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.UnitTests.TestHelpers; +using Umbraco.Web.Common.Builder; namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing { @@ -29,7 +31,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing public void LazyCollectionBuilderHandlesTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(container, Mock.Of(), TestHelper.GetMockedTypeLoader()); + composition.WithCollectionBuilder() .Add() @@ -55,7 +58,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing public void LazyCollectionBuilderHandlesProducers() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(container, Mock.Of(), TestHelper.GetMockedTypeLoader()); + composition.WithCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) @@ -80,7 +84,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing public void LazyCollectionBuilderHandlesTypesAndProducers() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(container, Mock.Of(), TestHelper.GetMockedTypeLoader()); + composition.WithCollectionBuilder() .Add() @@ -106,7 +111,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing public void LazyCollectionBuilderThrowsOnIllegalTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(container, Mock.Of(), TestHelper.GetMockedTypeLoader()); composition.WithCollectionBuilder() .Add() @@ -128,7 +133,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing public void LazyCollectionBuilderCanExcludeTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(container, Mock.Of(), TestHelper.GetMockedTypeLoader()); composition.WithCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/PackageActionCollectionTests.cs index b13da91a96..6ebd0c677a 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/PackageActionCollectionTests.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Xml; using System.Xml.Linq; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; @@ -12,6 +13,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.PackageActions; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.UnitTests.TestHelpers; +using Umbraco.Web.Common.Builder; namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing { @@ -23,7 +25,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing { var container = TestHelper.GetServiceCollection(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(container, Mock.Of(), TestHelper.GetMockedTypeLoader()); + var expectedPackageActions = TypeLoader.GetPackageActions(); composition.WithCollectionBuilder() diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs index 7d22b0c958..8486dabcbf 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeLoaderTests.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Composing var typeFinder = TestHelper.GetTypeFinder(); _typeLoader = new TypeLoader(typeFinder, NoAppCache.Instance, new DirectoryInfo(TestHelper.IOHelper.MapPath("~/App_Data/TEMP")), - Mock.Of>(), new ProfilingLogger(Mock.Of(), Mock.Of()), false, + Mock.Of>(), new ProfilingLogger(Mock.Of>(), Mock.Of()), false, // for testing, we'll specify which assemblies are scanned for the PluginTypeResolver // TODO: Should probably update this so it only searches this assembly and add custom types to be found @@ -240,16 +240,16 @@ AnotherContentFinder var list3 = new[] { f1, f3, f5, f7 }; //Act - var hash1 = GetFileHash(list1, new ProfilingLogger(Mock.Of(), Mock.Of())); - var hash2 = GetFileHash(list2, new ProfilingLogger(Mock.Of(), Mock.Of())); - var hash3 = GetFileHash(list3, new ProfilingLogger(Mock.Of(), Mock.Of())); + var hash1 = GetFileHash(list1, new ProfilingLogger(Mock.Of>(), Mock.Of())); + var hash2 = GetFileHash(list2, new ProfilingLogger(Mock.Of>(), Mock.Of())); + var hash3 = GetFileHash(list3, new ProfilingLogger(Mock.Of>(), Mock.Of())); //Assert Assert.AreNotEqual(hash1, hash2); Assert.AreNotEqual(hash1, hash3); Assert.AreNotEqual(hash2, hash3); - Assert.AreEqual(hash1, GetFileHash(list1, new ProfilingLogger(Mock.Of(), Mock.Of()))); + Assert.AreEqual(hash1, GetFileHash(list1, new ProfilingLogger(Mock.Of>(), Mock.Of()))); } [Test] diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/ContentTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/ContentTests.cs index e6adc2eb5e..6b226e7e59 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/ContentTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/ContentTests.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Globalization; using System.Linq; using System.Threading; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Moq; using Newtonsoft.Json; @@ -224,7 +225,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Models private static IProfilingLogger GetTestProfilingLogger() { - var logger = NullLoggerFactory.Instance.CreateLogger("ProfilingLogger"); + var logger = NullLoggerFactory.Instance.CreateLogger(); var profiler = new TestProfiler(); return new ProfilingLogger(logger, profiler); } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs index 613b251249..67c294f5a9 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Published/NestedContentTests.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Published { private (IPublishedContentType, IPublishedContentType) CreateContentTypes() { - var logger = Mock.Of(); + var logger = Mock.Of>(); var loggerFactory = NullLoggerFactory.Instance; var profiler = Mock.Of(); var proflog = new ProfilingLogger(logger, profiler); diff --git a/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs index 3598c75cf7..8d2a6eb217 100644 --- a/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCacheBinderTests.cs @@ -4,6 +4,7 @@ using System.Threading; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Events; @@ -26,13 +27,13 @@ namespace Umbraco.Tests.Cache [UmbracoTest(WithApplication = true)] public class DistributedCacheBinderTests : UmbracoTestBase { - protected override void Compose(Composition composition) + protected override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); // refreshers.HandleEvents wants a UmbracoContext // which wants these - composition.Services.AddUnique(_ => Mock.Of()); - composition.WithCollectionBuilder(); + builder.Services.AddUnique(Mock.Of()); + builder.WithCollectionBuilder(); } [Test] diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index cfcf7a82d8..2e377a0617 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Cache.PublishedCache { base.Compose(); - Composition.WithCollectionBuilder() + Builder.WithCollectionBuilder() .Clear() .Append(); diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index 8623b015a4..170e5e357e 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Text; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -17,6 +18,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Web; +using Umbraco.Web.Common.Builder; using FileSystems = Umbraco.Core.IO.FileSystems; namespace Umbraco.Tests.IO @@ -32,15 +34,8 @@ namespace Umbraco.Tests.IO { _register = TestHelper.GetRegister(); - var composition = new Composition( - _register, - TestHelper.GetMockedTypeLoader(), - Mock.Of(), - Mock.Of(), - TestHelper.IOHelper, - AppCaches.NoCache - ); - + var composition = new UmbracoBuilder(_register, Mock.Of(), TestHelper.GetMockedTypeLoader()); + composition.Services.AddTransient(_ => Mock.Of()); composition.Services.AddTransient(); composition.Services.AddTransient(typeof(ILogger<>), typeof(Logger<>)); diff --git a/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs b/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs index c94f9f5403..b48e3230f6 100644 --- a/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs +++ b/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs @@ -58,7 +58,7 @@ namespace Umbraco.Tests.Packaging // pollute everything, they are ignored by the type finder and explicitely // added to the editors collection - Composition.WithCollectionBuilder() + Builder.WithCollectionBuilder() .Add() .Add(); } @@ -70,7 +70,7 @@ namespace Umbraco.Tests.Packaging if (!withApplication) return; // re-register with actual media fs - Composition.ComposeFileSystems(); + Builder.ComposeFileSystems(); } private PackageDataInstallation PackageDataInstallation => Factory.GetRequiredService(); diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 76e2c52978..d3c9eaf36d 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -20,6 +21,7 @@ using Umbraco.Core.Strings; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.TestHelpers; using Umbraco.Web; +using Umbraco.Web.Common.Builder; using Umbraco.Web.PublishedCache; namespace Umbraco.Tests.Published @@ -35,14 +37,7 @@ namespace Umbraco.Tests.Published // Current.Reset(); var register = TestHelper.GetRegister(); - var composition = new Composition( - register, - TestHelper.GetMockedTypeLoader(), - Mock.Of(), - Mock.Of(), - Mock.Of(), - AppCaches.NoCache - ); + var composition = new UmbracoBuilder(register, Mock.Of(), TestHelper.GetMockedTypeLoader()); composition.WithCollectionBuilder() .Append() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs index 547e7a637f..edcd199463 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.Services.AddUnique(_ => GetServiceContext()); + Builder.Services.AddUnique(GetServiceContext()); } protected ServiceContext GetServiceContext() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index c67382d093..75983ba41a 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -45,7 +45,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.Services.AddUnique(f => new PublishedModelFactory(f.GetRequiredService().GetTypes(), f.GetRequiredService())); + Builder.Services.AddUnique(f => new PublishedModelFactory(f.GetRequiredService().GetTypes(), f.GetRequiredService())); } protected override TypeLoader CreateTypeLoader(IIOHelper ioHelper, ITypeFinder typeFinder, IAppPolicyCache runtimeCache, ILogger logger, IProfilingLogger profilingLogger , IHostingEnvironment hostingEnvironment) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index 0e7bdbc068..a5e72919e2 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -18,6 +18,7 @@ using Umbraco.Web.Routing; using Umbraco.Core.Media; using System; using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core.Security; using Umbraco.Core.Serialization; namespace Umbraco.Tests.PublishedContent @@ -34,7 +35,7 @@ namespace Umbraco.Tests.PublishedContent // FIXME: what about the if (PropertyValueConvertersResolver.HasCurrent == false) ?? // can we risk double - registering and then, what happens? - Composition.WithCollectionBuilder() + Builder.WithCollectionBuilder() .Clear() .Append() .Append() @@ -57,7 +58,7 @@ namespace Umbraco.Tests.PublishedContent var dataTypeService = new TestObjects.TestDataTypeService( new DataType(new RichTextPropertyEditor( loggerFactory, - Mock.Of(), + Mock.Of(), Mock.Of(), Mock.Of(), imageSourceParser, diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index e75abf500d..dea7504e7b 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -28,6 +28,7 @@ using Umbraco.Web.Templates; using Umbraco.Web.Routing; using Current = Umbraco.Web.Composing.Current; using Umbraco.Core.Media; +using Umbraco.Core.Security; using Umbraco.Core.Serialization; namespace Umbraco.Tests.PublishedContent @@ -43,17 +44,18 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); _publishedSnapshotAccessorMock = new Mock(); - Composition.Services.AddUnique(_publishedSnapshotAccessorMock.Object); + Builder.Services.AddUnique(_publishedSnapshotAccessorMock.Object); - Composition.Services.AddUnique(f => new PublishedModelFactory(f.GetRequiredService().GetTypes(), f.GetRequiredService())); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(f => new PublishedModelFactory(f.GetRequiredService().GetTypes(), f.GetRequiredService())); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); var loggerFactory = NullLoggerFactory.Instance; var mediaService = Mock.Of(); var mediaFileService = Mock.Of(); var contentTypeBaseServiceProvider = Mock.Of(); var umbracoContextAccessor = Mock.Of(); + var backOfficeSecurityAccessor = Mock.Of(); var publishedUrlProvider = Mock.Of(); var imageSourceParser = new HtmlImageSourceParser(publishedUrlProvider); var serializer = new ConfigurationEditorJsonSerializer(); @@ -64,11 +66,11 @@ namespace Umbraco.Tests.PublishedContent var dataTypeService = new TestObjects.TestDataTypeService( new DataType(new VoidEditor(loggerFactory, Mock.Of(), localizationService, LocalizedTextService, ShortStringHelper), serializer) { Id = 1 }, new DataType(new TrueFalsePropertyEditor(loggerFactory, Mock.Of(), localizationService, IOHelper, ShortStringHelper, LocalizedTextService), serializer) { Id = 1001 }, - new DataType(new RichTextPropertyEditor(loggerFactory,umbracoContextAccessor, Mock.Of(), localizationService, imageSourceParser, linkParser, pastedImages, ShortStringHelper, IOHelper, LocalizedTextService, Mock.Of()), serializer) { Id = 1002 }, + new DataType(new RichTextPropertyEditor(loggerFactory,backOfficeSecurityAccessor, Mock.Of(), localizationService, imageSourceParser, linkParser, pastedImages, ShortStringHelper, IOHelper, LocalizedTextService, Mock.Of()), serializer) { Id = 1002 }, new DataType(new IntegerPropertyEditor(loggerFactory, Mock.Of(), localizationService, ShortStringHelper, LocalizedTextService), serializer) { Id = 1003 }, new DataType(new TextboxPropertyEditor(loggerFactory, Mock.Of(), localizationService, IOHelper, ShortStringHelper, LocalizedTextService), serializer) { Id = 1004 }, new DataType(new MediaPickerPropertyEditor(loggerFactory, Mock.Of(), localizationService, IOHelper, ShortStringHelper, LocalizedTextService), serializer) { Id = 1005 }); - Composition.Services.AddUnique(f => dataTypeService); + Builder.Services.AddUnique(f => dataTypeService); } protected override void Initialize() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index c53cbea9e9..9262c72dfa 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -43,11 +43,11 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.WithCollectionBuilder() + Builder.WithCollectionBuilder() .Clear() .Append(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); } private IMediaType MakeNewMediaType(IUser user, string text, int parentId = -1) diff --git a/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs b/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs index 84e22c7760..d9c6021534 100644 --- a/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs +++ b/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Routing protected override void Compose() { base.Compose(); - Composition.Services.AddTransient(); + Builder.Services.AddTransient(); } protected override void ComposeSettings() @@ -28,8 +28,8 @@ namespace Umbraco.Tests.Routing var contentSettings = new ContentSettings(); var userPasswordConfigurationSettings = new UserPasswordConfigurationSettings(); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(contentSettings)); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(userPasswordConfigurationSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(contentSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(userPasswordConfigurationSettings)); } protected IPublishedUrlProvider GetPublishedUrlProvider(IUmbracoContext umbracoContext, DefaultUrlProvider urlProvider) diff --git a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs index edcbf858e2..c51ca27b8c 100644 --- a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs +++ b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs @@ -15,7 +15,7 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Composition.Services.AddTransient(); + Builder.Services.AddTransient(); } private void SetDomains1() diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index b3663738dd..9332dc894a 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -5,23 +5,17 @@ using System.Web.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Hosting; -using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Runtime; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.Common; -using Umbraco.Tests.Common.Builders; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; @@ -31,7 +25,6 @@ using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Web.Runtime; using Umbraco.Web.WebApi; -using ConnectionStrings = Umbraco.Core.Configuration.Models.ConnectionStrings; using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Tests.Routing @@ -53,15 +46,6 @@ namespace Umbraco.Tests.Routing HostingEnvironment); } - public class TestRuntimeBootstrapper : CoreRuntimeBootstrapper - { - public TestRuntimeBootstrapper(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) - : base(globalSettings, connectionStrings,umbracoVersion, ioHelper, NullLoggerFactory.Instance, Mock.Of(), new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), AppCaches.NoCache) - { - } - - } - protected override void Compose() { base.Compose(); @@ -72,11 +56,11 @@ namespace Umbraco.Tests.Routing // var surfaceControllerTypes = new SurfaceControllerTypeCollection(Composition.TypeLoader.GetSurfaceControllers()); // Composition.Services.AddUnique(surfaceControllerTypes); - var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Composition.TypeLoader.GetUmbracoApiControllers()); - Composition.Services.AddUnique(umbracoApiControllerTypes); + var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Builder.TypeLoader.GetUmbracoApiControllers()); + Builder.Services.AddUnique(umbracoApiControllerTypes); var requestHandlerSettings = new RequestHandlerSettings(); - Composition.Services.AddUnique(_ => new DefaultShortStringHelper(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings))); + Builder.Services.AddUnique(_ => new DefaultShortStringHelper(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings))); } public override void TearDown() diff --git a/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs b/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs index eba88383e7..c403ade51c 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Routing protected override void ComposeSettings() { base.ComposeSettings(); - Composition.Services.AddUnique(x => Microsoft.Extensions.Options.Options.Create(_globalSettings)); + Builder.Services.AddUnique(x => Microsoft.Extensions.Options.Options.Create(_globalSettings)); } [TestCase(1046, "/")] diff --git a/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs b/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs index 9e0d311188..fd87ce84b1 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Routing protected override void ComposeSettings() { base.ComposeSettings(); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(_globalSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(_globalSettings)); } /// diff --git a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs index 346af19a4c..4c658379cd 100644 --- a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs +++ b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Composition.Services.AddUnique(_ => GetServiceContext()); + Builder.Services.AddUnique(GetServiceContext()); } protected ServiceContext GetServiceContext() diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index 5fef721dfa..80b92b4d1b 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -25,8 +25,8 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Composition.Services.AddUnique(_ => Mock.Of()); - Composition.Services.AddTransient(); + Builder.Services.AddUnique(Mock.Of()); + Builder.Services.AddTransient(); } void SetDomains1() diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index f367db2123..10cb8c9ac4 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -27,8 +27,8 @@ namespace Umbraco.Tests.Routing protected override void Compose() { base.Compose(); - Composition.Services.AddUnique(_ => Mock.Of()); - Composition.Services.AddTransient(); + Builder.Services.AddUnique(Mock.Of()); + Builder.Services.AddTransient(); } [Test] diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 59f9a43526..5ab6aeaa1d 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging; using Moq; @@ -20,6 +21,7 @@ using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Web; using Current = Umbraco.Web.Composing.Current; using Microsoft.Extensions.DependencyInjection; +using Umbraco.Web.Common.Builder; namespace Umbraco.Tests.Scoping { @@ -38,7 +40,7 @@ namespace Umbraco.Tests.Scoping var services = TestHelper.GetRegister(); - var composition = new Composition(services, TestHelper.GetMockedTypeLoader(), Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(services, Mock.Of(), TestHelper.GetMockedTypeLoader()); _testObjects = new TestObjects(services); diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 5968a13ce8..f32ce9d9e1 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -43,10 +43,10 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // FIXME: and we cannot inject a DistributedCache yet // so doing all this mess - Composition.Services.AddUnique(); - Composition.Services.AddUnique(f => Mock.Of()); - Composition.WithCollectionBuilder() - .Add(() => Composition.TypeLoader.GetCacheRefreshers()); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(f => Mock.Of()); + Builder.WithCollectionBuilder() + .Add(() => Builder.TypeLoader.GetCacheRefreshers()); } public override void TearDown() diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 3a07a9864a..6814210cc4 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -38,10 +38,10 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // FIXME: and we cannot inject a DistributedCache yet // so doing all this mess - Composition.Services.AddUnique(); - Composition.Services.AddUnique(f => Mock.Of()); - Composition.WithCollectionBuilder() - .Add(() => Composition.TypeLoader.GetCacheRefreshers()); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(f => Mock.Of()); + Builder.WithCollectionBuilder() + .Add(() => Builder.TypeLoader.GetCacheRefreshers()); } protected override void ComposeSettings() @@ -50,9 +50,9 @@ namespace Umbraco.Tests.Scoping var globalSettings = new GlobalSettings(); var userPasswordConfigurationSettings = new UserPasswordConfigurationSettings(); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(contentSettings)); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(globalSettings)); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(userPasswordConfigurationSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(contentSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(globalSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(userPasswordConfigurationSettings)); } [TearDown] diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index ddfc6fa7f1..a048c76022 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Moq; using NPoco; @@ -14,6 +15,7 @@ using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence; using Umbraco.Persistance.SqlCe; using Umbraco.Web; +using Umbraco.Web.Common.Builder; using Current = Umbraco.Web.Composing.Current; namespace Umbraco.Tests.TestHelpers @@ -38,7 +40,7 @@ namespace Umbraco.Tests.TestHelpers var services = TestHelper.GetRegister(); var ioHelper = TestHelper.IOHelper; - var logger = new ProfilingLogger(Mock.Of(), Mock.Of()); + var logger = new ProfilingLogger(Mock.Of>(), Mock.Of()); var typeFinder = TestHelper.GetTypeFinder(); var typeLoader = new TypeLoader(typeFinder, NoAppCache.Instance, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), @@ -46,7 +48,8 @@ namespace Umbraco.Tests.TestHelpers logger, false); - var composition = new Composition(services, typeLoader, Mock.Of(), Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new UmbracoBuilder(services, Mock.Of(), TestHelper.GetMockedTypeLoader()); + services.AddUnique(_ => Mock.Of()); services.AddUnique(_ => NullLoggerFactory.Instance); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index eaa186bef6..c6587f6ad8 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -37,8 +37,8 @@ namespace Umbraco.Tests.TestHelpers { base.Compose(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); } protected override void Initialize() @@ -109,7 +109,7 @@ namespace Umbraco.Tests.TestHelpers contentFinders ?? new ContentFinderCollection(Enumerable.Empty()), new TestLastChanceFinder(), new TestVariationContextAccessor(), - new ProfilingLogger(Mock.Of(), Mock.Of()), + new ProfilingLogger(Mock.Of>(), Mock.Of()), Mock.Of>(), Mock.Of(), Mock.Of(), diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 53a7e7ba36..faf387528d 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -73,18 +73,18 @@ namespace Umbraco.Tests.TestHelpers { base.Compose(); - Composition.Services.AddTransient(); - Composition.Services.AddTransient(factory => PublishedSnapshotService); - Composition.Services.AddTransient(factory => DefaultCultureAccessor); + Builder.Services.AddTransient(); + Builder.Services.AddTransient(factory => PublishedSnapshotService); + Builder.Services.AddTransient(factory => DefaultCultureAccessor); - Composition.WithCollectionBuilder() + Builder.WithCollectionBuilder() .Clear() - .Add(() => Composition.TypeLoader.GetDataEditors()); + .Add(() => Builder.TypeLoader.GetDataEditors()); - Composition.WithCollectionBuilder() - .Add(Composition.TypeLoader.GetUmbracoApiControllers()); + Builder.WithCollectionBuilder() + .Add(Builder.TypeLoader.GetUmbracoApiControllers()); - Composition.Services.AddUnique(f => + Builder.Services.AddUnique(f => { if (Options.Database == UmbracoTestOptions.Database.None) return TestObjects.GetDatabaseFactoryMock(); diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index 9c259d7d16..2d9c66806b 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -19,6 +19,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Templates; using Umbraco.Core.Persistence; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Tests.Common; using Umbraco.Tests.TestHelpers; @@ -63,11 +64,11 @@ namespace Umbraco.Tests.Testing.TestingTests public void Can_Mock_Umbraco_Helper() { // unless we can inject them in MembershipHelper, we need need this - Composition.Services.AddTransient(_ => Mock.Of()); - Composition.Services.AddTransient(_ => Mock.Of()); - Composition.Services.AddTransient(_ => Mock.Of()); - Composition.Services.AddTransient(_ => AppCaches.Disabled); - Composition.Services.AddTransient(); + Builder.Services.AddTransient(_ => Mock.Of()); + Builder.Services.AddTransient(_ => Mock.Of()); + Builder.Services.AddTransient(_ => Mock.Of()); + Builder.Services.AddTransient(_ => AppCaches.Disabled); + Builder.Services.AddTransient(); // ReSharper disable once UnusedVariable var helper = new UmbracoHelper(Mock.Of(), @@ -113,7 +114,7 @@ namespace Umbraco.Tests.Testing.TestingTests var membershipHelper = new MembershipHelper(Mock.Of(), Mock.Of(), membershipProvider, Mock.Of(), memberService, memberTypeService, Mock.Of(), AppCaches.Disabled, NullLoggerFactory.Instance, ShortStringHelper, Mock.Of()); var umbracoMapper = new UmbracoMapper(new MapDefinitionCollection(new[] { Mock.Of() })); - var umbracoApiController = new FakeUmbracoApiController(new GlobalSettings(), Mock.Of(), Mock.Of(), ServiceContext.CreatePartial(), AppCaches.NoCache, profilingLogger , Mock.Of(), umbracoMapper, Mock.Of()); + var umbracoApiController = new FakeUmbracoApiController(new GlobalSettings(), Mock.Of(), Mock.Of(), Mock.Of(), ServiceContext.CreatePartial(), AppCaches.NoCache, profilingLogger , Mock.Of(), umbracoMapper, Mock.Of()); Assert.Pass(); } @@ -121,7 +122,7 @@ namespace Umbraco.Tests.Testing.TestingTests internal class FakeUmbracoApiController : UmbracoApiController { - public FakeUmbracoApiController(GlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { } + public FakeUmbracoApiController(GlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + : base(globalSettings, umbracoContextAccessor, backOfficeSecurityAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { } } } diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 4466b9424e..b780665c23 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -9,6 +9,7 @@ using System.Web.Routing; using System.Web.Security; using System.Xml.Linq; using Examine; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -16,6 +17,7 @@ using Moq; using NUnit.Framework; using Serilog; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Composing.CompositionExtensions; @@ -50,6 +52,7 @@ using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; using Umbraco.Web.Actions; using Umbraco.Web.AspNet; +using Umbraco.Web.Common.Builder; using Umbraco.Web.ContentApps; using Umbraco.Web.Hosting; using Umbraco.Web.Install; @@ -103,7 +106,7 @@ namespace Umbraco.Tests.Testing // test feature, and no test "base" class should be. only actual test feature classes // should be marked with that attribute. - protected Composition Composition { get; private set; } + protected IUmbracoBuilder Builder { get; private set; } protected IServiceProvider Factory { get; private set; } @@ -186,7 +189,7 @@ namespace Umbraco.Tests.Testing _loggerFactory = loggerFactory; var profiler = new LogProfiler(loggerFactory.CreateLogger()); var msLogger = loggerFactory.CreateLogger("msLogger"); - var proflogger = new ProfilingLogger(loggerFactory.CreateLogger("ProfilingLogger"), profiler); + var proflogger = new ProfilingLogger(loggerFactory.CreateLogger(), profiler); IOHelper = TestHelper.IOHelper; TypeFinder = new TypeFinder(loggerFactory.CreateLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly), new VaryingRuntimeHash()); @@ -204,15 +207,7 @@ namespace Umbraco.Tests.Testing var services = TestHelper.GetRegister(); - - Composition = new Composition( - services, - typeLoader, - proflogger, - MockRuntimeState(RuntimeLevel.Run), - TestHelper.IOHelper, - AppCaches.NoCache - ); + Builder = new UmbracoBuilder(services, Mock.Of(), typeLoader); //TestHelper.GetConfigs().RegisterWith(register); services.AddUnique(typeof(ILoggerFactory), loggerFactory); @@ -248,7 +243,7 @@ namespace Umbraco.Tests.Testing TestObjects = new TestObjects(services); Compose(); - Current.Factory = Factory = Composition.CreateServiceProvider(); + Current.Factory = Factory = Builder.CreateServiceProvider(); Initialize(); } @@ -263,10 +258,10 @@ namespace Umbraco.Tests.Testing ComposeMisc(); // not sure really - Compose(Composition); + Compose(Builder); } - protected virtual void Compose(Composition composition) + protected virtual void Compose(IUmbracoBuilder builder) { } protected virtual void Initialize() @@ -312,19 +307,21 @@ namespace Umbraco.Tests.Testing Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); // web - Composition.Services.AddUnique(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); - Composition.Services.AddUnique(); - Composition.WithCollectionBuilder(); + Builder.Services.AddUnique(Current.UmbracoContextAccessor); + Builder.Services.AddUnique(new HybridBackofficeSecurityAccessor(AppCaches.NoCache.RequestCache)); + Builder.Services.AddUnique(); + Builder.WithCollectionBuilder(); - Composition.DataValueReferenceFactories(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.SetCultureDictionaryFactory(); - Composition.Services.AddSingleton(f => f.GetRequiredService().CreateDictionary()); + Builder.DataValueReferenceFactories(); + + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.SetCultureDictionaryFactory(); + Builder.Services.AddSingleton(f => f.GetRequiredService().CreateDictionary()); // register back office sections in the order we want them rendered - Composition.WithCollectionBuilder().Append() + Builder.WithCollectionBuilder().Append() .Append() .Append() .Append() @@ -332,18 +329,18 @@ namespace Umbraco.Tests.Testing .Append() .Append() .Append(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); var webRoutingSettings = new WebRoutingSettings(); - Composition.Services.AddUnique(factory => + Builder.Services.AddUnique(factory => new UrlProvider( factory.GetRequiredService(), Microsoft.Extensions.Options.Options.Create(webRoutingSettings), @@ -360,25 +357,25 @@ namespace Umbraco.Tests.Testing // what else? var runtimeStateMock = new Mock(); runtimeStateMock.Setup(x => x.Level).Returns(RuntimeLevel.Run); - Composition.Services.AddUnique(f => runtimeStateMock.Object); - Composition.Services.AddTransient(_ => Mock.Of()); - Composition.Services.AddTransient(); + Builder.Services.AddUnique(f => runtimeStateMock.Object); + Builder.Services.AddTransient(_ => Mock.Of()); + Builder.Services.AddTransient(); // ah... - Composition.WithCollectionBuilder(); - Composition.WithCollectionBuilder(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); + Builder.WithCollectionBuilder(); + Builder.WithCollectionBuilder(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); // register empty content apps collection - Composition.WithCollectionBuilder(); + Builder.WithCollectionBuilder(); // manifest - Composition.ManifestValueValidators(); - Composition.ManifestFilters(); - Composition.MediaUrlGenerators() + Builder.ManifestValueValidators(); + Builder.ManifestFilters(); + Builder.MediaUrlGenerators() .Add() .Add(); @@ -388,7 +385,7 @@ namespace Umbraco.Tests.Testing { if (configure == false) return; - Composition + Builder .ComposeCoreMappingProfiles(); } @@ -442,13 +439,13 @@ namespace Umbraco.Tests.Testing var userPasswordConfigurationSettings = new UserPasswordConfigurationSettings(); var webRoutingSettings = new WebRoutingSettings(); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(contentSettings)); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(coreDebugSettings)); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(globalSettings)); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(nuCacheSettings)); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(requestHandlerSettings)); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(userPasswordConfigurationSettings)); - Composition.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(webRoutingSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(contentSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(coreDebugSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(globalSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(nuCacheSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(requestHandlerSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(userPasswordConfigurationSettings)); + Builder.Services.AddTransient(x => Microsoft.Extensions.Options.Options.Create(webRoutingSettings)); } protected virtual void ComposeApplication(bool withApplication) @@ -458,69 +455,69 @@ namespace Umbraco.Tests.Testing if (withApplication == false) return; // default Datalayer/Repositories/SQL/Database/etc... - Composition.ComposeRepositories(); + Builder.ComposeRepositories(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); // register filesystems - Composition.Services.AddUnique(factory => TestObjects.GetFileSystemsMock()); + Builder.Services.AddUnique(factory => TestObjects.GetFileSystemsMock()); var scheme = Mock.Of(); var mediaFileSystem = new MediaFileSystem(Mock.Of(), scheme, _loggerFactory.CreateLogger(), TestHelper.ShortStringHelper); - Composition.Services.AddUnique(factory => mediaFileSystem); + Builder.Services.AddUnique(factory => mediaFileSystem); // no factory (noop) - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); // register application stuff (database factory & context, services...) - Composition.WithCollectionBuilder() + Builder.WithCollectionBuilder() .AddCoreMappers(); - Composition.Services.AddUnique(_ => new TransientEventMessagesFactory()); + Builder.Services.AddUnique(_ => new TransientEventMessagesFactory()); var globalSettings = new GlobalSettings(); var connectionStrings = new ConnectionStrings(); - Composition.Services.AddUnique(f => new UmbracoDatabaseFactory(_loggerFactory.CreateLogger(), + Builder.Services.AddUnique(f => new UmbracoDatabaseFactory(_loggerFactory.CreateLogger(), LoggerFactory, globalSettings, connectionStrings, new Lazy(f.GetRequiredService), TestHelper.DbProviderFactoryCreator)); - Composition.Services.AddUnique(f => f.GetService().SqlContext); + Builder.Services.AddUnique(f => f.GetService().SqlContext); - Composition.WithCollectionBuilder(); // empty + Builder.WithCollectionBuilder(); // empty - Composition.Services.AddUnique(factory + Builder.Services.AddUnique(factory => TestObjects.GetScopeProvider(_loggerFactory, factory.GetService(), factory.GetService(), factory.GetService())); - Composition.Services.AddUnique(factory => (IScopeAccessor) factory.GetRequiredService()); + Builder.Services.AddUnique(factory => (IScopeAccessor) factory.GetRequiredService()); - Composition.ComposeServices(); + Builder.ComposeServices(); // composition root is doing weird things, fix - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); // somehow property editor ends up wanting this - Composition.WithCollectionBuilder(); + Builder.WithCollectionBuilder(); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); // note - don't register collections, use builders - Composition.WithCollectionBuilder(); - Composition.Services.AddUnique(); - Composition.Services.AddUnique(); + Builder.WithCollectionBuilder(); + Builder.Services.AddUnique(); + Builder.Services.AddUnique(); - Composition.Services.AddUnique(TestHelper.GetHttpContextAccessor(GetHttpContextFactory("/").HttpContext)); + Builder.Services.AddUnique(TestHelper.GetHttpContextAccessor(GetHttpContextFactory("/").HttpContext)); } #endregion diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index ab8884cbaf..59b453cc5b 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -1,4 +1,5 @@ using System.IO; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using NUnit.Framework; using Umbraco.Core; @@ -20,7 +21,7 @@ namespace Umbraco.Tests.UmbracoExamine { // var logger = new SerilogLogger(new FileInfo(TestHelper.MapPathForTestFiles("~/unit-test.config"))); - _profilingLogger = new ProfilingLogger(NullLogger.Instance, new LogProfiler(NullLogger.Instance)); + _profilingLogger = new ProfilingLogger(NullLoggerFactory.Instance.CreateLogger(), new LogProfiler(NullLogger.Instance)); } private IProfilingLogger _profilingLogger; @@ -35,7 +36,7 @@ namespace Umbraco.Tests.UmbracoExamine { base.Compose(); var requestHandlerSettings = new RequestHandlerSettings(); - Composition.Services.AddUnique(_ => new DefaultShortStringHelper(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings))); + Builder.Services.AddUnique(_ => new DefaultShortStringHelper(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings))); } } } diff --git a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs index 040799a09a..39eef86a98 100644 --- a/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs +++ b/src/Umbraco.Tests/UmbracoExamine/IndexInitializer.cs @@ -159,7 +159,7 @@ namespace Umbraco.Tests.UmbracoExamine public static IProfilingLogger GetMockProfilingLogger() { - return new ProfilingLogger(Mock.Of(), Mock.Of()); + return new ProfilingLogger(Mock.Of>(), Mock.Of()); } public static UmbracoContentIndex GetUmbracoIndexer( diff --git a/src/Umbraco.Tests/Web/Controllers/AuthenticationControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/AuthenticationControllerTests.cs index 0cb990df3d..cdc2bfed00 100644 --- a/src/Umbraco.Tests/Web/Controllers/AuthenticationControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/AuthenticationControllerTests.cs @@ -51,12 +51,12 @@ namespace Umbraco.Tests.Web.Controllers // replace the true IUserService implementation with a mock // so that each test can configure the service to their liking - Composition.Services.AddUnique(f => Mock.Of()); + Builder.Services.AddUnique(f => Mock.Of()); // kill the true IEntityService too - Composition.Services.AddUnique(f => Mock.Of()); + Builder.Services.AddUnique(f => Mock.Of()); - Composition.Services.AddUnique(); + Builder.Services.AddUnique(); } diff --git a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs index a5e6051d45..506d2252c0 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Core.Mapping; using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Strings.Css; @@ -36,7 +37,8 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IIOHelper _ioHelper; private readonly IFileSystems _fileSystems; private readonly IFileService _fileService; - private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; + private readonly ILocalizedTextService _localizedTextService; private readonly UmbracoMapper _umbracoMapper; private readonly IShortStringHelper _shortStringHelper; @@ -46,7 +48,7 @@ namespace Umbraco.Web.BackOffice.Controllers IIOHelper ioHelper, IFileSystems fileSystems, IFileService fileService, - IUmbracoContextAccessor umbracoContextAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, ILocalizedTextService localizedTextService, UmbracoMapper umbracoMapper, IShortStringHelper shortStringHelper, @@ -55,7 +57,7 @@ namespace Umbraco.Web.BackOffice.Controllers _ioHelper = ioHelper; _fileSystems = fileSystems; _fileService = fileService; - _umbracoContextAccessor = umbracoContextAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _localizedTextService = localizedTextService; _umbracoMapper = umbracoMapper; _shortStringHelper = shortStringHelper; @@ -74,7 +76,7 @@ namespace Umbraco.Web.BackOffice.Controllers if (display == null) throw new ArgumentNullException("display"); if (string.IsNullOrWhiteSpace(type)) throw new ArgumentException("Value cannot be null or whitespace.", "type"); - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; switch (type) { case Core.Constants.Trees.PartialViews: @@ -324,7 +326,7 @@ namespace Umbraco.Web.BackOffice.Controllers if (string.IsNullOrWhiteSpace(virtualPath)) throw new ArgumentException("Value cannot be null or whitespace.", "virtualPath"); virtualPath = System.Web.HttpUtility.UrlDecode(virtualPath); - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; switch (type) { case Constants.Trees.PartialViews: @@ -557,7 +559,7 @@ namespace Umbraco.Web.BackOffice.Controllers ? relPath + display.Name : relPath.EnsureEndsWith('/') + display.Name; } - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; var file = getFileByName(relPath); if (file != null) { @@ -610,7 +612,7 @@ namespace Umbraco.Web.BackOffice.Controllers display.Name = EnsureCorrectFileExtension(display.Name, ".cshtml"); Attempt partialViewResult; - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; var virtualPath = NormalizeVirtualPath(display.VirtualPath, systemDirectory); var view = getView(virtualPath); diff --git a/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs b/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs index ec2642edb7..d96708b11d 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs @@ -15,6 +15,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Dashboards; +using Umbraco.Core.Security; using Umbraco.Web.Services; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; @@ -33,7 +34,7 @@ namespace Umbraco.Web.BackOffice.Controllers [Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)] public class DashboardController : UmbracoApiController { - private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly AppCaches _appCaches; private readonly ILogger _logger; private readonly IDashboardService _dashboardService; @@ -44,18 +45,15 @@ namespace Umbraco.Web.BackOffice.Controllers /// Initializes a new instance of the with all its dependencies. /// public DashboardController( - IUmbracoContextAccessor umbracoContextAccessor, - ISqlContext sqlContext, - ServiceContext services, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, AppCaches appCaches, ILogger logger, - IRuntimeState runtimeState, IDashboardService dashboardService, IUmbracoVersion umbracoVersion, IShortStringHelper shortStringHelper) { - _umbracoContextAccessor = umbracoContextAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _appCaches = appCaches; _logger = logger; _dashboardService = dashboardService; @@ -70,7 +68,7 @@ namespace Umbraco.Web.BackOffice.Controllers [ValidateAngularAntiForgeryToken] public async Task GetRemoteDashboardContent(string section, string baseUrl = "https://dashboard.umbraco.org/") { - var user = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var user = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; var allowedSections = string.Join(",", user.AllowedSections); var language = user.Language; var version = _umbracoVersion.SemanticVersion.ToSemanticString(); @@ -215,7 +213,7 @@ namespace Umbraco.Web.BackOffice.Controllers [TypeFilter(typeof(OutgoingEditorModelEventAttribute))] public IEnumerable> GetDashboard(string section) { - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; return _dashboardService.GetDashboards(section, currentUser).Select(x => new Tab { Id = x.Id, diff --git a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs index 664eab13cc..0ffe64e251 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Configuration.Models; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Security; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Filters; @@ -45,7 +46,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IMediaTypeService _mediaTypeService; private readonly IMemberTypeService _memberTypeService; private readonly ILocalizedTextService _localizedTextService; - private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly IConfigurationEditorJsonSerializer _serializer; public DataTypeController( @@ -58,7 +59,7 @@ namespace Umbraco.Web.BackOffice.Controllers IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, ILocalizedTextService localizedTextService, - IUmbracoContextAccessor umbracoContextAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IConfigurationEditorJsonSerializer serializer) { _propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors)); @@ -70,7 +71,7 @@ namespace Umbraco.Web.BackOffice.Controllers _mediaTypeService = mediaTypeService ?? throw new ArgumentNullException(nameof(mediaTypeService)); _memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService)); _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); - _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); + _backOfficeSecurityAccessor = backOfficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backOfficeSecurityAccessor)); _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); } @@ -151,7 +152,7 @@ namespace Umbraco.Web.BackOffice.Controllers { throw new HttpResponseException(HttpStatusCode.NotFound); } - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; _dataTypeService.Delete(foundType, currentUser.Id); return Ok(); @@ -251,7 +252,7 @@ namespace Umbraco.Web.BackOffice.Controllers public IActionResult DeleteContainer(int id) { - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; _dataTypeService.DeleteContainer(id, currentUser.Id); return Ok(); @@ -259,7 +260,7 @@ namespace Umbraco.Web.BackOffice.Controllers public IActionResult PostCreateContainer(int parentId, string name) { - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; var result = _dataTypeService.CreateContainer(parentId, name, currentUser.Id); return result @@ -289,7 +290,7 @@ namespace Umbraco.Web.BackOffice.Controllers dataType.PersistedDataType.Configuration = configuration; - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; // save the data type try { @@ -346,7 +347,7 @@ namespace Umbraco.Web.BackOffice.Controllers public IActionResult PostRenameContainer(int id, string name) { - var currentUser = _umbracoContextAccessor.GetRequiredUmbracoContext().Security.CurrentUser; + var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser; var result = _dataTypeService.RenameContainer(id, name, currentUser.Id); return result diff --git a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs index 6daf5849b1..762e405d62 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs @@ -22,39 +22,6 @@ namespace Umbraco.Extensions { public static class BackOfficeServiceCollectionExtensions { - /// - /// Adds the services required for running the Umbraco back office - /// - /// - public static void AddUmbracoBackOffice(this IServiceCollection services) - { - services.AddAntiforgery(); - - // TODO: We had this check in v8 where we don't enable these unless we can run... - //if (runtimeState.Level != RuntimeLevel.Upgrade && runtimeState.Level != RuntimeLevel.Run) return app; - - services.AddSingleton(); - services - .AddAuthentication(Constants.Security.BackOfficeAuthenticationType) - .AddCookie(Constants.Security.BackOfficeAuthenticationType) - .AddCookie(Constants.Security.BackOfficeExternalAuthenticationType, o => - { - o.Cookie.Name = Constants.Security.BackOfficeExternalAuthenticationType; - o.ExpireTimeSpan = TimeSpan.FromMinutes(5); - }); - - // TODO: Need to add more cookie options, see https://github.com/dotnet/aspnetcore/blob/3.0/src/Identity/Core/src/IdentityServiceCollectionExtensions.cs#L45 - - services.ConfigureOptions(); - - services.AddUmbracoCommonAuthorizationPolicies(); - services.AddBackOfficeAuthorizationPolicies(); - } - - public static void AddUmbracoPreview(this IServiceCollection services) - { - services.AddSignalR(); - } /// /// Adds the services required for using Umbraco back office Identity @@ -116,7 +83,7 @@ namespace Umbraco.Extensions /// Add authorization handlers and policies /// /// - private static void AddBackOfficeAuthorizationPolicies(this IServiceCollection services) + public static void AddBackOfficeAuthorizationPolicies(this IServiceCollection services) { // NOTE: Even though we are registering these handlers globally they will only actually execute their logic for // any auth defining a matching requirement and scheme. @@ -133,313 +100,315 @@ namespace Umbraco.Extensions services.AddSingleton(); services.AddSingleton(); - services.AddAuthorization(options => + services.AddAuthorization(CreatePolicies); + } + + private static void CreatePolicies(AuthorizationOptions options) + { + options.AddPolicy(AuthorizationPolicies.MediaPermissionPathById, policy => { - options.AddPolicy(AuthorizationPolicies.MediaPermissionPathById, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new MediaPermissionsQueryStringRequirement("id")); - }); + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new MediaPermissionsQueryStringRequirement("id")); + }); - options.AddPolicy(AuthorizationPolicies.ContentPermissionEmptyRecycleBin, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(Constants.System.RecycleBinContent, ActionDelete.ActionLetter)); - }); + options.AddPolicy(AuthorizationPolicies.ContentPermissionEmptyRecycleBin, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(Constants.System.RecycleBinContent, ActionDelete.ActionLetter)); + }); - options.AddPolicy(AuthorizationPolicies.ContentPermissionAdministrationById, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionRights.ActionLetter)); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionRights.ActionLetter, "contentId")); - }); + options.AddPolicy(AuthorizationPolicies.ContentPermissionAdministrationById, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionRights.ActionLetter)); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionRights.ActionLetter, "contentId")); + }); - options.AddPolicy(AuthorizationPolicies.ContentPermissionProtectById, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionProtect.ActionLetter)); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionProtect.ActionLetter, "contentId")); - }); + options.AddPolicy(AuthorizationPolicies.ContentPermissionProtectById, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionProtect.ActionLetter)); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionProtect.ActionLetter, "contentId")); + }); - options.AddPolicy(AuthorizationPolicies.ContentPermissionRollbackById, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionRollback.ActionLetter)); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionRollback.ActionLetter, "contentId")); - }); + options.AddPolicy(AuthorizationPolicies.ContentPermissionRollbackById, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionRollback.ActionLetter)); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionRollback.ActionLetter, "contentId")); + }); - options.AddPolicy(AuthorizationPolicies.ContentPermissionPublishById, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionPublish.ActionLetter)); - }); + options.AddPolicy(AuthorizationPolicies.ContentPermissionPublishById, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionPublish.ActionLetter)); + }); - options.AddPolicy(AuthorizationPolicies.ContentPermissionBrowseById, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionBrowse.ActionLetter)); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionBrowse.ActionLetter, "contentId")); - }); + options.AddPolicy(AuthorizationPolicies.ContentPermissionBrowseById, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionBrowse.ActionLetter)); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionBrowse.ActionLetter, "contentId")); + }); - options.AddPolicy(AuthorizationPolicies.ContentPermissionDeleteById, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionDelete.ActionLetter)); - }); + options.AddPolicy(AuthorizationPolicies.ContentPermissionDeleteById, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new ContentPermissionsQueryStringRequirement(ActionDelete.ActionLetter)); + }); - options.AddPolicy(AuthorizationPolicies.BackOfficeAccess, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new BackOfficeRequirement()); - }); + options.AddPolicy(AuthorizationPolicies.BackOfficeAccess, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new BackOfficeRequirement()); + }); - options.AddPolicy(AuthorizationPolicies.BackOfficeAccessWithoutApproval, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new BackOfficeRequirement(false)); - }); + options.AddPolicy(AuthorizationPolicies.BackOfficeAccessWithoutApproval, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new BackOfficeRequirement(false)); + }); - options.AddPolicy(AuthorizationPolicies.AdminUserEditsRequireAdmin, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new AdminUsersRequirement()); - policy.Requirements.Add(new AdminUsersRequirement("userIds")); - }); + options.AddPolicy(AuthorizationPolicies.AdminUserEditsRequireAdmin, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new AdminUsersRequirement()); + policy.Requirements.Add(new AdminUsersRequirement("userIds")); + }); - options.AddPolicy(AuthorizationPolicies.UserBelongsToUserGroupInRequest, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new UserGroupRequirement()); - policy.Requirements.Add(new UserGroupRequirement("userGroupIds")); - }); + options.AddPolicy(AuthorizationPolicies.UserBelongsToUserGroupInRequest, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new UserGroupRequirement()); + policy.Requirements.Add(new UserGroupRequirement("userGroupIds")); + }); - options.AddPolicy(AuthorizationPolicies.DenyLocalLoginIfConfigured, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new DenyLocalLoginRequirement()); - }); + options.AddPolicy(AuthorizationPolicies.DenyLocalLoginIfConfigured, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new DenyLocalLoginRequirement()); + }); - options.AddPolicy(AuthorizationPolicies.SectionAccessContent, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement(Constants.Applications.Content)); - }); + options.AddPolicy(AuthorizationPolicies.SectionAccessContent, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement(Constants.Applications.Content)); + }); - options.AddPolicy(AuthorizationPolicies.SectionAccessContentOrMedia, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement(Constants.Applications.Content, Constants.Applications.Media)); - }); + options.AddPolicy(AuthorizationPolicies.SectionAccessContentOrMedia, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement(Constants.Applications.Content, Constants.Applications.Media)); + }); - options.AddPolicy(AuthorizationPolicies.SectionAccessUsers, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement(Constants.Applications.Users)); - }); + options.AddPolicy(AuthorizationPolicies.SectionAccessUsers, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement(Constants.Applications.Users)); + }); - options.AddPolicy(AuthorizationPolicies.SectionAccessForTinyMce, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement( - Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members)); - }); + options.AddPolicy(AuthorizationPolicies.SectionAccessForTinyMce, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement( + Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members)); + }); - options.AddPolicy(AuthorizationPolicies.SectionAccessMedia, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement(Constants.Applications.Media)); - }); + options.AddPolicy(AuthorizationPolicies.SectionAccessMedia, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement(Constants.Applications.Media)); + }); - options.AddPolicy(AuthorizationPolicies.SectionAccessMembers, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement(Constants.Applications.Members)); - }); + options.AddPolicy(AuthorizationPolicies.SectionAccessMembers, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement(Constants.Applications.Members)); + }); - options.AddPolicy(AuthorizationPolicies.SectionAccessPackages, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement(Constants.Applications.Packages)); - }); + options.AddPolicy(AuthorizationPolicies.SectionAccessPackages, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement(Constants.Applications.Packages)); + }); - options.AddPolicy(AuthorizationPolicies.SectionAccessSettings, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement(Constants.Applications.Settings)); - }); + options.AddPolicy(AuthorizationPolicies.SectionAccessSettings, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement(Constants.Applications.Settings)); + }); - //We will not allow the tree to render unless the user has access to any of the sections that the tree gets rendered - // this is not ideal but until we change permissions to be tree based (not section) there's not much else we can do here. - options.AddPolicy(AuthorizationPolicies.SectionAccessForContentTree, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement( - Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Users, - Constants.Applications.Settings, Constants.Applications.Packages, Constants.Applications.Members)); - }); - options.AddPolicy(AuthorizationPolicies.SectionAccessForMediaTree, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement( - Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Users, - Constants.Applications.Settings, Constants.Applications.Packages, Constants.Applications.Members)); - }); - options.AddPolicy(AuthorizationPolicies.SectionAccessForMemberTree, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement( - Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members)); - }); + //We will not allow the tree to render unless the user has access to any of the sections that the tree gets rendered + // this is not ideal but until we change permissions to be tree based (not section) there's not much else we can do here. + options.AddPolicy(AuthorizationPolicies.SectionAccessForContentTree, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement( + Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Users, + Constants.Applications.Settings, Constants.Applications.Packages, Constants.Applications.Members)); + }); + options.AddPolicy(AuthorizationPolicies.SectionAccessForMediaTree, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement( + Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Users, + Constants.Applications.Settings, Constants.Applications.Packages, Constants.Applications.Members)); + }); + options.AddPolicy(AuthorizationPolicies.SectionAccessForMemberTree, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement( + Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members)); + }); - // Permission is granted to this policy if the user has access to any of these sections: Content, media, settings, developer, members - options.AddPolicy(AuthorizationPolicies.SectionAccessForDataTypeReading, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new SectionRequirement( - Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members, - Constants.Applications.Settings, Constants.Applications.Packages)); - }); + // Permission is granted to this policy if the user has access to any of these sections: Content, media, settings, developer, members + options.AddPolicy(AuthorizationPolicies.SectionAccessForDataTypeReading, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionRequirement( + Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members, + Constants.Applications.Settings, Constants.Applications.Packages)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessDocuments, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.Content)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessDocuments, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.Content)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessUsers, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.Users)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessUsers, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.Users)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessPartialViews, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.PartialViews)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessPartialViews, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.PartialViews)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessPartialViewMacros, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.PartialViewMacros)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessPartialViewMacros, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.PartialViewMacros)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessPackages, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.Packages)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessPackages, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.Packages)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessLogs, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.LogViewer)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessLogs, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.LogViewer)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessDataTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.DataTypes)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessDataTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.DataTypes)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessTemplates, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.Templates)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessTemplates, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.Templates)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessMemberTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.MemberTypes)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessMemberTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.MemberTypes)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessRelationTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.RelationTypes)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessRelationTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.RelationTypes)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.DocumentTypes)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.DocumentTypes)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessMemberGroups, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.MemberGroups)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessMemberGroups, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.MemberGroups)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessMediaTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.MediaTypes)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessMediaTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.MediaTypes)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessMacros, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.Macros)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessMacros, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.Macros)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessLanguages, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.Languages)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessLanguages, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.Languages)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.Dictionary)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.Dictionary)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessDictionary, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.Dictionary, Constants.Trees.Dictionary)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessDictionary, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.Dictionary, Constants.Trees.Dictionary)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessDictionaryOrTemplates, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.Dictionary, Constants.Trees.Templates)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessDictionaryOrTemplates, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.Dictionary, Constants.Trees.Templates)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentsOrDocumentTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.DocumentTypes, Constants.Trees.Content)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentsOrDocumentTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.DocumentTypes, Constants.Trees.Content)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessMediaOrMediaTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.MediaTypes, Constants.Trees.Media)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessMediaOrMediaTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.MediaTypes, Constants.Trees.Media)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessMembersOrMemberTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.MemberTypes, Constants.Trees.Members)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessMembersOrMemberTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.MemberTypes, Constants.Trees.Members)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessAnySchemaTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement(Constants.Trees.DataTypes, Constants.Trees.DocumentTypes, Constants.Trees.MediaTypes, Constants.Trees.MemberTypes)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessAnySchemaTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement(Constants.Trees.DataTypes, Constants.Trees.DocumentTypes, Constants.Trees.MediaTypes, Constants.Trees.MemberTypes)); + }); - options.AddPolicy(AuthorizationPolicies.TreeAccessAnyContentOrTypes, policy => - { - policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); - policy.Requirements.Add(new TreeRequirement( - Constants.Trees.DocumentTypes, Constants.Trees.Content, - Constants.Trees.MediaTypes, Constants.Trees.Media, - Constants.Trees.MemberTypes, Constants.Trees.Members)); - }); + options.AddPolicy(AuthorizationPolicies.TreeAccessAnyContentOrTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeRequirement( + Constants.Trees.DocumentTypes, Constants.Trees.Content, + Constants.Trees.MediaTypes, Constants.Trees.Media, + Constants.Trees.MemberTypes, Constants.Trees.Members)); }); } } diff --git a/src/Umbraco.Web.BackOffice/Extensions/CompositionExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/CompositionExtensions.cs index 2a8a2e900d..4e8fe01b7f 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/CompositionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/CompositionExtensions.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Composing; +using Umbraco.Core.Builder; +using Umbraco.Core.Composing; using Umbraco.Web.BackOffice.Trees; // the namespace here is intentional - although defined in Umbraco.Web assembly, @@ -18,10 +19,10 @@ namespace Umbraco.Extensions /// /// Gets the back office tree collection builder /// - /// + /// /// - public static TreeCollectionBuilder Trees(this Composition composition) - => composition.WithCollectionBuilder(); + public static TreeCollectionBuilder Trees(this IUmbracoBuilder builder) + => builder.WithCollectionBuilder(); #endregion } diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBuilderExtensions.cs index c494425274..2b6eb1d111 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBuilderExtensions.cs @@ -1,33 +1,71 @@ -using Umbraco.Web.Common.Builder; +using System; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core.Builder; +using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.Security; +using Umbraco.Web.Common.Builder; namespace Umbraco.Extensions { public static class UmbracoBuilderExtensions { - public static IUmbracoBuilder WithAllBackOfficeComponents(this IUmbracoBuilder builder) + public static IUmbracoBuilder AddAllBackOfficeComponents(this IUmbracoBuilder builder) { return builder - .WithConfiguration() - .WithCore() - .WithWebComponents() - .WithRuntimeMinifier() - .WithBackOffice() - .WithBackOfficeIdentity() - .WithMiniProfiler() - .WithMvcAndRazor() - .WithWebServer() - .WithPreview() - .WithHostedServices() - .WithHttpClients(); + .AddConfiguration() + .AddUmbracoCore() + .AddWebComponents() + .AddRuntimeMinifier() + .AddBackOffice() + .AddBackOfficeIdentity() + .AddBackOfficeAuthorizationPolicies() + .AddMiniProfiler() + .AddMvcAndRazor() + .AddWebServer() + .AddPreviewSupport() + .AddHostedServices() + .AddHttpClients(); } - public static IUmbracoBuilder WithBackOffice(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithBackOffice), () => builder.Services.AddUmbracoBackOffice()); + public static IUmbracoBuilder AddBackOffice(this IUmbracoBuilder builder) + { + builder.Services.AddAntiforgery(); + builder.Services.AddSingleton(); + builder.Services + .AddAuthentication(Core.Constants.Security.BackOfficeAuthenticationType) + .AddCookie(Core.Constants.Security.BackOfficeAuthenticationType) + .AddCookie(Core.Constants.Security.BackOfficeExternalAuthenticationType, o => + { + o.Cookie.Name = Core.Constants.Security.BackOfficeExternalAuthenticationType; + o.ExpireTimeSpan = TimeSpan.FromMinutes(5); + }); - public static IUmbracoBuilder WithBackOfficeIdentity(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithBackOfficeIdentity), () => builder.Services.AddUmbracoBackOfficeIdentity()); + // TODO: Need to add more cookie options, see https://github.com/dotnet/aspnetcore/blob/3.0/src/Identity/Core/src/IdentityServiceCollectionExtensions.cs#L45 - public static IUmbracoBuilder WithPreview(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithPreview), () => builder.Services.AddUmbracoPreview()); + builder.Services.ConfigureOptions(); + return builder; + } + + public static IUmbracoBuilder AddBackOfficeIdentity(this IUmbracoBuilder builder) + { + builder.Services.AddUmbracoBackOfficeIdentity(); + + return builder; + } + + public static IUmbracoBuilder AddBackOfficeAuthorizationPolicies(this IUmbracoBuilder builder) + { + builder.Services.AddBackOfficeAuthorizationPolicies(); + + return builder; + } + + public static IUmbracoBuilder AddPreviewSupport(this IUmbracoBuilder builder) + { + builder.Services.AddSignalR(); + + return builder; + } } } diff --git a/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs b/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs index bc72b1dd44..600ff101fe 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/WebMappingProfiles.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Core; using Umbraco.Core.BackOffice; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.Mapping; using Umbraco.Web.BackOffice.Mapping; @@ -9,16 +10,16 @@ namespace Umbraco.Extensions { public static class WebMappingProfiles { - public static Composition ComposeWebMappingProfiles(this Composition composition) + public static IUmbracoBuilder ComposeWebMappingProfiles(this IUmbracoBuilder builder) { - composition.WithCollectionBuilder() + builder.WithCollectionBuilder() .Add() .Add() .Add(); - composition.Services.AddTransient(); + builder.Services.AddTransient(); - return composition; + return builder; } } } diff --git a/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs index 54e7006bec..a2ad2cd834 100644 --- a/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs +++ b/src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Mapping; @@ -34,6 +35,7 @@ namespace Umbraco.Web.BackOffice.Mapping private readonly ILoggerFactory _loggerFactory; private readonly IUserService _userService; private readonly IEntityService _entityService; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly IVariationContextAccessor _variationContextAccessor; private readonly IPublishedUrlProvider _publishedUrlProvider; private readonly UriUtility _uriUtility; @@ -43,9 +45,25 @@ namespace Umbraco.Web.BackOffice.Mapping private readonly ContentVariantMapper _contentVariantMapper; - public ContentMapDefinition(CommonMapper commonMapper, CommonTreeNodeMapper commonTreeNodeMapper, ICultureDictionary cultureDictionary, ILocalizedTextService localizedTextService, IContentService contentService, IContentTypeService contentTypeService, - IFileService fileService, IUmbracoContextAccessor umbracoContextAccessor, IPublishedRouter publishedRouter, ILocalizationService localizationService, ILoggerFactory loggerFactory, - IUserService userService, IVariationContextAccessor variationContextAccessor, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, UriUtility uriUtility, IPublishedUrlProvider publishedUrlProvider, IEntityService entityService) + public ContentMapDefinition( + CommonMapper commonMapper, + CommonTreeNodeMapper commonTreeNodeMapper, + ICultureDictionary cultureDictionary, + ILocalizedTextService localizedTextService, + IContentService contentService, + IContentTypeService contentTypeService, + IFileService fileService, + IUmbracoContextAccessor umbracoContextAccessor, + IPublishedRouter publishedRouter, + ILocalizationService localizationService, + ILoggerFactory loggerFactory, + IUserService userService, + IVariationContextAccessor variationContextAccessor, + IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, + UriUtility uriUtility, + IPublishedUrlProvider publishedUrlProvider, + IEntityService entityService, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor) { _commonMapper = commonMapper; _commonTreeNodeMapper = commonTreeNodeMapper; @@ -60,6 +78,7 @@ namespace Umbraco.Web.BackOffice.Mapping _loggerFactory = loggerFactory; _userService = userService; _entityService = entityService; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _variationContextAccessor = variationContextAccessor; _uriUtility = uriUtility; _publishedUrlProvider = publishedUrlProvider; @@ -159,10 +178,10 @@ namespace Umbraco.Web.BackOffice.Mapping private IEnumerable GetActions(IContent source) { - var umbracoContext = _umbracoContextAccessor.UmbracoContext; + var backOfficeSecurity = _backOfficeSecurityAccessor.BackOfficeSecurity; //cannot check permissions without a context - if (umbracoContext == null) + if (backOfficeSecurity is null) return Enumerable.Empty(); string path; @@ -174,10 +193,7 @@ namespace Umbraco.Web.BackOffice.Mapping path = parent == null ? "-1" : parent.Path; } - // TODO: This is certainly not ideal usage here - perhaps the best way to deal with this in the future is - // with the IUmbracoContextAccessor. In the meantime, if used outside of a web app this will throw a null - // reference exception :( - return _userService.GetPermissionsForPath(umbracoContext.Security.CurrentUser, path).GetAllPermissions(); + return _userService.GetPermissionsForPath(backOfficeSecurity.CurrentUser, path).GetAllPermissions(); } private UrlInfo[] GetUrls(IContent source) diff --git a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs index fb6b015520..d11dffb1ac 100644 --- a/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs +++ b/src/Umbraco.Web.BackOffice/Runtime/BackOfficeComposer.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.IO; @@ -22,36 +23,36 @@ namespace Umbraco.Web.BackOffice.Runtime [ComposeAfter(typeof(AspNetCoreComposer))] public class BackOfficeComposer : IComposer { - public void Compose(Composition composition) + public void Compose(IUmbracoBuilder builder) { - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddScoped(); - composition.Services.AddScoped(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); // register back office trees // the collection builder only accepts types inheriting from TreeControllerBase // and will filter out those that are not attributed with TreeAttribute - var umbracoApiControllerTypes = composition.TypeLoader.GetUmbracoApiControllers().ToList(); - composition.Trees() + var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList(); + builder.Trees() .AddTreeControllers(umbracoApiControllerTypes.Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))); - composition.ComposeWebMappingProfiles(); + builder.ComposeWebMappingProfiles(); - composition.Services.AddUnique(factory => + builder.Services.AddUnique(factory => new PhysicalFileSystem( factory.GetRequiredService(), factory.GetRequiredService(), factory.GetRequiredService>(), "~/")); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Web.BackOffice/SignalR/PreviewHubComposer.cs b/src/Umbraco.Web.BackOffice/SignalR/PreviewHubComposer.cs index de40340e6f..e994571c90 100644 --- a/src/Umbraco.Web.BackOffice/SignalR/PreviewHubComposer.cs +++ b/src/Umbraco.Web.BackOffice/SignalR/PreviewHubComposer.cs @@ -1,13 +1,14 @@ using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; namespace Umbraco.Web.BackOffice.SignalR { public class PreviewHubComposer : ComponentComposer, ICoreComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); } } } diff --git a/src/Umbraco.Web.Common/AspNetCore/OptionsMonitorAdapter.cs b/src/Umbraco.Web.Common/AspNetCore/OptionsMonitorAdapter.cs new file mode 100644 index 0000000000..9162c85cdd --- /dev/null +++ b/src/Umbraco.Web.Common/AspNetCore/OptionsMonitorAdapter.cs @@ -0,0 +1,33 @@ +using System; +using Microsoft.Extensions.Options; + +namespace Umbraco.Web.Common.AspNetCore +{ + /// + /// HACK: OptionsMonitor but without the monitoring, hopefully temporary. + /// This is just used so we can get an AspNetCoreHostingEnvironment to + /// build a TypeLoader long before ServiceProvider is built. + /// + [Obsolete("Please let the container wire up a real OptionsMonitor for you")] + internal class OptionsMonitorAdapter : IOptionsMonitor where T : class, new() + { + private readonly T _inner; + + public OptionsMonitorAdapter(T inner) + { + _inner = inner ?? throw new ArgumentNullException(nameof(inner)); + } + + public T Get(string name) + { + return _inner; + } + + public IDisposable OnChange(Action listener) + { + throw new NotImplementedException(); + } + + public T CurrentValue => _inner; + } +} diff --git a/src/Umbraco.Web.Common/Builder/IUmbracoBuilder.cs b/src/Umbraco.Web.Common/Builder/IUmbracoBuilder.cs deleted file mode 100644 index 2de7d2d285..0000000000 --- a/src/Umbraco.Web.Common/Builder/IUmbracoBuilder.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Text; - -namespace Umbraco.Web.Common.Builder -{ - - public interface IUmbracoBuilder - { - IServiceCollection Services { get; } - IWebHostEnvironment WebHostEnvironment { get; } - IConfiguration Config { get; } - IUmbracoBuilder AddWith(string key, Action add); - void Build(); - } -} diff --git a/src/Umbraco.Web.Common/Builder/UmbracoBuilder.cs b/src/Umbraco.Web.Common/Builder/UmbracoBuilder.cs deleted file mode 100644 index 3efb1e74f5..0000000000 --- a/src/Umbraco.Web.Common/Builder/UmbracoBuilder.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; - -namespace Umbraco.Web.Common.Builder -{ - public class UmbracoBuilder : IUmbracoBuilder - { - private readonly Dictionary _registrations = new Dictionary(); - - public UmbracoBuilder(IServiceCollection services, IWebHostEnvironment webHostEnvironment, IConfiguration config) - { - Services = services; - WebHostEnvironment = webHostEnvironment; - Config = config; - } - - public IServiceCollection Services { get; } - public IWebHostEnvironment WebHostEnvironment { get; } - public IConfiguration Config { get; } - - public IUmbracoBuilder AddWith(string key, Action add) - { - if (_registrations.ContainsKey(key)) return this; - _registrations[key] = add; - return this; - } - - public void Build() - { - foreach (var a in _registrations) - a.Value(); - } - } -} diff --git a/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs index 10f214a522..4c464ad989 100644 --- a/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Builder/UmbracoBuilderExtensions.cs @@ -5,85 +5,346 @@ using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SqlClient; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Serilog; +using Smidge; +using Smidge.Nuglify; using Umbraco.Core; +using Umbraco.Core.Builder; +using Umbraco.Core.Cache; +using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration.Models.Validation; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Runtime; using Umbraco.Extensions; +using Umbraco.Infrastructure.HostedServices; +using Umbraco.Infrastructure.HostedServices.ServerRegistration; +using Umbraco.Infrastructure.Runtime; +using Umbraco.Web.Common.ApplicationModels; +using Umbraco.Web.Common.AspNetCore; using Umbraco.Web.Common.Filters; using Umbraco.Web.Common.ModelBinders; +using Umbraco.Web.Common.Profiler; +using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment; namespace Umbraco.Web.Common.Builder { // TODO: We could add parameters to configure each of these for flexibility public static class UmbracoBuilderExtensions { - public static IUmbracoBuilder AddUmbraco(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IConfiguration config) + public static IUmbracoBuilder AddUmbraco( + this IServiceCollection services, + IWebHostEnvironment webHostEnvironment, + IConfiguration config) { if (services is null) throw new ArgumentNullException(nameof(services)); - if (webHostEnvironment is null) throw new ArgumentNullException(nameof(webHostEnvironment)); if (config is null) throw new ArgumentNullException(nameof(config)); - services.AddLazySupport(); + var loggingConfig = new LoggingConfiguration(Path.Combine(webHostEnvironment.ContentRootPath, "umbraco", "logs")); - var builder = new UmbracoBuilder(services, webHostEnvironment, config); + var tempHostingEnvironment = GetTemporaryHostingEnvironment(webHostEnvironment, config); + services.AddLogger(tempHostingEnvironment, loggingConfig, config); + + IHttpContextAccessor httpContextAccessor = new HttpContextAccessor(); + services.AddSingleton(httpContextAccessor); + + var requestCache = new GenericDictionaryRequestAppCache(() => httpContextAccessor.HttpContext?.Items); + var appCaches = AppCaches.Create(requestCache); + services.AddUnique(appCaches); + + var profiler = GetWebProfiler(config); + services.AddUnique(profiler); + + var loggerFactory = LoggerFactory.Create(cfg => cfg.AddSerilog(Log.Logger, false)); + var typeLoader = services.AddTypeLoader(Assembly.GetEntryAssembly(), webHostEnvironment, tempHostingEnvironment, loggerFactory, appCaches, config, profiler); + + return new UmbracoBuilder(services, config, typeLoader, loggerFactory); + } + + /// Composes Composers + public static IUmbracoBuilder AddUmbracoCore(this IUmbracoBuilder builder) + { + if (builder is null) throw new ArgumentNullException(nameof(builder)); + + builder.Services.AddLazySupport(); + + // Add supported databases + builder.AddUmbracoSqlCeSupport(); + builder.AddUmbracoSqlServerSupport(); + + builder.Services.AddSingleton(factory => new DbProviderFactoryCreator( + DbProviderFactories.GetFactory, + factory.GetServices(), + factory.GetServices(), + factory.GetServices() + )); + + builder.Services.AddUnique(factory => + { + var globalSettings = factory.GetRequiredService>().Value; + var connectionStrings = factory.GetRequiredService>().Value; + var hostingEnvironment = factory.GetRequiredService(); + + var dbCreator = factory.GetRequiredService(); + var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + var loggerFactory = factory.GetRequiredService(); + + return globalSettings.MainDomLock.Equals("SqlMainDomLock") || isWindows == false + ? (IMainDomLock)new SqlMainDomLock(loggerFactory.CreateLogger(), loggerFactory, globalSettings, connectionStrings, dbCreator, hostingEnvironment) + : new MainDomSemaphoreLock(loggerFactory.CreateLogger(), hostingEnvironment); + }); + + builder.Services.AddUnique(); + builder.Services.AddUnique(factory => factory.GetRequiredService().RuntimeCache); + builder.Services.AddUnique(factory => factory.GetRequiredService().RequestCache); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(factory => factory.GetRequiredService().CreateDatabase()); + builder.Services.AddUnique(factory => factory.GetRequiredService().SqlContext); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + + builder.AddComposers(); + return builder; } - public static IUmbracoBuilder WithConfiguration(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithConfiguration), () => builder.Services.AddUmbracoConfiguration(builder.Config)); + public static IUmbracoBuilder AddComposers(this IUmbracoBuilder builder) + { + var composerTypes = builder.TypeLoader.GetTypes(); + var enableDisable = builder.TypeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute)); + new Composers(builder, composerTypes, enableDisable, builder.BuilderLoggerFactory.CreateLogger()).Compose(); - public static IUmbracoBuilder WithCore(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithCore), () => builder.Services.AddUmbracoCore(builder.WebHostEnvironment, builder.Config)); + return builder; + } - public static IUmbracoBuilder WithHostedServices(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithHostedServices), () => builder.Services.AddUmbracoHostedServices()); + public static IUmbracoBuilder AddConfiguration(this IUmbracoBuilder builder) + { + // Register configuration validators. + builder.Services.AddSingleton, ContentSettingsValidator>(); + builder.Services.AddSingleton, GlobalSettingsValidator>(); + builder.Services.AddSingleton, HealthChecksSettingsValidator>(); + builder.Services.AddSingleton, RequestHandlerSettingsValidator>(); - public static IUmbracoBuilder WithHttpClients(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithHttpClients), () => builder.Services.AddUmbracoHttpClients()); + // Register configuration sections. + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigActiveDirectory)); + builder.Services.Configure(builder.Config.GetSection("ConnectionStrings"), o => o.BindNonPublicProperties = true); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigContent)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigCoreDebug)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExceptionFilter)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigGlobal)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHealthChecks)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigHosting)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigImaging)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigExamine)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigKeepAlive)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigLogging)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigMemberPassword)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigModelsBuilder), o => o.BindNonPublicProperties = true); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigNuCache)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRequestHandler)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigRuntime)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigSecurity)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTours)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigTypeFinder)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigUserPassword)); + builder.Services.Configure(builder.Config.GetSection(Core.Constants.Configuration.ConfigWebRouting)); - public static IUmbracoBuilder WithMiniProfiler(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithMiniProfiler), () => + return builder; + } + + + public static IUmbracoBuilder AddHostedServices(this IUmbracoBuilder builder) + { + builder.Services.AddHostedService(); + builder.Services.AddHostedService(); + builder.Services.AddHostedService(); + builder.Services.AddHostedService(); + builder.Services.AddHostedService(); + builder.Services.AddHostedService(); + builder.Services.AddHostedService(); + return builder; + } + + public static IUmbracoBuilder AddHttpClients(this IUmbracoBuilder builder) + { + builder.Services.AddHttpClient(); + return builder; + } + + public static IUmbracoBuilder AddMiniProfiler(this IUmbracoBuilder builder) + { builder.Services.AddMiniProfiler(options => { options.ShouldProfile = request => false; // WebProfiler determine and start profiling. We should not use the MiniProfilerMiddleware to also profile - })); - - public static IUmbracoBuilder WithMvcAndRazor(this IUmbracoBuilder builder, Action mvcOptions = null, Action mvcBuilding = null) - => builder.AddWith(nameof(WithMvcAndRazor), () => - { - - - // TODO: We need to figure out if we can work around this because calling AddControllersWithViews modifies the global app and order is very important - // this will directly affect developers who need to call that themselves. - //We need to have runtime compilation of views when using umbraco. We could consider having only this when a specific config is set. - //But as far as I can see, there are still precompiled views, even when this is activated, so maybe it is okay. - var mvcBuilder = builder.Services.AddControllersWithViews(options => - { - options.ModelBinderProviders.Insert(0, new ContentModelBinderProvider()); - - options.Filters.Insert(0, new EnsurePartialViewMacroViewContextFilterAttribute()); - mvcOptions?.Invoke(options); - }).AddRazorRuntimeCompilation(); - mvcBuilding?.Invoke(mvcBuilder); }); - public static IUmbracoBuilder WithRuntimeMinifier(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithRuntimeMinifier), () => builder.Services.AddUmbracoRuntimeMinifier(builder.Config)); + return builder; + } - public static IUmbracoBuilder WithWebComponents(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithWebComponents), () => builder.Services.AddUmbracoWebComponents(builder.Config)); - - public static IUmbracoBuilder WithWebServer(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithWebServer), () => + public static IUmbracoBuilder AddMvcAndRazor(this IUmbracoBuilder builder, Action mvcOptions = null, Action mvcBuilding = null) + { + // TODO: We need to figure out if we can work around this because calling AddControllersWithViews modifies the global app and order is very important + // this will directly affect developers who need to call that themselves. + //We need to have runtime compilation of views when using umbraco. We could consider having only this when a specific config is set. + //But as far as I can see, there are still precompiled views, even when this is activated, so maybe it is okay. + var mvcBuilder = builder.Services.AddControllersWithViews(options => { - // TODO: We need to figure out why thsi is needed and fix those endpoints to not need them, we don't want to change global things - // If using Kestrel: https://stackoverflow.com/a/55196057 - builder.Services.Configure(options => - { - options.AllowSynchronousIO = true; - }); - builder.Services.Configure(options => - { - options.AllowSynchronousIO = true; - }); + options.ModelBinderProviders.Insert(0, new ContentModelBinderProvider()); + + options.Filters.Insert(0, new EnsurePartialViewMacroViewContextFilterAttribute()); + mvcOptions?.Invoke(options); + }).AddRazorRuntimeCompilation(); + mvcBuilding?.Invoke(mvcBuilder); + + return builder; + } + + public static IUmbracoBuilder AddRuntimeMinifier(this IUmbracoBuilder builder) + { + builder.Services.AddSmidge(builder.Config.GetSection(Core.Constants.Configuration.ConfigRuntimeMinification)); + builder.Services.AddSmidgeNuglify(); + + return builder; + } + + public static IUmbracoBuilder AddWebComponents(this IUmbracoBuilder builder) + { + // Add service session + // This can be overwritten by the user by adding their own call to AddSession + // since the last call of AddSession take precedence + builder.Services.AddSession(options => + { + options.Cookie.Name = "UMB_SESSION"; + options.Cookie.HttpOnly = true; }); + + builder.Services.ConfigureOptions(); + builder.Services.TryAddEnumerable(ServiceDescriptor.Transient()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Transient()); + builder.Services.AddUmbracoImageSharp(builder.Config); + + return builder; + } + + public static IUmbracoBuilder AddWebServer(this IUmbracoBuilder builder) + { + // TODO: We need to figure out why thsi is needed and fix those endpoints to not need them, we don't want to change global things + // If using Kestrel: https://stackoverflow.com/a/55196057 + builder.Services.Configure(options => + { + options.AllowSynchronousIO = true; + }); + builder.Services.Configure(options => + { + options.AllowSynchronousIO = true; + }); + + return builder; + } + + /// + /// Adds SqlCe support for Umbraco + /// + private static IUmbracoBuilder AddUmbracoSqlCeSupport(this IUmbracoBuilder builder) + { + try + { + var binFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + if (binFolder != null) + { + var dllPath = Path.Combine(binFolder, "Umbraco.Persistance.SqlCe.dll"); + var umbSqlCeAssembly = Assembly.LoadFrom(dllPath); + + var sqlCeSyntaxProviderType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeSyntaxProvider"); + var sqlCeBulkSqlInsertProviderType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeBulkSqlInsertProvider"); + var sqlCeEmbeddedDatabaseCreatorType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeEmbeddedDatabaseCreator"); + + if (!(sqlCeSyntaxProviderType is null || sqlCeBulkSqlInsertProviderType is null || sqlCeEmbeddedDatabaseCreatorType is null)) + { + builder.Services.AddSingleton(typeof(ISqlSyntaxProvider), sqlCeSyntaxProviderType); + builder.Services.AddSingleton(typeof(IBulkSqlInsertProvider), sqlCeBulkSqlInsertProviderType); + builder.Services.AddSingleton(typeof(IEmbeddedDatabaseCreator), sqlCeEmbeddedDatabaseCreatorType); + } + + var sqlCeAssembly = Assembly.LoadFrom(Path.Combine(binFolder, "System.Data.SqlServerCe.dll")); + + var sqlCe = sqlCeAssembly.GetType("System.Data.SqlServerCe.SqlCeProviderFactory"); + if (!(sqlCe is null)) + { + DbProviderFactories.RegisterFactory(Core.Constants.DbProviderNames.SqlCe, sqlCe); + } + } + } + catch + { + // Ignore if SqlCE is not available + } + + return builder; + } + + /// + /// Adds Sql Server support for Umbraco + /// + private static IUmbracoBuilder AddUmbracoSqlServerSupport(this IUmbracoBuilder builder) + { + DbProviderFactories.RegisterFactory(Core.Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance); + + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + + return builder; + } + + private static IProfiler GetWebProfiler(IConfiguration config) + { + var isDebug = config.GetValue($"{Core.Constants.Configuration.ConfigHosting}:Debug"); + // create and start asap to profile boot + if (!isDebug) + { + // should let it be null, that's how MiniProfiler is meant to work, + // but our own IProfiler expects an instance so let's get one + return new VoidProfiler(); + } + + var webProfiler = new WebProfiler(); + webProfiler.StartBoot(); + + return webProfiler; + } + + /// + /// HACK: returns an AspNetCoreHostingEnvironment that doesn't monitor changes to configuration.
+ /// We require this to create a TypeLoader during ConfigureServices.
+ /// Instances returned from this method shouldn't be registered in the service collection. + ///
+ private static IHostingEnvironment GetTemporaryHostingEnvironment(IWebHostEnvironment webHostEnvironment, IConfiguration config) + { + var hostingSettings = config.GetSection(Core.Constants.Configuration.ConfigHosting).Get() ?? new HostingSettings(); + var wrappedHostingSettings = new OptionsMonitorAdapter(hostingSettings); + + return new AspNetCoreHostingEnvironment(wrappedHostingSettings, webHostEnvironment); + } } } diff --git a/src/Umbraco.Web.Common/Controllers/IRenderController.cs b/src/Umbraco.Web.Common/Controllers/IRenderController.cs index 3eaf1c35c3..7534abc9b4 100644 --- a/src/Umbraco.Web.Common/Controllers/IRenderController.cs +++ b/src/Umbraco.Web.Common/Controllers/IRenderController.cs @@ -3,7 +3,6 @@ /// /// A marker interface to designate that a controller will be used for Umbraco front-end requests and/or route hijacking /// - /// Migrated already to .Net Core public interface IRenderController { diff --git a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs index 5c1d81b28b..caf4132664 100644 --- a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs @@ -39,6 +39,9 @@ namespace Umbraco.Extensions if (!app.UmbracoCanBoot()) return app; + var hostingEnvironment = app.ApplicationServices.GetRequiredService(); + AppDomain.CurrentDomain.SetData("DataDirectory", hostingEnvironment?.MapPathContentRoot(Core.Constants.SystemDirectories.Data)); + var runtime = app.ApplicationServices.GetRequiredService(); // Register a listener for application shutdown in order to terminate the runtime diff --git a/src/Umbraco.Web/GridTemplateExtensions.cs b/src/Umbraco.Web.Common/Extensions/GridTemplateExtensions.cs similarity index 78% rename from src/Umbraco.Web/GridTemplateExtensions.cs rename to src/Umbraco.Web.Common/Extensions/GridTemplateExtensions.cs index 81dc33d2c6..e4a1c0d117 100644 --- a/src/Umbraco.Web/GridTemplateExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/GridTemplateExtensions.cs @@ -1,27 +1,27 @@ using System; -using System.Web.Mvc; -using System.Web.Mvc.Html; +using Microsoft.AspNetCore.Html; +using Microsoft.AspNetCore.Mvc.Rendering; using Umbraco.Core.Models.PublishedContent; -namespace Umbraco.Web +namespace Umbraco.Extensions { public static class GridTemplateExtensions { - public static MvcHtmlString GetGridHtml(this HtmlHelper html, IPublishedProperty property, string framework = "bootstrap3") + public static IHtmlContent GetGridHtml(this IHtmlHelper html, IPublishedProperty property, string framework = "bootstrap3") { var asString = property.GetValue() as string; - if (asString != null && string.IsNullOrEmpty(asString)) return new MvcHtmlString(string.Empty); + if (asString != null && string.IsNullOrEmpty(asString)) return new HtmlString(string.Empty); var view = "Grid/" + framework; return html.Partial(view, property.GetValue()); } - public static MvcHtmlString GetGridHtml(this HtmlHelper html, IPublishedContent contentItem) + public static IHtmlContent GetGridHtml(this IHtmlHelper html, IPublishedContent contentItem) { return html.GetGridHtml(contentItem, "bodyText", "bootstrap3"); } - public static MvcHtmlString GetGridHtml(this HtmlHelper html, IPublishedContent contentItem, string propertyAlias) + public static IHtmlContent GetGridHtml(this IHtmlHelper html, IPublishedContent contentItem, string propertyAlias) { if (propertyAlias == null) throw new ArgumentNullException(nameof(propertyAlias)); if (string.IsNullOrWhiteSpace(propertyAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(propertyAlias)); @@ -29,7 +29,7 @@ namespace Umbraco.Web return html.GetGridHtml(contentItem, propertyAlias, "bootstrap3"); } - public static MvcHtmlString GetGridHtml(this HtmlHelper html, IPublishedContent contentItem, string propertyAlias, string framework) + public static IHtmlContent GetGridHtml(this IHtmlHelper html, IPublishedContent contentItem, string propertyAlias, string framework) { if (propertyAlias == null) throw new ArgumentNullException(nameof(propertyAlias)); if (string.IsNullOrWhiteSpace(propertyAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(propertyAlias)); @@ -40,17 +40,17 @@ namespace Umbraco.Web var model = prop.GetValue(); var asString = model as string; - if (asString != null && string.IsNullOrEmpty(asString)) return new MvcHtmlString(string.Empty); + if (asString != null && string.IsNullOrEmpty(asString)) return new HtmlString(string.Empty); return html.Partial(view, model); } - public static MvcHtmlString GetGridHtml(this HtmlHelper html, IPublishedElement contentItem) + public static IHtmlContent GetGridHtml(this IHtmlHelper html, IPublishedElement contentItem) { return html.GetGridHtml(contentItem, "bodyText", "bootstrap3"); } - public static MvcHtmlString GetGridHtml(this HtmlHelper html, IPublishedElement contentItem, string propertyAlias) + public static IHtmlContent GetGridHtml(this IHtmlHelper html, IPublishedElement contentItem, string propertyAlias) { if (propertyAlias == null) throw new ArgumentNullException(nameof(propertyAlias)); if (string.IsNullOrWhiteSpace(propertyAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(propertyAlias)); @@ -58,7 +58,7 @@ namespace Umbraco.Web return html.GetGridHtml(contentItem, propertyAlias, "bootstrap3"); } - public static MvcHtmlString GetGridHtml(this HtmlHelper html, IPublishedElement contentItem, string propertyAlias, string framework) + public static IHtmlContent GetGridHtml(this IHtmlHelper html, IPublishedElement contentItem, string propertyAlias, string framework) { if (propertyAlias == null) throw new ArgumentNullException(nameof(propertyAlias)); if (string.IsNullOrWhiteSpace(propertyAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(propertyAlias)); @@ -69,25 +69,25 @@ namespace Umbraco.Web var model = prop.GetValue(); var asString = model as string; - if (asString != null && string.IsNullOrEmpty(asString)) return new MvcHtmlString(string.Empty); + if (asString != null && string.IsNullOrEmpty(asString)) return new HtmlString(string.Empty); return html.Partial(view, model); } - public static MvcHtmlString GetGridHtml(this IPublishedProperty property, HtmlHelper html, string framework = "bootstrap3") + public static IHtmlContent GetGridHtml(this IPublishedProperty property, IHtmlHelper html, string framework = "bootstrap3") { var asString = property.GetValue() as string; - if (asString != null && string.IsNullOrEmpty(asString)) return new MvcHtmlString(string.Empty); + if (asString != null && string.IsNullOrEmpty(asString)) return new HtmlString(string.Empty); var view = "Grid/" + framework; return html.Partial(view, property.GetValue()); } - public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, HtmlHelper html) + public static IHtmlContent GetGridHtml(this IPublishedContent contentItem, IHtmlHelper html) { return GetGridHtml(contentItem, html, "bodyText", "bootstrap3"); } - public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, HtmlHelper html, string propertyAlias) + public static IHtmlContent GetGridHtml(this IPublishedContent contentItem, IHtmlHelper html, string propertyAlias) { if (propertyAlias == null) throw new ArgumentNullException(nameof(propertyAlias)); if (string.IsNullOrWhiteSpace(propertyAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(propertyAlias)); @@ -95,7 +95,7 @@ namespace Umbraco.Web return GetGridHtml(contentItem, html, propertyAlias, "bootstrap3"); } - public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, HtmlHelper html, string propertyAlias, string framework) + public static IHtmlContent GetGridHtml(this IPublishedContent contentItem, IHtmlHelper html, string propertyAlias, string framework) { if (propertyAlias == null) throw new ArgumentNullException(nameof(propertyAlias)); if (string.IsNullOrWhiteSpace(propertyAlias)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(propertyAlias)); @@ -106,7 +106,7 @@ namespace Umbraco.Web var model = prop.GetValue(); var asString = model as string; - if (asString != null && string.IsNullOrEmpty(asString)) return new MvcHtmlString(string.Empty); + if (asString != null && string.IsNullOrEmpty(asString)) return new HtmlString(string.Empty); return html.Partial(view, model); } diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index c98cbca39e..49500a7eda 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -1,11 +1,6 @@ -using System; -using System.Data.Common; -using System.Data.SqlClient; using System.IO; using System.Reflection; -using System.Runtime.InteropServices; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -15,378 +10,24 @@ using Serilog.Extensions.Hosting; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Configuration.Models.Validation; -using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Runtime; -using Umbraco.Infrastructure.HostedServices; -using Umbraco.Infrastructure.HostedServices.ServerRegistration; using Umbraco.Web.Common.AspNetCore; using Umbraco.Web.Common.Profiler; -using ConnectionStrings = Umbraco.Core.Configuration.Models.ConnectionStrings; -using CoreDebugSettings = Umbraco.Core.Configuration.Models.CoreDebugSettings; using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment; namespace Umbraco.Extensions { public static class UmbracoCoreServiceCollectionExtensions { - /// - /// Adds the Umbraco Configuration requirements - /// - /// - /// - /// - public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services, IConfiguration configuration) - { - if (configuration == null) throw new ArgumentNullException(nameof(configuration)); - - // Register configuration validators. - services.AddSingleton, ContentSettingsValidator>(); - services.AddSingleton, GlobalSettingsValidator>(); - services.AddSingleton, HealthChecksSettingsValidator >(); - services.AddSingleton, RequestHandlerSettingsValidator>(); - - // Register configuration sections. - services.Configure(configuration.GetSection(Constants.Configuration.ConfigActiveDirectory)); - services.Configure(configuration.GetSection("ConnectionStrings"), o => o.BindNonPublicProperties = true); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigContent)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigCoreDebug)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigExceptionFilter)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigGlobal)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigHealthChecks)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigHosting)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigImaging)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigExamine)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigKeepAlive)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigLogging)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigMemberPassword)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigModelsBuilder), o => o.BindNonPublicProperties = true); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigNuCache)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigRequestHandler)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigRuntime)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurity)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigTours)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigTypeFinder)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigUserPassword)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigWebRouting)); - - return services; - } - - /// - /// Adds the Umbraco Back Core requirements - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static IServiceCollection AddUmbracoCore(this IServiceCollection services, - IWebHostEnvironment webHostEnvironment, - Assembly entryAssembly, - AppCaches appCaches, - ILoggingConfiguration loggingConfiguration, - IConfiguration configuration) - => services.AddUmbracoCore(webHostEnvironment, entryAssembly, appCaches, loggingConfiguration, configuration, GetCoreRuntime); - - /// - /// Adds the Umbraco Back Core requirements - /// - /// - /// - /// - /// - /// - public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IConfiguration configuration) - { - var loggingConfig = new LoggingConfiguration( - Path.Combine(webHostEnvironment.ContentRootPath, "umbraco", "logs")); - - IHttpContextAccessor httpContextAccessor = new HttpContextAccessor(); - services.AddSingleton(httpContextAccessor); - services.AddSingleton(loggingConfig); - - var requestCache = new GenericDictionaryRequestAppCache(() => httpContextAccessor.HttpContext?.Items); - var appCaches = new AppCaches( - new DeepCloneAppCache(new ObjectCacheAppCache()), - requestCache, - new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); - - services.AddUmbracoCore(webHostEnvironment, - Assembly.GetEntryAssembly(), - appCaches, - loggingConfig, - configuration, - GetCoreRuntime); - - return services; - } - - /// - /// Adds the Umbraco Back Core requirements - /// - /// - /// - /// - /// - /// - /// - /// - /// Delegate to create an - /// - /// - public static IServiceCollection AddUmbracoCore( - this IServiceCollection services, - IWebHostEnvironment webHostEnvironment, - Assembly entryAssembly, - AppCaches appCaches, - ILoggingConfiguration loggingConfiguration, - IConfiguration configuration, - //TODO: Yep that's extremely ugly - Func getRuntimeBootstrapper) - { - if (services is null) throw new ArgumentNullException(nameof(services)); - if (entryAssembly is null) throw new ArgumentNullException(nameof(entryAssembly)); - - services.AddLazySupport(); - - // Add service session - // This can be overwritten by the user by adding their own call to AddSession - // since the last call of AddSession take precedence - services.AddSession(options => - { - options.Cookie.Name = "UMB_SESSION"; - options.Cookie.HttpOnly = true; - }); - - // Add supported databases - services.AddUmbracoSqlCeSupport(); - services.AddUmbracoSqlServerSupport(); - - services.AddSingleton(x => new DbProviderFactoryCreator( - DbProviderFactories.GetFactory, - x.GetServices(), - x.GetServices(), - x.GetServices() - )); - - // TODO: We want to avoid pre-resolving a container as much as possible we should not - // be doing this any more than we are now. The ugly part about this is that the service - // instances resolved here won't be the same instances resolved from the container - // later once the true container is built. However! ... in the case of IDbProviderFactoryCreator - // it will be the same instance resolved later because we are re-registering this instance back - // into the container. This is not true for `Configs` but we should do that too, see comments in - // `RegisterEssentials`. - var serviceProvider = services.BuildServiceProvider(); - - var globalSettings = serviceProvider.GetService>(); - var connectionStrings = serviceProvider.GetService>(); - var hostingSettings = serviceProvider.GetService>(); - var typeFinderSettings = serviceProvider.GetService>(); - - var dbProviderFactoryCreator = serviceProvider.GetRequiredService(); - - CreateCompositionRoot(services, - globalSettings, - hostingSettings, - webHostEnvironment, - loggingConfiguration, - configuration, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); - - var loggerFactory = services.BuildServiceProvider().GetService(); - - var umbracoVersion = new UmbracoVersion(); - var typeFinder = CreateTypeFinder(loggerFactory, profiler, webHostEnvironment, entryAssembly, typeFinderSettings); - - var bootstrapper = getRuntimeBootstrapper( - globalSettings.CurrentValue, - connectionStrings.Value, - umbracoVersion, - ioHelper, - loggerFactory, - profiler, - hostingEnvironment, - backOfficeInfo, - typeFinder, - appCaches, - dbProviderFactoryCreator); - - bootstrapper.Configure(services); - - return services; - } - - /// - /// Adds SqlCe support for Umbraco - /// - /// - /// - private static IServiceCollection AddUmbracoSqlCeSupport(this IServiceCollection services) - { - try - { - var binFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - if (binFolder != null) - { - var dllPath = Path.Combine(binFolder, "Umbraco.Persistance.SqlCe.dll"); - var umbSqlCeAssembly = Assembly.LoadFrom(dllPath); - - var sqlCeSyntaxProviderType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeSyntaxProvider"); - var sqlCeBulkSqlInsertProviderType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeBulkSqlInsertProvider"); - var sqlCeEmbeddedDatabaseCreatorType = umbSqlCeAssembly.GetType("Umbraco.Persistance.SqlCe.SqlCeEmbeddedDatabaseCreator"); - - if (!(sqlCeSyntaxProviderType is null || sqlCeBulkSqlInsertProviderType is null || sqlCeEmbeddedDatabaseCreatorType is null)) - { - services.AddSingleton(typeof(ISqlSyntaxProvider), sqlCeSyntaxProviderType); - services.AddSingleton(typeof(IBulkSqlInsertProvider), sqlCeBulkSqlInsertProviderType); - services.AddSingleton(typeof(IEmbeddedDatabaseCreator), sqlCeEmbeddedDatabaseCreatorType); - } - - var sqlCeAssembly = Assembly.LoadFrom(Path.Combine(binFolder, "System.Data.SqlServerCe.dll")); - - var sqlCe = sqlCeAssembly.GetType("System.Data.SqlServerCe.SqlCeProviderFactory"); - if (!(sqlCe is null)) - { - DbProviderFactories.RegisterFactory(Core.Constants.DbProviderNames.SqlCe, sqlCe); - } - } - } - catch - { - // Ignore if SqlCE is not available - } - - return services; - } - - /// - /// Adds Sql Server support for Umbraco - /// - /// - /// - public static IServiceCollection AddUmbracoSqlServerSupport(this IServiceCollection services) - { - DbProviderFactories.RegisterFactory(Core.Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance); - - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - return services; - } - - /// - /// Adds hosted services for Umbraco. - /// - /// - /// - public static IServiceCollection AddUmbracoHostedServices(this IServiceCollection services) - { - services.AddHostedService(); - services.AddHostedService(); - services.AddHostedService(); - services.AddHostedService(); - services.AddHostedService(); - - services.AddHostedService(); - services.AddHostedService(); - - return services; - } - - /// - /// Adds HTTP clients for Umbraco. - /// - /// - /// - public static IServiceCollection AddUmbracoHttpClients(this IServiceCollection services) - { - services.AddHttpClient(); - return services; - } - - private static ITypeFinder CreateTypeFinder(ILoggerFactory loggerFactory, IProfiler profiler, IWebHostEnvironment webHostEnvironment, Assembly entryAssembly, IOptionsMonitor typeFinderSettings) - { - var runtimeHashPaths = new RuntimeHashPaths(); - runtimeHashPaths.AddFolder(new DirectoryInfo(Path.Combine(webHostEnvironment.ContentRootPath, "bin"))); - var runtimeHash = new RuntimeHash(new ProfilingLogger(loggerFactory.CreateLogger("RuntimeHash"), profiler), runtimeHashPaths); - return new TypeFinder(loggerFactory.CreateLogger(), new DefaultUmbracoAssemblyProvider(entryAssembly), runtimeHash, new TypeFinderConfig(typeFinderSettings)); - } - - private static CoreRuntimeBootstrapper GetCoreRuntime( - GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILoggerFactory loggerFactory, - IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo, - ITypeFinder typeFinder, AppCaches appCaches, IDbProviderFactoryCreator dbProviderFactoryCreator) - { - // Determine if we should use the sql main dom or the default - var appSettingMainDomLock = globalSettings.MainDomLock; - - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - var mainDomLock = appSettingMainDomLock == "SqlMainDomLock" || isWindows == false - ? (IMainDomLock)new SqlMainDomLock(loggerFactory.CreateLogger(), loggerFactory, globalSettings, connectionStrings, dbProviderFactoryCreator, hostingEnvironment) - : new MainDomSemaphoreLock(loggerFactory.CreateLogger(), hostingEnvironment); - - var mainDom = new MainDom(loggerFactory.CreateLogger(), mainDomLock); - - var coreRuntime = new CoreRuntimeBootstrapper( - globalSettings, - connectionStrings, - umbracoVersion, - ioHelper, - loggerFactory, - profiler, - new AspNetCoreBootPermissionsChecker(), - hostingEnvironment, - backOfficeInfo, - dbProviderFactoryCreator, - mainDom, - typeFinder, - appCaches); - - return coreRuntime; - } - - private static IServiceCollection CreateCompositionRoot( - IServiceCollection services, - IOptionsMonitor globalSettings, - IOptionsMonitor hostingSettings, - IWebHostEnvironment webHostEnvironment, - ILoggingConfiguration loggingConfiguration, - IConfiguration configuration, - out IIOHelper ioHelper, - out Core.Hosting.IHostingEnvironment hostingEnvironment, - out IBackOfficeInfo backOfficeInfo, - out IProfiler profiler) - { - if (globalSettings == null) - throw new InvalidOperationException($"Could not resolve type {typeof(GlobalSettings)} from the container, ensure {nameof(AddUmbracoConfiguration)} is called before calling {nameof(AddUmbracoCore)}"); - - hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment); - ioHelper = new IOHelper(hostingEnvironment); - AddLogger(services, hostingEnvironment, loggingConfiguration, configuration); - backOfficeInfo = new AspNetCoreBackOfficeInfo(globalSettings); - profiler = GetWebProfiler(hostingEnvironment); - - return services; - } - + /// /// Create and configure the logger /// - /// - private static void AddLogger( - IServiceCollection services, + public static IServiceCollection AddLogger( + this IServiceCollection services, IHostingEnvironment hostingEnvironment, ILoggingConfiguration loggingConfiguration, IConfiguration configuration) @@ -397,7 +38,6 @@ namespace Umbraco.Extensions // This is nessasary to pick up all the loggins to MS ILogger. Log.Logger = logger.SerilogLog; - // Wire up all the bits that serilog needs. We need to use our own code since the Serilog ext methods don't cater to our needs since // we don't want to use the global serilog `Log` object and we don't have our own ILogger implementation before the HostBuilder runs which // is the only other option that these ext methods allow. @@ -420,32 +60,61 @@ namespace Umbraco.Extensions // Consumed by user code services.AddSingleton(diagnosticContext); + services.AddSingleton(loggingConfiguration); + + return services; } - private static IProfiler GetWebProfiler(Umbraco.Core.Hosting.IHostingEnvironment hostingEnvironment) + internal static ITypeFinder AddTypeFinder( + this IServiceCollection services, + ILoggerFactory loggerFactory, + IWebHostEnvironment webHostEnvironment, + Assembly entryAssembly, + IConfiguration config, + IProfilingLogger profilingLogger) { - // create and start asap to profile boot - if (!hostingEnvironment.IsDebugMode) - { - // should let it be null, that's how MiniProfiler is meant to work, - // but our own IProfiler expects an instance so let's get one - return new VoidProfiler(); - } - var webProfiler = new WebProfiler(); - webProfiler.StartBoot(); + var typeFinderSettings = config.GetSection(Core.Constants.Configuration.ConfigTypeFinder).Get() ?? new TypeFinderSettings(); - return webProfiler; + var runtimeHashPaths = new RuntimeHashPaths().AddFolder(new DirectoryInfo(Path.Combine(webHostEnvironment.ContentRootPath, "bin"))); + var runtimeHash = new RuntimeHash(profilingLogger, runtimeHashPaths); + + var typeFinder = new TypeFinder( + loggerFactory.CreateLogger(), + new DefaultUmbracoAssemblyProvider(entryAssembly), + runtimeHash, + new TypeFinderConfig(Options.Create(typeFinderSettings)) + ); + + services.AddUnique(typeFinder); + + return typeFinder; } - private class AspNetCoreBootPermissionsChecker : IUmbracoBootPermissionChecker + public static TypeLoader AddTypeLoader( + this IServiceCollection services, + Assembly entryAssembly, + IWebHostEnvironment webHostEnvironment, + IHostingEnvironment hostingEnvironment, + ILoggerFactory loggerFactory, + AppCaches appCaches, + IConfiguration configuration, + IProfiler profiler) { - public void ThrowIfNotPermissions() - { - // nothing to check - } - } + var profilingLogger = new ProfilingLogger(loggerFactory.CreateLogger(), profiler); + var typeFinder = services.AddTypeFinder(loggerFactory, webHostEnvironment, entryAssembly, configuration, profilingLogger); + var typeLoader = new TypeLoader( + typeFinder, + appCaches.RuntimeCache, + new DirectoryInfo(hostingEnvironment.LocalTempPath), + loggerFactory.CreateLogger(), + profilingLogger + ); + + services.AddUnique(typeLoader); + + return typeLoader; + } } - } diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs index fdab7d7169..c1f9849621 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs @@ -14,28 +14,17 @@ using SixLabors.ImageSharp.Web.Processors; using SixLabors.ImageSharp.Web.Providers; using Smidge; using Smidge.Nuglify; +using Umbraco.Core.Builder; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration.Models.Validation; using Umbraco.Web.Common.ApplicationModels; namespace Umbraco.Extensions { public static class UmbracoWebServiceCollectionExtensions { - /// - /// Registers the web components needed for Umbraco - /// - /// - /// - /// - public static IServiceCollection AddUmbracoWebComponents(this IServiceCollection services, IConfiguration configuration) - { - services.ConfigureOptions(); - services.TryAddEnumerable(ServiceDescriptor.Transient()); - services.TryAddEnumerable(ServiceDescriptor.Transient()); - services.AddUmbracoImageSharp(configuration); + - return services; - } /// /// Adds Image Sharp with Umbraco settings @@ -81,20 +70,6 @@ namespace Umbraco.Extensions return services; } - /// - /// Adds the Umbraco runtime minifier - /// - /// - /// - /// - public static IServiceCollection AddUmbracoRuntimeMinifier(this IServiceCollection services, - IConfiguration configuration) - { - services.AddSmidge(configuration.GetSection(Core.Constants.Configuration.ConfigRuntimeMinification)); - services.AddSmidgeNuglify(); - - return services; - } private static void RemoveIntParamenterIfValueGreatherThen(IDictionary commands, string parameter, int maxValue) { @@ -117,7 +92,7 @@ namespace Umbraco.Extensions /// We generally don't want to change the global MVC settings since we want to be unobtrusive as possible but some /// global mods are needed - so long as they don't interfere with normal user usages of MVC. /// - private class UmbracoMvcConfigureOptions : IConfigureOptions + public class UmbracoMvcConfigureOptions : IConfigureOptions { // TODO: we can inject params with DI here diff --git a/src/Umbraco.Web.Common/Install/InstallAuthorizeAttribute.cs b/src/Umbraco.Web.Common/Install/InstallAuthorizeAttribute.cs index 5490da961d..04f743144e 100644 --- a/src/Umbraco.Web.Common/Install/InstallAuthorizeAttribute.cs +++ b/src/Umbraco.Web.Common/Install/InstallAuthorizeAttribute.cs @@ -1,9 +1,9 @@ using System; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Core; +using Umbraco.Core.Security; namespace Umbraco.Web.Common.Install { @@ -21,33 +21,42 @@ namespace Umbraco.Web.Common.Install private class InstallAuthorizeFilter : IAuthorizationFilter { + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; + private readonly IRuntimeState _runtimeState; + private readonly ILogger _logger; + + public InstallAuthorizeFilter( + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, + IRuntimeState runtimeState, + ILogger logger) + { + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; + _runtimeState = runtimeState; + _logger = logger; + } + public void OnAuthorization(AuthorizationFilterContext authorizationFilterContext) { - var serviceProvider = authorizationFilterContext.HttpContext.RequestServices; - var runtimeState = serviceProvider.GetService(); - var umbracoContext = serviceProvider.GetService(); - var logger = serviceProvider.GetService>(); - - if (!IsAllowed(runtimeState, umbracoContext, logger)) + if (!IsAllowed()) { authorizationFilterContext.Result = new ForbidResult(); } } - private static bool IsAllowed(IRuntimeState runtimeState, IUmbracoContext umbracoContext, ILogger logger) + private bool IsAllowed() { try { // if not configured (install or upgrade) then we can continue // otherwise we need to ensure that a user is logged in - return runtimeState.Level == RuntimeLevel.Install - || runtimeState.Level == RuntimeLevel.Upgrade - || (umbracoContext?.Security?.ValidateCurrentUser() ?? false); + return _runtimeState.Level == RuntimeLevel.Install + || _runtimeState.Level == RuntimeLevel.Upgrade + || (_backOfficeSecurityAccessor?.BackOfficeSecurity?.ValidateCurrentUser() ?? false); } catch (Exception ex) { - logger.LogError(ex, "An error occurred determining authorization"); + _logger.LogError(ex, "An error occurred determining authorization"); return false; } } diff --git a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs index c0d2fdbdd4..43425d7bb8 100644 --- a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs @@ -25,6 +25,7 @@ namespace Umbraco.Web.Macros private readonly IProfilingLogger _profilingLogger; private readonly ILogger _logger; private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly ContentSettings _contentSettings; private readonly ILocalizedTextService _textService; private readonly AppCaches _appCaches; @@ -40,6 +41,7 @@ namespace Umbraco.Web.Macros IProfilingLogger profilingLogger , ILogger logger, IUmbracoContextAccessor umbracoContextAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IOptions contentSettings, ILocalizedTextService textService, AppCaches appCaches, @@ -54,6 +56,7 @@ namespace Umbraco.Web.Macros _profilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger )); _logger = logger; _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); _textService = textService; _appCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches)); @@ -89,7 +92,7 @@ namespace Umbraco.Web.Macros { object key = 0; - if (_umbracoContextAccessor.GetRequiredUmbracoContext().Security.IsAuthenticated()) + if (_backOfficeSecurityAccessor.BackOfficeSecurity.IsAuthenticated()) { key = _memberUserKeyProvider.GetMemberProviderUserKey() ?? 0; } diff --git a/src/Umbraco.Web.Common/Profiler/WebProfilerComposer.cs b/src/Umbraco.Web.Common/Profiler/WebProfilerComposer.cs index fd8f275291..702c30f692 100644 --- a/src/Umbraco.Web.Common/Profiler/WebProfilerComposer.cs +++ b/src/Umbraco.Web.Common/Profiler/WebProfilerComposer.cs @@ -1,15 +1,16 @@ using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; namespace Umbraco.Web.Common.Profiler { internal class WebProfilerComposer : ComponentComposer, ICoreComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); - composition.Services.AddUnique(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs index 196b115618..58fa5ea317 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreBootFailedComposer.cs @@ -1,4 +1,5 @@ using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Web.Common.Middleware; @@ -9,9 +10,9 @@ namespace Umbraco.Web.Common.Runtime /// public class AspNetCoreBootFailedComposer : IComposer { - public void Compose(Composition composition) + public void Compose(IUmbracoBuilder builder) { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs index 163991c458..f20ab5ab75 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Diagnostics; @@ -40,68 +41,63 @@ namespace Umbraco.Web.Common.Runtime [ComposeAfter(typeof(CoreInitialComposer))] public class AspNetCoreComposer : ComponentComposer, IComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); // AspNetCore specific services - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); // Our own netcore implementations - composition.Services.AddMultipleUnique(); + builder.Services.AddMultipleUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); // The umbraco request lifetime - composition.Services.AddMultipleUnique(); + builder.Services.AddMultipleUnique(); // Password hasher - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddTransient(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddTransient(); + builder.Services.AddUnique(); - composition.Services.AddMultipleUnique(); + builder.Services.AddMultipleUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); // register the umbraco context factory - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); //register the install components - composition.ComposeInstaller(); + builder.ComposeInstaller(); - var umbracoApiControllerTypes = composition.TypeLoader.GetUmbracoApiControllers().ToList(); - composition.WithCollectionBuilder() + var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList(); + builder.WithCollectionBuilder() .Add(umbracoApiControllerTypes); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddUnique(factory => new LegacyPasswordSecurity()); - - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); } } } diff --git a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs index 3400ee49d9..5b3d776679 100644 --- a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs +++ b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Smidge.FileProcessors; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.Runtime; using Umbraco.Core.WebAssets; @@ -9,14 +10,14 @@ namespace Umbraco.Web.Common.RuntimeMinification { public sealed class SmidgeComposer : IComposer { - public void Compose(Composition composition) + public void Compose(IUmbracoBuilder builder) { // TODO: For this to work we need to have services.AddSmidge() based on the Smidge APIs but our composer APIs don't really let us do that // This makes it a bit awkward to boot the runtime since that call would need to be made outside of the composer... .hrm... - composition.Services.AddUnique(); - composition.Services.AddUnique(); - composition.Services.AddTransient(); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddTransient(); } } } diff --git a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs index a0bc8b9140..56dd4b054e 100644 --- a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs +++ b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs @@ -21,6 +21,7 @@ namespace Umbraco.Web private readonly Lazy _publishedSnapshot; private string _previewToken; private bool? _previewing; + private IBackOfficeSecurity _backofficeSecurity; // initializes a new instance of the UmbracoContext class // internal for unit tests @@ -46,7 +47,7 @@ namespace Umbraco.Web ObjectCreated = DateTime.Now; UmbracoRequestId = Guid.NewGuid(); - Security = backofficeSecurity ?? throw new ArgumentNullException(nameof(backofficeSecurity)); + _backofficeSecurity = backofficeSecurity ?? throw new ArgumentNullException(nameof(backofficeSecurity)); // beware - we cannot expect a current user here, so detecting preview mode must be a lazy thing _publishedSnapshot = new Lazy(() => publishedSnapshotService.CreatePublishedSnapshot(PreviewToken)); @@ -74,11 +75,6 @@ namespace Umbraco.Web /// public Guid UmbracoRequestId { get; } - /// - /// Gets the BackofficeSecurity class - /// - public IBackOfficeSecurity Security { get; } - /// /// Gets the uri that is handled by ASP.NET after server-side rewriting took place. /// @@ -168,7 +164,7 @@ namespace Umbraco.Web var requestUrl = _requestAccessor.GetRequestUrl(); if (requestUrl != null && requestUrl.IsBackOfficeRequest(_globalSettings, _hostingEnvironment) == false - && Security.CurrentUser != null) + && _backofficeSecurity.CurrentUser != null) { var previewToken = _cookieManager.GetCookieValue(Constants.Web.PreviewCookieName); // may be null or empty _previewToken = previewToken.IsNullOrWhiteSpace() ? null : previewToken; @@ -190,8 +186,6 @@ namespace Umbraco.Web { // DisposableObject ensures that this runs only once - Security.DisposeIfDisposable(); - // help caches release resources // (but don't create caches just to dispose them) // context is not multi-threaded diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index 2a4d4a4580..ca62523c4d 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -32,12 +32,10 @@ namespace Umbraco.Web.UI.NetCore // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { - var umbracoBuilder = services.AddUmbraco(_env, _config); - umbracoBuilder - .WithAllBackOfficeComponents() - .WithAllWebsiteComponents() + services.AddUmbraco(_env, _config) + .AddAllBackOfficeComponents() + .AddUmbracoWebsite() .Build(); - } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/src/Umbraco.Web.UI/Views/Partials/BlockList/Default.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/BlockList/Default.cshtml similarity index 77% rename from src/Umbraco.Web.UI/Views/Partials/BlockList/Default.cshtml rename to src/Umbraco.Web.UI.NetCore/Views/Partials/BlockList/Default.cshtml index c94a51f6d9..6da7e63ac6 100644 --- a/src/Umbraco.Web.UI/Views/Partials/BlockList/Default.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/BlockList/Default.cshtml @@ -1,13 +1,13 @@ -@inherits UmbracoViewPage -@using Umbraco.Core.Models.Blocks -@{ - if (!Model.Any()) { return; } -} -
- @foreach (var block in Model) - { - if (block?.ContentUdi == null) { continue; } - var data = block.Content; - @Html.Partial("BlockList/Components/" + data.ContentType.Alias, block) - } -
+@inherits Umbraco.Web.Common.AspNetCore.UmbracoViewPage +@using Umbraco.Core.Models.Blocks +@{ + if (!Model.Any()) { return; } +} +
+ @foreach (var block in Model) + { + if (block?.ContentUdi == null) { continue; } + var data = block.Content; + @Html.Partial("BlockList/Components/" + data.ContentType.Alias, block) + } +
diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3-Fluid.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Bootstrap3-Fluid.cshtml similarity index 66% rename from src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3-Fluid.cshtml rename to src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Bootstrap3-Fluid.cshtml index 131b0515ae..b8bb0b521e 100644 --- a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3-Fluid.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Bootstrap3-Fluid.cshtml @@ -1,5 +1,6 @@ -@inherits UmbracoViewPage -@using Umbraco.Web.Templates +@inherits Umbraco.Web.Common.AspNetCore.UmbracoViewPage +@using System.Web +@using Microsoft.AspNetCore.Html @using Newtonsoft.Json.Linq @* @@ -36,25 +37,28 @@ } -@helper renderRow(dynamic row){ -
-
- @foreach ( var area in row.areas ) { -
-
- @foreach (var control in area.controls) { - if (control !=null && control.editor != null && control.editor.view != null ) { - @Html.Partial("grid/editors/base", (object)control) - } - } -
-
} +@functions { + private void renderRow(dynamic row) + { +
+
+ @foreach ( var area in row.areas ) { +
+
+ @foreach (var control in area.controls) { + if (control !=null && control.editor != null && control.editor.view != null ) { + @Html.Partial("grid/editors/base", (object)control) + } + } +
+
} +
-
+ } } @functions { - public static MvcHtmlString RenderElementAttributes(dynamic contentItem) + public static HtmlString RenderElementAttributes(dynamic contentItem) { var attrs = new List(); JObject cfg = contentItem.config; @@ -83,6 +87,6 @@ attrs.Add("style='" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "'"); } - return new MvcHtmlString(string.Join(" ", attrs)); + return new HtmlString(string.Join(" ", attrs)); } } diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Bootstrap3.cshtml similarity index 63% rename from src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml rename to src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Bootstrap3.cshtml index c30feb2165..5453a7aac5 100644 --- a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Bootstrap3.cshtml @@ -1,5 +1,6 @@ -@inherits UmbracoViewPage -@using Umbraco.Web.Templates +@inherits Umbraco.Web.Common.AspNetCore.UmbracoViewPage +@using System.Web +@using Microsoft.AspNetCore.Html @using Newtonsoft.Json.Linq @if (Model != null && Model.sections != null) @@ -34,31 +35,37 @@
} -@helper renderRow(dynamic row, bool singleColumn){ -
- @if (singleColumn) { - @:
- } -
- @foreach ( var area in row.areas ) { -
-
- @foreach (var control in area.controls) { - if (control !=null && control.editor != null && control.editor.view != null ) { - @Html.Partial("grid/editors/base", (object)control) - } - } -
-
} +@functions { + + private void renderRow(dynamic row, bool singleColumn) + { +
+ @if (singleColumn) { + @:
+ } +
+ @foreach ( var area in row.areas ) { +
+
+ @foreach (var control in area.controls) { + if (control !=null && control.editor != null && control.editor.view != null ) { + @Html.Partial("grid/editors/base", (object)control) + } + } +
+
} +
+ @if (singleColumn) { + @:
+ }
- @if (singleColumn) { - @:
- } -
+ } + } + @functions { - public static MvcHtmlString RenderElementAttributes(dynamic contentItem) + public static HtmlString RenderElementAttributes(dynamic contentItem) { var attrs = new List(); JObject cfg = contentItem.config; @@ -87,6 +94,6 @@ attrs.Add("style=\"" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "\""); } - return new MvcHtmlString(string.Join(" ", attrs)); + return new HtmlString(string.Join(" ", attrs)); } } diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Base.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Base.cshtml similarity index 75% rename from src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Base.cshtml rename to src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Base.cshtml index a86c04819a..d3cdf80f06 100644 --- a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Base.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Base.cshtml @@ -1,12 +1,11 @@ @model dynamic -@using Umbraco.Web.Templates @functions { public static string EditorView(dynamic contentItem) { string view = contentItem.editor.render != null ? contentItem.editor.render.ToString() : contentItem.editor.view.ToString(); view = view.ToLower().Replace(".html", ".cshtml"); - + if (!view.Contains("/")) { view = "grid/editors/" + view; } @@ -16,9 +15,9 @@ } @try { - string editor = EditorView(Model); + string editor = EditorView(Model); @Html.Partial(editor, (object)Model) } -catch (Exception ex) { +catch (Exception ex) {
@ex.ToString()
-} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Embed.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Embed.cshtml similarity index 80% rename from src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Embed.cshtml rename to src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Embed.cshtml index 4a915a444b..250310217c 100644 --- a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Embed.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Embed.cshtml @@ -1,5 +1,6 @@ -@model dynamic -@using Umbraco.Web.Templates +@using Umbraco.Core +@model dynamic + @{ string embedValue = Convert.ToString(Model.value); embedValue = embedValue.DetectIsJson() ? Model.value.preview : Model.value; diff --git a/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Macro.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Macro.cshtml new file mode 100644 index 0000000000..26c6e8a09c --- /dev/null +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Macro.cshtml @@ -0,0 +1,17 @@ +@inherits Umbraco.Web.Common.AspNetCore.UmbracoViewPage +@using Umbraco.Web.Website +@inject UmbracoHelper Umbraco; + +@if (Model.value != null) +{ + string macroAlias = Model.value.macroAlias.ToString(); + var parameters = new Dictionary(); + foreach (var mpd in Model.value.macroParamsDictionary) + { + parameters.Add(mpd.Name, mpd.Value); + } + + + @Umbraco.RenderMacro(macroAlias, parameters) + +} diff --git a/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Rte.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Rte.cshtml new file mode 100644 index 0000000000..b7bac31bd1 --- /dev/null +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/Rte.cshtml @@ -0,0 +1,13 @@ +@model dynamic +@using Umbraco.Web.Templates +@inject HtmlLocalLinkParser HtmlLocalLinkParser; +@inject HtmlUrlParser HtmlUrlParser; +@inject HtmlImageSourceParser HtmlImageSourceParser; + +@{ + + var value = HtmlUrlParser.EnsureUrls(Model.value.ToString()); + value = HtmlImageSourceParser.EnsureImageSources(value); + value = HtmlLocalLinkParser.EnsureInternalLinks(value); +} +@Html.Raw(value) diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/TextString.cshtml similarity index 87% rename from src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml rename to src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/TextString.cshtml index 0e47b5bd78..2ceac54e26 100644 --- a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/TextString.cshtml @@ -1,6 +1,6 @@ -@model dynamic -@using Umbraco.Web.Composing -@using Umbraco.Web.Templates +@using System.Web +@using Umbraco.Extensions +@model dynamic @if (Model.editor.config.markup != null) { diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 93f13e73e0..0e07e0af50 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -200,14 +200,6 @@ Designer - - - - - - - - Web.Template.config Designer diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Macro.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Macro.cshtml deleted file mode 100644 index e0822808d8..0000000000 --- a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Macro.cshtml +++ /dev/null @@ -1,17 +0,0 @@ -@inherits UmbracoViewPage -@using Umbraco.Web.Templates - - -@if (Model.value != null) -{ - string macroAlias = Model.value.macroAlias.ToString(); - ViewDataDictionary parameters = new ViewDataDictionary(); - foreach (dynamic mpd in Model.value.macroParamsDictionary) - { - parameters.Add(mpd.Name, mpd.Value); - } - - - @Umbraco.RenderMacro(macroAlias, parameters) - -} diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Rte.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Rte.cshtml deleted file mode 100644 index 715aad12d6..0000000000 --- a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Rte.cshtml +++ /dev/null @@ -1,20 +0,0 @@ -@model dynamic -@using Umbraco.Web.Composing -@using Umbraco.Web.Templates - -@* - TODO: When this project is asp.net core we can @inject HtmlLocalLinkParser etc (or come up with something even better) -*@ - -@using Microsoft.Extensions.DependencyInjection - -@{ - var htmlLocalLinkParser = Current.Factory.GetRequiredService(); - var htmlUrlParser = Current.Factory.GetRequiredService(); - var htmlImageSourceParser = Current.Factory.GetRequiredService(); - - var value = htmlUrlParser.EnsureUrls(Model.value.ToString()); - value = htmlImageSourceParser.EnsureImageSources(value); - value = htmlLocalLinkParser.EnsureInternalLinks(value); -} -@Html.Raw(value) diff --git a/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs index a48ed435bf..a367dc71ea 100644 --- a/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs @@ -893,7 +893,7 @@ namespace Umbraco.Extensions /// /// The HTML encoded text with text line breaks replaced with HTML line breaks (<br />). /// - public static IHtmlContent ReplaceLineBreaks(this HtmlHelper helper, string text) + public static IHtmlContent ReplaceLineBreaks(this IHtmlHelper helper, string text) { return StringUtilities.ReplaceLineBreaks(text); } @@ -905,7 +905,7 @@ namespace Umbraco.Extensions /// /// The text to create a hash from /// Hash of the text string - public static string CreateHash(this HtmlHelper helper, string text) + public static string CreateHash(this IHtmlHelper helper, string text) { return text.GenerateHash(); } diff --git a/src/Umbraco.Web.Website/Extensions/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/Extensions/UmbracoBuilderExtensions.cs index 8e56cd6dca..3715f5e37b 100644 --- a/src/Umbraco.Web.Website/Extensions/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/Extensions/UmbracoBuilderExtensions.cs @@ -1,20 +1,32 @@ -using Umbraco.Web.Common.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Umbraco.Core.Builder; +using Umbraco.Web.Common.Builder; +using Umbraco.Web.Website.ViewEngines; namespace Umbraco.Extensions { public static class UmbracoBuilderExtensions { - public static IUmbracoBuilder WithAllWebsiteComponents(this IUmbracoBuilder builder) + public static IUmbracoBuilder AddUmbracoWebsite(this IUmbracoBuilder builder) { - builder - .WithUmbracoWebsite(); + // Set the render & plugin view engines (Super complicated, but this allows us to use the IServiceCollection + // to inject dependencies into the viewEngines) + builder.Services.AddTransient, RenderMvcViewOptionsSetup>(); + builder.Services.AddSingleton(); + builder.Services.AddTransient, PluginMvcViewOptionsSetup>(); + builder.Services.AddSingleton(); + + // Wraps all existing view engines in a ProfilerViewEngine + builder.Services.AddTransient, ProfilingViewEngineWrapperMvcViewOptionsSetup>(); + + //TODO figure out if we need more to work on load balanced setups + builder.Services.AddDataProtection(); return builder; } - public static IUmbracoBuilder WithUmbracoWebsite(this IUmbracoBuilder builder) - => builder.AddWith(nameof(WithUmbracoWebsite), () => builder.Services.AddUmbracoWebsite()); - } } diff --git a/src/Umbraco.Web.Website/Extensions/UmbracoWebsiteServiceCollectionExtensions.cs b/src/Umbraco.Web.Website/Extensions/UmbracoWebsiteServiceCollectionExtensions.cs deleted file mode 100644 index 036d66128d..0000000000 --- a/src/Umbraco.Web.Website/Extensions/UmbracoWebsiteServiceCollectionExtensions.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Umbraco.Web.Website.ViewEngines; - -namespace Umbraco.Extensions -{ - public static class UmbracoWebsiteServiceCollectionExtensions - { - public static void AddUmbracoWebsite(this IServiceCollection services) - { - // Set the render & plugin view engines (Super complicated, but this allows us to use the IServiceCollection - // to inject dependencies into the viewEngines) - services.AddTransient, RenderMvcViewOptionsSetup>(); - services.AddSingleton(); - services.AddTransient, PluginMvcViewOptionsSetup>(); - services.AddSingleton(); - - // Wraps all existing view engines in a ProfilerViewEngine - services.AddTransient, ProfilingViewEngineWrapperMvcViewOptionsSetup>(); - - //TODO figure out if we need more to work on load balanced setups - services.AddDataProtection(); - } - } -} diff --git a/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs b/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs index 055b146a51..ce3ff7271e 100644 --- a/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs +++ b/src/Umbraco.Web.Website/Runtime/WebsiteComposer.cs @@ -1,4 +1,5 @@ using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Extensions; using Umbraco.Web.Website.Routing; @@ -12,12 +13,12 @@ namespace Umbraco.Web.Website.Runtime [ComposeAfter(typeof(AspNetCoreComposer))] public class WebsiteComposer : IComposer { - public void Compose(Composition composition) + public void Compose(IUmbracoBuilder builder) { - composition.Services.AddUnique(); + builder.Services.AddUnique(); - composition.WithCollectionBuilder() - .Add(composition.TypeLoader.GetSurfaceControllers()); + builder.WithCollectionBuilder() + .Add(builder.TypeLoader.GetSurfaceControllers()); } } } diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index b1e13745d8..8f698db995 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -21,6 +21,7 @@ using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Runtime; using Umbraco.Core.Scoping; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Sync; @@ -87,6 +88,9 @@ namespace Umbraco.Web.Composing public static IUmbracoContext UmbracoContext => UmbracoContextAccessor.UmbracoContext; + public static IBackOfficeSecurityAccessor BackOfficeSecurityAccessor + => Factory.GetRequiredService(); + public static UmbracoHelper UmbracoHelper => Factory.GetRequiredService(); public static IUmbracoComponentRenderer UmbracoComponentRenderer diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index d96e21aa3d..957172ccff 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -1,6 +1,7 @@ using System; using Microsoft.Extensions.DependencyInjection; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Web.Actions; using Umbraco.Web.ContentApps; @@ -19,21 +20,21 @@ using Current = Umbraco.Web.Composing.Current; // the namespace here is intentional - although defined in Umbraco.Web assembly, // this class should be visible when using Umbraco.Core.Components, alongside -// Umbraco.Core's own CompositionExtensions class +// Umbraco.Core's own IUmbracoBuilderExtensions class // ReSharper disable once CheckNamespace namespace Umbraco.Web { /// - /// Provides extension methods to the class. + /// Provides extension methods to the class. /// - public static class WebCompositionExtensions + public static class WebIUmbracoBuilderExtensions { [Obsolete("This extension method exists only to ease migration, please refactor")] - public static IServiceProvider CreateServiceProvider(this Composition composition) + public static IServiceProvider CreateServiceProvider(this IUmbracoBuilder builder) { - composition.RegisterBuilders(); - return composition.Services.BuildServiceProvider(); + builder.Build(); + return builder.Services.BuildServiceProvider(); } #region Uniques @@ -42,62 +43,62 @@ namespace Umbraco.Web /// Sets the content last chance finder. /// /// The type of the content last chance finder. - /// The composition. - public static void SetContentLastChanceFinder(this Composition composition) + /// The builder. + public static void SetContentLastChanceFinder(this IUmbracoBuilder builder) where T : class, IContentLastChanceFinder { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } /// /// Sets the content last chance finder. /// - /// The composition. + /// The builder. /// A function creating a last chance finder. - public static void SetContentLastChanceFinder(this Composition composition, Func factory) + public static void SetContentLastChanceFinder(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the content last chance finder. /// - /// The composition. + /// The builder. /// A last chance finder. - public static void SetContentLastChanceFinder(this Composition composition, IContentLastChanceFinder finder) + public static void SetContentLastChanceFinder(this IUmbracoBuilder builder, IContentLastChanceFinder finder) { - composition.Services.AddUnique(_ => finder); + builder.Services.AddUnique(finder); } /// /// Sets the site domain helper. /// /// The type of the site domain helper. - /// - public static void SetSiteDomainHelper(this Composition composition) + /// + public static void SetSiteDomainHelper(this IUmbracoBuilder builder) where T : class, ISiteDomainHelper { - composition.Services.AddUnique(); + builder.Services.AddUnique(); } /// /// Sets the site domain helper. /// - /// The composition. + /// The builder. /// A function creating a helper. - public static void SetSiteDomainHelper(this Composition composition, Func factory) + public static void SetSiteDomainHelper(this IUmbracoBuilder builder, Func factory) { - composition.Services.AddUnique(factory); + builder.Services.AddUnique(factory); } /// /// Sets the site domain helper. /// - /// The composition. + /// The builder. /// A helper. - public static void SetSiteDomainHelper(this Composition composition, ISiteDomainHelper helper) + public static void SetSiteDomainHelper(this IUmbracoBuilder builder, ISiteDomainHelper helper) { - composition.Services.AddUnique(_ => helper); + builder.Services.AddUnique(helper); } #endregion diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs index a9127aca17..8ada898c21 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.Mvc private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private IBackOfficeSecurity BackOfficeSecurity => _backOfficeSecurityAccessor.BackOfficeSecurity ?? Current.UmbracoContext.Security; + private IBackOfficeSecurity BackOfficeSecurity => _backOfficeSecurityAccessor.BackOfficeSecurity ?? Current.BackOfficeSecurityAccessor.BackOfficeSecurity; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 32e7835ffb..0d866363c4 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -3,6 +3,7 @@ using System.Web.Security; using Microsoft.AspNet.SignalR; using Microsoft.Extensions.DependencyInjection; using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.Dictionary; using Umbraco.Core.Templates; @@ -23,36 +24,36 @@ namespace Umbraco.Web.Runtime [ComposeBefore(typeof(ICoreComposer))] public sealed class WebInitialComposer : ComponentComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); + base.Compose(builder); - composition.Services.AddTransient(); + builder.Services.AddTransient(); // register membership stuff - composition.Services.AddTransient(factory => MembershipProviderExtensions.GetMembersMembershipProvider()); - composition.Services.AddTransient(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetRequiredService())); - composition.Services.AddScoped(); - composition.Services.AddTransient(factory => factory.GetRequiredService().PublishedSnapshot.Members); - composition.Services.AddUnique(); - composition.Services.AddUnique(); + builder.Services.AddTransient(factory => MembershipProviderExtensions.GetMembersMembershipProvider()); + builder.Services.AddTransient(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetRequiredService())); + builder.Services.AddScoped(); + builder.Services.AddTransient(factory => factory.GetRequiredService().PublishedSnapshot.Members); + builder.Services.AddUnique(); + builder.Services.AddUnique(); + builder.Services.AddTransient(factory => + { + var state = factory.GetRequiredService(); - // register the umbraco helper - this is Transient! very important! - // also, if not level.Run, we cannot really use the helper (during upgrade...) - // so inject a "void" helper (not exactly pretty but...) - if (composition.RuntimeState.Level == RuntimeLevel.Run) - composition.Services.AddTransient(factory => + if (state.Level == RuntimeLevel.Run) { var umbCtx = factory.GetRequiredService(); return new UmbracoHelper(umbCtx.IsFrontEndUmbracoRequest ? umbCtx.PublishedRequest?.PublishedContent : null, factory.GetRequiredService(), factory.GetRequiredService(), factory.GetRequiredService()); - }); - else - composition.Services.AddTransient(_ => new UmbracoHelper()); + } - composition.Services.AddUnique(); + return new UmbracoHelper(); + }); + + builder.Services.AddUnique(); // configure the container for web //composition.ConfigureForWeb(); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 8157a90715..ae2c1b8fb6 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -221,7 +221,6 @@ - diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 3218710902..032ee9bb4f 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -19,35 +19,8 @@ namespace Umbraco.Web /// public class UmbracoApplication : UmbracoApplicationBase { - protected override CoreRuntimeBootstrapper GetRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) - { - var dbProviderFactoryCreator = new UmbracoDbProviderFactoryCreator(); - // Determine if we should use the sql main dom or the default - var appSettingMainDomLock = globalSettings.MainDomLock; - - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - var mainDomLock = appSettingMainDomLock == "SqlMainDomLock" || isWindows == false - ? (IMainDomLock)new SqlMainDomLock(loggerFactory.CreateLogger(), loggerFactory, globalSettings, connectionStrings, dbProviderFactoryCreator, hostingEnvironment) - : new MainDomSemaphoreLock(loggerFactory.CreateLogger(), hostingEnvironment); - - var mainDom = new MainDom(loggerFactory.CreateLogger(), mainDomLock); - - // Commented out as part of .NET Core transition as the HttpRequestAppCache constructor has changed to - // to match the change in the type of the HTTP context Items collection. - //// var requestCache = new HttpRequestAppCache(() => HttpContext.Current != null ? HttpContext.Current.Items : null); - IRequestCache requestCache = null; - var appCaches = new AppCaches( - new DeepCloneAppCache(new ObjectCacheAppCache()), - requestCache, - new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); - - var umbracoBootPermissionChecker = new AspNetUmbracoBootPermissionChecker(); - return new CoreRuntimeBootstrapper(globalSettings, connectionStrings,umbracoVersion, ioHelper, loggerFactory, profiler, umbracoBootPermissionChecker, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, - GetTypeFinder(hostingEnvironment, logger, profiler), appCaches); - } - } } diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index fe10cfba81..9f3aa7dd0d 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -113,7 +113,7 @@ namespace Umbraco.Web runtimeHashPaths.AddFile(new FileInfo(hostingEnvironment.MapPathContentRoot("~/App_Code"))); // global.asax (the app domain also monitors this, if it changes will do a full restart) runtimeHashPaths.AddFile(new FileInfo(hostingEnvironment.MapPathContentRoot("~/global.asax"))); - var runtimeHash = new RuntimeHash(new ProfilingLogger(_loggerFactory.CreateLogger("RuntimeHash"), profiler), runtimeHashPaths); + var runtimeHash = new RuntimeHash(new ProfilingLogger(_loggerFactory.CreateLogger(), profiler), runtimeHashPaths); return new TypeFinder(_loggerFactory.CreateLogger(), new DefaultUmbracoAssemblyProvider( // GetEntryAssembly was actually an exposed API by request of the aspnetcore team which works in aspnet core because a website // in that case is essentially an exe. However in netframework there is no entry assembly, things don't really work that way since @@ -129,11 +129,6 @@ namespace Umbraco.Web Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly()), runtimeHash); } - /// - /// Gets a runtime. - /// - protected abstract CoreRuntimeBootstrapper GetRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo); - /// /// Gets the application register. /// @@ -177,17 +172,17 @@ namespace Umbraco.Web // create the register for the application, and boot // the boot manager is responsible for registrations var register = GetRegister(globalSettings); - var boostrapper = GetRuntime( - _globalSettings, - _connectionStrings, - umbracoVersion, - _ioHelper, - _logger, - _loggerFactory, - null, // TODO get from somewhere that isn't Current. - null, // TODO get from somewhere that isn't Current. - null // TODO get from somewhere that isn't Current. - ); + //var boostrapper = GetRuntime( + // _globalSettings, + // _connectionStrings, + // umbracoVersion, + // _ioHelper, + // _logger, + // _loggerFactory, + // null, // TODO get from somewhere that isn't Current. + // null, // TODO get from somewhere that isn't Current. + // null // TODO get from somewhere that isn't Current. + // ); //_factory = Current.Factory = _runtime.Configure(register); diff --git a/src/Umbraco.Web/UmbracoHttpHandler.cs b/src/Umbraco.Web/UmbracoHttpHandler.cs index 8a76770fda..711af68613 100644 --- a/src/Umbraco.Web/UmbracoHttpHandler.cs +++ b/src/Umbraco.Web/UmbracoHttpHandler.cs @@ -13,12 +13,13 @@ namespace Umbraco.Web private UrlHelper _url; protected UmbracoHttpHandler() - : this(Current.UmbracoContextAccessor, Current.Services, Current.Logger, Current.ProfilingLogger) + : this(Current.UmbracoContextAccessor, Current.BackOfficeSecurityAccessor, Current.Services, Current.Logger, Current.ProfilingLogger) { } - protected UmbracoHttpHandler(IUmbracoContextAccessor umbracoContextAccessor,ServiceContext service, ILogger logger, IProfilingLogger profilingLogger ) + protected UmbracoHttpHandler(IUmbracoContextAccessor umbracoContextAccessor, IBackOfficeSecurityAccessor backOfficeSecurityAccessor,ServiceContext service, ILogger logger, IProfilingLogger profilingLogger ) { UmbracoContextAccessor = umbracoContextAccessor; + BackOfficeSecurityAccessor = backOfficeSecurityAccessor; Logger = logger; ProfilingLogger = profilingLogger ; Services = service; @@ -43,6 +44,8 @@ namespace Umbraco.Web /// public IUmbracoContextAccessor UmbracoContextAccessor { get; } + public IBackOfficeSecurityAccessor BackOfficeSecurityAccessor { get; } + /// /// Gets the services context. /// @@ -51,7 +54,7 @@ namespace Umbraco.Web /// /// Gets the web security helper. /// - public IBackOfficeSecurity Security => UmbracoContextAccessor.UmbracoContext.Security; + public IBackOfficeSecurity Security => BackOfficeSecurityAccessor.BackOfficeSecurity; /// /// Gets the Url helper. diff --git a/src/Umbraco.Web/UmbracoWebService.cs b/src/Umbraco.Web/UmbracoWebService.cs index 0d4c4646f0..27c6af2c8b 100644 --- a/src/Umbraco.Web/UmbracoWebService.cs +++ b/src/Umbraco.Web/UmbracoWebService.cs @@ -16,17 +16,18 @@ namespace Umbraco.Web { private UrlHelper _url; - protected UmbracoWebService(ILogger logger, IProfilingLogger profilingLogger, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, GlobalSettings globalSettings) + protected UmbracoWebService(ILogger logger, IProfilingLogger profilingLogger, IUmbracoContextAccessor umbracoContextAccessor, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, ServiceContext services, GlobalSettings globalSettings) { Logger = logger; ProfilingLogger = profilingLogger; UmbracoContextAccessor = umbracoContextAccessor; + BackOfficeSecurityAccessor = backOfficeSecurityAccessor; Services = services; GlobalSettings = globalSettings; } protected UmbracoWebService() - : this(Current.Logger, Current.ProfilingLogger, Current.UmbracoContextAccessor, Current.Services, new GlobalSettings()) + : this(Current.Logger, Current.ProfilingLogger, Current.UmbracoContextAccessor, Current.BackOfficeSecurityAccessor, Current.Services,new GlobalSettings()) { } @@ -50,6 +51,8 @@ namespace Umbraco.Web /// public IUmbracoContextAccessor UmbracoContextAccessor { get; } + public IBackOfficeSecurityAccessor BackOfficeSecurityAccessor { get; } + /// /// Gets the services context. /// @@ -63,7 +66,7 @@ namespace Umbraco.Web /// /// Gets the web security helper. /// - public IBackOfficeSecurity Security => UmbracoContext.Security; + public IBackOfficeSecurity Security => BackOfficeSecurityAccessor.BackOfficeSecurity; /// /// Gets the Url helper. diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index 724ea810c9..b1d8c7fcfe 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Persistence; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Routing; @@ -21,8 +22,8 @@ namespace Umbraco.Web.WebApi { } - protected UmbracoApiController(GlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + protected UmbracoApiController(GlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + : base(globalSettings, umbracoContextAccessor, backOfficeSecurityAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { } } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 7d9c620a6d..e5e123db88 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -41,6 +41,7 @@ namespace Umbraco.Web.WebApi : this( Current.Factory.GetRequiredService(), Current.Factory.GetRequiredService(), + Current.Factory.GetRequiredService(), Current.Factory.GetRequiredService(), Current.Factory.GetRequiredService(), Current.Factory.GetRequiredService(), @@ -54,9 +55,10 @@ namespace Umbraco.Web.WebApi /// /// Initializes a new instance of the class with all its dependencies. /// - protected UmbracoApiControllerBase(GlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + protected UmbracoApiControllerBase(GlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) { UmbracoContextAccessor = umbracoContextAccessor; + BackOfficeSecurityAccessor = backOfficeSecurityAccessor; SqlContext = sqlContext; Services = services; AppCaches = appCaches; @@ -82,6 +84,8 @@ namespace Umbraco.Web.WebApi /// public virtual IUmbracoContextAccessor UmbracoContextAccessor { get; } + public IBackOfficeSecurityAccessor BackOfficeSecurityAccessor { get; } + /// /// Gets the sql context. @@ -118,7 +122,7 @@ namespace Umbraco.Web.WebApi /// /// Gets the web security helper. /// - public IBackOfficeSecurity Security => UmbracoContext.Security; + public IBackOfficeSecurity Security => BackOfficeSecurityAccessor.BackOfficeSecurity; /// /// Tries to get the current HttpContext. diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs index 8e414be5ef..dea72b7be9 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.WebApi private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private IBackOfficeSecurity BackOfficeSecurity => _backOfficeSecurityAccessor.BackOfficeSecurity ?? Current.UmbracoContext.Security; + private IBackOfficeSecurity BackOfficeSecurity => _backOfficeSecurityAccessor.BackOfficeSecurity ?? Current.BackOfficeSecurityAccessor.BackOfficeSecurity; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 87627501bd..f744213276 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Security; using Umbraco.Core.Mapping; +using Umbraco.Core.Security; using Umbraco.Web.Routing; namespace Umbraco.Web.WebApi @@ -36,8 +37,8 @@ namespace Umbraco.Web.WebApi { } - protected UmbracoAuthorizedApiController(GlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) - : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) + protected UmbracoAuthorizedApiController(GlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, IBackOfficeSecurityAccessor backOfficeSecurityAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + : base(globalSettings, umbracoContextAccessor, backOfficeSecurityAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { } diff --git a/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComposer.cs b/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComposer.cs index bb8c2be059..c591191524 100644 --- a/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComposer.cs +++ b/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComposer.cs @@ -1,4 +1,5 @@ using Umbraco.Core; +using Umbraco.Core.Builder; using Umbraco.Core.Composing; using Umbraco.Core.WebAssets; @@ -6,10 +7,10 @@ namespace Umbraco.Web.WebAssets.CDF { public sealed class ClientDependencyComposer : ComponentComposer { - public override void Compose(Composition composition) + public override void Compose(IUmbracoBuilder builder) { - base.Compose(composition); - composition.Services.AddUnique(); + base.Compose(builder); + builder.Services.AddUnique(); } } }