From abb5911b245873050a8237b620060eb8349c19b6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 26 Feb 2021 16:53:53 +1100 Subject: [PATCH 01/10] WIP fixing issue with macro forms --- .../Controllers/ProxyViewDataFeature.cs | 13 ++- .../UmbracoBuilderExtensions.cs | 1 + .../Macros/MacroRenderer.cs | 27 ++--- .../Macros/PartialViewMacroEngine.cs | 101 +++++------------- .../Macros/PartialViewMacroViewComponent.cs | 14 ++- .../Templates/TemplateRenderer.cs | 21 ++-- .../Controllers/SurfaceController.cs | 2 +- .../Controllers/UmbLoginController.cs | 6 +- .../Extensions/HtmlHelperRenderExtensions.cs | 13 +-- 9 files changed, 79 insertions(+), 119 deletions(-) diff --git a/src/Umbraco.Web.Common/Controllers/ProxyViewDataFeature.cs b/src/Umbraco.Web.Common/Controllers/ProxyViewDataFeature.cs index f926ccbfaa..e44f3270fe 100644 --- a/src/Umbraco.Web.Common/Controllers/ProxyViewDataFeature.cs +++ b/src/Umbraco.Web.Common/Controllers/ProxyViewDataFeature.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.AspNetCore.Mvc.ViewFeatures; namespace Umbraco.Cms.Web.Common.Controllers { @@ -10,11 +10,20 @@ namespace Umbraco.Cms.Web.Common.Controllers /// /// Initializes a new instance of the class. /// - public ProxyViewDataFeature(ViewDataDictionary viewData) => ViewData = viewData; + public ProxyViewDataFeature(ViewDataDictionary viewData, ITempDataDictionary tempData) + { + ViewData = viewData; + TempData = tempData; + } /// /// Gets the /// public ViewDataDictionary ViewData { get; } + + /// + /// Gets the + /// + public ITempDataDictionary TempData { get; } } } diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index 9dd375c9af..9e2e79cb9b 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -255,6 +255,7 @@ namespace Umbraco.Extensions builder.Services.AddUnique(); builder.Services.AddUnique(); + builder.Services.AddUnique(); builder.Services.AddUnique(); // register the umbraco context factory diff --git a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs index f798199012..389267cd61 100644 --- a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs @@ -37,6 +37,7 @@ namespace Umbraco.Cms.Web.Common.Macros private readonly ISessionManager _sessionManager; private readonly IRequestAccessor _requestAccessor; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly PartialViewMacroEngine _partialViewMacroEngine; public MacroRenderer( IProfilingLogger profilingLogger, @@ -52,7 +53,8 @@ namespace Umbraco.Cms.Web.Common.Macros IMemberUserKeyProvider memberUserKeyProvider, ISessionManager sessionManager, IRequestAccessor requestAccessor, - IHttpContextAccessor httpContextAccessor) + IHttpContextAccessor httpContextAccessor, + PartialViewMacroEngine partialViewMacroEngine) { _profilingLogger = profilingLogger ?? throw new ArgumentNullException(nameof(profilingLogger)); _logger = logger; @@ -68,6 +70,7 @@ namespace Umbraco.Cms.Web.Common.Macros _sessionManager = sessionManager; _requestAccessor = requestAccessor; _httpContextAccessor = httpContextAccessor; + _partialViewMacroEngine = partialViewMacroEngine; } #region MacroContent cache @@ -338,38 +341,28 @@ namespace Umbraco.Cms.Web.Common.Macros private Attempt ExecuteMacroOfType(MacroModel model, IPublishedContent content) { if (model == null) + { throw new ArgumentNullException(nameof(model)); + } // ensure that we are running against a published node (ie available in XML) // that may not be the case if the macro is embedded in a RTE of an unpublished document if (content == null) + { return Attempt.Fail(new MacroContent { Text = "[macro failed (no content)]" }); + } - var textService = _textService; + ILocalizedTextService textService = _textService; return ExecuteMacroWithErrorWrapper(model, $"Executing PartialView: MacroSource=\"{model.MacroSource}\".", "Executed PartialView.", - () => ExecutePartialView(model, content), + () => _partialViewMacroEngine.Execute(model, content), () => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource })); } - #endregion - - #region Execute engines - - /// - /// Renders a PartialView Macro. - /// - /// The text output of the macro execution. - private MacroContent ExecutePartialView(MacroModel macro, IPublishedContent content) - { - var engine = new PartialViewMacroEngine(_httpContextAccessor, _hostingEnvironment); - return engine.Execute(macro, content); - } - #endregion #region Execution helpers diff --git a/src/Umbraco.Web.Common/Macros/PartialViewMacroEngine.cs b/src/Umbraco.Web.Common/Macros/PartialViewMacroEngine.cs index ef59c9f896..5b37557cd2 100644 --- a/src/Umbraco.Web.Common/Macros/PartialViewMacroEngine.cs +++ b/src/Umbraco.Web.Common/Macros/PartialViewMacroEngine.cs @@ -16,6 +16,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Macros; using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Web.Common.Controllers; using Umbraco.Extensions; using static Umbraco.Cms.Core.Constants.Web.Routing; @@ -27,47 +28,19 @@ namespace Umbraco.Cms.Web.Common.Macros public class PartialViewMacroEngine { private readonly IHttpContextAccessor _httpContextAccessor; - private readonly IHostingEnvironment _hostingEnvironment; - //private readonly Func _getUmbracoContext; + private readonly IModelMetadataProvider _modelMetadataProvider; + private readonly ITempDataProvider _tempDataProvider; public PartialViewMacroEngine( - //IUmbracoContextAccessor umbracoContextAccessor, IHttpContextAccessor httpContextAccessor, - IHostingEnvironment hostingEnvironment) + IModelMetadataProvider modelMetadataProvider, + ITempDataProvider tempDataProvider) { _httpContextAccessor = httpContextAccessor; - _hostingEnvironment = hostingEnvironment; - - //_getUmbracoContext = () => - //{ - // var context = umbracoContextAccessor.UmbracoContext; - // if (context == null) - // { - // throw new InvalidOperationException( - // $"The {GetType()} cannot execute with a null UmbracoContext.Current reference."); - // } - - // return context; - //}; + _modelMetadataProvider = modelMetadataProvider; + _tempDataProvider = tempDataProvider; } - //public bool Validate(string code, string tempFileName, IPublishedContent currentPage, out string errorMessage) - //{ - // var temp = GetVirtualPathFromPhysicalPath(tempFileName); - // try - // { - // CompileAndInstantiate(temp); - // } - // catch (Exception exception) - // { - // errorMessage = exception.Message; - // return false; - // } - - // errorMessage = string.Empty; - // return true; - //} - public MacroContent Execute(MacroModel macro, IPublishedContent content) { if (macro == null) @@ -85,31 +58,32 @@ namespace Umbraco.Cms.Web.Common.Macros throw new ArgumentException("The MacroSource property of the macro object cannot be null or empty"); } - var httpContext = _httpContextAccessor.GetRequiredHttpContext(); - //var umbCtx = _getUmbracoContext(); - var routeVals = new RouteData(); - routeVals.Values.Add(ControllerToken, "PartialViewMacro"); - routeVals.Values.Add(ActionToken, "Index"); + HttpContext httpContext = _httpContextAccessor.GetRequiredHttpContext(); + //var routeVals = new RouteData(); + //routeVals.Values.Add(ControllerToken, "PartialViewMacro"); + //routeVals.Values.Add(ActionToken, "Index"); //TODO: Was required for UmbracoViewPage need to figure out if we still need that, i really don't think this is necessary //routeVals.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx); - var modelMetadataProvider = httpContext.RequestServices.GetRequiredService(); - var tempDataProvider = httpContext.RequestServices.GetRequiredService(); + RouteData currentRouteData = httpContext.GetRouteData(); + + // Check if there's proxied ViewData (i.e. returned from a SurfaceController) + ProxyViewDataFeature proxyViewDataFeature = httpContext.Features.Get(); + ViewDataDictionary viewData = proxyViewDataFeature?.ViewData ?? new ViewDataDictionary(_modelMetadataProvider, new ModelStateDictionary()); + ITempDataDictionary tempData = proxyViewDataFeature?.TempData ?? new TempDataDictionary(httpContext, _tempDataProvider); var viewContext = new ViewContext( - new ActionContext(httpContext, httpContext.GetRouteData(), new ControllerActionDescriptor()), + new ActionContext(httpContext, currentRouteData, new ControllerActionDescriptor()), new FakeView(), - new ViewDataDictionary(modelMetadataProvider, new ModelStateDictionary()), - new TempDataDictionary(httpContext, tempDataProvider), + viewData, + tempData, TextWriter.Null, new HtmlHelperOptions() ); - routeVals.DataTokens.Add("ParentActionViewContext", viewContext); - - var viewComponent = new PartialViewMacroViewComponent(macro, content); + //routeVals.DataTokens.Add("ParentActionViewContext", viewContext); var writer = new StringWriter(); var viewComponentContext = new ViewComponentContext( @@ -119,7 +93,9 @@ namespace Umbraco.Cms.Web.Common.Macros viewContext, writer); - viewComponent.InvokeAsync().GetAwaiter().GetResult().Execute(viewComponentContext); + var viewComponent = new PartialViewMacroViewComponent(macro, content, viewComponentContext); + + viewComponent.Invoke().Execute(viewComponentContext); var output = writer.GetStringBuilder().ToString(); @@ -129,38 +105,11 @@ namespace Umbraco.Cms.Web.Common.Macros private class FakeView : IView { /// - public Task RenderAsync(ViewContext context) - { - return Task.CompletedTask; - } + public Task RenderAsync(ViewContext context) => Task.CompletedTask; /// public string Path { get; } = "View"; } - - //private string GetVirtualPathFromPhysicalPath(string physicalPath) - //{ - // var rootpath = _hostingEnvironment.MapPathContentRoot("~/"); - // physicalPath = physicalPath.Replace(rootpath, ""); - // physicalPath = physicalPath.Replace("\\", "/"); - // return "~/" + physicalPath; - //} - - //private static PartialViewMacroPage CompileAndInstantiate(string virtualPath) - //{ - // // //Compile Razor - We Will Leave This To ASP.NET Compilation Engine & ASP.NET WebPages - // // //Security in medium trust is strict around here, so we can only pass a virtual file path - // // //ASP.NET Compilation Engine caches returned types - // // //Changed From BuildManager As Other Properties Are Attached Like Context Path/ - // // var webPageBase = WebPageBase.CreateInstanceFromVirtualPath(virtualPath); - // // var webPage = webPageBase as PartialViewMacroPage; - // // if (webPage == null) - // // throw new InvalidCastException("All Partial View Macro views must inherit from " + typeof(PartialViewMacroPage).FullName); - // // return webPage; - - // //TODO? How to check this - // return null; - //} } } diff --git a/src/Umbraco.Web.Common/Macros/PartialViewMacroViewComponent.cs b/src/Umbraco.Web.Common/Macros/PartialViewMacroViewComponent.cs index 2b317585b4..5cab93c00f 100644 --- a/src/Umbraco.Web.Common/Macros/PartialViewMacroViewComponent.cs +++ b/src/Umbraco.Web.Common/Macros/PartialViewMacroViewComponent.cs @@ -1,6 +1,7 @@ -using System.Linq; +using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ViewComponents; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.Macros; using Umbraco.Cms.Core.Models; @@ -20,13 +21,17 @@ namespace Umbraco.Cms.Web.Common.Macros public PartialViewMacroViewComponent( MacroModel macro, - IPublishedContent content) + IPublishedContent content, + ViewComponentContext viewComponentContext) { _macro = macro; _content = content; + // This must be set before Invoke is called else the call to View will end up + // using an empty ViewData instance because this hasn't been set yet. + ViewComponentContext = viewComponentContext; } - public async Task InvokeAsync() + public IViewComponentResult Invoke() { var model = new PartialViewMacroModel( _content, @@ -34,7 +39,8 @@ namespace Umbraco.Cms.Web.Common.Macros _macro.Alias, _macro.Name, _macro.Properties.ToDictionary(x => x.Key, x => (object)x.Value)); - var result = View(_macro.MacroSource, model); + + ViewViewComponentResult result = View(_macro.MacroSource, model); return result; } diff --git a/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs b/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs index 5818609aeb..81f034918a 100644 --- a/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs @@ -36,9 +36,10 @@ namespace Umbraco.Cms.Web.Common.Templates private readonly IFileService _fileService; private readonly ILocalizationService _languageService; private readonly WebRoutingSettings _webRoutingSettings; - private readonly IShortStringHelper _shortStringHelper; private readonly IHttpContextAccessor _httpContextAccessor; private readonly ICompositeViewEngine _viewEngine; + private readonly IModelMetadataProvider _modelMetadataProvider; + private readonly ITempDataProvider _tempDataProvider; public TemplateRenderer( IUmbracoContextAccessor umbracoContextAccessor, @@ -46,18 +47,20 @@ namespace Umbraco.Cms.Web.Common.Templates IFileService fileService, ILocalizationService textService, IOptions webRoutingSettings, - IShortStringHelper shortStringHelper, IHttpContextAccessor httpContextAccessor, - ICompositeViewEngine viewEngine) + ICompositeViewEngine viewEngine, + IModelMetadataProvider modelMetadataProvider, + ITempDataProvider tempDataProvider) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter)); _fileService = fileService ?? throw new ArgumentNullException(nameof(fileService)); _languageService = textService ?? throw new ArgumentNullException(nameof(textService)); _webRoutingSettings = webRoutingSettings.Value ?? throw new ArgumentNullException(nameof(webRoutingSettings)); - _shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); _viewEngine = viewEngine ?? throw new ArgumentNullException(nameof(viewEngine)); + _modelMetadataProvider = modelMetadataProvider; + _tempDataProvider = tempDataProvider; } public async Task RenderAsync(int pageId, int? altTemplateId, StringWriter writer) @@ -156,10 +159,7 @@ namespace Umbraco.Cms.Web.Common.Templates throw new InvalidOperationException($"A view with the name {request.GetTemplateAlias()} could not be found"); } - var modelMetadataProvider = httpContext.RequestServices.GetRequiredService(); - var tempDataProvider = httpContext.RequestServices.GetRequiredService(); - - var viewData = new ViewDataDictionary(modelMetadataProvider, new ModelStateDictionary()) + var viewData = new ViewDataDictionary(_modelMetadataProvider, new ModelStateDictionary()) { Model = request.PublishedContent }; @@ -169,7 +169,7 @@ namespace Umbraco.Cms.Web.Common.Templates new ActionContext(httpContext, httpContext.GetRouteData(), new ControllerActionDescriptor()), viewResult.View, viewData, - new TempDataDictionary(httpContext, tempDataProvider), + new TempDataDictionary(httpContext, _tempDataProvider), writer, new HtmlHelperOptions() ); @@ -182,6 +182,9 @@ namespace Umbraco.Cms.Web.Common.Templates sw.Write(output); } + // TODO: I feel like we need to do more than this, pretty sure we need to replace the UmbracoRouteValues + // HttpRequest feature too while this renders. + private void SetNewItemsOnContextObjects(IPublishedRequest request) { // now, set the new ones for this page execution diff --git a/src/Umbraco.Web.Website/Controllers/SurfaceController.cs b/src/Umbraco.Web.Website/Controllers/SurfaceController.cs index a0798d2fd0..b86af23999 100644 --- a/src/Umbraco.Web.Website/Controllers/SurfaceController.cs +++ b/src/Umbraco.Web.Website/Controllers/SurfaceController.cs @@ -98,7 +98,7 @@ namespace Umbraco.Cms.Web.Website.Controllers /// protected UmbracoPageResult CurrentUmbracoPage() { - HttpContext.Features.Set(new ProxyViewDataFeature(ViewData)); + HttpContext.Features.Set(new ProxyViewDataFeature(ViewData, TempData)); return new UmbracoPageResult(ProfilingLogger); } } diff --git a/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs b/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs index 67c4cd9bf7..996103f9e5 100644 --- a/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs +++ b/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Logging; @@ -35,6 +36,9 @@ namespace Umbraco.Cms.Web.Website.Controllers return CurrentUmbracoPage(); } + // TODO: This is supposed to be for members! not users + //throw new NotImplementedException("Implement this for members"); + if (await _websiteSecurityAccessor.WebsiteSecurity.LoginAsync(model.Username, model.Password) == false) { // Don't add a field level error, just model level. diff --git a/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs index 1502a51665..ddca7f37aa 100644 --- a/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs @@ -165,16 +165,11 @@ namespace Umbraco.Extensions return htmlHelper.ValidationSummary(excludePropertyErrors, message, htmlAttributes); } - var htmlGenerator = GetRequiredService(htmlHelper); + IHtmlGenerator htmlGenerator = GetRequiredService(htmlHelper); - var viewContext = htmlHelper.ViewContext.Clone(); - foreach (var key in viewContext.ViewData.Keys.ToArray()) - { - if (!key.StartsWith(prefix)) - { - viewContext.ViewData.Remove(key); - } - } + ViewContext viewContext = htmlHelper.ViewContext.Clone(); + //change the HTML field name + viewContext.ViewData.TemplateInfo.HtmlFieldPrefix = prefix; var tagBuilder = htmlGenerator.GenerateValidationSummary( viewContext, From 6148336d04e0132b535c3e8199a7cd2d618ac8de Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 1 Mar 2021 12:51:07 +1100 Subject: [PATCH 02/10] Adds new event so we know when umbraco routes a value, ensure the IUmbracoWebsiteSecurity is initialized for front-end requests, cleans up some of the routing middleware, adds lots of notes --- .../Events/UmbracoRequestBegin.cs | 2 +- .../Events/UmbracoRoutedRequest.cs | 33 +++++++++++++ src/Umbraco.Core/HybridAccessorBase.cs | 45 ++++++++++++------ .../HybridEventMessagesAccessor.cs | 4 +- .../HybridVariationContextAccessor.cs | 5 +- .../HybridBackofficeSecurityAccessor.cs | 5 +- .../HybridUmbracoWebsiteSecurityAccessor.cs | 5 +- .../IBackOfficeSecurityFactory.cs} | 2 +- .../Security/IUmbracoWebsiteSecurity.cs | 19 ++------ .../Web/HybridUmbracoContextAccessor.cs | 5 +- .../HostedServices/ScheduledPublishing.cs | 7 ++- .../UmbracoTestServerTestBase.cs | 6 ++- .../Testing/UmbracoIntegrationTest.cs | 1 + .../Filters/ContentModelValidatorTests.cs | 2 +- .../ScheduledPublishingTests.cs | 1 + .../UmbracoBuilderExtensions.cs | 2 + .../Middleware/UmbracoRequestMiddleware.cs | 30 ++++++------ .../Security/BackofficeSecurityFactory.cs | 10 ++-- .../Security/UmbracoWebsiteSecurity.cs | 9 ++-- .../Security/UmbracoWebsiteSecurityFactory.cs | 46 +++++++++++++++++++ .../Controllers/UmbLoginController.cs | 12 +++-- .../UmbracoBuilderExtensions.cs | 4 +- .../Routing/UmbracoRouteValueTransformer.cs | 10 +++- 23 files changed, 180 insertions(+), 85 deletions(-) create mode 100644 src/Umbraco.Core/Events/UmbracoRoutedRequest.cs rename src/Umbraco.Core/{IBackofficeSecurityFactory.cs => Security/IBackOfficeSecurityFactory.cs} (91%) rename src/{Umbraco.Web.Website => Umbraco.Web.Common}/Security/UmbracoWebsiteSecurity.cs (97%) create mode 100644 src/Umbraco.Web.Common/Security/UmbracoWebsiteSecurityFactory.cs diff --git a/src/Umbraco.Core/Events/UmbracoRequestBegin.cs b/src/Umbraco.Core/Events/UmbracoRequestBegin.cs index ffb55938b3..00eb41df96 100644 --- a/src/Umbraco.Core/Events/UmbracoRequestBegin.cs +++ b/src/Umbraco.Core/Events/UmbracoRequestBegin.cs @@ -1,4 +1,4 @@ -// Copyright (c) Umbraco. +// Copyright (c) Umbraco. // See LICENSE for more details. using Umbraco.Cms.Core.Web; diff --git a/src/Umbraco.Core/Events/UmbracoRoutedRequest.cs b/src/Umbraco.Core/Events/UmbracoRoutedRequest.cs new file mode 100644 index 0000000000..dd2b4d0d58 --- /dev/null +++ b/src/Umbraco.Core/Events/UmbracoRoutedRequest.cs @@ -0,0 +1,33 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using System; +using Umbraco.Cms.Core.Web; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Core.Events +{ + /// + /// Notification raised when Umbraco routes a front-end request. + /// + public class UmbracoRoutedRequest : INotification + { + /// + /// Initializes a new instance of the class. + /// + public UmbracoRoutedRequest(IUmbracoContext umbracoContext) + { + if (!umbracoContext.IsFrontEndUmbracoRequest()) + { + throw new InvalidOperationException($"{nameof(UmbracoRoutedRequest)} is only valid for Umbraco front-end requests"); + } + + UmbracoContext = umbracoContext; + } + + /// + /// Gets the + /// + public IUmbracoContext UmbracoContext { get; } + } +} diff --git a/src/Umbraco.Core/HybridAccessorBase.cs b/src/Umbraco.Core/HybridAccessorBase.cs index ae3b4471e9..9843efdfe1 100644 --- a/src/Umbraco.Core/HybridAccessorBase.cs +++ b/src/Umbraco.Core/HybridAccessorBase.cs @@ -1,4 +1,4 @@ -using System; +using System; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Scoping; @@ -18,12 +18,15 @@ namespace Umbraco.Cms.Core { private readonly IRequestCache _requestCache; + // TODO: Do they need to be static?? These are singleton instances IMO they shouldn't be static // ReSharper disable StaticMemberInGenericType - private static readonly object Locker = new object(); - private static bool _registered; + private static readonly object s_locker = new object(); + private static bool s_registered; // ReSharper restore StaticMemberInGenericType - protected abstract string ItemKey { get; } + private string _itemKey; + + protected string ItemKey => _itemKey ?? (_itemKey = GetType().FullName); // read // http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html @@ -43,34 +46,42 @@ namespace Umbraco.Cms.Core private T NonContextValue { get => CallContext.GetData(ItemKey); - set - { - CallContext.SetData(ItemKey, value); - } + set => CallContext.SetData(ItemKey, value); } protected HybridAccessorBase(IRequestCache requestCache) { _requestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache)); - lock (Locker) + lock (s_locker) { // register the itemKey once with SafeCallContext - if (_registered) return; - _registered = true; + if (s_registered) + { + return; + } + + s_registered = true; } // ReSharper disable once VirtualMemberCallInConstructor var itemKey = ItemKey; // virtual SafeCallContext.Register(() => { - var value = CallContext.GetData(itemKey); + T value = CallContext.GetData(itemKey); return value; }, o => { - if (o == null) return; - var value = o as T; - if (value == null) throw new ArgumentException($"Expected type {typeof(T).FullName}, got {o.GetType().FullName}", nameof(o)); + if (o == null) + { + return; + } + + if (!(o is T value)) + { + throw new ArgumentException($"Expected type {typeof(T).FullName}, got {o.GetType().FullName}", nameof(o)); + } + CallContext.SetData(itemKey, value); }); } @@ -93,9 +104,13 @@ namespace Umbraco.Cms.Core NonContextValue = value; } else if (value == null) + { _requestCache.Remove(ItemKey); + } else + { _requestCache.Set(ItemKey, value); + } } } } diff --git a/src/Umbraco.Core/HybridEventMessagesAccessor.cs b/src/Umbraco.Core/HybridEventMessagesAccessor.cs index 6f4d33a307..df6a34aae8 100644 --- a/src/Umbraco.Core/HybridEventMessagesAccessor.cs +++ b/src/Umbraco.Core/HybridEventMessagesAccessor.cs @@ -1,12 +1,10 @@ -using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Events; namespace Umbraco.Cms.Core { public class HybridEventMessagesAccessor : HybridAccessorBase, IEventMessagesAccessor { - protected override string ItemKey => "Umbraco.Core.Events.HybridEventMessagesAccessor"; - public HybridEventMessagesAccessor(IRequestCache requestCache) : base(requestCache) { } diff --git a/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs b/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs index c412a4de3a..9c50b60ac1 100644 --- a/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs +++ b/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.Cache; namespace Umbraco.Cms.Core.Models.PublishedContent { @@ -11,9 +11,6 @@ namespace Umbraco.Cms.Core.Models.PublishedContent : base(requestCache) { } - /// - protected override string ItemKey => "Umbraco.Web.HybridVariationContextAccessor"; - /// /// Gets or sets the object. /// diff --git a/src/Umbraco.Core/Security/HybridBackofficeSecurityAccessor.cs b/src/Umbraco.Core/Security/HybridBackofficeSecurityAccessor.cs index 990715ce39..924f0a31a6 100644 --- a/src/Umbraco.Core/Security/HybridBackofficeSecurityAccessor.cs +++ b/src/Umbraco.Core/Security/HybridBackofficeSecurityAccessor.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.Cache; namespace Umbraco.Cms.Core.Security { @@ -11,9 +11,6 @@ namespace Umbraco.Cms.Core.Security : base(requestCache) { } - /// - protected override string ItemKey => "Umbraco.Web.HybridBackofficeSecurityAccessor"; - /// /// Gets or sets the object. /// diff --git a/src/Umbraco.Core/Security/HybridUmbracoWebsiteSecurityAccessor.cs b/src/Umbraco.Core/Security/HybridUmbracoWebsiteSecurityAccessor.cs index cb986588d3..3145f400d1 100644 --- a/src/Umbraco.Core/Security/HybridUmbracoWebsiteSecurityAccessor.cs +++ b/src/Umbraco.Core/Security/HybridUmbracoWebsiteSecurityAccessor.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.Cache; namespace Umbraco.Cms.Core.Security { @@ -12,9 +12,6 @@ namespace Umbraco.Cms.Core.Security : base(requestCache) { } - /// - protected override string ItemKey => "Umbraco.Web.HybridUmbracoWebsiteSecurityAccessor"; - /// /// Gets or sets the object. /// diff --git a/src/Umbraco.Core/IBackofficeSecurityFactory.cs b/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs similarity index 91% rename from src/Umbraco.Core/IBackofficeSecurityFactory.cs rename to src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs index ac7c875f16..423332ed42 100644 --- a/src/Umbraco.Core/IBackofficeSecurityFactory.cs +++ b/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Core +namespace Umbraco.Core.Security { /// /// Creates and manages instances. diff --git a/src/Umbraco.Core/Security/IUmbracoWebsiteSecurity.cs b/src/Umbraco.Core/Security/IUmbracoWebsiteSecurity.cs index 86dbb9683e..10fb9b5f2c 100644 --- a/src/Umbraco.Core/Security/IUmbracoWebsiteSecurity.cs +++ b/src/Umbraco.Core/Security/IUmbracoWebsiteSecurity.cs @@ -1,9 +1,10 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using Umbraco.Cms.Core.Models.Security; namespace Umbraco.Cms.Core.Security { + // TODO: I think we can kill this whole thing, the logic can just be in the controllers public interface IUmbracoWebsiteSecurity { /// @@ -35,18 +36,10 @@ namespace Umbraco.Cms.Core.Security /// Result of update profile operation. Task UpdateMemberProfileAsync(ProfileModel model); - /// - /// A helper method to perform the validation and logging in of a member. - /// - /// The username. - /// The password. - /// Result of login operation. + // TODO: Kill this, we will just use the MemberManager / MemberSignInManager Task LoginAsync(string username, string password); - /// - /// Check if a member is logged in - /// - /// True if logged in, false if not. + // TODO: Kill this, we will just use the MemberManager bool IsLoggedIn(); /// @@ -55,9 +48,7 @@ namespace Umbraco.Cms.Core.Security /// Instance of Task GetCurrentLoginStatusAsync(); - /// - /// Logs out the current member. - /// + // TODO: Kill this, we will just use the MemberManager Task LogOutAsync(); /// diff --git a/src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs b/src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs index a266c07769..503bb25b57 100644 --- a/src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs +++ b/src/Umbraco.Core/Web/HybridUmbracoContextAccessor.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.Cache; namespace Umbraco.Cms.Core.Web { @@ -14,9 +14,6 @@ namespace Umbraco.Cms.Core.Web : base(requestCache) { } - /// - protected override string ItemKey => "Umbraco.Web.HybridUmbracoContextAccessor"; - /// /// Gets or sets the object. /// diff --git a/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs b/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs index bc81bfabcf..f5f5ee22a2 100644 --- a/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs +++ b/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs @@ -12,6 +12,7 @@ using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Sync; using Umbraco.Cms.Core.Web; +using Umbraco.Core.Security; namespace Umbraco.Cms.Infrastructure.HostedServices { @@ -106,7 +107,11 @@ namespace Umbraco.Cms.Infrastructure.HostedServices // - batched messenger should not depend on a current HttpContext // but then what should be its "scope"? could we attach it to scopes? // - and we should definitively *not* have to flush it here (should be auto) - // + + // TODO: This dependency chain is broken and needs to be fixed. + // This is required to be called before EnsureUmbracoContext else the UmbracoContext's IBackOfficeSecurity instance is null + // This is a very ugly Temporal Coupling which also means that developers can no longer just use IUmbracoContextFactory the + // way it was intended. _backofficeSecurityFactory.EnsureBackOfficeSecurity(); using UmbracoContextReference contextReference = _umbracoContextFactory.EnsureUmbracoContext(); try diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index caed95ae52..60a48f3f4c 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -14,7 +14,6 @@ using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using NUnit.Framework; -using Umbraco.Cms.Core; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; @@ -25,6 +24,7 @@ using Umbraco.Cms.Tests.Integration.Testing; using Umbraco.Cms.Web.BackOffice.Controllers; using Umbraco.Cms.Web.Common.Controllers; using Umbraco.Cms.Web.Website.Controllers; +using Umbraco.Core.Security; using Umbraco.Extensions; using Constants = Umbraco.Cms.Core.Constants; @@ -122,6 +122,10 @@ namespace Umbraco.Cms.Tests.Integration.TestServerTest } }; + // TODO: This dependency chain is broken and needs to be fixed. + // This is required to be called before EnsureUmbracoContext else the UmbracoContext's IBackOfficeSecurity instance is null + // This is a very ugly Temporal Coupling which also means that developers can no longer just use IUmbracoContextFactory the + // way it was intended. backofficeSecurityFactory.EnsureBackOfficeSecurity(); umbracoContextFactory.EnsureUmbracoContext(); diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index eab085f67e..d3625d109a 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -36,6 +36,7 @@ using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.DependencyInjection; using Umbraco.Cms.Tests.Integration.Extensions; using Umbraco.Cms.Tests.Integration.Implementations; +using Umbraco.Core.Security; using Umbraco.Extensions; using Constants = Umbraco.Cms.Core.Constants; diff --git a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs index 5cf0dc7b28..3e54039714 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs @@ -11,7 +11,6 @@ using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NUnit.Framework; -using Umbraco.Cms.Core; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; @@ -25,6 +24,7 @@ using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.Testing; using Umbraco.Cms.Web.BackOffice.Filters; using Umbraco.Cms.Web.BackOffice.ModelBinders; +using Umbraco.Core.Security; using Umbraco.Extensions; using DataType = Umbraco.Cms.Core.Models.DataType; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs index 62ee1fdd29..3782a8aece 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs @@ -13,6 +13,7 @@ using Umbraco.Cms.Core.Sync; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Infrastructure; using Umbraco.Cms.Infrastructure.HostedServices; +using Umbraco.Core.Security; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices { diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index 9e2e79cb9b..1d636706f7 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -53,6 +53,7 @@ using Umbraco.Cms.Web.Common.Routing; using Umbraco.Cms.Web.Common.Security; using Umbraco.Cms.Web.Common.Templates; using Umbraco.Cms.Web.Common.UmbracoContext; +using Umbraco.Core.Security; using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment; namespace Umbraco.Extensions @@ -263,6 +264,7 @@ namespace Umbraco.Extensions builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); + builder.AddNotificationHandler(); builder.Services.AddUnique(); var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList(); diff --git a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs index 6fdd41a757..2515948bea 100644 --- a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs +++ b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs @@ -10,9 +10,11 @@ using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Logging; +using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Infrastructure.PublishedCache; using Umbraco.Cms.Web.Common.Profiler; +using Umbraco.Core.Security; using Umbraco.Extensions; namespace Umbraco.Cms.Web.Common.Middleware @@ -83,27 +85,26 @@ namespace Umbraco.Cms.Web.Common.Middleware EnsureContentCacheInitialized(); - _backofficeSecurityFactory.EnsureBackOfficeSecurity(); // Needs to be before UmbracoContext, TODO: Why? + // TODO: This dependency chain is broken and needs to be fixed. + // This is required to be called before EnsureUmbracoContext else the UmbracoContext's IBackOfficeSecurity instance is null + // This is ugly Temporal Coupling which also means that developers can no longer just use IUmbracoContextFactory the + // way it was intended. + _backofficeSecurityFactory.EnsureBackOfficeSecurity(); UmbracoContextReference umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext(); Uri currentApplicationUrl = GetApplicationUrlFromCurrentRequest(context.Request); _hostingEnvironment.EnsureApplicationMainUrl(currentApplicationUrl); - - bool isFrontEndRequest = umbracoContextReference.UmbracoContext.IsFrontEndUmbracoRequest(); - var pathAndQuery = context.Request.GetEncodedPathAndQuery(); try { - if (isFrontEndRequest) - { - LogHttpRequest.TryGetCurrentHttpRequestId(out Guid httpRequestId, _requestCache); - _logger.LogTrace("Begin request [{HttpRequestId}]: {RequestUrl}", httpRequestId, pathAndQuery); - } + // Verbose log start of every request + LogHttpRequest.TryGetCurrentHttpRequestId(out Guid httpRequestId, _requestCache); + _logger.LogTrace("Begin request [{HttpRequestId}]: {RequestUrl}", httpRequestId, pathAndQuery); try - { + { await _eventAggregator.PublishAsync(new UmbracoRequestBegin(umbracoContextReference.UmbracoContext)); } catch (Exception ex) @@ -126,11 +127,10 @@ namespace Umbraco.Cms.Web.Common.Middleware } finally { - if (isFrontEndRequest) - { - LogHttpRequest.TryGetCurrentHttpRequestId(out Guid httpRequestId, _requestCache); - _logger.LogTrace("End Request [{HttpRequestId}]: {RequestUrl} ({RequestDuration}ms)", httpRequestId, pathAndQuery, DateTime.Now.Subtract(umbracoContextReference.UmbracoContext.ObjectCreated).TotalMilliseconds); - } + // Verbose log end of every request (in v8 we didn't log the end request of ALL requests, only the front-end which was + // strange since we always logged the beginning, so now we just log start/end of all requests) + LogHttpRequest.TryGetCurrentHttpRequestId(out Guid httpRequestId, _requestCache); + _logger.LogTrace("End Request [{HttpRequestId}]: {RequestUrl} ({RequestDuration}ms)", httpRequestId, pathAndQuery, DateTime.Now.Subtract(umbracoContextReference.UmbracoContext.ObjectCreated).TotalMilliseconds); try { diff --git a/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs b/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs index 41e7f6d816..eda7f4b98e 100644 --- a/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs +++ b/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs @@ -1,11 +1,11 @@ -using Microsoft.AspNetCore.Http; -using Umbraco.Cms.Core; +using Microsoft.AspNetCore.Http; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; +using Umbraco.Core.Security; namespace Umbraco.Cms.Web.Common.Security { - // TODO: This is only for the back office, does it need to be in common? + // TODO: This is only for the back office, does it need to be in common? YES currently UmbracoContext has an transitive dependency on this which needs to be fixed/reviewed. public class BackOfficeSecurityFactory: IBackOfficeSecurityFactory { @@ -14,11 +14,11 @@ namespace Umbraco.Cms.Web.Common.Security private readonly IHttpContextAccessor _httpContextAccessor; public BackOfficeSecurityFactory( - IBackOfficeSecurityAccessor backofficeSecurityAccessor, + IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IUserService userService, IHttpContextAccessor httpContextAccessor) { - _backOfficeSecurityAccessor = backofficeSecurityAccessor; + _backOfficeSecurityAccessor = backOfficeSecurityAccessor; _userService = userService; _httpContextAccessor = httpContextAccessor; } diff --git a/src/Umbraco.Web.Website/Security/UmbracoWebsiteSecurity.cs b/src/Umbraco.Web.Common/Security/UmbracoWebsiteSecurity.cs similarity index 97% rename from src/Umbraco.Web.Website/Security/UmbracoWebsiteSecurity.cs rename to src/Umbraco.Web.Common/Security/UmbracoWebsiteSecurity.cs index c878730d90..5a67f6f484 100644 --- a/src/Umbraco.Web.Website/Security/UmbracoWebsiteSecurity.cs +++ b/src/Umbraco.Web.Common/Security/UmbracoWebsiteSecurity.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -11,9 +11,8 @@ using Umbraco.Cms.Core.Models.Security; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; -using Constants = Umbraco.Cms.Core.Constants; -namespace Umbraco.Cms.Web.Website.Security +namespace Umbraco.Cms.Web.Common.Security { public class UmbracoWebsiteSecurity : IUmbracoWebsiteSecurity { @@ -36,7 +35,7 @@ namespace Umbraco.Cms.Web.Website.Security /// public RegisterModel CreateRegistrationModel(string memberTypeAlias = null) { - var providedOrDefaultMemberTypeAlias = memberTypeAlias ?? Constants.Conventions.MemberTypes.DefaultAlias; + var providedOrDefaultMemberTypeAlias = memberTypeAlias ?? Core.Constants.Conventions.MemberTypes.DefaultAlias; var memberType = _memberTypeService.Get(providedOrDefaultMemberTypeAlias); if (memberType == null) { @@ -114,7 +113,7 @@ namespace Umbraco.Cms.Web.Website.Security public Task RegisterMemberAsync(RegisterModel model, bool logMemberIn = true) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } /// diff --git a/src/Umbraco.Web.Common/Security/UmbracoWebsiteSecurityFactory.cs b/src/Umbraco.Web.Common/Security/UmbracoWebsiteSecurityFactory.cs new file mode 100644 index 0000000000..ec256a86cb --- /dev/null +++ b/src/Umbraco.Web.Common/Security/UmbracoWebsiteSecurityFactory.cs @@ -0,0 +1,46 @@ +using Microsoft.AspNetCore.Http; +using Umbraco.Cms.Core.Events; +using Umbraco.Cms.Core.Security; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Strings; + +namespace Umbraco.Cms.Web.Common.Security +{ + /// + /// Ensures that the is populated on a front-end request + /// + internal sealed class UmbracoWebsiteSecurityFactory : INotificationHandler + { + private readonly IUmbracoWebsiteSecurityAccessor _umbracoWebsiteSecurityAccessor; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IMemberService _memberService; + private readonly IMemberTypeService _memberTypeService; + private readonly IShortStringHelper _shortStringHelper; + + public UmbracoWebsiteSecurityFactory( + IUmbracoWebsiteSecurityAccessor umbracoWebsiteSecurityAccessor, + IHttpContextAccessor httpContextAccessor, + IMemberService memberService, + IMemberTypeService memberTypeService, + IShortStringHelper shortStringHelper) + { + _umbracoWebsiteSecurityAccessor = umbracoWebsiteSecurityAccessor; + _httpContextAccessor = httpContextAccessor; + _memberService = memberService; + _memberTypeService = memberTypeService; + _shortStringHelper = shortStringHelper; + } + + public void Handle(UmbracoRoutedRequest notification) + { + if (_umbracoWebsiteSecurityAccessor.WebsiteSecurity is null) + { + _umbracoWebsiteSecurityAccessor.WebsiteSecurity = new UmbracoWebsiteSecurity( + _httpContextAccessor, + _memberService, + _memberTypeService, + _shortStringHelper); + } + } + } +} diff --git a/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs b/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs index 996103f9e5..93b1f23b76 100644 --- a/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs +++ b/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs @@ -18,8 +18,13 @@ namespace Umbraco.Cms.Web.Website.Controllers { private readonly IUmbracoWebsiteSecurityAccessor _websiteSecurityAccessor; - public UmbLoginController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, - ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider, + public UmbLoginController( + IUmbracoContextAccessor umbracoContextAccessor, + IUmbracoDatabaseFactory databaseFactory, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger profilingLogger, + IPublishedUrlProvider publishedUrlProvider, IUmbracoWebsiteSecurityAccessor websiteSecurityAccessor) : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider) { @@ -36,9 +41,6 @@ namespace Umbraco.Cms.Web.Website.Controllers return CurrentUmbracoPage(); } - // TODO: This is supposed to be for members! not users - //throw new NotImplementedException("Implement this for members"); - if (await _websiteSecurityAccessor.WebsiteSecurity.LoginAsync(model.Username, model.Password) == false) { // Don't add a field level error, just model level. diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs index 3823cde255..58074ac9a5 100644 --- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs @@ -2,8 +2,10 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Security; using Umbraco.Cms.Infrastructure.DependencyInjection; using Umbraco.Cms.Web.Common.Routing; +using Umbraco.Cms.Web.Common.Security; using Umbraco.Cms.Web.Website.Collections; using Umbraco.Cms.Web.Website.Controllers; using Umbraco.Cms.Web.Website.Routing; @@ -40,7 +42,7 @@ namespace Umbraco.Extensions builder.Services.AddSingleton(); builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + builder.Services.AddSingleton(); builder .AddDistributedCache() diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs index d0e5d4c72a..13e70897ab 100644 --- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs +++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs @@ -13,6 +13,7 @@ using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Services; @@ -48,6 +49,7 @@ namespace Umbraco.Cms.Web.Website.Routing private readonly IRoutableDocumentFilter _routableDocumentFilter; private readonly IDataProtectionProvider _dataProtectionProvider; private readonly IControllerActionSearcher _controllerActionSearcher; + private readonly IEventAggregator _eventAggregator; /// /// Initializes a new instance of the class. @@ -62,7 +64,8 @@ namespace Umbraco.Cms.Web.Website.Routing IUmbracoRouteValuesFactory routeValuesFactory, IRoutableDocumentFilter routableDocumentFilter, IDataProtectionProvider dataProtectionProvider, - IControllerActionSearcher controllerActionSearcher) + IControllerActionSearcher controllerActionSearcher, + IEventAggregator eventAggregator) { if (globalSettings is null) { @@ -79,6 +82,7 @@ namespace Umbraco.Cms.Web.Website.Routing _routableDocumentFilter = routableDocumentFilter ?? throw new ArgumentNullException(nameof(routableDocumentFilter)); _dataProtectionProvider = dataProtectionProvider; _controllerActionSearcher = controllerActionSearcher; + _eventAggregator = eventAggregator; } /// @@ -117,6 +121,10 @@ namespace Umbraco.Cms.Web.Website.Routing // Store the route values as a httpcontext feature httpContext.Features.Set(umbracoRouteValues); + // publish an event that we've routed a request + // TODO: does this occur on 404 or have we already returned? + await _eventAggregator.PublishAsync(new UmbracoRoutedRequest(_umbracoContextAccessor.UmbracoContext)); + // Need to check if there is form data being posted back to an Umbraco URL PostedDataProxyInfo postedInfo = GetFormInfo(httpContext, values); if (postedInfo != null) From 70caa227e2e919b6e50f135c8cc5e0c7b970f6ce Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 1 Mar 2021 12:57:04 +1100 Subject: [PATCH 03/10] notes --- src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs index 13e70897ab..c5d13b721a 100644 --- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs +++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs @@ -122,7 +122,6 @@ namespace Umbraco.Cms.Web.Website.Routing httpContext.Features.Set(umbracoRouteValues); // publish an event that we've routed a request - // TODO: does this occur on 404 or have we already returned? await _eventAggregator.PublishAsync(new UmbracoRoutedRequest(_umbracoContextAccessor.UmbracoContext)); // Need to check if there is form data being posted back to an Umbraco URL From fa3f66aa07c8fbbf96278ad8eba27d7979cb21d9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 1 Mar 2021 13:01:28 +1100 Subject: [PATCH 04/10] removes comments --- .../Macros/PartialViewMacroEngine.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Umbraco.Web.Common/Macros/PartialViewMacroEngine.cs b/src/Umbraco.Web.Common/Macros/PartialViewMacroEngine.cs index 5b37557cd2..4cbc2d7648 100644 --- a/src/Umbraco.Web.Common/Macros/PartialViewMacroEngine.cs +++ b/src/Umbraco.Web.Common/Macros/PartialViewMacroEngine.cs @@ -59,13 +59,7 @@ namespace Umbraco.Cms.Web.Common.Macros } HttpContext httpContext = _httpContextAccessor.GetRequiredHttpContext(); - //var routeVals = new RouteData(); - //routeVals.Values.Add(ControllerToken, "PartialViewMacro"); - //routeVals.Values.Add(ActionToken, "Index"); - - //TODO: Was required for UmbracoViewPage need to figure out if we still need that, i really don't think this is necessary - //routeVals.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx); - + RouteData currentRouteData = httpContext.GetRouteData(); // Check if there's proxied ViewData (i.e. returned from a SurfaceController) @@ -82,9 +76,6 @@ namespace Umbraco.Cms.Web.Common.Macros new HtmlHelperOptions() ); - - //routeVals.DataTokens.Add("ParentActionViewContext", viewContext); - var writer = new StringWriter(); var viewComponentContext = new ViewComponentContext( new ViewComponentDescriptor(), From 9408a90d142e1143d98640ae5f96d3880d550903 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 1 Mar 2021 14:17:03 +1100 Subject: [PATCH 05/10] left over namespace --- .../Security/UmbracoWebsiteSecurityTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Security/UmbracoWebsiteSecurityTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Security/UmbracoWebsiteSecurityTests.cs index 5e53486d11..54d2f7787b 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Security/UmbracoWebsiteSecurityTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Security/UmbracoWebsiteSecurityTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Umbraco. +// Copyright (c) Umbraco. // See LICENSE for more details. using System.Linq; @@ -13,7 +13,6 @@ using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Tests.Common.Builders; -using Umbraco.Cms.Web.Website.Security; using CoreConstants = Umbraco.Cms.Core.Constants; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Website.Security From c1f14de943bf0c6bfc250872152b41bf2cf11a21 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 1 Mar 2021 14:20:15 +1100 Subject: [PATCH 06/10] fix build --- .../Routing/UmbracoRouteValueTransformerTests.cs | 4 +++- .../Security/UmbracoWebsiteSecurityTests.cs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs index 4d74ea6427..e8e8fec2e0 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformerTests.cs @@ -13,6 +13,7 @@ using Moq; using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Services; @@ -56,7 +57,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Website.Routing routeValuesFactory ?? Mock.Of(), filter ?? Mock.Of(x => x.IsDocumentRequest(It.IsAny()) == true), Mock.Of(), - Mock.Of()); + Mock.Of(), + Mock.Of()); return transformer; } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Security/UmbracoWebsiteSecurityTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Security/UmbracoWebsiteSecurityTests.cs index 54d2f7787b..badcaae8b5 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Security/UmbracoWebsiteSecurityTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Security/UmbracoWebsiteSecurityTests.cs @@ -13,6 +13,7 @@ using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Tests.Common.Builders; +using Umbraco.Cms.Web.Common.Security; using CoreConstants = Umbraco.Cms.Core.Constants; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Website.Security From 1c50ece9862d76d82af8870d88e6f055a3ec22d7 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 2 Mar 2021 16:20:44 +0100 Subject: [PATCH 07/10] Use c#9 + namespace fix --- src/Umbraco.Core/HybridAccessorBase.cs | 2 +- .../Security/IBackOfficeSecurityFactory.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 5 ---- .../Umbraco.Examine.Lucene.csproj | 1 - .../HostedServices/ScheduledPublishing.cs | 1 - .../Runtime/SqlMainDomLock.cs | 1 + .../Umbraco.Infrastructure.csproj | 1 - .../Umbraco.PublishedCache.NuCache.csproj | 2 -- .../Umbraco.Tests.Common.csproj | 1 - .../UmbracoTestServerTestBase.cs | 4 ++-- .../Testing/UmbracoIntegrationTest.cs | 3 +-- .../Umbraco.Tests.Integration.csproj | 1 - .../Filters/ContentModelValidatorTests.cs | 2 +- .../ScheduledPublishingTests.cs | 2 +- .../Umbraco.Web.BackOffice.csproj | 1 - .../UmbracoBuilderExtensions.cs | 1 - .../Macros/MacroRenderer.cs | 3 +-- .../Middleware/UmbracoRequestMiddleware.cs | 1 - .../Security/BackofficeSecurityFactory.cs | 3 +-- .../Umbraco.Web.Common.csproj | 1 - .../BergViewComponent.cs | 23 +++++++++++++++++++ .../Umbraco.Web.UI.NetCore.csproj | 2 -- .../Umbraco.Web.Website.csproj | 1 - 23 files changed, 33 insertions(+), 31 deletions(-) create mode 100644 src/Umbraco.Web.UI.NetCore/BergViewComponent.cs diff --git a/src/Umbraco.Core/HybridAccessorBase.cs b/src/Umbraco.Core/HybridAccessorBase.cs index 9843efdfe1..06713aa59e 100644 --- a/src/Umbraco.Core/HybridAccessorBase.cs +++ b/src/Umbraco.Core/HybridAccessorBase.cs @@ -77,7 +77,7 @@ namespace Umbraco.Cms.Core return; } - if (!(o is T value)) + if (o is not T value) { throw new ArgumentException($"Expected type {typeof(T).FullName}, got {o.GetType().FullName}", nameof(o)); } diff --git a/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs b/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs index 423332ed42..ee553e85e6 100644 --- a/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs +++ b/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Security +namespace Umbraco.Cms.Core.Security { /// /// Creates and manages instances. diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 2f38e4953b..1166bc1270 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -2,13 +2,8 @@ netstandard2.0 - 8 Umbraco.Cms.Core - 0.5.0 - 0.5.0 - 0.5.0 Umbraco CMS - Umbraco.Core diff --git a/src/Umbraco.Examine.Lucene/Umbraco.Examine.Lucene.csproj b/src/Umbraco.Examine.Lucene/Umbraco.Examine.Lucene.csproj index 71f10f003b..d0419abe6b 100644 --- a/src/Umbraco.Examine.Lucene/Umbraco.Examine.Lucene.csproj +++ b/src/Umbraco.Examine.Lucene/Umbraco.Examine.Lucene.csproj @@ -4,7 +4,6 @@ net472 Umbraco.Cms.Infrastructure.Examine Umbraco CMS - Umbraco.Examine Umbraco.Examine.Lucene diff --git a/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs b/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs index f5f5ee22a2..0fc1809250 100644 --- a/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs +++ b/src/Umbraco.Infrastructure/HostedServices/ScheduledPublishing.cs @@ -12,7 +12,6 @@ using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Sync; using Umbraco.Cms.Core.Web; -using Umbraco.Core.Security; namespace Umbraco.Cms.Infrastructure.HostedServices { diff --git a/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs b/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs index 22fa172874..e8f5072e18 100644 --- a/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs +++ b/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs @@ -80,6 +80,7 @@ _hostingEnvironment = hostingEnvironment; { db = _dbFactory.CreateDatabase(); + _hasTable = db.HasTable(Cms.Core.Constants.DatabaseSchema.Tables.KeyValue); if (!_hasTable) { diff --git a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj index cd49b2abb1..61bd171336 100644 --- a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj +++ b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj @@ -2,7 +2,6 @@ netstandard2.0 - 8 Umbraco.Cms.Infrastructure diff --git a/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj b/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj index 8973054260..fe3ce47de4 100644 --- a/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj +++ b/src/Umbraco.PublishedCache.NuCache/Umbraco.PublishedCache.NuCache.csproj @@ -3,8 +3,6 @@ netstandard2.0 Umbraco.Cms.Infrastructure.PublishedCache - 8 - Umbraco.Infrastructure.PublishedCache diff --git a/src/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj b/src/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj index b02c1a5a29..870e33e3cb 100644 --- a/src/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj +++ b/src/Umbraco.Tests.Common/Umbraco.Tests.Common.csproj @@ -2,7 +2,6 @@ netstandard2.0 - latest Umbraco.Cms.Tests.Common diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index 60a48f3f4c..dbb2adef89 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -14,9 +14,11 @@ using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using NUnit.Framework; +using Umbraco.Cms.Core; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.DependencyInjection; @@ -24,9 +26,7 @@ using Umbraco.Cms.Tests.Integration.Testing; using Umbraco.Cms.Web.BackOffice.Controllers; using Umbraco.Cms.Web.Common.Controllers; using Umbraco.Cms.Web.Website.Controllers; -using Umbraco.Core.Security; using Umbraco.Extensions; -using Constants = Umbraco.Cms.Core.Constants; namespace Umbraco.Cms.Tests.Integration.TestServerTest { diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index d3625d109a..133320b853 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -25,6 +25,7 @@ using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Scoping; +using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; using Umbraco.Cms.Core.Web; @@ -36,9 +37,7 @@ using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.DependencyInjection; using Umbraco.Cms.Tests.Integration.Extensions; using Umbraco.Cms.Tests.Integration.Implementations; -using Umbraco.Core.Security; using Umbraco.Extensions; -using Constants = Umbraco.Cms.Core.Constants; namespace Umbraco.Cms.Tests.Integration.Testing { diff --git a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index 18cc68996d..f45a7bc444 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -4,7 +4,6 @@ Exe net5.0 false - 8 Umbraco.Cms.Tests.Integration diff --git a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs index 3e54039714..91432f142e 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs @@ -16,6 +16,7 @@ using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.PropertyEditors; +using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Serialization; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Strings; @@ -24,7 +25,6 @@ using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.Testing; using Umbraco.Cms.Web.BackOffice.Filters; using Umbraco.Cms.Web.BackOffice.ModelBinders; -using Umbraco.Core.Security; using Umbraco.Extensions; using DataType = Umbraco.Cms.Core.Models.DataType; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs index 3782a8aece..3ef434edab 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/HostedServices/ScheduledPublishingTests.cs @@ -8,12 +8,12 @@ using Moq; using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Runtime; +using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Sync; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Infrastructure; using Umbraco.Cms.Infrastructure.HostedServices; -using Umbraco.Core.Security; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices { diff --git a/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj b/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj index 8a1a0ebcdf..e66bfb1577 100644 --- a/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj +++ b/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj @@ -3,7 +3,6 @@ net5.0 Library - latest Umbraco.Cms.Web.BackOffice diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index 1d636706f7..6c11b91a95 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -53,7 +53,6 @@ using Umbraco.Cms.Web.Common.Routing; using Umbraco.Cms.Web.Common.Security; using Umbraco.Cms.Web.Common.Templates; using Umbraco.Cms.Web.Common.UmbracoContext; -using Umbraco.Core.Security; using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment; namespace Umbraco.Extensions diff --git a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs index 389267cd61..129936071c 100644 --- a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs @@ -353,13 +353,12 @@ namespace Umbraco.Cms.Web.Common.Macros return Attempt.Fail(new MacroContent { Text = "[macro failed (no content)]" }); } - ILocalizedTextService textService = _textService; return ExecuteMacroWithErrorWrapper(model, $"Executing PartialView: MacroSource=\"{model.MacroSource}\".", "Executed PartialView.", () => _partialViewMacroEngine.Execute(model, content), - () => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource })); + () => _textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource })); } diff --git a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs index 2515948bea..467ec29451 100644 --- a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs +++ b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs @@ -14,7 +14,6 @@ using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Infrastructure.PublishedCache; using Umbraco.Cms.Web.Common.Profiler; -using Umbraco.Core.Security; using Umbraco.Extensions; namespace Umbraco.Cms.Web.Common.Middleware diff --git a/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs b/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs index eda7f4b98e..ad0731f790 100644 --- a/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs +++ b/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs @@ -1,7 +1,6 @@ -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; -using Umbraco.Core.Security; namespace Umbraco.Cms.Web.Common.Security { diff --git a/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj b/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj index 2bcf4a3e55..c08204f1cf 100644 --- a/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj +++ b/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj @@ -3,7 +3,6 @@ net5.0 Library - latest Umbraco.Cms.Web.Common diff --git a/src/Umbraco.Web.UI.NetCore/BergViewComponent.cs b/src/Umbraco.Web.UI.NetCore/BergViewComponent.cs new file mode 100644 index 0000000000..17d9fe6cf1 --- /dev/null +++ b/src/Umbraco.Web.UI.NetCore/BergViewComponent.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Core.Web; + +namespace Umbraco.Cms.Web.UI.NetCore +{ + public class BergViewComponent : ViewComponent + { + private readonly IUmbracoContextAccessor _umbracoContextAccessor; + + public BergViewComponent(IUmbracoContextAccessor umbracoContextAccessor) + { + _umbracoContextAccessor = umbracoContextAccessor; + } + + public IViewComponentResult Invoke() + { + TempData["BERG"] = "coool"; + + var currentPage = _umbracoContextAccessor.UmbracoContext.PublishedRequest?.PublishedContent; + return View(currentPage); + } + } +} diff --git a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj index 4f6bb1240f..104035ed84 100644 --- a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj +++ b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj @@ -3,7 +3,6 @@ net5.0 Umbraco.Cms.Web.UI.NetCore - latest Umbraco.Cms.Web.UI.NetCore @@ -22,7 +21,6 @@ - diff --git a/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj b/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj index 8b940ba47b..c38670f45d 100644 --- a/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj +++ b/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj @@ -3,7 +3,6 @@ net5.0 Library - latest Umbraco.Cms.Web.Website From cf6d33f8433bd924409f3e0699b07225cc27847b Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Wed, 3 Mar 2021 09:38:02 +1100 Subject: [PATCH 08/10] Update src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs Co-authored-by: Bjarke Berg --- src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs b/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs index 423332ed42..ee553e85e6 100644 --- a/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs +++ b/src/Umbraco.Core/Security/IBackOfficeSecurityFactory.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Security +namespace Umbraco.Cms.Core.Security { /// /// Creates and manages instances. From e7b96a5214d27974553c55542406ba7c7f57a9d3 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 3 Mar 2021 06:05:42 +0100 Subject: [PATCH 09/10] Change static fields to instance, in singleton --- src/Umbraco.Core/HybridAccessorBase.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Core/HybridAccessorBase.cs b/src/Umbraco.Core/HybridAccessorBase.cs index 06713aa59e..51a51e0d01 100644 --- a/src/Umbraco.Core/HybridAccessorBase.cs +++ b/src/Umbraco.Core/HybridAccessorBase.cs @@ -18,15 +18,12 @@ namespace Umbraco.Cms.Core { private readonly IRequestCache _requestCache; - // TODO: Do they need to be static?? These are singleton instances IMO they shouldn't be static - // ReSharper disable StaticMemberInGenericType - private static readonly object s_locker = new object(); - private static bool s_registered; - // ReSharper restore StaticMemberInGenericType + private readonly object _locker = new object(); + private readonly bool _registered; private string _itemKey; - protected string ItemKey => _itemKey ?? (_itemKey = GetType().FullName); + protected string ItemKey => _itemKey ??= GetType().FullName; // read // http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html @@ -53,15 +50,15 @@ namespace Umbraco.Cms.Core { _requestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache)); - lock (s_locker) + lock (_locker) { // register the itemKey once with SafeCallContext - if (s_registered) + if (_registered) { return; } - s_registered = true; + _registered = true; } // ReSharper disable once VirtualMemberCallInConstructor From c3d6cc0dcd0fe9394aa41fb6a5cd889af1cbb793 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 3 Mar 2021 07:09:49 +0100 Subject: [PATCH 10/10] Revert test view component --- .../BergViewComponent.cs | 23 ------------------- .../Umbraco.Web.UI.NetCore.csproj | 1 + 2 files changed, 1 insertion(+), 23 deletions(-) delete mode 100644 src/Umbraco.Web.UI.NetCore/BergViewComponent.cs diff --git a/src/Umbraco.Web.UI.NetCore/BergViewComponent.cs b/src/Umbraco.Web.UI.NetCore/BergViewComponent.cs deleted file mode 100644 index 17d9fe6cf1..0000000000 --- a/src/Umbraco.Web.UI.NetCore/BergViewComponent.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Umbraco.Cms.Core.Web; - -namespace Umbraco.Cms.Web.UI.NetCore -{ - public class BergViewComponent : ViewComponent - { - private readonly IUmbracoContextAccessor _umbracoContextAccessor; - - public BergViewComponent(IUmbracoContextAccessor umbracoContextAccessor) - { - _umbracoContextAccessor = umbracoContextAccessor; - } - - public IViewComponentResult Invoke() - { - TempData["BERG"] = "coool"; - - var currentPage = _umbracoContextAccessor.UmbracoContext.PublishedRequest?.PublishedContent; - return View(currentPage); - } - } -} diff --git a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj index 104035ed84..066a27ccee 100644 --- a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj +++ b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj @@ -21,6 +21,7 @@ +