Browse Source

Merge pull request #10152 from abpframework/maliming/PermissionsRequirementHandler

Add `PermissionsRequirement` and `PermissionsRequirementHandler` to check multiple permissions.
pull/10160/head
liangshiwei 5 years ago
committed by GitHub
parent
commit
19ee96129c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/PermissionsRequirement.cs
  2. 31
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/PermissionsRequirementHandler.cs
  3. 1
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs
  4. 11
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
  5. 14
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController.cs
  6. 27
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController_Tests.cs
  7. 1
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/TestPermissionDefinitionProvider.cs
  8. 7
      framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs

25
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/PermissionsRequirement.cs

@ -0,0 +1,25 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authorization;
namespace Volo.Abp.Authorization
{
public class PermissionsRequirement : IAuthorizationRequirement
{
public string[] PermissionNames { get; }
public bool RequiresAll { get; }
public PermissionsRequirement([NotNull]string[] permissionNames, bool requiresAll)
{
Check.NotNull(permissionNames, nameof(permissionNames));
PermissionNames = permissionNames;
RequiresAll = requiresAll;
}
public override string ToString()
{
return $"PermissionsRequirement: {string.Join(", ", PermissionNames)}";
}
}
}

31
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/PermissionsRequirementHandler.cs

@ -0,0 +1,31 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Authorization.Permissions;
namespace Volo.Abp.Authorization
{
public class PermissionsRequirementHandler : AuthorizationHandler<PermissionsRequirement>
{
private readonly IPermissionChecker _permissionChecker;
public PermissionsRequirementHandler(IPermissionChecker permissionChecker)
{
_permissionChecker = permissionChecker;
}
protected override async Task HandleRequirementAsync(
AuthorizationHandlerContext context,
PermissionsRequirement requirement)
{
var multiplePermissionGrantResult = await _permissionChecker.IsGrantedAsync(context.User, requirement.PermissionNames);
if (requirement.RequiresAll ?
multiplePermissionGrantResult.AllGranted :
multiplePermissionGrantResult.Result.Any(x => x.Value == PermissionGrantResult.Granted))
{
context.Succeed(requirement);
}
}
}
}

1
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs

@ -31,6 +31,7 @@ namespace Volo.Abp.Authorization
context.Services.AddAuthorizationCore();
context.Services.AddSingleton<IAuthorizationHandler, PermissionRequirementHandler>();
context.Services.AddSingleton<IAuthorizationHandler, PermissionsRequirementHandler>();
context.Services.TryAddTransient<DefaultAuthorizationPolicyProvider>();

11
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs

@ -11,6 +11,7 @@ using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.Localization.Resource;
using Volo.Abp.AspNetCore.Security.Claims;
using Volo.Abp.AspNetCore.TestBase;
using Volo.Abp.Authorization;
using Volo.Abp.Autofac;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Localization;
@ -65,6 +66,16 @@ namespace Volo.Abp.AspNetCore.Mvc
{
policy.RequireClaim("MyCustomClaimType", "42");
});
options.AddPolicy("TestPermission1_And_TestPermission2", policy =>
{
policy.Requirements.Add(new PermissionsRequirement(new []{"TestPermission1", "TestPermission2"}, requiresAll: true));
});
options.AddPolicy("TestPermission1_Or_TestPermission2", policy =>
{
policy.Requirements.Add(new PermissionsRequirement(new []{"TestPermission1", "TestPermission2"}, requiresAll: false));
});
});
Configure<AbpAspNetCoreMvcOptions>(options =>

14
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController.cs

@ -38,5 +38,19 @@ namespace Volo.Abp.AspNetCore.Mvc.Authorization
CurrentUser.Id.ShouldBe(FakeUserId);
return Content("OK");
}
[Authorize("TestPermission1_And_TestPermission2")]
public ActionResult Custom_And_PolicyTest()
{
CurrentUser.Id.ShouldBe(FakeUserId);
return Content("OK");
}
[Authorize("TestPermission1_Or_TestPermission2")]
public ActionResult Custom_Or_PolicyTest()
{
CurrentUser.Id.ShouldBe(FakeUserId);
return Content("OK");
}
}
}

27
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController_Tests.cs

@ -1,5 +1,4 @@
using System;
using System.Net;
using System.Net;
using System.Security.Claims;
using System.Threading.Tasks;
using Shouldly;
@ -72,5 +71,29 @@ namespace Volo.Abp.AspNetCore.Mvc.Authorization
var result = await GetResponseAsStringAsync("/AuthTest/PermissionTest");
result.ShouldBe("OK");
}
[Fact]
public async Task Custom_And_Policy_Should_Not_Work_When_Permissions_Not_Granted()
{
_fakeRequiredService.Claims.AddRange(new[]
{
new Claim(AbpClaimTypes.UserId, AuthTestController.FakeUserId.ToString())
});
var response = await GetResponseAsync("/AuthTest/Custom_And_PolicyTest", HttpStatusCode.Forbidden, xmlHttpRequest: true);
response.StatusCode.ShouldBe(HttpStatusCode.Forbidden);
}
[Fact]
public async Task Custom_Or_Policy_Should_Work_When_Permissions_Are_Granted()
{
_fakeRequiredService.Claims.AddRange(new[]
{
new Claim(AbpClaimTypes.UserId, AuthTestController.FakeUserId.ToString())
});
var result = await GetResponseAsStringAsync("/AuthTest/Custom_Or_PolicyTest");
result.ShouldBe("OK");
}
}
}

1
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/TestPermissionDefinitionProvider.cs

@ -9,6 +9,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Authorization
var testGroup = context.AddGroup("TestGroup");
testGroup.AddPermission("TestPermission1");
testGroup.AddPermission("TestPermission2");
}
}
}

7
framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs

@ -3,6 +3,7 @@ using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Net.Http.Headers;
using Shouldly;
using Volo.Abp.AspNetCore.TestBase;
@ -30,11 +31,15 @@ namespace Volo.Abp.AspNetCore
}
}
protected virtual async Task<HttpResponseMessage> GetResponseAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
protected virtual async Task<HttpResponseMessage> GetResponseAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK, bool xmlHttpRequest = false)
{
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, url))
{
requestMessage.Headers.Add("Accept-Language", CultureInfo.CurrentUICulture.Name);
if (xmlHttpRequest)
{
requestMessage.Headers.Add(HeaderNames.XRequestedWith, "XMLHttpRequest");
}
var response = await Client.SendAsync(requestMessage);
response.StatusCode.ShouldBe(expectedStatusCode);
return response;

Loading…
Cancel
Save