Browse Source

Redesign permission checker.

pull/216/head
Halil İbrahim Kalkan 8 years ago
parent
commit
82c8dce8e5
  1. 7
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs
  2. 2
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/PermissionRequirementHandler.cs
  3. 8
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/AlwaysAllowPermissionChecker.cs
  4. 5
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionChecker.cs
  5. 2
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs
  6. 28
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs
  7. 8
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionCheckerExtensions.cs
  8. 22
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueCheckContext.cs
  9. 2
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProvider.cs
  10. 19
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs
  11. 26
      src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/UserPermissionValueProvider.cs
  12. 3
      src/Volo.Abp.Identity.Application/Volo/Abp/Identity/UserPermissionManagementProvider.cs
  13. 1
      src/Volo.Abp.Identity.Application/Volo/Abp/Permissions/RolePermissionManagerExtensions.cs
  14. 1
      src/Volo.Abp.Identity.Application/Volo/Abp/Permissions/UserPermissionManagerExtensions.cs
  15. 2
      src/Volo.Abp.Session/Volo.Abp.Session.csproj
  16. 9
      src/Volo.Abp.Session/Volo/Abp/Session/AbpSessionModule.cs
  17. 2
      src/Volo.Abp.Session/Volo/Abp/Settings/UserSettingManagerExtensions.cs
  18. 3
      test/Volo.Abp.Identity.Tests/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs
  19. 30
      test/Volo.Abp.Permissions.Tests/Volo/Abp/Permissions/PermissionChecker_User_Tests.cs
  20. 1
      test/Volo.Abp.Permissions.Tests/Volo/Abp/Permissions/PermissionTestDataBuilder.cs

7
src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Modularity;
using Volo.Abp.Security;
@ -14,6 +15,12 @@ namespace Volo.Abp.Authorization
services.AddSingleton<IAuthorizationHandler, PermissionRequirementHandler>();
services.Configure<PermissionOptions>(options =>
{
options.ValueProviders.Add<UserPermissionValueProvider>();
options.ValueProviders.Add<RolePermissionValueProvider>();
});
services.AddAssemblyOf<AbpAuthorizationModule>();
}
}

2
src/Volo.Abp.Authorization/Volo/Abp/Authorization/PermissionRequirementHandler.cs

@ -17,7 +17,7 @@ namespace Volo.Abp.Authorization
AuthorizationHandlerContext context,
PermissionRequirement requirement)
{
if (await _permissionChecker.IsGrantedAsync(requirement.PermissionName))
if (await _permissionChecker.IsGrantedAsync(context.User, requirement.PermissionName))
{
context.Succeed(requirement);
}

8
src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/AlwaysAllowPermissionChecker.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Volo.Abp.Authorization.Permissions
{
@ -14,5 +15,10 @@ namespace Volo.Abp.Authorization.Permissions
{
return Task.FromResult(new PermissionGrantInfo(name, true, "AlwaysAllow"));
}
public Task<PermissionGrantInfo> CheckAsync(ClaimsPrincipal claimsPrincipal, string name)
{
return Task.FromResult(new PermissionGrantInfo(name, true, "AlwaysAllow"));
}
}
}

5
src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionChecker.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Security.Claims;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Authorization.Permissions
@ -6,5 +7,7 @@ namespace Volo.Abp.Authorization.Permissions
public interface IPermissionChecker
{
Task<PermissionGrantInfo> CheckAsync([NotNull]string name);
Task<PermissionGrantInfo> CheckAsync([CanBeNull] ClaimsPrincipal claimsPrincipal, [NotNull]string name);
}
}

2
src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs

@ -7,6 +7,6 @@ namespace Volo.Abp.Authorization.Permissions
{
string Name { get; }
Task<PermissionValueProviderGrantInfo> CheckAsync(PermissionDefinition permission);
Task<PermissionValueProviderGrantInfo> CheckAsync(PermissionValueCheckContext context);
}
}

28
src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs

@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.Authorization.Permissions
{
@ -14,6 +17,8 @@ namespace Volo.Abp.Authorization.Permissions
protected IReadOnlyList<IPermissionValueProvider> ValueProviders => _lazyProviders.Value;
protected ICurrentPrincipalAccessor PrincipalAccessor { get; }
protected PermissionOptions Options { get; }
private readonly Lazy<List<IPermissionValueProvider>> _lazyProviders;
@ -21,8 +26,10 @@ namespace Volo.Abp.Authorization.Permissions
public PermissionChecker(
IOptions<PermissionOptions> options,
IServiceProvider serviceProvider,
ICurrentPrincipalAccessor principalAccessor,
IPermissionDefinitionManager permissionDefinitionManager)
{
PrincipalAccessor = principalAccessor;
PermissionDefinitionManager = permissionDefinitionManager;
Options = options.Value;
@ -35,25 +42,30 @@ namespace Volo.Abp.Authorization.Permissions
);
}
public Task<PermissionGrantInfo> CheckAsync(string name)
public virtual Task<PermissionGrantInfo> CheckAsync(string name)
{
var permission = PermissionDefinitionManager.Get(name);
return GetPermissionGrantInfo(permission);
return CheckAsync(PrincipalAccessor.Principal, name);
}
protected virtual async Task<PermissionGrantInfo> GetPermissionGrantInfo(PermissionDefinition permission)
public virtual async Task<PermissionGrantInfo> CheckAsync(ClaimsPrincipal claimsPrincipal, string name)
{
Check.NotNull(name, nameof(name));
var context = new PermissionValueCheckContext(
PermissionDefinitionManager.Get(name),
claimsPrincipal
);
foreach (var provider in ValueProviders)
{
var result = await provider.CheckAsync(permission);
var result = await provider.CheckAsync(context);
if (result.IsGranted)
{
return new PermissionGrantInfo(permission.Name, true, provider.Name, result.ProviderKey);
return new PermissionGrantInfo(context.Permission.Name, true, provider.Name, result.ProviderKey);
}
}
return new PermissionGrantInfo(permission.Name, false);
return new PermissionGrantInfo(context.Permission.Name, false);
}
}
}

