Refactored CoreRuntime to inject a IUmbracoBootPermissionChecker, instead of using system.web to test this it self. Also moved some logging from CoreWebsite into WebRuntime, that used hosting information

This commit is contained in:
Bjarke Berg
2019-11-20 10:20:20 +01:00
parent 97ade695a7
commit ec169d17d7
10 changed files with 98 additions and 61 deletions

View File

@@ -0,0 +1,7 @@
namespace Umbraco.Core.Runtime
{
public interface IUmbracoBootPermissionChecker
{
void ThrowIfNotPermissions();
}
}

View File

@@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Web;
using System.Web.Hosting;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
@@ -26,13 +24,17 @@ namespace Umbraco.Core.Runtime
private ComponentCollection _components;
private IFactory _factory;
private RuntimeState _state;
private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker;
public CoreRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger)
public CoreRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler, IUmbracoBootPermissionChecker umbracoBootPermissionChecker)
{
IOHelper = ioHelper;
Configs = configs;
UmbracoVersion = umbracoVersion ;
Profiler = profiler;
_umbracoBootPermissionChecker = umbracoBootPermissionChecker;
Logger = logger;
// runtime state
@@ -56,7 +58,7 @@ namespace Umbraco.Core.Runtime
/// <summary>
/// Gets the profiler.
/// </summary>
protected IProfiler Profiler { get; private set; }
protected IProfiler Profiler { get; set; }
/// <summary>
/// Gets the profiling logger.
@@ -84,12 +86,6 @@ namespace Umbraco.Core.Runtime
// create and register the essential services
// ie the bare minimum required to boot
// loggers
var profiler = Profiler = GetProfiler();
if (profiler == null)
throw new InvalidOperationException($"The object returned from {nameof(GetProfiler)} cannot be null");
var profilingLogger = ProfilingLogger = new ProfilingLogger(Logger, profiler);
TypeFinder = GetTypeFinder();
if (TypeFinder == null)
@@ -105,16 +101,13 @@ namespace Umbraco.Core.Runtime
// objects.
var umbracoVersion = new UmbracoVersion();
var profilingLogger = ProfilingLogger = new ProfilingLogger(Logger, Profiler);
using (var timer = profilingLogger.TraceDuration<CoreRuntime>(
$"Booting Umbraco {umbracoVersion.SemanticVersion.ToSemanticString()}.",
"Booted.",
"Boot failed."))
{
Logger.Info<CoreRuntime>("Booting site '{HostingSiteName}', app '{HostingApplicationID}', path '{HostingPhysicalPath}', server '{MachineName}'.",
HostingEnvironment.SiteName,
HostingEnvironment.ApplicationID,
HostingEnvironment.ApplicationPhysicalPath,
NetworkHelper.MachineName);
Logger.Info<CoreRuntime>("Booting Core");
Logger.Debug<CoreRuntime>("Runtime: {Runtime}", GetType().FullName);
// application environment
@@ -137,7 +130,7 @@ namespace Umbraco.Core.Runtime
try
{
// throws if not full-trust
new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted).Demand();
_umbracoBootPermissionChecker.ThrowIfNotPermissions();
// run handlers
RuntimeOptions.DoRuntimeBoot(ProfilingLogger);
@@ -331,12 +324,6 @@ namespace Umbraco.Core.Runtime
protected virtual IEnumerable<Type> GetComposerTypes(TypeLoader typeLoader)
=> typeLoader.GetTypes<IComposer>();
/// <summary>
/// Gets a profiler.
/// </summary>
protected virtual IProfiler GetProfiler()
=> new LogProfiler(Logger);
/// <summary>
/// Gets a <see cref="ITypeFinder"/>
/// </summary>

View File

@@ -51,11 +51,10 @@ namespace Umbraco.Tests.Routing
public class TestRuntime : WebRuntime
{
public TestRuntime(UmbracoApplicationBase umbracoApplication, Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger)
: base(umbracoApplication, configs, umbracoVersion, ioHelper, Mock.Of<ILogger>())
: base(umbracoApplication, configs, umbracoVersion, ioHelper, Mock.Of<ILogger>(), Mock.Of<IProfiler>())
{
}
protected override IProfiler GetProfiler() => Mock.Of<IProfiler>();
}
protected override void Compose()

View File

@@ -20,6 +20,7 @@ using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Web;
using Umbraco.Web.Runtime;
namespace Umbraco.Tests.Runtimes
{
@@ -80,7 +81,7 @@ namespace Umbraco.Tests.Runtimes
// test application
public class TestUmbracoApplication : UmbracoApplicationBase
{
public TestUmbracoApplication() : base(new DebugDiagnosticsLogger(new MessageTemplates()), GetConfigs())
public TestUmbracoApplication() : base(new DebugDiagnosticsLogger(new MessageTemplates()), GetConfigs(), IOHelper.Default, GetProfiler())
{
}
@@ -92,23 +93,27 @@ namespace Umbraco.Tests.Runtimes
return configs;
}
private static IProfiler GetProfiler()
{
return new TestProfiler();
}
public IRuntime Runtime { get; private set; }
protected override IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger)
protected override IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler)
{
return Runtime = new TestRuntime(configs, umbracoVersion, ioHelper, logger);
return Runtime = new TestRuntime(configs, umbracoVersion, ioHelper, logger, profiler);
}
}
// test runtime
public class TestRuntime : CoreRuntime
{
public TestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger)
:base(configs, umbracoVersion, ioHelper, logger)
public TestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler)
:base(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker())
{
}
protected override IProfiler GetProfiler() => new TestProfiler();
// must override the database factory
// else BootFailedException because U cannot connect to the configured db

