Removes UmbracoApplicationAuthorizeAttribute and migrates usages to authz policies
This commit is contained in:
@@ -2,31 +2,47 @@
|
||||
{
|
||||
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";
|
||||
// TODO: Rethink these names! Describe what they are doing probably
|
||||
|
||||
public const string SectionAccessContentOrMedia = nameof(SectionAccessContentOrMedia);
|
||||
public const string SectionAccessContent = nameof(SectionAccessContent);
|
||||
public const string SectionAccessPackages = nameof(SectionAccessPackages);
|
||||
public const string SectionAccessUsers = nameof(SectionAccessUsers);
|
||||
public const string SectionAccessMedia = nameof(SectionAccessMedia);
|
||||
public const string SectionAccessSettings = nameof(SectionAccessSettings);
|
||||
public const string SectionAccessForTinyMce = nameof(SectionAccessForTinyMce);
|
||||
public const string SectionAccessForMemberTree = nameof(SectionAccessForMemberTree);
|
||||
public const string SectionAccessForMediaTree = nameof(SectionAccessForMediaTree);
|
||||
public const string SectionAccessForContentTree = nameof(SectionAccessForContentTree);
|
||||
public const string SectionAccessForDataTypeReading = nameof(SectionAccessForDataTypeReading);
|
||||
public const string SectionAccessMembers = nameof(SectionAccessMembers);
|
||||
|
||||
public const string TreeAccessDocuments = nameof(TreeAccessDocuments);
|
||||
public const string TreeAccessUsers = nameof(TreeAccessUsers);
|
||||
public const string TreeAccessPartialViews = nameof(TreeAccessPartialViews);
|
||||
public const string TreeAccessPartialViewMacros = nameof(TreeAccessPartialViewMacros);
|
||||
public const string TreeAccessDataTypes = nameof(TreeAccessDataTypes);
|
||||
public const string TreeAccessPackages = nameof(TreeAccessPackages);
|
||||
public const string TreeAccessLogs = nameof(TreeAccessLogs);
|
||||
public const string TreeAccessTemplates = nameof(TreeAccessTemplates);
|
||||
public const string TreeAccessDictionary = nameof(TreeAccessDictionary);
|
||||
public const string TreeAccessRelationTypes = nameof(TreeAccessRelationTypes);
|
||||
public const string TreeAccessMediaTypes = nameof(TreeAccessMediaTypes);
|
||||
public const string TreeAccessMacros = nameof(TreeAccessMacros);
|
||||
public const string TreeAccessLanguages = nameof(TreeAccessLanguages);
|
||||
public const string TreeAccessMemberGroups = nameof(TreeAccessMemberGroups);
|
||||
public const string TreeAccessDocumentTypes = nameof(TreeAccessDocumentTypes);
|
||||
public const string TreeAccessMemberTypes = nameof(TreeAccessMemberTypes);
|
||||
public const string TreeAccessDocumentsOrDocumentTypes = nameof(TreeAccessDocumentsOrDocumentTypes);
|
||||
public const string TreeAccessMediaOrMediaTypes = nameof(TreeAccessMediaOrMediaTypes);
|
||||
public const string TreeAccessMembersOrMemberTypes = nameof(TreeAccessMembersOrMemberTypes);
|
||||
public const string TreeAccessAnySchemaTypes = nameof(TreeAccessAnySchemaTypes);
|
||||
public const string TreeAccessDictionaryOrTemplates = nameof(TreeAccessDictionaryOrTemplates);
|
||||
|
||||
/// <summary>
|
||||
/// 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)
|
||||
/// </summary>
|
||||
public const string TreeAccessAnyContentOrTypes = "TreeAccessAnyContentOrTypes";
|
||||
public const string TreeAccessAnyContentOrTypes = nameof(TreeAccessAnyContentOrTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Authorization requirements for <see cref="UmbracoSectionAuthorizeHandler"/>
|
||||
/// </summary>
|
||||
public class SectionAliasesRequirement : IAuthorizationRequirement
|
||||
{
|
||||
/// <summary>
|
||||
/// The aliases for sections that the user will need access to
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string> SectionAliases { get; }
|
||||
|
||||
public SectionAliasesRequirement(params string[] aliases) => SectionAliases = aliases;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the current user has access to the section
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The user only needs access to one of the sections specified, not all of the sections.
|
||||
/// </remarks>
|
||||
public class UmbracoSectionAuthorizeHandler : AuthorizationHandler<SectionAliasesRequirement>
|
||||
{
|
||||
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
|
||||
|
||||
public UmbracoSectionAuthorizeHandler(IBackOfficeSecurityAccessor backofficeSecurityAccessor)
|
||||
{
|
||||
_backofficeSecurityAccessor = backofficeSecurityAccessor;
|
||||
}
|
||||
|
||||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SectionAliasesRequirement requirement)
|
||||
{
|
||||
if (IsAuthorized(requirement))
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Fail();
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private bool IsAuthorized(SectionAliasesRequirement requirement)
|
||||
{
|
||||
var authorized = _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null
|
||||
&& requirement.SectionAliases.Any(app => _backofficeSecurityAccessor.BackOfficeSecurity.UserHasSectionAccess(
|
||||
app, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser));
|
||||
|
||||
return authorized;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,9 @@ using Umbraco.Web.Services;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the current user has access to the application for which the specified tree(s) belongs
|
||||
/// Ensures that the current user has access to the section for which the specified tree(s) belongs
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This would allow a tree to be moved between sections.
|
||||
@@ -17,10 +18,6 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </remarks>
|
||||
public class UmbracoTreeAuthorizeHandler : AuthorizationHandler<TreeAliasesRequirement>
|
||||
{
|
||||
/// <summary>
|
||||
/// Can be used by unit tests to enable/disable this filter
|
||||
/// </summary>
|
||||
internal static readonly bool Enable = true;
|
||||
|
||||
private readonly ITreeService _treeService;
|
||||
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
|
||||
@@ -40,25 +37,6 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
_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))
|
||||
@@ -72,5 +50,19 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private bool IsAuthorized(TreeAliasesRequirement requirement)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user