diff --git a/src/Umbraco.Web.BackOffice/Authorization/AuthorizationPolicies.cs b/src/Umbraco.Web.BackOffice/Authorization/AuthorizationPolicies.cs
new file mode 100644
index 0000000000..7352a43b47
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Authorization/AuthorizationPolicies.cs
@@ -0,0 +1,32 @@
+namespace Umbraco.Web.BackOffice.Authorization
+{
+ public static class AuthorizationPolicies
+ {
+ public const string TreeAccessUsers = "TreeAccessUsers";
+ public const string TreeAccessPartialViews = "TreeAccessPartialViews";
+ public const string TreeAccessPartialViewMacros = "TreeAccessPartialViewMacros";
+ public const string TreeAccessDataTypes = "TreeAccessDataTypes";
+ public const string TreeAccessPackages = "TreeAccessPackages";
+ public const string TreeAccessLogs = "TreeAccessLogs";
+ public const string TreeAccessTemplates = "TreeAccessTemplates";
+ public const string TreeAccessDictionary = "TreeAccessDictionary";
+ public const string TreeAccessRelationTypes = "TreeAccessRelationTypes";
+ public const string TreeAccessMediaTypes = "TreeAccessMediaTypes";
+ public const string TreeAccessMacros = "TreeAccessMacros";
+ public const string TreeAccessLanguages = "TreeAccessLanguages";
+ public const string TreeAccessMemberGroups = "TreeAccessMemberGroups";
+ public const string TreeAccessDocumentTypes = "TreeAccessDocumentTypes";
+ public const string TreeAccessMemberTypes = "TreeAccessMemberTypes";
+ public const string TreeAccessDocumentsOrDocumentTypes = "TreeAccessDocumentsAndDocumentTypes";
+ public const string TreeAccessMediaOrMediaTypes = "TreeAccessMediaAndMediaTypes";
+ public const string TreeAccessMembersOrMemberTypes = "TreeAccessMembersAndMemberTypes";
+ public const string TreeAccessAnySchemaTypes = "TreeAccessSchemaTypes";
+ public const string TreeAccessDictionaryOrTemplates = "TreeAccessDictionaryOrTemplates";
+
+ ///
+ /// Defines access based on if the user has access to any tree's exposing any types of content (documents, media, members)
+ /// or any content types (document types, media types, member types)
+ ///
+ public const string TreeAccessAnyContentOrTypes = "TreeAccessAnyContentOrTypes";
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/Authorization/TreeAliasesRequirement.cs b/src/Umbraco.Web.BackOffice/Authorization/TreeAliasesRequirement.cs
new file mode 100644
index 0000000000..44ecb8dfe3
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Authorization/TreeAliasesRequirement.cs
@@ -0,0 +1,19 @@
+using Microsoft.AspNetCore.Authorization;
+using System.Collections.Generic;
+
+namespace Umbraco.Web.BackOffice.Authorization
+{
+
+ ///
+ /// Authorization requirements for
+ ///
+ public class TreeAliasesRequirement : IAuthorizationRequirement
+ {
+ ///
+ /// The aliases for trees that the user will need access to
+ ///
+ public IReadOnlyCollection TreeAliases { get; }
+
+ public TreeAliasesRequirement(params string[] aliases) => TreeAliases = aliases;
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/Authorization/UmbracoTreeAuthorizeHandler.cs b/src/Umbraco.Web.BackOffice/Authorization/UmbracoTreeAuthorizeHandler.cs
new file mode 100644
index 0000000000..b2cd18c1ce
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Authorization/UmbracoTreeAuthorizeHandler.cs
@@ -0,0 +1,76 @@
+using Microsoft.AspNetCore.Authorization;
+using System;
+using System.Linq;
+using Umbraco.Core;
+using System.Threading.Tasks;
+using Umbraco.Core.Security;
+using Umbraco.Web.Services;
+
+namespace Umbraco.Web.BackOffice.Authorization
+{
+ ///
+ /// Ensures that the current user has access to the application for which the specified tree(s) belongs
+ ///
+ ///
+ /// This would allow a tree to be moved between sections.
+ /// The user only needs access to one of the trees specified, not all of the trees.
+ ///
+ public class UmbracoTreeAuthorizeHandler : AuthorizationHandler
+ {
+ ///
+ /// Can be used by unit tests to enable/disable this filter
+ ///
+ internal static readonly bool Enable = true;
+
+ private readonly ITreeService _treeService;
+ 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 UmbracoTreeAuthorizeHandler(ITreeService treeService, IBackOfficeSecurityAccessor backofficeSecurityAccessor)
+ {
+ _treeService = treeService ?? throw new ArgumentNullException(nameof(treeService));
+ _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor));
+ }
+
+ private bool IsAuthorized(TreeAliasesRequirement requirement)
+ {
+ if (Enable == false)
+ {
+ return true;
+ }
+
+ var apps = requirement.TreeAliases.Select(x => _treeService
+ .GetByAlias(x))
+ .WhereNotNull()
+ .Select(x => x.SectionAlias)
+ .Distinct()
+ .ToArray();
+
+ return _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null
+ && apps.Any(app => _backofficeSecurityAccessor.BackOfficeSecurity.UserHasSectionAccess(
+ app, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser));
+ }
+
+ protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TreeAliasesRequirement requirement)
+ {
+ if (IsAuthorized(requirement))
+ {
+ context.Succeed(requirement);
+ }
+ else
+ {
+ context.Fail();
+ }
+
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs
index 9d18727c62..33f19141c3 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs
@@ -36,6 +36,8 @@ using ContentType = Umbraco.Core.Models.ContentType;
using Umbraco.Core.Configuration.Models;
using Microsoft.Extensions.Options;
using Umbraco.Core.Serialization;
+using Microsoft.AspNetCore.Authorization;
+using Umbraco.Web.BackOffice.Authorization;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -48,7 +50,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// An API controller used for dealing with content types
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
- [UmbracoTreeAuthorize(Constants.Trees.DocumentTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
public class ContentTypeController : ContentTypeControllerBase
{
private readonly IEntityXmlSerializer _serializer;
@@ -136,7 +138,7 @@ namespace Umbraco.Web.BackOffice.Controllers
}
[HttpGet]
- [UmbracoTreeAuthorize(Constants.Trees.DocumentTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
public bool HasContentNodes(int id)
{
return _contentTypeService.HasContentNodes(id);
@@ -223,10 +225,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Gets all user defined properties.
///
///
- [UmbracoTreeAuthorize(
- Constants.Trees.DocumentTypes, Constants.Trees.Content,
- Constants.Trees.MediaTypes, Constants.Trees.Media,
- Constants.Trees.MemberTypes, Constants.Trees.Members)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessAnyContentOrTypes)]
public IEnumerable GetAllPropertyTypeAliases()
{
return _contentTypeService.GetAllPropertyTypeAliases();
@@ -236,10 +235,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Gets all the standard fields.
///
///
- [UmbracoTreeAuthorize(
- Constants.Trees.DocumentTypes, Constants.Trees.Content,
- Constants.Trees.MediaTypes, Constants.Trees.Media,
- Constants.Trees.MemberTypes, Constants.Trees.Members)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessAnyContentOrTypes)]
public IEnumerable GetAllStandardFields()
{
string[] preValuesSource = { "createDate", "creatorName", "level", "nodeType", "nodeTypeAlias", "pageID", "pageName", "parentID", "path", "template", "updateDate", "writerID", "writerName" };
@@ -280,10 +276,7 @@ namespace Umbraco.Web.BackOffice.Controllers
return Ok(result);
}
- [UmbracoTreeAuthorize(
- Constants.Trees.DocumentTypes, Constants.Trees.Content,
- Constants.Trees.MediaTypes, Constants.Trees.Media,
- Constants.Trees.MemberTypes, Constants.Trees.Members)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessAnyContentOrTypes)]
public ContentPropertyDisplay GetPropertyTypeScaffold(int id)
{
var dataTypeDiff = _dataTypeService.GetDataType(id);
@@ -523,7 +516,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Returns the allowed child content type objects for the content item id passed in
///
///
- [UmbracoTreeAuthorize(Constants.Trees.DocumentTypes, Constants.Trees.Content)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentsOrDocumentTypes)]
public IEnumerable GetAllowedChildren(int contentId)
{
if (contentId == Constants.System.RecycleBinContent)
diff --git a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
index c88d0d16c9..f8bc313bed 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Net;
using System.Net.Mime;
using System.Text;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Umbraco.Core;
@@ -14,6 +15,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Exceptions;
@@ -31,7 +33,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Content Types, Member Types or Media Types ... and of course to Data Types
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
- [UmbracoTreeAuthorize(Constants.Trees.DataTypes, Constants.Trees.DocumentTypes, Constants.Trees.MediaTypes, Constants.Trees.MemberTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentsOrDocumentTypes)]
public class DataTypeController : BackOfficeNotificationsController
{
private readonly PropertyEditorCollection _propertyEditors;
@@ -414,7 +416,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members
///
- [UmbracoApplicationAuthorizeAttribute(Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
+ [UmbracoApplicationAuthorize(Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
Constants.Applications.Settings, Constants.Applications.Packages)]
public IEnumerable GetAll()
{
@@ -430,7 +432,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members
///
- [UmbracoTreeAuthorize(Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
+ [UmbracoApplicationAuthorize(Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
Constants.Applications.Settings, Constants.Applications.Packages)]
public IDictionary> GetGroupedDataTypes()
{
@@ -462,9 +464,8 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members
///
- [UmbracoTreeAuthorize(Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
+ [UmbracoApplicationAuthorize(Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
Constants.Applications.Settings, Constants.Applications.Packages)]
-
public IDictionary> GetGroupedPropertyEditors()
{
var datatypes = new List();
@@ -495,9 +496,8 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Permission is granted to this method if the user has access to any of these sections: Content, media, settings, developer, members
///
- [UmbracoTreeAuthorize(Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
+ [UmbracoApplicationAuthorize(Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members,
Constants.Applications.Settings, Constants.Applications.Packages)]
-
public IEnumerable GetAllPropertyEditors()
{
return _propertyEditorCollection
diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs
index 785264d816..00e10852c7 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs
@@ -18,6 +18,8 @@ using Umbraco.Web.Security;
using Constants = Umbraco.Core.Constants;
using Umbraco.Core.Configuration.Models;
using Microsoft.Extensions.Options;
+using Microsoft.AspNetCore.Authorization;
+using Umbraco.Web.BackOffice.Authorization;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -30,7 +32,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Dictionary
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
- [UmbracoTreeAuthorize(Constants.Trees.Dictionary)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessDictionary)]
public class DictionaryController : BackOfficeNotificationsController
{
private readonly ILogger _logger;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs
index 66f8b6d7e0..a3e6c83ae6 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Umbraco.Core;
@@ -10,6 +11,7 @@ using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Exceptions;
@@ -80,7 +82,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Deletes a language with a given ID
///
- [UmbracoTreeAuthorize(Constants.Trees.Languages)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessLanguages)]
[HttpDelete]
[HttpPost]
public IActionResult DeleteLanguage(int id)
@@ -109,7 +111,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Creates or saves a language
///
- [UmbracoTreeAuthorize(Constants.Trees.Languages)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessLanguages)]
[HttpPost]
public Language SaveLanguage(Language language)
{
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs
index e4ef90b30c..8b9fb8e7d2 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs
@@ -19,6 +19,8 @@ using Umbraco.Web.Security;
using Umbraco.Core;
using Umbraco.Core.Mapping;
using Umbraco.Core.Security;
+using Umbraco.Web.BackOffice.Authorization;
+using Microsoft.AspNetCore.Authorization;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -27,7 +29,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// The API controller used for editing dictionary items
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
- [UmbracoTreeAuthorize(Constants.Trees.Macros)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMacros)]
public class MacrosController : BackOfficeNotificationsController
{
private readonly ParameterEditorCollection _parameterEditorCollection;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs
index cd834e79fb..84a3e5a260 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Core;
using Umbraco.Core.Dictionary;
@@ -10,6 +11,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Exceptions;
@@ -27,7 +29,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// An API controller used for dealing with content types
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
- [UmbracoTreeAuthorize(Constants.Trees.MediaTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMediaTypes)]
public class MediaTypeController : ContentTypeControllerBase
{
private readonly IContentTypeService _contentTypeService;
@@ -78,7 +80,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[DetermineAmbiguousActionByPassingParameters]
- [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
public MediaTypeDisplay GetById(int id)
{
var ct = _mediaTypeService.Get(id);
@@ -97,7 +99,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[DetermineAmbiguousActionByPassingParameters]
- [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
public MediaTypeDisplay GetById(Guid id)
{
var mediaType = _mediaTypeService.Get(id);
@@ -116,7 +118,7 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
[DetermineAmbiguousActionByPassingParameters]
- [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
public MediaTypeDisplay GetById(Udi id)
{
var guidUdi = id as GuidUdi;
@@ -314,7 +316,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Returns the allowed child content type objects for the content item id passed in - based on an INT id
///
///
- [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
[DetermineAmbiguousActionByPassingParameters]
public IEnumerable GetAllowedChildren(int contentId)
{
@@ -361,7 +363,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Returns the allowed child content type objects for the content item id passed in - based on a GUID id
///
///
- [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
[DetermineAmbiguousActionByPassingParameters]
public IEnumerable GetAllowedChildren(Guid contentId)
{
@@ -378,7 +380,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// Returns the allowed child content type objects for the content item id passed in - based on a UDI id
///
///
- [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMediaOrMediaTypes)]
[DetermineAmbiguousActionByPassingParameters]
public IEnumerable GetAllowedChildren(Udi contentId)
{
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs
index d3d06132d3..12f26f484b 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs
@@ -2,11 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Core;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Exceptions;
@@ -19,7 +21,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// An API controller used for dealing with member groups
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
- [UmbracoTreeAuthorize(Constants.Trees.MemberGroups)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMemberGroups)]
public class MemberGroupController : UmbracoAuthorizedJsonController
{
private readonly IMemberGroupService _memberGroupService;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs
index 3557680ab1..dccc2b7907 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs
@@ -24,6 +24,8 @@ using Umbraco.Web.Common.Exceptions;
using Umbraco.Web.Editors;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
+using Microsoft.AspNetCore.Authorization;
+using Umbraco.Web.BackOffice.Authorization;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -31,7 +33,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// An API controller used for dealing with member types
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
- [UmbracoTreeAuthorize(new string[] { Constants.Trees.MemberTypes, Constants.Trees.Members})]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMemberTypes)]
public class MemberTypeController : ContentTypeControllerBase
{
private readonly IMemberTypeService _memberTypeService;
@@ -71,7 +73,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)]
[DetermineAmbiguousActionByPassingParameters]
public MemberTypeDisplay GetById(int id)
{
@@ -90,7 +91,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)]
[DetermineAmbiguousActionByPassingParameters]
public MemberTypeDisplay GetById(Guid id)
{
@@ -109,7 +109,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
///
///
- [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)]
[DetermineAmbiguousActionByPassingParameters]
public MemberTypeDisplay GetById(Udi id)
{
@@ -134,7 +133,6 @@ namespace Umbraco.Web.BackOffice.Controllers
///
[HttpDelete]
[HttpPost]
- [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)]
public IActionResult DeleteById(int id)
{
var foundType = _memberTypeService.Get(id);
@@ -161,8 +159,6 @@ namespace Umbraco.Web.BackOffice.Controllers
/// be looked up via the db, they need to be passed in.
///
///
-
- [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)]
public IActionResult GetAvailableCompositeMemberTypes(int contentTypeId,
[FromQuery]string[] filterContentTypes,
[FromQuery]string[] filterPropertyTypes)
@@ -176,7 +172,6 @@ namespace Umbraco.Web.BackOffice.Controllers
return Ok(result);
}
- [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)]
public MemberTypeDisplay GetEmpty()
{
var ct = new MemberType(_shortStringHelper, -1);
@@ -190,13 +185,13 @@ namespace Umbraco.Web.BackOffice.Controllers
///
/// Returns all member types
///
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMembersOrMemberTypes)]
public IEnumerable GetAllTypes()
{
return _memberTypeService.GetAll()
.Select(_umbracoMapper.Map);
}
- [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)]
public ActionResult PostSave(MemberTypeSave contentTypeSave)
{
//get the persisted member type
diff --git a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs
index 1ab5bd9bfa..7c80ebcc81 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs
@@ -15,6 +15,8 @@ using Umbraco.Core.Mapping;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Exceptions;
+using Umbraco.Web.BackOffice.Authorization;
+using Microsoft.AspNetCore.Authorization;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -22,7 +24,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// The API controller for editing relation types.
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
- [UmbracoTreeAuthorize(Constants.Trees.RelationTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessRelationTypes)]
public class RelationTypeController : BackOfficeNotificationsController
{
private readonly ILogger _logger;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
index f80c3015e9..d60e87a23b 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Core;
using Umbraco.Core.IO;
@@ -9,6 +10,7 @@ using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Common.Exceptions;
@@ -18,7 +20,7 @@ using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Controllers
{
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
- [UmbracoTreeAuthorize(Constants.Trees.Templates)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessTemplates)]
public class TemplateController : BackOfficeNotificationsController
{
private readonly IFileService _fileService;
diff --git a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs
index 93c6576d4e..7a77739342 100644
--- a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs
+++ b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs
@@ -1,4 +1,5 @@
using System;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
@@ -9,6 +10,7 @@ using Umbraco.Core.Security;
using Umbraco.Core.Serialization;
using Umbraco.Infrastructure.BackOffice;
using Umbraco.Net;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.BackOffice.Security;
using Umbraco.Web.Common.AspNetCore;
@@ -42,6 +44,8 @@ namespace Umbraco.Extensions
// TODO: Need to add more cookie options, see https://github.com/dotnet/aspnetcore/blob/3.0/src/Identity/Core/src/IdentityServiceCollectionExtensions.cs#L45
services.ConfigureOptions();
+
+ services.AddBackOfficeAuthorizationPolicies();
}
public static void AddUmbracoPreview(this IServiceCollection services)
@@ -87,7 +91,7 @@ namespace Umbraco.Extensions
services.GetRequiredService()));
services.TryAddScoped, DefaultUserConfirmation>();
services.TryAddScoped, UserClaimsPrincipalFactory>();
-
+
// CUSTOM:
services.TryAddScoped();
services.TryAddScoped();
@@ -104,5 +108,82 @@ namespace Umbraco.Extensions
return new BackOfficeIdentityBuilder(services);
}
+
+ private static void AddBackOfficeAuthorizationPolicies(this IServiceCollection services)
+ {
+ services.AddAuthorization(options =>
+ {
+ options.AddPolicy(AuthorizationPolicies.TreeAccessUsers, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Users)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessPartialViews, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.PartialViews)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessPartialViewMacros, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.PartialViewMacros)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessPackages, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Packages)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessLogs, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.LogViewer)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessDataTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DataTypes)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessTemplates, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Templates)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessMemberTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MemberTypes)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessRelationTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.RelationTypes)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DocumentTypes)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessMemberGroups, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MemberGroups)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessMediaTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MediaTypes)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessMacros, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Macros)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessLanguages, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Languages)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Dictionary)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessDictionary, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Dictionary, Constants.Trees.Dictionary)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessDictionaryOrTemplates, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Dictionary, Constants.Trees.Templates)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentsOrDocumentTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DocumentTypes, Constants.Trees.Content)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessMediaOrMediaTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MediaTypes, Constants.Trees.Media)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessMembersOrMemberTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MemberTypes, Constants.Trees.Members)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessAnySchemaTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DataTypes, Constants.Trees.DocumentTypes, Constants.Trees.MediaTypes, Constants.Trees.MemberTypes)));
+
+ options.AddPolicy(AuthorizationPolicies.TreeAccessAnyContentOrTypes, policy =>
+ policy.Requirements.Add(new TreeAliasesRequirement(
+ Constants.Trees.DocumentTypes, Constants.Trees.Content,
+ Constants.Trees.MediaTypes, Constants.Trees.Media,
+ Constants.Trees.MemberTypes, Constants.Trees.Members)));
+ });
+
+ services.AddSingleton();
+ }
}
}
diff --git a/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs
deleted file mode 100644
index eef7469322..0000000000
--- a/src/Umbraco.Web.BackOffice/Filters/UmbracoTreeAuthorizeAttribute.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using System;
-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;
-
-namespace Umbraco.Web.BackOffice.Filters
-{
- ///
- /// Ensures that the current user has access to the application for which the specified tree(s) belongs
- ///
- ///
- /// This would allow a tree to be moved between sections
- ///
- public class UmbracoTreeAuthorizeAttribute : TypeFilterAttribute
- {
- public UmbracoTreeAuthorizeAttribute(params string[] treeAliases) : base(typeof(UmbracoTreeAuthorizeFilter))
- {
- Arguments = new object[]
- {
- treeAliases
- };
- }
-
- private sealed class UmbracoTreeAuthorizeFilter : IAuthorizationFilter
- {
- ///
- /// Can be used by unit tests to enable/disable this filter
- ///
- internal static readonly bool Enable = true;
-
- private readonly string[] _treeAliases;
-
- private readonly ITreeService _treeService;
- 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, IBackOfficeSecurityAccessor backofficeSecurityAccessor,
- params string[] treeAliases)
- {
- _treeService = treeService ?? throw new ArgumentNullException(nameof(treeService));
- _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor));
- _treeAliases = treeAliases;
- }
-
- public void OnAuthorization(AuthorizationFilterContext context)
- {
- if (!IsAuthorized())
- {
- context.Result = new ForbidResult();
- }
- }
-
- private bool IsAuthorized()
- {
- if (Enable == false)
- {
- return true;
- }
-
- var apps = _treeAliases.Select(x => _treeService
- .GetByAlias(x))
- .WhereNotNull()
- .Select(x => x.SectionAlias)
- .Distinct()
- .ToArray();
-
- return _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null
- && apps.Any(app => _backofficeSecurityAccessor.BackOfficeSecurity.UserHasSectionAccess(
- app, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser));
- }
- }
- }
-}
diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs
index 5c8312c058..15c206e65f 100644
--- a/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/ContentTypeTreeController.cs
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Actions;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Models.ContentEditing;
@@ -16,7 +18,7 @@ using Umbraco.Web.WebApi;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.DocumentTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
[Tree(Constants.Applications.Settings, Constants.Trees.DocumentTypes, SortOrder = 0, TreeGroup = Constants.Trees.Groups.Settings)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs
index 3502d7a506..f4e42729f0 100644
--- a/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/DataTypeTreeController.cs
@@ -14,10 +14,12 @@ using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Trees;
using Umbraco.Web.WebApi;
+using Umbraco.Web.BackOffice.Authorization;
+using Microsoft.AspNetCore.Authorization;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.DataTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessDataTypes)]
[Tree(Constants.Applications.Settings, Constants.Trees.DataTypes, SortOrder = 3, TreeGroup = Constants.Trees.Groups.Settings)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/DictionaryTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/DictionaryTreeController.cs
index a9878a3dbc..163e1607a7 100644
--- a/src/Umbraco.Web.BackOffice/Trees/DictionaryTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/DictionaryTreeController.cs
@@ -1,10 +1,12 @@
using System;
using System.Linq;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Actions;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Models.Trees;
@@ -14,12 +16,9 @@ using Umbraco.Web.WebApi;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(
- Constants.Trees.Dictionary,
- Constants.Trees.Templates
- // We are allowed to see the dictionary tree, if we are allowed to manage templates, such that se can use the
- // dictionary items in templates, even when we dont have authorization to manage the dictionary items
- )]
+ // We are allowed to see the dictionary tree, if we are allowed to manage templates, such that se can use the
+ // dictionary items in templates, even when we dont have authorization to manage the dictionary items
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessDictionaryOrTemplates)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
[Tree(Constants.Applications.Translation, Constants.Trees.Dictionary, TreeGroup = Constants.Trees.Groups.Settings)]
diff --git a/src/Umbraco.Web.BackOffice/Trees/LanguageTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/LanguageTreeController.cs
index d4a2c91fad..9ac3d0d43c 100644
--- a/src/Umbraco.Web.BackOffice/Trees/LanguageTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/LanguageTreeController.cs
@@ -1,5 +1,7 @@
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Models.Trees;
@@ -9,7 +11,7 @@ using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.Languages)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessLanguages)]
[Tree(Constants.Applications.Settings, Constants.Trees.Languages, SortOrder = 11, TreeGroup = Constants.Trees.Groups.Settings)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/LogViewerTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/LogViewerTreeController.cs
index 9ffe6e8b68..4e484c447c 100644
--- a/src/Umbraco.Web.BackOffice/Trees/LogViewerTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/LogViewerTreeController.cs
@@ -1,5 +1,7 @@
-using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Models.Trees;
@@ -9,7 +11,7 @@ using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.LogViewer)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessLogs)]
[Tree(Constants.Applications.Settings, Constants.Trees.LogViewer, SortOrder= 9, TreeGroup = Constants.Trees.Groups.Settings)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs
index 567f0a3646..1df741ce81 100644
--- a/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/MacrosTreeController.cs
@@ -8,10 +8,12 @@ using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Trees;
using Umbraco.Web.WebApi;
using Constants = Umbraco.Core.Constants;
+using Umbraco.Web.BackOffice.Authorization;
+using Microsoft.AspNetCore.Authorization;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.Macros)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMacros)]
[Tree(Constants.Applications.Settings, Constants.Trees.Macros, TreeTitle = "Macros", SortOrder = 4, TreeGroup = Constants.Trees.Groups.Settings)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs
index 4df81b7023..de8e51719d 100644
--- a/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/MediaTypeTreeController.cs
@@ -13,10 +13,12 @@ using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Trees;
using Umbraco.Web.WebApi;
+using Umbraco.Web.BackOffice.Authorization;
+using Microsoft.AspNetCore.Authorization;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.MediaTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMediaTypes)]
[Tree(Constants.Applications.Settings, Constants.Trees.MediaTypes, SortOrder = 1, TreeGroup = Constants.Trees.Groups.Settings)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/MemberGroupTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MemberGroupTreeController.cs
index 17de4ca37d..440a3439f2 100644
--- a/src/Umbraco.Web.BackOffice/Trees/MemberGroupTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/MemberGroupTreeController.cs
@@ -1,8 +1,10 @@
using System.Collections.Generic;
using System.Linq;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Umbraco.Core;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Models.Trees;
@@ -11,7 +13,7 @@ using Umbraco.Web.WebApi;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.MemberGroups)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMemberGroups)]
[Tree(Constants.Applications.Members, Constants.Trees.MemberGroups, SortOrder = 1)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs
index c9e340617e..9f560700e8 100644
--- a/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/MemberTypeTreeController.cs
@@ -1,9 +1,11 @@
using System.Collections.Generic;
using System.Linq;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.BackOffice.Trees;
using Umbraco.Web.Common.Attributes;
@@ -16,7 +18,7 @@ using Umbraco.Web.WebApi;
namespace Umbraco.Web.BackOffice.Trees
{
[CoreTree]
- [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessMemberTypes)]
[Tree(Constants.Applications.Settings, Constants.Trees.MemberTypes, SortOrder = 2, TreeGroup = Constants.Trees.Groups.Settings)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
public class MemberTypeTreeController : MemberTypeAndGroupTreeControllerBase, ISearchableTree
diff --git a/src/Umbraco.Web.BackOffice/Trees/PackagesTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/PackagesTreeController.cs
index fc1f3d876f..08051c6ab3 100644
--- a/src/Umbraco.Web.BackOffice/Trees/PackagesTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/PackagesTreeController.cs
@@ -1,5 +1,7 @@
-using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Models.Trees;
@@ -9,7 +11,7 @@ using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.Packages)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessPackages)]
[Tree(Constants.Applications.Packages, Constants.Trees.Packages, SortOrder = 0, IsSingleNodeTree = true)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs
index 5baeac7d17..c5f95ebc5e 100644
--- a/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs
@@ -1,5 +1,7 @@
-using Umbraco.Core.IO;
+using Microsoft.AspNetCore.Authorization;
+using Umbraco.Core.IO;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Trees;
@@ -12,7 +14,7 @@ namespace Umbraco.Web.BackOffice.Trees
/// Tree for displaying partial view macros in the developer app
///
[Tree(Constants.Applications.Settings, Constants.Trees.PartialViewMacros, SortOrder = 8, TreeGroup = Constants.Trees.Groups.Templating)]
- [UmbracoTreeAuthorize(Constants.Trees.PartialViewMacros)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessPartialViewMacros)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
public class PartialViewMacrosTreeController : PartialViewsTreeController
diff --git a/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs
index dcb98ac5b4..8fd7d8de6a 100644
--- a/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs
@@ -1,5 +1,7 @@
-using Umbraco.Core.IO;
+using Microsoft.AspNetCore.Authorization;
+using Umbraco.Core.IO;
using Umbraco.Core.Services;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Composing;
@@ -14,7 +16,7 @@ namespace Umbraco.Web.BackOffice.Trees
/// Tree for displaying partial views in the settings app
///
[Tree(Core.Constants.Applications.Settings, Core.Constants.Trees.PartialViews, SortOrder = 7, TreeGroup = Core.Constants.Trees.Groups.Templating)]
- [UmbracoTreeAuthorize(Constants.Trees.PartialViews)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessPartialViews)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
public class PartialViewsTreeController : FileSystemTreeController
diff --git a/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs
index 965e957f02..ceb8b9a032 100644
--- a/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/RelationTypeTreeController.cs
@@ -9,10 +9,12 @@ using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Trees;
using Umbraco.Web.WebApi;
+using Umbraco.Web.BackOffice.Authorization;
+using Microsoft.AspNetCore.Authorization;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.RelationTypes)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessRelationTypes)]
[Tree(Constants.Applications.Settings, Constants.Trees.RelationTypes, SortOrder = 5, TreeGroup = Constants.Trees.Groups.Settings)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs
index cfe2d57ce5..2054a6b5f4 100644
--- a/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/TemplatesTreeController.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Umbraco.Core;
using Umbraco.Core.Models;
@@ -8,6 +9,7 @@ using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
using Umbraco.Extensions;
using Umbraco.Web.Actions;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Models.ContentEditing;
@@ -19,7 +21,7 @@ using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.Templates)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessTemplates)]
[Tree(Constants.Applications.Settings, Constants.Trees.Templates, SortOrder = 6, TreeGroup = Constants.Trees.Groups.Templating)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
diff --git a/src/Umbraco.Web.BackOffice/Trees/UserTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/UserTreeController.cs
index feb8d2a9ec..33e943e9b4 100644
--- a/src/Umbraco.Web.BackOffice/Trees/UserTreeController.cs
+++ b/src/Umbraco.Web.BackOffice/Trees/UserTreeController.cs
@@ -1,22 +1,16 @@
-using Microsoft.AspNetCore.Http;
-using Umbraco.Core;
-using Umbraco.Core.Cache;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.Logging;
-using Umbraco.Core.Mapping;
-using Umbraco.Core.Persistence;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
using Umbraco.Core.Services;
-using Umbraco.Web.BackOffice.Filters;
+using Umbraco.Web.BackOffice.Authorization;
using Umbraco.Web.Common.Attributes;
using Umbraco.Web.Models.Trees;
-using Umbraco.Web.Routing;
using Umbraco.Web.Trees;
using Umbraco.Web.WebApi;
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.BackOffice.Trees
{
- [UmbracoTreeAuthorize(Constants.Trees.Users)]
+ [Authorize(Policy = AuthorizationPolicies.TreeAccessUsers)]
[Tree(Constants.Applications.Users, Constants.Trees.Users, SortOrder = 0, IsSingleNodeTree = true)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]