View File

@@ -75,7 +75,7 @@ namespace Umbraco.Tests.Runtimes
composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion);
// create the core runtime and have it compose itself
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger);coreRuntime.Compose(composition);
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker());coreRuntime.Compose(composition);
// determine actual runtime level
runtimeState.DetermineRuntimeLevel(databaseFactory, logger);
@@ -268,7 +268,7 @@ namespace Umbraco.Tests.Runtimes
composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion);
// create the core runtime and have it compose itself
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger);
var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker());
coreRuntime.Compose(composition);
// get the components

View File

@@ -0,0 +1,13 @@
using System.Web;
using Umbraco.Core.Runtime;
namespace Umbraco.Web.Runtime
{
public class AspNetUmbracoBootPermissionChecker : IUmbracoBootPermissionChecker
{
public void ThrowIfNotPermissions()
{
new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted).Demand();
}
}
}

View File

@@ -1,4 +1,6 @@
using System.Web;
using System.Web.Hosting;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
@@ -18,52 +20,72 @@ namespace Umbraco.Web.Runtime
public class WebRuntime : CoreRuntime
{
private readonly UmbracoApplicationBase _umbracoApplication;
private IProfiler _webProfiler;
private BuildManagerTypeFinder _typeFinder;
/// <summary>
/// Initializes a new instance of the <see cref="WebRuntime"/> class.
/// </summary>
/// <param name="umbracoApplication"></param>
public WebRuntime(UmbracoApplicationBase umbracoApplication, Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger):
base(configs, umbracoVersion, ioHelper, logger)
public WebRuntime(UmbracoApplicationBase umbracoApplication, Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler):
base(configs, umbracoVersion, ioHelper, logger, profiler ,new AspNetUmbracoBootPermissionChecker())
{
_umbracoApplication = umbracoApplication;
Profiler = GetWebProfiler();
}
private IProfiler GetWebProfiler()
{
// create and start asap to profile boot
if (!State.Debug)
{
// 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.Start();
return webProfiler;
}
/// <inheritdoc/>
public override IFactory Boot(IRegister register)
{
// create and start asap to profile boot
if (State.Debug)
var profilingLogger = new ProfilingLogger(Logger, Profiler);
var umbracoVersion = new UmbracoVersion();
using (var timer = profilingLogger.TraceDuration<CoreRuntime>(
$"Booting Umbraco {umbracoVersion.SemanticVersion.ToSemanticString()}.",
"Booted.",
"Boot failed."))
{
_webProfiler = new WebProfiler();
_webProfiler.Start();
}
else
{
// 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
_webProfiler = new VoidProfiler();
Logger.Info<CoreRuntime>("Booting site '{HostingSiteName}', app '{HostingApplicationID}', path '{HostingPhysicalPath}', server '{MachineName}'.",
HostingEnvironment.SiteName,
HostingEnvironment.ApplicationID,
HostingEnvironment.ApplicationPhysicalPath,
NetworkHelper.MachineName);
Logger.Debug<CoreRuntime>("Runtime: {Runtime}", GetType().FullName);
var factory = base.Boot(register);
// now (and only now) is the time to switch over to perWebRequest scopes.
// up until that point we may not have a request, and scoped services would
// fail to resolve - but we run Initialize within a factory scope - and then,
// here, we switch the factory to bind scopes to requests
factory.EnablePerWebRequestScope();
return factory;
}
var factory = base.Boot(register);
// now (and only now) is the time to switch over to perWebRequest scopes.
// up until that point we may not have a request, and scoped services would
// fail to resolve - but we run Initialize within a factory scope - and then,
// here, we switch the factory to bind scopes to requests
factory.EnablePerWebRequestScope();
return factory;
}
#region Getters
protected override ITypeFinder GetTypeFinder() => _typeFinder ?? (_typeFinder = new BuildManagerTypeFinder(IOHelper, Logger, new BuildManagerTypeFinder.TypeFinderConfig()));
protected override IProfiler GetProfiler() => _webProfiler;
protected override AppCaches GetAppCaches() => new AppCaches(
// we need to have the dep clone runtime cache provider to ensure
// all entities are cached properly (cloned in and cloned out)

View File

@@ -252,6 +252,7 @@
<Compile Include="Routing\IPublishedRouter.cs" />
<Compile Include="Routing\MediaUrlProviderCollection.cs" />
<Compile Include="Routing\MediaUrlProviderCollectionBuilder.cs" />
<Compile Include="Runtime\AspNetUmbracoBootPermissionChecker.cs" />
<Compile Include="Scheduling\TempFileCleanup.cs" />
<Compile Include="Search\BackgroundIndexRebuilder.cs" />
<Compile Include="Search\ExamineFinalComponent.cs" />

View File

@@ -13,9 +13,9 @@ namespace Umbraco.Web
/// </summary>
public class UmbracoApplication : UmbracoApplicationBase
{
protected override IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger)
protected override IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler)
{
return new WebRuntime(this, configs, umbracoVersion, ioHelper, logger);
return new WebRuntime(this, configs, umbracoVersion, ioHelper, logger, profiler);
}
/// <summary>

View File

@@ -22,26 +22,29 @@ namespace Umbraco.Web
public readonly ILogger _logger;
private readonly Configs _configs;
private readonly IIOHelper _ioHelper;
private readonly IProfiler _profiler;
protected UmbracoApplicationBase()
{
_logger = SerilogLogger.CreateWithDefaultConfiguration();
_ioHelper = IOHelper.Default;
_configs = new ConfigsFactory(_ioHelper).Create();
_profiler = new LogProfiler(_logger);
}
protected UmbracoApplicationBase(ILogger logger, Configs configs)
protected UmbracoApplicationBase(ILogger logger, Configs configs, IIOHelper ioHelper, IProfiler profiler)
{
_logger = logger;
_configs = configs;
_ioHelper = IOHelper.Default;
_ioHelper = ioHelper;
_profiler = profiler;
}
/// <summary>
/// Gets a runtime.
/// </summary>
protected abstract IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger);
protected abstract IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler);
/// <summary>
/// Gets the application register.
@@ -86,7 +89,7 @@ namespace Umbraco.Web
// create the register for the application, and boot
// the boot manager is responsible for registrations
var register = GetRegister(globalSettings);
_runtime = GetRuntime(_configs, umbracoVersion, _ioHelper, _logger);
_runtime = GetRuntime(_configs, umbracoVersion, _ioHelper, _logger, _profiler);
_runtime.Boot(register);
}