From 85afde0ea1019aa2fe6b3ae6fa157d15716b8614 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 13 Feb 2020 07:46:49 +0100 Subject: [PATCH 1/3] Replaced usages of HttpContext.Items with usages of IRequestCache --- .../Cache/DictionaryAppCache.cs | 5 +++ .../Cache/HttpRequestAppCache.cs | 15 +++++++ .../Cache/IRequestCache.cs | 4 +- src/Umbraco.Abstractions/Cache/NoAppCache.cs | 5 +++ .../XmlPublishedContent.cs | 5 --- .../Routing/UmbracoModuleTests.cs | 3 +- .../Security/BackOfficeCookieManagerTests.cs | 5 +-- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 1 + .../BatchedDatabaseServerMessenger.cs | 36 +++++----------- src/Umbraco.Web/HttpContextExtensions.cs | 14 ------- .../HttpContextUmbracoContextAccessor.cs | 18 ++++---- src/Umbraco.Web/HybridAccessorBase.cs | 26 +++++++----- .../HybridEventMessagesAccessor.cs | 7 ++-- .../HybridUmbracoContextAccessor.cs | 8 ++-- .../HttpContextVariationContextAccessor.cs | 15 +++---- .../HybridVariationContextAccessor.cs | 9 ++-- .../Security/AppBuilderExtensions.cs | 41 +++++++++++-------- .../Security/AuthenticationExtensions.cs | 12 ------ .../Security/BackOfficeCookieManager.cs | 13 +++--- ...ForceRenewalCookieAuthenticationHandler.cs | 8 ++-- ...ceRenewalCookieAuthenticationMiddleware.cs | 8 +++- .../UmbracoBackOfficeCookieAuthOptions.cs | 6 ++- src/Umbraco.Web/UmbracoDefaultOwinStartup.cs | 8 ++-- src/Umbraco.Web/UmbracoInjectedModule.cs | 20 +++++---- 24 files changed, 152 insertions(+), 140 deletions(-) diff --git a/src/Umbraco.Abstractions/Cache/DictionaryAppCache.cs b/src/Umbraco.Abstractions/Cache/DictionaryAppCache.cs index fd360b303d..d372916240 100644 --- a/src/Umbraco.Abstractions/Cache/DictionaryAppCache.cs +++ b/src/Umbraco.Abstractions/Cache/DictionaryAppCache.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Text.RegularExpressions; @@ -101,5 +102,9 @@ namespace Umbraco.Core.Cache var compiled = new Regex(regex, RegexOptions.Compiled); _items.RemoveAll(kvp => compiled.IsMatch(kvp.Key)); } + + public IEnumerator> GetEnumerator() => _items.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } } diff --git a/src/Umbraco.Abstractions/Cache/HttpRequestAppCache.cs b/src/Umbraco.Abstractions/Cache/HttpRequestAppCache.cs index 87d87ad1c9..e698d93ebe 100644 --- a/src/Umbraco.Abstractions/Cache/HttpRequestAppCache.cs +++ b/src/Umbraco.Abstractions/Cache/HttpRequestAppCache.cs @@ -171,5 +171,20 @@ namespace Umbraco.Core.Cache } #endregion + + public IEnumerator> GetEnumerator() + { + if (!TryGetContextItems(out var items)) + { + yield break; + } + + foreach (DictionaryEntry item in items) + { + yield return new KeyValuePair(item.Key.ToString(), item.Value); + } + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } } diff --git a/src/Umbraco.Abstractions/Cache/IRequestCache.cs b/src/Umbraco.Abstractions/Cache/IRequestCache.cs index 5ed32b5ba0..7ed7f8251c 100644 --- a/src/Umbraco.Abstractions/Cache/IRequestCache.cs +++ b/src/Umbraco.Abstractions/Cache/IRequestCache.cs @@ -1,6 +1,8 @@ +using System.Collections.Generic; + namespace Umbraco.Core.Cache { - public interface IRequestCache : IAppCache + public interface IRequestCache : IAppCache, IEnumerable> { bool Set(string key, object value); bool Remove(string key); diff --git a/src/Umbraco.Abstractions/Cache/NoAppCache.cs b/src/Umbraco.Abstractions/Cache/NoAppCache.cs index 5ca8f47059..60bc6fb8b8 100644 --- a/src/Umbraco.Abstractions/Cache/NoAppCache.cs +++ b/src/Umbraco.Abstractions/Cache/NoAppCache.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; @@ -84,5 +85,9 @@ namespace Umbraco.Core.Cache /// public virtual void ClearByRegex(string regex) { } + + public IEnumerator> GetEnumerator() => new Dictionary().GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } } diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedContent.cs index 4d6f57f490..b1ee6a7c4d 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedContent.cs @@ -439,11 +439,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache return (IPublishedContent) appCache.Get(key, () => (new XmlPublishedContent(node, isPreviewing, appCache, contentTypeCache, variationContextAccessor)).CreateModel(Current.PublishedModelFactory)); } - public static void ClearRequest() - { - Current.AppCaches.RequestCache.ClearByKey(CacheKeyPrefix); - } - private const string CacheKeyPrefix = "CONTENTCACHE_XMLPUBLISHEDCONTENT_"; } } diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index d4c242a762..c601c48148 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -42,7 +42,8 @@ namespace Umbraco.Tests.Routing logger, null, // FIXME: PublishedRouter complexities... Mock.Of(), - new RoutableDocumentFilter(globalSettings, IOHelper) + new RoutableDocumentFilter(globalSettings, IOHelper), + AppCaches.RequestCache ); runtime.Level = RuntimeLevel.Run; diff --git a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs index 7ff0776ba8..b16c739553 100644 --- a/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs +++ b/src/Umbraco.Tests/Security/BackOfficeCookieManagerTests.cs @@ -8,7 +8,6 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Web.Composing; -using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; @@ -39,7 +38,7 @@ namespace Umbraco.Tests.Security var runtime = Mock.Of(x => x.Level == RuntimeLevel.Install); var mgr = new BackOfficeCookieManager( - Mock.Of(accessor => accessor.UmbracoContext == umbracoContext), runtime, TestObjects.GetGlobalSettings(), TestHelper.IOHelper); + Mock.Of(accessor => accessor.UmbracoContext == umbracoContext), runtime, TestObjects.GetGlobalSettings(), IOHelper, AppCaches.RequestCache); var result = mgr.ShouldAuthenticateRequest(Mock.Of(), new Uri("http://localhost/umbraco")); @@ -58,7 +57,7 @@ namespace Umbraco.Tests.Security new TestVariationContextAccessor(), IOHelper); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); - var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx), runtime, TestObjects.GetGlobalSettings(), TestHelper.IOHelper); + var mgr = new BackOfficeCookieManager(Mock.Of(accessor => accessor.UmbracoContext == umbCtx), runtime, TestObjects.GetGlobalSettings(), IOHelper, AppCaches.RequestCache); var request = new Mock(); request.Setup(owinRequest => owinRequest.Uri).Returns(new Uri("http://localhost/umbraco")); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index ee922cdfcb..6f07b1ecd2 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -29,6 +29,7 @@ namespace Umbraco.Tests.TestHelpers protected override void Compose() { base.Compose(); + base.Compose(); Composition.RegisterUnique(); Composition.RegisterUnique(); diff --git a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs index 8a6862b018..a893fa6b49 100644 --- a/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Web/BatchedDatabaseServerMessenger.cs @@ -28,22 +28,14 @@ namespace Umbraco.Web public class BatchedDatabaseServerMessenger : DatabaseServerMessenger { private readonly IUmbracoDatabaseFactory _databaseFactory; - private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IRequestCache _requestCache; public BatchedDatabaseServerMessenger( - IRuntimeState runtime, - IUmbracoDatabaseFactory databaseFactory, - IScopeProvider scopeProvider, - ISqlContext sqlContext, - IProfilingLogger proflog, - DatabaseServerMessengerOptions options, - IHostingEnvironment hostingEnvironment, - CacheRefresherCollection cacheRefreshers, - IHttpContextAccessor httpContextAccessor) + IRuntimeState runtime, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, DatabaseServerMessengerOptions options, IHostingEnvironment hostingEnvironment, CacheRefresherCollection cacheRefreshers, IRequestCache requestCache) : base(runtime, scopeProvider, sqlContext, proflog, true, options, hostingEnvironment, cacheRefreshers) { _databaseFactory = databaseFactory; - _httpContextAccessor = httpContextAccessor; + _requestCache = requestCache; } // invoked by DatabaseServerRegistrarAndMessengerComponent @@ -112,24 +104,18 @@ namespace Umbraco.Web protected ICollection GetBatch(bool create) { - // try get the http context from the UmbracoContext, we do this because in the case we are launching an async - // thread and we know that the cache refreshers will execute, we will ensure the UmbracoContext and therefore we - // can get the http context from it - var httpContext = (_httpContextAccessor.HttpContext) - // if this is null, it could be that an async thread is calling this method that we weren't aware of and the UmbracoContext - // wasn't ensured at the beginning of the thread. We can try to see if the HttpContext.Current is available which might be - // the case if the asp.net synchronization context has kicked in - ?? (HttpContext.Current == null ? null : new HttpContextWrapper(HttpContext.Current)); - - // if no context was found, return null - we cannot not batch - if (httpContext == null) return null; - var key = typeof (BatchedDatabaseServerMessenger).Name; + if (!_requestCache.IsAvailable) return null; + // no thread-safety here because it'll run in only 1 thread (request) at a time - var batch = (ICollection)httpContext.Items[key]; + var batch = (ICollection)_requestCache.Get(key); if (batch == null && create) - httpContext.Items[key] = batch = new List(); + { + batch = new List(); + _requestCache.Set(key, batch); + } + return batch; } diff --git a/src/Umbraco.Web/HttpContextExtensions.cs b/src/Umbraco.Web/HttpContextExtensions.cs index 22eb4d1917..bb080c5618 100644 --- a/src/Umbraco.Web/HttpContextExtensions.cs +++ b/src/Umbraco.Web/HttpContextExtensions.cs @@ -4,20 +4,6 @@ namespace Umbraco.Core { public static class HttpContextExtensions { - public static T GetContextItem(this HttpContextBase httpContext, string key) - { - if (httpContext == null) return default(T); - if (httpContext.Items[key] == null) return default(T); - var val = httpContext.Items[key].TryConvertTo(); - if (val) return val.Result; - return default(T); - } - - public static T GetContextItem(this HttpContext httpContext, string key) - { - return new HttpContextWrapper(httpContext).GetContextItem(key); - } - public static string GetCurrentRequestIpAddress(this HttpContextBase httpContext) { if (httpContext == null) diff --git a/src/Umbraco.Web/HttpContextUmbracoContextAccessor.cs b/src/Umbraco.Web/HttpContextUmbracoContextAccessor.cs index a6f89ec154..5a522b02c7 100644 --- a/src/Umbraco.Web/HttpContextUmbracoContextAccessor.cs +++ b/src/Umbraco.Web/HttpContextUmbracoContextAccessor.cs @@ -1,31 +1,29 @@ using System; +using Umbraco.Core.Cache; namespace Umbraco.Web { internal class HttpContextUmbracoContextAccessor : IUmbracoContextAccessor { + private readonly IRequestCache _requestCache; private const string HttpContextItemKey = "Umbraco.Web.UmbracoContext"; - private readonly IHttpContextAccessor _httpContextAccessor; - public HttpContextUmbracoContextAccessor(IHttpContextAccessor httpContextAccessor) + public HttpContextUmbracoContextAccessor(IRequestCache requestCache) { - _httpContextAccessor = httpContextAccessor; + _requestCache = requestCache; } public IUmbracoContext UmbracoContext { get { - var httpContext = _httpContextAccessor.HttpContext; - if (httpContext == null) throw new Exception("oops:httpContext"); - return (IUmbracoContext) httpContext.Items[HttpContextItemKey]; + if (!_requestCache.IsAvailable) throw new InvalidOperationException("No request cache available"); + return (IUmbracoContext) _requestCache.Get(HttpContextItemKey); } - set { - var httpContext = _httpContextAccessor.HttpContext; - if (httpContext == null) throw new Exception("oops:httpContext"); - httpContext.Items[HttpContextItemKey] = value; + if (!_requestCache.IsAvailable) throw new InvalidOperationException("No request cache available"); + _requestCache.Set(HttpContextItemKey, value); } } } diff --git a/src/Umbraco.Web/HybridAccessorBase.cs b/src/Umbraco.Web/HybridAccessorBase.cs index ec18b6f3d4..e8c8c9de0c 100644 --- a/src/Umbraco.Web/HybridAccessorBase.cs +++ b/src/Umbraco.Web/HybridAccessorBase.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.Remoting.Messaging; using Umbraco.Core; +using Umbraco.Core.Cache; namespace Umbraco.Web { @@ -16,12 +17,14 @@ namespace Umbraco.Web public abstract class HybridAccessorBase where T : class { + private readonly IRequestCache _requestCache; + // ReSharper disable StaticMemberInGenericType private static readonly object Locker = new object(); private static bool _registered; // ReSharper restore StaticMemberInGenericType - private readonly IHttpContextAccessor _httpContextAccessor; + // private readonly IHttpContextAccessor _httpContextAccessor; protected abstract string ItemKey { get; } @@ -50,9 +53,9 @@ namespace Umbraco.Web } } - protected HybridAccessorBase(IHttpContextAccessor httpContextAccessor) + protected HybridAccessorBase(IRequestCache requestCache) { - _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); + _requestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache)); lock (Locker) { @@ -81,20 +84,23 @@ namespace Umbraco.Web { get { - var httpContext = _httpContextAccessor.HttpContext; - if (httpContext == null) return NonContextValue; - return (T) httpContext.Items[ItemKey]; + if (!_requestCache.IsAvailable) + { + return NonContextValue; + } + return (T) _requestCache.Get(ItemKey); } set { - var httpContext = _httpContextAccessor.HttpContext; - if (httpContext == null) + if (!_requestCache.IsAvailable) + { NonContextValue = value; + } else if (value == null) - httpContext.Items.Remove(ItemKey); + _requestCache.Remove(ItemKey); else - httpContext.Items[ItemKey] = value; + _requestCache.Set(ItemKey, value); } } } diff --git a/src/Umbraco.Web/HybridEventMessagesAccessor.cs b/src/Umbraco.Web/HybridEventMessagesAccessor.cs index fddde403d8..b2700eb137 100644 --- a/src/Umbraco.Web/HybridEventMessagesAccessor.cs +++ b/src/Umbraco.Web/HybridEventMessagesAccessor.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Events; +using Umbraco.Core.Cache; +using Umbraco.Core.Events; namespace Umbraco.Web { @@ -6,8 +7,8 @@ namespace Umbraco.Web { protected override string ItemKey => "Umbraco.Core.Events.HybridEventMessagesAccessor"; - public HybridEventMessagesAccessor(IHttpContextAccessor httpContextAccessor) - : base(httpContextAccessor) + public HybridEventMessagesAccessor(IRequestCache requestCache) + : base(requestCache) { } public EventMessages EventMessages diff --git a/src/Umbraco.Web/HybridUmbracoContextAccessor.cs b/src/Umbraco.Web/HybridUmbracoContextAccessor.cs index 3c22826f30..bb8e2d6993 100644 --- a/src/Umbraco.Web/HybridUmbracoContextAccessor.cs +++ b/src/Umbraco.Web/HybridUmbracoContextAccessor.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Web +using Umbraco.Core.Cache; + +namespace Umbraco.Web { /// /// Implements a hybrid . @@ -8,8 +10,8 @@ /// /// Initializes a new instance of the class. /// - public HybridUmbracoContextAccessor(IHttpContextAccessor httpContextAccessor) - : base(httpContextAccessor) + public HybridUmbracoContextAccessor(IRequestCache requestCache) + : base(requestCache) { } /// diff --git a/src/Umbraco.Web/Models/PublishedContent/HttpContextVariationContextAccessor.cs b/src/Umbraco.Web/Models/PublishedContent/HttpContextVariationContextAccessor.cs index 0007b346c5..41b81a4a6e 100644 --- a/src/Umbraco.Web/Models/PublishedContent/HttpContextVariationContextAccessor.cs +++ b/src/Umbraco.Web/Models/PublishedContent/HttpContextVariationContextAccessor.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Cache; +using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Web.Models.PublishedContent { @@ -7,22 +8,22 @@ namespace Umbraco.Web.Models.PublishedContent /// public class HttpContextVariationContextAccessor : IVariationContextAccessor { - public const string ContextKey = "Umbraco.Web.Models.PublishedContent.DefaultVariationContextAccessor"; - public readonly IHttpContextAccessor HttpContextAccessor; + private readonly IRequestCache _requestCache; + private const string _contextKey = "Umbraco.Web.Models.PublishedContent.DefaultVariationContextAccessor"; /// /// Initializes a new instance of the class. /// - public HttpContextVariationContextAccessor(IHttpContextAccessor httpContextAccessor) + public HttpContextVariationContextAccessor(IRequestCache requestCache) { - HttpContextAccessor = httpContextAccessor; + _requestCache = requestCache; } /// public VariationContext VariationContext { - get => (VariationContext) HttpContextAccessor.HttpContext?.Items[ContextKey]; - set => HttpContextAccessor.HttpContext.Items[ContextKey] = value; + get => (VariationContext) _requestCache.Get(_contextKey); + set => _requestCache.Set(_contextKey, value); } } } diff --git a/src/Umbraco.Web/Models/PublishedContent/HybridVariationContextAccessor.cs b/src/Umbraco.Web/Models/PublishedContent/HybridVariationContextAccessor.cs index cb002e11b0..897ff17db4 100644 --- a/src/Umbraco.Web/Models/PublishedContent/HybridVariationContextAccessor.cs +++ b/src/Umbraco.Web/Models/PublishedContent/HybridVariationContextAccessor.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Cache; +using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Web.Models.PublishedContent { @@ -7,8 +8,8 @@ namespace Umbraco.Web.Models.PublishedContent /// internal class HybridVariationContextAccessor : HybridAccessorBase, IVariationContextAccessor { - public HybridVariationContextAccessor(IHttpContextAccessor httpContextAccessor) - : base(httpContextAccessor) + public HybridVariationContextAccessor(IRequestCache requestCache) + : base(requestCache) { } /// @@ -23,4 +24,4 @@ namespace Umbraco.Web.Models.PublishedContent set => Value = value; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Security/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/AppBuilderExtensions.cs index 27c1b4fdc5..041b56f1c8 100644 --- a/src/Umbraco.Web/Security/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/AppBuilderExtensions.cs @@ -11,6 +11,7 @@ using Microsoft.Owin.Security.DataHandler; using Microsoft.Owin.Security.DataProtection; using Owin; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -153,9 +154,10 @@ namespace Umbraco.Web.Security IGlobalSettings globalSettings, ISecuritySection securitySection, IIOHelper ioHelper, + IRequestCache requestCache, IUmbracoSettingsSection umbracoSettingsSection) { - return app.UseUmbracoBackOfficeCookieAuthentication(umbracoContextAccessor, runtimeState, userService, globalSettings, securitySection, ioHelper, PipelineStage.Authenticate, umbracoSettingsSection); + return app.UseUmbracoBackOfficeCookieAuthentication(umbracoContextAccessor, runtimeState, userService, globalSettings, securitySection, ioHelper, requestCache, PipelineStage.Authenticate, umbracoSettingsSection); } /// @@ -179,11 +181,12 @@ namespace Umbraco.Web.Security IGlobalSettings globalSettings, ISecuritySection securitySection, IIOHelper ioHelper, + IRequestCache requestCache, PipelineStage stage, IUmbracoSettingsSection umbracoSettingsSection) { //Create the default options and provider - var authOptions = app.CreateUmbracoCookieAuthOptions(umbracoContextAccessor, globalSettings, runtimeState, securitySection, ioHelper); + var authOptions = app.CreateUmbracoCookieAuthOptions(umbracoContextAccessor, globalSettings, runtimeState, securitySection, ioHelper, requestCache); authOptions.Provider = new BackOfficeCookieAuthenticationProvider(userService, runtimeState, globalSettings, ioHelper, umbracoSettingsSection) { @@ -198,7 +201,7 @@ namespace Umbraco.Web.Security }; - return app.UseUmbracoBackOfficeCookieAuthentication(umbracoContextAccessor, runtimeState, globalSettings, securitySection, ioHelper, authOptions, stage); + return app.UseUmbracoBackOfficeCookieAuthentication(umbracoContextAccessor, runtimeState, globalSettings, securitySection, ioHelper, requestCache, authOptions, stage); } /// @@ -215,7 +218,8 @@ namespace Umbraco.Web.Security /// Configurable pipeline stage /// /// - public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, IGlobalSettings globalSettings, ISecuritySection securitySection, IIOHelper ioHelper, CookieAuthenticationOptions cookieOptions, PipelineStage stage) + public static IAppBuilder UseUmbracoBackOfficeCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, IGlobalSettings globalSettings, + ISecuritySection securitySection, IIOHelper ioHelper, IRequestCache requestCache, CookieAuthenticationOptions cookieOptions, PipelineStage stage) { if (app == null) throw new ArgumentNullException(nameof(app)); if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); @@ -225,7 +229,7 @@ namespace Umbraco.Web.Security if (cookieOptions.Provider is BackOfficeCookieAuthenticationProvider == false) throw new ArgumentException($"cookieOptions.Provider must be of type {typeof(BackOfficeCookieAuthenticationProvider)}.", nameof(cookieOptions)); - app.UseUmbracoBackOfficeCookieAuthenticationInternal(cookieOptions, runtimeState, stage); + app.UseUmbracoBackOfficeCookieAuthenticationInternal(cookieOptions, runtimeState, requestCache, stage); //don't apply if app is not ready if (runtimeState.Level != RuntimeLevel.Upgrade && runtimeState.Level != RuntimeLevel.Run) return app; @@ -233,7 +237,7 @@ namespace Umbraco.Web.Security var cookieAuthOptions = app.CreateUmbracoCookieAuthOptions( umbracoContextAccessor, globalSettings, runtimeState, securitySection, //This defines the explicit path read cookies from for this middleware - ioHelper, new[] {$"{globalSettings.Path}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds"}); + ioHelper, requestCache, new[] {$"{globalSettings.Path}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds"}); cookieAuthOptions.Provider = cookieOptions.Provider; //This is a custom middleware, we need to return the user's remaining logged in seconds @@ -279,7 +283,7 @@ namespace Umbraco.Web.Security }); } - private static void UseUmbracoBackOfficeCookieAuthenticationInternal(this IAppBuilder app, CookieAuthenticationOptions options, IRuntimeState runtimeState, PipelineStage stage) + private static void UseUmbracoBackOfficeCookieAuthenticationInternal(this IAppBuilder app, CookieAuthenticationOptions options, IRuntimeState runtimeState, IRequestCache requestCache, PipelineStage stage) { if (app == null) throw new ArgumentNullException(nameof(app)); if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); @@ -290,7 +294,7 @@ namespace Umbraco.Web.Security if (runtimeState.Level == RuntimeLevel.Upgrade || runtimeState.Level == RuntimeLevel.Run) { //Then our custom middlewares - app.Use(typeof(ForceRenewalCookieAuthenticationMiddleware), app, options, Current.UmbracoContextAccessor); + app.Use(typeof(ForceRenewalCookieAuthenticationMiddleware), app, options, Current.UmbracoContextAccessor, requestCache); app.Use(typeof(FixWindowsAuthMiddlware)); } @@ -311,9 +315,9 @@ namespace Umbraco.Web.Security /// /// By default this will be configured to execute on PipelineStage.Authenticate /// - public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState,IGlobalSettings globalSettings, IIOHelper ioHelper) + public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState,IGlobalSettings globalSettings, IIOHelper ioHelper, IRequestCache requestCache) { - return app.UseUmbracoBackOfficeExternalCookieAuthentication(umbracoContextAccessor, runtimeState, globalSettings, ioHelper, PipelineStage.Authenticate); + return app.UseUmbracoBackOfficeExternalCookieAuthentication(umbracoContextAccessor, runtimeState, globalSettings, ioHelper, requestCache, PipelineStage.Authenticate); } /// @@ -329,7 +333,7 @@ namespace Umbraco.Web.Security /// public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, - IGlobalSettings globalSettings, IIOHelper ioHelper, PipelineStage stage) + IGlobalSettings globalSettings, IIOHelper ioHelper, IRequestCache requestCache, PipelineStage stage) { if (app == null) throw new ArgumentNullException(nameof(app)); if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); @@ -342,7 +346,7 @@ namespace Umbraco.Web.Security CookieName = Constants.Security.BackOfficeExternalCookieName, ExpireTimeSpan = TimeSpan.FromMinutes(5), //Custom cookie manager so we can filter requests - CookieManager = new BackOfficeCookieManager(umbracoContextAccessor, runtimeState, globalSettings, ioHelper), + CookieManager = new BackOfficeCookieManager(umbracoContextAccessor, runtimeState, globalSettings, ioHelper, requestCache), CookiePath = "/", CookieSecure = globalSettings.UseHttps ? CookieSecureOption.Always : CookieSecureOption.SameAsRequest, CookieHttpOnly = true, @@ -369,9 +373,9 @@ namespace Umbraco.Web.Security /// /// By default this will be configured to execute on PipelineStage.PostAuthenticate /// - public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, IGlobalSettings globalSettings, ISecuritySection securitySettings, IIOHelper ioHelper) + public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, IGlobalSettings globalSettings, ISecuritySection securitySettings, IIOHelper ioHelper, IRequestCache requestCache) { - return app.UseUmbracoPreviewAuthentication(umbracoContextAccessor, runtimeState, globalSettings, securitySettings, ioHelper, PipelineStage.PostAuthenticate); + return app.UseUmbracoPreviewAuthentication(umbracoContextAccessor, runtimeState, globalSettings, securitySettings, ioHelper, requestCache, PipelineStage.PostAuthenticate); } /// @@ -389,11 +393,11 @@ namespace Umbraco.Web.Security /// This ensures that during a preview request that the back office use is also Authenticated and that the back office Identity /// is added as a secondary identity to the current IPrincipal so it can be used to Authorize the previewed document. /// - public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, IGlobalSettings globalSettings, ISecuritySection securitySettings, IIOHelper ioHelper, PipelineStage stage) + public static IAppBuilder UseUmbracoPreviewAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, IGlobalSettings globalSettings, ISecuritySection securitySettings, IIOHelper ioHelper, IRequestCache requestCache, PipelineStage stage) { if (runtimeState.Level != RuntimeLevel.Run) return app; - var authOptions = app.CreateUmbracoCookieAuthOptions(umbracoContextAccessor, globalSettings, runtimeState, securitySettings, ioHelper); + var authOptions = app.CreateUmbracoCookieAuthOptions(umbracoContextAccessor, globalSettings, runtimeState, securitySettings, ioHelper, requestCache); app.Use(typeof(PreviewAuthenticationMiddleware), authOptions, Current.Configs.Global(), ioHelper); // This middleware must execute at least on PostAuthentication, by default it is on Authorize @@ -424,7 +428,7 @@ namespace Umbraco.Web.Security /// public static UmbracoBackOfficeCookieAuthOptions CreateUmbracoCookieAuthOptions(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, - IGlobalSettings globalSettings, IRuntimeState runtimeState, ISecuritySection securitySettings, IIOHelper ioHelper, string[] explicitPaths = null) + IGlobalSettings globalSettings, IRuntimeState runtimeState, ISecuritySection securitySettings, IIOHelper ioHelper, IRequestCache requestCache, string[] explicitPaths = null) { //this is how aspnet wires up the default AuthenticationTicket protector so we'll use the same code var ticketDataFormat = new TicketDataFormat( @@ -439,7 +443,8 @@ namespace Umbraco.Web.Security globalSettings, runtimeState, ticketDataFormat, - ioHelper); + ioHelper, + requestCache); return authOptions; } diff --git a/src/Umbraco.Web/Security/AuthenticationExtensions.cs b/src/Umbraco.Web/Security/AuthenticationExtensions.cs index 1b89002188..1fd8e45c55 100644 --- a/src/Umbraco.Web/Security/AuthenticationExtensions.cs +++ b/src/Umbraco.Web/Security/AuthenticationExtensions.cs @@ -169,18 +169,6 @@ namespace Umbraco.Web.Security return true; } - /// - /// This will force ticket renewal in the OWIN pipeline - /// - /// - /// - internal static bool RenewUmbracoAuthTicket(this HttpContext http) - { - if (http == null) throw new ArgumentNullException("http"); - http.Items[Constants.Security.ForceReAuthFlag] = true; - return true; - } - /// /// returns the number of seconds the user has until their auth session times out /// diff --git a/src/Umbraco.Web/Security/BackOfficeCookieManager.cs b/src/Umbraco.Web/Security/BackOfficeCookieManager.cs index 5d70b9b09c..b7b39ea4bf 100644 --- a/src/Umbraco.Web/Security/BackOfficeCookieManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeCookieManager.cs @@ -5,6 +5,7 @@ using System.Web; using Microsoft.Owin; using Microsoft.Owin.Infrastructure; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Security; @@ -24,19 +25,21 @@ namespace Umbraco.Web.Security private readonly IRuntimeState _runtime; private readonly IGlobalSettings _globalSettings; private readonly IIOHelper _ioHelper; + private readonly IRequestCache _requestCache; private readonly string[] _explicitPaths; private readonly string _getRemainingSecondsPath; - public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime, IGlobalSettings globalSettings, IIOHelper ioHelper) - : this(umbracoContextAccessor, runtime, globalSettings, ioHelper,null) + public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime, IGlobalSettings globalSettings, IIOHelper ioHelper, IRequestCache requestCache) + : this(umbracoContextAccessor, runtime, globalSettings, ioHelper,requestCache, null) { } - public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime, IGlobalSettings globalSettings, IIOHelper ioHelper, IEnumerable explicitPaths) + public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime, IGlobalSettings globalSettings, IIOHelper ioHelper, IRequestCache requestCache, IEnumerable explicitPaths) { _umbracoContextAccessor = umbracoContextAccessor; _runtime = runtime; _globalSettings = globalSettings; _ioHelper = ioHelper; + _requestCache = requestCache; _explicitPaths = explicitPaths?.ToArray(); _getRemainingSecondsPath = $"{globalSettings.Path}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds"; } @@ -89,8 +92,6 @@ namespace Umbraco.Web.Security return false; var request = owinContext.Request; - var httpContext = owinContext.TryGetHttpContext(); - //check the explicit paths if (_explicitPaths != null) { @@ -102,7 +103,7 @@ namespace Umbraco.Web.Security if (//check the explicit flag (checkForceAuthTokens && owinContext.Get(Constants.Security.ForceReAuthFlag) != null) - || (checkForceAuthTokens && httpContext.Success && httpContext.Result.Items[Constants.Security.ForceReAuthFlag] != null) + || (checkForceAuthTokens && _requestCache.IsAvailable && _requestCache.Get(Constants.Security.ForceReAuthFlag) != null) //check back office || request.Uri.IsBackOfficeRequest(HttpRuntime.AppDomainAppVirtualPath, _globalSettings, _ioHelper) //check installer diff --git a/src/Umbraco.Web/Security/ForceRenewalCookieAuthenticationHandler.cs b/src/Umbraco.Web/Security/ForceRenewalCookieAuthenticationHandler.cs index 896a0ca63e..b3092b90c9 100644 --- a/src/Umbraco.Web/Security/ForceRenewalCookieAuthenticationHandler.cs +++ b/src/Umbraco.Web/Security/ForceRenewalCookieAuthenticationHandler.cs @@ -3,6 +3,7 @@ using Microsoft.Owin.Security; using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.Infrastructure; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Security; namespace Umbraco.Web.Security @@ -13,10 +14,12 @@ namespace Umbraco.Web.Security internal class ForceRenewalCookieAuthenticationHandler : AuthenticationHandler { private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IRequestCache _requestCache; - public ForceRenewalCookieAuthenticationHandler(IUmbracoContextAccessor umbracoContextAccessor) + public ForceRenewalCookieAuthenticationHandler(IUmbracoContextAccessor umbracoContextAccessor, IRequestCache requestCache) { _umbracoContextAccessor = umbracoContextAccessor; + _requestCache = requestCache; } /// @@ -68,9 +71,8 @@ namespace Umbraco.Web.Security //This is auth'd normally, so OWIN will naturally take care of the cookie renewal if (normalAuthUrl) return Task.FromResult(0); - var httpCtx = Context.TryGetHttpContext(); //check for the special flag in either the owin or http context - var shouldRenew = Context.Get(Constants.Security.ForceReAuthFlag) != null || (httpCtx.Success && httpCtx.Result.Items[Constants.Security.ForceReAuthFlag] != null); + var shouldRenew = Context.Get(Constants.Security.ForceReAuthFlag) != null || (_requestCache.IsAvailable && _requestCache.Get(Constants.Security.ForceReAuthFlag) != null); if (shouldRenew) { diff --git a/src/Umbraco.Web/Security/ForceRenewalCookieAuthenticationMiddleware.cs b/src/Umbraco.Web/Security/ForceRenewalCookieAuthenticationMiddleware.cs index 1b72412f1c..b8f8127544 100644 --- a/src/Umbraco.Web/Security/ForceRenewalCookieAuthenticationMiddleware.cs +++ b/src/Umbraco.Web/Security/ForceRenewalCookieAuthenticationMiddleware.cs @@ -2,6 +2,7 @@ using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.Infrastructure; using Owin; +using Umbraco.Core.Cache; namespace Umbraco.Web.Security { @@ -11,19 +12,22 @@ namespace Umbraco.Web.Security internal class ForceRenewalCookieAuthenticationMiddleware : CookieAuthenticationMiddleware { private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IRequestCache _requestCache; public ForceRenewalCookieAuthenticationMiddleware( OwinMiddleware next, IAppBuilder app, UmbracoBackOfficeCookieAuthOptions options, - IUmbracoContextAccessor umbracoContextAccessor) : base(next, app, options) + IUmbracoContextAccessor umbracoContextAccessor, + IRequestCache requestCache) : base(next, app, options) { _umbracoContextAccessor = umbracoContextAccessor; + _requestCache = requestCache; } protected override AuthenticationHandler CreateHandler() { - return new ForceRenewalCookieAuthenticationHandler(_umbracoContextAccessor); + return new ForceRenewalCookieAuthenticationHandler(_umbracoContextAccessor, _requestCache); } } } diff --git a/src/Umbraco.Web/Security/UmbracoBackOfficeCookieAuthOptions.cs b/src/Umbraco.Web/Security/UmbracoBackOfficeCookieAuthOptions.cs index 1ad2535c2f..d8c4ca791d 100644 --- a/src/Umbraco.Web/Security/UmbracoBackOfficeCookieAuthOptions.cs +++ b/src/Umbraco.Web/Security/UmbracoBackOfficeCookieAuthOptions.cs @@ -3,6 +3,7 @@ using Microsoft.Owin; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Cookies; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -23,7 +24,8 @@ namespace Umbraco.Web.Security IGlobalSettings globalSettings, IRuntimeState runtimeState, ISecureDataFormat secureDataFormat, - IIOHelper ioHelper) + IIOHelper ioHelper, + IRequestCache requestCache) { var secureDataFormat1 = secureDataFormat ?? throw new ArgumentNullException(nameof(secureDataFormat)); LoginTimeoutMinutes = globalSettings.TimeOutInMinutes; @@ -40,7 +42,7 @@ namespace Umbraco.Web.Security TicketDataFormat = new UmbracoSecureDataFormat(LoginTimeoutMinutes, secureDataFormat1); //Custom cookie manager so we can filter requests - CookieManager = new BackOfficeCookieManager(umbracoContextAccessor, runtimeState, globalSettings, ioHelper, explicitPaths); + CookieManager = new BackOfficeCookieManager(umbracoContextAccessor, runtimeState, globalSettings, ioHelper, requestCache, explicitPaths); } /// diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs index 6b6bdeb0aa..a30f77b217 100644 --- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs +++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs @@ -2,6 +2,7 @@ using Microsoft.Owin; using Owin; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -34,6 +35,7 @@ namespace Umbraco.Web protected UmbracoMapper Mapper => Current.Mapper; protected IIpResolver IpResolver => Current.IpResolver; protected IIOHelper IOHelper => Current.IOHelper; + protected IRequestCache RequestCache => Current.AppCaches.RequestCache; /// /// Main startup method @@ -102,9 +104,9 @@ namespace Umbraco.Web // Ensure owin is configured for Umbraco back office authentication. // Front-end OWIN cookie configuration must be declared after this code. app - .UseUmbracoBackOfficeCookieAuthentication(UmbracoContextAccessor, RuntimeState, Services.UserService, GlobalSettings, UmbracoSettings.Security, IOHelper, PipelineStage.Authenticate, UmbracoSettings) - .UseUmbracoBackOfficeExternalCookieAuthentication(UmbracoContextAccessor, RuntimeState, GlobalSettings, IOHelper, PipelineStage.Authenticate) - .UseUmbracoPreviewAuthentication(UmbracoContextAccessor, RuntimeState, GlobalSettings, UmbracoSettings.Security, IOHelper, PipelineStage.Authorize); + .UseUmbracoBackOfficeCookieAuthentication(UmbracoContextAccessor, RuntimeState, Services.UserService, GlobalSettings, UmbracoSettings.Security, IOHelper, RequestCache, PipelineStage.Authenticate, UmbracoSettings) + .UseUmbracoBackOfficeExternalCookieAuthentication(UmbracoContextAccessor, RuntimeState, GlobalSettings, IOHelper, RequestCache, PipelineStage.Authenticate) + .UseUmbracoPreviewAuthentication(UmbracoContextAccessor, RuntimeState, GlobalSettings, UmbracoSettings.Security, IOHelper, RequestCache, PipelineStage.Authorize); } public static event EventHandler MiddlewareConfigured; diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs index 72579188ed..b8fb6d7449 100644 --- a/src/Umbraco.Web/UmbracoInjectedModule.cs +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Web; using System.Web.Routing; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -38,6 +39,7 @@ namespace Umbraco.Web private readonly IPublishedRouter _publishedRouter; private readonly IUmbracoContextFactory _umbracoContextFactory; private readonly RoutableDocumentFilter _routableDocumentLookup; + private readonly IRequestCache _requestCache; public UmbracoInjectedModule( IGlobalSettings globalSettings, @@ -45,7 +47,8 @@ namespace Umbraco.Web ILogger logger, IPublishedRouter publishedRouter, IUmbracoContextFactory umbracoContextFactory, - RoutableDocumentFilter routableDocumentLookup) + RoutableDocumentFilter routableDocumentLookup, + IRequestCache requestCache) { _globalSettings = globalSettings; _runtime = runtime; @@ -53,6 +56,7 @@ namespace Umbraco.Web _publishedRouter = publishedRouter; _umbracoContextFactory = umbracoContextFactory; _routableDocumentLookup = routableDocumentLookup; + _requestCache = requestCache; } #region HttpModule event handlers @@ -305,15 +309,15 @@ namespace Umbraco.Web /// Any object that is in the HttpContext.Items collection that is IDisposable will get disposed on the end of the request /// /// - private void DisposeHttpContextItems(HttpContext http) + private void DisposeRequestCacheItems(HttpContext http, IRequestCache requestCache) { // do not process if client-side request if (http.Request.Url.IsClientSideRequest()) return; //get a list of keys to dispose - var keys = new HashSet(); - foreach (DictionaryEntry i in http.Items) + var keys = new HashSet(); + foreach (var i in requestCache) { if (i.Value is IDisposeOnRequestEnd || i.Key is IDisposeOnRequestEnd) { @@ -325,7 +329,7 @@ namespace Umbraco.Web { try { - http.Items[k].DisposeIfDisposable(); + requestCache.Get(k).DisposeIfDisposable(); } catch (Exception ex) { @@ -376,7 +380,7 @@ namespace Umbraco.Web { var httpContext = ((HttpApplication) sender).Context; - LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, Current.AppCaches.RequestCache); + LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache); _logger.Verbose("Begin request [{HttpRequestId}]: {RequestUrl}", httpRequestId, httpContext.Request.Url); BeginRequest(new HttpContextWrapper(httpContext)); @@ -421,14 +425,14 @@ namespace Umbraco.Web if (Current.UmbracoContext != null && Current.UmbracoContext.IsFrontEndUmbracoRequest) { - LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, Current.AppCaches.RequestCache); + LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache); _logger.Verbose("End Request [{HttpRequestId}]: {RequestUrl} ({RequestDuration}ms)", httpRequestId, httpContext.Request.Url, DateTime.Now.Subtract(Current.UmbracoContext.ObjectCreated).TotalMilliseconds); } UmbracoModule.OnEndRequest(this, new UmbracoRequestEventArgs(Current.UmbracoContext, new HttpContextWrapper(httpContext))); - DisposeHttpContextItems(httpContext); + DisposeRequestCacheItems(httpContext, _requestCache); }; } From 215cb60b157feb29f7c85765e82ab14aed3250a1 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 13 Feb 2020 07:56:50 +0100 Subject: [PATCH 2/3] Refactored usages of HttpContext.IsDebuggerEnabled to use the IHostingEnvironment.IsDebugMode --- .../Umbraco/Views/AuthorizeUpgrade.cshtml | 2 +- .../Umbraco/Views/Default.cshtml | 2 +- src/Umbraco.Web/CacheHelperExtensions.cs | 5 ++++- .../Editors/BackOfficeController.cs | 21 ++++++++++++------- src/Umbraco.Web/Editors/BackOfficeModel.cs | 7 ++++++- .../Editors/BackOfficePreviewModel.cs | 5 +++-- .../Editors/BackOfficeServerVariables.cs | 17 ++++++++------- src/Umbraco.Web/Editors/PreviewController.cs | 11 ++++++++-- .../HtmlHelperBackOfficeExtensions.cs | 5 +++-- src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 2 +- .../Mvc/MinifyJavaScriptResultAttribute.cs | 16 +++++++++++++- src/Umbraco.Web/Mvc/UmbracoController.cs | 2 +- 12 files changed, 67 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml index e95057efe9..11033aa785 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml @@ -48,7 +48,7 @@ redirectUrl = Url.Action("AuthorizeUpgrade", "BackOffice") }); } - @Html.BareMinimumServerVariablesScript(Url, externalLoginUrl, Model.Features, Model.GlobalSettings, Model.UmbracoVersion, Model.UmbracoSettingsSection, Model.IOHelper, Model.TreeCollection) + @Html.BareMinimumServerVariablesScript(Url, externalLoginUrl, Model.Features, Model.GlobalSettings, Model.UmbracoVersion, Model.UmbracoSettingsSection, Model.IOHelper, Model.TreeCollection, Model.HttpContextAccessor, Model.HostingEnvironment)