-
Notifications
You must be signed in to change notification settings - Fork 422
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new filter attribute (AuthorizeMenuAttribute) that allows for ver…
…ification of access to a specific controller and action in the admin panel using menu configuration
- Loading branch information
support
committed
Oct 8, 2023
1 parent
cbec431
commit 080df38
Showing
9 changed files
with
440 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
222 changes: 222 additions & 0 deletions
222
src/Tests/Grand.Web.Common.Tests/AuthorizeMenuAttributeTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
using Grand.Business.Core.Interfaces.Common.Security; | ||
using Grand.Business.Core.Interfaces.System.Admin; | ||
using Grand.Domain.Admin; | ||
using Grand.Domain.Customers; | ||
using Grand.Domain.Data; | ||
using Grand.Infrastructure; | ||
using Grand.Infrastructure.Configuration; | ||
using Grand.SharedKernel.Extensions; | ||
using Grand.Web.Common.Filters; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.Abstractions; | ||
using Microsoft.AspNetCore.Mvc.Filters; | ||
using Microsoft.AspNetCore.Routing; | ||
using Moq; | ||
using NUnit.Framework; | ||
using Assert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; | ||
|
||
namespace Grand.Web.Common.Tests; | ||
|
||
[TestFixture] | ||
public class AuthorizeMenuAttributeTests | ||
{ | ||
private Mock<IPermissionService> _mockPermissionService; | ||
private Mock<IAdminSiteMapService> _mockAdminSiteMapService; | ||
private Mock<IWorkContext> _mockWorkContext; | ||
private SecurityConfig _securityConfig; | ||
private AuthorizationFilterContext _mockFilterContext; | ||
|
||
[SetUp] | ||
public void Setup() | ||
{ | ||
CommonPath.BaseDirectory = ""; | ||
DataSettingsManager.SaveSettings(new DataSettings() { ConnectionString = "connectionstring", DbProvider = DbProvider.MongoDB }).GetAwaiter().GetResult(); | ||
var settings = DataSettingsManager.LoadSettings(); | ||
_mockPermissionService = new Mock<IPermissionService>(); | ||
_mockAdminSiteMapService = new Mock<IAdminSiteMapService>(); | ||
_mockWorkContext = new Mock<IWorkContext>(); | ||
_securityConfig = new SecurityConfig(); | ||
var filters = new List<IFilterMetadata> | ||
{ | ||
new AuthorizeMenuAttribute(false) | ||
}; | ||
_mockFilterContext = new AuthorizationFilterContext(GetMockedAuthorizationFilterContext(), filters); | ||
} | ||
private AuthorizationFilterContext GetMockedAuthorizationFilterContext() | ||
{ | ||
|
||
// Mocking HttpContext | ||
var httpContextMock = new Mock<HttpContext>(); | ||
|
||
// Mocking RouteData | ||
var routeData = new RouteData(); | ||
routeData.Values.Add("controller", "SampleController"); | ||
routeData.Values.Add("action", "SampleAction"); | ||
|
||
// Mocking ActionDescriptor | ||
var actionDescriptorMock = new Mock<ActionDescriptor>(); | ||
//actionDescriptorMock.Object.Filters.Add(new AuthorizeMenuAttribute(false)); | ||
|
||
|
||
var actionContext = new ActionContext( | ||
httpContextMock.Object, | ||
routeData, | ||
actionDescriptorMock.Object | ||
); | ||
|
||
// Mocking filters for the context (can be empty if not needed for testing) | ||
var filters = new List<IFilterMetadata> | ||
{ | ||
new AuthorizeMenuAttribute(false) | ||
}; | ||
|
||
var authorizationFilterContext = new AuthorizationFilterContext(actionContext, filters); | ||
|
||
return authorizationFilterContext; | ||
} | ||
[Test] | ||
public async Task TestAuthorizeMenuAttribute_WithoutIgnoreFilter_DatabaseNotInstalled() | ||
{ | ||
// Arrange | ||
var attribute = new AuthorizeMenuAttribute(false); | ||
var filter = new AuthorizeMenuAttribute.AuthorizeMenuFilter( | ||
false, | ||
_mockPermissionService.Object, | ||
_mockAdminSiteMapService.Object, | ||
_mockWorkContext.Object, | ||
_securityConfig | ||
); | ||
|
||
// Act | ||
await filter.OnAuthorizationAsync(_mockFilterContext); | ||
|
||
// Assert | ||
// Assuming RedirectToRouteResult is not set when the database is not installed | ||
Assert.IsNull(_mockFilterContext.Result); | ||
} | ||
|
||
[Test] | ||
public async Task TestAuthorizeMenuAttribute_WithoutIgnoreFilter_AuthorizeAdminMenuDisabled() | ||
{ | ||
// Arrange | ||
_securityConfig.AuthorizeAdminMenu = false; | ||
var attribute = new AuthorizeMenuAttribute(false); | ||
var filter = new AuthorizeMenuAttribute.AuthorizeMenuFilter( | ||
false, | ||
_mockPermissionService.Object, | ||
_mockAdminSiteMapService.Object, | ||
_mockWorkContext.Object, | ||
_securityConfig | ||
); | ||
|
||
// Act | ||
await filter.OnAuthorizationAsync(_mockFilterContext); | ||
|
||
// Assert | ||
// Assuming RedirectToRouteResult is not set when AuthorizeAdminMenu is disabled | ||
Assert.IsNull(_mockFilterContext.Result); | ||
} | ||
|
||
[Test] | ||
public async Task TestAuthorizeMenuAttribute_WithValidSiteMap_AllPermissions() | ||
{ | ||
// Arrange | ||
var menuSiteMap = new AdminSiteMap { AllPermissions = true, PermissionNames = new List<string> { "Permission1" }, ActionName = "SampleAction", ControllerName = "SampleController" }; | ||
_mockAdminSiteMapService.Setup(s => s.GetSiteMap()).ReturnsAsync(new List<AdminSiteMap> { menuSiteMap }); | ||
_mockPermissionService.Setup(s => s.Authorize(It.IsAny<string>(), It.IsAny<Customer>())).ReturnsAsync(false); | ||
_securityConfig.AuthorizeAdminMenu = true; | ||
var attribute = new AuthorizeMenuAttribute(false); | ||
var filter = new AuthorizeMenuAttribute.AuthorizeMenuFilter( | ||
false, | ||
_mockPermissionService.Object, | ||
_mockAdminSiteMapService.Object, | ||
_mockWorkContext.Object, | ||
_securityConfig | ||
); | ||
|
||
// Act | ||
await filter.OnAuthorizationAsync(_mockFilterContext); | ||
|
||
// Assert | ||
Assert.IsInstanceOfType(_mockFilterContext.Result, typeof(RedirectToRouteResult)); | ||
} | ||
|
||
[Test] | ||
public async Task TestAuthorizeMenuAttribute_NoPermissionsInSiteMap() | ||
{ | ||
// Arrange | ||
var menuSiteMap = new AdminSiteMap { AllPermissions = true, PermissionNames = new List<string> { }, ActionName = "SampleAction", ControllerName = "SampleController" }; | ||
_mockAdminSiteMapService.Setup(s => s.GetSiteMap()).ReturnsAsync(new List<AdminSiteMap> { menuSiteMap }); | ||
_mockPermissionService.Setup(s => s.Authorize(It.IsAny<string>(), It.IsAny<Customer>())).ReturnsAsync(false); | ||
|
||
_securityConfig.AuthorizeAdminMenu = true; | ||
var attribute = new AuthorizeMenuAttribute(false); | ||
var filter = new AuthorizeMenuAttribute.AuthorizeMenuFilter( | ||
false, | ||
_mockPermissionService.Object, | ||
_mockAdminSiteMapService.Object, | ||
_mockWorkContext.Object, | ||
_securityConfig | ||
); | ||
|
||
// Act | ||
await filter.OnAuthorizationAsync(_mockFilterContext); | ||
|
||
// Assert | ||
// No permissions in the sitemap, so no redirect should occur | ||
Assert.IsNull(_mockFilterContext.Result); | ||
} | ||
|
||
[Test] | ||
public async Task TestAuthorizeMenuAttribute_WithoutAllPermissions_Authorized() | ||
{ | ||
// Arrange | ||
var menuSiteMap = new AdminSiteMap { AllPermissions = false, PermissionNames = new List<string> { "Permission1" }, ActionName = "SampleAction", ControllerName = "SampleController" }; | ||
_mockAdminSiteMapService.Setup(s => s.GetSiteMap()).ReturnsAsync(new List<AdminSiteMap> { menuSiteMap }); | ||
_mockPermissionService.Setup(s => s.Authorize(It.IsAny<string>(), It.IsAny<Customer>())).ReturnsAsync(true); | ||
_securityConfig.AuthorizeAdminMenu = true; | ||
|
||
var attribute = new AuthorizeMenuAttribute(false); | ||
var filter = new AuthorizeMenuAttribute.AuthorizeMenuFilter( | ||
false, | ||
_mockPermissionService.Object, | ||
_mockAdminSiteMapService.Object, | ||
_mockWorkContext.Object, | ||
_securityConfig | ||
); | ||
|
||
// Act | ||
await filter.OnAuthorizationAsync(_mockFilterContext); | ||
|
||
// Assert | ||
// Permission exists and user is authorized, so no redirect should occur | ||
Assert.IsNull(_mockFilterContext.Result); | ||
} | ||
|
||
[Test] | ||
public async Task TestAuthorizeMenuAttribute_WithoutAllPermissions_NotAuthorized() | ||
{ | ||
// Arrange | ||
var menuSiteMap = new AdminSiteMap { AllPermissions = false, PermissionNames = new List<string> { "Permission1" }, ActionName = "SampleAction", ControllerName = "SampleController" }; | ||
_mockAdminSiteMapService.Setup(s => s.GetSiteMap()).ReturnsAsync(new List<AdminSiteMap> { menuSiteMap }); | ||
_mockPermissionService.Setup(s => s.Authorize(It.IsAny<string>(), It.IsAny<Customer>())).ReturnsAsync(false); | ||
_securityConfig.AuthorizeAdminMenu = true; | ||
|
||
var attribute = new AuthorizeMenuAttribute(false); | ||
var filter = new AuthorizeMenuAttribute.AuthorizeMenuFilter( | ||
false, | ||
_mockPermissionService.Object, | ||
_mockAdminSiteMapService.Object, | ||
_mockWorkContext.Object, | ||
_securityConfig | ||
); | ||
|
||
// Act | ||
await filter.OnAuthorizationAsync(_mockFilterContext); | ||
|
||
// Assert | ||
// Permission exists but user is not authorized, so a redirect should occur | ||
Assert.IsInstanceOfType(_mockFilterContext.Result, typeof(RedirectToRouteResult)); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
src/Tests/Grand.Web.Common.Tests/Grand.Web.Common.Tests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<Import Project="..\..\Build\Grand.Common.props" /> | ||
<PropertyGroup> | ||
<IsPackable>false</IsPackable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" /> | ||
<PackageReference Include="Moq" Version="4.20.69" /> | ||
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" /> | ||
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" /> | ||
<PackageReference Include="coverlet.collector" Version="6.0.0"> | ||
<PrivateAssets>all</PrivateAssets> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
</PackageReference> | ||
<PackageReference Include="NUnit" Version="3.13.3" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\Core\Grand.SharedKernel\Grand.SharedKernel.csproj" /> | ||
<ProjectReference Include="..\..\Web\Grand.Web.Common\Grand.Web.Common.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Folder Include="Properties\" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Remove="Properties\launchSettings.json" /> | ||
<None Update="App_Data\index.txt"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.