diff --git a/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/IMultiplePermissionManager.cs b/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/IMultiplePermissionManager.cs
new file mode 100644
index 000000000..b2aa69800
--- /dev/null
+++ b/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/IMultiplePermissionManager.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.PermissionManagement;
+
+namespace LINGYUN.Abp.PermissionManagement;
+public interface IMultiplePermissionManager : IPermissionManager
+{
+ ///
+ /// 批量设置权限
+ ///
+ /// 权限提供者
+ /// 权限提供者Key
+ /// 权限集合
+ ///
+ Task SetManyAsync(string providerName, string providerKey, IEnumerable permissions);
+}
diff --git a/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/MultiplePermissionManager.cs b/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/MultiplePermissionManager.cs
new file mode 100644
index 000000000..f635d83fa
--- /dev/null
+++ b/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/MultiplePermissionManager.cs
@@ -0,0 +1,108 @@
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Caching;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Guids;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.SimpleStateChecking;
+
+
+namespace LINGYUN.Abp.PermissionManagement;
+
+[Dependency(ReplaceServices = true)]
+[ExposeServices(
+ typeof(IMultiplePermissionManager),
+ typeof(PermissionManager),
+ typeof(MultiplePermissionManager))]
+public class MultiplePermissionManager : PermissionManager, IMultiplePermissionManager, ISingletonDependency
+{
+ public MultiplePermissionManager(
+ IPermissionDefinitionManager permissionDefinitionManager,
+ ISimpleStateCheckerManager simpleStateCheckerManager,
+ IPermissionGrantRepository permissionGrantRepository,
+ IServiceProvider serviceProvider,
+ IGuidGenerator guidGenerator,
+ IOptions options,
+ ICurrentTenant currentTenant,
+ IDistributedCache cache)
+ : base(
+ permissionDefinitionManager,
+ simpleStateCheckerManager,
+ permissionGrantRepository,
+ serviceProvider,
+ guidGenerator,
+ options,
+ currentTenant,
+ cache)
+ {
+ }
+
+ public async virtual Task SetManyAsync(string providerName, string providerKey, IEnumerable permissions)
+ {
+ // 所有权限定义
+ var permissionDefinitions = await PermissionDefinitionManager.GetPermissionsAsync();
+
+ // 存在的权限集合
+ var existsPermissions = permissions
+ .Join(
+ permissionDefinitions,
+ p => p.Name,
+ pd => pd.Name,
+ (p, pd) =>
+ {
+ return new
+ {
+ State = p,
+ Definition = pd
+ };
+ });
+
+ // 检查权限状态
+ var existsPermissionDefinitions = existsPermissions.Select(p => p.Definition).ToArray();
+ var stateCheckResult = await SimpleStateCheckerManager.IsEnabledAsync(existsPermissionDefinitions);
+ var invalidCheckPermissions = stateCheckResult.Where(x => !x.Value).Select(x => x.Key.Name);
+ if (invalidCheckPermissions.Any())
+ {
+ throw new ApplicationException($"The permission named '{invalidCheckPermissions.JoinAsString(";")}' is disabled!");
+ }
+
+ // 检查权限提供者范围
+ var invalidProviderPermissions = existsPermissions.Where(x => x.Definition.Providers.Any() && !x.Definition.Providers.Contains(providerName)).Select(x => x.Definition.Name);
+ if (invalidProviderPermissions.Any())
+ {
+ throw new ApplicationException($"The permission named '{invalidProviderPermissions.JoinAsString(";")}' has not compatible with the provider named '{providerName}'");
+ }
+ // 检查权限多租户范围
+ var multiTenancySide = CurrentTenant.GetMultiTenancySide();
+ var invalidMultiTenancySidePermissions = existsPermissions.Where(x => !x.Definition.MultiTenancySide.HasFlag(multiTenancySide)).Select(x => x.Definition.Name);
+ if (invalidMultiTenancySidePermissions.Any())
+ {
+ throw new ApplicationException($"The permission named '{invalidMultiTenancySidePermissions.JoinAsString(";")}' has multitenancy side which is not compatible with the current multitenancy side '{multiTenancySide}'");
+ }
+
+ // 获取权限提供者
+ var provider = ManagementProviders.FirstOrDefault(m => m.Name == providerName) ??
+ throw new AbpException("Unknown permission management provider: " + providerName);
+
+ // 移除现有全部授权
+ var delPermissionGrants = await PermissionGrantRepository.GetListAsync(providerName, providerKey);
+ await PermissionGrantRepository.DeleteManyAsync(delPermissionGrants);
+
+ // 重新添加授权
+ var newPermissionGrants = existsPermissions
+ .Where(p => p.State.IsGranted)
+ .Select(p => new PermissionGrant(
+ GuidGenerator.Create(),
+ p.Definition.Name,
+ provider.Name,
+ providerKey,
+ CurrentTenant.Id));
+ await PermissionGrantRepository.InsertManyAsync(newPermissionGrants);
+ }
+}
diff --git a/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionAppService.cs b/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionAppService.cs
new file mode 100644
index 000000000..b934cdbb3
--- /dev/null
+++ b/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionAppService.cs
@@ -0,0 +1,44 @@
+using Microsoft.Extensions.Options;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.SimpleStateChecking;
+using VoloPermissionAppService = Volo.Abp.PermissionManagement.PermissionAppService;
+
+namespace LINGYUN.Abp.PermissionManagement;
+
+[Dependency(ReplaceServices = true)]
+[ExposeServices(
+ typeof(IPermissionAppService),
+ typeof(VoloPermissionAppService),
+ typeof(PermissionAppService))]
+public class PermissionAppService : VoloPermissionAppService
+{
+ public PermissionAppService(
+ IMultiplePermissionManager permissionManager,
+ IPermissionDefinitionManager permissionDefinitionManager,
+ IOptions options,
+ ISimpleStateCheckerManager simpleStateCheckerManager)
+ : base(permissionManager, permissionDefinitionManager, options, simpleStateCheckerManager)
+ {
+ }
+
+ public async override Task UpdateAsync(string providerName, string providerKey, UpdatePermissionsDto input)
+ {
+ if (PermissionManager is IMultiplePermissionManager permissionManager)
+ {
+ await CheckProviderPolicy(providerName);
+
+ await permissionManager.SetManyAsync(
+ providerName,
+ providerKey,
+ input.Permissions.Select(p => new PermissionChangeState(p.Name, p.IsGranted)));
+ }
+ else
+ {
+ await base.UpdateAsync(providerName, providerKey, input);
+ }
+ }
+}
diff --git a/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionChangeState.cs b/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionChangeState.cs
new file mode 100644
index 000000000..e5f0acfe5
--- /dev/null
+++ b/aspnet-core/modules/permissions-management/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionChangeState.cs
@@ -0,0 +1,11 @@
+namespace LINGYUN.Abp.PermissionManagement;
+public class PermissionChangeState
+{
+ public string Name { get; }
+ public bool IsGranted { get; }
+ public PermissionChangeState(string name, bool isGranted)
+ {
+ Name = name;
+ IsGranted = isGranted;
+ }
+}