8
src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionCheckerExtensions.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Volo.Abp.Authorization.Permissions
{
@ -9,6 +10,11 @@ namespace Volo.Abp.Authorization.Permissions
return (await permissionChecker.CheckAsync(name)).IsGranted;
}
public static async Task<bool> IsGrantedAsync(this IPermissionChecker permissionChecker, ClaimsPrincipal principal, string name)
{
return (await permissionChecker.CheckAsync(principal, name)).IsGranted;
}
//TODO: Add sync extensions
}
}

22
src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueCheckContext.cs

@ -0,0 +1,22 @@
using System.Security.Claims;
using JetBrains.Annotations;
namespace Volo.Abp.Authorization.Permissions
{
public class PermissionValueCheckContext
{
[NotNull]
public PermissionDefinition Permission { get; }
[CanBeNull]
public ClaimsPrincipal Principal { get; }
public PermissionValueCheckContext([NotNull] PermissionDefinition permission, [CanBeNull] ClaimsPrincipal principal)
{
Check.NotNull(permission, nameof(permission));
Permission = permission;
Principal = principal;
}
}
}

2
src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProvider.cs

@ -13,6 +13,6 @@ namespace Volo.Abp.Authorization.Permissions
PermissionStore = permissionStore;
}
public abstract Task<PermissionValueProviderGrantInfo> CheckAsync(PermissionDefinition permission);
public abstract Task<PermissionValueProviderGrantInfo> CheckAsync(PermissionValueCheckContext context);
}
}

19
src/Volo.Abp.Session/Volo/Abp/Session/RolePermissionValueProvider.cs → src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs

@ -1,8 +1,8 @@
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.Session
namespace Volo.Abp.Authorization.Permissions
{
public class RolePermissionValueProvider : PermissionValueProvider
{
@ -10,24 +10,23 @@ namespace Volo.Abp.Session
public override string Name => ProviderName;
protected ICurrentUser CurrentUser { get; }
public RolePermissionValueProvider(IPermissionStore permissionStore, ICurrentUser currentUser)
public RolePermissionValueProvider(IPermissionStore permissionStore)
: base(permissionStore)
{
CurrentUser = currentUser;
}
public override async Task<PermissionValueProviderGrantInfo> CheckAsync(PermissionDefinition permission)
public override async Task<PermissionValueProviderGrantInfo> CheckAsync(PermissionValueCheckContext context)
{
if (CurrentUser.Id == null || !CurrentUser.Roles.Any())
var roles = context.Principal?.FindAll(AbpClaimTypes.Role).Select(c => c.Value).ToArray();
if (roles == null || !roles.Any())
{
return PermissionValueProviderGrantInfo.NonGranted;
}
foreach (var role in CurrentUser.Roles)
foreach (var role in roles)
{
if (await PermissionStore.IsGrantedAsync(permission.Name, Name, role))
if (await PermissionStore.IsGrantedAsync(context.Permission.Name, Name, role))
{
return new PermissionValueProviderGrantInfo(true, role);
}

26
src/Volo.Abp.Session/Volo/Abp/Session/UserPermissionValueProvider.cs → src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/UserPermissionValueProvider.cs

@ -1,7 +1,7 @@
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.Session
namespace Volo.Abp.Authorization.Permissions
{
public class UserPermissionValueProvider : PermissionValueProvider
{
@ -9,25 +9,27 @@ namespace Volo.Abp.Session
public override string Name => ProviderName;
protected ICurrentUser CurrentUser { get; }
public UserPermissionValueProvider(IPermissionStore permissionStore, ICurrentUser currentUser)
public UserPermissionValueProvider(IPermissionStore permissionStore)
: base(permissionStore)
{
CurrentUser = currentUser;
}
public override async Task<PermissionValueProviderGrantInfo> CheckAsync(PermissionDefinition permission)
public override async Task<PermissionValueProviderGrantInfo> CheckAsync(PermissionValueCheckContext context)
{
if (CurrentUser.Id == null)
var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value;
if (userId == null)
{
return PermissionValueProviderGrantInfo.NonGranted;
}
return new PermissionValueProviderGrantInfo(
await PermissionStore.IsGrantedAsync(permission.Name, Name, CurrentUser.Id.Value.ToString()),
CurrentUser.Id.ToString()
);
if (await PermissionStore.IsGrantedAsync(context.Permission.Name, Name, userId))
{
return new PermissionValueProviderGrantInfo(true, userId);
}
return PermissionValueProviderGrantInfo.NonGranted;
}
}
}

3
src/Volo.Abp.Identity.Application/Volo/Abp/Identity/UserPermissionManagementProvider.cs

@ -1,4 +1,5 @@
using Volo.Abp.Guids;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Permissions;
using Volo.Abp.Session;

1
src/Volo.Abp.Identity.Application/Volo/Abp/Permissions/RolePermissionManagerExtensions.cs

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Session;
namespace Volo.Abp.Permissions

1
src/Volo.Abp.Identity.Application/Volo/Abp/Permissions/UserPermissionManagerExtensions.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Session;
namespace Volo.Abp.Permissions

2
src/Volo.Abp.Session/Volo.Abp.Session.csproj

@ -14,8 +14,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Authorization\Volo.Abp.Authorization.csproj" />
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
</ItemGroup>

9
src/Volo.Abp.Session/Volo/Abp/Session/AbpSessionModule.cs

@ -1,6 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Authorization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Modularity;
using Volo.Abp.Security;
using Volo.Abp.Settings;
@ -9,7 +7,6 @@ namespace Volo.Abp.Session
{
[DependsOn(typeof(AbpSecurityModule))]
[DependsOn(typeof(AbpSettingsModule))]
[DependsOn(typeof(AbpAuthorizationModule))]
public class AbpSessionModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
@ -19,12 +16,6 @@ namespace Volo.Abp.Session
options.ValueProviders.Add<UserSettingValueProvider>();
});
services.Configure<PermissionOptions>(options =>
{
options.ValueProviders.Add<UserPermissionValueProvider>();
options.ValueProviders.Add<RolePermissionValueProvider>();
});
services.AddAssemblyOf<AbpSessionModule>();
}
}

2
src/Volo.Abp.Session/Volo/Abp/Settings/UserSettingManagerExtensions.cs

@ -6,6 +6,8 @@ using Volo.Abp.Session;
namespace Volo.Abp.Settings
{
//TODO: Consider to move to another package?
public static class UserSettingManagerExtensions
{
public static Task<string> GetOrNullForUserAsync(this ISettingManager settingManager, [NotNull] string name, Guid userId, bool fallback = true)

3
test/Volo.Abp.Identity.Tests/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs

@ -1,4 +1,5 @@
using Volo.Abp.DependencyInjection;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Permissions;
using Volo.Abp.Session;

30
test/Volo.Abp.Permissions.Tests/Volo/Abp/Permissions/PermissionChecker_User_Tests.cs

@ -1,9 +1,11 @@
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
using Shouldly;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Security.Claims;
using Volo.Abp.Session;
using Xunit;
@ -13,26 +15,16 @@ namespace Volo.Abp.Permissions
{
private readonly IPermissionChecker _permissionChecker;
private Guid? _currentUserId;
public PermissionChecker_User_Tests()
{
_permissionChecker = GetRequiredService<IPermissionChecker>();
}
protected override void AfterAddApplication(IServiceCollection services)
{
var currentUser = Substitute.For<ICurrentUser>();
currentUser.Id.Returns(ci => _currentUserId);
services.AddSingleton(currentUser);
}
[Fact]
public async Task Should_Return_True_For_Granted_Current_User()
{
_currentUserId = PermissionTestDataBuilder.User1Id;
(await _permissionChecker.IsGrantedAsync(
CreatePrincipal(PermissionTestDataBuilder.User1Id),
"MyPermission1"
)).ShouldBeTrue();
}
@ -40,9 +32,8 @@ namespace Volo.Abp.Permissions
[Fact]
public async Task Should_Return_False_For_Non_Granted_Current_User()
{
_currentUserId = PermissionTestDataBuilder.User2Id;
(await _permissionChecker.IsGrantedAsync(
CreatePrincipal(PermissionTestDataBuilder.User2Id),
"MyPermission1"
)).ShouldBeFalse();
}
@ -51,8 +42,21 @@ namespace Volo.Abp.Permissions
public async Task Should_Return_False_For_Current_User_If_Anonymous()
{
(await _permissionChecker.IsGrantedAsync(
CreatePrincipal(null),
"MyPermission1"
)).ShouldBeFalse();
}
private static ClaimsPrincipal CreatePrincipal(Guid? userId)
{
var claimsIdentity = new ClaimsIdentity();
if (userId != null)
{
claimsIdentity.AddClaim(new Claim(AbpClaimTypes.UserId, userId.ToString()));
}
return new ClaimsPrincipal(claimsIdentity);
}
}
}

1
test/Volo.Abp.Permissions.Tests/Volo/Abp/Permissions/PermissionTestDataBuilder.cs

@ -1,4 +1,5 @@
using System;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Session;

Loading…
Cancel
Save