diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs
index 1c41727f7b..c1e4896513 100644
--- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs
+++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs
@@ -71,6 +71,9 @@ namespace Volo.Abp.UI.Navigation
[NotNull]
public ApplicationMenuItemList Items { get; }
+ [CanBeNull]
+ public string RequiredPermissionName { get; }
+
///
/// Can be used to store a custom object related to this menu item. Optional.
///
@@ -95,7 +98,8 @@ namespace Volo.Abp.UI.Navigation
object customData = null,
string target = null,
string elementId = null,
- string cssClass = null)
+ string cssClass = null,
+ string requiredPermissionName = null)
{
Check.NotNullOrWhiteSpace(name, nameof(name));
Check.NotNullOrWhiteSpace(displayName, nameof(displayName));
@@ -109,6 +113,7 @@ namespace Volo.Abp.UI.Navigation
Target = target;
ElementId = elementId ?? GetDefaultElementId();
CssClass = cssClass;
+ RequiredPermissionName = requiredPermissionName;
Items = new ApplicationMenuItemList();
}
diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs
index 5c33866aa2..6fe6102622 100644
--- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs
+++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs
@@ -2,7 +2,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
+using Volo.Abp.Authorization.Permissions;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.UI.Navigation
@@ -13,7 +15,7 @@ namespace Volo.Abp.UI.Navigation
protected IHybridServiceScopeFactory ServiceScopeFactory { get; }
public MenuManager(
- IOptions options,
+ IOptions options,
IHybridServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
@@ -32,6 +34,8 @@ namespace Volo.Abp.UI.Navigation
{
await contributor.ConfigureMenuAsync(context);
}
+
+ await CheckPermissionsAsync(scope.ServiceProvider, menu);
}
NormalizeMenu(menu);
@@ -39,6 +43,52 @@ namespace Volo.Abp.UI.Navigation
return menu;
}
+ protected virtual async Task CheckPermissionsAsync(IServiceProvider serviceProvider, IHasMenuItems menuWithItems)
+ {
+ var requiredPermissionMenus = new List();
+ GetRequiredPermissionNameMenus(menuWithItems, requiredPermissionMenus);
+
+ if (requiredPermissionMenus.Any())
+ {
+ var permissionChecker = serviceProvider.GetRequiredService();
+ var grantResult = await permissionChecker.IsGrantedAsync(requiredPermissionMenus.Select(x => x.RequiredPermissionName).ToArray());
+
+ var toBeDeletedMenus = new List();
+ foreach (var menu in requiredPermissionMenus)
+ {
+ if (grantResult.Result[menu.RequiredPermissionName!] != PermissionGrantResult.Granted)
+ {
+ toBeDeletedMenus.Add(menu);
+ }
+ }
+
+ RemoveMenus(menuWithItems, toBeDeletedMenus);
+ }
+ }
+
+ protected virtual void GetRequiredPermissionNameMenus(IHasMenuItems menuWithItems, List output)
+ {
+ foreach (var menuItem in menuWithItems.Items)
+ {
+ if (!menuItem.RequiredPermissionName.IsNullOrWhiteSpace())
+ {
+ output.Add(menuItem);
+ }
+
+ GetRequiredPermissionNameMenus(menuItem, output);
+ }
+ }
+
+ protected virtual void RemoveMenus(IHasMenuItems menuWithItems, List toBeDeleted)
+ {
+ menuWithItems.Items.RemoveAll(toBeDeleted.Contains);
+
+ foreach (var menuItem in menuWithItems.Items)
+ {
+ RemoveMenus(menuItem, toBeDeleted);
+ }
+ }
+
protected virtual void NormalizeMenu(IHasMenuItems menuWithItems)
{
foreach (var menuItem in menuWithItems.Items)
@@ -49,4 +99,4 @@ namespace Volo.Abp.UI.Navigation
menuWithItems.Items.Normalize();
}
}
-}
\ No newline at end of file
+}
diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj
index ecfd73c615..a59bb11e0f 100644
--- a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj
+++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj
@@ -9,6 +9,8 @@
+
+
diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/AbpUiNavigationTestModule.cs b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/AbpUiNavigationTestModule.cs
new file mode 100644
index 0000000000..35b368cc1b
--- /dev/null
+++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/AbpUiNavigationTestModule.cs
@@ -0,0 +1,21 @@
+using Volo.Abp.Authorization;
+using Volo.Abp.Autofac;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.UI.Navigation
+{
+ [DependsOn(typeof(AbpUiNavigationModule))]
+ [DependsOn(typeof(AbpAuthorizationModule))]
+ [DependsOn(typeof(AbpAutofacModule))]
+ public class AbpUiNavigationTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.MenuContributors.Add(new MenuManager_Tests.TestMenuContributor1());
+ options.MenuContributors.Add(new MenuManager_Tests.TestMenuContributor2());
+ });
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/FakePermissionStore.cs b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/FakePermissionStore.cs
new file mode 100644
index 0000000000..ac074220f5
--- /dev/null
+++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/FakePermissionStore.cs
@@ -0,0 +1,28 @@
+using System.Threading.Tasks;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.UI.Navigation
+{
+ public class FakePermissionStore : IPermissionStore, ITransientDependency
+ {
+ public Task IsGrantedAsync(string name, string providerName, string providerKey)
+ {
+ var result = (name.Contains("Administration") || name.Contains("Dashboard")) && !name.Contains("SubMenu1");
+ return Task.FromResult(result);
+ }
+
+ public Task IsGrantedAsync(string[] names, string providerName, string providerKey)
+ {
+ var result = new MultiplePermissionGrantResult();
+ foreach (var name in names)
+ {
+ result.Result.Add(name, (name.Contains("Administration") || name.Contains("Dashboard")) && !name.Contains("SubMenu1")
+ ? PermissionGrantResult.Granted
+ : PermissionGrantResult.Prohibited);
+ }
+
+ return Task.FromResult(result);
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs
index 96db1622b5..c72082945b 100644
--- a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs
+++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs
@@ -1,13 +1,17 @@
-using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Security.Claims;
+using System.Threading;
+using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
+using NSubstitute;
using Shouldly;
-using Volo.Abp.Modularity;
+using Volo.Abp.Security.Claims;
using Volo.Abp.Testing;
using Xunit;
namespace Volo.Abp.UI.Navigation
{
- public class MenuManager_Tests : AbpIntegratedTest
+ public class MenuManager_Tests : AbpIntegratedTest
{
private readonly IMenuManager _menuManager;
@@ -16,6 +20,24 @@ namespace Volo.Abp.UI.Navigation
_menuManager = ServiceProvider.GetRequiredService();
}
+ protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
+ {
+ options.UseAutofac();
+ }
+
+ protected override void AfterAddApplication(IServiceCollection services)
+ {
+ var claims = new List() {
+ new Claim(AbpClaimTypes.UserId, "1fcf46b2-28c3-48d0-8bac-fa53268a2775"),
+ };
+
+ var identity = new ClaimsIdentity(claims);
+ var claimsPrincipal = new ClaimsPrincipal(identity);
+ var principalAccessor = Substitute.For();
+ principalAccessor.Principal.Returns(ci => claimsPrincipal);
+ Thread.CurrentPrincipal = claimsPrincipal;
+ }
+
[Fact]
public async Task Should_Get_Menu()
{
@@ -29,22 +51,8 @@ namespace Volo.Abp.UI.Navigation
mainMenu.Items[1].Items[0].Name.ShouldBe("Administration.UserManagement");
mainMenu.Items[1].Items[1].Name.ShouldBe("Administration.RoleManagement");
mainMenu.Items[1].Items[2].Name.ShouldBe("Administration.DashboardSettings");
- mainMenu.Items[1].Items[3].Name.ShouldBe("Administration.SubMenu1");
- mainMenu.Items[1].Items[3].Items[0].Name.ShouldBe("Administration.SubMenu1.1");
- mainMenu.Items[1].Items[3].Items[1].Name.ShouldBe("Administration.SubMenu1.2");
- }
-
- [DependsOn(typeof(AbpUiNavigationModule))]
- public class TestModule : AbpModule
- {
- public override void ConfigureServices(ServiceConfigurationContext context)
- {
- Configure(options =>
- {
- options.MenuContributors.Add(new TestMenuContributor1());
- options.MenuContributors.Add(new TestMenuContributor2());
- });
- }
+ mainMenu.Items[1].Items[3].Name.ShouldBe("Administration.SubMenu1"); //No need permission.
+ // Administration.SubMenu1.1 and Administration.SubMenu1.2 are removed because of don't have permissions.
}
/* Adds menu items:
@@ -65,8 +73,8 @@ namespace Volo.Abp.UI.Navigation
var administration = context.Menu.GetAdministration();
- administration.AddItem(new ApplicationMenuItem("Administration.UserManagement", "User Management", url: "/admin/users"));
- administration.AddItem(new ApplicationMenuItem("Administration.RoleManagement", "Role Management", url: "/admin/roles"));
+ administration.AddItem(new ApplicationMenuItem("Administration.UserManagement", "User Management", url: "/admin/users", requiredPermissionName: "Administration.UserManagement"));
+ administration.AddItem(new ApplicationMenuItem("Administration.RoleManagement", "Role Management", url: "/admin/roles", requiredPermissionName: "Administration.RoleManagement"));
return Task.CompletedTask;
}
@@ -86,16 +94,16 @@ namespace Volo.Abp.UI.Navigation
return Task.CompletedTask;
}
- context.Menu.Items.Insert(0, new ApplicationMenuItem("Dashboard", "Dashboard", url: "/dashboard"));
+ context.Menu.Items.Insert(0, new ApplicationMenuItem("Dashboard", "Dashboard", url: "/dashboard", requiredPermissionName: "Dashboard"));
var administration = context.Menu.GetAdministration();
- administration.AddItem(new ApplicationMenuItem("Administration.DashboardSettings", "Dashboard Settings", url: "/admin/settings/dashboard"));
+ administration.AddItem(new ApplicationMenuItem("Administration.DashboardSettings", "Dashboard Settings", url: "/admin/settings/dashboard", requiredPermissionName: "Administration.DashboardSettings"));
administration.AddItem(
- new ApplicationMenuItem("Administration.SubMenu1", "Sub menu 1")
- .AddItem(new ApplicationMenuItem("Administration.SubMenu1.1", "Sub menu 1.1", url: "/submenu1/submenu1_1"))
- .AddItem(new ApplicationMenuItem("Administration.SubMenu1.2", "Sub menu 1.2", url: "/submenu1/submenu1_2"))
+ new ApplicationMenuItem("Administration.SubMenu1", "Sub menu 1", url: "/submenu1")
+ .AddItem(new ApplicationMenuItem("Administration.SubMenu1.1", "Sub menu 1.1", url: "/submenu1/submenu1_1", requiredPermissionName: "Administration.SubMenu1.1"))
+ .AddItem(new ApplicationMenuItem("Administration.SubMenu1.2", "Sub menu 1.2", url: "/submenu1/submenu1_2", requiredPermissionName: "Administration.SubMenu1.2"))
);
return Task.CompletedTask;
diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/TestPermissionDefinitionProvider.cs b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/TestPermissionDefinitionProvider.cs
new file mode 100644
index 0000000000..c9afe5a1f0
--- /dev/null
+++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/TestPermissionDefinitionProvider.cs
@@ -0,0 +1,24 @@
+using Volo.Abp.Authorization.Permissions;
+
+namespace Volo.Abp.UI.Navigation
+{
+ public class TestPermissionDefinitionProvider : PermissionDefinitionProvider
+ {
+ public override void Define(IPermissionDefinitionContext context)
+ {
+ var group = context.AddGroup("TestGroup");
+
+ group.AddPermission("Dashboard");
+
+ group.AddPermission("Administration");
+ group.AddPermission("Administration.UserManagement");
+ group.AddPermission("Administration.RoleManagement");
+
+ group.AddPermission("Administration.DashboardSettings");
+
+ group.AddPermission("Administration.SubMenu1");
+ group.AddPermission("Administration.SubMenu1.1");
+ group.AddPermission("Administration.SubMenu1.2");
+ }
+ }
+}