From a9732cb2334868190cd19abecc7a31885591bae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 6 Feb 2020 14:57:25 +0100 Subject: [PATCH 01/19] corrected button style to match new style --- .../src/views/propertyeditors/listview/listview.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index ee1847b430..55adb18c6e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -21,7 +21,7 @@
- From 312dc1d9a757469daa209fe99f66abc5b0dc2309 Mon Sep 17 00:00:00 2001 From: Niels Swimberghe Date: Tue, 15 Sep 2020 12:54:00 -0400 Subject: [PATCH 02/19] Change wrong URL in KeepAlive XML Comments The XML comments for KeepAlive mention the URL for the KeepAlive.Ping action but incorrectly omits 'umbraco' from the path. The change adds the 'umbraco' section to the path. --- src/Umbraco.Web.UI/config/umbracoSettings.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index 73a5143a20..d723b9c7c0 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -259,7 +259,7 @@ Defaults to "false". @keepAlivePingUrl The url of the KeepAlivePing action. By default, the url will use the umbracoApplicationUrl setting as the basis. - Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/api/keepalive/ping + Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/umbraco/api/keepalive/ping Defaults to "{umbracoApplicationUrl}/api/keepalive/ping". --> From 5a37854dd5d3412cc0ac18dfed003b212ac192c7 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 14 Sep 2020 12:02:26 +0100 Subject: [PATCH 03/19] Merge pull request #7599 from umbraco/v8/feature/ui-media-create-button-style UI: corrected button style to match new style (cherry picked from commit 2e055ca146a7ab1814ce232ccc97fa07571733df) --- .../src/views/propertyeditors/listview/listview.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index 05a294cc1c..e72b81b019 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -21,7 +21,7 @@
- From 6d2135edd5b0c92560492ee6417d136740a0d07b Mon Sep 17 00:00:00 2001 From: Niels Swimberghe Date: Tue, 15 Sep 2020 12:54:00 -0400 Subject: [PATCH 04/19] Change wrong URL in KeepAlive XML Comments The XML comments for KeepAlive mention the URL for the KeepAlive.Ping action but incorrectly omits 'umbraco' from the path. The change adds the 'umbraco' section to the path. (cherry picked from commit 312dc1d9a757469daa209fe99f66abc5b0dc2309) --- src/Umbraco.Web.UI/config/umbracoSettings.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index 73a5143a20..d723b9c7c0 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -259,7 +259,7 @@ Defaults to "false". @keepAlivePingUrl The url of the KeepAlivePing action. By default, the url will use the umbracoApplicationUrl setting as the basis. - Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/api/keepalive/ping + Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/umbraco/api/keepalive/ping Defaults to "{umbracoApplicationUrl}/api/keepalive/ping". --> From deb03e4d82e48674c6d8bdc7926e820e17454d9e Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Thu, 17 Sep 2020 11:32:52 +0200 Subject: [PATCH 05/19] Eliminates error/no-preview when grid media picker have no crop set (#8620) --- .../mediapicker/overlays/mediacropdetails.controller.js | 5 +++++ .../mediapicker/overlays/mediacropdetails.html | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js index d9ea5a7a09..030200e1e6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js @@ -6,6 +6,7 @@ vm.submit = submit; vm.close = close; + vm.cropSet = cropSet; if (!$scope.model.target.coordinates && !$scope.model.target.focalPoint) { $scope.model.target.focalPoint = { left: .5, top: .5 }; @@ -56,4 +57,8 @@ } } + function cropSet() { + var model = $scope.model; + return (model.cropSize || {}).width && model.target.thumbnail; + } }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html index 3814ac851e..cda42043c1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html @@ -26,7 +26,7 @@
-
+
Preview
@@ -34,7 +34,7 @@ {{model.target.name}}
-
+
Crop section
From 6d15a2fce3ba8e0585b5b6df45d1a274daf76a46 Mon Sep 17 00:00:00 2001 From: Lars-Erik Aabech Date: Thu, 17 Sep 2020 11:32:52 +0200 Subject: [PATCH 06/19] Eliminates error/no-preview when grid media picker have no crop set (#8620) (cherry picked from commit deb03e4d82e48674c6d8bdc7926e820e17454d9e) --- .../mediapicker/overlays/mediacropdetails.controller.js | 5 +++++ .../mediapicker/overlays/mediacropdetails.html | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js index d9ea5a7a09..030200e1e6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js @@ -6,6 +6,7 @@ vm.submit = submit; vm.close = close; + vm.cropSet = cropSet; if (!$scope.model.target.coordinates && !$scope.model.target.focalPoint) { $scope.model.target.focalPoint = { left: .5, top: .5 }; @@ -56,4 +57,8 @@ } } + function cropSet() { + var model = $scope.model; + return (model.cropSize || {}).width && model.target.thumbnail; + } }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html index 3814ac851e..cda42043c1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html @@ -26,7 +26,7 @@
-
+
Preview
@@ -34,7 +34,7 @@ {{model.target.name}}
-
+
Crop section
From 6b0539fefcf2f7e103a38638c0328f2a418cb520 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 17 Sep 2020 12:19:07 +0200 Subject: [PATCH 07/19] Set version to RC --- src/SolutionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 3f512bc65a..26496aa9e6 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -19,4 +19,4 @@ using System.Resources; // these are FYI and changed automatically [assembly: AssemblyFileVersion("8.8.0")] -[assembly: AssemblyInformationalVersion("8.8.0")] +[assembly: AssemblyInformationalVersion("8.8.0-rc")] From 0506c8c555e5398591afd84277e0f48a69673415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 17 Sep 2020 14:59:12 +0200 Subject: [PATCH 08/19] defineIcon method --- .../src/common/services/iconhelper.service.js | 53 +++++++++---------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js index 0d0135fff8..f714cba4ad 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js @@ -31,7 +31,7 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { { oldIcon: ".sprToPublish", newIcon: "mail-forward" }, { oldIcon: ".sprTranslate", newIcon: "comments" }, { oldIcon: ".sprUpdate", newIcon: "save" }, - + { oldIcon: ".sprTreeSettingDomain", newIcon: "icon-home" }, { oldIcon: ".sprTreeDoc", newIcon: "icon-document" }, { oldIcon: ".sprTreeDoc2", newIcon: "icon-diploma-alt" }, @@ -39,21 +39,21 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { { oldIcon: ".sprTreeDoc4", newIcon: "icon-newspaper-alt" }, { oldIcon: ".sprTreeDoc5", newIcon: "icon-notepad-alt" }, - { oldIcon: ".sprTreeDocPic", newIcon: "icon-picture" }, + { oldIcon: ".sprTreeDocPic", newIcon: "icon-picture" }, { oldIcon: ".sprTreeFolder", newIcon: "icon-folder" }, { oldIcon: ".sprTreeFolder_o", newIcon: "icon-folder" }, { oldIcon: ".sprTreeMediaFile", newIcon: "icon-music" }, { oldIcon: ".sprTreeMediaMovie", newIcon: "icon-movie" }, { oldIcon: ".sprTreeMediaPhoto", newIcon: "icon-picture" }, - + { oldIcon: ".sprTreeMember", newIcon: "icon-user" }, { oldIcon: ".sprTreeMemberGroup", newIcon: "icon-users" }, { oldIcon: ".sprTreeMemberType", newIcon: "icon-users" }, - + { oldIcon: ".sprTreeNewsletter", newIcon: "icon-file-text-alt" }, { oldIcon: ".sprTreePackage", newIcon: "icon-box" }, { oldIcon: ".sprTreeRepository", newIcon: "icon-server-alt" }, - + { oldIcon: ".sprTreeSettingDataType", newIcon: "icon-autofill" }, // TODO: Something needs to be done with the old tree icons that are commented out. @@ -61,7 +61,7 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { { oldIcon: ".sprTreeSettingAgent", newIcon: "" }, { oldIcon: ".sprTreeSettingCss", newIcon: "" }, { oldIcon: ".sprTreeSettingCssItem", newIcon: "" }, - + { oldIcon: ".sprTreeSettingDataTypeChild", newIcon: "" }, { oldIcon: ".sprTreeSettingDomain", newIcon: "" }, { oldIcon: ".sprTreeSettingLanguage", newIcon: "" }, @@ -94,9 +94,9 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { var iconCache = []; var liveRequests = []; var allIconsRequested = false; - + return { - + /** Used by the create dialogs for content/media types to format the data so that the thumbnails are styled properly */ formatContentTypeThumbnails: function (contentTypes) { for (var i = 0; i < contentTypes.length; i++) { @@ -209,15 +209,11 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { ,'Failed to retrieve icon: ' + iconName) .then(icon => { if(icon) { - var trustedIcon = { - name: icon.Name, - svgString: $sce.trustAsHtml(icon.SvgString) - }; - this._cacheIcon(trustedIcon); + var trustedIcon = this.defineIcon(icon.name, icon.SvgString); - liveRequests = _.filter(liveRequests, iconRequestPath); + liveRequests = _.filter(liveRequests, iconRequestPath); - resolve(trustedIcon); + resolve(trustedIcon); } }) .catch(err => { @@ -240,15 +236,10 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { ,'Failed to retrieve icons') .then(icons => { icons.forEach(icon => { - var trustedIcon = { - name: icon.Name, - svgString: $sce.trustAsHtml(icon.SvgString) - }; - - this._cacheIcon(trustedIcon); + this.defineIcon(icon.Name, icon.SvgString); }); - resolve(iconCache); + resolve(iconCache); }) .catch(err => { console.warn(err); @@ -278,7 +269,7 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { console.warn("Can't read the css rules of: " + document.styleSheets[i].href, e); continue; } - + if (classes !== null) { for(var x=0;x x.name === name); + if(icon === undefined) { + icon = { + name: name, + svgString: $sce.trustAsHtml(svg) + }; + iconCache.push(icon); + } + return icon; }, /** Returns the cached icon or undefined */ From e2957bb715d797299d5cc65c8d073fd17bb15441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 17 Sep 2020 14:59:49 +0200 Subject: [PATCH 09/19] inject icons to iconHelper to avoid making requests to the icon controller --- .../Umbraco/Views/Default.cshtml | 286 +++++++++--------- 1 file changed, 148 insertions(+), 138 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml index 616763c06f..d0f0fd2cc8 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml @@ -1,138 +1,148 @@ -@using Umbraco.Core -@using ClientDependency.Core -@using ClientDependency.Core.Mvc -@using Umbraco.Core.Composing -@using Umbraco.Core.IO -@using Umbraco.Web -@using Umbraco.Core.Configuration - -@inherits WebViewPage - -@{ - var isDebug = false; - if (Request.RawUrl.IndexOf('?') >= 0) - { - var parsed = HttpUtility.ParseQueryString(Request.RawUrl.Split('?')[1]); - var attempt = parsed["umbDebug"].TryConvertTo(); - if (attempt && attempt.Result) - { - isDebug = true; - } - } - - Html - .RequiresCss("assets/css/umbraco.css", "Umbraco") - .RequiresCss("lib/bootstrap-social/bootstrap-social.css", "Umbraco") - .RequiresCss("lib/font-awesome/css/font-awesome.min.css", "Umbraco"); -} - - - - - - - - - - - - - - Umbraco - - @Html.RenderCssHere( - new BasicPath("Umbraco", IOHelper.ResolveUrl(SystemDirectories.Umbraco))) - - - - - -
- - - - - - - - - - - -
- - - - - - - - - - - - - @Html.BareMinimumServerVariablesScript(Url, Url.Action("ExternalLogin", "BackOffice", new { area = ViewData.GetUmbracoPath() }), Model.Features, Current.Configs.Global()) - - - - - - - @if (isDebug) - { - @Html.RenderProfiler() - } - - - +@using Umbraco.Core +@using ClientDependency.Core +@using ClientDependency.Core.Mvc +@using Umbraco.Core.Composing +@using Umbraco.Core.IO +@using Umbraco.Web +@using Umbraco.Core.Configuration + +@inherits WebViewPage + +@{ + var isDebug = false; + if (Request.RawUrl.IndexOf('?') >= 0) + { + var parsed = HttpUtility.ParseQueryString(Request.RawUrl.Split('?')[1]); + var attempt = parsed["umbDebug"].TryConvertTo(); + if (attempt && attempt.Result) + { + isDebug = true; + } + } + + Html + .RequiresCss("assets/css/umbraco.css", "Umbraco") + .RequiresCss("lib/bootstrap-social/bootstrap-social.css", "Umbraco") + .RequiresCss("lib/font-awesome/css/font-awesome.min.css", "Umbraco"); +} + + + + + + + + + + + + + + Umbraco + + @Html.RenderCssHere( + new BasicPath("Umbraco", IOHelper.ResolveUrl(SystemDirectories.Umbraco))) + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + @Html.BareMinimumServerVariablesScript(Url, Url.Action("ExternalLogin", "BackOffice", new { area = ViewData.GetUmbracoPath() }), Model.Features, Current.Configs.Global()) + + + + + + + @if (isDebug) + { + @Html.RenderProfiler() + } + + + From d7ab7d3d2eb3e70faff8462201cfa175cd528db0 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Fri, 18 Sep 2020 08:30:48 +0200 Subject: [PATCH 10/19] Removed test code Signed-off-by: Bjarke Berg --- .../Extensions/UmbracoCoreServiceCollectionExtensions.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index 8d75159ce9..44fb18a159 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -284,13 +284,6 @@ namespace Umbraco.Extensions factory = coreRuntime.Configure(container); - - services.Configure(hostingSettings => - { - hostingSettings.Debug = false; - }); - - return services; } From 525ca95acf7a11bc66087c095bf1a25839095f44 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 22 Sep 2020 08:01:04 +0200 Subject: [PATCH 11/19] uncomment SMTP info by default Signed-off-by: Bjarke Berg --- src/Umbraco.Web.UI.NetCore/appsettings.Development.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.NetCore/appsettings.Development.json b/src/Umbraco.Web.UI.NetCore/appsettings.Development.json index 9f81927bdc..13f4c95bbd 100644 --- a/src/Umbraco.Web.UI.NetCore/appsettings.Development.json +++ b/src/Umbraco.Web.UI.NetCore/appsettings.Development.json @@ -3,9 +3,9 @@ "CMS": { "Global":{ "Smtp": { - "From": "your@email.here", - "Host": "localhost", - "Port": "25" +// "From": "your@email.here", +// "Host": "localhost", +// "Port": "25" } }, "Hosting":{ From b327399cd2c637a715792dc1d40ac1e6253ae3eb Mon Sep 17 00:00:00 2001 From: Claus Date: Tue, 22 Sep 2020 08:11:58 +0200 Subject: [PATCH 12/19] adding icon svg data from IconController. --- src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml | 8 ++------ src/Umbraco.Web/Editors/BackOfficeModel.cs | 6 ++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml index d0f0fd2cc8..666f7a64f5 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml @@ -4,7 +4,6 @@ @using Umbraco.Core.Composing @using Umbraco.Core.IO @using Umbraco.Web -@using Umbraco.Core.Configuration @inherits WebViewPage @@ -122,12 +121,9 @@ @Html.AngularValueTinyMceAssets() app.run(["iconHelper", function (iconHelper) { - @* We inject icons to the icon helper(service), since icons can only be loaded if user is authorized. By injecting these to the service they will not be requested as they will become cached. *@ - - iconHelper.defineIcon("icon-check", ''); - iconHelper.defineIcon("icon-delete", ''); - + iconHelper.defineIcon("icon-check", '@Html.Raw(Model.IconCheckData)'); + iconHelper.defineIcon("icon-delete", '@Html.Raw(Model.IconDeleteData)'); }]); //required for the noscript trick diff --git a/src/Umbraco.Web/Editors/BackOfficeModel.cs b/src/Umbraco.Web/Editors/BackOfficeModel.cs index 9833121301..b11ea6a5d1 100644 --- a/src/Umbraco.Web/Editors/BackOfficeModel.cs +++ b/src/Umbraco.Web/Editors/BackOfficeModel.cs @@ -6,13 +6,19 @@ namespace Umbraco.Web.Editors public class BackOfficeModel { + private IconController IconController { get; } public BackOfficeModel(UmbracoFeatures features, IGlobalSettings globalSettings) { Features = features; GlobalSettings = globalSettings; + IconController = new IconController(); + IconCheckData = IconController.GetIcon("icon-check")?.SvgString; + IconDeleteData = IconController.GetIcon("icon-delete")?.SvgString; } public UmbracoFeatures Features { get; } public IGlobalSettings GlobalSettings { get; } + public string IconCheckData { get; } + public string IconDeleteData { get; } } } From 6e56b16342571935c38f06fcb131694265ea295b Mon Sep 17 00:00:00 2001 From: Claus Date: Tue, 22 Sep 2020 08:57:48 +0200 Subject: [PATCH 13/19] adding IconService --- src/Umbraco.Web/Composing/Current.cs | 3 + .../Editors/BackOfficeController.cs | 23 +++- src/Umbraco.Web/Editors/BackOfficeModel.cs | 8 +- src/Umbraco.Web/Editors/IconController.cs | 81 ++------------ src/Umbraco.Web/Runtime/WebInitialComposer.cs | 2 +- src/Umbraco.Web/Services/IIconService.cs | 29 +++++ src/Umbraco.Web/Services/IconService.cs | 100 ++++++++++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 2 + 8 files changed, 166 insertions(+), 82 deletions(-) create mode 100644 src/Umbraco.Web/Services/IIconService.cs create mode 100644 src/Umbraco.Web/Services/IconService.cs diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 2419eaa6d4..14898d0c02 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -146,6 +146,9 @@ namespace Umbraco.Web.Composing public static ISectionService SectionService => Factory.GetInstance(); + public static IIconService IconService + => Factory.GetInstance(); + #endregion #region Web Constants diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index e77a1b70f2..3e16dd9692 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -15,7 +14,6 @@ using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; -using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; using Umbraco.Core.Models.Identity; @@ -26,6 +24,7 @@ using Umbraco.Web.Composing; using Umbraco.Web.Features; using Umbraco.Web.JavaScript; using Umbraco.Web.Security; +using Umbraco.Web.Services; using Constants = Umbraco.Core.Constants; using JArray = Newtonsoft.Json.Linq.JArray; @@ -42,6 +41,7 @@ namespace Umbraco.Web.Editors private readonly ManifestParser _manifestParser; private readonly UmbracoFeatures _features; private readonly IRuntimeState _runtimeState; + private readonly IIconService _iconService; private BackOfficeUserManager _userManager; private BackOfficeSignInManager _signInManager; @@ -51,6 +51,16 @@ namespace Umbraco.Web.Editors _manifestParser = manifestParser; _features = features; _runtimeState = runtimeState; + _iconService = Current.IconService; + } + + public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper, IIconService iconService) + : base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger, umbracoHelper) + { + _manifestParser = manifestParser; + _features = features; + _runtimeState = runtimeState; + _iconService = iconService; } protected BackOfficeSignInManager SignInManager => _signInManager ?? (_signInManager = OwinContext.GetBackOfficeSignInManager()); @@ -65,9 +75,14 @@ namespace Umbraco.Web.Editors /// public async Task Default() { + var backofficeModel = new BackOfficeModel(_features, GlobalSettings) + { + IconCheckData = _iconService.GetIcon("icon-check")?.SvgString, + IconDeleteData = _iconService.GetIcon("icon-delete")?.SvgString + }; return await RenderDefaultOrProcessExternalLoginAsync( - () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", new BackOfficeModel(_features, GlobalSettings)), - () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", new BackOfficeModel(_features, GlobalSettings))); + () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", backofficeModel), + () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", backofficeModel)); } [HttpGet] diff --git a/src/Umbraco.Web/Editors/BackOfficeModel.cs b/src/Umbraco.Web/Editors/BackOfficeModel.cs index b11ea6a5d1..ba85a64b42 100644 --- a/src/Umbraco.Web/Editors/BackOfficeModel.cs +++ b/src/Umbraco.Web/Editors/BackOfficeModel.cs @@ -6,19 +6,15 @@ namespace Umbraco.Web.Editors public class BackOfficeModel { - private IconController IconController { get; } public BackOfficeModel(UmbracoFeatures features, IGlobalSettings globalSettings) { Features = features; GlobalSettings = globalSettings; - IconController = new IconController(); - IconCheckData = IconController.GetIcon("icon-check")?.SvgString; - IconDeleteData = IconController.GetIcon("icon-delete")?.SvgString; } public UmbracoFeatures Features { get; } public IGlobalSettings GlobalSettings { get; } - public string IconCheckData { get; } - public string IconDeleteData { get; } + public string IconCheckData { get; set; } + public string IconDeleteData { get; set; } } } diff --git a/src/Umbraco.Web/Editors/IconController.cs b/src/Umbraco.Web/Editors/IconController.cs index 72af2194ae..2554f633df 100644 --- a/src/Umbraco.Web/Editors/IconController.cs +++ b/src/Umbraco.Web/Editors/IconController.cs @@ -1,21 +1,20 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; -using Umbraco.Core.Logging; using Umbraco.Web.Models; -using System.IO; -using Umbraco.Core; -using Umbraco.Core.IO; -using Ganss.XSS; -using Umbraco.Core.Cache; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { [PluginController("UmbracoApi")] public class IconController : UmbracoAuthorizedApiController { + private readonly IIconService _iconService; + + public IconController(IIconService iconService) + { + _iconService = iconService; + } /// /// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path @@ -24,21 +23,7 @@ namespace Umbraco.Web.Editors /// public IconModel GetIcon(string iconName) { - return string.IsNullOrWhiteSpace(iconName) - ? null - : CreateIconModel(iconName.StripFileExtension(), IOHelper.MapPath($"{GlobalSettings.IconsPath}/{iconName}.svg")); - } - - /// - /// Gets an IconModel using values from a FileInfo model - /// - /// - /// - public IconModel GetIcon(FileInfo fileInfo) - { - return fileInfo == null || string.IsNullOrWhiteSpace(fileInfo.Name) - ? null - : CreateIconModel(fileInfo.Name.StripFileExtension(), fileInfo.FullName); + return _iconService.GetIcon(iconName); } /// @@ -47,53 +32,7 @@ namespace Umbraco.Web.Editors /// public List GetAllIcons() { - var icons = new List(); - var directory = new DirectoryInfo(IOHelper.MapPath($"{GlobalSettings.IconsPath}/")); - var iconNames = directory.GetFiles("*.svg"); - - iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo => - { - var icon = GetIcon(iconInfo); - - if (icon != null) - { - icons.Add(icon); - } - }); - - return icons; - } - - /// - /// Gets an IconModel containing the icon name and SvgString - /// - /// - /// - /// - private IconModel CreateIconModel(string iconName, string iconPath) - { - var sanitizer = new HtmlSanitizer(); - sanitizer.AllowedAttributes.UnionWith(Core.Constants.SvgSanitizer.Attributes); - sanitizer.AllowedCssProperties.UnionWith(Core.Constants.SvgSanitizer.Attributes); - sanitizer.AllowedTags.UnionWith(Core.Constants.SvgSanitizer.Tags); - - try - { - var svgContent = File.ReadAllText(iconPath); - var sanitizedString = sanitizer.Sanitize(svgContent); - - var svg = new IconModel - { - Name = iconName, - SvgString = sanitizedString - }; - - return svg; - } - catch - { - return null; - } + return _iconService.GetAllIcons(); } } } diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 135d54560b..112910930e 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -137,8 +137,8 @@ namespace Umbraco.Web.Runtime composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(); - composition.RegisterUnique(); + composition.RegisterUnique(); composition.RegisterUnique(factory => ExamineManager.Instance); diff --git a/src/Umbraco.Web/Services/IIconService.cs b/src/Umbraco.Web/Services/IIconService.cs new file mode 100644 index 0000000000..cdd75f8d4b --- /dev/null +++ b/src/Umbraco.Web/Services/IIconService.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.IO; +using Umbraco.Web.Models; + +namespace Umbraco.Web.Services +{ + public interface IIconService + { + /// + /// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path + /// + /// + /// + IconModel GetIcon(string iconName); + + /// + /// Gets an IconModel using values from a FileInfo model + /// + /// + /// + IconModel GetIcon(FileInfo fileInfo); + + /// + /// Gets a list of all svg icons found at at the global icons path. + /// + /// + List GetAllIcons(); + } +} diff --git a/src/Umbraco.Web/Services/IconService.cs b/src/Umbraco.Web/Services/IconService.cs new file mode 100644 index 0000000000..4093f69174 --- /dev/null +++ b/src/Umbraco.Web/Services/IconService.cs @@ -0,0 +1,100 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Ganss.XSS; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; +using Umbraco.Web.Models; + +namespace Umbraco.Web.Services +{ + internal class IconService : IIconService + { + private readonly IGlobalSettings _globalSettings; + + public IconService(IGlobalSettings globalSettings) + { + _globalSettings = globalSettings; + } + + /// + /// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path + /// + /// + /// + public IconModel GetIcon(string iconName) + { + return string.IsNullOrWhiteSpace(iconName) + ? null + : CreateIconModel(iconName.StripFileExtension(), IOHelper.MapPath($"{_globalSettings.IconsPath}/{iconName}.svg")); + } + + /// + /// Gets an IconModel using values from a FileInfo model + /// + /// + /// + public IconModel GetIcon(FileInfo fileInfo) + { + return fileInfo == null || string.IsNullOrWhiteSpace(fileInfo.Name) + ? null + : CreateIconModel(fileInfo.Name.StripFileExtension(), fileInfo.FullName); + } + + /// + /// Gets a list of all svg icons found at at the global icons path. + /// + /// + public List GetAllIcons() + { + var icons = new List(); + var directory = new DirectoryInfo(IOHelper.MapPath($"{_globalSettings.IconsPath}/")); + var iconNames = directory.GetFiles("*.svg"); + + iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo => + { + var icon = GetIcon(iconInfo); + + if (icon != null) + { + icons.Add(icon); + } + }); + + return icons; + } + + /// + /// Gets an IconModel containing the icon name and SvgString + /// + /// + /// + /// + private IconModel CreateIconModel(string iconName, string iconPath) + { + var sanitizer = new HtmlSanitizer(); + sanitizer.AllowedAttributes.UnionWith(Core.Constants.SvgSanitizer.Attributes); + sanitizer.AllowedCssProperties.UnionWith(Core.Constants.SvgSanitizer.Attributes); + sanitizer.AllowedTags.UnionWith(Core.Constants.SvgSanitizer.Tags); + + try + { + var svgContent = File.ReadAllText(iconPath); + var sanitizedString = sanitizer.Sanitize(svgContent); + + var svg = new IconModel + { + Name = iconName, + SvgString = sanitizedString + }; + + return svg; + } + catch + { + return null; + } + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 33051671ee..2efc6fdd56 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -284,10 +284,12 @@ + + From ccc0e82579617f7706dd1561ae6b211bcda97de0 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 22 Sep 2020 08:58:16 +0200 Subject: [PATCH 14/19] #8919 - Avoid having fat controller and do not new up a controller in a model --- src/Umbraco.Web/Composing/Current.cs | 3 + .../Editors/BackOfficeController.cs | 48 +++++++++- src/Umbraco.Web/Editors/BackOfficeModel.cs | 22 +++-- .../Editors/BackOfficePreviewModel.cs | 22 ++++- src/Umbraco.Web/Editors/IconController.cs | 83 +++------------- src/Umbraco.Web/Editors/PreviewController.cs | 23 ++++- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 1 + src/Umbraco.Web/Services/IIconService.cs | 21 +++++ src/Umbraco.Web/Services/IconService.cs | 94 +++++++++++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 4 +- 10 files changed, 234 insertions(+), 87 deletions(-) create mode 100644 src/Umbraco.Web/Services/IIconService.cs create mode 100644 src/Umbraco.Web/Services/IconService.cs diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 2419eaa6d4..14898d0c02 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -146,6 +146,9 @@ namespace Umbraco.Web.Composing public static ISectionService SectionService => Factory.GetInstance(); + public static IIconService IconService + => Factory.GetInstance(); + #endregion #region Web Constants diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index e77a1b70f2..c9106cffb5 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -26,6 +26,7 @@ using Umbraco.Web.Composing; using Umbraco.Web.Features; using Umbraco.Web.JavaScript; using Umbraco.Web.Security; +using Umbraco.Web.Services; using Constants = Umbraco.Core.Constants; using JArray = Newtonsoft.Json.Linq.JArray; @@ -42,15 +43,54 @@ namespace Umbraco.Web.Editors private readonly ManifestParser _manifestParser; private readonly UmbracoFeatures _features; private readonly IRuntimeState _runtimeState; + private readonly IIconService _iconService; private BackOfficeUserManager _userManager; private BackOfficeSignInManager _signInManager; - public BackOfficeController(ManifestParser manifestParser, UmbracoFeatures features, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) + [Obsolete("Use the constructor that injects IIconService.")] + public BackOfficeController( + ManifestParser manifestParser, + UmbracoFeatures features, + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger profilingLogger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper) + : this(manifestParser, + features, + globalSettings, + umbracoContextAccessor, + services, + appCaches, + profilingLogger, + runtimeState, + umbracoHelper, + Current.IconService) + { + _manifestParser = manifestParser; + _features = features; + _runtimeState = runtimeState; + } + + public BackOfficeController( + ManifestParser manifestParser, + UmbracoFeatures features, + IGlobalSettings globalSettings, + IUmbracoContextAccessor umbracoContextAccessor, + ServiceContext services, + AppCaches appCaches, + IProfilingLogger profilingLogger, + IRuntimeState runtimeState, + UmbracoHelper umbracoHelper, + IIconService iconService) : base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger, umbracoHelper) { _manifestParser = manifestParser; _features = features; _runtimeState = runtimeState; + _iconService = iconService; } protected BackOfficeSignInManager SignInManager => _signInManager ?? (_signInManager = OwinContext.GetBackOfficeSignInManager()); @@ -66,8 +106,8 @@ namespace Umbraco.Web.Editors public async Task Default() { return await RenderDefaultOrProcessExternalLoginAsync( - () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", new BackOfficeModel(_features, GlobalSettings)), - () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", new BackOfficeModel(_features, GlobalSettings))); + () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", new BackOfficeModel(_features, GlobalSettings, _iconService)), + () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", new BackOfficeModel(_features, GlobalSettings, _iconService))); } [HttpGet] @@ -150,7 +190,7 @@ namespace Umbraco.Web.Editors { return await RenderDefaultOrProcessExternalLoginAsync( //The default view to render when there is no external login info or errors - () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/AuthorizeUpgrade.cshtml", new BackOfficeModel(_features, GlobalSettings)), + () => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/AuthorizeUpgrade.cshtml", new BackOfficeModel(_features, GlobalSettings, _iconService)), //The ActionResult to perform if external login is successful () => Redirect("/")); } diff --git a/src/Umbraco.Web/Editors/BackOfficeModel.cs b/src/Umbraco.Web/Editors/BackOfficeModel.cs index b11ea6a5d1..b620d893e3 100644 --- a/src/Umbraco.Web/Editors/BackOfficeModel.cs +++ b/src/Umbraco.Web/Editors/BackOfficeModel.cs @@ -1,21 +1,29 @@ -using Umbraco.Core.Configuration; +using System; +using Umbraco.Core.Configuration; +using Umbraco.Web.Composing; using Umbraco.Web.Features; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { public class BackOfficeModel { - private IconController IconController { get; } - public BackOfficeModel(UmbracoFeatures features, IGlobalSettings globalSettings) + + + [Obsolete("Use the overload that injects IIconService.")] + public BackOfficeModel(UmbracoFeatures features, IGlobalSettings globalSettings) : this(features, globalSettings, Current.IconService) + { + + } + public BackOfficeModel(UmbracoFeatures features, IGlobalSettings globalSettings, IIconService iconService) { Features = features; GlobalSettings = globalSettings; - IconController = new IconController(); - IconCheckData = IconController.GetIcon("icon-check")?.SvgString; - IconDeleteData = IconController.GetIcon("icon-delete")?.SvgString; + IconCheckData = iconService.GetIcon("icon-check")?.SvgString; + IconDeleteData = iconService.GetIcon("icon-delete")?.SvgString; } - + public UmbracoFeatures Features { get; } public IGlobalSettings GlobalSettings { get; } public string IconCheckData { get; } diff --git a/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs b/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs index b66e432699..7239bba8f7 100644 --- a/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs +++ b/src/Umbraco.Web/Editors/BackOfficePreviewModel.cs @@ -1,7 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; + using Umbraco.Core.Configuration; using Umbraco.Core.Models; +using Umbraco.Web.Composing; using Umbraco.Web.Features; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { @@ -10,7 +14,21 @@ namespace Umbraco.Web.Editors private readonly UmbracoFeatures _features; public IEnumerable Languages { get; } - public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings, IEnumerable languages) : base(features, globalSettings) + [Obsolete("Use the overload that injects IIconService.")] + public BackOfficePreviewModel( + UmbracoFeatures features, + IGlobalSettings globalSettings, + IEnumerable languages) + : this(features, globalSettings, languages, Current.IconService) + { + } + + public BackOfficePreviewModel( + UmbracoFeatures features, + IGlobalSettings globalSettings, + IEnumerable languages, + IIconService iconService) + : base(features, globalSettings, iconService) { _features = features; Languages = languages; diff --git a/src/Umbraco.Web/Editors/IconController.cs b/src/Umbraco.Web/Editors/IconController.cs index 72af2194ae..b45b0948c8 100644 --- a/src/Umbraco.Web/Editors/IconController.cs +++ b/src/Umbraco.Web/Editors/IconController.cs @@ -1,21 +1,20 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; -using Umbraco.Core.Logging; using Umbraco.Web.Models; -using System.IO; -using Umbraco.Core; -using Umbraco.Core.IO; -using Ganss.XSS; -using Umbraco.Core.Cache; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { [PluginController("UmbracoApi")] public class IconController : UmbracoAuthorizedApiController { + private readonly IIconService _iconService; + + public IconController(IIconService iconService) + { + _iconService = iconService; + } /// /// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path @@ -24,76 +23,16 @@ namespace Umbraco.Web.Editors /// public IconModel GetIcon(string iconName) { - return string.IsNullOrWhiteSpace(iconName) - ? null - : CreateIconModel(iconName.StripFileExtension(), IOHelper.MapPath($"{GlobalSettings.IconsPath}/{iconName}.svg")); - } - - /// - /// Gets an IconModel using values from a FileInfo model - /// - /// - /// - public IconModel GetIcon(FileInfo fileInfo) - { - return fileInfo == null || string.IsNullOrWhiteSpace(fileInfo.Name) - ? null - : CreateIconModel(fileInfo.Name.StripFileExtension(), fileInfo.FullName); + return _iconService.GetIcon(iconName); } /// /// Gets a list of all svg icons found at at the global icons path. /// /// - public List GetAllIcons() + public IList GetAllIcons() { - var icons = new List(); - var directory = new DirectoryInfo(IOHelper.MapPath($"{GlobalSettings.IconsPath}/")); - var iconNames = directory.GetFiles("*.svg"); - - iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo => - { - var icon = GetIcon(iconInfo); - - if (icon != null) - { - icons.Add(icon); - } - }); - - return icons; - } - - /// - /// Gets an IconModel containing the icon name and SvgString - /// - /// - /// - /// - private IconModel CreateIconModel(string iconName, string iconPath) - { - var sanitizer = new HtmlSanitizer(); - sanitizer.AllowedAttributes.UnionWith(Core.Constants.SvgSanitizer.Attributes); - sanitizer.AllowedCssProperties.UnionWith(Core.Constants.SvgSanitizer.Attributes); - sanitizer.AllowedTags.UnionWith(Core.Constants.SvgSanitizer.Tags); - - try - { - var svgContent = File.ReadAllText(iconPath); - var sanitizedString = sanitizer.Sanitize(svgContent); - - var svg = new IconModel - { - Name = iconName, - SvgString = sanitizedString - }; - - return svg; - } - catch - { - return null; - } + return _iconService.GetAllIcons(); } } } diff --git a/src/Umbraco.Web/Editors/PreviewController.cs b/src/Umbraco.Web/Editors/PreviewController.cs index c1848419dc..f148655acd 100644 --- a/src/Umbraco.Web/Editors/PreviewController.cs +++ b/src/Umbraco.Web/Editors/PreviewController.cs @@ -12,6 +12,7 @@ using Umbraco.Web.JavaScript; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; +using Umbraco.Web.Services; using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors @@ -24,19 +25,39 @@ namespace Umbraco.Web.Editors private readonly IPublishedSnapshotService _publishedSnapshotService; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly ILocalizationService _localizationService; + private readonly IIconService _iconService; + [Obsolete("Use the constructor that injects IIconService.")] public PreviewController( UmbracoFeatures features, IGlobalSettings globalSettings, IPublishedSnapshotService publishedSnapshotService, IUmbracoContextAccessor umbracoContextAccessor, ILocalizationService localizationService) + :this(features, + globalSettings, + publishedSnapshotService, + umbracoContextAccessor, + localizationService, + Current.IconService) + { + + } + + public PreviewController( + UmbracoFeatures features, + IGlobalSettings globalSettings, + IPublishedSnapshotService publishedSnapshotService, + IUmbracoContextAccessor umbracoContextAccessor, + ILocalizationService localizationService, + IIconService iconService) { _features = features; _globalSettings = globalSettings; _publishedSnapshotService = publishedSnapshotService; _umbracoContextAccessor = umbracoContextAccessor; _localizationService = localizationService; + _iconService = iconService; } [UmbracoAuthorize(redirectToUmbracoLogin: true)] @@ -45,7 +66,7 @@ namespace Umbraco.Web.Editors { var availableLanguages = _localizationService.GetAllLanguages(); - var model = new BackOfficePreviewModel(_features, _globalSettings, availableLanguages); + var model = new BackOfficePreviewModel(_features, _globalSettings, availableLanguages, _iconService); if (model.PreviewExtendedHeaderView.IsNullOrWhiteSpace() == false) { diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 135d54560b..d9a8ee37f2 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -139,6 +139,7 @@ namespace Umbraco.Web.Runtime composition.RegisterUnique(); composition.RegisterUnique(); + composition.RegisterUnique(); composition.RegisterUnique(factory => ExamineManager.Instance); diff --git a/src/Umbraco.Web/Services/IIconService.cs b/src/Umbraco.Web/Services/IIconService.cs new file mode 100644 index 0000000000..177921ceae --- /dev/null +++ b/src/Umbraco.Web/Services/IIconService.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using Umbraco.Web.Models; + +namespace Umbraco.Web.Services +{ + public interface IIconService + { + /// + /// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path + /// + /// + /// + IconModel GetIcon(string iconName); + + /// + /// Gets a list of all svg icons found at at the global icons path. + /// + /// + IList GetAllIcons(); + } +} diff --git a/src/Umbraco.Web/Services/IconService.cs b/src/Umbraco.Web/Services/IconService.cs new file mode 100644 index 0000000000..93389668b6 --- /dev/null +++ b/src/Umbraco.Web/Services/IconService.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Ganss.XSS; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; +using Umbraco.Web.Models; + +namespace Umbraco.Web.Services +{ + public class IconService : IIconService + { + private readonly IGlobalSettings _globalSettings; + + public IconService(IGlobalSettings globalSettings) + { + _globalSettings = globalSettings; + } + + + /// + public IList GetAllIcons() + { + var icons = new List(); + var directory = new DirectoryInfo(IOHelper.MapPath($"{_globalSettings.IconsPath}/")); + var iconNames = directory.GetFiles("*.svg"); + + iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo => + { + var icon = GetIcon(iconInfo); + + if (icon != null) + { + icons.Add(icon); + } + }); + + return icons; + } + + /// + public IconModel GetIcon(string iconName) + { + return string.IsNullOrWhiteSpace(iconName) + ? null + : CreateIconModel(iconName.StripFileExtension(), IOHelper.MapPath($"{_globalSettings.IconsPath}/{iconName}.svg")); + } + + /// + /// Gets an IconModel using values from a FileInfo model + /// + /// + /// + private IconModel GetIcon(FileInfo fileInfo) + { + return fileInfo == null || string.IsNullOrWhiteSpace(fileInfo.Name) + ? null + : CreateIconModel(fileInfo.Name.StripFileExtension(), fileInfo.FullName); + } + + /// + /// Gets an IconModel containing the icon name and SvgString + /// + /// + /// + /// + private IconModel CreateIconModel(string iconName, string iconPath) + { + var sanitizer = new HtmlSanitizer(); + sanitizer.AllowedAttributes.UnionWith(Core.Constants.SvgSanitizer.Attributes); + sanitizer.AllowedCssProperties.UnionWith(Core.Constants.SvgSanitizer.Attributes); + sanitizer.AllowedTags.UnionWith(Core.Constants.SvgSanitizer.Tags); + + try + { + var svgContent = File.ReadAllText(iconPath); + var sanitizedString = sanitizer.Sanitize(svgContent); + + var svg = new IconModel + { + Name = iconName, + SvgString = sanitizedString + }; + + return svg; + } + catch + { + return null; + } + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 33051671ee..ff67493aaa 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -238,8 +238,8 @@ - + @@ -284,10 +284,12 @@ + + From 96facc4d35ce13ebc3c7f43fe51d678494656779 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 22 Sep 2020 10:01:00 +0200 Subject: [PATCH 15/19] Netcore: Introduce BackofficeSecurityAccessor (#8871) * Introduced IWebSecurityAccessor Signed-off-by: Bjarke Berg * Fixed tests Signed-off-by: Bjarke Berg * Renamed WebSecurity to BackofficeSecurity and all related names * Fixes typos Co-authored-by: Elitsa Marinovska --- .../HybridBackofficeSecurityAccessor.cs | 30 ++++++++++ .../IBackofficeSecurityFactory.cs | 15 +++++ src/Umbraco.Core/IUmbracoContext.cs | 4 +- ...IWebSecurity.cs => IBackofficeSecurity.cs} | 2 +- .../Security/IBackofficeSecurityAccessor.cs | 9 +++ .../InstallSteps/StarterKitDownloadStep.cs | 11 ++-- .../InstallSteps/StarterKitInstallStep.cs | 9 +-- .../Mapping/MemberTabsAndPropertiesMapper.cs | 16 +++-- .../UmbracoTestServerTestBase.cs | 2 + .../Testing/UmbracoIntegrationTest.cs | 1 + .../Filters/ContentModelValidatorTests.cs | 7 ++- .../AppendUserModifiedHeaderAttributeTests.cs | 8 +-- ...terAllowedOutgoingContentAttributeTests.cs | 11 ++-- .../Controllers/SurfaceControllerTests.cs | 20 ++++--- .../PublishedContentCacheTests.cs | 2 +- .../PublishedContentSnapshotTestBase.cs | 2 +- .../Scoping/ScopedNuCacheTests.cs | 2 +- .../TestControllerActivatorBase.cs | 10 ++-- .../TestHelpers/TestWithDatabaseBase.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- .../Web/Mvc/UmbracoViewPageTests.cs | 2 +- .../Web/WebExtensionMethodTests.cs | 6 +- .../Controllers/AuthenticationController.cs | 15 ++--- .../Controllers/BackOfficeController.cs | 11 ++-- .../Controllers/ContentController.cs | 60 +++++++++---------- .../Controllers/ContentTypeController.cs | 17 +++--- .../Controllers/CurrentUserController.cs | 43 ++++++------- .../Controllers/DictionaryController.cs | 15 ++--- .../Controllers/EntityController.cs | 17 +++--- .../Controllers/LogController.cs | 9 +-- .../Controllers/MacrosController.cs | 11 ++-- .../Controllers/MediaController.cs | 31 +++++----- .../Controllers/MediaTypeController.cs | 15 ++--- .../Controllers/MemberController.cs | 14 ++--- .../Controllers/MemberTypeController.cs | 11 ++-- .../Controllers/PackageController.cs | 9 +-- .../Controllers/PackageInstallController.cs | 17 +++--- .../Controllers/PreviewController.cs | 11 ++-- .../RedirectUrlManagementController.cs | 14 +++-- .../Controllers/SectionController.cs | 15 ++--- .../Controllers/TourController.cs | 11 ++-- .../Controllers/UpdateCheckController.cs | 9 +-- .../Controllers/UserGroupsController.cs | 23 +++---- .../Controllers/UsersController.cs | 28 +++++---- .../Filters/AdminUsersAuthorizeAttribute.cs | 9 +-- .../AppendUserModifiedHeaderAttribute.cs | 4 +- .../Filters/ContentModelValidator.cs | 10 ++-- .../Filters/ContentSaveModelValidator.cs | 4 +- .../Filters/ContentSaveValidationAttribute.cs | 18 +++--- ...EnsureUserPermissionForContentAttribute.cs | 26 ++++---- .../EnsureUserPermissionForMediaAttribute.cs | 19 +++--- .../FilterAllowedOutgoingContentAttribute.cs | 5 +- .../FilterAllowedOutgoingMediaAttribute.cs | 8 +-- .../IsCurrentUserModelFilterAttribute.cs | 9 +-- .../MediaItemSaveValidationAttribute.cs | 11 ++-- .../Filters/MediaSaveModelValidator.cs | 4 +- .../Filters/MemberSaveModelValidator.cs | 6 +- .../Filters/MemberSaveValidationAttribute.cs | 9 +-- .../OutgoingEditorModelEventAttribute.cs | 9 +-- .../UmbracoApplicationAuthorizeAttribute.cs | 15 ++--- .../Filters/UmbracoTreeAuthorizeAttribute.cs | 17 +++--- .../UserGroupAuthorizationAttribute.cs | 9 +-- .../Trees/ApplicationTreeController.cs | 3 +- .../Trees/ContentTreeController.cs | 15 ++--- .../Trees/ContentTreeControllerBase.cs | 24 ++++---- .../Trees/MediaTreeController.cs | 13 ++-- .../Trees/MemberTreeController.cs | 9 +-- .../Install/InstallController.cs | 9 +-- .../Middleware/UmbracoRequestMiddleware.cs | 11 +++- .../Runtime/AspNetCoreComposer.cs | 3 +- .../{WebSecurity.cs => BackofficeSecurity.cs} | 5 +- .../Security/BackofficeSecurityFactory.cs | 43 +++++++++++++ .../UmbracoContext/UmbracoContext.cs | 10 ++-- .../UmbracoContext/UmbracoContextFactory.cs | 9 +-- .../Mvc/UmbracoAuthorizeAttribute.cs | 13 ++-- src/Umbraco.Web/Mvc/UmbracoController.cs | 2 +- .../{WebSecurity.cs => BackofficeSecurity.cs} | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- src/Umbraco.Web/UmbracoContext.cs | 10 ++-- src/Umbraco.Web/UmbracoContextFactory.cs | 2 +- src/Umbraco.Web/UmbracoHttpHandler.cs | 2 +- src/Umbraco.Web/UmbracoWebService.cs | 2 +- .../WebApi/UmbracoApiControllerBase.cs | 2 +- .../WebApi/UmbracoAuthorizeAttribute.cs | 13 ++-- 84 files changed, 571 insertions(+), 404 deletions(-) create mode 100644 src/Umbraco.Core/HybridBackofficeSecurityAccessor.cs create mode 100644 src/Umbraco.Core/IBackofficeSecurityFactory.cs rename src/Umbraco.Core/Security/{IWebSecurity.cs => IBackofficeSecurity.cs} (97%) create mode 100644 src/Umbraco.Core/Security/IBackofficeSecurityAccessor.cs rename src/Umbraco.Web.Common/Security/{WebSecurity.cs => BackofficeSecurity.cs} (98%) create mode 100644 src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs rename src/Umbraco.Web/Security/{WebSecurity.cs => BackofficeSecurity.cs} (95%) diff --git a/src/Umbraco.Core/HybridBackofficeSecurityAccessor.cs b/src/Umbraco.Core/HybridBackofficeSecurityAccessor.cs new file mode 100644 index 0000000000..a953ed8b82 --- /dev/null +++ b/src/Umbraco.Core/HybridBackofficeSecurityAccessor.cs @@ -0,0 +1,30 @@ +using Umbraco.Core.Cache; +using Umbraco.Core.Security; +using Umbraco.Web; +using Umbraco.Web.Security; + +namespace Umbraco.Core +{ + + public class HybridBackofficeSecurityAccessor : HybridAccessorBase, IBackofficeSecurityAccessor + { + /// + /// Initializes a new instance of the class. + /// + public HybridBackofficeSecurityAccessor(IRequestCache requestCache) + : base(requestCache) + { } + + /// + protected override string ItemKey => "Umbraco.Web.HybridBackofficeSecurityAccessor"; + + /// + /// Gets or sets the object. + /// + public IBackofficeSecurity BackofficeSecurity + { + get => Value; + set => Value = value; + } + } +} diff --git a/src/Umbraco.Core/IBackofficeSecurityFactory.cs b/src/Umbraco.Core/IBackofficeSecurityFactory.cs new file mode 100644 index 0000000000..9f8f791e4c --- /dev/null +++ b/src/Umbraco.Core/IBackofficeSecurityFactory.cs @@ -0,0 +1,15 @@ +using Umbraco.Web.Security; + +namespace Umbraco.Core +{ + /// + /// Creates and manages instances. + /// + public interface IBackofficeSecurityFactory + { + /// + /// Ensures that a current exists. + /// + void EnsureBackofficeSecurity(); + } +} diff --git a/src/Umbraco.Core/IUmbracoContext.cs b/src/Umbraco.Core/IUmbracoContext.cs index 66b3dc3965..03fb305fb6 100644 --- a/src/Umbraco.Core/IUmbracoContext.cs +++ b/src/Umbraco.Core/IUmbracoContext.cs @@ -16,9 +16,9 @@ namespace Umbraco.Web DateTime ObjectCreated { get; } /// - /// Gets the WebSecurity class + /// Gets the BackofficeSecurity class /// - IWebSecurity Security { get; } + IBackofficeSecurity Security { get; } /// /// Gets the uri that is handled by ASP.NET after server-side rewriting took place. diff --git a/src/Umbraco.Core/Security/IWebSecurity.cs b/src/Umbraco.Core/Security/IBackofficeSecurity.cs similarity index 97% rename from src/Umbraco.Core/Security/IWebSecurity.cs rename to src/Umbraco.Core/Security/IBackofficeSecurity.cs index 594f6d96ea..3a0e0baa1d 100644 --- a/src/Umbraco.Core/Security/IWebSecurity.cs +++ b/src/Umbraco.Core/Security/IBackofficeSecurity.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Membership; namespace Umbraco.Web.Security { - public interface IWebSecurity + public interface IBackofficeSecurity { /// /// Gets the current user. diff --git a/src/Umbraco.Core/Security/IBackofficeSecurityAccessor.cs b/src/Umbraco.Core/Security/IBackofficeSecurityAccessor.cs new file mode 100644 index 0000000000..d3cea99f9f --- /dev/null +++ b/src/Umbraco.Core/Security/IBackofficeSecurityAccessor.cs @@ -0,0 +1,9 @@ +using Umbraco.Web.Security; + +namespace Umbraco.Core.Security +{ + public interface IBackofficeSecurityAccessor + { + IBackofficeSecurity BackofficeSecurity { get; set; } + } +} diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitDownloadStep.cs index 24133d3be1..d060db2c43 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitDownloadStep.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Umbraco.Core.Services; using Umbraco.Core.Configuration; using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Security; using Umbraco.Net; using Umbraco.Web.Install.Models; using Umbraco.Web.Security; @@ -17,16 +18,16 @@ namespace Umbraco.Web.Install.InstallSteps internal class StarterKitDownloadStep : InstallSetupStep { private readonly InstallHelper _installHelper; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IUmbracoVersion _umbracoVersion; private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime; private readonly IContentService _contentService; private readonly IPackagingService _packageService; - public StarterKitDownloadStep(IContentService contentService, IPackagingService packageService, InstallHelper installHelper, IWebSecurity webSecurity, IUmbracoVersion umbracoVersion, IUmbracoApplicationLifetime umbracoApplicationLifetime) + public StarterKitDownloadStep(IContentService contentService, IPackagingService packageService, InstallHelper installHelper, IBackofficeSecurityAccessor backofficeSecurityAccessor, IUmbracoVersion umbracoVersion, IUmbracoApplicationLifetime umbracoApplicationLifetime) { _installHelper = installHelper; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _umbracoVersion = umbracoVersion; _umbracoApplicationLifetime = umbracoApplicationLifetime; _contentService = contentService; @@ -67,7 +68,7 @@ namespace Umbraco.Web.Install.InstallSteps private async Task<(string packageFile, int packageId)> DownloadPackageFilesAsync(Guid kitGuid) { //Go get the package file from the package repo - var packageFile = await _packageService.FetchPackageFileAsync(kitGuid, _umbracoVersion.Current, _webSecurity.GetUserId().ResultOr(0)); + var packageFile = await _packageService.FetchPackageFileAsync(kitGuid, _umbracoVersion.Current, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); if (packageFile == null) throw new InvalidOperationException("Could not fetch package file " + kitGuid); //add an entry to the installedPackages.config @@ -77,7 +78,7 @@ namespace Umbraco.Web.Install.InstallSteps _packageService.SaveInstalledPackage(packageDefinition); - _packageService.InstallCompiledPackageFiles(packageDefinition, packageFile, _webSecurity.GetUserId().ResultOr(-1)); + _packageService.InstallCompiledPackageFiles(packageDefinition, packageFile, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(-1)); return (compiledPackage.PackageFile.Name, packageDefinition.Id); } diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs index daf8255132..0f2394dcf4 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/StarterKitInstallStep.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Umbraco.Core.Security; using Umbraco.Net; using Umbraco.Core.Services; using Umbraco.Web.Install.Models; @@ -15,13 +16,13 @@ namespace Umbraco.Web.Install.InstallSteps internal class StarterKitInstallStep : InstallSetupStep { private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IPackagingService _packagingService; - public StarterKitInstallStep(IUmbracoApplicationLifetime umbracoApplicationLifetime, IWebSecurity webSecurity, IPackagingService packagingService) + public StarterKitInstallStep(IUmbracoApplicationLifetime umbracoApplicationLifetime, IBackofficeSecurityAccessor backofficeSecurityAccessor, IPackagingService packagingService) { _umbracoApplicationLifetime = umbracoApplicationLifetime; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _packagingService = packagingService; } @@ -48,7 +49,7 @@ namespace Umbraco.Web.Install.InstallSteps var packageFile = new FileInfo(definition.PackagePath); - _packagingService.InstallCompiledPackageData(definition, packageFile, _webSecurity.GetUserId().ResultOr(-1)); + _packagingService.InstallCompiledPackageData(definition, packageFile, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(-1)); } public override bool RequiresExecution(object model) diff --git a/src/Umbraco.Infrastructure/Models/Mapping/MemberTabsAndPropertiesMapper.cs b/src/Umbraco.Infrastructure/Models/Mapping/MemberTabsAndPropertiesMapper.cs index b281e18b73..abc32fc008 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/MemberTabsAndPropertiesMapper.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/MemberTabsAndPropertiesMapper.cs @@ -10,6 +10,10 @@ using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Web.Models.ContentEditing; +using Umbraco.Core.Dictionary; +using Umbraco.Core.Configuration; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Security; using Umbraco.Web.Security; namespace Umbraco.Web.Models.Mapping @@ -24,7 +28,7 @@ namespace Umbraco.Web.Models.Mapping /// public class MemberTabsAndPropertiesMapper : TabsAndPropertiesMapper { - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly ILocalizedTextService _localizedTextService; private readonly IMemberTypeService _memberTypeService; private readonly IMemberService _memberService; @@ -33,7 +37,7 @@ namespace Umbraco.Web.Models.Mapping private readonly PropertyEditorCollection _propertyEditorCollection; public MemberTabsAndPropertiesMapper(ICultureDictionary cultureDictionary, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILocalizedTextService localizedTextService, IMemberTypeService memberTypeService, IMemberService memberService, @@ -43,7 +47,7 @@ namespace Umbraco.Web.Models.Mapping PropertyEditorCollection propertyEditorCollection) : base(cultureDictionary, localizedTextService, contentTypeBaseServiceProvider) { - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); _memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService)); _memberService = memberService ?? throw new ArgumentNullException(nameof(memberService)); @@ -76,8 +80,8 @@ namespace Umbraco.Web.Models.Mapping isLockedOutProperty.Value = _localizedTextService.Localize("general/no"); } - if (_webSecurity.CurrentUser != null - && _webSecurity.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings))) + if (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser != null + && _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings))) { var memberTypeLink = string.Format("#/member/memberTypes/edit/{0}", source.ContentTypeId); @@ -191,7 +195,7 @@ namespace Umbraco.Web.Models.Mapping // check if this property is flagged as sensitive var isSensitiveProperty = memberType.IsSensitiveProperty(prop.Alias); // check permissions for viewing sensitive data - if (isSensitiveProperty && (_webSecurity.CurrentUser.HasAccessToSensitiveData() == false)) + if (isSensitiveProperty && (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.HasAccessToSensitiveData() == false)) { // mark this property as sensitive prop.IsSensitive = true; diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index 08be22c07b..465305cd24 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -90,6 +90,7 @@ namespace Umbraco.Tests.Integration.TestServerTest { var url = LinkGenerator.GetUmbracoApiService(methodSelector); + var backofficeSecurityFactory = GetRequiredService(); var umbracoContextFactory = GetRequiredService(); var httpContextAccessor = GetRequiredService(); @@ -104,6 +105,7 @@ namespace Umbraco.Tests.Integration.TestServerTest } }; + backofficeSecurityFactory.EnsureBackofficeSecurity(); umbracoContextFactory.EnsureUmbracoContext(); return url; diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index b21de325cc..705690b898 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -243,6 +243,7 @@ namespace Umbraco.Tests.Integration.Testing public virtual void Configure(IApplicationBuilder app) { + Services.GetRequiredService().EnsureBackofficeSecurity(); Services.GetRequiredService().EnsureUmbracoContext(); // get the currently set ptions 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 236338390b..1a343a1e0b 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/Filters/ContentModelValidatorTests.cs @@ -18,6 +18,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Mapping; using Umbraco.Core.Models; + using Umbraco.Core.Security; using Umbraco.Core.Strings; using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.TestHelpers.Entities; @@ -138,12 +139,14 @@ public void Validating_ContentItemSave() { var logger = Services.GetRequiredService(); - var webSecurity = Services.GetRequiredService(); + var backofficeSecurityFactory = Services.GetRequiredService(); + backofficeSecurityFactory.EnsureBackofficeSecurity(); + var backofficeSecurityAccessor = Services.GetRequiredService(); var localizedTextService = Services.GetRequiredService(); var propertyValidationService = Services.GetRequiredService(); var umbracoMapper = Services.GetRequiredService(); - var validator = new ContentSaveModelValidator(logger, webSecurity, localizedTextService, propertyValidationService); + var validator = new ContentSaveModelValidator(logger, backofficeSecurityAccessor.BackofficeSecurity, localizedTextService, propertyValidationService); var content = MockedContent.CreateTextpageContent(_contentType, "test", -1); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Filters/AppendUserModifiedHeaderAttributeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Filters/AppendUserModifiedHeaderAttributeTests.cs index f087a4851c..6c725d1049 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Filters/AppendUserModifiedHeaderAttributeTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Filters/AppendUserModifiedHeaderAttributeTests.cs @@ -91,16 +91,16 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Filters .SetupGet(x => x.Id) .Returns(100); - var webSecurityMock = new Mock(); - webSecurityMock + var backofficeSecurityMock = new Mock(); + backofficeSecurityMock .SetupGet(x => x.CurrentUser) .Returns(currentUserMock.Object); var serviceProviderMock = new Mock(); serviceProviderMock - .Setup(x => x.GetService(typeof(IWebSecurity))) - .Returns(webSecurityMock.Object); + .Setup(x => x.GetService(typeof(IBackofficeSecurity))) + .Returns(backofficeSecurityMock.Object); httpContext.RequestServices = serviceProviderMock.Object; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttributeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttributeTests.cs index 54499d97ba..f6e551dc27 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttributeTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttributeTests.cs @@ -8,6 +8,7 @@ using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Tests.Common.TestHelpers.Entities; using Umbraco.Web.Actions; @@ -30,7 +31,7 @@ namespace Umbraco.Tests.Web.Controllers ActionBrowse.ActionLetter, Mock.Of(), Mock.Of(), - Mock.Of() ); + Mock.Of() ); var result = att.GetValueFromResponse(new ObjectResult(expected)); @@ -48,7 +49,7 @@ namespace Umbraco.Tests.Web.Controllers ActionBrowse.ActionLetter, Mock.Of(), Mock.Of(), - Mock.Of() ); + Mock.Of() ); var result = att.GetValueFromResponse(new ObjectResult(container)); @@ -66,7 +67,7 @@ namespace Umbraco.Tests.Web.Controllers ActionBrowse.ActionLetter, Mock.Of(), Mock.Of(), - Mock.Of() ); + Mock.Of() ); var actual = att.GetValueFromResponse(new ObjectResult(container)); @@ -94,7 +95,7 @@ namespace Umbraco.Tests.Web.Controllers ActionBrowse.ActionLetter, userService, entityService, - Mock.Of() ); + Mock.Of() ); var path = ""; for (var i = 0; i < 10; i++) @@ -145,7 +146,7 @@ namespace Umbraco.Tests.Web.Controllers ActionBrowse.ActionLetter, userService, Mock.Of(), - Mock.Of() ); + Mock.Of() ); att.FilterBasedOnPermissions(list, user); Assert.AreEqual(3, list.Count); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs index 0d288b6310..a1904cb0da 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Controllers/SurfaceControllerTests.cs @@ -9,6 +9,7 @@ using NUnit.Framework; using Umbraco.Core.Cache; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Tests.Common; using Umbraco.Tests.Common.Builders; @@ -39,6 +40,8 @@ namespace Umbraco.Tests.Integration { var httpContextAccessor = Mock.Of(); var hostingEnvironment = Mock.Of(); + var backofficeSecurityAccessor = Mock.Of(); + Mock.Get(backofficeSecurityAccessor).Setup(x => x.BackofficeSecurity).Returns(Mock.Of()); var globalSettings = new GlobalSettingsBuilder().Build(); var umbracoContextFactory = new UmbracoContextFactory( @@ -53,7 +56,7 @@ namespace Umbraco.Tests.Integration httpContextAccessor, Mock.Of(), Mock.Of(), - Mock.Of()); + backofficeSecurityAccessor); var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(); var umbracoContext = umbracoContextReference.UmbracoContext; @@ -73,7 +76,8 @@ namespace Umbraco.Tests.Integration var globalSettings = new GlobalSettingsBuilder().Build(); var httpContextAccessor = Mock.Of(); var hostingEnvironment = Mock.Of(); - + var backofficeSecurityAccessor = Mock.Of(); + Mock.Get(backofficeSecurityAccessor).Setup(x => x.BackofficeSecurity).Returns(Mock.Of()); var umbracoContextFactory = new UmbracoContextFactory( _umbracoContextAccessor, Mock.Of(), @@ -86,7 +90,7 @@ namespace Umbraco.Tests.Integration httpContextAccessor, Mock.Of(), Mock.Of(), - Mock.Of()); + backofficeSecurityAccessor); var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(); var umbCtx = umbracoContextReference.UmbracoContext; @@ -105,7 +109,8 @@ namespace Umbraco.Tests.Integration publishedSnapshot.Setup(x => x.Members).Returns(Mock.Of()); var content = new Mock(); content.Setup(x => x.Id).Returns(2); - + var backofficeSecurityAccessor = Mock.Of(); + Mock.Get(backofficeSecurityAccessor).Setup(x => x.BackofficeSecurity).Returns(Mock.Of()); var publishedSnapshotService = new Mock(); var httpContextAccessor = Mock.Of(); var hostingEnvironment = Mock.Of(); @@ -123,7 +128,7 @@ namespace Umbraco.Tests.Integration httpContextAccessor, Mock.Of(), Mock.Of(), - Mock.Of()); + backofficeSecurityAccessor); var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(); var umbracoContext = umbracoContextReference.UmbracoContext; @@ -147,7 +152,8 @@ namespace Umbraco.Tests.Integration var globalSettings = new GlobalSettingsBuilder().Build(); var httpContextAccessor = Mock.Of(); var hostingEnvironment = Mock.Of(); - + var backofficeSecurityAccessor = Mock.Of(); + Mock.Get(backofficeSecurityAccessor).Setup(x => x.BackofficeSecurity).Returns(Mock.Of()); var umbracoContextFactory = new UmbracoContextFactory( _umbracoContextAccessor, Mock.Of(), @@ -160,7 +166,7 @@ namespace Umbraco.Tests.Integration httpContextAccessor, Mock.Of(), Mock.Of(), - Mock.Of()); + backofficeSecurityAccessor); var umbracoContextReference = umbracoContextFactory.EnsureUmbracoContext(); var umbracoContext = umbracoContextReference.UmbracoContext; diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs index 13f58f8021..02f6f24779 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedContentCacheTests.cs @@ -81,7 +81,7 @@ namespace Umbraco.Tests.Cache.PublishedCache _umbracoContext = new UmbracoContext( httpContextAccessor, publishedSnapshotService.Object, - Mock.Of(), + Mock.Of(), globalSettings, HostingEnvironment, new TestVariationContextAccessor(), diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index 3d9b4af526..1c70879da1 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -74,7 +74,7 @@ namespace Umbraco.Tests.PublishedContent var umbracoContext = new UmbracoContext( httpContextAccessor, publishedSnapshotService.Object, - Mock.Of(), + Mock.Of(), globalSettings, HostingEnvironment, new TestVariationContextAccessor(), diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 243ad50eef..edd4d38075 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -126,7 +126,7 @@ namespace Umbraco.Tests.Scoping var umbracoContext = new UmbracoContext( httpContextAccessor, service, - Mock.Of(), + Mock.Of(), globalSettings, HostingEnvironment, new TestVariationContextAccessor(), diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 87d470f31e..379c176099 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -95,7 +95,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting var backofficeIdentity = (UmbracoBackOfficeIdentity) owinContext.Authentication.User.Identity; - var webSecurity = new Mock(); + var backofficeSecurity = new Mock(); //mock CurrentUser var groups = new List(); @@ -116,13 +116,13 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting mockUser.Setup(x => x.StartContentIds).Returns(backofficeIdentity.StartContentNodes); mockUser.Setup(x => x.StartMediaIds).Returns(backofficeIdentity.StartMediaNodes); mockUser.Setup(x => x.Username).Returns(backofficeIdentity.Username); - webSecurity.Setup(x => x.CurrentUser) + backofficeSecurity.Setup(x => x.CurrentUser) .Returns(mockUser.Object); //mock Validate - webSecurity.Setup(x => x.ValidateCurrentUser()) + backofficeSecurity.Setup(x => x.ValidateCurrentUser()) .Returns(() => true); - webSecurity.Setup(x => x.UserHasSectionAccess(It.IsAny(), It.IsAny())) + backofficeSecurity.Setup(x => x.UserHasSectionAccess(It.IsAny(), It.IsAny())) .Returns(() => true); var publishedSnapshot = new Mock(); @@ -135,7 +135,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting var httpContextAccessor = TestHelper.GetHttpContextAccessor(httpContext); var umbCtx = new UmbracoContext(httpContextAccessor, publishedSnapshotService.Object, - webSecurity.Object, + backofficeSecurity.Object, globalSettings, TestHelper.GetHostingEnvironment(), new TestVariationContextAccessor(), diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index f1a834021f..fe41ac2d9c 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -372,7 +372,7 @@ namespace Umbraco.Tests.TestHelpers var umbracoContext = new UmbracoContext( httpContextAccessor, service, - Mock.Of(), + Mock.Of(), globalSettings ?? new GlobalSettingsBuilder().Build(), HostingEnvironment, new TestVariationContextAccessor(), diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 0c39ee47f0..08a1297cda 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -316,7 +316,7 @@ namespace Umbraco.Tests.Testing Composition.RegisterUnique(); Composition.RegisterUnique(); - Composition.RegisterUnique(); + Composition.RegisterUnique(); Composition.RegisterUnique(); Composition.RegisterUnique(); Composition.RegisterUnique(); diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 5e89f29496..bcaf1ceccf 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -440,7 +440,7 @@ namespace Umbraco.Tests.Web.Mvc var ctx = new UmbracoContext( httpContextAccessor, _service, - Mock.Of(), + Mock.Of(), globalSettings, HostingEnvironment, new TestVariationContextAccessor(), diff --git a/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs b/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs index 32d8e0917b..0e5b963d9f 100644 --- a/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs +++ b/src/Umbraco.Tests/Web/WebExtensionMethodTests.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Web var umbCtx = new UmbracoContext( httpContextAccessor, Mock.Of(), - Mock.Of(), + Mock.Of(), TestObjects.GetGlobalSettings(), HostingEnvironment, new TestVariationContextAccessor(), @@ -53,7 +53,7 @@ namespace Umbraco.Tests.Web var umbCtx = new UmbracoContext( httpContextAccessor, Mock.Of(), - Mock.Of(), + Mock.Of(), TestObjects.GetGlobalSettings(), HostingEnvironment, new TestVariationContextAccessor(), @@ -84,7 +84,7 @@ namespace Umbraco.Tests.Web var umbCtx = new UmbracoContext( httpContextAccessor, Mock.Of(), - Mock.Of(), + Mock.Of(), TestObjects.GetGlobalSettings(), HostingEnvironment, new TestVariationContextAccessor(), diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs index 53a7a324dc..185269b6f1 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Extensions; using Umbraco.Net; @@ -39,7 +40,7 @@ namespace Umbraco.Web.BackOffice.Controllers [IsBackOffice] // TODO: This could be applied with our Application Model conventions public class AuthenticationController : UmbracoApiControllerBase { - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly BackOfficeUserManager _userManager; private readonly BackOfficeSignInManager _signInManager; private readonly IUserService _userService; @@ -58,7 +59,7 @@ namespace Umbraco.Web.BackOffice.Controllers // TODO: We need to review all _userManager.Raise calls since many/most should be on the usermanager or signinmanager, very few should be here public AuthenticationController( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, BackOfficeUserManager backOfficeUserManager, BackOfficeSignInManager signInManager, IUserService userService, @@ -73,7 +74,7 @@ namespace Umbraco.Web.BackOffice.Controllers Core.Hosting.IHostingEnvironment hostingEnvironment, IRequestAccessor requestAccessor) { - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _userManager = backOfficeUserManager; _signInManager = signInManager; _userService = userService; @@ -96,7 +97,7 @@ namespace Umbraco.Web.BackOffice.Controllers [UmbracoAuthorize] public IDictionary GetPasswordConfig(int userId) { - return _passwordConfiguration.GetConfiguration(userId != _webSecurity.CurrentUser.Id); + return _passwordConfiguration.GetConfiguration(userId != _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); } /// @@ -164,7 +165,7 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpGet] public bool IsAuthenticated() { - var attempt = _webSecurity.AuthorizeRequest(); + var attempt = _backofficeSecurityAccessor.BackofficeSecurity.AuthorizeRequest(); if (attempt == ValidateRequestAttempt.Success) { return true; @@ -186,7 +187,7 @@ namespace Umbraco.Web.BackOffice.Controllers //[CheckIfUserTicketDataIsStale] // TODO: Migrate this, though it will need to be done differently at the cookie auth level public UserDetail GetCurrentUser() { - var user = _webSecurity.CurrentUser; + var user = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; var result = _umbracoMapper.Map(user); //set their remaining seconds @@ -207,7 +208,7 @@ namespace Umbraco.Web.BackOffice.Controllers [SetAngularAntiForgeryTokens] public ActionResult GetCurrentInvitedUser() { - var user = _webSecurity.CurrentUser; + var user = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; if (user.IsApproved) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs index 141578cccd..6db4efab40 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs @@ -15,6 +15,7 @@ using Umbraco.Core.Configuration.Grid; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.WebAssets; using Umbraco.Extensions; @@ -45,7 +46,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly BackOfficeServerVariables _backOfficeServerVariables; private readonly AppCaches _appCaches; private readonly BackOfficeSignInManager _signInManager; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly ILogger _logger; public BackOfficeController( @@ -59,7 +60,7 @@ namespace Umbraco.Web.BackOffice.Controllers BackOfficeServerVariables backOfficeServerVariables, AppCaches appCaches, BackOfficeSignInManager signInManager, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILogger logger) { _userManager = userManager; @@ -72,7 +73,7 @@ namespace Umbraco.Web.BackOffice.Controllers _backOfficeServerVariables = backOfficeServerVariables; _appCaches = appCaches; _signInManager = signInManager; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _logger = logger; } @@ -93,7 +94,7 @@ namespace Umbraco.Web.BackOffice.Controllers //if you are hitting VerifyInvite, you're already signed in as a different user, and the token is invalid //you'll exit on one of the return RedirectToAction(nameof(Default)) but you're still logged in so you just get //dumped at the default admin view with no detail - if (_webSecurity.IsAuthenticated()) + if (_backofficeSecurityAccessor.BackofficeSecurity.IsAuthenticated()) { await _signInManager.SignOutAsync(); } @@ -186,7 +187,7 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpGet] public Dictionary> LocalizedText(string culture = null) { - var isAuthenticated = _webSecurity.IsAuthenticated(); + var isAuthenticated = _backofficeSecurityAccessor.BackofficeSecurity.IsAuthenticated(); var cultureInfo = string.IsNullOrWhiteSpace(culture) //if the user is logged in, get their culture, otherwise default to 'en' diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs index 7704b198ae..66ece55162 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs @@ -56,7 +56,7 @@ namespace Umbraco.Web.Editors private readonly IContentService _contentService; private readonly ILocalizedTextService _localizedTextService; private readonly IUserService _userService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IEntityService _entityService; private readonly IContentTypeService _contentTypeService; private readonly UmbracoMapper _umbracoMapper; @@ -84,7 +84,7 @@ namespace Umbraco.Web.Editors PropertyEditorCollection propertyEditors, IContentService contentService, IUserService userService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IEntityService entityService, IContentTypeService contentTypeService, UmbracoMapper umbracoMapper, @@ -105,7 +105,7 @@ namespace Umbraco.Web.Editors _contentService = contentService; _localizedTextService = localizedTextService; _userService = userService; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _entityService = entityService; _contentTypeService = contentTypeService; _umbracoMapper = umbracoMapper; @@ -428,7 +428,7 @@ namespace Umbraco.Web.Editors private ContentItemDisplay GetEmpty(IContentType contentType, int parentId) { - var emptyContent = _contentService.Create("", parentId, contentType.Alias, _webSecurity.GetUserId().ResultOr(0)); + var emptyContent = _contentService.Create("", parentId, contentType.Alias, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); var mapped = MapToDisplay(emptyContent); // translate the content type name if applicable mapped.ContentTypeName = _localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, mapped.ContentTypeName); @@ -597,9 +597,9 @@ namespace Umbraco.Web.Editors EnsureUniqueName(name, content, nameof(name)); - var blueprint = _contentService.CreateContentFromBlueprint(content, name, _webSecurity.GetUserId().ResultOr(0)); + var blueprint = _contentService.CreateContentFromBlueprint(content, name, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); - _contentService.SaveBlueprint(blueprint, _webSecurity.GetUserId().ResultOr(0)); + _contentService.SaveBlueprint(blueprint, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); var notificationModel = new SimpleNotificationModel(); notificationModel.AddSuccessNotification( @@ -633,7 +633,7 @@ namespace Umbraco.Web.Editors { EnsureUniqueName(content.Name, content, "Name"); - _contentService.SaveBlueprint(contentItem.PersistedContent, _webSecurity.CurrentUser.Id); + _contentService.SaveBlueprint(contentItem.PersistedContent, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); //we need to reuse the underlying logic so return the result that it wants return OperationResult.Succeed(new EventMessages()); }, @@ -658,7 +658,7 @@ namespace Umbraco.Web.Editors { var contentItemDisplay = PostSaveInternal( contentItem, - content => _contentService.Save(contentItem.PersistedContent, _webSecurity.CurrentUser.Id), + content => _contentService.Save(contentItem.PersistedContent, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id), MapToDisplay); return contentItemDisplay; @@ -760,7 +760,7 @@ namespace Umbraco.Web.Editors case ContentSaveAction.SendPublish: case ContentSaveAction.SendPublishNew: - var sendResult = _contentService.SendToPublication(contentItem.PersistedContent, _webSecurity.CurrentUser.Id); + var sendResult = _contentService.SendToPublication(contentItem.PersistedContent, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); wasCancelled = sendResult == false; if (sendResult) { @@ -1204,7 +1204,7 @@ namespace Umbraco.Web.Editors //if this item's path has already been denied or if the user doesn't have access to it, add to the deny list if (denied.Any(x => c.Path.StartsWith($"{x.Path},")) || (ContentPermissionsHelper.CheckPermissions(c, - _webSecurity.CurrentUser, _userService, _entityService, + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, _userService, _entityService, ActionPublish.ActionLetter) == ContentPermissionsHelper.ContentAccess.Denied)) { denied.Add(c); @@ -1221,7 +1221,7 @@ namespace Umbraco.Web.Editors if (!contentItem.PersistedContent.ContentType.VariesByCulture()) { //its invariant, proceed normally - var publishStatus = _contentService.SaveAndPublishBranch(contentItem.PersistedContent, force, userId: _webSecurity.CurrentUser.Id); + var publishStatus = _contentService.SaveAndPublishBranch(contentItem.PersistedContent, force, userId: _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); // TODO: Deal with multiple cancellations wasCancelled = publishStatus.Any(x => x.Result == PublishResultType.FailedPublishCancelledByEvent); successfulCultures = null; //must be null! this implies invariant @@ -1256,7 +1256,7 @@ namespace Umbraco.Web.Editors if (canPublish) { //proceed to publish if all validation still succeeds - var publishStatus = _contentService.SaveAndPublishBranch(contentItem.PersistedContent, force, culturesToPublish, _webSecurity.CurrentUser.Id); + var publishStatus = _contentService.SaveAndPublishBranch(contentItem.PersistedContent, force, culturesToPublish, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); // TODO: Deal with multiple cancellations wasCancelled = publishStatus.Any(x => x.Result == PublishResultType.FailedPublishCancelledByEvent); successfulCultures = contentItem.Variants.Where(x => x.Publish).Select(x => x.Culture).ToArray(); @@ -1265,7 +1265,7 @@ namespace Umbraco.Web.Editors else { //can only save - var saveResult = _contentService.Save(contentItem.PersistedContent, _webSecurity.CurrentUser.Id); + var saveResult = _contentService.Save(contentItem.PersistedContent, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); var publishStatus = new[] { new PublishResult(PublishResultType.FailedPublishMandatoryCultureMissing, null, contentItem.PersistedContent) @@ -1293,7 +1293,7 @@ namespace Umbraco.Web.Editors if (!contentItem.PersistedContent.ContentType.VariesByCulture()) { //its invariant, proceed normally - var publishStatus = _contentService.SaveAndPublish(contentItem.PersistedContent, userId: _webSecurity.CurrentUser.Id); + var publishStatus = _contentService.SaveAndPublish(contentItem.PersistedContent, userId: _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); wasCancelled = publishStatus.Result == PublishResultType.FailedPublishCancelledByEvent; successfulCultures = null; //must be null! this implies invariant return publishStatus; @@ -1338,7 +1338,7 @@ namespace Umbraco.Web.Editors if (canPublish) { //proceed to publish if all validation still succeeds - var publishStatus = _contentService.SaveAndPublish(contentItem.PersistedContent, culturesToPublish, _webSecurity.CurrentUser.Id); + var publishStatus = _contentService.SaveAndPublish(contentItem.PersistedContent, culturesToPublish, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); wasCancelled = publishStatus.Result == PublishResultType.FailedPublishCancelledByEvent; successfulCultures = culturesToPublish; return publishStatus; @@ -1346,7 +1346,7 @@ namespace Umbraco.Web.Editors else { //can only save - var saveResult = _contentService.Save(contentItem.PersistedContent, _webSecurity.CurrentUser.Id); + var saveResult = _contentService.Save(contentItem.PersistedContent, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); var publishStatus = new PublishResult(PublishResultType.FailedPublishMandatoryCultureMissing, null, contentItem.PersistedContent); wasCancelled = saveResult.Result == OperationResultType.FailedCancelledByEvent; successfulCultures = Array.Empty(); @@ -1501,7 +1501,7 @@ namespace Umbraco.Web.Editors return HandleContentNotFound(id, false); } - var publishResult = _contentService.SaveAndPublish(foundContent, userId: _webSecurity.GetUserId().ResultOr(0)); + var publishResult = _contentService.SaveAndPublish(foundContent, userId: _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); if (publishResult.Success == false) { var notificationModel = new SimpleNotificationModel(); @@ -1553,7 +1553,7 @@ namespace Umbraco.Web.Editors //if the current item is in the recycle bin if (foundContent.Trashed == false) { - var moveResult = _contentService.MoveToRecycleBin(foundContent, _webSecurity.GetUserId().ResultOr(0)); + var moveResult = _contentService.MoveToRecycleBin(foundContent, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); if (moveResult.Success == false) { //returning an object of INotificationModel will ensure that any pending @@ -1563,7 +1563,7 @@ namespace Umbraco.Web.Editors } else { - var deleteResult = _contentService.Delete(foundContent, _webSecurity.GetUserId().ResultOr(0)); + var deleteResult = _contentService.Delete(foundContent, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); if (deleteResult.Success == false) { //returning an object of INotificationModel will ensure that any pending @@ -1587,7 +1587,7 @@ namespace Umbraco.Web.Editors [EnsureUserPermissionForContent(Constants.System.RecycleBinContent, ActionDelete.ActionLetter)] public IActionResult EmptyRecycleBin() { - _contentService.EmptyRecycleBin(_webSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); + _contentService.EmptyRecycleBin(_backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); return new UmbracoNotificationSuccessResponse(_localizedTextService.Localize("defaultdialogs/recycleBinIsEmpty")); } @@ -1616,7 +1616,7 @@ namespace Umbraco.Web.Editors var contentService = _contentService; // Save content with new sort order and update content xml in db accordingly - var sortResult = contentService.Sort(sorted.IdSortOrder, _webSecurity.CurrentUser.Id); + var sortResult = contentService.Sort(sorted.IdSortOrder, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); if (!sortResult.Success) { Logger.Warn("Content sorting failed, this was probably caused by an event being cancelled"); @@ -1643,7 +1643,7 @@ namespace Umbraco.Web.Editors { var toMove = ValidateMoveOrCopy(move); - _contentService.Move(toMove, move.ParentId, _webSecurity.GetUserId().ResultOr(0)); + _contentService.Move(toMove, move.ParentId, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); return Content(toMove.Path, MediaTypeNames.Text.Plain, Encoding.UTF8); } @@ -1658,7 +1658,7 @@ namespace Umbraco.Web.Editors { var toCopy = ValidateMoveOrCopy(copy); - var c = _contentService.Copy(toCopy, copy.ParentId, copy.RelateToOriginal, copy.Recursive, _webSecurity.GetUserId().ResultOr(0)); + var c = _contentService.Copy(toCopy, copy.ParentId, copy.RelateToOriginal, copy.Recursive, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); return Content(c.Path, MediaTypeNames.Text.Plain, Encoding.UTF8); } @@ -1681,7 +1681,7 @@ namespace Umbraco.Web.Editors if (model.Cultures.Length == 0 || model.Cultures.Length == languageCount) { //this means that the entire content item will be unpublished - var unpublishResult = _contentService.Unpublish(foundContent, userId: _webSecurity.GetUserId().ResultOr(0)); + var unpublishResult = _contentService.Unpublish(foundContent, userId: _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); var content = MapToDisplay(foundContent); @@ -1704,7 +1704,7 @@ namespace Umbraco.Web.Editors var results = new Dictionary(); foreach (var c in model.Cultures) { - var result = _contentService.Unpublish(foundContent, culture: c, userId: _webSecurity.GetUserId().ResultOr(0)); + var result = _contentService.Unpublish(foundContent, culture: c, userId: _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); results[c] = result; if (result.Result == PublishResultType.SuccessUnpublishMandatoryCulture) { @@ -1772,7 +1772,7 @@ namespace Umbraco.Web.Editors return NotFound("There is no content node with id {model.NodeId}."); } - var permission = _userService.GetPermissions(_webSecurity.CurrentUser, node.Path); + var permission = _userService.GetPermissions(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, node.Path); if (permission.AssignedPermissions.Contains(ActionAssignDomain.ActionLetter.ToString(), StringComparer.Ordinal) == false) @@ -2260,7 +2260,7 @@ namespace Umbraco.Web.Editors { var display = _umbracoMapper.Map(content, context => { - context.Items["CurrentUser"] = _webSecurity.CurrentUser; + context.Items["CurrentUser"] = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; }); display.AllowPreview = display.AllowPreview && content.Trashed == false && content.ContentType.IsElement == false; return display; @@ -2275,7 +2275,7 @@ namespace Umbraco.Web.Editors var content = _contentService.GetById(contentId); if (content == null) return NotFound(); - var userNotifications = _notificationService.GetUserNotifications(_webSecurity.CurrentUser, content.Path).ToList(); + var userNotifications = _notificationService.GetUserNotifications(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, content.Path).ToList(); foreach (var a in _actionCollection.Where(x => x.ShowInNotifier)) { @@ -2297,7 +2297,7 @@ namespace Umbraco.Web.Editors var content = _contentService.GetById(contentId); if (content == null) return NotFound(); - _notificationService.SetNotifications(_webSecurity.CurrentUser, content, notifyOptions); + _notificationService.SetNotifications(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, content, notifyOptions); return NoContent(); } @@ -2362,7 +2362,7 @@ namespace Umbraco.Web.Editors [HttpPost] public IActionResult PostRollbackContent(int contentId, int versionId, string culture = "*") { - var rollbackResult = _contentService.Rollback(contentId, versionId, culture, _webSecurity.GetUserId().ResultOr(0)); + var rollbackResult = _contentService.Rollback(contentId, versionId, culture, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); if (rollbackResult.Success) return Ok(); diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index 4f7260a35c..7955b82eeb 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -26,6 +26,7 @@ using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Mapping; +using Umbraco.Core.Security; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Common.Exceptions; @@ -56,7 +57,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IIOHelper _ioHelper; private readonly IContentTypeService _contentTypeService; private readonly UmbracoMapper _umbracoMapper; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IDataTypeService _dataTypeService; private readonly IShortStringHelper _shortStringHelper; private readonly ILocalizedTextService _localizedTextService; @@ -81,7 +82,7 @@ namespace Umbraco.Web.BackOffice.Controllers PropertyEditorCollection propertyEditors, IScopeProvider scopeProvider, IIOHelper ioHelper, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IDataTypeService dataTypeService, IShortStringHelper shortStringHelper, IFileService fileService, @@ -108,7 +109,7 @@ namespace Umbraco.Web.BackOffice.Controllers _ioHelper = ioHelper; _contentTypeService = contentTypeService; _umbracoMapper = umbracoMapper; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _dataTypeService = dataTypeService; _shortStringHelper = shortStringHelper; _localizedTextService = localizedTextService; @@ -207,7 +208,7 @@ namespace Umbraco.Web.BackOffice.Controllers throw new HttpResponseException(HttpStatusCode.NotFound); } - _contentTypeService.Delete(foundType, _webSecurity.CurrentUser.Id); + _contentTypeService.Delete(foundType, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return Ok(); } @@ -306,14 +307,14 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpPost] public IActionResult DeleteContainer(int id) { - _contentTypeService.DeleteContainer(id, _webSecurity.CurrentUser.Id); + _contentTypeService.DeleteContainer(id, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return Ok(); } public IActionResult PostCreateContainer(int parentId, string name) { - var result = _contentTypeService.CreateContainer(parentId, name, _webSecurity.CurrentUser.Id); + var result = _contentTypeService.CreateContainer(parentId, name, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return result ? Ok(result.Result) //return the id @@ -322,7 +323,7 @@ namespace Umbraco.Web.BackOffice.Controllers public IActionResult PostRenameContainer(int id, string name) { - var result = _contentTypeService.RenameContainer(id, name, _webSecurity.CurrentUser.Id); + var result = _contentTypeService.RenameContainer(id, name, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return result ? Ok(result.Result) //return the id @@ -622,7 +623,7 @@ namespace Umbraco.Web.BackOffice.Controllers var xd = new XmlDocument {XmlResolver = null}; xd.Load(filePath); - var userId = _webSecurity.GetUserId().ResultOr(0); + var userId = _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0); var element = XElement.Parse(xd.InnerXml); dataInstaller.ImportDocumentType(element, userId); diff --git a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs index 433c26169f..3aab1853dc 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs @@ -16,6 +16,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Media; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Extensions; @@ -39,7 +40,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly ContentSettings _contentSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IImageUrlGenerator _imageUrlGenerator; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IUserService _userService; private readonly UmbracoMapper _umbracoMapper; private readonly BackOfficeUserManager _backOfficeUserManager; @@ -53,7 +54,7 @@ namespace Umbraco.Web.BackOffice.Controllers IOptions contentSettings, IHostingEnvironment hostingEnvironment, IImageUrlGenerator imageUrlGenerator, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IUserService userService, UmbracoMapper umbracoMapper, BackOfficeUserManager backOfficeUserManager, @@ -66,7 +67,7 @@ namespace Umbraco.Web.BackOffice.Controllers _contentSettings = contentSettings.Value; _hostingEnvironment = hostingEnvironment; _imageUrlGenerator = imageUrlGenerator; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _userService = userService; _umbracoMapper = umbracoMapper; _backOfficeUserManager = backOfficeUserManager; @@ -86,7 +87,7 @@ namespace Umbraco.Web.BackOffice.Controllers public Dictionary GetPermissions(int[] nodeIds) { var permissions = _userService - .GetPermissions(_webSecurity.CurrentUser, nodeIds); + .GetPermissions(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, nodeIds); var permissionsDictionary = new Dictionary(); foreach (var nodeId in nodeIds) @@ -107,7 +108,7 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpGet] public bool HasPermission(string permissionToCheck, int nodeId) { - var p = _userService.GetPermissions(_webSecurity.CurrentUser, nodeId).GetAllPermissions(); + var p = _userService.GetPermissions(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, nodeId).GetAllPermissions(); if (p.Contains(permissionToCheck.ToString(CultureInfo.InvariantCulture))) { return true; @@ -126,15 +127,15 @@ namespace Umbraco.Web.BackOffice.Controllers if (status == null) throw new ArgumentNullException(nameof(status)); List userTours; - if (_webSecurity.CurrentUser.TourData.IsNullOrWhiteSpace()) + if (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.TourData.IsNullOrWhiteSpace()) { userTours = new List { status }; - _webSecurity.CurrentUser.TourData = JsonConvert.SerializeObject(userTours); - _userService.Save(_webSecurity.CurrentUser); + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.TourData = JsonConvert.SerializeObject(userTours); + _userService.Save(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser); return userTours; } - userTours = JsonConvert.DeserializeObject>(_webSecurity.CurrentUser.TourData).ToList(); + userTours = JsonConvert.DeserializeObject>(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.TourData).ToList(); var found = userTours.FirstOrDefault(x => x.Alias == status.Alias); if (found != null) { @@ -142,8 +143,8 @@ namespace Umbraco.Web.BackOffice.Controllers userTours.Remove(found); } userTours.Add(status); - _webSecurity.CurrentUser.TourData = JsonConvert.SerializeObject(userTours); - _userService.Save(_webSecurity.CurrentUser); + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.TourData = JsonConvert.SerializeObject(userTours); + _userService.Save(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser); return userTours; } @@ -153,10 +154,10 @@ namespace Umbraco.Web.BackOffice.Controllers /// public IEnumerable GetUserTours() { - if (_webSecurity.CurrentUser.TourData.IsNullOrWhiteSpace()) + if (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.TourData.IsNullOrWhiteSpace()) return Enumerable.Empty(); - var userTours = JsonConvert.DeserializeObject>(_webSecurity.CurrentUser.TourData); + var userTours = JsonConvert.DeserializeObject>(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.TourData); return userTours; } @@ -172,7 +173,7 @@ namespace Umbraco.Web.BackOffice.Controllers [UmbracoAuthorize(redirectToUmbracoLogin: false, requireApproval : true)] public async Task PostSetInvitedUserPassword([FromBody]string newPassword) { - var user = await _backOfficeUserManager.FindByIdAsync(_webSecurity.GetUserId().ResultOr(0).ToString()); + var user = await _backOfficeUserManager.FindByIdAsync(_backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0).ToString()); if (user == null) throw new InvalidOperationException("Could not find user"); var result = await _backOfficeUserManager.AddPasswordAsync(user, newPassword); @@ -187,13 +188,13 @@ namespace Umbraco.Web.BackOffice.Controllers } //They've successfully set their password, we can now update their user account to be approved - _webSecurity.CurrentUser.IsApproved = true; + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.IsApproved = true; //They've successfully set their password, and will now get fully logged into the back office, so the lastlogindate is set so the backoffice shows they have logged in - _webSecurity.CurrentUser.LastLoginDate = DateTime.UtcNow; - _userService.Save(_webSecurity.CurrentUser); + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.LastLoginDate = DateTime.UtcNow; + _userService.Save(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser); //now we can return their full object since they are now really logged into the back office - var userDisplay = _umbracoMapper.Map(_webSecurity.CurrentUser); + var userDisplay = _umbracoMapper.Map(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser); userDisplay.SecondsUntilTimeout = HttpContext.User.GetRemainingAuthSeconds(); return userDisplay; @@ -203,7 +204,7 @@ namespace Umbraco.Web.BackOffice.Controllers public async Task PostSetAvatar(IList files) { //borrow the logic from the user controller - return await UsersController.PostSetAvatarInternal(files, _userService, _appCaches.RuntimeCache, _mediaFileSystem, _shortStringHelper, _contentSettings, _hostingEnvironment, _imageUrlGenerator, _webSecurity.GetUserId().ResultOr(0)); + return await UsersController.PostSetAvatarInternal(files, _userService, _appCaches.RuntimeCache, _mediaFileSystem, _shortStringHelper, _contentSettings, _hostingEnvironment, _imageUrlGenerator, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); } /// @@ -216,7 +217,7 @@ namespace Umbraco.Web.BackOffice.Controllers public async Task> PostChangePassword(ChangingPasswordModel data) { var passwordChanger = new PasswordChanger(_logger); - var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(_webSecurity.CurrentUser, _webSecurity.CurrentUser, data, _backOfficeUserManager); + var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, data, _backOfficeUserManager); if (passwordChangeResult.Success) { @@ -238,7 +239,7 @@ namespace Umbraco.Web.BackOffice.Controllers [ValidateAngularAntiForgeryToken] public async Task> GetCurrentUserLinkedLogins() { - var identityUser = await _backOfficeUserManager.FindByIdAsync(_webSecurity.GetUserId().ResultOr(0).ToString()); + var identityUser = await _backOfficeUserManager.FindByIdAsync(_backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0).ToString()); return identityUser.Logins.ToDictionary(x => x.LoginProvider, x => x.ProviderKey); } } diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs index 2882c28f4f..207dee60f4 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; @@ -34,7 +35,7 @@ namespace Umbraco.Web.BackOffice.Controllers { private readonly ILogger _logger; private readonly ILocalizationService _localizationService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly GlobalSettings _globalSettings; private readonly ILocalizedTextService _localizedTextService; private readonly UmbracoMapper _umbracoMapper; @@ -42,7 +43,7 @@ namespace Umbraco.Web.BackOffice.Controllers public DictionaryController( ILogger logger, ILocalizationService localizationService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IOptions globalSettings, ILocalizedTextService localizedTextService, UmbracoMapper umbracoMapper @@ -50,7 +51,7 @@ namespace Umbraco.Web.BackOffice.Controllers { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); @@ -74,10 +75,10 @@ namespace Umbraco.Web.BackOffice.Controllers foreach (var dictionaryItem in foundDictionaryDescendants) { - _localizationService.Delete(dictionaryItem, _webSecurity.CurrentUser.Id); + _localizationService.Delete(dictionaryItem, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); } - _localizationService.Delete(foundDictionary, _webSecurity.CurrentUser.Id); + _localizationService.Delete(foundDictionary, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return Ok(); } @@ -104,7 +105,7 @@ namespace Umbraco.Web.BackOffice.Controllers { var message = _localizedTextService.Localize( "dictionaryItem/changeKeyError", - _webSecurity.CurrentUser.GetUserCulture(_localizedTextService, _globalSettings), + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.GetUserCulture(_localizedTextService, _globalSettings), new Dictionary { { "0", key } }); throw HttpResponseException.CreateNotificationValidationErrorResponse(message); } @@ -218,7 +219,7 @@ namespace Umbraco.Web.BackOffice.Controllers if (dictionaryItem == null) throw HttpResponseException.CreateNotificationValidationErrorResponse("Dictionary item does not exist"); - var userCulture = _webSecurity.CurrentUser.GetUserCulture(_localizedTextService, _globalSettings); + var userCulture = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.GetUserCulture(_localizedTextService, _globalSettings); if (dictionary.NameIsDirty) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs index 1afe9bccf4..35d9c51cd4 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Entities; using Umbraco.Core.Persistence; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Xml; @@ -53,7 +54,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IPublishedContentQuery _publishedContentQuery; private readonly IShortStringHelper _shortStringHelper; private readonly IEntityService _entityService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IPublishedUrlProvider _publishedUrlProvider; private readonly IContentService _contentService; private readonly UmbracoMapper _umbracoMapper; @@ -74,7 +75,7 @@ namespace Umbraco.Web.BackOffice.Controllers IPublishedContentQuery publishedContentQuery, IShortStringHelper shortStringHelper, IEntityService entityService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IPublishedUrlProvider publishedUrlProvider, IContentService contentService, UmbracoMapper umbracoMapper, @@ -96,7 +97,7 @@ namespace Umbraco.Web.BackOffice.Controllers publishedContentQuery ?? throw new ArgumentNullException(nameof(publishedContentQuery)); _shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _publishedUrlProvider = publishedUrlProvider ?? throw new ArgumentNullException(nameof(publishedUrlProvider)); _contentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); @@ -175,7 +176,7 @@ namespace Umbraco.Web.BackOffice.Controllers if (string.IsNullOrEmpty(query)) return result; - var allowedSections = _webSecurity.CurrentUser.AllowedSections.ToArray(); + var allowedSections = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.AllowedSections.ToArray(); foreach (var searchableTree in _searchableTreeCollection.SearchableApplicationTrees.OrderBy(t => t.Value.SortOrder)) { @@ -721,9 +722,9 @@ namespace Umbraco.Web.BackOffice.Controllers switch (type) { case UmbracoEntityTypes.Document: - return _webSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService); + return _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService); case UmbracoEntityTypes.Media: - return _webSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService); + return _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService); default: return Array.Empty(); } @@ -862,10 +863,10 @@ namespace Umbraco.Web.BackOffice.Controllers switch (entityType) { case UmbracoEntityTypes.Document: - aids = _webSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService); + aids = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService); break; case UmbracoEntityTypes.Media: - aids = _webSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService); + aids = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService); break; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/LogController.cs b/src/Umbraco.Web.BackOffice/Controllers/LogController.cs index e99ea890d7..7dd2b1af44 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/LogController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/LogController.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Mapping; using Umbraco.Core.Media; using Umbraco.Core.Models; using Umbraco.Core.Persistence; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; @@ -26,7 +27,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IImageUrlGenerator _imageUrlGenerator; private readonly IAuditService _auditService; private readonly UmbracoMapper _umbracoMapper; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IUserService _userService; private readonly AppCaches _appCaches; private readonly ISqlContext _sqlContext; @@ -36,7 +37,7 @@ namespace Umbraco.Web.BackOffice.Controllers IImageUrlGenerator imageUrlGenerator, IAuditService auditService, UmbracoMapper umbracoMapper, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IUserService userService, AppCaches appCaches, ISqlContext sqlContext) @@ -45,7 +46,7 @@ namespace Umbraco.Web.BackOffice.Controllers _imageUrlGenerator = imageUrlGenerator ?? throw new ArgumentNullException(nameof(imageUrlGenerator)); _auditService = auditService ?? throw new ArgumentNullException(nameof(auditService)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _appCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches)); _sqlContext = sqlContext ?? throw new ArgumentNullException(nameof(sqlContext)); @@ -89,7 +90,7 @@ namespace Umbraco.Web.BackOffice.Controllers long totalRecords; var dateQuery = sinceDate.HasValue ? _sqlContext.Query().Where(x => x.CreateDate >= sinceDate) : null; - var userId = _webSecurity.GetUserId().ResultOr(0); + var userId = _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0); var result = _auditService.GetPagedItemsByUser(userId, pageNumber - 1, pageSize, out totalRecords, orderDirection, customFilter:dateQuery); var mapped = _umbracoMapper.MapEnumerable(result); return new PagedResult(totalRecords, pageNumber, pageSize) diff --git a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs index cf951a57c3..b64a4753bb 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs @@ -18,6 +18,7 @@ using Umbraco.Web.Common.Exceptions; using Umbraco.Web.Security; using Umbraco.Core; using Umbraco.Core.Mapping; +using Umbraco.Core.Security; namespace Umbraco.Web.BackOffice.Controllers { @@ -32,7 +33,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly ParameterEditorCollection _parameterEditorCollection; private readonly IMacroService _macroService; private readonly IShortStringHelper _shortStringHelper; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly ILogger _logger; private readonly IHostingEnvironment _hostingEnvironment; private readonly UmbracoMapper _umbracoMapper; @@ -41,7 +42,7 @@ namespace Umbraco.Web.BackOffice.Controllers ParameterEditorCollection parameterEditorCollection, IMacroService macroService, IShortStringHelper shortStringHelper, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILogger logger, IHostingEnvironment hostingEnvironment, UmbracoMapper umbracoMapper @@ -50,7 +51,7 @@ namespace Umbraco.Web.BackOffice.Controllers _parameterEditorCollection = parameterEditorCollection ?? throw new ArgumentNullException(nameof(parameterEditorCollection)); _macroService = macroService ?? throw new ArgumentNullException(nameof(macroService)); _shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); @@ -95,7 +96,7 @@ namespace Umbraco.Web.BackOffice.Controllers MacroSource = string.Empty }; - _macroService.Save(macro, _webSecurity.CurrentUser.Id); + _macroService.Save(macro, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return macro.Id; } @@ -215,7 +216,7 @@ namespace Umbraco.Web.BackOffice.Controllers try { - _macroService.Save(macro, _webSecurity.CurrentUser.Id); + _macroService.Save(macro, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); macroDisplay.Notifications.Clear(); diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs index c9eaea0d4a..34f0f0afd7 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs @@ -26,6 +26,9 @@ using Umbraco.Core.Models.Validation; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Security; +using Umbraco.Web.ContentApps; +using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Extensions; @@ -55,7 +58,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IMediaTypeService _mediaTypeService; private readonly IMediaService _mediaService; private readonly IEntityService _entityService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly UmbracoMapper _umbracoMapper; private readonly IDataTypeService _dataTypeService; private readonly ILocalizedTextService _localizedTextService; @@ -72,7 +75,7 @@ namespace Umbraco.Web.BackOffice.Controllers IMediaTypeService mediaTypeService, IMediaService mediaService, IEntityService entityService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, UmbracoMapper umbracoMapper, IDataTypeService dataTypeService, ISqlContext sqlContext, @@ -88,7 +91,7 @@ namespace Umbraco.Web.BackOffice.Controllers _mediaTypeService = mediaTypeService; _mediaService = mediaService; _entityService = entityService; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _umbracoMapper = umbracoMapper; _dataTypeService = dataTypeService; _localizedTextService = localizedTextService; @@ -115,7 +118,7 @@ namespace Umbraco.Web.BackOffice.Controllers throw new HttpResponseException(HttpStatusCode.NotFound); } - var emptyContent = _mediaService.CreateMedia("", parentId, contentType.Alias, _webSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); + var emptyContent = _mediaService.CreateMedia("", parentId, contentType.Alias, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); var mapped = _umbracoMapper.Map(emptyContent); //remove the listview app if it exists @@ -277,7 +280,7 @@ namespace Umbraco.Web.BackOffice.Controllers protected int[] UserStartNodes { - get { return _userStartNodes ?? (_userStartNodes = _webSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService)); } + get { return _userStartNodes ?? (_userStartNodes = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService)); } } /// @@ -434,7 +437,7 @@ namespace Umbraco.Web.BackOffice.Controllers //if the current item is in the recycle bin if (foundMedia.Trashed == false) { - var moveResult = _mediaService.MoveToRecycleBin(foundMedia, _webSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); + var moveResult = _mediaService.MoveToRecycleBin(foundMedia, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); if (moveResult == false) { //returning an object of INotificationModel will ensure that any pending @@ -444,7 +447,7 @@ namespace Umbraco.Web.BackOffice.Controllers } else { - var deleteResult = _mediaService.Delete(foundMedia, _webSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); + var deleteResult = _mediaService.Delete(foundMedia, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); if (deleteResult == false) { //returning an object of INotificationModel will ensure that any pending @@ -468,7 +471,7 @@ namespace Umbraco.Web.BackOffice.Controllers var destinationParentID = move.ParentId; var sourceParentID = toMove.ParentId; - var moveResult = _mediaService.Move(toMove, move.ParentId, _webSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); + var moveResult = _mediaService.Move(toMove, move.ParentId, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); if (sourceParentID == destinationParentID) { @@ -542,7 +545,7 @@ namespace Umbraco.Web.BackOffice.Controllers } //save the item - var saveStatus = _mediaService.Save(contentItem.PersistedContent, _webSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); + var saveStatus = _mediaService.Save(contentItem.PersistedContent, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); //return the updated model var display = _umbracoMapper.Map(contentItem.PersistedContent); @@ -588,7 +591,7 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpPost] public IActionResult EmptyRecycleBin() { - _mediaService.EmptyRecycleBin(_webSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); + _mediaService.EmptyRecycleBin(_backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); return new UmbracoNotificationSuccessResponse(_localizedTextService.Localize("defaultdialogs/recycleBinIsEmpty")); } @@ -645,7 +648,7 @@ namespace Umbraco.Web.BackOffice.Controllers var mediaService = _mediaService; var f = mediaService.CreateMedia(folder.Name, parentId.Value, Constants.Conventions.MediaTypes.Folder); - mediaService.Save(f, _webSecurity.CurrentUser.Id); + mediaService.Save(f, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return _umbracoMapper.Map(f); } @@ -753,7 +756,7 @@ namespace Umbraco.Web.BackOffice.Controllers var mediaItemName = fileName.ToFriendlyName(); - var f = mediaService.CreateMedia(mediaItemName, parentId.Value, mediaType, _webSecurity.CurrentUser.Id); + var f = mediaService.CreateMedia(mediaItemName, parentId.Value, mediaType, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); await using (var stream = formFile.OpenReadStream()) @@ -762,7 +765,7 @@ namespace Umbraco.Web.BackOffice.Controllers } - var saveResult = mediaService.Save(f, _webSecurity.CurrentUser.Id); + var saveResult = mediaService.Save(f, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); if (saveResult == false) { AddCancelMessage(tempFiles, @@ -855,7 +858,7 @@ namespace Umbraco.Web.BackOffice.Controllers //ensure the user has access to this folder by parent id! if (validatePermissions && CheckPermissions( new Dictionary(), - _webSecurity.CurrentUser, + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, _mediaService, _entityService, intParentId) == false) diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs index 617d3f1538..31cc5d63cd 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs @@ -7,6 +7,7 @@ using Umbraco.Core; using Umbraco.Core.Dictionary; using Umbraco.Core.Mapping; using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.BackOffice.Filters; @@ -36,7 +37,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IMediaTypeService _mediaTypeService; private readonly IShortStringHelper _shortStringHelper; private readonly UmbracoMapper _umbracoMapper; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; public MediaTypeController(ICultureDictionary cultureDictionary, EditorValidatorCollection editorValidatorCollection, @@ -48,7 +49,7 @@ namespace Umbraco.Web.BackOffice.Controllers IShortStringHelper shortStringHelper, IEntityService entityService, IMediaService mediaService, - IWebSecurity webSecurity) + IBackofficeSecurityAccessor backofficeSecurityAccessor) : base( cultureDictionary, editorValidatorCollection, @@ -64,7 +65,7 @@ namespace Umbraco.Web.BackOffice.Controllers _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); _contentTypeService = contentTypeService ?? throw new ArgumentNullException(nameof(contentTypeService)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); } @@ -147,7 +148,7 @@ namespace Umbraco.Web.BackOffice.Controllers throw new HttpResponseException(HttpStatusCode.NotFound); } - _mediaTypeService.Delete(foundType, _webSecurity.CurrentUser.Id); + _mediaTypeService.Delete(foundType, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return Ok(); } @@ -241,14 +242,14 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpPost] public IActionResult DeleteContainer(int id) { - _mediaTypeService.DeleteContainer(id, _webSecurity.CurrentUser.Id); + _mediaTypeService.DeleteContainer(id, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return Ok(); } public IActionResult PostCreateContainer(int parentId, string name) { - var result = _mediaTypeService.CreateContainer(parentId, name, _webSecurity.CurrentUser.Id); + var result = _mediaTypeService.CreateContainer(parentId, name, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return result ? Ok(result.Result) //return the id @@ -257,7 +258,7 @@ namespace Umbraco.Web.BackOffice.Controllers public IActionResult PostRenameContainer(int id, string name) { - var result = _mediaTypeService.RenameContainer(id, name, _webSecurity.CurrentUser.Id); + var result = _mediaTypeService.RenameContainer(id, name, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return result ? Ok(result.Result) //return the id diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs index 6a93bf6437..6d60da0910 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs @@ -54,7 +54,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IMemberTypeService _memberTypeService; private readonly IDataTypeService _dataTypeService; private readonly ILocalizedTextService _localizedTextService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IJsonSerializer _jsonSerializer; public MemberController( @@ -70,7 +70,7 @@ namespace Umbraco.Web.BackOffice.Controllers IMemberService memberService, IMemberTypeService memberTypeService, IDataTypeService dataTypeService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IJsonSerializer jsonSerializer) : base(cultureDictionary, logger, shortStringHelper, eventMessages, localizedTextService) { @@ -82,7 +82,7 @@ namespace Umbraco.Web.BackOffice.Controllers _memberTypeService = memberTypeService; _dataTypeService = dataTypeService; _localizedTextService = localizedTextService; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _jsonSerializer = jsonSerializer; } @@ -310,7 +310,7 @@ namespace Umbraco.Web.BackOffice.Controllers throw new InvalidOperationException($"No member type found with alias {contentItem.ContentTypeAlias}"); var member = new Member(contentItem.Name, contentItem.Email, contentItem.Username, memberType, true) { - CreatorId = _webSecurity.CurrentUser.Id, + CreatorId = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id, RawPasswordValue = _passwordSecurity.HashPasswordForStorage(contentItem.Password.NewPassword), Comments = contentItem.Comments, IsApproved = contentItem.IsApproved @@ -328,13 +328,13 @@ namespace Umbraco.Web.BackOffice.Controllers /// private void UpdateMemberData(MemberSave contentItem) { - contentItem.PersistedContent.WriterId = _webSecurity.CurrentUser.Id; + contentItem.PersistedContent.WriterId = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id; // If the user doesn't have access to sensitive values, then we need to check if any of the built in member property types // have been marked as sensitive. If that is the case we cannot change these persisted values no matter what value has been posted. // There's only 3 special ones we need to deal with that are part of the MemberSave instance: Comments, IsApproved, IsLockedOut // but we will take care of this in a generic way below so that it works for all props. - if (!_webSecurity.CurrentUser.HasAccessToSensitiveData()) + if (!_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.HasAccessToSensitiveData()) { var memberType = _memberTypeService.Get(contentItem.PersistedContent.ContentTypeId); var sensitiveProperties = memberType @@ -458,7 +458,7 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpGet] public IActionResult ExportMemberData(Guid key) { - var currentUser = _webSecurity.CurrentUser; + var currentUser = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; if (currentUser.HasAccessToSensitiveData() == false) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs index 8ef8749c2d..e4d616cc43 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Strings; using Umbraco.Web.Models.ContentEditing; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Mapping; +using Umbraco.Core.Security; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; @@ -33,7 +34,7 @@ namespace Umbraco.Web.Editors public class MemberTypeController : ContentTypeControllerBase { private readonly IMemberTypeService _memberTypeService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IShortStringHelper _shortStringHelper; private readonly UmbracoMapper _umbracoMapper; private readonly ILocalizedTextService _localizedTextService; @@ -46,7 +47,7 @@ namespace Umbraco.Web.Editors IMemberTypeService memberTypeService, UmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IShortStringHelper shortStringHelper) : base(cultureDictionary, editorValidatorCollection, @@ -57,7 +58,7 @@ namespace Umbraco.Web.Editors localizedTextService) { _memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); _localizedTextService = @@ -141,7 +142,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.NotFound); } - _memberTypeService.Delete(foundType, _webSecurity.CurrentUser.Id); + _memberTypeService.Delete(foundType, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); return Ok(); } @@ -201,7 +202,7 @@ namespace Umbraco.Web.Editors var ctId = Convert.ToInt32(contentTypeSave.Id); var ct = ctId > 0 ? _memberTypeService.Get(ctId) : null; - if (_webSecurity.CurrentUser.HasAccessToSensitiveData() == false) + if (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.HasAccessToSensitiveData() == false) { //We need to validate if any properties on the contentTypeSave have had their IsSensitiveValue changed, //and if so, we need to check if the current user has access to sensitive values. If not, we have to return an error diff --git a/src/Umbraco.Web.BackOffice/Controllers/PackageController.cs b/src/Umbraco.Web.BackOffice/Controllers/PackageController.cs index d8df34748d..fa16288fb5 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PackageController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PackageController.cs @@ -10,6 +10,7 @@ using Semver; using Umbraco.Core; using Umbraco.Core.Hosting; using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; @@ -27,16 +28,16 @@ namespace Umbraco.Web.BackOffice.Controllers { private readonly IHostingEnvironment _hostingEnvironment; private readonly IPackagingService _packagingService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; public PackageController( IHostingEnvironment hostingEnvironment, IPackagingService packagingService, - IWebSecurity webSecurity) + IBackofficeSecurityAccessor backofficeSecurityAccessor) { _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); _packagingService = packagingService ?? throw new ArgumentNullException(nameof(packagingService)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); } public IEnumerable GetCreatedPackages() @@ -90,7 +91,7 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpDelete] public IActionResult DeleteCreatedPackage(int packageId) { - _packagingService.DeleteCreatedPackage(packageId, _webSecurity.GetUserId().ResultOr(0)); + _packagingService.DeleteCreatedPackage(packageId, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); return Ok(); } diff --git a/src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs b/src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs index b61e86746a..fe9523f410 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models.Packaging; using Umbraco.Net; using Umbraco.Core.Packaging; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.WebAssets; using Umbraco.Web.BackOffice.Filters; @@ -38,7 +39,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IRuntimeMinifier _runtimeMinifier; private readonly IPackagingService _packagingService; private readonly ILogger _logger; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly ILocalizedTextService _localizedTextService; public PackageInstallController( @@ -48,7 +49,7 @@ namespace Umbraco.Web.BackOffice.Controllers IRuntimeMinifier runtimeMinifier, IPackagingService packagingService, ILogger logger, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILocalizedTextService localizedTextService) { _umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion)); @@ -57,7 +58,7 @@ namespace Umbraco.Web.BackOffice.Controllers _runtimeMinifier = runtimeMinifier ?? throw new ArgumentNullException(nameof(runtimeMinifier)); _packagingService = packagingService ?? throw new ArgumentNullException(nameof(packagingService)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); } @@ -87,14 +88,14 @@ namespace Umbraco.Web.BackOffice.Controllers var package = _packagingService.GetInstalledPackageById(packageId); if (package == null) return NotFound(); - var summary = _packagingService.UninstallPackage(package.Name, _webSecurity.GetUserId().ResultOr(0)); + var summary = _packagingService.UninstallPackage(package.Name, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); //now get all other packages by this name since we'll uninstall all versions foreach (var installed in _packagingService.GetAllInstalledPackages() .Where(x => x.Name == package.Name && x.Id != package.Id)) { //remove from the xml - _packagingService.DeleteInstalledPackage(installed.Id, _webSecurity.GetUserId().ResultOr(0)); + _packagingService.DeleteInstalledPackage(installed.Id, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); } } catch (Exception ex) @@ -223,7 +224,7 @@ namespace Umbraco.Web.BackOffice.Controllers var packageFile = await _packagingService.FetchPackageFileAsync( Guid.Parse(packageGuid), _umbracoVersion.Current, - _webSecurity.GetUserId().ResultOr(0)); + _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); fileName = packageFile.Name; } @@ -310,7 +311,7 @@ namespace Umbraco.Web.BackOffice.Controllers if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id); var zipFile = new FileInfo(definition.PackagePath); - var installedFiles = _packagingService.InstallCompiledPackageFiles(definition, zipFile, _webSecurity.GetUserId().ResultOr(0)); + var installedFiles = _packagingService.InstallCompiledPackageFiles(definition, zipFile, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); //set a restarting marker and reset the app pool _umbracoApplicationLifetime.Restart(); @@ -342,7 +343,7 @@ namespace Umbraco.Web.BackOffice.Controllers if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id); var zipFile = new FileInfo(definition.PackagePath); - var installSummary = _packagingService.InstallCompiledPackageData(definition, zipFile, _webSecurity.GetUserId().ResultOr(0)); + var installSummary = _packagingService.InstallCompiledPackageData(definition, zipFile, _backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); return model; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs index 3878eb9b14..771ca28f55 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.WebAssets; using Umbraco.Extensions; @@ -32,8 +33,8 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly UmbracoFeatures _features; private readonly GlobalSettings _globalSettings; private readonly IPublishedSnapshotService _publishedSnapshotService; - private readonly IWebSecurity _webSecurity; - private readonly ILocalizationService _localizationService; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; + private readonly ILocalizationService _localizationService; private readonly IHostingEnvironment _hostingEnvironment; private readonly ICookieManager _cookieManager; private readonly IRuntimeMinifier _runtimeMinifier; @@ -43,7 +44,7 @@ namespace Umbraco.Web.BackOffice.Controllers UmbracoFeatures features, IOptions globalSettings, IPublishedSnapshotService publishedSnapshotService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILocalizationService localizationService, IHostingEnvironment hostingEnvironment, ICookieManager cookieManager, @@ -53,7 +54,7 @@ namespace Umbraco.Web.BackOffice.Controllers _features = features; _globalSettings = globalSettings.Value; _publishedSnapshotService = publishedSnapshotService; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _localizationService = localizationService; _hostingEnvironment = hostingEnvironment; _cookieManager = cookieManager; @@ -107,7 +108,7 @@ namespace Umbraco.Web.BackOffice.Controllers [UmbracoAuthorize] public ActionResult Frame(int id, string culture) { - var user = _webSecurity.CurrentUser; + var user = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; var previewToken = _publishedSnapshotService.EnterPreview(user, id); diff --git a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs index 7a4b18e807..c5a2108ced 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs @@ -15,6 +15,7 @@ using Umbraco.Web.Security; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Microsoft.Extensions.Options; +using Umbraco.Core.Security; namespace Umbraco.Web.BackOffice.Controllers { @@ -23,15 +24,16 @@ namespace Umbraco.Web.BackOffice.Controllers { private readonly ILogger _logger; private readonly WebRoutingSettings _webRoutingSettings; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IRedirectUrlService _redirectUrlService; private readonly UmbracoMapper _umbracoMapper; private readonly IHostingEnvironment _hostingEnvironment; private readonly IConfigManipulator _configManipulator; - public RedirectUrlManagementController(ILogger logger, + public RedirectUrlManagementController( + ILogger logger, IOptions webRoutingSettings, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IRedirectUrlService redirectUrlService, UmbracoMapper umbracoMapper, IHostingEnvironment hostingEnvironment, @@ -39,7 +41,7 @@ namespace Umbraco.Web.BackOffice.Controllers { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _webRoutingSettings = webRoutingSettings.Value ?? throw new ArgumentNullException(nameof(webRoutingSettings)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _redirectUrlService = redirectUrlService ?? throw new ArgumentNullException(nameof(redirectUrlService)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); @@ -54,7 +56,7 @@ namespace Umbraco.Web.BackOffice.Controllers public IActionResult GetEnableState() { var enabled = _webRoutingSettings.DisableRedirectUrlTracking == false; - var userIsAdmin = _webSecurity.CurrentUser.IsAdmin(); + var userIsAdmin = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.IsAdmin(); return Ok(new { enabled, userIsAdmin }); } @@ -110,7 +112,7 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpPost] public IActionResult ToggleUrlTracker(bool disable) { - var userIsAdmin = _webSecurity.CurrentUser.IsAdmin(); + var userIsAdmin = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.IsAdmin(); if (userIsAdmin == false) { var errorMessage = "User is not a member of the administrators group and so is not allowed to toggle the URL tracker"; diff --git a/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs b/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs index 5239994e04..810e3e5646 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc.Controllers; using Umbraco.Core; using Umbraco.Core.Mapping; using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.Common.Attributes; @@ -27,15 +28,15 @@ namespace Umbraco.Web.Editors private readonly ISectionService _sectionService; private readonly ITreeService _treeService; private readonly UmbracoMapper _umbracoMapper; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; public SectionController( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILocalizedTextService localizedTextService, IDashboardService dashboardService, ISectionService sectionService, ITreeService treeService, UmbracoMapper umbracoMapper, IControllerFactory controllerFactory) { - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _localizedTextService = localizedTextService; _dashboardService = dashboardService; _sectionService = sectionService; @@ -46,7 +47,7 @@ namespace Umbraco.Web.Editors public IEnumerable
GetSections() { - var sections = _sectionService.GetAllowedSections(_webSecurity.GetUserId().ResultOr(0)); + var sections = _sectionService.GetAllowedSections(_backofficeSecurityAccessor.BackofficeSecurity.GetUserId().ResultOr(0)); var sectionModels = sections.Select(_umbracoMapper.Map
).ToArray(); @@ -58,7 +59,7 @@ namespace Umbraco.Web.Editors ControllerContext = ControllerContext }; - var dashboards = _dashboardService.GetDashboards(_webSecurity.CurrentUser); + var dashboards = _dashboardService.GetDashboards(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser); //now we can add metadata for each section so that the UI knows if there's actually anything at all to render for //a dashboard for a given section, then the UI can deal with it accordingly (i.e. redirect to the first tree) @@ -104,10 +105,10 @@ namespace Umbraco.Web.Editors { var sections = _sectionService.GetSections(); var mapped = sections.Select(_umbracoMapper.Map
); - if (_webSecurity.CurrentUser.IsAdmin()) + if (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.IsAdmin()) return mapped; - return mapped.Where(x => _webSecurity.CurrentUser.AllowedSections.Contains(x.Alias)).ToArray(); + return mapped.Where(x => _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.AllowedSections.Contains(x.Alias)).ToArray(); } } } diff --git a/src/Umbraco.Web.BackOffice/Controllers/TourController.cs b/src/Umbraco.Web.BackOffice/Controllers/TourController.cs index 6e7af87a11..818b4edf66 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TourController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TourController.cs @@ -7,6 +7,7 @@ using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models; @@ -21,21 +22,21 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly TourFilterCollection _filters; private readonly IHostingEnvironment _hostingEnvironment; private readonly TourSettings _tourSettings; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IContentTypeService _contentTypeService; public TourController( TourFilterCollection filters, IHostingEnvironment hostingEnvironment, IOptions tourSettings, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IContentTypeService contentTypeService) { _filters = filters; _hostingEnvironment = hostingEnvironment; _tourSettings = tourSettings.Value; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _contentTypeService = contentTypeService; } @@ -46,7 +47,7 @@ namespace Umbraco.Web.BackOffice.Controllers if (_tourSettings.EnableTours == false) return result; - var user = _webSecurity.CurrentUser; + var user = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; if (user == null) return result; @@ -188,7 +189,7 @@ namespace Umbraco.Web.BackOffice.Controllers var backOfficeTours = tours.Where(x => aliasFilters.Count == 0 || aliasFilters.All(filter => filter.IsMatch(x.Alias)) == false); - var user = _webSecurity.CurrentUser; + var user = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; var localizedTours = backOfficeTours.Where(x => string.IsNullOrWhiteSpace(x.Culture) || x.Culture.Equals(user.Language, diff --git a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs index 16fcb5b38c..71dc97c835 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs @@ -10,6 +10,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Models; @@ -23,20 +24,20 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IUpgradeService _upgradeService; private readonly IUmbracoVersion _umbracoVersion; private readonly ICookieManager _cookieManager; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly GlobalSettings _globalSettings; public UpdateCheckController( IUpgradeService upgradeService, IUmbracoVersion umbracoVersion, ICookieManager cookieManager, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IOptions globalSettings) { _upgradeService = upgradeService ?? throw new ArgumentNullException(nameof(upgradeService)); _umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion)); _cookieManager = cookieManager ?? throw new ArgumentNullException(nameof(cookieManager)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); } @@ -45,7 +46,7 @@ namespace Umbraco.Web.BackOffice.Controllers { var updChkCookie = _cookieManager.GetCookieValue("UMB_UPDCHK"); var updateCheckCookie = updChkCookie ?? string.Empty; - if (_globalSettings.VersionCheckPeriod > 0 && string.IsNullOrEmpty(updateCheckCookie) && _webSecurity.CurrentUser.IsAdmin()) + if (_globalSettings.VersionCheckPeriod > 0 && string.IsNullOrEmpty(updateCheckCookie) && _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.IsAdmin()) { try { diff --git a/src/Umbraco.Web.BackOffice/Controllers/UserGroupsController.cs b/src/Umbraco.Web.BackOffice/Controllers/UserGroupsController.cs index 44b675771b..6d641c9cf9 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UserGroupsController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UserGroupsController.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Mvc; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.BackOffice.Filters; @@ -27,13 +28,13 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IContentService _contentService; private readonly IEntityService _entityService; private readonly IMediaService _mediaService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly UmbracoMapper _umbracoMapper; private readonly ILocalizedTextService _localizedTextService; private readonly IShortStringHelper _shortStringHelper; public UserGroupsController(IUserService userService, IContentService contentService, - IEntityService entityService, IMediaService mediaService, IWebSecurity webSecurity, + IEntityService entityService, IMediaService mediaService, IBackofficeSecurityAccessor backofficeSecurityAccessor, UmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper) { @@ -41,7 +42,7 @@ namespace Umbraco.Web.BackOffice.Controllers _contentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); @@ -57,19 +58,19 @@ namespace Umbraco.Web.BackOffice.Controllers var authHelper = new UserGroupEditorAuthorizationHelper( _userService, _contentService, _mediaService, _entityService); - var isAuthorized = authHelper.AuthorizeGroupAccess(_webSecurity.CurrentUser, userGroupSave.Alias); + var isAuthorized = authHelper.AuthorizeGroupAccess(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, userGroupSave.Alias); if (isAuthorized == false) throw new HttpResponseException(HttpStatusCode.Unauthorized, isAuthorized.Result); //if sections were added we need to check that the current user has access to that section - isAuthorized = authHelper.AuthorizeSectionChanges(_webSecurity.CurrentUser, + isAuthorized = authHelper.AuthorizeSectionChanges(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, userGroupSave.PersistedUserGroup.AllowedSections, userGroupSave.Sections); if (isAuthorized == false) throw new HttpResponseException(HttpStatusCode.Unauthorized, isAuthorized.Result); //if start nodes were changed we need to check that the current user has access to them - isAuthorized = authHelper.AuthorizeStartNodeChanges(_webSecurity.CurrentUser, + isAuthorized = authHelper.AuthorizeStartNodeChanges(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, userGroupSave.PersistedUserGroup.StartContentId, userGroupSave.StartContentId, userGroupSave.PersistedUserGroup.StartMediaId, @@ -111,18 +112,18 @@ namespace Umbraco.Web.BackOffice.Controllers private void EnsureNonAdminUserIsInSavedUserGroup(UserGroupSave userGroupSave) { - if (_webSecurity.CurrentUser.IsAdmin()) + if (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.IsAdmin()) { return; } var userIds = userGroupSave.Users.ToList(); - if (userIds.Contains(_webSecurity.CurrentUser.Id)) + if (userIds.Contains(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id)) { return; } - userIds.Add(_webSecurity.CurrentUser.Id); + userIds.Add(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Id); userGroupSave.Users = userIds; } @@ -144,7 +145,7 @@ namespace Umbraco.Web.BackOffice.Controllers var allGroups = _umbracoMapper.MapEnumerable(_userService.GetAllUserGroups()) .ToList(); - var isAdmin = _webSecurity.CurrentUser.IsAdmin(); + var isAdmin = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.IsAdmin(); if (isAdmin) return allGroups; if (onlyCurrentUserGroups == false) @@ -155,7 +156,7 @@ namespace Umbraco.Web.BackOffice.Controllers } //we cannot return user groups that this user does not have access to - var currentUserGroups = _webSecurity.CurrentUser.Groups.Select(x => x.Alias).ToArray(); + var currentUserGroups = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Groups.Select(x => x.Alias).ToArray(); return allGroups.Where(x => currentUserGroups.Contains(x.Alias)).ToArray(); } diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs index 3cffa307eb..cfa1e980bd 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs @@ -24,8 +24,12 @@ using Umbraco.Core.Media; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; +using Umbraco.Web.Models; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.WebApi.Filters; using Umbraco.Extensions; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.BackOffice.ModelBinders; @@ -58,7 +62,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly SecuritySettings _securitySettings; private readonly IRequestAccessor _requestAccessor; private readonly IEmailSender _emailSender; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly AppCaches _appCaches; private readonly IShortStringHelper _shortStringHelper; private readonly IUserService _userService; @@ -81,7 +85,7 @@ namespace Umbraco.Web.BackOffice.Controllers IOptions securitySettings, IRequestAccessor requestAccessor, IEmailSender emailSender, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, AppCaches appCaches, IShortStringHelper shortStringHelper, IUserService userService, @@ -103,7 +107,7 @@ namespace Umbraco.Web.BackOffice.Controllers _securitySettings = securitySettings.Value; _requestAccessor = requestAccessor; _emailSender = emailSender; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _appCaches = appCaches; _shortStringHelper = shortStringHelper; _userService = userService; @@ -124,7 +128,7 @@ namespace Umbraco.Web.BackOffice.Controllers /// public string[] GetCurrentUserAvatarUrls() { - var urls = _webSecurity.CurrentUser.GetUserAvatarUrls(_appCaches.RuntimeCache, _mediaFileSystem, _imageUrlGenerator); + var urls = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.GetUserAvatarUrls(_appCaches.RuntimeCache, _mediaFileSystem, _imageUrlGenerator); if (urls == null) throw new HttpResponseException(HttpStatusCode.BadRequest, "Could not access Gravatar endpoint"); @@ -290,7 +294,7 @@ namespace Umbraco.Web.BackOffice.Controllers var hideDisabledUsers = _securitySettings.HideDisabledUsersInBackoffice; var excludeUserGroups = new string[0]; - var isAdmin = _webSecurity.CurrentUser.IsAdmin(); + var isAdmin = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.IsAdmin(); if (isAdmin == false) { //this user is not an admin so in that case we need to exclude all admin users @@ -299,7 +303,7 @@ namespace Umbraco.Web.BackOffice.Controllers var filterQuery = _sqlContext.Query(); - if (!_webSecurity.CurrentUser.IsSuper()) + if (!_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.IsSuper()) { // only super can see super - but don't use IsSuper, cannot be mapped to SQL //filterQuery.Where(x => !x.IsSuper()); @@ -360,7 +364,7 @@ namespace Umbraco.Web.BackOffice.Controllers //Perform authorization here to see if the current user can actually save this user with the info being requested var authHelper = new UserEditorAuthorizationHelper(_contentService,_mediaService, _userService, _entityService); - var canSaveUser = authHelper.IsAuthorized(_webSecurity.CurrentUser, null, null, null, userSave.UserGroups); + var canSaveUser = authHelper.IsAuthorized(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, null, null, null, userSave.UserGroups); if (canSaveUser == false) { throw new HttpResponseException(HttpStatusCode.Unauthorized, canSaveUser.Result); @@ -444,7 +448,7 @@ namespace Umbraco.Web.BackOffice.Controllers //Perform authorization here to see if the current user can actually save this user with the info being requested var authHelper = new UserEditorAuthorizationHelper(_contentService,_mediaService, _userService, _entityService); - var canSaveUser = authHelper.IsAuthorized(_webSecurity.CurrentUser, user, null, null, userSave.UserGroups); + var canSaveUser = authHelper.IsAuthorized(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, user, null, null, userSave.UserGroups); if (canSaveUser == false) { throw new HttpResponseException(HttpStatusCode.Unauthorized, canSaveUser.Result); @@ -479,7 +483,7 @@ namespace Umbraco.Web.BackOffice.Controllers //send the email - await SendUserInviteEmailAsync(display, _webSecurity.CurrentUser.Name, _webSecurity.CurrentUser.Email, user, userSave.Message); + await SendUserInviteEmailAsync(display, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Name, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Email, user, userSave.Message); display.AddSuccessNotification(_localizedTextService.Localize("speechBubbles/resendInviteHeader"), _localizedTextService.Localize("speechBubbles/resendInviteSuccess", new[] { user.Name })); @@ -575,7 +579,7 @@ namespace Umbraco.Web.BackOffice.Controllers //Perform authorization here to see if the current user can actually save this user with the info being requested var authHelper = new UserEditorAuthorizationHelper(_contentService,_mediaService, _userService, _entityService); - var canSaveUser = authHelper.IsAuthorized(_webSecurity.CurrentUser, found, userSave.StartContentIds, userSave.StartMediaIds, userSave.UserGroups); + var canSaveUser = authHelper.IsAuthorized(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, found, userSave.StartContentIds, userSave.StartMediaIds, userSave.UserGroups); if (canSaveUser == false) { throw new HttpResponseException(HttpStatusCode.Unauthorized, canSaveUser.Result); @@ -658,7 +662,7 @@ namespace Umbraco.Web.BackOffice.Controllers } var passwordChanger = new PasswordChanger(_logger); - var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(_webSecurity.CurrentUser, found, changingPasswordModel, _backOfficeUserManager); + var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, found, changingPasswordModel, _backOfficeUserManager); if (passwordChangeResult.Success) { @@ -683,7 +687,7 @@ namespace Umbraco.Web.BackOffice.Controllers [AdminUsersAuthorize("userIds")] public IActionResult PostDisableUsers([FromQuery]int[] userIds) { - var tryGetCurrentUserId = _webSecurity.GetUserId(); + var tryGetCurrentUserId = _backofficeSecurityAccessor.BackofficeSecurity.GetUserId(); if (tryGetCurrentUserId && userIds.Contains(tryGetCurrentUserId.Result)) { throw HttpResponseException.CreateNotificationValidationErrorResponse("The current user cannot disable itself"); diff --git a/src/Umbraco.Web.BackOffice/Filters/AdminUsersAuthorizeAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/AdminUsersAuthorizeAttribute.cs index 526504b04d..4920b6351a 100644 --- a/src/Umbraco.Web.BackOffice/Filters/AdminUsersAuthorizeAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/AdminUsersAuthorizeAttribute.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Umbraco.Core; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Editors; using Umbraco.Web.Security; @@ -34,7 +35,7 @@ namespace Umbraco.Web.BackOffice.Filters private readonly IContentService _contentService; private readonly IMediaService _mediaService; private readonly IEntityService _entityService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; public AdminUsersAuthorizeFilter( IRequestAccessor requestAccessor, @@ -42,7 +43,7 @@ namespace Umbraco.Web.BackOffice.Filters IContentService contentService, IMediaService mediaService, IEntityService entityService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, string parameterName) { _requestAccessor = requestAccessor; @@ -50,7 +51,7 @@ namespace Umbraco.Web.BackOffice.Filters _contentService = contentService; _mediaService = mediaService; _entityService = entityService; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _parameterName = parameterName; } @@ -86,7 +87,7 @@ namespace Umbraco.Web.BackOffice.Filters var users = _userService.GetUsersById(userIds); var authHelper = new UserEditorAuthorizationHelper(_contentService, _mediaService, _userService, _entityService); - return users.All(user => authHelper.IsAuthorized(_webSecurity.CurrentUser, user, null, null, null) != false); + return users.All(user => authHelper.IsAuthorized(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, user, null, null, null) != false); } } diff --git a/src/Umbraco.Web.BackOffice/Filters/AppendUserModifiedHeaderAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/AppendUserModifiedHeaderAttribute.cs index 6541d122ab..c484de3bfb 100644 --- a/src/Umbraco.Web.BackOffice/Filters/AppendUserModifiedHeaderAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/AppendUserModifiedHeaderAttribute.cs @@ -43,8 +43,8 @@ namespace Umbraco.Web.BackOffice.Filters throw new InvalidOperationException($"No argument found for the current action with the name: {_userIdParameter}"); } - var webSecurity = context.HttpContext.RequestServices.GetService(); - var user = webSecurity.CurrentUser; + var backofficeSecurity = context.HttpContext.RequestServices.GetService(); + var user = backofficeSecurity.CurrentUser; if (user == null) { return; diff --git a/src/Umbraco.Web.BackOffice/Filters/ContentModelValidator.cs b/src/Umbraco.Web.BackOffice/Filters/ContentModelValidator.cs index 71323b1659..eee5cb6d30 100644 --- a/src/Umbraco.Web.BackOffice/Filters/ContentModelValidator.cs +++ b/src/Umbraco.Web.BackOffice/Filters/ContentModelValidator.cs @@ -22,14 +22,14 @@ namespace Umbraco.Web.BackOffice.Filters internal abstract class ContentModelValidator { - protected IWebSecurity WebSecurity { get; } + protected IBackofficeSecurity BackofficeSecurity { get; } public IPropertyValidationService PropertyValidationService { get; } protected ILogger Logger { get; } - protected ContentModelValidator(ILogger logger, IWebSecurity webSecurity, IPropertyValidationService propertyValidationService) + protected ContentModelValidator(ILogger logger, IBackofficeSecurity backofficeSecurity, IPropertyValidationService propertyValidationService) { Logger = logger ?? throw new ArgumentNullException(nameof(logger)); - WebSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + BackofficeSecurity = backofficeSecurity ?? throw new ArgumentNullException(nameof(backofficeSecurity)); PropertyValidationService = propertyValidationService ?? throw new ArgumentNullException(nameof(propertyValidationService)); } } @@ -53,10 +53,10 @@ namespace Umbraco.Web.BackOffice.Filters protected ContentModelValidator( ILogger logger, - IWebSecurity webSecurity, + IBackofficeSecurity backofficeSecurity, ILocalizedTextService textService, IPropertyValidationService propertyValidationService) - : base(logger, webSecurity, propertyValidationService) + : base(logger, backofficeSecurity, propertyValidationService) { _textService = textService ?? throw new ArgumentNullException(nameof(textService)); } diff --git a/src/Umbraco.Web.BackOffice/Filters/ContentSaveModelValidator.cs b/src/Umbraco.Web.BackOffice/Filters/ContentSaveModelValidator.cs index 493b2e04ea..a73b20dca5 100644 --- a/src/Umbraco.Web.BackOffice/Filters/ContentSaveModelValidator.cs +++ b/src/Umbraco.Web.BackOffice/Filters/ContentSaveModelValidator.cs @@ -13,10 +13,10 @@ namespace Umbraco.Web.BackOffice.Filters { public ContentSaveModelValidator( ILogger logger, - IWebSecurity webSecurity, + IBackofficeSecurity backofficeSecurity, ILocalizedTextService textService, IPropertyValidationService propertyValidationService) - : base(logger, webSecurity, textService, propertyValidationService) + : base(logger, backofficeSecurity, textService, propertyValidationService) { } diff --git a/src/Umbraco.Web.BackOffice/Filters/ContentSaveValidationAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/ContentSaveValidationAttribute.cs index 216f94499b..457929690f 100644 --- a/src/Umbraco.Web.BackOffice/Filters/ContentSaveValidationAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/ContentSaveValidationAttribute.cs @@ -35,12 +35,12 @@ namespace Umbraco.Web.BackOffice.Filters private readonly ILogger _logger; private readonly ILocalizedTextService _textService; private readonly IUserService _userService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; public ContentSaveValidationFilter( ILogger logger, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILocalizedTextService textService, IContentService contentService, IUserService userService, @@ -48,7 +48,7 @@ namespace Umbraco.Web.BackOffice.Filters IPropertyValidationService propertyValidationService) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _textService = textService ?? throw new ArgumentNullException(nameof(textService)); _contentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); @@ -59,11 +59,11 @@ namespace Umbraco.Web.BackOffice.Filters public void OnActionExecuting(ActionExecutingContext context) { var model = (ContentItemSave) context.ActionArguments["contentItem"]; - var contentItemValidator = new ContentSaveModelValidator(_logger, _webSecurity, _textService, _propertyValidationService); + var contentItemValidator = new ContentSaveModelValidator(_logger, _backofficeSecurityAccessor.BackofficeSecurity, _textService, _propertyValidationService); if (!ValidateAtLeastOneVariantIsBeingSaved(model, context)) return; if (!contentItemValidator.ValidateExistingContent(model, context)) return; - if (!ValidateUserAccess(model, context, _webSecurity)) return; + if (!ValidateUserAccess(model, context, _backofficeSecurityAccessor.BackofficeSecurity)) return; //validate for each variant that is being updated foreach (var variant in model.Variants.Where(x => x.Save)) @@ -101,9 +101,9 @@ namespace Umbraco.Web.BackOffice.Filters ///
/// /// - /// + /// private bool ValidateUserAccess(ContentItemSave contentItem, ActionExecutingContext actionContext, - IWebSecurity webSecurity) + IBackofficeSecurity backofficeSecurity) { // We now need to validate that the user is allowed to be doing what they are doing. // Based on the action we need to check different permissions. @@ -217,13 +217,13 @@ namespace Umbraco.Web.BackOffice.Filters actionContext.HttpContext.Items[typeof(IContent).ToString()] = contentItem; accessResult = ContentPermissionsHelper.CheckPermissions( - contentToCheck, webSecurity.CurrentUser, + contentToCheck, backofficeSecurity.CurrentUser, _userService, _entityService, permissionToCheck.ToArray()); } else { accessResult = ContentPermissionsHelper.CheckPermissions( - contentIdToCheck, webSecurity.CurrentUser, + contentIdToCheck, backofficeSecurity.CurrentUser, _userService, _contentService, _entityService, out contentToCheck, permissionToCheck.ToArray()); diff --git a/src/Umbraco.Web.BackOffice/Filters/EnsureUserPermissionForContentAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/EnsureUserPermissionForContentAttribute.cs index 131854808e..1c271d93e6 100644 --- a/src/Umbraco.Web.BackOffice/Filters/EnsureUserPermissionForContentAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/EnsureUserPermissionForContentAttribute.cs @@ -75,7 +75,7 @@ namespace Umbraco.Web.BackOffice.Filters private sealed class EnsureUserPermissionForContentFilter : IActionFilter { private readonly int? _nodeId; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IEntityService _entityService; private readonly IUserService _userService; private readonly IContentService _contentService; @@ -83,58 +83,58 @@ namespace Umbraco.Web.BackOffice.Filters private readonly char? _permissionToCheck; public EnsureUserPermissionForContentFilter( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IEntityService entityService, IUserService userService, IContentService contentService, string paramName) - :this(webSecurity, entityService, userService, contentService, null, paramName, ActionBrowse.ActionLetter) + :this(backofficeSecurityAccessor, entityService, userService, contentService, null, paramName, ActionBrowse.ActionLetter) { } public EnsureUserPermissionForContentFilter( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IEntityService entityService, IUserService userService, IContentService contentService, int nodeId, char permissionToCheck) - :this(webSecurity, entityService, userService, contentService, nodeId, null, permissionToCheck) + :this(backofficeSecurityAccessor, entityService, userService, contentService, nodeId, null, permissionToCheck) { } public EnsureUserPermissionForContentFilter( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IEntityService entityService, IUserService userService, IContentService contentService, int nodeId) - :this(webSecurity, entityService, userService, contentService, nodeId, null, null) + :this(backofficeSecurityAccessor, entityService, userService, contentService, nodeId, null, null) { } public EnsureUserPermissionForContentFilter( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IEntityService entityService, IUserService userService, IContentService contentService, string paramName, char permissionToCheck) - :this(webSecurity, entityService, userService, contentService, null, paramName, permissionToCheck) + :this(backofficeSecurityAccessor, entityService, userService, contentService, null, paramName, permissionToCheck) { } private EnsureUserPermissionForContentFilter( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IEntityService entityService, IUserService userService, IContentService contentService, int? nodeId, string paramName, char? permissionToCheck) { - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _contentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); @@ -156,7 +156,7 @@ namespace Umbraco.Web.BackOffice.Filters public void OnActionExecuting(ActionExecutingContext context) { - if (_webSecurity.CurrentUser == null) + if (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser == null) { //not logged in throw new HttpResponseException(HttpStatusCode.Unauthorized); @@ -213,7 +213,7 @@ namespace Umbraco.Web.BackOffice.Filters } var permissionResult = ContentPermissionsHelper.CheckPermissions(nodeId, - _webSecurity.CurrentUser, + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, _userService, _contentService, _entityService, diff --git a/src/Umbraco.Web.BackOffice/Filters/EnsureUserPermissionForMediaAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/EnsureUserPermissionForMediaAttribute.cs index 526e95cf96..3bf3bd8730 100644 --- a/src/Umbraco.Web.BackOffice/Filters/EnsureUserPermissionForMediaAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/EnsureUserPermissionForMediaAttribute.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.Common.Exceptions; @@ -40,7 +41,7 @@ namespace Umbraco.Web.WebApi.Filters { private readonly int? _nodeId; private readonly string _paramName; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IEntityService _entityService; private readonly IMediaService _mediaService; @@ -48,21 +49,21 @@ namespace Umbraco.Web.WebApi.Filters /// This constructor will only be able to test the start node access ///
public EnsureUserPermissionForMediaFilter( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IEntityService entityService, IMediaService mediaService, int nodeId) - :this(webSecurity, entityService, mediaService, nodeId, null) + :this(backofficeSecurityAccessor, entityService, mediaService, nodeId, null) { _nodeId = nodeId; } public EnsureUserPermissionForMediaFilter( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IEntityService entityService, IMediaService mediaService, string paramName) - :this(webSecurity, entityService, mediaService,null, paramName) + :this(backofficeSecurityAccessor, entityService, mediaService,null, paramName) { if (paramName == null) throw new ArgumentNullException(nameof(paramName)); if (string.IsNullOrEmpty(paramName)) @@ -70,12 +71,12 @@ namespace Umbraco.Web.WebApi.Filters } private EnsureUserPermissionForMediaFilter( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, IEntityService entityService, IMediaService mediaService, int? nodeId, string paramName) { - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); @@ -117,7 +118,7 @@ namespace Umbraco.Web.WebApi.Filters public void OnActionExecuting(ActionExecutingContext context) { - if (_webSecurity.CurrentUser == null) + if (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser == null) { throw new HttpResponseException(System.Net.HttpStatusCode.Unauthorized); } @@ -158,7 +159,7 @@ namespace Umbraco.Web.WebApi.Filters if (MediaController.CheckPermissions( context.HttpContext.Items, - _webSecurity.CurrentUser, + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, _mediaService, _entityService, nodeId)) diff --git a/src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttribute.cs index 855cd05829..c67bbefd89 100644 --- a/src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttribute.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Mvc; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Actions; using Umbraco.Web.Security; @@ -60,8 +61,8 @@ namespace Umbraco.Web.BackOffice.Filters - public FilterAllowedOutgoingContentFilter(Type outgoingType, string propertyName, char permissionToCheck, IUserService userService, IEntityService entityService, IWebSecurity webSecurity) - : base(entityService, webSecurity, outgoingType, propertyName) + public FilterAllowedOutgoingContentFilter(Type outgoingType, string propertyName, char permissionToCheck, IUserService userService, IEntityService entityService, IBackofficeSecurityAccessor backofficeSecurityAccessor) + : base(entityService, backofficeSecurityAccessor, outgoingType, propertyName) { _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); diff --git a/src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingMediaAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingMediaAttribute.cs index a600f5a928..a6325e0650 100644 --- a/src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingMediaAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingMediaAttribute.cs @@ -34,13 +34,13 @@ namespace Umbraco.Web.WebApi.Filters { private readonly Type _outgoingType; private readonly IEntityService _entityService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly string _propertyName; - public FilterAllowedOutgoingMediaFilter(IEntityService entityService, IWebSecurity webSecurity, Type outgoingType, string propertyName) + public FilterAllowedOutgoingMediaFilter(IEntityService entityService, IBackofficeSecurityAccessor backofficeSecurityAccessor, Type outgoingType, string propertyName) { _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _propertyName = propertyName; _outgoingType = outgoingType; @@ -57,7 +57,7 @@ namespace Umbraco.Web.WebApi.Filters { if (context.Result == null) return; - var user = _webSecurity.CurrentUser; + var user = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; if (user == null) return; var objectContent = context.Result as ObjectResult; diff --git a/src/Umbraco.Web.BackOffice/Filters/IsCurrentUserModelFilterAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/IsCurrentUserModelFilterAttribute.cs index 521dd34d77..380995db4d 100644 --- a/src/Umbraco.Web.BackOffice/Filters/IsCurrentUserModelFilterAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/IsCurrentUserModelFilterAttribute.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; +using Umbraco.Core.Security; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Security; @@ -15,11 +16,11 @@ namespace Umbraco.Web.BackOffice.Filters private class IsCurrentUserModelFilter : IActionFilter { - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; - public IsCurrentUserModelFilter(IWebSecurity webSecurity) + public IsCurrentUserModelFilter(IBackofficeSecurityAccessor backofficeSecurityAccessor) { - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; } @@ -27,7 +28,7 @@ namespace Umbraco.Web.BackOffice.Filters { if (context.Result == null) return; - var user = _webSecurity.CurrentUser; + var user = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; if (user == null) return; var objectContent = context.Result as ObjectResult; diff --git a/src/Umbraco.Web.BackOffice/Filters/MediaItemSaveValidationAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/MediaItemSaveValidationAttribute.cs index a81f4d329a..ee89a8e2fd 100644 --- a/src/Umbraco.Web.BackOffice/Filters/MediaItemSaveValidationAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/MediaItemSaveValidationAttribute.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc.Filters; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.Models.ContentEditing; @@ -29,18 +30,18 @@ namespace Umbraco.Web.BackOffice.Filters private readonly ILogger _logger; private readonly IMediaService _mediaService; private readonly ILocalizedTextService _textService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; public MediaItemSaveValidationFilter( ILogger logger, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILocalizedTextService textService, IMediaService mediaService, IEntityService entityService, IPropertyValidationService propertyValidationService) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _textService = textService ?? throw new ArgumentNullException(nameof(textService)); _mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); @@ -50,7 +51,7 @@ namespace Umbraco.Web.BackOffice.Filters public void OnActionExecuting(ActionExecutingContext context) { var model = (MediaItemSave) context.ActionArguments["contentItem"]; - var contentItemValidator = new MediaSaveModelValidator(_logger, _webSecurity, _textService, _propertyValidationService); + var contentItemValidator = new MediaSaveModelValidator(_logger, _backofficeSecurityAccessor.BackofficeSecurity, _textService, _propertyValidationService); if (ValidateUserAccess(model, context)) { @@ -101,7 +102,7 @@ namespace Umbraco.Web.BackOffice.Filters if (MediaController.CheckPermissions( actionContext.HttpContext.Items, - _webSecurity.CurrentUser, + _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, _mediaService, _entityService, contentIdToCheck, contentToCheck) == false) { diff --git a/src/Umbraco.Web.BackOffice/Filters/MediaSaveModelValidator.cs b/src/Umbraco.Web.BackOffice/Filters/MediaSaveModelValidator.cs index 4dd9e6592c..7eaf0cb60f 100644 --- a/src/Umbraco.Web.BackOffice/Filters/MediaSaveModelValidator.cs +++ b/src/Umbraco.Web.BackOffice/Filters/MediaSaveModelValidator.cs @@ -13,10 +13,10 @@ namespace Umbraco.Web.BackOffice.Filters { public MediaSaveModelValidator( ILogger logger, - IWebSecurity webSecurity, + IBackofficeSecurity backofficeSecurity, ILocalizedTextService textService, IPropertyValidationService propertyValidationService) - : base(logger, webSecurity, textService, propertyValidationService) + : base(logger, backofficeSecurity, textService, propertyValidationService) { } } diff --git a/src/Umbraco.Web.BackOffice/Filters/MemberSaveModelValidator.cs b/src/Umbraco.Web.BackOffice/Filters/MemberSaveModelValidator.cs index 208f0eeb07..9ca7cc4f31 100644 --- a/src/Umbraco.Web.BackOffice/Filters/MemberSaveModelValidator.cs +++ b/src/Umbraco.Web.BackOffice/Filters/MemberSaveModelValidator.cs @@ -26,13 +26,13 @@ namespace Umbraco.Web.BackOffice.Filters public MemberSaveModelValidator( ILogger logger, - IWebSecurity webSecurity, + IBackofficeSecurity backofficeSecurity, ILocalizedTextService textService, IMemberTypeService memberTypeService, IMemberService memberService, IShortStringHelper shortStringHelper, IPropertyValidationService propertyValidationService) - : base(logger, webSecurity, textService, propertyValidationService) + : base(logger, backofficeSecurity, textService, propertyValidationService) { _memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService)); _memberService = memberService ?? throw new ArgumentNullException(nameof(memberService)); @@ -96,7 +96,7 @@ namespace Umbraco.Web.BackOffice.Filters //if the user doesn't have access to sensitive values, then we need to validate the incoming properties to check //if a sensitive value is being submitted. - if (WebSecurity.CurrentUser.HasAccessToSensitiveData() == false) + if (BackofficeSecurity.CurrentUser.HasAccessToSensitiveData() == false) { var contentType = _memberTypeService.Get(model.PersistedContent.ContentTypeId); var sensitiveProperties = contentType diff --git a/src/Umbraco.Web.BackOffice/Filters/MemberSaveValidationAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/MemberSaveValidationAttribute.cs index e6f6edb2e3..bfa03264c3 100644 --- a/src/Umbraco.Web.BackOffice/Filters/MemberSaveValidationAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/MemberSaveValidationAttribute.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Umbraco.Core.Logging; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Models.ContentEditing; @@ -22,7 +23,7 @@ namespace Umbraco.Web.BackOffice.Filters private sealed class MemberSaveValidationFilter : IActionFilter { private readonly ILogger _logger; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly ILocalizedTextService _textService; private readonly IMemberTypeService _memberTypeService; private readonly IMemberService _memberService; @@ -31,7 +32,7 @@ namespace Umbraco.Web.BackOffice.Filters public MemberSaveValidationFilter( ILogger logger, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILocalizedTextService textService, IMemberTypeService memberTypeService, IMemberService memberService, @@ -39,7 +40,7 @@ namespace Umbraco.Web.BackOffice.Filters IPropertyValidationService propertyValidationService) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _textService = textService ?? throw new ArgumentNullException(nameof(textService)); _memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService)); _memberService = memberService ?? throw new ArgumentNullException(nameof(memberService)); @@ -50,7 +51,7 @@ namespace Umbraco.Web.BackOffice.Filters public void OnActionExecuting(ActionExecutingContext context) { var model = (MemberSave)context.ActionArguments["contentItem"]; - var contentItemValidator = new MemberSaveModelValidator(_logger, _webSecurity, _textService, _memberTypeService, _memberService, _shortStringHelper, _propertyValidationService); + var contentItemValidator = new MemberSaveModelValidator(_logger, _backofficeSecurityAccessor.BackofficeSecurity, _textService, _memberTypeService, _memberService, _shortStringHelper, _propertyValidationService); //now do each validation step if (contentItemValidator.ValidateExistingContent(model, context)) if (contentItemValidator.ValidateProperties(model, model, context)) diff --git a/src/Umbraco.Web.BackOffice/Filters/OutgoingEditorModelEventAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/OutgoingEditorModelEventAttribute.cs index d433ba9886..9952eb52f9 100644 --- a/src/Umbraco.Web.BackOffice/Filters/OutgoingEditorModelEventAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/OutgoingEditorModelEventAttribute.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Umbraco.Core; +using Umbraco.Core.Security; using Umbraco.Web.Editors; using Umbraco.Web.Security; @@ -13,12 +14,12 @@ namespace Umbraco.Web.WebApi.Filters internal sealed class OutgoingEditorModelEventAttribute : ActionFilterAttribute { private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; - public OutgoingEditorModelEventAttribute(IUmbracoContextAccessor umbracoContextAccessor, IWebSecurity webSecurity) + public OutgoingEditorModelEventAttribute(IUmbracoContextAccessor umbracoContextAccessor, IBackofficeSecurityAccessor backofficeSecurityAccessor) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); } public override void OnActionExecuted(ActionExecutedContext context) @@ -26,7 +27,7 @@ namespace Umbraco.Web.WebApi.Filters if (context.Result == null) return; var umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); - var user = _webSecurity.CurrentUser; + var user = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; if (user == null) return; if (context.Result is ObjectResult objectContent) diff --git a/src/Umbraco.Web.BackOffice/Filters/UmbracoApplicationAuthorizeAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UmbracoApplicationAuthorizeAttribute.cs index 4465436e77..3850682cf2 100644 --- a/src/Umbraco.Web.BackOffice/Filters/UmbracoApplicationAuthorizeAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/UmbracoApplicationAuthorizeAttribute.cs @@ -1,6 +1,7 @@ using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; +using Umbraco.Core.Security; using Umbraco.Web.Security; namespace Umbraco.Web.BackOffice.Filters @@ -22,19 +23,19 @@ namespace Umbraco.Web.BackOffice.Filters ///
internal static bool Enable = true; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly string[] _appNames; /// /// Constructor to set any number of applications that the user needs access to be authorized /// - /// + /// /// /// If the user has access to any of the specified apps, they will be authorized. /// - public UmbracoApplicationAuthorizeFilter(IWebSecurity webSecurity, params string[] appName) + public UmbracoApplicationAuthorizeFilter(IBackofficeSecurityAccessor backofficeSecurityAccessor, params string[] appName) { - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _appNames = appName; } @@ -54,9 +55,9 @@ namespace Umbraco.Web.BackOffice.Filters return true; } - var authorized = _webSecurity.CurrentUser != null - && _appNames.Any(app => _webSecurity.UserHasSectionAccess( - app, _webSecurity.CurrentUser)); + var authorized = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser != null + && _appNames.Any(app => _backofficeSecurityAccessor.BackofficeSecurity.UserHasSectionAccess( + app, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser)); return authorized; } diff --git a/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs index d4ec1b45e1..5f6e00e82e 100644 --- a/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs @@ -3,6 +3,7 @@ using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Umbraco.Core; +using Umbraco.Core.Security; using Umbraco.Web.Security; using Umbraco.Web.Services; @@ -34,22 +35,22 @@ namespace Umbraco.Web.BackOffice.Filters private readonly string[] _treeAliases; private readonly ITreeService _treeService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; /// /// Constructor to set authorization to be based on a tree alias for which application security will be applied /// - /// + /// + /// /// /// If the user has access to the application that the treeAlias is specified in, they will be authorized. /// Multiple trees may be specified. /// - /// - public UmbracoTreeAuthorizeFilter(ITreeService treeService, IWebSecurity webSecurity, + public UmbracoTreeAuthorizeFilter(ITreeService treeService, IBackofficeSecurityAccessor backofficeSecurityAccessor, params string[] treeAliases) { _treeService = treeService ?? throw new ArgumentNullException(nameof(treeService)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _treeAliases = treeAliases; } @@ -75,9 +76,9 @@ namespace Umbraco.Web.BackOffice.Filters .Distinct() .ToArray(); - return _webSecurity.CurrentUser != null - && apps.Any(app => _webSecurity.UserHasSectionAccess( - app, _webSecurity.CurrentUser)); + return _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser != null + && apps.Any(app => _backofficeSecurityAccessor.BackofficeSecurity.UserHasSectionAccess( + app, _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser)); } } } diff --git a/src/Umbraco.Web.BackOffice/Filters/UserGroupAuthorizationAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UserGroupAuthorizationAttribute.cs index b0175fe6ec..d867cc90bc 100644 --- a/src/Umbraco.Web.BackOffice/Filters/UserGroupAuthorizationAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/UserGroupAuthorizationAttribute.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Umbraco.Core; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.Security; @@ -34,7 +35,7 @@ namespace Umbraco.Web.BackOffice.Filters private readonly IContentService _contentService; private readonly IMediaService _mediaService; private readonly IEntityService _entityService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; public UserGroupAuthorizationFilter( IRequestAccessor requestAccessor, @@ -42,7 +43,7 @@ namespace Umbraco.Web.BackOffice.Filters IContentService contentService, IMediaService mediaService, IEntityService entityService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, string parameterName) { _requestAccessor = requestAccessor; @@ -50,7 +51,7 @@ namespace Umbraco.Web.BackOffice.Filters _contentService = contentService; _mediaService = mediaService; _entityService = entityService; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _parameterName = parameterName; } @@ -64,7 +65,7 @@ namespace Umbraco.Web.BackOffice.Filters private bool IsAuthorized(AuthorizationFilterContext actionContext) { - var currentUser = _webSecurity.CurrentUser; + var currentUser = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser; var queryString = actionContext.HttpContext.Request.Query; diff --git a/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs index c9bcf01fad..6253aa1ff4 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs @@ -1,4 +1,5 @@ -using System; + +using System; using System.Collections.Generic; using System.Linq; using System.Net; diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs index 44c83e3009..10fbdea0b6 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs @@ -13,6 +13,7 @@ using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Search; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; +using Umbraco.Core.Security; using Constants = Umbraco.Core.Constants; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.BackOffice.Trees; @@ -44,7 +45,7 @@ namespace Umbraco.Web.Trees private readonly ActionCollection _actions; private readonly GlobalSettings _globalSettings; private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IContentService _contentService; private readonly IEntityService _entityService; private readonly IPublicAccessService _publicAccessService; @@ -56,7 +57,7 @@ namespace Umbraco.Web.Trees UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IMenuItemCollectionFactory menuItemCollectionFactory, IEntityService entityService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILogger logger, ActionCollection actionCollection, IUserService userService, @@ -67,13 +68,13 @@ namespace Umbraco.Web.Trees IContentService contentService, IPublicAccessService publicAccessService, ILocalizationService localizationService) - : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory, entityService, webSecurity, logger, actionCollection, userService, dataTypeService) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory, entityService, backofficeSecurityAccessor, logger, actionCollection, userService, dataTypeService) { _treeSearcher = treeSearcher; _actions = actions; _globalSettings = globalSettings.Value; _menuItemCollectionFactory = menuItemCollectionFactory; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _contentService = contentService; _entityService = entityService; _publicAccessService = publicAccessService; @@ -88,7 +89,7 @@ namespace Umbraco.Web.Trees private int[] _userStartNodes; protected override int[] UserStartNodes - => _userStartNodes ?? (_userStartNodes = _webSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService)); + => _userStartNodes ?? (_userStartNodes = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService)); @@ -166,7 +167,7 @@ namespace Umbraco.Web.Trees menu.DefaultMenuAlias = ActionNew.ActionAlias; // we need to get the default permissions as you can't set permissions on the very root node - var permission = _userService.GetPermissions(_webSecurity.CurrentUser, Constants.System.Root).First(); + var permission = _userService.GetPermissions(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, Constants.System.Root).First(); var nodeActions = _actions.FromEntityPermission(permission) .Select(x => new MenuItem(x)); @@ -202,7 +203,7 @@ namespace Umbraco.Web.Trees } //if the user has no path access for this node, all they can do is refresh - if (!_webSecurity.CurrentUser.HasContentPathAccess(item, _entityService)) + if (!_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.HasContentPathAccess(item, _entityService)) { var menu = _menuItemCollectionFactory.Create(); menu.Items.Add(new RefreshNode(LocalizedTextService, true)); diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs index 8e05cb874e..ef2f4c2899 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Trees public abstract class ContentTreeControllerBase : TreeController, ITreeNodeController { private readonly IEntityService _entityService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly ILogger _logger; private readonly ActionCollection _actionCollection; private readonly IUserService _userService; @@ -38,7 +38,7 @@ namespace Umbraco.Web.Trees UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IMenuItemCollectionFactory menuItemCollectionFactory, IEntityService entityService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILogger logger, ActionCollection actionCollection, IUserService userService, @@ -47,7 +47,7 @@ namespace Umbraco.Web.Trees : base(localizedTextService, umbracoApiControllerTypeCollection) { _entityService = entityService; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _logger = logger; _actionCollection = actionCollection; _userService = userService; @@ -147,12 +147,12 @@ namespace Umbraco.Web.Trees switch (RecycleBinId) { case Constants.System.RecycleBinMedia: - startNodeIds = _webSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService); - startNodePaths = _webSecurity.CurrentUser.GetMediaStartNodePaths(_entityService); + startNodeIds = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService); + startNodePaths = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.GetMediaStartNodePaths(_entityService); break; case Constants.System.RecycleBinContent: - startNodeIds = _webSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService); - startNodePaths = _webSecurity.CurrentUser.GetContentStartNodePaths(_entityService); + startNodeIds = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.CalculateContentStartNodeIds(_entityService); + startNodePaths = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.GetContentStartNodePaths(_entityService); break; default: throw new NotSupportedException("Path access is only determined on content or media"); @@ -196,7 +196,7 @@ namespace Umbraco.Web.Trees // TODO: in the future we could return a validation statement so we can have some UI to notify the user they don't have access if (ignoreUserStartNodes == false && HasPathAccess(id, queryStrings) == false) { - _logger.Warn("User {Username} does not have access to node with id {Id}", _webSecurity.CurrentUser.Username, id); + _logger.Warn("User {Username} does not have access to node with id {Id}", _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.Username, id); return nodes; } @@ -312,8 +312,8 @@ namespace Umbraco.Web.Trees { if (entity == null) return false; return RecycleBinId == Constants.System.RecycleBinContent - ? _webSecurity.CurrentUser.HasContentPathAccess(entity, _entityService) - : _webSecurity.CurrentUser.HasMediaPathAccess(entity, _entityService); + ? _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.HasContentPathAccess(entity, _entityService) + : _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.HasMediaPathAccess(entity, _entityService); } /// @@ -441,7 +441,7 @@ namespace Umbraco.Web.Trees var deleteAction = _actionCollection.FirstOrDefault(y => y.Letter == ActionDelete.ActionLetter); if (deleteAction != null) { - var perms = _webSecurity.CurrentUser.GetPermissions(Constants.System.RecycleBinContentString, _userService); + var perms = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.GetPermissions(Constants.System.RecycleBinContentString, _userService); deleteAllowed = perms.FirstOrDefault(x => x.Contains(deleteAction.Letter)) != null; } @@ -492,7 +492,7 @@ namespace Umbraco.Web.Trees internal IEnumerable GetAllowedUserMenuItemsForNode(IUmbracoEntity dd) { - var permissionsForPath = _userService.GetPermissionsForPath(_webSecurity.CurrentUser, dd.Path).GetAllPermissions(); + var permissionsForPath = _userService.GetPermissionsForPath(_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser, dd.Path).GetAllPermissions(); return _actionCollection.GetByLetters(permissionsForPath).Select(x => new MenuItem(x)); } diff --git a/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs index 46ef45e85d..2a7f769c7b 100644 --- a/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs @@ -12,6 +12,7 @@ using Umbraco.Web.Models.Trees; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Search; using Umbraco.Core.Logging; +using Umbraco.Core.Security; using Constants = Umbraco.Core.Constants; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.BackOffice.Trees; @@ -39,26 +40,26 @@ namespace Umbraco.Web.Trees private readonly UmbracoTreeSearcher _treeSearcher; private readonly IMediaService _mediaService; private readonly IEntityService _entityService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; public MediaTreeController( ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IMenuItemCollectionFactory menuItemCollectionFactory, IEntityService entityService, - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, ILogger logger, ActionCollection actionCollection, IUserService userService, IDataTypeService dataTypeService, UmbracoTreeSearcher treeSearcher, IMediaService mediaService) - : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory, entityService, webSecurity, logger, actionCollection, userService, dataTypeService) + : base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory, entityService, backofficeSecurityAccessor, logger, actionCollection, userService, dataTypeService) { _treeSearcher = treeSearcher; _mediaService = mediaService; _entityService = entityService; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; } protected override int RecycleBinId => Constants.System.RecycleBinMedia; @@ -67,7 +68,7 @@ namespace Umbraco.Web.Trees private int[] _userStartNodes; protected override int[] UserStartNodes - => _userStartNodes ?? (_userStartNodes = _webSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService)); + => _userStartNodes ?? (_userStartNodes = _backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService)); /// /// Creates a tree node for a content item based on an UmbracoEntity @@ -134,7 +135,7 @@ namespace Umbraco.Web.Trees } //if the user has no path access for this node, all they can do is refresh - if (!_webSecurity.CurrentUser.HasMediaPathAccess(item, _entityService)) + if (!_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.HasMediaPathAccess(item, _entityService)) { menu.Items.Add(new RefreshNode(LocalizedTextService, true)); return menu; diff --git a/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs index 967e4f22fc..859ee2f846 100644 --- a/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Extensions; using Umbraco.Web.Actions; @@ -37,7 +38,7 @@ namespace Umbraco.Web.Trees private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; private readonly IMemberService _memberService; private readonly IMemberTypeService _memberTypeService; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; public MemberTreeController( ILocalizedTextService localizedTextService, @@ -46,14 +47,14 @@ namespace Umbraco.Web.Trees IMenuItemCollectionFactory menuItemCollectionFactory, IMemberService memberService, IMemberTypeService memberTypeService, - IWebSecurity webSecurity) + IBackofficeSecurityAccessor backofficeSecurityAccessor) : base(localizedTextService, umbracoApiControllerTypeCollection) { _treeSearcher = treeSearcher; _menuItemCollectionFactory = menuItemCollectionFactory; _memberService = memberService; _memberTypeService = memberTypeService; - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; } /// @@ -145,7 +146,7 @@ namespace Umbraco.Web.Trees //add delete option for all members menu.Items.Add(LocalizedTextService, opensDialog: true); - if (_webSecurity.CurrentUser.HasAccessToSensitiveData()) + if (_backofficeSecurityAccessor.BackofficeSecurity.CurrentUser.HasAccessToSensitiveData()) { menu.Items.Add(new ExportMember(LocalizedTextService)); } diff --git a/src/Umbraco.Web.Common/Install/InstallController.cs b/src/Umbraco.Web.Common/Install/InstallController.cs index 306a376533..026f604d50 100644 --- a/src/Umbraco.Web.Common/Install/InstallController.cs +++ b/src/Umbraco.Web.Common/Install/InstallController.cs @@ -7,6 +7,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; +using Umbraco.Core.Security; using Umbraco.Core.WebAssets; using Umbraco.Extensions; using Umbraco.Web.Common.Filters; @@ -25,7 +26,7 @@ namespace Umbraco.Web.Common.Install [Area(Umbraco.Core.Constants.Web.Mvc.InstallArea)] public class InstallController : Controller { - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly InstallHelper _installHelper; private readonly IRuntimeState _runtime; private readonly GlobalSettings _globalSettings; @@ -36,7 +37,7 @@ namespace Umbraco.Web.Common.Install private readonly IRuntimeMinifier _runtimeMinifier; public InstallController( - IWebSecurity webSecurity, + IBackofficeSecurityAccessor backofficeSecurityAccessor, InstallHelper installHelper, IRuntimeState runtime, IOptions globalSettings, @@ -46,7 +47,7 @@ namespace Umbraco.Web.Common.Install ILogger logger, LinkGenerator linkGenerator) { - _webSecurity = webSecurity; + _backofficeSecurityAccessor = backofficeSecurityAccessor; _installHelper = installHelper; _runtime = runtime; _globalSettings = globalSettings.Value; @@ -72,7 +73,7 @@ namespace Umbraco.Web.Common.Install // Update ClientDependency version and delete its temp directories to make sure we get fresh caches _runtimeMinifier.Reset(); - var result = _webSecurity.ValidateCurrentUser(false); + var result = _backofficeSecurityAccessor.BackofficeSecurity.ValidateCurrentUser(false); switch (result) { diff --git a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs index 587a60caa9..f5b8d74402 100644 --- a/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs +++ b/src/Umbraco.Web.Common/Middleware/UmbracoRequestMiddleware.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Logging; using System.Threading; using Umbraco.Core.Cache; using System.Collections.Generic; +using Umbraco.Core.Security; namespace Umbraco.Web.Common.Middleware { @@ -24,17 +25,20 @@ namespace Umbraco.Web.Common.Middleware private readonly IUmbracoRequestLifetimeManager _umbracoRequestLifetimeManager; private readonly IUmbracoContextFactory _umbracoContextFactory; private readonly IRequestCache _requestCache; + private readonly IBackofficeSecurityFactory _backofficeSecurityFactory; public UmbracoRequestMiddleware( ILogger logger, IUmbracoRequestLifetimeManager umbracoRequestLifetimeManager, IUmbracoContextFactory umbracoContextFactory, - IRequestCache requestCache) + IRequestCache requestCache, + IBackofficeSecurityFactory backofficeSecurityFactory) { _logger = logger; _umbracoRequestLifetimeManager = umbracoRequestLifetimeManager; _umbracoContextFactory = umbracoContextFactory; _requestCache = requestCache; + _backofficeSecurityFactory = backofficeSecurityFactory; } public async Task InvokeAsync(HttpContext context, RequestDelegate next) @@ -47,13 +51,14 @@ namespace Umbraco.Web.Common.Middleware await next(context); return; } - + _backofficeSecurityFactory.EnsureBackofficeSecurity(); // Needs to be before UmbracoContext var umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext(); + try { if (umbracoContextReference.UmbracoContext.IsFrontEndUmbracoRequest) - { + { LogHttpRequest.TryGetCurrentHttpRequestId(out var httpRequestId, _requestCache); _logger.Verbose("Begin request [{HttpRequestId}]: {RequestUrl}", httpRequestId, requestUri); } diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs index 67755da5ea..58b7fc16b5 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs @@ -75,7 +75,8 @@ namespace Umbraco.Web.Common.Runtime // register the umbraco context factory composition.RegisterUnique(); - composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); //register the install components //NOTE: i tried to not have these registered if we weren't installing or upgrading but post install when the site restarts diff --git a/src/Umbraco.Web.Common/Security/WebSecurity.cs b/src/Umbraco.Web.Common/Security/BackofficeSecurity.cs similarity index 98% rename from src/Umbraco.Web.Common/Security/WebSecurity.cs rename to src/Umbraco.Web.Common/Security/BackofficeSecurity.cs index b822adf656..6587501be7 100644 --- a/src/Umbraco.Web.Common/Security/WebSecurity.cs +++ b/src/Umbraco.Web.Common/Security/BackofficeSecurity.cs @@ -13,14 +13,15 @@ using Umbraco.Web.Security; namespace Umbraco.Web.Common.Security { - public class WebSecurity : IWebSecurity + + public class BackofficeSecurity : IBackofficeSecurity { private readonly IUserService _userService; private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; - public WebSecurity( + public BackofficeSecurity( IUserService userService, IOptions globalSettings, IHostingEnvironment hostingEnvironment, diff --git a/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs b/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs new file mode 100644 index 0000000000..7718981b27 --- /dev/null +++ b/src/Umbraco.Web.Common/Security/BackofficeSecurityFactory.cs @@ -0,0 +1,43 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Hosting; +using Umbraco.Core.Security; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Common.Security +{ + public class BackofficeSecurityFactory: IBackofficeSecurityFactory + { + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; + private readonly IUserService _userService; + private readonly IOptions _globalSettings; + private readonly IHostingEnvironment _hostingEnvironment; + private readonly IHttpContextAccessor _httpContextAccessor; + + public BackofficeSecurityFactory( + IBackofficeSecurityAccessor backofficeSecurityAccessor, + IUserService userService, + IOptions globalSettings, + IHostingEnvironment hostingEnvironment, + IHttpContextAccessor httpContextAccessor) + { + _backofficeSecurityAccessor = backofficeSecurityAccessor; + _userService = userService; + _globalSettings = globalSettings; + _hostingEnvironment = hostingEnvironment; + _httpContextAccessor = httpContextAccessor; + } + + public void EnsureBackofficeSecurity() + { + if (_backofficeSecurityAccessor.BackofficeSecurity is null) + { + _backofficeSecurityAccessor.BackofficeSecurity = new BackofficeSecurity(_userService, _globalSettings, _hostingEnvironment, _httpContextAccessor); + } + + } + } +} diff --git a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs index b255013b7f..6b4ce706e3 100644 --- a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs +++ b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web // warn: does *not* manage setting any IUmbracoContextAccessor internal UmbracoContext( IPublishedSnapshotService publishedSnapshotService, - IWebSecurity webSecurity, + IBackofficeSecurity backofficeSecurity, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IVariationContextAccessor variationContextAccessor, @@ -40,7 +40,7 @@ namespace Umbraco.Web IRequestAccessor requestAccessor) { if (publishedSnapshotService == null) throw new ArgumentNullException(nameof(publishedSnapshotService)); - if (webSecurity == null) throw new ArgumentNullException(nameof(webSecurity)); + if (backofficeSecurity == null) throw new ArgumentNullException(nameof(backofficeSecurity)); VariationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); _hostingEnvironment = hostingEnvironment; @@ -49,7 +49,7 @@ namespace Umbraco.Web ObjectCreated = DateTime.Now; UmbracoRequestId = Guid.NewGuid(); - Security = webSecurity; + Security = backofficeSecurity; // beware - we cannot expect a current user here, so detecting preview mode must be a lazy thing _publishedSnapshot = new Lazy(() => publishedSnapshotService.CreatePublishedSnapshot(PreviewToken)); @@ -78,9 +78,9 @@ namespace Umbraco.Web public Guid UmbracoRequestId { get; } /// - /// Gets the WebSecurity class + /// Gets the BackofficeSecurity class /// - public IWebSecurity Security { get; } + public IBackofficeSecurity Security { get; } /// /// Gets the uri that is handled by ASP.NET after server-side rewriting took place. diff --git a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs index d9df11e4a9..a31ef614cf 100644 --- a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs +++ b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Common.Security; using Umbraco.Web.PublishedCache; @@ -30,7 +31,7 @@ namespace Umbraco.Web private readonly IHttpContextAccessor _httpContextAccessor; private readonly ICookieManager _cookieManager; private readonly IRequestAccessor _requestAccessor; - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly UriUtility _uriUtility; /// @@ -48,7 +49,7 @@ namespace Umbraco.Web IHttpContextAccessor httpContextAccessor, ICookieManager cookieManager, IRequestAccessor requestAccessor, - IWebSecurity webSecurity) + IBackofficeSecurityAccessor backofficeSecurityAccessor) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService)); @@ -61,7 +62,7 @@ namespace Umbraco.Web _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); _cookieManager = cookieManager ?? throw new ArgumentNullException(nameof(cookieManager)); _requestAccessor = requestAccessor ?? throw new ArgumentNullException(nameof(requestAccessor)); - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); } private IUmbracoContext CreateUmbracoContext() @@ -79,7 +80,7 @@ namespace Umbraco.Web return new UmbracoContext( _publishedSnapshotService, - _webSecurity, + _backofficeSecurityAccessor.BackofficeSecurity, _globalSettings, _hostingEnvironment, _variationContextAccessor, diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs index 64a9e56014..6148535d46 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs @@ -3,6 +3,7 @@ using System.Web; using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Security; using Umbraco.Core.Configuration.Models; using Umbraco.Web.Composing; using Umbraco.Web.Security; @@ -14,22 +15,22 @@ namespace Umbraco.Web.Mvc public sealed class UmbracoAuthorizeAttribute : AuthorizeAttribute { // see note in HttpInstallAuthorizeAttribute - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IRuntimeState _runtimeState; private readonly string _redirectUrl; private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private IWebSecurity WebSecurity => _webSecurity ?? Current.UmbracoContext.Security; + private IBackofficeSecurity BackofficeSecurity => _backofficeSecurityAccessor.BackofficeSecurity ?? Current.UmbracoContext.Security; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS /// - /// + /// /// - public UmbracoAuthorizeAttribute(IWebSecurity webSecurity, IRuntimeState runtimeState) + public UmbracoAuthorizeAttribute(IBackofficeSecurityAccessor backofficeSecurityAccessor, IRuntimeState runtimeState) { - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _runtimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState)); } @@ -75,7 +76,7 @@ namespace Umbraco.Web.Mvc // otherwise we need to ensure that a user is logged in return RuntimeState.Level == RuntimeLevel.Install || RuntimeState.Level == RuntimeLevel.Upgrade - || WebSecurity.ValidateCurrentUser(); + || BackofficeSecurity.ValidateCurrentUser(); } catch (Exception) { diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 940a9521aa..29f0949473 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -67,7 +67,7 @@ namespace Umbraco.Web.Mvc /// /// Gets the web security helper. /// - public virtual IWebSecurity Security => UmbracoContext.Security; + public virtual IBackofficeSecurity Security => UmbracoContext.Security; protected UmbracoController() : this( diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/BackofficeSecurity.cs similarity index 95% rename from src/Umbraco.Web/Security/WebSecurity.cs rename to src/Umbraco.Web/Security/BackofficeSecurity.cs index 5776ec876a..e5e46ea37f 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/BackofficeSecurity.cs @@ -14,7 +14,7 @@ namespace Umbraco.Web.Security { // NOTE: Moved to netcore - public class WebSecurity : IWebSecurity + public class BackofficeSecurity : IBackofficeSecurity { public IUser CurrentUser => throw new NotImplementedException(); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index c2d36285e6..dfade80794 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -157,7 +157,7 @@ - + diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index bda836c847..a4b6e1dd14 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -30,7 +30,7 @@ namespace Umbraco.Web // warn: does *not* manage setting any IUmbracoContextAccessor internal UmbracoContext(IHttpContextAccessor httpContextAccessor, IPublishedSnapshotService publishedSnapshotService, - IWebSecurity webSecurity, + IBackofficeSecurity backofficeSecurity, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IVariationContextAccessor variationContextAccessor, @@ -39,7 +39,7 @@ namespace Umbraco.Web { if (httpContextAccessor == null) throw new ArgumentNullException(nameof(httpContextAccessor)); if (publishedSnapshotService == null) throw new ArgumentNullException(nameof(publishedSnapshotService)); - if (webSecurity == null) throw new ArgumentNullException(nameof(webSecurity)); + if (backofficeSecurity == null) throw new ArgumentNullException(nameof(backofficeSecurity)); VariationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); _httpContextAccessor = httpContextAccessor; _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); @@ -58,7 +58,7 @@ namespace Umbraco.Web ObjectCreated = DateTime.Now; UmbracoRequestId = Guid.NewGuid(); - Security = webSecurity; + Security = backofficeSecurity; // beware - we cannot expect a current user here, so detecting preview mode must be a lazy thing _publishedSnapshot = new Lazy(() => publishedSnapshotService.CreatePublishedSnapshot(PreviewToken)); @@ -87,9 +87,9 @@ namespace Umbraco.Web public Guid UmbracoRequestId { get; } /// - /// Gets the WebSecurity class + /// Gets the BackofficeSecurity class /// - public IWebSecurity Security { get; } + public IBackofficeSecurity Security { get; } /// /// Gets the uri that is handled by ASP.NET after server-side rewriting took place. diff --git a/src/Umbraco.Web/UmbracoContextFactory.cs b/src/Umbraco.Web/UmbracoContextFactory.cs index 4eba56c36f..cc0bd59fa1 100644 --- a/src/Umbraco.Web/UmbracoContextFactory.cs +++ b/src/Umbraco.Web/UmbracoContextFactory.cs @@ -68,7 +68,7 @@ namespace Umbraco.Web _variationContextAccessor.VariationContext = new VariationContext(_defaultCultureAccessor.DefaultCulture); } - return new UmbracoContext(_httpContextAccessor, _publishedSnapshotService, new WebSecurity(), _globalSettings, _hostingEnvironment, _variationContextAccessor, _uriUtility, _cookieManager); + return new UmbracoContext(_httpContextAccessor, _publishedSnapshotService, new BackofficeSecurity(), _globalSettings, _hostingEnvironment, _variationContextAccessor, _uriUtility, _cookieManager); } /// diff --git a/src/Umbraco.Web/UmbracoHttpHandler.cs b/src/Umbraco.Web/UmbracoHttpHandler.cs index eb219f82d2..7db09b62ff 100644 --- a/src/Umbraco.Web/UmbracoHttpHandler.cs +++ b/src/Umbraco.Web/UmbracoHttpHandler.cs @@ -52,7 +52,7 @@ namespace Umbraco.Web /// /// Gets the web security helper. /// - public IWebSecurity Security => UmbracoContextAccessor.UmbracoContext.Security; + public IBackofficeSecurity Security => UmbracoContextAccessor.UmbracoContext.Security; /// /// Gets the Url helper. diff --git a/src/Umbraco.Web/UmbracoWebService.cs b/src/Umbraco.Web/UmbracoWebService.cs index a0d12cba93..9dca6f5d33 100644 --- a/src/Umbraco.Web/UmbracoWebService.cs +++ b/src/Umbraco.Web/UmbracoWebService.cs @@ -62,7 +62,7 @@ namespace Umbraco.Web /// /// Gets the web security helper. /// - public IWebSecurity Security => UmbracoContext.Security; + public IBackofficeSecurity Security => UmbracoContext.Security; /// /// Gets the Url helper. diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 7c15775f7b..3434d825fe 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -118,7 +118,7 @@ namespace Umbraco.Web.WebApi /// /// Gets the web security helper. /// - public IWebSecurity Security => UmbracoContext.Security; + public IBackofficeSecurity Security => UmbracoContext.Security; /// /// Tries to get the current HttpContext. diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs index 69c697d0fc..83f08660d9 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizeAttribute.cs @@ -1,6 +1,7 @@ using System; using System.Web.Http; using Umbraco.Core; +using Umbraco.Core.Security; using Umbraco.Web.Composing; using Umbraco.Web.Security; @@ -19,21 +20,21 @@ namespace Umbraco.Web.WebApi internal static bool Enable = true; // TODO: inject! - private readonly IWebSecurity _webSecurity; + private readonly IBackofficeSecurityAccessor _backofficeSecurityAccessor; private readonly IRuntimeState _runtimeState; private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; - private IWebSecurity WebSecurity => _webSecurity ?? Current.UmbracoContext.Security; + private IBackofficeSecurity BackofficeSecurity => _backofficeSecurityAccessor.BackofficeSecurity ?? Current.UmbracoContext.Security; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS /// - /// + /// /// - public UmbracoAuthorizeAttribute(IWebSecurity webSecurity, IRuntimeState runtimeState) + public UmbracoAuthorizeAttribute(IBackofficeSecurityAccessor backofficeSecurityAccessor, IRuntimeState runtimeState) { - _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); + _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _runtimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState)); } @@ -58,7 +59,7 @@ namespace Umbraco.Web.WebApi // otherwise we need to ensure that a user is logged in return RuntimeState.Level == RuntimeLevel.Install || RuntimeState.Level == RuntimeLevel.Upgrade - || WebSecurity.ValidateCurrentUser(false, _requireApproval) == ValidateRequestAttempt.Success; + || BackofficeSecurity.ValidateCurrentUser(false, _requireApproval) == ValidateRequestAttempt.Success; } catch (Exception) { From 164fa24ef3269c5c6f397fb6d07a3b785c70c970 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 22 Sep 2020 10:04:55 +0200 Subject: [PATCH 16/19] #8919 - Fix issue with wrong casing of variable name --- .../src/common/services/iconhelper.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js index f714cba4ad..5034de67eb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js @@ -209,7 +209,7 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { ,'Failed to retrieve icon: ' + iconName) .then(icon => { if(icon) { - var trustedIcon = this.defineIcon(icon.name, icon.SvgString); + var trustedIcon = this.defineIcon(icon.Name, icon.SvgString); liveRequests = _.filter(liveRequests, iconRequestPath); From 1badb69481ef82cc09990a79c642a0f406f9e384 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 22 Sep 2020 10:14:34 +0200 Subject: [PATCH 17/19] #8919 - Clean up obsolete ctor --- src/Umbraco.Web/Editors/BackOfficeController.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 71bda4bfd2..cd5a3a50b6 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -67,9 +67,7 @@ namespace Umbraco.Web.Editors umbracoHelper, Current.IconService) { - _manifestParser = manifestParser; - _features = features; - _runtimeState = runtimeState; + } public BackOfficeController( From 8e9889d2690cca54ec1640cfd02f9c23ed78076e Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 22 Sep 2020 12:44:36 +0200 Subject: [PATCH 18/19] Post merge Signed-off-by: Bjarke Berg --- src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj | 1 - 1 file changed, 1 deletion(-) 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 81d1c9f1d2..fefd18c11a 100644 --- a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj +++ b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj @@ -12,7 +12,6 @@ - From a80de91031aa474e428a9f1232a1a4c2b6df3555 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 22 Sep 2020 13:19:54 +0200 Subject: [PATCH 19/19] Netcore: Handle tree authentication (#8866) * Added helper methods to invoke the authorization filters of the other controller action Signed-off-by: Bjarke Berg * Implemented Tree Auth Signed-off-by: Bjarke Berg * cleanup Signed-off-by: Bjarke Berg * Throw forbidden if user has no access instead of InternalServerError Signed-off-by: Bjarke Berg * EnsureBackofficeSecurity for background jobs Signed-off-by: Bjarke Berg Co-authored-by: Elitsa Marinovska --- .../Scheduling/ScheduledPublishing.cs | 5 +- .../Scheduling/SchedulerComponent.cs | 7 +- .../Controllers/SectionController.cs | 8 +- .../Extensions/ControllerContextExtensions.cs | 125 ++++++++++++++++++ .../Trees/ApplicationTreeController.cs | 81 ++++-------- .../UmbracoContext/UmbracoContext.cs | 4 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 - .../WebApi/HttpControllerContextExtensions.cs | 54 -------- 8 files changed, 170 insertions(+), 115 deletions(-) create mode 100644 src/Umbraco.Web.BackOffice/Extensions/ControllerContextExtensions.cs delete mode 100644 src/Umbraco.Web/WebApi/HttpControllerContextExtensions.cs diff --git a/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs b/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs index 6ec0250d90..674012e797 100644 --- a/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs +++ b/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs @@ -14,13 +14,14 @@ namespace Umbraco.Web.Scheduling private readonly IMainDom _mainDom; private readonly IRuntimeState _runtime; private readonly IServerMessenger _serverMessenger; + private readonly IBackofficeSecurityFactory _backofficeSecurityFactory; private readonly IServerRegistrar _serverRegistrar; private readonly IUmbracoContextFactory _umbracoContextFactory; public ScheduledPublishing(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, IRuntimeState runtime, IMainDom mainDom, IServerRegistrar serverRegistrar, IContentService contentService, - IUmbracoContextFactory umbracoContextFactory, ILogger logger, IServerMessenger serverMessenger) + IUmbracoContextFactory umbracoContextFactory, ILogger logger, IServerMessenger serverMessenger, IBackofficeSecurityFactory backofficeSecurityFactory) : base(runner, delayMilliseconds, periodMilliseconds) { _runtime = runtime; @@ -30,6 +31,7 @@ namespace Umbraco.Web.Scheduling _umbracoContextFactory = umbracoContextFactory; _logger = logger; _serverMessenger = serverMessenger; + _backofficeSecurityFactory = backofficeSecurityFactory; } public override bool IsAsync => false; @@ -76,6 +78,7 @@ namespace Umbraco.Web.Scheduling // 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) // + _backofficeSecurityFactory.EnsureBackofficeSecurity(); using (var contextReference = _umbracoContextFactory.EnsureUmbracoContext()) { try diff --git a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs index cbf1df197d..5fb4f19473 100644 --- a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs +++ b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs @@ -39,6 +39,7 @@ namespace Umbraco.Web.Scheduling private readonly HealthChecksSettings _healthChecksSettings; private readonly IServerMessenger _serverMessenger; private readonly IRequestAccessor _requestAccessor; + private readonly IBackofficeSecurityFactory _backofficeSecurityFactory; private readonly LoggingSettings _loggingSettings; private readonly KeepAliveSettings _keepAliveSettings; private readonly IHostingEnvironment _hostingEnvironment; @@ -60,7 +61,8 @@ namespace Umbraco.Web.Scheduling IApplicationShutdownRegistry applicationShutdownRegistry, IOptions healthChecksSettings, IServerMessenger serverMessenger, IRequestAccessor requestAccessor, IOptions loggingSettings, IOptions keepAliveSettings, - IHostingEnvironment hostingEnvironment) + IHostingEnvironment hostingEnvironment, + IBackofficeSecurityFactory backofficeSecurityFactory) { _runtime = runtime; _mainDom = mainDom; @@ -77,6 +79,7 @@ namespace Umbraco.Web.Scheduling _healthChecksSettings = healthChecksSettings.Value ?? throw new ArgumentNullException(nameof(healthChecksSettings)); _serverMessenger = serverMessenger; _requestAccessor = requestAccessor; + _backofficeSecurityFactory = backofficeSecurityFactory; _loggingSettings = loggingSettings.Value; _keepAliveSettings = keepAliveSettings.Value; _hostingEnvironment = hostingEnvironment; @@ -150,7 +153,7 @@ namespace Umbraco.Web.Scheduling { // scheduled publishing/unpublishing // install on all, will only run on non-replica servers - var task = new ScheduledPublishing(_publishingRunner, DefaultDelayMilliseconds, OneMinuteMilliseconds, _runtime, _mainDom, _serverRegistrar, _contentService, _umbracoContextFactory, _logger, _serverMessenger); + var task = new ScheduledPublishing(_publishingRunner, DefaultDelayMilliseconds, OneMinuteMilliseconds, _runtime, _mainDom, _serverRegistrar, _contentService, _umbracoContextFactory, _logger, _serverMessenger, _backofficeSecurityFactory); _publishingRunner.TryAdd(task); return task; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs b/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs index 810e3e5646..c579a3ec1d 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/SectionController.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Infrastructure; using Umbraco.Core; using Umbraco.Core.Mapping; using Umbraco.Core.Models; @@ -23,6 +24,7 @@ namespace Umbraco.Web.Editors public class SectionController : UmbracoAuthorizedJsonController { private readonly IControllerFactory _controllerFactory; + private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider; private readonly IDashboardService _dashboardService; private readonly ILocalizedTextService _localizedTextService; private readonly ISectionService _sectionService; @@ -34,7 +36,8 @@ namespace Umbraco.Web.Editors IBackofficeSecurityAccessor backofficeSecurityAccessor, ILocalizedTextService localizedTextService, IDashboardService dashboardService, ISectionService sectionService, ITreeService treeService, - UmbracoMapper umbracoMapper, IControllerFactory controllerFactory) + UmbracoMapper umbracoMapper, IControllerFactory controllerFactory, + IActionDescriptorCollectionProvider actionDescriptorCollectionProvider) { _backofficeSecurityAccessor = backofficeSecurityAccessor; _localizedTextService = localizedTextService; @@ -43,6 +46,7 @@ namespace Umbraco.Web.Editors _treeService = treeService; _umbracoMapper = umbracoMapper; _controllerFactory = controllerFactory; + _actionDescriptorCollectionProvider = actionDescriptorCollectionProvider; } public IEnumerable
GetSections() @@ -54,7 +58,7 @@ namespace Umbraco.Web.Editors // this is a bit nasty since we'll be proxying via the app tree controller but we sort of have to do that // since tree's by nature are controllers and require request contextual data var appTreeController = - new ApplicationTreeController(_treeService, _sectionService, _localizedTextService, _controllerFactory) + new ApplicationTreeController(_treeService, _sectionService, _localizedTextService, _controllerFactory, _actionDescriptorCollectionProvider) { ControllerContext = ControllerContext }; diff --git a/src/Umbraco.Web.BackOffice/Extensions/ControllerContextExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/ControllerContextExtensions.cs new file mode 100644 index 0000000000..ca17d97fc7 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Extensions/ControllerContextExtensions.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; + +namespace Umbraco.Extensions +{ + internal static class ControllerContextExtensions + { + /// + /// Invokes the authorization filters for the controller action. + /// + /// Whether the user is authenticated or not. + internal static async Task InvokeAuthorizationFiltersForRequest(this ControllerContext controllerContext, ActionContext actionContext) + { + var actionDescriptor = controllerContext.ActionDescriptor; + + var filters = actionDescriptor.FilterDescriptors; + var filterGrouping = new FilterGrouping(filters, controllerContext.HttpContext.RequestServices); + + // because the continuation gets built from the inside out we need to reverse the filter list + // so that least specific filters (Global) get run first and the most specific filters (Action) get run last. + var authorizationFilters = filterGrouping.AuthorizationFilters.Reverse().ToList(); + var asyncAuthorizationFilters = filterGrouping.AsyncAuthorizationFilters.Reverse().ToList(); + + if (authorizationFilters.Count == 0 && asyncAuthorizationFilters.Count == 0) + return true; + + // if the authorization filter returns a result, it means it failed to authorize + var authorizationFilterContext = new AuthorizationFilterContext(actionContext, filters.Select(x=>x.Filter).ToArray()); + return await ExecuteAuthorizationFiltersAsync(authorizationFilterContext, authorizationFilters, asyncAuthorizationFilters); + } + + /// + /// Executes a chain of filters. + /// + /// + /// Recursively calls in to itself as its continuation for the next filter in the chain. + /// + private static async Task ExecuteAuthorizationFiltersAsync( + AuthorizationFilterContext authorizationFilterContext, + IList authorizationFilters, + IList asyncAuthorizationFilters) + { + + foreach (var authorizationFilter in authorizationFilters) + { + authorizationFilter.OnAuthorization(authorizationFilterContext); + if (!(authorizationFilterContext.Result is null)) + { + return false; + } + + } + + foreach (var asyncAuthorizationFilter in asyncAuthorizationFilters) + { + await asyncAuthorizationFilter.OnAuthorizationAsync(authorizationFilterContext); + if (!(authorizationFilterContext.Result is null)) + { + return false; + } + } + + return true; + } + + /// + /// Quickly split filters into different types + /// + private class FilterGrouping + { + private readonly List _actionFilters = new List(); + private readonly List _asyncActionFilters = new List(); + private readonly List _authorizationFilters = new List(); + private readonly List _asyncAuthorizationFilters = new List(); + private readonly List _exceptionFilters = new List(); + private readonly List _asyncExceptionFilters = new List(); + + public FilterGrouping(IEnumerable filters, IServiceProvider serviceProvider) + { + if (filters == null) throw new ArgumentNullException("filters"); + + foreach (FilterDescriptor f in filters) + { + var filter = f.Filter; + Categorize(filter, _actionFilters, serviceProvider); + Categorize(filter, _authorizationFilters, serviceProvider); + Categorize(filter, _exceptionFilters, serviceProvider); + Categorize(filter, _asyncActionFilters, serviceProvider); + Categorize(filter, _asyncAuthorizationFilters, serviceProvider); + } + } + + public IEnumerable ActionFilters => _actionFilters; + public IEnumerable AsyncActionFilters => _asyncActionFilters; + public IEnumerable AuthorizationFilters => _authorizationFilters; + + public IEnumerable AsyncAuthorizationFilters => _asyncAuthorizationFilters; + + public IEnumerable ExceptionFilters => _exceptionFilters; + + public IEnumerable AsyncExceptionFilters => _asyncExceptionFilters; + + private static void Categorize(IFilterMetadata filter, List list, IServiceProvider serviceProvider) where T : class + { + if(filter is TypeFilterAttribute typeFilterAttribute) + { + filter = typeFilterAttribute.CreateInstance(serviceProvider); + } + + T match = filter as T; + if (match != null) + { + list.Add(match); + } + } + } + } +} diff --git a/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs index 6253aa1ff4..92cb5b1b93 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ApplicationTreeController.cs @@ -8,10 +8,12 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Primitives; using Umbraco.Core; using Umbraco.Core.Services; +using Umbraco.Extensions; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.BackOffice.Trees; using Umbraco.Web.Common.Attributes; @@ -35,18 +37,22 @@ namespace Umbraco.Web.Trees private readonly ISectionService _sectionService; private readonly ILocalizedTextService _localizedTextService; private readonly IControllerFactory _controllerFactory; + private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider; + public ApplicationTreeController( ITreeService treeService, ISectionService sectionService, ILocalizedTextService localizedTextService, - IControllerFactory controllerFactory + IControllerFactory controllerFactory, + IActionDescriptorCollectionProvider actionDescriptorCollectionProvider ) { _treeService = treeService; _sectionService = sectionService; _localizedTextService = localizedTextService; _controllerFactory = controllerFactory; + _actionDescriptorCollectionProvider = actionDescriptorCollectionProvider; } /// @@ -251,67 +257,36 @@ namespace Umbraco.Web.Trees private async Task GetApiControllerProxy(Type controllerType, string action, FormCollection querystring) { // note: this is all required in order to execute the auth-filters for the sub request, we - // need to "trick" web-api into thinking that it is actually executing the proxied controller. - + // need to "trick" mvc into thinking that it is actually executing the proxied controller. + var controllerName = controllerType.Name.Substring(0, controllerType.Name.Length - 10); // remove controller part of name; // create proxy route data specifying the action & controller to execute var routeData = new RouteData(new RouteValueDictionary() { ["action"] = action, - ["controller"] = controllerType.Name.Substring(0,controllerType.Name.Length-10) // remove controller part of name; - + ["controller"] = controllerName }); + if (!(querystring is null)) + { + foreach (var (key,value) in querystring) + { + routeData.Values[key] = value; + } + } + var actionDescriptor = _actionDescriptorCollectionProvider.ActionDescriptors.Items + .Cast() + .First(x => + x.ControllerName.Equals(controllerName) && + x.ActionName == action); - var controllerContext = new ControllerContext( - new ActionContext( - HttpContext, - routeData, - new ControllerActionDescriptor() - { - ControllerTypeInfo = controllerType.GetTypeInfo() - } - )); + var actionContext = new ActionContext(HttpContext, routeData, actionDescriptor); + var proxyControllerContext = new ControllerContext(actionContext); + var controller = (TreeController) _controllerFactory.CreateController(proxyControllerContext); - var controller = (TreeController) _controllerFactory.CreateController(controllerContext); - - - //TODO Refactor trees or reimplement this hacks to check authentication. - //https://dev.azure.com/umbraco/D-Team%20Tracker/_workitems/edit/3694 - - // var context = ControllerContext; - // - // // get the controller - // var controller = (TreeController) DependencyResolver.Current.GetService(controllerType) - // ?? throw new Exception($"Failed to create controller of type {controllerType.FullName}."); - // - // // create the proxy URL for the controller action - // var proxyUrl = HttpContext.Request.RequestUri.GetLeftPart(UriPartial.Authority) - // + HttpContext.Request.GetUrlHelper().GetUmbracoApiService(action, controllerType) - // + "?" + querystring.ToQueryString(); - // - // - // - // // create a proxy request - // var proxyRequest = new HttpRequestMessage(HttpMethod.Get, proxyUrl); - // - // // create a proxy controller context - // var proxyContext = new HttpControllerContext(context.Configuration, proxyRoute, proxyRequest) - // { - // ControllerDescriptor = new HttpControllerDescriptor(context.ControllerDescriptor.Configuration, ControllerExtensions.GetControllerName(controllerType), controllerType), - // RequestContext = context.RequestContext, - // Controller = controller - // }; - // - // // wire everything - // controller.ControllerContext = proxyContext; - // controller.Request = proxyContext.Request; - // controller.RequestContext.RouteData = proxyRoute; - // - // // auth - // var authResult = await controller.ControllerContext.InvokeAuthorizationFiltersForRequest(); - // if (authResult != null) - // throw new HttpResponseException(authResult); + var isAllowed = await controller.ControllerContext.InvokeAuthorizationFiltersForRequest(actionContext); + if (!isAllowed) + throw new HttpResponseException(HttpStatusCode.Forbidden); return controller; } diff --git a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs index 6b4ce706e3..5e5b6f6910 100644 --- a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs +++ b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs @@ -40,16 +40,16 @@ namespace Umbraco.Web IRequestAccessor requestAccessor) { if (publishedSnapshotService == null) throw new ArgumentNullException(nameof(publishedSnapshotService)); - if (backofficeSecurity == null) throw new ArgumentNullException(nameof(backofficeSecurity)); VariationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); + _hostingEnvironment = hostingEnvironment; _cookieManager = cookieManager; _requestAccessor = requestAccessor; ObjectCreated = DateTime.Now; UmbracoRequestId = Guid.NewGuid(); - Security = backofficeSecurity; + Security = backofficeSecurity ?? throw new ArgumentNullException(nameof(backofficeSecurity)); // beware - we cannot expect a current user here, so detecting preview mode must be a lazy thing _publishedSnapshot = new Lazy(() => publishedSnapshotService.CreatePublishedSnapshot(PreviewToken)); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index dfade80794..962c8ed528 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -296,7 +296,6 @@ - diff --git a/src/Umbraco.Web/WebApi/HttpControllerContextExtensions.cs b/src/Umbraco.Web/WebApi/HttpControllerContextExtensions.cs deleted file mode 100644 index 323e52eb36..0000000000 --- a/src/Umbraco.Web/WebApi/HttpControllerContextExtensions.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using System.Web.Http; -using System.Web.Http.Controllers; -using System.Web.Http.Filters; -using Umbraco.Web.WebApi.Filters; - -namespace Umbraco.Web.WebApi -{ - internal static class HttpControllerContextExtensions - { - /// - /// Invokes the authorization filters for the controller action. - /// - /// The response of the first filter returning a result, if any, otherwise null (authorized). - internal static async Task InvokeAuthorizationFiltersForRequest(this HttpControllerContext controllerContext) - { - var controllerDescriptor = controllerContext.ControllerDescriptor; - var controllerServices = controllerDescriptor.Configuration.Services; - var actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext); - - var filters = actionDescriptor.GetFilterPipeline(); - var filterGrouping = new FilterGrouping(filters); - - // because the continuation gets built from the inside out we need to reverse the filter list - // so that least specific filters (Global) get run first and the most specific filters (Action) get run last. - var authorizationFilters = filterGrouping.AuthorizationFilters.Reverse().ToList(); - - if (authorizationFilters.Count == 0) - return null; - - // if the authorization filter returns a result, it means it failed to authorize - var actionContext = new HttpActionContext(controllerContext, actionDescriptor); - return await ExecuteAuthorizationFiltersAsync(actionContext, CancellationToken.None, authorizationFilters); - } - - /// - /// Executes a chain of filters. - /// - /// - /// Recursively calls in to itself as its continuation for the next filter in the chain. - /// - private static async Task ExecuteAuthorizationFiltersAsync(HttpActionContext actionContext, CancellationToken token, IList filters, int index = 0) - { - return await filters[index].ExecuteAuthorizationFilterAsync(actionContext, token, - () => ++index == filters.Count - ? Task.FromResult(null) - : ExecuteAuthorizationFiltersAsync(actionContext, token, filters, index)); - } - } -}