Browse Source

Merge pull request #26130 from abpframework/auto-merge-forward/rel-10.7-to-dev-30

Auto-merge forward rel-10.7 → dev
pull/25822/merge
Volosoft Agent 1 day ago
committed by GitHub
parent
commit
18dcd779ea
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 11
      modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RolePermissionManagementProvider.cs
  2. 18
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/PermissionManager_Tests.cs
  3. 40
      modules/permission-management/src/Volo.Abp.PermissionManagement.Application/Volo/Abp/PermissionManagement/PermissionAppService.cs
  4. 40
      modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor.MudBlazor/Components/PermissionManagementModal.razor.cs
  5. 41
      modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs
  6. 6
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManagementProvider.cs
  7. 30
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManager.cs
  8. 25
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionStore.cs
  9. 59
      modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs
  10. 46
      modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js
  11. 24
      modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs
  12. 1
      modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementTestModule.cs
  13. 63
      modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs
  14. 19
      modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionStore_Tests.cs
  15. 6
      modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs
  16. 53
      modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestGlobalPermissionStateChecker.cs

11
modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RolePermissionManagementProvider.cs

@ -65,9 +65,18 @@ public class RolePermissionManagementProvider : PermissionManagementProvider
return multiplePermissionValueProviderGrantInfo; return multiplePermissionValueProviderGrantInfo;
} }
var permissionGrantsByName = new Dictionary<string, PermissionGrant>();
foreach (var permissionGrant in permissionGrants)
{
if (!permissionGrantsByName.ContainsKey(permissionGrant.Name))
{
permissionGrantsByName[permissionGrant.Name] = permissionGrant;
}
}
foreach (var permissionName in names) foreach (var permissionName in names)
{ {
var permissionGrant = permissionGrants.FirstOrDefault(x => x.Name == permissionName); var permissionGrant = permissionGrantsByName.GetOrDefault(permissionName);
if (permissionGrant != null) if (permissionGrant != null)
{ {
multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(true, permissionGrant.ProviderKey); multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(true, permissionGrant.ProviderKey);

18
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/PermissionManager_Tests.cs

@ -87,6 +87,24 @@ public class PermissionManager_Tests : AbpIdentityDomainTestBase
ShouldNotHavePermission(grantInfos, TestPermissionNames.MyPermission2_ChildPermission1); ShouldNotHavePermission(grantInfos, TestPermissionNames.MyPermission2_ChildPermission1);
} }
[Fact]
public async Task Should_Report_A_Single_Role_Provider_When_Several_Roles_Grant_The_Permission()
{
var user = GetUser("john.nash");
var grantInfos = await _permissionManager.GetAllForUserAsync(user.Id);
var grantInfo = grantInfos.Single(x => x.Name == TestPermissionNames.MyPermission1);
grantInfo.IsGranted.ShouldBeTrue();
var roleProviders = grantInfo.Providers
.Where(x => x.Name == RolePermissionValueProvider.ProviderName)
.ToList();
roleProviders.Count.ShouldBe(1);
roleProviders.Single().Key.ShouldBeOneOf("moderator", "supporter");
}
private static void RoleShouldHavePermission(List<PermissionWithGrantedProviders> grantInfos, string roleName, string permissionName) private static void RoleShouldHavePermission(List<PermissionWithGrantedProviders> grantInfos, string roleName, string permissionName)
{ {
grantInfos.ShouldContain( grantInfos.ShouldContain(

40
modules/permission-management/src/Volo.Abp.PermissionManagement.Application/Volo/Abp/PermissionManagement/PermissionAppService.cs

@ -78,20 +78,29 @@ public class PermissionAppService : ApplicationService, IPermissionAppService
.Where(x => !x.Providers.Any() || x.Providers.Contains(providerName)) .Where(x => !x.Providers.Any() || x.Providers.Contains(providerName))
.Where(x => x.MultiTenancySide.HasFlag(multiTenancySide)); .Where(x => x.MultiTenancySide.HasFlag(multiTenancySide));
var neededCheckPermissions = new List<PermissionDefinition>(); var candidatePermissions = permissions.Distinct().ToArray();
foreach (var permission in permissions) var childrenByParent = candidatePermissions
.Where(x => x.Parent != null)
.GroupBy(x => x.Parent!)
.ToDictionary(x => x.Key, x => x.ToArray());
/* The state checkers of a permission only run when its parent is enabled,
so each tree level is checked in its own batch. */
var enabledPermissions = new HashSet<PermissionDefinition>();
var currentLevel = candidatePermissions.Where(x => x.Parent == null).ToArray();
while (currentLevel.Any())
{ {
if (permission.Parent != null && !neededCheckPermissions.Contains(permission.Parent)) var levelResult = await SimpleStateCheckerManager.IsEnabledAsync(currentLevel);
{ var enabledLevelPermissions = currentLevel.Where(x => levelResult[x]).ToArray();
continue; enabledPermissions.UnionWith(enabledLevelPermissions);
}
if (await SimpleStateCheckerManager.IsEnabledAsync(permission)) currentLevel = enabledLevelPermissions
{ .SelectMany(x => childrenByParent.GetOrDefault(x) ?? Array.Empty<PermissionDefinition>())
neededCheckPermissions.Add(permission); .ToArray();
}
} }
var neededCheckPermissions = candidatePermissions.Where(enabledPermissions.Contains).ToList();
if (!neededCheckPermissions.Any()) if (!neededCheckPermissions.Any())
{ {
continue; continue;
@ -106,11 +115,20 @@ public class PermissionAppService : ApplicationService, IPermissionAppService
providerName, providerName,
providerKey); providerKey);
var grantInfoByName = new Dictionary<string, PermissionWithGrantedProviders>();
foreach (var grantInfo in multipleGrantInfo.Result)
{
if (!grantInfoByName.ContainsKey(grantInfo.Name))
{
grantInfoByName[grantInfo.Name] = grantInfo;
}
}
foreach (var permissionGroup in permissionGroups) foreach (var permissionGroup in permissionGroups)
{ {
foreach (var permission in permissionGroup.Permissions) foreach (var permission in permissionGroup.Permissions)
{ {
var grantInfo = multipleGrantInfo.Result.FirstOrDefault(x => x.Name == permission.Name); var grantInfo = grantInfoByName.GetOrDefault(permission.Name);
if (grantInfo == null) if (grantInfo == null)
{ {
continue; continue;

40
modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor.MudBlazor/Components/PermissionManagementModal.razor.cs

@ -28,6 +28,7 @@ public partial class PermissionManagementModal
protected string? _entityDisplayName; protected string? _entityDisplayName;
protected List<PermissionGroupDto>? _allGroups; protected List<PermissionGroupDto>? _allGroups;
protected Dictionary<string, bool> _loadedPermissionValues = new Dictionary<string, bool>();
protected List<PermissionGroupDto>? _groups; protected List<PermissionGroupDto>? _groups;
protected int _activeTabIndex = 0; protected int _activeTabIndex = 0;
@ -60,6 +61,10 @@ public partial class PermissionManagementModal
_allGroups = result.Groups.OrderBy(x => x.DisplayName).ToList(); _allGroups = result.Groups.OrderBy(x => x.DisplayName).ToList();
_groups = _allGroups.ToList(); _groups = _allGroups.ToList();
_loadedPermissionValues = _allGroups
.SelectMany(x => x.Permissions)
.ToDictionary(x => x.Name, x => x.IsGranted);
NormalizePermissionGroup(); NormalizePermissionGroup();
GrantAll = _allGroups.SelectMany(x => x.Permissions).All(p => p.IsGranted); GrantAll = _allGroups.SelectMany(x => x.Permissions).All(p => p.IsGranted);
@ -134,15 +139,14 @@ public partial class PermissionManagementModal
return; return;
} }
var updateDto = new UpdatePermissionsDto var permissions = _allGroups.SelectMany(g => g.Permissions).ToList();
{
Permissions = _allGroups var changedPermissions = permissions
.SelectMany(g => g.Permissions) .Where(p => !_loadedPermissionValues.TryGetValue(p.Name, out var loadedValue) || loadedValue != p.IsGranted)
.Select(p => new UpdatePermissionDto { IsGranted = p.IsGranted, Name = p.Name }) .Select(p => new UpdatePermissionDto { IsGranted = p.IsGranted, Name = p.Name })
.ToArray() .ToArray();
};
if (!updateDto.Permissions.Any(x => x.IsGranted)) if (!permissions.Any(p => p.IsGranted))
{ {
var confirmed = await DialogService.ShowMessageBoxAsync( var confirmed = await DialogService.ShowMessageBoxAsync(
L["Warning"], L["Warning"],
@ -156,15 +160,21 @@ public partial class PermissionManagementModal
} }
} }
await PermissionAppService.UpdateAsync(_providerName!, _providerKey!, updateDto); if (changedPermissions.Any())
Guid? userId = null;
if (_providerName == UserPermissionValueProvider.ProviderName && Guid.TryParse(_providerKey, out var parsedUserId))
{ {
userId = parsedUserId; await PermissionAppService.UpdateAsync(_providerName!, _providerKey!, new UpdatePermissionsDto
} {
Permissions = changedPermissions
});
await CurrentApplicationConfigurationCacheResetService.ResetAsync(userId); Guid? userId = null;
if (_providerName == UserPermissionValueProvider.ProviderName && Guid.TryParse(_providerKey, out var parsedUserId))
{
userId = parsedUserId;
}
await CurrentApplicationConfigurationCacheResetService.ResetAsync(userId);
}
_isVisible = false; _isVisible = false;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);

41
modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs

@ -26,6 +26,8 @@ public partial class PermissionManagementModal
protected string _entityDisplayName; protected string _entityDisplayName;
protected List<PermissionGroupDto> _allGroups; protected List<PermissionGroupDto> _allGroups;
protected Dictionary<string, bool> _loadedPermissionValues = new Dictionary<string, bool>();
protected List<PermissionGroupDto> _groups; protected List<PermissionGroupDto> _groups;
protected string _selectedTabName; protected string _selectedTabName;
@ -58,6 +60,10 @@ public partial class PermissionManagementModal
_allGroups = result.Groups.OrderBy(x => x.DisplayName).ToList(); _allGroups = result.Groups.OrderBy(x => x.DisplayName).ToList();
_groups = _allGroups.ToList(); _groups = _allGroups.ToList();
_loadedPermissionValues = _allGroups
.SelectMany(x => x.Permissions)
.ToDictionary(x => x.Name, x => x.IsGranted);
NormalizePermissionGroup(); NormalizePermissionGroup();
GrantAll = _allGroups.SelectMany(x => x.Permissions).All(p => p.IsGranted); GrantAll = _allGroups.SelectMany(x => x.Permissions).All(p => p.IsGranted);
@ -121,15 +127,14 @@ public partial class PermissionManagementModal
try try
{ {
var updateDto = new UpdatePermissionsDto var permissions = _allGroups.SelectMany(g => g.Permissions).ToList();
{
Permissions = _allGroups
.SelectMany(g => g.Permissions)
.Select(p => new UpdatePermissionDto { IsGranted = p.IsGranted, Name = p.Name })
.ToArray()
};
if (!updateDto.Permissions.Any(x => x.IsGranted)) var changedPermissions = permissions
.Where(p => !_loadedPermissionValues.TryGetValue(p.Name, out var loadedValue) || loadedValue != p.IsGranted)
.Select(p => new UpdatePermissionDto { IsGranted = p.IsGranted, Name = p.Name })
.ToArray();
if (!permissions.Any(p => p.IsGranted))
{ {
if (!await Message.Confirm(L["SaveWithoutAnyPermissionsWarningMessage"].Value)) if (!await Message.Confirm(L["SaveWithoutAnyPermissionsWarningMessage"].Value))
{ {
@ -137,15 +142,21 @@ public partial class PermissionManagementModal
} }
} }
await PermissionAppService.UpdateAsync(_providerName, _providerKey, updateDto); if (changedPermissions.Any())
Guid? userId = null;
if (_providerName == UserPermissionValueProvider.ProviderName && Guid.TryParse(_providerKey, out var parsedUserId))
{ {
userId = parsedUserId; await PermissionAppService.UpdateAsync(_providerName, _providerKey, new UpdatePermissionsDto
} {
Permissions = changedPermissions
});
await CurrentApplicationConfigurationCacheResetService.ResetAsync(userId); Guid? userId = null;
if (_providerName == UserPermissionValueProvider.ProviderName && Guid.TryParse(_providerKey, out var parsedUserId))
{
userId = parsedUserId;
}
await CurrentApplicationConfigurationCacheResetService.ResetAsync(userId);
}
await InvokeAsync(_modal.Hide); await InvokeAsync(_modal.Hide);
await Notify.Success(L["SavedSuccessfully"]); await Notify.Success(L["SavedSuccessfully"]);

6
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManagementProvider.cs

@ -1,4 +1,5 @@
using System.Linq; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids; using Volo.Abp.Guids;
@ -44,10 +45,11 @@ public abstract class PermissionManagementProvider : IPermissionManagementProvid
} }
var permissionGrants = await PermissionGrantRepository.GetListAsync(names, providerName, providerKey); var permissionGrants = await PermissionGrantRepository.GetListAsync(names, providerName, providerKey);
var grantedPermissionNames = new HashSet<string>(permissionGrants.Select(x => x.Name));
foreach (var permissionName in names) foreach (var permissionName in names)
{ {
var isGrant = permissionGrants.Any(x => x.Name == permissionName); var isGrant = grantedPermissionNames.Contains(permissionName);
multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(isGrant, providerKey); multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(isGrant, providerKey);
} }

30
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManager.cs

@ -218,14 +218,22 @@ public class PermissionManager : IPermissionManager, ISingletonDependency
var permissionNames = permissions.Select(x => x.Name).ToArray(); var permissionNames = permissions.Select(x => x.Name).ToArray();
var multiplePermissionWithGrantedProviders = new MultiplePermissionWithGrantedProviders(permissionNames); var multiplePermissionWithGrantedProviders = new MultiplePermissionWithGrantedProviders(permissionNames);
var stateCheckPermissions = permissions
.Where(x => x.IsEnabled)
.Where(x => x.MultiTenancySide.HasFlag(CurrentTenant.GetMultiTenancySide()))
.Where(x => !x.Providers.Any() || x.Providers.Contains(providerName))
.Distinct()
.ToArray();
var stateCheckResult = stateCheckPermissions.Any()
? await SimpleStateCheckerManager.IsEnabledAsync(stateCheckPermissions)
: new SimpleStateCheckerResult<PermissionDefinition>();
var neededCheckPermissions = new List<PermissionDefinition>(); var neededCheckPermissions = new List<PermissionDefinition>();
foreach (var permission in permissions foreach (var permission in stateCheckPermissions)
.Where(x => x.IsEnabled)
.Where(x => x.MultiTenancySide.HasFlag(CurrentTenant.GetMultiTenancySide()))
.Where(x => !x.Providers.Any() || x.Providers.Contains(providerName)))
{ {
if (await SimpleStateCheckerManager.IsEnabledAsync(permission)) if (stateCheckResult[permission])
{ {
neededCheckPermissions.Add(permission); neededCheckPermissions.Add(permission);
} }
@ -236,6 +244,15 @@ public class PermissionManager : IPermissionManager, ISingletonDependency
return multiplePermissionWithGrantedProviders; return multiplePermissionWithGrantedProviders;
} }
var permissionsWithGrantedProvidersByName = new Dictionary<string, PermissionWithGrantedProviders>();
foreach (var permissionWithGrantedProviders in multiplePermissionWithGrantedProviders.Result)
{
if (!permissionsWithGrantedProvidersByName.ContainsKey(permissionWithGrantedProviders.Name))
{
permissionsWithGrantedProvidersByName[permissionWithGrantedProviders.Name] = permissionWithGrantedProviders;
}
}
foreach (var provider in ManagementProviders) foreach (var provider in ManagementProviders)
{ {
permissionNames = neededCheckPermissions.Select(x => x.Name).ToArray(); permissionNames = neededCheckPermissions.Select(x => x.Name).ToArray();
@ -245,8 +262,7 @@ public class PermissionManager : IPermissionManager, ISingletonDependency
{ {
if (providerResultDict.Value.IsGranted) if (providerResultDict.Value.IsGranted)
{ {
var permissionWithGrantedProvider = multiplePermissionWithGrantedProviders.Result var permissionWithGrantedProvider = permissionsWithGrantedProvidersByName[providerResultDict.Key];
.First(x => x.Name == providerResultDict.Key);
permissionWithGrantedProvider.IsGranted = true; permissionWithGrantedProvider.IsGranted = true;
permissionWithGrantedProvider.Providers.Add(new PermissionValueProviderInfo(provider.Name, providerResultDict.Value.ProviderKey)); permissionWithGrantedProvider.Providers.Add(new PermissionValueProviderInfo(provider.Name, providerResultDict.Value.ProviderKey));

25
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionStore.cs

@ -154,16 +154,29 @@ public class PermissionStore : IPermissionStore, ITransientDependency
var newCacheItems = await SetCacheItemsAsync(providerName, providerKey, notCacheKeys); var newCacheItems = await SetCacheItemsAsync(providerName, providerKey, notCacheKeys);
var result = new List<KeyValuePair<string, PermissionGrantCacheItem>>(); var newCacheItemsByKey = new Dictionary<string, PermissionGrantCacheItem>();
foreach (var key in cacheKeys) foreach (var newCacheItem in newCacheItems)
{ {
var item = newCacheItems.FirstOrDefault(x => x.Key == key); if (!newCacheItemsByKey.ContainsKey(newCacheItem.Key))
if (item.Value == null)
{ {
item = cacheItems.FirstOrDefault(x => x.Key == key); newCacheItemsByKey[newCacheItem.Key] = newCacheItem.Value;
} }
}
result.Add(new KeyValuePair<string, PermissionGrantCacheItem>(key, item.Value)); var cacheItemsByKey = new Dictionary<string, PermissionGrantCacheItem>();
foreach (var cacheItem in cacheItems)
{
if (!cacheItemsByKey.ContainsKey(cacheItem.Key))
{
cacheItemsByKey[cacheItem.Key] = cacheItem.Value;
}
}
var result = new List<KeyValuePair<string, PermissionGrantCacheItem>>();
foreach (var key in cacheKeys)
{
var item = newCacheItemsByKey.GetOrDefault(key) ?? cacheItemsByKey.GetOrDefault(key);
result.Add(new KeyValuePair<string, PermissionGrantCacheItem>(key, item));
} }
return result; return result;

59
modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml.cs

@ -32,6 +32,16 @@ public class PermissionManagementModal : AbpPageModel
[BindProperty] [BindProperty]
public List<PermissionGroupViewModel> Groups { get; set; } public List<PermissionGroupViewModel> Groups { get; set; }
/* A replaced view that still posts the whole Groups tree does not set this, so it keeps working. */
[BindProperty]
public bool OnlyChangedPermissions { get; set; }
[BindProperty]
public string GrantedPermissionNames { get; set; }
[BindProperty]
public string RevokedPermissionNames { get; set; }
public string EntityDisplayName { get; set; } public string EntityDisplayName { get; set; }
public bool SelectAllInThisTab { get; set; } public bool SelectAllInThisTab { get; set; }
@ -89,14 +99,21 @@ public class PermissionManagementModal : AbpPageModel
{ {
ValidateModel(); ValidateModel();
var updatePermissionDtos = Groups var updatePermissionDtos = OnlyChangedPermissions
.SelectMany(g => g.Permissions) ? GetChangedPermissions()
.Select(p => new UpdatePermissionDto : Groups
{ .SelectMany(g => g.Permissions)
Name = p.Name, .Select(p => new UpdatePermissionDto
IsGranted = p.IsGranted {
}) Name = p.Name,
.ToArray(); IsGranted = p.IsGranted
})
.ToArray();
if (updatePermissionDtos.IsNullOrEmpty())
{
return NoContent();
}
await PermissionAppService.UpdateAsync( await PermissionAppService.UpdateAsync(
ProviderName, ProviderName,
@ -118,6 +135,32 @@ public class PermissionManagementModal : AbpPageModel
return NoContent(); return NoContent();
} }
protected virtual UpdatePermissionDto[] GetChangedPermissions()
{
var permissions = new Dictionary<string, bool>();
foreach (var name in SplitPermissionNames(GrantedPermissionNames))
{
permissions[name] = true;
}
foreach (var name in SplitPermissionNames(RevokedPermissionNames))
{
permissions[name] = false;
}
return permissions
.Select(permission => new UpdatePermissionDto { Name = permission.Key, IsGranted = permission.Value })
.ToArray();
}
protected virtual string[] SplitPermissionNames(string names)
{
return names.IsNullOrWhiteSpace()
? Array.Empty<string>()
: names.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
}
public class PermissionGroupViewModel public class PermissionGroupViewModel
{ {
public string Name { get; set; } public string Name { get; set; }

46
modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js

@ -299,6 +299,48 @@ var abp = abp || {};
setSelectAllInAllTabs(); setSelectAllInAllTabs();
var $form = $("#PermissionManagementForm"); var $form = $("#PermissionManagementForm");
// defaultChecked holds the state the server rendered.
function submitChangedPermissions() {
// A replaced view without these attributes posts the whole tree instead.
var $permissions = $form.find('[data-permission-name]');
if (!$permissions.length) {
$form.submit();
return;
}
var granted = [];
var revoked = [];
$permissions.each(function () {
var $permission = $(this);
var checkbox = $permission.find('input[type="checkbox"]')[0];
if (!checkbox || checkbox.checked === checkbox.defaultChecked) {
return;
}
(checkbox.checked ? granted : revoked)
.push($permission.attr('data-permission-name'));
});
var $treeInputs = $form.find('fieldset').find('input').not(':disabled');
var $postedInputs = $()
.add($('<input type="hidden" name="OnlyChangedPermissions" value="true" />'))
.add($('<input type="hidden" name="GrantedPermissionNames" />').val(granted.join('\n')))
.add($('<input type="hidden" name="RevokedPermissionNames" />').val(revoked.join('\n')));
$treeInputs.prop('disabled', true);
$form.append($postedInputs);
try {
$form.submit();
} finally {
// The form is serialized synchronously, so the inputs can be restored right away.
$treeInputs.prop('disabled', false);
$postedInputs.remove();
}
}
var $submitButton = $form.find("button[type='submit']"); var $submitButton = $form.find("button[type='submit']");
if ($submitButton) { if ($submitButton) {
$submitButton.click(function (e) { $submitButton.click(function (e) {
@ -308,12 +350,12 @@ var abp = abp || {};
abp.message.confirm(l("SaveWithoutAnyPermissionsWarningMessage")) abp.message.confirm(l("SaveWithoutAnyPermissionsWarningMessage"))
.then(function (confirmed) { .then(function (confirmed) {
if (confirmed) { if (confirmed) {
$form.submit(); submitChangedPermissions();
} }
}); });
} }
else { else {
$form.submit(); submitChangedPermissions();
} }
}); });
} }

24
modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs

@ -17,6 +17,7 @@ public class PermissionAppService_Tests : AbpPermissionManagementApplicationTest
private readonly IPermissionGrantRepository _permissionGrantRepository; private readonly IPermissionGrantRepository _permissionGrantRepository;
private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor; private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;
private readonly FakePermissionChecker _fakePermissionChecker; private readonly FakePermissionChecker _fakePermissionChecker;
private readonly TestGlobalPermissionStateCheckerCounter _stateCheckerCounter;
public PermissionAppService_Tests() public PermissionAppService_Tests()
{ {
@ -24,6 +25,29 @@ public class PermissionAppService_Tests : AbpPermissionManagementApplicationTest
_permissionGrantRepository = GetRequiredService<IPermissionGrantRepository>(); _permissionGrantRepository = GetRequiredService<IPermissionGrantRepository>();
_currentPrincipalAccessor = GetRequiredService<ICurrentPrincipalAccessor>(); _currentPrincipalAccessor = GetRequiredService<ICurrentPrincipalAccessor>();
_fakePermissionChecker = GetRequiredService<FakePermissionChecker>(); _fakePermissionChecker = GetRequiredService<FakePermissionChecker>();
_stateCheckerCounter = GetRequiredService<TestGlobalPermissionStateCheckerCounter>();
}
[Fact]
public async Task Get_Should_Not_Check_The_State_Of_A_Permission_Whose_Parent_Is_Not_Enabled()
{
_stateCheckerCounter.Reset();
await _permissionAppService.GetAsync(UserPermissionValueProvider.ProviderName,
PermissionTestDataBuilder.User1Id.ToString());
_stateCheckerCounter.CheckedPermissionNames.ShouldContain("MyPermission5");
_stateCheckerCounter.CheckedPermissionNames.ShouldNotContain("MyPermission5.ChildPermission1");
using (_currentPrincipalAccessor.Change(new Claim(AbpClaimTypes.Role, "super-admin")))
{
_stateCheckerCounter.Reset();
await _permissionAppService.GetAsync(UserPermissionValueProvider.ProviderName,
PermissionTestDataBuilder.User1Id.ToString());
_stateCheckerCounter.CheckedPermissionNames.ShouldContain("MyPermission5.ChildPermission1");
}
} }
[Fact] [Fact]

1
modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementTestModule.cs

@ -22,6 +22,7 @@ public class AbpPermissionManagementTestModule : AbpModule
{ {
context.Services.AddEntityFrameworkInMemoryDatabase(); context.Services.AddEntityFrameworkInMemoryDatabase();
var databaseName = Guid.NewGuid().ToString(); var databaseName = Guid.NewGuid().ToString();
Configure<AbpDbContextOptions>(options => Configure<AbpDbContextOptions>(options =>

63
modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs

@ -1,10 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Claims;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Shouldly; using Shouldly;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Security.Claims;
using Xunit; using Xunit;
namespace Volo.Abp.PermissionManagement; namespace Volo.Abp.PermissionManagement;
@ -13,11 +15,15 @@ public class PermissionManager_Tests : PermissionTestBase
{ {
private readonly IPermissionManager _permissionManager; private readonly IPermissionManager _permissionManager;
private readonly IPermissionGrantRepository _permissionGrantRepository; private readonly IPermissionGrantRepository _permissionGrantRepository;
private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;
private readonly TestGlobalPermissionStateCheckerCounter _stateCheckerCounter;
public PermissionManager_Tests() public PermissionManager_Tests()
{ {
_permissionManager = GetRequiredService<IPermissionManager>(); _permissionManager = GetRequiredService<IPermissionManager>();
_permissionGrantRepository = GetRequiredService<IPermissionGrantRepository>(); _permissionGrantRepository = GetRequiredService<IPermissionGrantRepository>();
_currentPrincipalAccessor = GetRequiredService<ICurrentPrincipalAccessor>();
_stateCheckerCounter = GetRequiredService<TestGlobalPermissionStateCheckerCounter>();
} }
[Fact] [Fact]
@ -71,6 +77,63 @@ public class PermissionManager_Tests : PermissionTestBase
grantedProviders.Result.Last().Providers.ShouldContain(x => x.Key == "Test"); grantedProviders.Result.Last().Providers.ShouldContain(x => x.Key == "Test");
} }
[Fact]
public async Task Multiple_Get_Should_Apply_State_Checkers_Per_Permission()
{
await _permissionGrantRepository.InsertAsync(new PermissionGrant(
Guid.NewGuid(),
"MyPermission1",
"Test",
"Test")
);
await _permissionGrantRepository.InsertAsync(new PermissionGrant(
Guid.NewGuid(),
"MyPermission5",
"Test",
"Test")
);
var names = new[] { "MyPermission1", "MyPermission5" };
_stateCheckerCounter.Reset();
var grantedProviders = await _permissionManager.GetAsync(names, "Test", "Test");
_stateCheckerCounter.BatchCheckCount.ShouldBe(1);
_stateCheckerCounter.SingleCheckCount.ShouldBe(0);
grantedProviders.Result.Single(x => x.Name == "MyPermission1").IsGranted.ShouldBeTrue();
grantedProviders.Result.Single(x => x.Name == "MyPermission5").IsGranted.ShouldBeFalse();
using (_currentPrincipalAccessor.Change(new Claim(AbpClaimTypes.Role, "super-admin")))
{
grantedProviders = await _permissionManager.GetAsync(names, "Test", "Test");
grantedProviders.Result.Single(x => x.Name == "MyPermission1").IsGranted.ShouldBeTrue();
grantedProviders.Result.Single(x => x.Name == "MyPermission5").IsGranted.ShouldBeTrue();
}
}
[Fact]
public async Task Multiple_Get_Should_Return_Not_Granted_When_Every_Permission_Is_Filtered_Out()
{
await _permissionGrantRepository.InsertAsync(new PermissionGrant(
Guid.NewGuid(),
"MyDisabledPermission1",
"Test",
"Test")
);
_stateCheckerCounter.Reset();
var grantedProviders = await _permissionManager.GetAsync(
new[] { "MyDisabledPermission1", "MyPermission1NotExist" },
"Test",
"Test");
grantedProviders.Result.Count.ShouldBe(2);
grantedProviders.Result.ShouldAllBe(x => !x.IsGranted);
_stateCheckerCounter.BatchCheckCount.ShouldBe(0);
_stateCheckerCounter.SingleCheckCount.ShouldBe(0);
}
[Fact] [Fact]
public async Task Get_Should_Return_Not_Granted_When_Permission_Undefined() public async Task Get_Should_Return_Not_Granted_When_Permission_Undefined()
{ {

19
modules/permission-management/test/Volo.Abp.PermissionManagement.Domain.Tests/Volo/Abp/PermissionManagement/PermissionStore_Tests.cs

@ -39,4 +39,23 @@ public class PermissionStore_Tests : PermissionTestBase
result.Result.FirstOrDefault(x => x.Key == "MyPermission1").Value.ShouldBe(PermissionGrantResult.Granted); result.Result.FirstOrDefault(x => x.Key == "MyPermission1").Value.ShouldBe(PermissionGrantResult.Granted);
result.Result.FirstOrDefault(x => x.Key == "MyPermission1NotExist").Value.ShouldBe(PermissionGrantResult.Undefined); result.Result.FirstOrDefault(x => x.Key == "MyPermission1NotExist").Value.ShouldBe(PermissionGrantResult.Undefined);
} }
[Fact]
public async Task IsGranted_Multiple_Should_Combine_Cached_And_Uncached_Permissions()
{
(await _permissionStore.IsGrantedAsync("MyPermission1",
UserPermissionValueProvider.ProviderName,
PermissionTestDataBuilder.User1Id.ToString())).ShouldBeTrue();
var result = await _permissionStore.IsGrantedAsync(
new[] { "MyPermission3", "MyPermission1", "MyPermission1NotExist" },
UserPermissionValueProvider.ProviderName,
PermissionTestDataBuilder.User1Id.ToString());
result.Result.Count.ShouldBe(3);
result.Result.FirstOrDefault(x => x.Key == "MyPermission3").Value.ShouldBe(PermissionGrantResult.Granted);
result.Result.FirstOrDefault(x => x.Key == "MyPermission1").Value.ShouldBe(PermissionGrantResult.Granted);
result.Result.FirstOrDefault(x => x.Key == "MyPermission1NotExist").Value.ShouldBe(PermissionGrantResult.Undefined);
}
} }

6
modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs

@ -4,6 +4,7 @@ using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Autofac; using Volo.Abp.Autofac;
using Volo.Abp.DistributedLocking; using Volo.Abp.DistributedLocking;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.SimpleStateChecking;
using Volo.Abp.Threading; using Volo.Abp.Threading;
namespace Volo.Abp.PermissionManagement; namespace Volo.Abp.PermissionManagement;
@ -19,6 +20,11 @@ public class AbpPermissionManagementTestBaseModule : AbpModule
{ {
context.Services.Replace(ServiceDescriptor.Singleton<IAbpDistributedLock, NullAbpDistributedLock>()); context.Services.Replace(ServiceDescriptor.Singleton<IAbpDistributedLock, NullAbpDistributedLock>());
context.Services.Configure<AbpSimpleStateCheckerOptions<PermissionDefinition>>(options =>
{
options.GlobalStateCheckers.Add<TestGlobalPermissionStateChecker>();
});
context.Services.Configure<PermissionManagementOptions>(options => context.Services.Configure<PermissionManagementOptions>(options =>
{ {
options.ManagementProviders.Add<TestPermissionManagementProvider>(); options.ManagementProviders.Add<TestPermissionManagementProvider>();

53
modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestGlobalPermissionStateChecker.cs

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.SimpleStateChecking;
namespace Volo.Abp.PermissionManagement;
public class TestGlobalPermissionStateCheckerCounter : ISingletonDependency
{
public int BatchCheckCount { get; set; }
public int SingleCheckCount { get; set; }
public HashSet<string> CheckedPermissionNames { get; } = new HashSet<string>();
public void Reset()
{
BatchCheckCount = 0;
SingleCheckCount = 0;
CheckedPermissionNames.Clear();
}
}
public class TestGlobalPermissionStateChecker : ISimpleBatchStateChecker<PermissionDefinition>, ITransientDependency
{
public Task<bool> IsEnabledAsync(SimpleStateCheckerContext<PermissionDefinition> context)
{
var counter = GetCounter(context.ServiceProvider);
counter.SingleCheckCount++;
counter.CheckedPermissionNames.Add(context.State.Name);
return Task.FromResult(true);
}
public Task<SimpleStateCheckerResult<PermissionDefinition>> IsEnabledAsync(SimpleBatchStateCheckerContext<PermissionDefinition> context)
{
var counter = GetCounter(context.ServiceProvider);
counter.BatchCheckCount++;
foreach (var state in context.States)
{
counter.CheckedPermissionNames.Add(state.Name);
}
return Task.FromResult(new SimpleStateCheckerResult<PermissionDefinition>(context.States));
}
private static TestGlobalPermissionStateCheckerCounter GetCounter(IServiceProvider serviceProvider)
{
return serviceProvider.GetRequiredService<TestGlobalPermissionStateCheckerCounter>();
}
}
Loading…
Cancel
Save