Browse Source

Merge pull request #24184 from abpframework/resource-based-auth

Resource based authorization
pull/24424/head
Halil İbrahim Kalkan 2 months ago
committed by GitHub
parent
commit
ba486cb7b2
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/AbpPermissionOptions.cs
  2. 2
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/ICanAddChildPermission.cs
  3. 14
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs
  4. 7
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionManager.cs
  5. 1
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs
  6. 35
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs
  7. 83
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs
  8. 8
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IHasResourcePermissions.cs
  9. 33
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IResourcePermissionChecker.cs
  10. 83
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IResourcePermissionStore.cs
  11. 12
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IResourcePermissionValueProvider.cs
  12. 8
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IResourcePermissionValueProviderManager.cs
  13. 43
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/NullResourcePermissionStore.cs
  14. 34
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionCheckerExtensions.cs
  15. 21
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionGrantInfo.cs
  16. 75
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionStoreExtensions.cs
  17. 22
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueCheckContext.cs
  18. 20
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueProvider.cs
  19. 38
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValuesCheckContext.cs
  20. 21
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/ResourcePermissionRequirement.cs
  21. 13
      framework/src/Volo.Abp.Authorization/Microsoft/Extensions/DependencyInjection/KeyedObjectResourcePermissionExtenstions.cs
  22. 5
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs
  23. 8
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationPolicyProvider.cs
  24. 8
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IDynamicPermissionDefinitionStore.cs
  25. 8
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IStaticPermissionDefinitionStore.cs
  26. 19
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullDynamicPermissionDefinitionStore.cs
  27. 44
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionManager.cs
  28. 28
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/KeyedObjectResourcePermissionCheckerExtensions.cs
  29. 33
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/KeyedObjectResourcePermissionRequirementHandler.cs
  30. 49
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/KeyedObjectResourcePermissionStoreExtensions.cs
  31. 173
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionChecker.cs
  32. 65
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionPopulator.cs
  33. 43
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueProviderManager.cs
  34. 79
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/RoleResourcePermissionValueProvider.cs
  35. 46
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/UserResourcePermissionValueProvider.cs
  36. 32
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/StaticPermissionDefinitionStore.cs
  37. 6
      framework/src/Volo.Abp.Core/Volo/Abp/IKeyedObject.cs
  38. 39
      framework/src/Volo.Abp.Core/Volo/Abp/KeyedObjectHelper.cs
  39. 5
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/EntityDto.cs
  40. 5
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleEntityDto.cs
  41. 2
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/IEntityDto.cs
  42. 13
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs
  43. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntity.cs
  44. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json
  45. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json
  46. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json
  47. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json
  48. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json
  49. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
  50. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json
  51. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json
  52. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json
  53. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json
  54. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json
  55. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json
  56. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json
  57. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json
  58. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json
  59. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json
  60. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json
  61. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json
  62. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json
  63. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json
  64. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json
  65. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json
  66. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json
  67. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json
  68. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json
  69. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json
  70. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json
  71. 4
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs
  72. 11
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs
  73. 62
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionChecker_Tests.cs
  74. 60
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionPopulator_Test.cs
  75. 58
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionValueProviderManager_Tests.cs
  76. 26
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/StaticPermissionDefinitionStore_Tests.cs
  77. 4
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/FakePermissionStore.cs
  78. 48
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/AuthorizationTestResourcePermissionDefinitionProvider.cs
  79. 46
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/FakeResourcePermissionStore.cs
  80. 37
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/TestEntityResource.cs
  81. 43
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/TestResourcePermissionValueProvider1.cs
  82. 43
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/TestResourcePermissionValueProvider2.cs
  83. 31
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectWithKeyHelper_Tests.cs
  84. 5
      framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs
  85. 12
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Integration/IIdentityUserIntegrationService.cs
  86. 6
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/RoleLookupCountInputDto.cs
  87. 8
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/RoleLookupSearchInputDto.cs
  88. 54
      modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/Integration/IdentityUserIntegrationService.cs
  89. 12
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IUserRoleFinder.cs
  90. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json
  91. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json
  92. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json
  93. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json
  94. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json
  95. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json
  96. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json
  97. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json
  98. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json
  99. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json
  100. 4
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json

4
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/AbpPermissionOptions.cs

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Collections; using Volo.Abp.Collections;
namespace Volo.Abp.Authorization.Permissions; namespace Volo.Abp.Authorization.Permissions;
@ -9,6 +10,8 @@ public class AbpPermissionOptions
public ITypeList<IPermissionValueProvider> ValueProviders { get; } public ITypeList<IPermissionValueProvider> ValueProviders { get; }
public ITypeList<IResourcePermissionValueProvider> ResourceValueProviders { get; }
public HashSet<string> DeletedPermissions { get; } public HashSet<string> DeletedPermissions { get; }
public HashSet<string> DeletedPermissionGroups { get; } public HashSet<string> DeletedPermissionGroups { get; }
@ -17,6 +20,7 @@ public class AbpPermissionOptions
{ {
DefinitionProviders = new TypeList<IPermissionDefinitionProvider>(); DefinitionProviders = new TypeList<IPermissionDefinitionProvider>();
ValueProviders = new TypeList<IPermissionValueProvider>(); ValueProviders = new TypeList<IPermissionValueProvider>();
ResourceValueProviders = new TypeList<IResourcePermissionValueProvider>();
DeletedPermissions = new HashSet<string>(); DeletedPermissions = new HashSet<string>();
DeletedPermissionGroups = new HashSet<string>(); DeletedPermissionGroups = new HashSet<string>();

2
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/ICanAddChildPermission.cs

@ -11,4 +11,4 @@ public interface ICanAddChildPermission
ILocalizableString? displayName = null, ILocalizableString? displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both, MultiTenancySides multiTenancySide = MultiTenancySides.Both,
bool isEnabled = true); bool isEnabled = true);
} }

14
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs

@ -1,5 +1,7 @@
using System; using System;
using JetBrains.Annotations;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Authorization.Permissions; namespace Volo.Abp.Authorization.Permissions;
@ -46,4 +48,16 @@ public interface IPermissionDefinitionContext
/// <param name="name">Name of the permission</param> /// <param name="name">Name of the permission</param>
/// </summary> /// </summary>
PermissionDefinition? GetPermissionOrNull(string name); PermissionDefinition? GetPermissionOrNull(string name);
PermissionDefinition AddResourcePermission(
string name,
string resourceName,
string managementPermissionName,
ILocalizableString? displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both,
bool isEnabled = true);
PermissionDefinition? GetResourcePermissionOrNull([NotNull] string resourceName, [NotNull] string name);
void RemoveResourcePermission([NotNull] string resourceName, [NotNull] string name);
} }

7
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionManager.cs

@ -11,7 +11,14 @@ public interface IPermissionDefinitionManager
Task<PermissionDefinition?> GetOrNullAsync([NotNull] string name); Task<PermissionDefinition?> GetOrNullAsync([NotNull] string name);
[ItemNotNull]
Task<PermissionDefinition> GetResourcePermissionAsync([NotNull]string resourceName, [NotNull] string name);
Task<PermissionDefinition?> GetResourcePermissionOrNullAsync([NotNull]string resourceName, [NotNull] string name);
Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync(); Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync();
Task<IReadOnlyList<PermissionDefinition>> GetResourcePermissionsAsync();
Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync(); Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync();
} }

1
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs

@ -6,7 +6,6 @@ public interface IPermissionValueProvider
{ {
string Name { get; } string Name { get; }
//TODO: Rename to GetResult? (CheckAsync throws exception by naming convention)
Task<PermissionGrantResult> CheckAsync(PermissionValueCheckContext context); Task<PermissionGrantResult> CheckAsync(PermissionValueCheckContext context);
Task<MultiplePermissionGrantResult> CheckAsync(PermissionValuesCheckContext context); Task<MultiplePermissionGrantResult> CheckAsync(PermissionValuesCheckContext context);

35
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs

@ -7,7 +7,7 @@ using Volo.Abp.SimpleStateChecking;
namespace Volo.Abp.Authorization.Permissions; namespace Volo.Abp.Authorization.Permissions;
public class PermissionDefinition : public class PermissionDefinition :
IHasSimpleStateCheckers<PermissionDefinition>, IHasSimpleStateCheckers<PermissionDefinition>,
ICanAddChildPermission ICanAddChildPermission
{ {
@ -16,6 +16,16 @@ public class PermissionDefinition :
/// </summary> /// </summary>
public string Name { get; } public string Name { get; }
/// <summary>
/// Resource name of the permission.
/// </summary>
public string? ResourceName { get; set; }
/// <summary>
/// Management permission of the resource permission.
/// </summary>
public string? ManagementPermissionName { get; set; }
/// <summary> /// <summary>
/// Parent of this permission if one exists. /// Parent of this permission if one exists.
/// If set, this permission can be granted only if parent is granted. /// If set, this permission can be granted only if parent is granted.
@ -76,6 +86,19 @@ public class PermissionDefinition :
set => Properties[name] = value; set => Properties[name] = value;
} }
protected internal PermissionDefinition(
[NotNull] string name,
string resourceName,
string managementPermissionName,
ILocalizableString? displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both,
bool isEnabled = true)
: this(name, displayName, multiTenancySide, isEnabled)
{
ResourceName = Check.NotNull(resourceName, nameof(resourceName));
ManagementPermissionName = Check.NotNull(managementPermissionName, nameof(managementPermissionName));
}
protected internal PermissionDefinition( protected internal PermissionDefinition(
[NotNull] string name, [NotNull] string name,
ILocalizableString? displayName = null, ILocalizableString? displayName = null,
@ -99,6 +122,11 @@ public class PermissionDefinition :
MultiTenancySides multiTenancySide = MultiTenancySides.Both, MultiTenancySides multiTenancySide = MultiTenancySides.Both,
bool isEnabled = true) bool isEnabled = true)
{ {
if (ResourceName != null)
{
throw new AbpException($"Resource permission cannot have child permissions. Resource: {ResourceName}");
}
var child = new PermissionDefinition( var child = new PermissionDefinition(
name, name,
displayName, displayName,
@ -109,12 +137,12 @@ public class PermissionDefinition :
}; };
child[PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName] = this[PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName]; child[PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName] = this[PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName];
_children.Add(child); _children.Add(child);
return child; return child;
} }
PermissionDefinition ICanAddChildPermission.AddPermission( PermissionDefinition ICanAddChildPermission.AddPermission(
string name, string name,
ILocalizableString? displayName = null, ILocalizableString? displayName = null,
@ -124,7 +152,6 @@ public class PermissionDefinition :
return this.AddChild(name, displayName, multiTenancySide, isEnabled); return this.AddChild(name, displayName, multiTenancySide, isEnabled);
} }
/// <summary> /// <summary>
/// Sets a property in the <see cref="Properties"/> dictionary. /// Sets a property in the <see cref="Properties"/> dictionary.
/// This is a shortcut for nested calls on this object. /// This is a shortcut for nested calls on this object.

83
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs

@ -1,7 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Authorization.Permissions; namespace Volo.Abp.Authorization.Permissions;
@ -11,17 +13,20 @@ public class PermissionDefinitionContext : IPermissionDefinitionContext
public Dictionary<string, PermissionGroupDefinition> Groups { get; } public Dictionary<string, PermissionGroupDefinition> Groups { get; }
public List<PermissionDefinition> ResourcePermissions { get; }
internal IPermissionDefinitionProvider? CurrentProvider { get; set; } internal IPermissionDefinitionProvider? CurrentProvider { get; set; }
public static class KnownPropertyNames public static class KnownPropertyNames
{ {
public const string CurrentProviderName = "_CurrentProviderName"; public const string CurrentProviderName = "_CurrentProviderName";
} }
public PermissionDefinitionContext(IServiceProvider serviceProvider) public PermissionDefinitionContext(IServiceProvider serviceProvider)
{ {
ServiceProvider = serviceProvider; ServiceProvider = serviceProvider;
Groups = new Dictionary<string, PermissionGroupDefinition>(); Groups = new Dictionary<string, PermissionGroupDefinition>();
ResourcePermissions = new List<PermissionDefinition>();
} }
public virtual PermissionGroupDefinition AddGroup( public virtual PermissionGroupDefinition AddGroup(
@ -43,7 +48,7 @@ public class PermissionDefinitionContext : IPermissionDefinitionContext
} }
Groups[name] = group; Groups[name] = group;
return group; return group;
} }
@ -51,37 +56,23 @@ public class PermissionDefinitionContext : IPermissionDefinitionContext
public virtual PermissionGroupDefinition GetGroup([NotNull] string name) public virtual PermissionGroupDefinition GetGroup([NotNull] string name)
{ {
var group = GetGroupOrNull(name); var group = GetGroupOrNull(name);
return group ?? throw new AbpException($"Could not find a permission definition group with the given name: {name}");
if (group == null)
{
throw new AbpException($"Could not find a permission definition group with the given name: {name}");
}
return group;
} }
public virtual PermissionGroupDefinition? GetGroupOrNull([NotNull] string name) public virtual PermissionGroupDefinition? GetGroupOrNull([NotNull] string name)
{ {
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
return Groups.GetOrDefault(name);
if (!Groups.ContainsKey(name))
{
return null;
}
return Groups[name];
} }
public virtual void RemoveGroup(string name) public virtual void RemoveGroup(string name)
{ {
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
if (!Groups.ContainsKey(name)) if (!Groups.Remove(name))
{ {
throw new AbpException($"Not found permission group with name: {name}"); throw new AbpException($"Not found permission group with name: {name}");
} }
Groups.Remove(name);
} }
public virtual PermissionDefinition? GetPermissionOrNull([NotNull] string name) public virtual PermissionDefinition? GetPermissionOrNull([NotNull] string name)
@ -100,4 +91,58 @@ public class PermissionDefinitionContext : IPermissionDefinitionContext
return null; return null;
} }
public virtual PermissionDefinition AddResourcePermission(
string name,
string resourceName,
string managementPermissionName,
ILocalizableString? displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both,
bool isEnabled = true)
{
Check.NotNull(name, nameof(name));
Check.NotNull(resourceName, nameof(resourceName));
Check.NotNull(managementPermissionName, nameof(managementPermissionName));
if (ResourcePermissions.Any(x => x.ResourceName == resourceName && x.Name == name))
{
throw new AbpException($"There is already an existing resource permission with name: {name} for resource: {resourceName}");
}
var permission = new PermissionDefinition(
name,
resourceName,
managementPermissionName,
displayName,
multiTenancySide,
isEnabled)
{
[KnownPropertyNames.CurrentProviderName] = CurrentProvider?.GetType().FullName
};
ResourcePermissions.Add(permission);
return permission;
}
public virtual PermissionDefinition? GetResourcePermissionOrNull([NotNull] string resourceName, [NotNull] string name)
{
Check.NotNull(resourceName, nameof(resourceName));
Check.NotNull(name, nameof(name));
return ResourcePermissions.FirstOrDefault(p => p.ResourceName == resourceName && p.Name == name);
}
public virtual void RemoveResourcePermission([NotNull] string resourceName, [NotNull] string name)
{
Check.NotNull(resourceName, nameof(resourceName));
Check.NotNull(name, nameof(name));
var resourcePermission = GetResourcePermissionOrNull(resourceName, name);
if (resourcePermission == null)
{
throw new AbpException($"Not found resource permission with name: {name} for resource: {resourceName}");
}
ResourcePermissions.Remove(resourcePermission);
}
} }

8
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IHasResourcePermissions.cs

@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Volo.Abp.Authorization.Permissions.Resources;
public interface IHasResourcePermissions : IKeyedObject
{
Dictionary<string, bool> ResourcePermissions { get; }
}

33
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IResourcePermissionChecker.cs

@ -0,0 +1,33 @@
using System.Security.Claims;
using System.Threading.Tasks;
namespace Volo.Abp.Authorization.Permissions.Resources;
public interface IResourcePermissionChecker
{
Task<bool> IsGrantedAsync(
string name,
string resourceName,
string resourceKey
);
Task<bool> IsGrantedAsync(
ClaimsPrincipal? claimsPrincipal,
string name,
string resourceName,
string resourceKey
);
Task<MultiplePermissionGrantResult> IsGrantedAsync(
string[] names,
string resourceName,
string resourceKey
);
Task<MultiplePermissionGrantResult> IsGrantedAsync(
ClaimsPrincipal? claimsPrincipal,
string[] names,
string resourceName,
string resourceKey
);
}

83
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IResourcePermissionStore.cs

@ -0,0 +1,83 @@
using System.Threading.Tasks;
namespace Volo.Abp.Authorization.Permissions.Resources;
public interface IResourcePermissionStore
{
/// <summary>
/// Checks if the given permission is granted for the given resource.
/// </summary>
/// <param name="name">The name of the permission.</param>
/// <param name="resourceName">The name of the resource.</param>
/// <param name="resourceKey">Resource key</param>
/// <param name="providerName">The name of the provider.</param>
/// <param name="providerKey">The key of the provider.</param>
/// <returns>
/// True if the permission is granted.
/// </returns>
Task<bool> IsGrantedAsync(
string name,
string resourceName,
string resourceKey,
string providerName,
string providerKey
);
/// <summary>
/// Checks if the given permissions are granted for the given resource.
/// </summary>
/// <param name="names">The name of the permissions.</param>
/// <param name="resourceName">The name of the resource.</param>
/// <param name="resourceKey">Resource key</param>
/// <param name="providerName">The name of the provider.</param>
/// <param name="providerKey">The key of the provider.</param>
/// <returns>
/// A <see cref="MultiplePermissionGrantResult"/> object containing the grant results for each permission.
/// </returns>
Task<MultiplePermissionGrantResult> IsGrantedAsync(
string[] names,
string resourceName,
string resourceKey,
string providerName,
string providerKey
);
/// <summary>
/// Gets all permissions for the given resource.
/// </summary>
/// <param name="resourceName">Resource name</param>
/// <param name="resourceKey">Resource key</param>
/// <returns>
/// A <see cref="MultiplePermissionGrantResult"/> object containing the grant results for each permission.
/// </returns>
Task<MultiplePermissionGrantResult> GetPermissionsAsync(
string resourceName,
string resourceKey
);
/// <summary>
/// Gets all granted permissions for the given resource.
/// </summary>
/// <param name="resourceName">Resource name</param>
/// <param name="resourceKey">Resource key</param>
/// <returns>
/// An array of granted permission names.
/// </returns>
Task<string[]> GetGrantedPermissionsAsync(
string resourceName,
string resourceKey
);
/// <summary>
/// Retrieves the keys of resources for which the specified permission is granted.
/// </summary>
/// <param name="resourceName">The name of the resource.</param>
/// <param name="name">The name of the permission.</param>
/// <returns>
/// An array of resource keys where the specified permission is granted.
/// </returns>
Task<string[]> GetGrantedResourceKeysAsync(
string resourceName,
string name
);
}

12
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IResourcePermissionValueProvider.cs

@ -0,0 +1,12 @@
using System.Threading.Tasks;
namespace Volo.Abp.Authorization.Permissions.Resources;
public interface IResourcePermissionValueProvider
{
string Name { get; }
Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context);
Task<MultiplePermissionGrantResult> CheckAsync(ResourcePermissionValuesCheckContext context);
}

8
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IResourcePermissionValueProviderManager.cs

@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Volo.Abp.Authorization.Permissions.Resources;
public interface IResourcePermissionValueProviderManager
{
IReadOnlyList<IResourcePermissionValueProvider> ValueProviders { get; }
}

43
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/NullResourcePermissionStore.cs

@ -0,0 +1,43 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class NullResourcePermissionStore : IResourcePermissionStore, ISingletonDependency
{
public ILogger<NullResourcePermissionStore> Logger { get; set; }
public NullResourcePermissionStore()
{
Logger = NullLogger<NullResourcePermissionStore>.Instance;
}
public Task<bool> IsGrantedAsync(string name, string resourceName, string resourceKey, string providerName, string providerKey)
{
return TaskCache.FalseResult;
}
public Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names, string resourceName, string resourceKey, string providerName, string providerKey)
{
return Task.FromResult(new MultiplePermissionGrantResult(names, PermissionGrantResult.Prohibited));
}
public Task<MultiplePermissionGrantResult> GetPermissionsAsync(string resourceName, string resourceKey)
{
return Task.FromResult(new MultiplePermissionGrantResult());
}
public Task<string[]> GetGrantedPermissionsAsync(string resourceName, string resourceKey)
{
return Task.FromResult(Array.Empty<string>());
}
public Task<string[]> GetGrantedResourceKeysAsync(string resourceName, string name)
{
return Task.FromResult(Array.Empty<string>());
}
}

34
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionCheckerExtensions.cs

@ -0,0 +1,34 @@
using System.Threading.Tasks;
namespace Volo.Abp.Authorization.Permissions.Resources;
public static class ResourcePermissionCheckerExtensions
{
/// <summary>
/// Checks if a specific permission is granted for a resource with a given key.
/// </summary>
/// <typeparam name="TResource">The type of the resource.</typeparam>
/// <param name="resourcePermissionChecker">The resource permission checker instance.</param>
/// <param name="permissionName">The name of the permission to check.</param>
/// <param name="resource">The resource instance to check permission for.</param>
/// <param name="resourceKey">The unique key identifying the resource instance.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains a boolean value indicating whether the permission is granted.</returns>
public static Task<bool> IsGrantedAsync<TResource>(
this IResourcePermissionChecker resourcePermissionChecker,
string permissionName,
TResource resource,
object resourceKey
)
{
Check.NotNull(resourcePermissionChecker, nameof(resourcePermissionChecker));
Check.NotNullOrWhiteSpace(permissionName, nameof(permissionName));
Check.NotNull(resource, nameof(resource));
Check.NotNull(resourceKey, nameof(resourceKey));
return resourcePermissionChecker.IsGrantedAsync(
permissionName,
typeof(TResource).FullName!,
resourceKey.ToString()!
);
}
}

21
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionGrantInfo.cs

@ -0,0 +1,21 @@
namespace Volo.Abp.Authorization.Permissions.Resources;
public class ResourcePermissionGrantInfo : PermissionGrantInfo
{
public string ResourceName { get; }
public string ResourceKey { get; }
public ResourcePermissionGrantInfo(
string name,
bool isGranted,
string resourceName,
string resourceKey,
string? providerName = null,
string? providerKey = null)
: base(name, isGranted, providerName, providerKey)
{
ResourceName = resourceName;
ResourceKey = resourceKey;
}
}

75
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionStoreExtensions.cs

@ -0,0 +1,75 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Volo.Abp.Authorization.Permissions.Resources;
public static class ResourcePermissionStoreExtensions
{
/// <summary>
/// Retrieves the list of granted permissions for a specific resource with a given key.
/// </summary>
/// <typeparam name="TResource">The type of the resource.</typeparam>
/// <param name="resourcePermissionStore">The resource permission store instance.</param>
/// <param name="resource">The resource instance to retrieve permissions for.</param>
/// <param name="resourceKey">The unique key identifying the resource instance.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains an array of strings representing the granted permissions.</returns>
public static async Task<string[]> GetGrantedPermissionsAsync<TResource>(
this IResourcePermissionStore resourcePermissionStore,
TResource resource,
object resourceKey
)
{
return (await GetPermissionsAsync(resourcePermissionStore, resource, resourceKey)).Where(x => x.Value).Select(x => x.Key).ToArray();
}
/// <summary>
/// Retrieves a dictionary of permissions and their granted status for the specified entity.
/// </summary>
/// <typeparam name="TResource">The type of the resource.</typeparam>
/// <param name="resourcePermissionStore">The resource permission store instance.</param>
/// <param name="resource">The resource for which the permissions are being retrieved.</param>
/// <param name="resourceKey">The unique key identifying the resource instance.</param>
/// <returns>A dictionary where the keys are permission names and the values are booleans indicating whether the permission is granted.</returns>
public static async Task<IDictionary<string, bool>> GetPermissionsAsync<TResource>(
this IResourcePermissionStore resourcePermissionStore,
TResource resource,
object resourceKey
)
{
Check.NotNull(resourcePermissionStore, nameof(resourcePermissionStore));
Check.NotNull(resource, nameof(resource));
Check.NotNull(resourceKey, nameof(resourceKey));
var result = await resourcePermissionStore.GetPermissionsAsync(
typeof(TResource).FullName!,
resourceKey.ToString()!
);
return result.Result.ToDictionary(x => x.Key, x => x.Value == PermissionGrantResult.Granted);
}
/// <summary>
/// Retrieves the keys of the resources granted a specific permission.
/// </summary>
/// <typeparam name="TResource">The type of the resource.</typeparam>
/// <param name="resourcePermissionStore">The resource permission store instance.</param>
/// <param name="resource">The resource instance to check granted permissions for.</param>
/// <param name="permissionName">The name of the permission to check.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains an array of strings representing the granted resource keys.</returns>
public static Task<string[]> GetGrantedResourceKeysAsync<TResource>(
this IResourcePermissionStore resourcePermissionStore,
TResource resource,
string permissionName
)
{
Check.NotNull(resourcePermissionStore, nameof(resourcePermissionStore));
Check.NotNull(resource, nameof(resource));
Check.NotNullOrWhiteSpace(permissionName, nameof(permissionName));
return resourcePermissionStore.GetGrantedResourceKeysAsync(
typeof(TResource).FullName!,
permissionName
);
}
}

22
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueCheckContext.cs

@ -0,0 +1,22 @@
using System.Security.Claims;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class ResourcePermissionValueCheckContext : PermissionValueCheckContext
{
public string ResourceName { get; }
public string ResourceKey { get; }
public ResourcePermissionValueCheckContext(PermissionDefinition permission, string resourceName, string resourceKey)
: this(permission, null, resourceName, resourceKey)
{
}
public ResourcePermissionValueCheckContext(PermissionDefinition permission, ClaimsPrincipal? principal, string resourceName, string resourceKey)
: base(permission, principal)
{
ResourceName = resourceName;
ResourceKey = resourceKey;
}
}

20
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueProvider.cs

@ -0,0 +1,20 @@
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Authorization.Permissions.Resources;
public abstract class ResourcePermissionValueProvider : IResourcePermissionValueProvider, ITransientDependency
{
public abstract string Name { get; }
protected IResourcePermissionStore ResourcePermissionStore { get; }
protected ResourcePermissionValueProvider(IResourcePermissionStore resourcePermissionStore)
{
ResourcePermissionStore = resourcePermissionStore;
}
public abstract Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context);
public abstract Task<MultiplePermissionGrantResult> CheckAsync(ResourcePermissionValuesCheckContext context);
}

38
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValuesCheckContext.cs

@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Security.Claims;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class ResourcePermissionValuesCheckContext : PermissionValuesCheckContext
{
public string ResourceName { get; }
public string ResourceKey { get; }
public ResourcePermissionValuesCheckContext(PermissionDefinition permission,string resourceName, string resourceKey)
: this([permission], null, resourceName, resourceKey)
{
}
public ResourcePermissionValuesCheckContext(PermissionDefinition permission, ClaimsPrincipal? principal, string resourceName, string resourceKey)
: this([permission], principal, resourceName, resourceKey)
{
}
public ResourcePermissionValuesCheckContext(List<PermissionDefinition> permissions, string resourceName, string resourceKey)
: this(permissions, null, resourceName, resourceKey)
{
ResourceName = resourceName;
ResourceKey = resourceKey;
}
public ResourcePermissionValuesCheckContext(List<PermissionDefinition> permissions, ClaimsPrincipal? principal, string resourceName, string resourceKey)
: base(permissions, principal)
{
ResourceName = resourceName;
ResourceKey = resourceKey;
}
}

21
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/ResourcePermissionRequirement.cs

@ -0,0 +1,21 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authorization;
namespace Volo.Abp.Authorization;
public class ResourcePermissionRequirement : IAuthorizationRequirement
{
public string PermissionName { get; }
public ResourcePermissionRequirement([NotNull] string permissionName)
{
Check.NotNull(permissionName, nameof(permissionName));
PermissionName = permissionName;
}
public override string ToString()
{
return $"ResourcePermissionRequirement: {PermissionName}";
}
}

13
framework/src/Volo.Abp.Authorization/Microsoft/Extensions/DependencyInjection/KeyedObjectResourcePermissionExtenstions.cs

@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Authorization.Permissions.Resources;
namespace Microsoft.Extensions.DependencyInjection;
public static class KeyedObjectResourcePermissionExtenstions
{
public static IServiceCollection AddKeyedObjectResourcePermissionAuthorization(this IServiceCollection services)
{
services.AddSingleton<IAuthorizationHandler, KeyedObjectResourcePermissionRequirementHandler>();
return services;
}
}

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

@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Authorization.Localization; using Volo.Abp.Authorization.Localization;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling; using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -32,6 +33,7 @@ public class AbpAuthorizationModule : AbpModule
{ {
context.Services.AddAuthorizationCore(); context.Services.AddAuthorizationCore();
context.Services.AddKeyedObjectResourcePermissionAuthorization();
context.Services.AddSingleton<IAuthorizationHandler, PermissionRequirementHandler>(); context.Services.AddSingleton<IAuthorizationHandler, PermissionRequirementHandler>();
context.Services.AddSingleton<IAuthorizationHandler, PermissionsRequirementHandler>(); context.Services.AddSingleton<IAuthorizationHandler, PermissionsRequirementHandler>();
@ -42,6 +44,9 @@ public class AbpAuthorizationModule : AbpModule
options.ValueProviders.Add<UserPermissionValueProvider>(); options.ValueProviders.Add<UserPermissionValueProvider>();
options.ValueProviders.Add<RolePermissionValueProvider>(); options.ValueProviders.Add<RolePermissionValueProvider>();
options.ValueProviders.Add<ClientPermissionValueProvider>(); options.ValueProviders.Add<ClientPermissionValueProvider>();
options.ResourceValueProviders.Add<UserResourcePermissionValueProvider>();
options.ResourceValueProviders.Add<RoleResourcePermissionValueProvider>();
}); });
Configure<AbpVirtualFileSystemOptions>(options => Configure<AbpVirtualFileSystemOptions>(options =>

8
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationPolicyProvider.cs

@ -40,6 +40,14 @@ public class AbpAuthorizationPolicyProvider : DefaultAuthorizationPolicyProvider
return policyBuilder.Build(); return policyBuilder.Build();
} }
if ((await _permissionDefinitionManager.GetResourcePermissionsAsync()).Any(x => x.Name == policyName))
{
//TODO: Optimize & Cache!
var policyBuilder = new AuthorizationPolicyBuilder(Array.Empty<string>());
policyBuilder.Requirements.Add(new ResourcePermissionRequirement(policyName));
return policyBuilder.Build();
}
return null; return null;
} }

8
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IDynamicPermissionDefinitionStore.cs

@ -8,6 +8,10 @@ public interface IDynamicPermissionDefinitionStore
Task<PermissionDefinition?> GetOrNullAsync(string name); Task<PermissionDefinition?> GetOrNullAsync(string name);
Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync(); Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync();
Task<PermissionDefinition?> GetResourcePermissionOrNullAsync(string resourceName, string name);
Task<IReadOnlyList<PermissionDefinition>> GetResourcePermissionsAsync();
Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync(); Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync();
} }

8
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IStaticPermissionDefinitionStore.cs

@ -8,6 +8,10 @@ public interface IStaticPermissionDefinitionStore
Task<PermissionDefinition?> GetOrNullAsync(string name); Task<PermissionDefinition?> GetOrNullAsync(string name);
Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync(); Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync();
Task<PermissionDefinition?> GetResourcePermissionOrNullAsync(string resourceName, string name);
Task<IReadOnlyList<PermissionDefinition>> GetResourcePermissionsAsync();
Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync(); Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync();
} }

19
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullDynamicPermissionDefinitionStore.cs

@ -9,10 +9,15 @@ namespace Volo.Abp.Authorization.Permissions;
public class NullDynamicPermissionDefinitionStore : IDynamicPermissionDefinitionStore, ISingletonDependency public class NullDynamicPermissionDefinitionStore : IDynamicPermissionDefinitionStore, ISingletonDependency
{ {
private readonly static Task<PermissionDefinition?> CachedPermissionResult = Task.FromResult((PermissionDefinition?)null); private readonly static Task<PermissionDefinition?> CachedPermissionResult = Task.FromResult((PermissionDefinition?)null);
private readonly static Task<IReadOnlyList<PermissionDefinition>> CachedPermissionsResult = private readonly static Task<IReadOnlyList<PermissionDefinition>> CachedPermissionsResult =
Task.FromResult((IReadOnlyList<PermissionDefinition>)Array.Empty<PermissionDefinition>().ToImmutableList()); Task.FromResult((IReadOnlyList<PermissionDefinition>)Array.Empty<PermissionDefinition>().ToImmutableList());
private readonly static Task<PermissionDefinition?> CachedResourcePermissionResult = Task.FromResult((PermissionDefinition?)null);
private readonly static Task<IReadOnlyList<PermissionDefinition>> CachedResourcePermissionsResult =
Task.FromResult((IReadOnlyList<PermissionDefinition>)Array.Empty<PermissionDefinition>().ToImmutableList());
private readonly static Task<IReadOnlyList<PermissionGroupDefinition>> CachedGroupsResult = private readonly static Task<IReadOnlyList<PermissionGroupDefinition>> CachedGroupsResult =
Task.FromResult((IReadOnlyList<PermissionGroupDefinition>)Array.Empty<PermissionGroupDefinition>().ToImmutableList()); Task.FromResult((IReadOnlyList<PermissionGroupDefinition>)Array.Empty<PermissionGroupDefinition>().ToImmutableList());
@ -26,8 +31,18 @@ public class NullDynamicPermissionDefinitionStore : IDynamicPermissionDefinition
return CachedPermissionsResult; return CachedPermissionsResult;
} }
public Task<PermissionDefinition?> GetResourcePermissionOrNullAsync(string resourceName, string name)
{
return CachedResourcePermissionResult;
}
public Task<IReadOnlyList<PermissionDefinition>> GetResourcePermissionsAsync()
{
return CachedResourcePermissionsResult;
}
public Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() public Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync()
{ {
return CachedGroupsResult; return CachedGroupsResult;
} }
} }

44
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionManager.cs

@ -34,17 +34,36 @@ public class PermissionDefinitionManager : IPermissionDefinitionManager, ITransi
{ {
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
return await _staticStore.GetOrNullAsync(name) ?? return await _staticStore.GetOrNullAsync(name) ??
await _dynamicStore.GetOrNullAsync(name); await _dynamicStore.GetOrNullAsync(name);
} }
public virtual async Task<PermissionDefinition> GetResourcePermissionAsync(string resourceName, string name)
{
var permission = await GetResourcePermissionOrNullAsync(resourceName, name);
if (permission == null)
{
throw new AbpException($"Undefined resource permission: {name} for resource: {resourceName}");
}
return permission;
}
public virtual async Task<PermissionDefinition?> GetResourcePermissionOrNullAsync(string resourceName, string name)
{
Check.NotNull(name, nameof(name));
return await _staticStore.GetResourcePermissionOrNullAsync(resourceName, name) ??
await _dynamicStore.GetResourcePermissionOrNullAsync(resourceName, name);
}
public virtual async Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync() public virtual async Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync()
{ {
var staticPermissions = await _staticStore.GetPermissionsAsync(); var staticPermissions = await _staticStore.GetPermissionsAsync();
var staticPermissionNames = staticPermissions var staticPermissionNames = staticPermissions
.Select(p => p.Name) .Select(p => p.Name)
.ToImmutableHashSet(); .ToImmutableHashSet();
var dynamicPermissions = await _dynamicStore.GetPermissionsAsync(); var dynamicPermissions = await _dynamicStore.GetPermissionsAsync();
/* We prefer static permissions over dynamics */ /* We prefer static permissions over dynamics */
@ -53,13 +72,28 @@ public class PermissionDefinitionManager : IPermissionDefinitionManager, ITransi
).ToImmutableList(); ).ToImmutableList();
} }
public async Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() public virtual async Task<IReadOnlyList<PermissionDefinition>> GetResourcePermissionsAsync()
{
var staticResourcePermissions = await _staticStore.GetResourcePermissionsAsync();
var staticResourcePermissionNames = staticResourcePermissions
.Select(p => p.Name)
.ToImmutableHashSet();
var dynamicResourcePermissions = await _dynamicStore.GetResourcePermissionsAsync();
/* We prefer static permissions over dynamics */
return staticResourcePermissions.Concat(
dynamicResourcePermissions.Where(d => !staticResourcePermissionNames.Contains(d.Name))
).ToImmutableList();
}
public virtual async Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync()
{ {
var staticGroups = await _staticStore.GetGroupsAsync(); var staticGroups = await _staticStore.GetGroupsAsync();
var staticGroupNames = staticGroups var staticGroupNames = staticGroups
.Select(p => p.Name) .Select(p => p.Name)
.ToImmutableHashSet(); .ToImmutableHashSet();
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); var dynamicGroups = await _dynamicStore.GetGroupsAsync();
/* We prefer static groups over dynamics */ /* We prefer static groups over dynamics */
@ -67,4 +101,4 @@ public class PermissionDefinitionManager : IPermissionDefinitionManager, ITransi
dynamicGroups.Where(d => !staticGroupNames.Contains(d.Name)) dynamicGroups.Where(d => !staticGroupNames.Contains(d.Name))
).ToImmutableList(); ).ToImmutableList();
} }
} }

28
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/KeyedObjectResourcePermissionCheckerExtensions.cs

@ -0,0 +1,28 @@
using System.Threading.Tasks;
namespace Volo.Abp.Authorization.Permissions.Resources;
public static class KeyedObjectResourcePermissionCheckerExtensions
{
/// <summary>
/// Checks if the specified permission is granted for the given resource.
/// </summary>
/// <typeparam name="TResource">The type of the object.</typeparam>
/// <param name="resourcePermissionChecker">The resource permission checker instance.</param>
/// <param name="permissionName">The name of the permission to check.</param>
/// <param name="resource">The resource for which the permission is being checked.</param>
/// <returns>A task that represents the asynchronous operation. The task result is a boolean indicating whether the permission is granted.</returns>
public static Task<bool> IsGrantedAsync<TResource>(this IResourcePermissionChecker resourcePermissionChecker, string permissionName, TResource resource)
where TResource : class, IKeyedObject
{
Check.NotNull(resourcePermissionChecker, nameof(resourcePermissionChecker));
Check.NotNullOrWhiteSpace(permissionName, nameof(permissionName));
Check.NotNull(resource, nameof(resource));
return resourcePermissionChecker.IsGrantedAsync(
permissionName,
resource,
resource.GetObjectKey() ?? throw new AbpException("The resource doesn't have a key.")
);
}
}

33
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/KeyedObjectResourcePermissionRequirementHandler.cs

@ -0,0 +1,33 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class KeyedObjectResourcePermissionRequirementHandler : AuthorizationHandler<ResourcePermissionRequirement, IKeyedObject>
{
protected readonly IResourcePermissionChecker PermissionChecker;
public KeyedObjectResourcePermissionRequirementHandler(IResourcePermissionChecker permissionChecker)
{
PermissionChecker = permissionChecker;
}
protected override async Task HandleRequirementAsync(
AuthorizationHandlerContext context,
ResourcePermissionRequirement requirement,
IKeyedObject? resource)
{
if (resource == null)
{
return;
}
var resourceName = resource.GetType().FullName!;
var resourceKey = resource.GetObjectKey() ?? throw new AbpException("The resource doesn't have a key.");
if (await PermissionChecker.IsGrantedAsync(context.User, requirement.PermissionName, resourceName, resourceKey))
{
context.Succeed(requirement);
}
}
}

49
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/KeyedObjectResourcePermissionStoreExtensions.cs

@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Volo.Abp.Authorization.Permissions.Resources;
public static class KeyedObjectResourcePermissionStoreExtensions
{
/// <summary>
/// Retrieves an array of granted permissions for a specific entity.
/// </summary>
/// <typeparam name="TResource">The type of the resource.</typeparam>
/// <param name="resourcePermissionStore">The resource permission store instance.</param>
/// <param name="resource">The resource for which the permissions are being checked.</param>
/// <returns>An array of granted permission names as strings.</returns>
public static async Task<string[]> GetGrantedPermissionsAsync<TResource>(
this IResourcePermissionStore resourcePermissionStore,
TResource resource
)
where TResource : class, IKeyedObject
{
Check.NotNull(resourcePermissionStore, nameof(resourcePermissionStore));
Check.NotNull(resource, nameof(resource));
return (await GetPermissionsAsync(resourcePermissionStore, resource)).Where(x => x.Value).Select(x => x.Key).ToArray();
}
/// <summary>
/// Retrieves a dictionary of permissions and their granted status for the specified entity.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="resourcePermissionStore">The resource permission store instance.</param>
/// <param name="entity">The entity for which the permissions are being retrieved.</param>
/// <returns>A dictionary where the keys are permission names and the values are booleans indicating whether the permission is granted.</returns>
public static async Task<IDictionary<string, bool>> GetPermissionsAsync<TEntity>(
this IResourcePermissionStore resourcePermissionStore,
TEntity entity
)
where TEntity : class, IKeyedObject
{
Check.NotNull(resourcePermissionStore, nameof(resourcePermissionStore));
Check.NotNull(entity, nameof(entity));
return await resourcePermissionStore.GetPermissionsAsync(
entity,
entity.GetObjectKey() ?? throw new AbpException("The entity doesn't have a key.")
);
}
}

173
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionChecker.cs

@ -0,0 +1,173 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security.Claims;
using Volo.Abp.SimpleStateChecking;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class ResourcePermissionChecker : IResourcePermissionChecker, ITransientDependency
{
protected IPermissionDefinitionManager PermissionDefinitionManager { get; }
protected ICurrentPrincipalAccessor PrincipalAccessor { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IResourcePermissionValueProviderManager PermissionValueProviderManager { get; }
protected ISimpleStateCheckerManager<PermissionDefinition> StateCheckerManager { get; }
protected IPermissionChecker PermissionChecker { get; }
public ResourcePermissionChecker(
ICurrentPrincipalAccessor principalAccessor,
IPermissionDefinitionManager permissionDefinitionManager,
ICurrentTenant currentTenant,
IResourcePermissionValueProviderManager permissionValueProviderManager,
ISimpleStateCheckerManager<PermissionDefinition> stateCheckerManager,
IPermissionChecker permissionChecker)
{
PrincipalAccessor = principalAccessor;
PermissionDefinitionManager = permissionDefinitionManager;
CurrentTenant = currentTenant;
PermissionValueProviderManager = permissionValueProviderManager;
StateCheckerManager = stateCheckerManager;
PermissionChecker = permissionChecker;
}
public virtual async Task<bool> IsGrantedAsync(string name, string resourceName, string resourceKey)
{
return await IsGrantedAsync(PrincipalAccessor.Principal, name, resourceName, resourceKey);
}
public virtual async Task<bool> IsGrantedAsync(
ClaimsPrincipal? claimsPrincipal,
string name,
string resourceName,
string resourceKey)
{
Check.NotNull(name, nameof(name));
var permission = await PermissionDefinitionManager.GetResourcePermissionOrNullAsync(resourceName, name);
if (permission == null)
{
return false;
}
if (!permission.IsEnabled)
{
return false;
}
if (!await StateCheckerManager.IsEnabledAsync(permission))
{
return false;
}
var multiTenancySide = claimsPrincipal?.GetMultiTenancySide()
?? CurrentTenant.GetMultiTenancySide();
if (!permission.MultiTenancySide.HasFlag(multiTenancySide))
{
return false;
}
var isGranted = false;
var context = new ResourcePermissionValueCheckContext(permission, claimsPrincipal, resourceName, resourceKey);
foreach (var provider in PermissionValueProviderManager.ValueProviders)
{
if (context.Permission.Providers.Any() &&
!context.Permission.Providers.Contains(provider.Name))
{
continue;
}
var result = await provider.CheckAsync(context);
if (result == PermissionGrantResult.Granted)
{
isGranted = true;
}
else if (result == PermissionGrantResult.Prohibited)
{
return false;
}
}
return isGranted;
}
public async Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names, string resourceName, string resourceKey)
{
return await IsGrantedAsync(PrincipalAccessor.Principal, names, resourceName, resourceKey);
}
public async Task<MultiplePermissionGrantResult> IsGrantedAsync(ClaimsPrincipal? claimsPrincipal, string[] names, string resourceName, string resourceKey)
{
Check.NotNull(names, nameof(names));
var result = new MultiplePermissionGrantResult();
if (!names.Any())
{
return result;
}
var multiTenancySide = claimsPrincipal?.GetMultiTenancySide() ??
CurrentTenant.GetMultiTenancySide();
var permissionDefinitions = new List<PermissionDefinition>();
foreach (var name in names)
{
var permission = await PermissionDefinitionManager.GetResourcePermissionOrNullAsync(resourceName, name);
if (permission == null)
{
result.Result.Add(name, PermissionGrantResult.Prohibited);
continue;
}
result.Result.Add(name, PermissionGrantResult.Undefined);
if (permission.IsEnabled &&
await StateCheckerManager.IsEnabledAsync(permission) &&
permission.MultiTenancySide.HasFlag(multiTenancySide))
{
permissionDefinitions.Add(permission);
}
}
foreach (var provider in PermissionValueProviderManager.ValueProviders)
{
var permissions = permissionDefinitions
.Where(x => !x.Providers.Any() || x.Providers.Contains(provider.Name))
.ToList();
if (permissions.IsNullOrEmpty())
{
continue;
}
var context = new ResourcePermissionValuesCheckContext(
permissions,
claimsPrincipal,
resourceName,
resourceKey);
var multipleResult = await provider.CheckAsync(context);
foreach (var grantResult in multipleResult.Result.Where(grantResult =>
result.Result.ContainsKey(grantResult.Key) &&
result.Result[grantResult.Key] == PermissionGrantResult.Undefined &&
grantResult.Value != PermissionGrantResult.Undefined))
{
result.Result[grantResult.Key] = grantResult.Value;
permissionDefinitions.RemoveAll(x => x.Name == grantResult.Key);
}
if (result.AllGranted || result.AllProhibited)
{
break;
}
}
return result;
}
}

65
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionPopulator.cs

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class ResourcePermissionPopulator : ITransientDependency
{
protected IPermissionDefinitionManager PermissionDefinitionManager { get; }
protected IResourcePermissionChecker ResourcePermissionChecker { get; }
protected IResourcePermissionStore ResourcePermissionStore { get; }
protected IPermissionChecker PermissionChecker { get; }
public ResourcePermissionPopulator(
IPermissionDefinitionManager permissionDefinitionManager,
IResourcePermissionChecker resourcePermissionChecker,
IResourcePermissionStore resourcePermissionStore,
IPermissionChecker permissionChecker)
{
PermissionDefinitionManager = permissionDefinitionManager;
ResourcePermissionChecker = resourcePermissionChecker;
ResourcePermissionStore = resourcePermissionStore;
PermissionChecker = permissionChecker;
}
public virtual async Task PopulateAsync<TResource>(TResource resource, string resourceName)
where TResource : IHasResourcePermissions
{
await PopulateAsync([resource], resourceName);
}
public virtual async Task PopulateAsync<TResource>(List<TResource> resources, string resourceName)
where TResource : IHasResourcePermissions
{
Check.NotNull(resources, nameof(resources));
Check.NotNullOrWhiteSpace(resourceName, nameof(resourceName));
var resopurcePermissions = (await PermissionDefinitionManager.GetResourcePermissionsAsync())
.Where(x => x.ResourceName == resourceName)
.ToArray();
foreach (var resource in resources)
{
var resourceKey = resource.GetObjectKey();
if (resourceKey.IsNullOrEmpty())
{
throw new AbpException("Resource key can not be null or empty.");
}
var results = await ResourcePermissionChecker.IsGrantedAsync(resopurcePermissions.Select(x => x.Name).ToArray(), resourceName, resourceKey);
foreach (var resopurcePermission in resopurcePermissions)
{
if (resource.ResourcePermissions == null)
{
ObjectHelper.TrySetProperty(resource, x => x.ResourcePermissions, () => new Dictionary<string, bool>());
}
var hasPermission = results.Result.TryGetValue(resopurcePermission.Name, out var granted) && granted == PermissionGrantResult.Granted;
resource.ResourcePermissions![resopurcePermission.Name] = hasPermission;
}
}
}
}

43
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueProviderManager.cs

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class ResourcePermissionValueProviderManager : IResourcePermissionValueProviderManager, ISingletonDependency
{
public IReadOnlyList<IResourcePermissionValueProvider> ValueProviders => _lazyProviders.Value;
private readonly Lazy<List<IResourcePermissionValueProvider>> _lazyProviders;
protected AbpPermissionOptions Options { get; }
protected IServiceProvider ServiceProvider { get; }
public ResourcePermissionValueProviderManager(
IServiceProvider serviceProvider,
IOptions<AbpPermissionOptions> options)
{
Options = options.Value;
ServiceProvider = serviceProvider;
_lazyProviders = new Lazy<List<IResourcePermissionValueProvider>>(GetProviders, true);
}
protected virtual List<IResourcePermissionValueProvider> GetProviders()
{
var providers = Options
.ResourceValueProviders
.Select(type => (ServiceProvider.GetRequiredService(type) as IResourcePermissionValueProvider)!)
.ToList();
var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1);
if(multipleProviders != null)
{
throw new AbpException($"Duplicate resource permission value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}");
}
return providers;
}
}

79
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/RoleResourcePermissionValueProvider.cs

@ -0,0 +1,79 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class RoleResourcePermissionValueProvider : ResourcePermissionValueProvider
{
public const string ProviderName = "R";
public override string Name => ProviderName;
public RoleResourcePermissionValueProvider(IResourcePermissionStore resourcePermissionStore)
: base(resourcePermissionStore)
{
}
public override async Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context)
{
var roles = context.Principal?.FindAll(AbpClaimTypes.Role).Select(c => c.Value).ToArray();
if (roles == null || !roles.Any())
{
return PermissionGrantResult.Undefined;
}
foreach (var role in roles.Distinct())
{
if (await ResourcePermissionStore.IsGrantedAsync(context.Permission.Name, context.ResourceName, context.ResourceKey, Name, role))
{
return PermissionGrantResult.Granted;
}
}
return PermissionGrantResult.Undefined;
}
public override async Task<MultiplePermissionGrantResult> CheckAsync(ResourcePermissionValuesCheckContext context)
{
var permissionNames = context.Permissions.Select(x => x.Name).Distinct().ToList();
Check.NotNullOrEmpty(permissionNames, nameof(permissionNames));
var result = new MultiplePermissionGrantResult(permissionNames.ToArray());
var roles = context.Principal?.FindAll(AbpClaimTypes.Role).Select(c => c.Value).ToArray();
if (roles == null || !roles.Any())
{
return result;
}
foreach (var role in roles.Distinct())
{
var multipleResult = await ResourcePermissionStore.IsGrantedAsync(permissionNames.ToArray(), context.ResourceName, context.ResourceKey, Name, role);
foreach (var grantResult in multipleResult.Result.Where(grantResult =>
result.Result.ContainsKey(grantResult.Key) &&
result.Result[grantResult.Key] == PermissionGrantResult.Undefined &&
grantResult.Value != PermissionGrantResult.Undefined))
{
result.Result[grantResult.Key] = grantResult.Value;
permissionNames.RemoveAll(x => x == grantResult.Key);
}
if (result.AllGranted || result.AllProhibited)
{
break;
}
if (permissionNames.IsNullOrEmpty())
{
break;
}
}
return result;
}
}

46
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/UserResourcePermissionValueProvider.cs

@ -0,0 +1,46 @@
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class UserResourcePermissionValueProvider : ResourcePermissionValueProvider
{
public const string ProviderName = "U";
public override string Name => ProviderName;
public UserResourcePermissionValueProvider(IResourcePermissionStore resourcePermissionStore)
: base(resourcePermissionStore)
{
}
public override async Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context)
{
var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value;
if (userId == null)
{
return PermissionGrantResult.Undefined;
}
return await ResourcePermissionStore.IsGrantedAsync(context.Permission.Name, context.ResourceName, context.ResourceKey, Name, userId)
? PermissionGrantResult.Granted
: PermissionGrantResult.Undefined;
}
public override async Task<MultiplePermissionGrantResult> CheckAsync(ResourcePermissionValuesCheckContext context)
{
var permissionNames = context.Permissions.Select(x => x.Name).Distinct().ToArray();
Check.NotNullOrEmpty(permissionNames, nameof(permissionNames));
var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value;
if (userId == null)
{
return new MultiplePermissionGrantResult(permissionNames);
}
return await ResourcePermissionStore.IsGrantedAsync(permissionNames, context.ResourceName, context.ResourceKey, Name, userId);
}
}

32
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/StaticPermissionDefinitionStore.cs

@ -11,12 +11,14 @@ namespace Volo.Abp.Authorization.Permissions;
public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore, ISingletonDependency public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore, ISingletonDependency
{ {
protected IDictionary<string, PermissionGroupDefinition> PermissionGroupDefinitions => _lazyPermissionGroupDefinitions.Value; protected IDictionary<string, PermissionGroupDefinition> PermissionGroupDefinitions => _lazyPermissionGroupDefinitions.Value.Item1;
private readonly Lazy<Dictionary<string, PermissionGroupDefinition>> _lazyPermissionGroupDefinitions; private readonly Lazy<(Dictionary<string, PermissionGroupDefinition>, List<PermissionDefinition>)> _lazyPermissionGroupDefinitions;
protected IDictionary<string, PermissionDefinition> PermissionDefinitions => _lazyPermissionDefinitions.Value; protected IDictionary<string, PermissionDefinition> PermissionDefinitions => _lazyPermissionDefinitions.Value;
private readonly Lazy<Dictionary<string, PermissionDefinition>> _lazyPermissionDefinitions; private readonly Lazy<Dictionary<string, PermissionDefinition>> _lazyPermissionDefinitions;
protected IList<PermissionDefinition> ResourcePermissionDefinitions => _lazyPermissionGroupDefinitions.Value.Item2;
protected AbpPermissionOptions Options { get; } protected AbpPermissionOptions Options { get; }
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
@ -33,12 +35,12 @@ public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore,
isThreadSafe: true isThreadSafe: true
); );
_lazyPermissionGroupDefinitions = new Lazy<Dictionary<string, PermissionGroupDefinition>>( _lazyPermissionGroupDefinitions = new Lazy<(Dictionary<string, PermissionGroupDefinition>, List<PermissionDefinition>)>(
CreatePermissionGroupDefinitions, CreatePermissionGroupDefinitions,
isThreadSafe: true isThreadSafe: true
); );
} }
protected virtual Dictionary<string, PermissionDefinition> CreatePermissionDefinitions() protected virtual Dictionary<string, PermissionDefinition> CreatePermissionDefinitions()
{ {
var permissions = new Dictionary<string, PermissionDefinition>(); var permissions = new Dictionary<string, PermissionDefinition>();
@ -71,7 +73,7 @@ public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore,
} }
} }
protected virtual Dictionary<string, PermissionGroupDefinition> CreatePermissionGroupDefinitions() protected virtual (Dictionary<string, PermissionGroupDefinition>, List<PermissionDefinition>) CreatePermissionGroupDefinitions()
{ {
using (var scope = _serviceProvider.CreateScope()) using (var scope = _serviceProvider.CreateScope())
{ {
@ -99,10 +101,10 @@ public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore,
context.CurrentProvider = provider; context.CurrentProvider = provider;
provider.PostDefine(context); provider.PostDefine(context);
} }
context.CurrentProvider = null; context.CurrentProvider = null;
return context.Groups; return (context.Groups, context.ResourcePermissions);
} }
} }
@ -110,7 +112,7 @@ public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore,
{ {
return Task.FromResult(PermissionDefinitions.GetOrDefault(name)); return Task.FromResult(PermissionDefinitions.GetOrDefault(name));
} }
public virtual Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync() public virtual Task<IReadOnlyList<PermissionDefinition>> GetPermissionsAsync()
{ {
return Task.FromResult<IReadOnlyList<PermissionDefinition>>( return Task.FromResult<IReadOnlyList<PermissionDefinition>>(
@ -118,10 +120,22 @@ public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore,
); );
} }
public virtual Task<PermissionDefinition?> GetResourcePermissionOrNullAsync(string resourceName, string name)
{
return Task.FromResult<PermissionDefinition?>(ResourcePermissionDefinitions.FirstOrDefault(p => p.ResourceName == resourceName && p.Name == name));
}
public virtual Task<IReadOnlyList<PermissionDefinition>> GetResourcePermissionsAsync()
{
return Task.FromResult<IReadOnlyList<PermissionDefinition>>(
ResourcePermissionDefinitions.ToImmutableList()
);
}
public Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() public Task<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync()
{ {
return Task.FromResult<IReadOnlyList<PermissionGroupDefinition>>( return Task.FromResult<IReadOnlyList<PermissionGroupDefinition>>(
PermissionGroupDefinitions.Values.ToImmutableList() PermissionGroupDefinitions.Values.ToImmutableList()
); );
} }
} }

6
framework/src/Volo.Abp.Core/Volo/Abp/IKeyedObject.cs

@ -0,0 +1,6 @@
namespace Volo.Abp;
public interface IKeyedObject
{
string? GetObjectKey();
}

39
framework/src/Volo.Abp.Core/Volo/Abp/KeyedObjectHelper.cs

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp;
public static class KeyedObjectHelper
{
public static string EncodeCompositeKey(params object?[] keys)
{
var raw = keys.JoinAsString("||");
var bytes = Encoding.UTF8.GetBytes(raw);
var base64 = Convert.ToBase64String(bytes);
var base64Url = base64
.Replace("+", "-")
.Replace("/", "_")
.TrimEnd('=');
return base64Url;
}
public static string DecodeCompositeKey(string encoded)
{
var base64 = encoded
.Replace("-", "+")
.Replace("_", "/");
switch (encoded.Length % 4)
{
case 2: base64 += "=="; break;
case 3: base64 += "="; break;
}
var bytes = Convert.FromBase64String(base64);
var raw = Encoding.UTF8.GetString(bytes);
return raw;
}
}

5
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/EntityDto.cs

@ -23,4 +23,9 @@ public abstract class EntityDto<TKey> : EntityDto, IEntityDto<TKey>
{ {
return $"[DTO: {GetType().Name}] Id = {Id}"; return $"[DTO: {GetType().Name}] Id = {Id}";
} }
public virtual string? GetObjectKey()
{
return Id?.ToString();
}
} }

5
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ExtensibleEntityDto.cs

@ -27,6 +27,11 @@ public abstract class ExtensibleEntityDto<TKey> : ExtensibleObject, IEntityDto<T
{ {
return $"[DTO: {GetType().Name}] Id = {Id}"; return $"[DTO: {GetType().Name}] Id = {Id}";
} }
public virtual string? GetObjectKey()
{
return Id?.ToString();
}
} }
[Serializable] [Serializable]

2
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/IEntityDto.cs

@ -5,7 +5,7 @@ public interface IEntityDto
} }
public interface IEntityDto<TKey> : IEntityDto public interface IEntityDto<TKey> : IEntityDto, IKeyedObject
{ {
TKey Id { get; set; } TKey Id { get; set; }
} }

13
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs

@ -18,6 +18,17 @@ public abstract class Entity : IEntity
return $"[ENTITY: {GetType().Name}] Keys = {GetKeys().JoinAsString(", ")}"; return $"[ENTITY: {GetType().Name}] Keys = {GetKeys().JoinAsString(", ")}";
} }
public virtual string? GetObjectKey()
{
var keys = GetKeys();
return keys.Length switch
{
0 => null,
1 when keys[0] != null => keys[0]?.ToString(),
_ => KeyedObjectHelper.EncodeCompositeKey(keys)
};
}
public abstract object?[] GetKeys(); public abstract object?[] GetKeys();
public bool EntityEquals(IEntity other) public bool EntityEquals(IEntity other)
@ -45,7 +56,7 @@ public abstract class Entity<TKey> : Entity, IEntity<TKey>
public override object?[] GetKeys() public override object?[] GetKeys()
{ {
return new object?[] { Id }; return [Id];
} }
/// <inheritdoc/> /// <inheritdoc/>

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntity.cs

@ -4,7 +4,7 @@
/// Defines an entity. It's primary key may not be "Id" or it may have a composite primary key. /// Defines an entity. It's primary key may not be "Id" or it may have a composite primary key.
/// Use <see cref="IEntity{TKey}"/> where possible for better integration to repositories and other structures in the framework. /// Use <see cref="IEntity{TKey}"/> where possible for better integration to repositories and other structures in the framework.
/// </summary> /// </summary>
public interface IEntity public interface IEntity : IKeyedObject
{ {
/// <summary> /// <summary>
/// Returns an array of ordered keys for this entity. /// Returns an array of ordered keys for this entity.

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json

@ -61,6 +61,7 @@
"ProfilePicture": "الصوره الشخصيه", "ProfilePicture": "الصوره الشخصيه",
"Theme": "سمة", "Theme": "سمة",
"NotAssigned": "غيرمعتمد", "NotAssigned": "غيرمعتمد",
"EntityActionsDisabledTooltip": "ليس لديك إذن لتنفيذ أي إجراء." "EntityActionsDisabledTooltip": "ليس لديك إذن لتنفيذ أي إجراء.",
"ResourcePermissions": "أذونات"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profilový obrázek", "ProfilePicture": "Profilový obrázek",
"Theme": "Téma", "Theme": "Téma",
"NotAssigned": "Nepřiřazena", "NotAssigned": "Nepřiřazena",
"EntityActionsDisabledTooltip": "Nemáte oprávnění provést žádnou akci." "EntityActionsDisabledTooltip": "Nemáte oprávnění provést žádnou akci.",
"ResourcePermissions": "Oprávnění"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profilbild", "ProfilePicture": "Profilbild",
"Theme": "Thema", "Theme": "Thema",
"NotAssigned": "Nicht zugeordnet", "NotAssigned": "Nicht zugeordnet",
"EntityActionsDisabledTooltip": "Sie haben keine Berechtigung, Aktionen auszuführen." "EntityActionsDisabledTooltip": "Sie haben keine Berechtigung, Aktionen auszuführen.",
"ResourcePermissions": "Berechtigungen"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json

@ -55,6 +55,7 @@
"OthersGroup": "άλλος", "OthersGroup": "άλλος",
"Today": "Σήμερα", "Today": "Σήμερα",
"Apply": "Ισχύουν", "Apply": "Ισχύουν",
"EntityActionsDisabledTooltip": "Δεν έχετε δικαίωμα να εκτελέσετε καμία ενέργεια." "EntityActionsDisabledTooltip": "Δεν έχετε δικαίωμα να εκτελέσετε καμία ενέργεια.",
"ResourcePermissions": "Δικαιώματα",
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json

@ -56,6 +56,7 @@
"NotAssigned": "Not Assigned", "NotAssigned": "Not Assigned",
"Today": "Today", "Today": "Today",
"Apply": "Apply", "Apply": "Apply",
"EntityActionsDisabledTooltip": "You do not have permission to perform any action." "EntityActionsDisabledTooltip": "You do not have permission to perform any action.",
"ResourcePermissions": "Permissions"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profile picture", "ProfilePicture": "Profile picture",
"Theme": "Theme", "Theme": "Theme",
"NotAssigned": "Not Assigned", "NotAssigned": "Not Assigned",
"EntityActionsDisabledTooltip": "You do not have permission to perform any action." "EntityActionsDisabledTooltip": "You do not have permission to perform any action.",
"ResourcePermissions": "Permissions"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json

@ -61,6 +61,7 @@
"ProfilePicture": "Foto de perfil", "ProfilePicture": "Foto de perfil",
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "No asignado", "NotAssigned": "No asignado",
"EntityActionsDisabledTooltip": "No tienes permisos para realizar ninguna acción." "EntityActionsDisabledTooltip": "No tienes permisos para realizar ninguna acción.",
"ResourcePermissions": "Permisos"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json

@ -55,6 +55,7 @@
"OthersGroup": "دیگر", "OthersGroup": "دیگر",
"Today": "امروز", "Today": "امروز",
"Apply": "درخواست دادن", "Apply": "درخواست دادن",
"EntityActionsDisabledTooltip": "شما دسترسی به انجام هر گونه عملیات ندارید." "EntityActionsDisabledTooltip": "شما دسترسی به انجام هر گونه عملیات ندارید.",
"ResourcePermissions": "مجوزها"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profiilikuva", "ProfilePicture": "Profiilikuva",
"Theme": "Teema", "Theme": "Teema",
"NotAssigned": "Ei määritetty", "NotAssigned": "Ei määritetty",
"EntityActionsDisabledTooltip": "Sinulla ei ole oikeutta suorittaa mitään toimintoa." "EntityActionsDisabledTooltip": "Sinulla ei ole oikeutta suorittaa mitään toimintoa.",
"ResourcePermissions": "Käyttöoikeudet"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json

@ -61,6 +61,7 @@
"ProfilePicture": "Image de profil", "ProfilePicture": "Image de profil",
"Theme": "Thème", "Theme": "Thème",
"NotAssigned": "Non attribué", "NotAssigned": "Non attribué",
"EntityActionsDisabledTooltip": "Vous n&#39;avez pas les permissions pour effectuer une action." "EntityActionsDisabledTooltip": "Vous n&#39;avez pas les permissions pour effectuer une action.",
"ResourcePermissions": "Autorisations"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json

@ -61,6 +61,7 @@
"ProfilePicture": "प्रोफ़ाइल फोटो", "ProfilePicture": "प्रोफ़ाइल फोटो",
"Theme": "विषय", "Theme": "विषय",
"NotAssigned": "सौंपा नहीं गया है", "NotAssigned": "सौंपा नहीं गया है",
"EntityActionsDisabledTooltip": "आपके पास कोई कार्रवाई नहीं है जो करने के लिए है।" "EntityActionsDisabledTooltip": "आपके पास कोई कार्रवाई नहीं है जो करने के लिए है।",
"ResourcePermissions": "अनुमतियाँ"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profilna slika", "ProfilePicture": "Profilna slika",
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Nije dodijeljeno", "NotAssigned": "Nije dodijeljeno",
"EntityActionsDisabledTooltip": "Nemate dozvolu za izvođenje bilo kakve akcije." "EntityActionsDisabledTooltip": "Nemate dozvolu za izvođenje bilo kakve akcije.",
"ResourcePermissions": "Dozvole"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profil kép", "ProfilePicture": "Profil kép",
"Theme": "Téma", "Theme": "Téma",
"NotAssigned": "Nem kijelölt", "NotAssigned": "Nem kijelölt",
"EntityActionsDisabledTooltip": "Nincs jogosultsága bármely művelethez." "EntityActionsDisabledTooltip": "Nincs jogosultsága bármely művelethez.",
"ResourcePermissions": "Engedélyek"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json

@ -61,6 +61,7 @@
"ProfilePicture": "Forsíðumynd", "ProfilePicture": "Forsíðumynd",
"Theme": "Þema", "Theme": "Þema",
"NotAssigned": "Ekki skráður", "NotAssigned": "Ekki skráður",
"EntityActionsDisabledTooltip": "Þú hefur ekki aðgang að þessum aðgerðum." "EntityActionsDisabledTooltip": "Þú hefur ekki aðgang að þessum aðgerðum.",
"ResourcePermissions": "Aðgangsheimildir"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json

@ -61,6 +61,7 @@
"ProfilePicture": "Immagine del profilo", "ProfilePicture": "Immagine del profilo",
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Non assegnato", "NotAssigned": "Non assegnato",
"EntityActionsDisabledTooltip": "Non hai i permessi per eseguire alcuna azione." "EntityActionsDisabledTooltip": "Non hai i permessi per eseguire alcuna azione.",
"ResourcePermissions": "Autorizzazioni"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profielfoto", "ProfilePicture": "Profielfoto",
"Theme": "Thema", "Theme": "Thema",
"NotAssigned": "Niet toegekend", "NotAssigned": "Niet toegekend",
"EntityActionsDisabledTooltip": "U hebt geen toegang tot deze acties." "EntityActionsDisabledTooltip": "U hebt geen toegang tot deze acties.",
"ResourcePermissions": "Machtigingen"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json

@ -61,6 +61,7 @@
"ProfilePicture": "Zdjęcie profilowe", "ProfilePicture": "Zdjęcie profilowe",
"Theme": "Temat", "Theme": "Temat",
"NotAssigned": "Nie przypisano", "NotAssigned": "Nie przypisano",
"EntityActionsDisabledTooltip": "Nie masz uprawnień do wykonania żadnej akcji." "EntityActionsDisabledTooltip": "Nie masz uprawnień do wykonania żadnej akcji.",
"ResourcePermissions": "Uprawnienia"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json

@ -61,6 +61,7 @@
"ProfilePicture": "Foto do perfil", "ProfilePicture": "Foto do perfil",
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Não atribuído", "NotAssigned": "Não atribuído",
"EntityActionsDisabledTooltip": "Você não tem permissão para executar qualquer ação." "EntityActionsDisabledTooltip": "Você não tem permissão para executar qualquer ação.",
"ResourcePermissions": "Permissões"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json

@ -61,6 +61,7 @@
"ProfilePicture": "Poză de profil", "ProfilePicture": "Poză de profil",
"Theme": "Temă", "Theme": "Temă",
"NotAssigned": "Nealocat", "NotAssigned": "Nealocat",
"EntityActionsDisabledTooltip": "Nu aveți permisiune să efectuați nicio acțiune." "EntityActionsDisabledTooltip": "Nu aveți permisiune să efectuați nicio acțiune.",
"ResourcePermissions": "Permisiuni"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json

@ -61,6 +61,7 @@
"ProfilePicture": "Изображение профиля", "ProfilePicture": "Изображение профиля",
"Theme": "Тема", "Theme": "Тема",
"NotAssigned": "Не назначен", "NotAssigned": "Не назначен",
"EntityActionsDisabledTooltip": "У вас нет прав на выполнение каких-либо действий." "EntityActionsDisabledTooltip": "У вас нет прав на выполнение каких-либо действий.",
"ResourcePermissions": "Разрешения"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profilový obrázok", "ProfilePicture": "Profilový obrázok",
"Theme": "Téma", "Theme": "Téma",
"NotAssigned": "Nepridelené", "NotAssigned": "Nepridelené",
"EntityActionsDisabledTooltip": "Nemáte oprávnenie vykonávať žiadnu akciu." "EntityActionsDisabledTooltip": "Nemáte oprávnenie vykonávať žiadnu akciu.",
"ResourcePermissions": "Oprávnenia"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profilna slika", "ProfilePicture": "Profilna slika",
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Ni dodeljena", "NotAssigned": "Ni dodeljena",
"EntityActionsDisabledTooltip": "Nimate pravic za izvajanje kakršne koli dejanje." "EntityActionsDisabledTooltip": "Nimate pravic za izvajanje kakršne koli dejanje.",
"ResourcePermissions": "Dovoljenja"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json

@ -60,6 +60,7 @@
"ProfilePicture": "Profilbild", "ProfilePicture": "Profilbild",
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Ej tilldelad", "NotAssigned": "Ej tilldelad",
"EntityActionsDisabledTooltip": "Du har inte tillgång till dessa åtgärder." "EntityActionsDisabledTooltip": "Du har inte tillgång till dessa åtgärder.",
"ResourcePermissions": "Behörigheter"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json

@ -61,6 +61,7 @@
"ProfilePicture": "Profil resmi", "ProfilePicture": "Profil resmi",
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Atanmadı", "NotAssigned": "Atanmadı",
"EntityActionsDisabledTooltip": "Bu işlemi gerçekleştirmek için yeterli yetkiniz yok." "EntityActionsDisabledTooltip": "Bu işlemi gerçekleştirmek için yeterli yetkiniz yok.",
"ResourcePermissions": "İzinler"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json

@ -61,6 +61,7 @@
"ProfilePicture": "Ảnh đại diện", "ProfilePicture": "Ảnh đại diện",
"Theme": "chủ đề", "Theme": "chủ đề",
"NotAssigned": "Không được chỉ định", "NotAssigned": "Không được chỉ định",
"EntityActionsDisabledTooltip": "Bạn không có quyền thực hiện bất kỳ hành động nào." "EntityActionsDisabledTooltip": "Bạn không có quyền thực hiện bất kỳ hành động nào.",
"ResourcePermissions": "Quyền"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json

@ -61,6 +61,7 @@
"ProfilePicture": "个人资料图片", "ProfilePicture": "个人资料图片",
"Theme": "主题", "Theme": "主题",
"NotAssigned": "未分配", "NotAssigned": "未分配",
"EntityActionsDisabledTooltip": "您没有权限执行任何操作。" "EntityActionsDisabledTooltip": "您没有权限执行任何操作。",
"ResourcePermissions": "权限"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json

@ -61,6 +61,7 @@
"ProfilePicture": "個人資料圖片", "ProfilePicture": "個人資料圖片",
"Theme": "主題", "Theme": "主題",
"NotAssigned": "未分配", "NotAssigned": "未分配",
"EntityActionsDisabledTooltip": "您沒有權限執行任何操作。" "EntityActionsDisabledTooltip": "您沒有權限執行任何操作。",
"ResourcePermissions": "權限"
} }
} }

4
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/AbpAuthorizationTestModule.cs

@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.TestServices; using Volo.Abp.Authorization.TestServices;
using Volo.Abp.Authorization.TestServices.Resources;
using Volo.Abp.Autofac; using Volo.Abp.Autofac;
using Volo.Abp.DynamicProxy; using Volo.Abp.DynamicProxy;
using Volo.Abp.ExceptionHandling; using Volo.Abp.ExceptionHandling;
@ -33,6 +34,9 @@ public class AbpAuthorizationTestModule : AbpModule
options.ValueProviders.Add<TestPermissionValueProvider2>(); options.ValueProviders.Add<TestPermissionValueProvider2>();
options.ValueProviders.Add<TestProhibitedPermissionValueProvider1>(); options.ValueProviders.Add<TestProhibitedPermissionValueProvider1>();
options.ValueProviders.Add<TestProhibitedPermissionValueProvider2>(); options.ValueProviders.Add<TestProhibitedPermissionValueProvider2>();
options.ResourceValueProviders.Add<TestResourcePermissionValueProvider1>();
options.ResourceValueProviders.Add<TestResourcePermissionValueProvider2>();
}); });
} }
} }

11
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionValueProviderManager_Tests.cs

@ -2,12 +2,11 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Shouldly; using Shouldly;
using Volo.Abp.Authorization;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.TestServices; using Volo.Abp.Authorization.TestServices;
using Xunit; using Xunit;
namespace Volo.Abp; namespace Volo.Abp.Authorization;
public class PermissionValueProviderManager_Tests: AuthorizationTestBase public class PermissionValueProviderManager_Tests: AuthorizationTestBase
{ {
@ -17,7 +16,7 @@ public class PermissionValueProviderManager_Tests: AuthorizationTestBase
{ {
_permissionValueProviderManager = GetRequiredService<IPermissionValueProviderManager>(); _permissionValueProviderManager = GetRequiredService<IPermissionValueProviderManager>();
} }
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{ {
options.Services.Configure<AbpPermissionOptions>(permissionOptions => options.Services.Configure<AbpPermissionOptions>(permissionOptions =>
@ -25,7 +24,7 @@ public class PermissionValueProviderManager_Tests: AuthorizationTestBase
permissionOptions.ValueProviders.Add<TestDuplicatePermissionValueProvider>(); permissionOptions.ValueProviders.Add<TestDuplicatePermissionValueProvider>();
}); });
} }
[Fact] [Fact]
public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected() public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected()
{ {
@ -33,7 +32,7 @@ public class PermissionValueProviderManager_Tests: AuthorizationTestBase
{ {
var providers = _permissionValueProviderManager.ValueProviders; var providers = _permissionValueProviderManager.ValueProviders;
}); });
exception.Message.ShouldBe($"Duplicate permission value provider name detected: TestPermissionValueProvider1. Providers:{Environment.NewLine}{typeof(TestDuplicatePermissionValueProvider).FullName}{Environment.NewLine}{typeof(TestPermissionValueProvider1).FullName}"); exception.Message.ShouldBe($"Duplicate permission value provider name detected: TestPermissionValueProvider1. Providers:{Environment.NewLine}{typeof(TestDuplicatePermissionValueProvider).FullName}{Environment.NewLine}{typeof(TestPermissionValueProvider1).FullName}");
} }
} }
@ -55,4 +54,4 @@ public class TestDuplicatePermissionValueProvider : PermissionValueProvider
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }

62
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionChecker_Tests.cs

@ -0,0 +1,62 @@
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Authorization.TestServices.Resources;
using Xunit;
namespace Volo.Abp.Authorization;
public class ResourcePermissionChecker_Tests: AuthorizationTestBase
{
private readonly IResourcePermissionChecker _resourcePermissionChecker;
public ResourcePermissionChecker_Tests()
{
_resourcePermissionChecker = GetRequiredService<IResourcePermissionChecker>();
}
[Fact]
public async Task IsGrantedAsync()
{
(await _resourcePermissionChecker.IsGrantedAsync("MyResourcePermission5", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(true);
(await _resourcePermissionChecker.IsGrantedAsync("UndefinedResourcePermission", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(false);
(await _resourcePermissionChecker.IsGrantedAsync("MyResourcePermission8", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(false);
}
[Fact]
public async Task IsGranted_Multiple_Result_Async()
{
var result = await _resourcePermissionChecker.IsGrantedAsync(new []
{
"MyResourcePermission1",
"MyResourcePermission2",
"UndefinedPermission",
"MyResourcePermission3",
"MyResourcePermission4",
"MyResourcePermission5",
"MyResourcePermission8"
}, TestEntityResource.ResourceName, TestEntityResource.ResourceKey5);
result.Result["MyResourcePermission1"].ShouldBe(PermissionGrantResult.Undefined);
result.Result["MyResourcePermission2"].ShouldBe(PermissionGrantResult.Prohibited);
result.Result["UndefinedPermission"].ShouldBe(PermissionGrantResult.Prohibited);
result.Result["MyResourcePermission3"].ShouldBe(PermissionGrantResult.Granted);
result.Result["MyResourcePermission4"].ShouldBe(PermissionGrantResult.Prohibited);
result.Result["MyResourcePermission5"].ShouldBe(PermissionGrantResult.Granted);
result.Result["MyResourcePermission8"].ShouldBe(PermissionGrantResult.Prohibited);
result = await _resourcePermissionChecker.IsGrantedAsync(new []
{
"MyResourcePermission6",
}, TestEntityResource.ResourceName, TestEntityResource.ResourceKey6);
result.Result["MyResourcePermission6"].ShouldBe(PermissionGrantResult.Granted);
result = await _resourcePermissionChecker.IsGrantedAsync(new []
{
"MyResourcePermission7",
}, TestEntityResource.ResourceName, TestEntityResource.ResourceKey7);
result.Result["MyResourcePermission7"].ShouldBe(PermissionGrantResult.Granted);
}
}

60
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionPopulator_Test.cs

@ -0,0 +1,60 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Authorization.TestServices.Resources;
using Xunit;
namespace Volo.Abp.Authorization;
public class ResourcePermissionPopulator_Tests : AuthorizationTestBase
{
private readonly ResourcePermissionPopulator _resourcePermissionPopulator;
public ResourcePermissionPopulator_Tests()
{
_resourcePermissionPopulator = GetRequiredService<ResourcePermissionPopulator>();
}
[Fact]
public async Task PopulateAsync()
{
var testResourceObject = new TestEntityResource(TestEntityResource.ResourceKey5);
testResourceObject.ResourcePermissions.IsNullOrEmpty().ShouldBeTrue();
await _resourcePermissionPopulator.PopulateAsync<TestEntityResource>(
testResourceObject,
TestEntityResource.ResourceName
);
testResourceObject.ResourcePermissions.ShouldNotBeNull();
testResourceObject.ResourcePermissions.Count.ShouldBe(8);
testResourceObject.ResourcePermissions["MyResourcePermission1"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission2"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission3"].ShouldBe(true);
testResourceObject.ResourcePermissions["MyResourcePermission4"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission5"].ShouldBe(true);
testResourceObject.ResourcePermissions["MyResourcePermission6"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission7"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission8"].ShouldBe(false);
testResourceObject = new TestEntityResource(TestEntityResource.ResourceKey6);
testResourceObject.ResourcePermissions.IsNullOrEmpty().ShouldBeTrue();
await _resourcePermissionPopulator.PopulateAsync<TestEntityResource>(
testResourceObject,
TestEntityResource.ResourceName
);
testResourceObject.ResourcePermissions.ShouldNotBeNull();
testResourceObject.ResourcePermissions.Count.ShouldBe(8);
testResourceObject.ResourcePermissions["MyResourcePermission1"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission2"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission3"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission4"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission5"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission6"].ShouldBe(true);
testResourceObject.ResourcePermissions["MyResourcePermission7"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission8"].ShouldBe(false);
}
}

58
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionValueProviderManager_Tests.cs

@ -0,0 +1,58 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Authorization.TestServices.Resources;
using Xunit;
namespace Volo.Abp.Authorization;
public class ResourcePermissionValueProviderManager_Tests: AuthorizationTestBase
{
private readonly IResourcePermissionValueProviderManager _resourcePermissionValueProviderManager;
public ResourcePermissionValueProviderManager_Tests()
{
_resourcePermissionValueProviderManager = GetRequiredService<IResourcePermissionValueProviderManager>();
}
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.Services.Configure<AbpPermissionOptions>(permissionOptions =>
{
permissionOptions.ResourceValueProviders.Add<TestDuplicateResourcePermissionValueProvider>();
});
}
[Fact]
public void Should_Throw_Exception_If_Duplicate_Provider_Name_Detected()
{
var exception = Assert.Throws<AbpException>(() =>
{
var providers = _resourcePermissionValueProviderManager.ValueProviders;
});
exception.Message.ShouldBe($"Duplicate resource permission value provider name detected: TestResourcePermissionValueProvider1. Providers:{Environment.NewLine}{typeof(TestDuplicateResourcePermissionValueProvider).FullName}{Environment.NewLine}{typeof(TestResourcePermissionValueProvider1).FullName}");
}
}
public class TestDuplicateResourcePermissionValueProvider : ResourcePermissionValueProvider
{
public TestDuplicateResourcePermissionValueProvider(IResourcePermissionStore permissionStore) : base(permissionStore)
{
}
public override string Name => "TestResourcePermissionValueProvider1";
public override Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context)
{
throw new NotImplementedException();
}
public override Task<MultiplePermissionGrantResult> CheckAsync(ResourcePermissionValuesCheckContext context)
{
throw new NotImplementedException();
}
}

26
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/StaticPermissionDefinitionStore_Tests.cs

@ -1,6 +1,7 @@
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.Authorization.TestServices.Resources;
using Xunit; using Xunit;
namespace Volo.Abp.Authorization; namespace Volo.Abp.Authorization;
@ -44,4 +45,29 @@ public class StaticPermissionDefinitionStore_Tests : AuthorizationTestBase
var groups = await _store.GetGroupsAsync(); var groups = await _store.GetGroupsAsync();
groups.ShouldNotContain(x => x.Name == "TestGetGroup"); groups.ShouldNotContain(x => x.Name == "TestGetGroup");
} }
[Fact]
public async Task GetResourcePermissionOrNullAsync()
{
var permission = await _store.GetResourcePermissionOrNullAsync(TestEntityResource.ResourceName, "MyResourcePermission1");
permission.ShouldNotBeNull();
permission.Name.ShouldBe("MyResourcePermission1");
permission.StateCheckers.ShouldContain(x => x.GetType() == typeof(TestRequireEditionPermissionSimpleStateChecker));
permission = await _store.GetResourcePermissionOrNullAsync(TestEntityResource.ResourceName, "NotExists");
permission.ShouldBeNull();
}
[Fact]
public async Task GetResourcePermissionsAsync()
{
var permissions = await _store.GetResourcePermissionsAsync();
permissions.ShouldContain(x => x.Name == "MyResourcePermission1");
permissions.ShouldContain(x => x.Name == "MyResourcePermission2");
permissions.ShouldContain(x => x.Name == "MyResourcePermission3");
permissions.ShouldContain(x => x.Name == "MyResourcePermission4");
permissions.ShouldContain(x => x.Name == "MyResourcePermission5");
permissions.ShouldContain(x => x.Name == "MyResourcePermission6");
permissions.ShouldContain(x => x.Name == "MyResourcePermission7");
}
} }

4
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/FakePermissionStore.cs

@ -8,7 +8,7 @@ public class FakePermissionStore : IPermissionStore, ITransientDependency
{ {
public Task<bool> IsGrantedAsync(string name, string providerName, string providerKey) public Task<bool> IsGrantedAsync(string name, string providerName, string providerKey)
{ {
return Task.FromResult(name == "MyPermission3" || name == "MyPermission5"); return Task.FromResult(name == "MyPermission3" || name == "MyPermission5" || name == "TestEntityManagementPermission");
} }
public Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names, string providerName, string providerKey) public Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names, string providerName, string providerKey)
@ -16,7 +16,7 @@ public class FakePermissionStore : IPermissionStore, ITransientDependency
var result = new MultiplePermissionGrantResult(); var result = new MultiplePermissionGrantResult();
foreach (var name in names) foreach (var name in names)
{ {
result.Result.Add(name, name == "MyPermission3" || name == "MyPermission5" result.Result.Add(name, name == "MyPermission3" || name == "MyPermission5" || name == "TestEntityManagementPermission"
? PermissionGrantResult.Granted ? PermissionGrantResult.Granted
: PermissionGrantResult.Prohibited); : PermissionGrantResult.Prohibited);
} }

48
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/AuthorizationTestResourcePermissionDefinitionProvider.cs

@ -0,0 +1,48 @@
using Shouldly;
using Volo.Abp.Authorization.Permissions;
using Xunit;
namespace Volo.Abp.Authorization.TestServices.Resources;
public class AuthorizationTestResourcePermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var getGroup = context.GetGroupOrNull("TestGroup");
if (getGroup == null)
{
getGroup = context.AddGroup("TestGroup");
}
getGroup.AddPermission("TestEntityManagementPermission");
getGroup.AddPermission("TestEntityManagementPermission2");
var permission1 = context.AddResourcePermission("MyResourcePermission1", resourceName: TestEntityResource.ResourceName, "TestEntityManagementPermission");
Assert.Throws<AbpException>(() =>
{
permission1.AddChild("MyResourcePermission1.ChildPermission1");
}).Message.ShouldBe($"Resource permission cannot have child permissions. Resource: {TestEntityResource.ResourceName}");
permission1.StateCheckers.Add(new TestRequireEditionPermissionSimpleStateChecker());;
permission1[PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName].ShouldBe(typeof(AuthorizationTestResourcePermissionDefinitionProvider).FullName);
context.AddResourcePermission("MyResourcePermission2", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission");
context.AddResourcePermission("MyResourcePermission3", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission");
context.AddResourcePermission("MyResourcePermission4", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission");
context.AddResourcePermission("MyResourcePermission5", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission");
context.AddResourcePermission("MyResourcePermission6", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission").WithProviders(nameof(TestResourcePermissionValueProvider1));
context.AddResourcePermission("MyResourcePermission7", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission").WithProviders(nameof(TestResourcePermissionValueProvider2));
context.AddResourcePermission("MyResourcePermission8", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission2");
Assert.Throws<AbpException>(() =>
{
context.AddResourcePermission("MyResourcePermission7", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission");
}).Message.ShouldBe($"There is already an existing resource permission with name: MyResourcePermission7 for resource: {typeof(TestEntityResource).FullName}");
context.AddResourcePermission("MyResourcePermission7", resourceName: typeof(TestEntityResource2).FullName!, "TestEntityManagementPermission").WithProviders(nameof(TestResourcePermissionValueProvider2));
context.GetResourcePermissionOrNull(TestEntityResource.ResourceName, "MyResourcePermission1").ShouldNotBeNull();
context.GetResourcePermissionOrNull(TestEntityResource.ResourceName, "MyResourcePermission7").ShouldNotBeNull();
context.GetResourcePermissionOrNull(TestEntityResource2.ResourceName, "MyResourcePermission7").ShouldNotBeNull();
context.GetResourcePermissionOrNull(TestEntityResource.ResourceName, "MyResourcePermission9").ShouldBeNull();
context.GetResourcePermissionOrNull(TestEntityResource2.ResourceName, "MyResourcePermission6").ShouldBeNull();
}
}

46
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/FakeResourcePermissionStore.cs

@ -0,0 +1,46 @@
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Authorization.TestServices.Resources;
public class FakeResourcePermissionStore : IResourcePermissionStore, ITransientDependency
{
public Task<bool> IsGrantedAsync(string name, string resourceName, string resourceKey, string providerName, string providerKey)
{
return Task.FromResult((name == "MyResourcePermission3" || name == "MyResourcePermission5") &&
resourceName == TestEntityResource.ResourceName &&
(resourceKey == TestEntityResource.ResourceKey3 || resourceKey == TestEntityResource.ResourceKey5));
}
public Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names, string resourceName, string resourceKey, string providerName, string providerKey)
{
var result = new MultiplePermissionGrantResult();
foreach (var name in names)
{
result.Result.Add(name, ((name == "MyResourcePermission3" || name == "MyResourcePermission5") &&
resourceName == TestEntityResource.ResourceName &&
(resourceKey == TestEntityResource.ResourceKey3 || resourceKey == TestEntityResource.ResourceKey5)
? PermissionGrantResult.Granted
: PermissionGrantResult.Prohibited));
}
return Task.FromResult(result);
}
public Task<MultiplePermissionGrantResult> GetPermissionsAsync(string resourceName, string resourceKey)
{
throw new System.NotImplementedException();
}
public Task<string[]> GetGrantedPermissionsAsync(string resourceName, string resourceKey)
{
throw new System.NotImplementedException();
}
public Task<string[]> GetGrantedResourceKeysAsync(string resourceName, string name)
{
throw new System.NotImplementedException();
}
}

37
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/TestEntityResource.cs

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Authorization.Permissions.Resources;
namespace Volo.Abp.Authorization.TestServices.Resources;
public class TestEntityResource : IHasResourcePermissions
{
public static readonly string ResourceName = typeof(TestEntityResource).FullName;
public static readonly string ResourceKey1 = Guid.NewGuid().ToString();
public static readonly string ResourceKey2 = Guid.NewGuid().ToString();
public static readonly string ResourceKey3 = Guid.NewGuid().ToString();
public static readonly string ResourceKey4 = Guid.NewGuid().ToString();
public static readonly string ResourceKey5 = Guid.NewGuid().ToString();
public static readonly string ResourceKey6 = Guid.NewGuid().ToString();
public static readonly string ResourceKey7 = Guid.NewGuid().ToString();
private string Id { get; }
public TestEntityResource(string id)
{
Id = id;
}
public string GetObjectKey()
{
return Id;
}
public Dictionary<string, bool> ResourcePermissions { get; set; }
}
public class TestEntityResource2
{
public static readonly string ResourceName = typeof(TestEntityResource2).FullName;
}

43
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/TestResourcePermissionValueProvider1.cs

@ -0,0 +1,43 @@
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions.Resources;
namespace Volo.Abp.Authorization.TestServices.Resources;
public class TestResourcePermissionValueProvider1 : ResourcePermissionValueProvider
{
public TestResourcePermissionValueProvider1(IResourcePermissionStore permissionStore) : base(permissionStore)
{
}
public override string Name => "TestResourcePermissionValueProvider1";
public override Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context)
{
var result = PermissionGrantResult.Undefined;
if (context.Permission.Name == "MyResourcePermission6" &&
context.ResourceName == TestEntityResource.ResourceName &&
context.ResourceKey == TestEntityResource.ResourceKey6)
{
result = PermissionGrantResult.Granted;
}
return Task.FromResult(result);
}
public override Task<MultiplePermissionGrantResult> CheckAsync(ResourcePermissionValuesCheckContext context)
{
var result = new MultiplePermissionGrantResult();
foreach (var name in context.Permissions.Select(x => x.Name))
{
result.Result.Add(name, name == "MyResourcePermission6" &&
context.ResourceName == TestEntityResource.ResourceName &&
context.ResourceKey == TestEntityResource.ResourceKey6
? PermissionGrantResult.Granted
: PermissionGrantResult.Undefined);
}
return Task.FromResult(result);
}
}

43
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/TestResourcePermissionValueProvider2.cs

@ -0,0 +1,43 @@
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions.Resources;
namespace Volo.Abp.Authorization.TestServices.Resources;
public class TestResourcePermissionValueProvider2 : ResourcePermissionValueProvider
{
public TestResourcePermissionValueProvider2(IResourcePermissionStore permissionStore) : base(permissionStore)
{
}
public override string Name => "TestResourcePermissionValueProvider2";
public override Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context)
{
var result = PermissionGrantResult.Undefined;
if (context.Permission.Name == "MyResourcePermission7" &&
context.ResourceName == TestEntityResource.ResourceName &&
context.ResourceKey == TestEntityResource.ResourceKey7)
{
result = PermissionGrantResult.Granted;
}
return Task.FromResult(result);
}
public override Task<MultiplePermissionGrantResult> CheckAsync(ResourcePermissionValuesCheckContext context)
{
var result = new MultiplePermissionGrantResult();
foreach (var name in context.Permissions.Select(x => x.Name))
{
result.Result.Add(name, name == "MyResourcePermission7" &&
context.ResourceName == TestEntityResource.ResourceName &&
context.ResourceKey == TestEntityResource.ResourceKey7
? PermissionGrantResult.Granted
: PermissionGrantResult.Undefined);
}
return Task.FromResult(result);
}
}

31
framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectWithKeyHelper_Tests.cs

@ -0,0 +1,31 @@
using System;
using Shouldly;
using Xunit;
namespace Volo.Abp;
public class KeyedObjectHelper_Tests
{
[Fact]
public void EncodeCompositeKey()
{
var encoded = KeyedObjectHelper.EncodeCompositeKey("Book", "123");
encoded.ShouldBe("Qm9va3x8MTIz");
}
[Fact]
public void DecodeCompositeKey()
{
var decoded = KeyedObjectHelper.DecodeCompositeKey("Qm9va3x8MTIz");
decoded.ShouldBe("Book||123");
}
[Fact]
public void Encode_Decode_CompositeKey()
{
var encoded = KeyedObjectHelper.EncodeCompositeKey("User", 42, Guid.Empty);
var decoded = KeyedObjectHelper.DecodeCompositeKey(encoded);
decoded.ShouldBe($"User||42||{Guid.Empty}");
}
}

5
framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs

@ -55,6 +55,11 @@ public class EntityHelper_Tests
{ {
return new object[] { Id }; return new object[] { Id };
} }
public string GetObjectKey()
{
return Id.ToString();
}
} }
private class MyEntityDisablesIdGeneration : Entity<Guid> private class MyEntityDisablesIdGeneration : Entity<Guid>

12
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Integration/IIdentityUserIntegrationService.cs

@ -10,12 +10,20 @@ namespace Volo.Abp.Identity.Integration;
public interface IIdentityUserIntegrationService : IApplicationService public interface IIdentityUserIntegrationService : IApplicationService
{ {
Task<string[]> GetRoleNamesAsync(Guid id); Task<string[]> GetRoleNamesAsync(Guid id);
Task<UserData> FindByIdAsync(Guid id); Task<UserData> FindByIdAsync(Guid id);
Task<UserData> FindByUserNameAsync(string userName); Task<UserData> FindByUserNameAsync(string userName);
Task<ListResultDto<UserData>> SearchAsync(UserLookupSearchInputDto input); Task<ListResultDto<UserData>> SearchAsync(UserLookupSearchInputDto input);
Task<ListResultDto<UserData>> SearchByIdsAsync(Guid[] ids);
Task<long> GetCountAsync(UserLookupCountInputDto input); Task<long> GetCountAsync(UserLookupCountInputDto input);
}
Task<ListResultDto<RoleData>> SearchRoleAsync(RoleLookupSearchInputDto input);
Task<ListResultDto<RoleData>> SearchRoleByNamesAsync(string[] ids);
Task<long> GetRoleCountAsync(RoleLookupCountInputDto input);
}

6
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/RoleLookupCountInputDto.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.Identity;
public class RoleLookupCountInputDto
{
public string Filter { get; set; }
}

8
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/RoleLookupSearchInputDto.cs

@ -0,0 +1,8 @@
using Volo.Abp.Application.Dtos;
namespace Volo.Abp.Identity;
public class RoleLookupSearchInputDto : ExtensiblePagedAndSortedResultRequestDto
{
public string Filter { get; set; }
}

54
modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/Integration/IdentityUserIntegrationService.cs

@ -2,6 +2,7 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Users; using Volo.Abp.Users;
namespace Volo.Abp.Identity.Integration; namespace Volo.Abp.Identity.Integration;
@ -10,13 +11,19 @@ public class IdentityUserIntegrationService : IdentityAppServiceBase, IIdentityU
{ {
protected IUserRoleFinder UserRoleFinder { get; } protected IUserRoleFinder UserRoleFinder { get; }
protected IdentityUserRepositoryExternalUserLookupServiceProvider UserLookupServiceProvider { get; } protected IdentityUserRepositoryExternalUserLookupServiceProvider UserLookupServiceProvider { get; }
protected IIdentityUserRepository UserRepository { get; }
protected IIdentityRoleRepository RoleRepository { get; }
public IdentityUserIntegrationService( public IdentityUserIntegrationService(
IUserRoleFinder userRoleFinder, IUserRoleFinder userRoleFinder,
IdentityUserRepositoryExternalUserLookupServiceProvider userLookupServiceProvider) IdentityUserRepositoryExternalUserLookupServiceProvider userLookupServiceProvider,
IIdentityUserRepository userRepository,
IIdentityRoleRepository roleRepository)
{ {
UserRoleFinder = userRoleFinder; UserRoleFinder = userRoleFinder;
UserLookupServiceProvider = userLookupServiceProvider; UserLookupServiceProvider = userLookupServiceProvider;
UserRepository = userRepository;
RoleRepository = roleRepository;
} }
public virtual async Task<string[]> GetRoleNamesAsync(Guid id) public virtual async Task<string[]> GetRoleNamesAsync(Guid id)
@ -62,8 +69,53 @@ public class IdentityUserIntegrationService : IdentityAppServiceBase, IIdentityU
); );
} }
public virtual async Task<ListResultDto<UserData>> SearchByIdsAsync(Guid[] ids)
{
var users = await UserRepository.GetListByIdsAsync(ids);
return new ListResultDto<UserData>(
users
.Select(u => new UserData(
u.Id,
u.UserName,
u.Email,
u.Name,
u.Surname,
u.EmailConfirmed,
u.PhoneNumber,
u.PhoneNumberConfirmed,
u.TenantId,
u.IsActive,
u.ExtraProperties))
.ToList()
);
}
public virtual async Task<long> GetCountAsync(UserLookupCountInputDto input) public virtual async Task<long> GetCountAsync(UserLookupCountInputDto input)
{ {
return await UserLookupServiceProvider.GetCountAsync(input.Filter); return await UserLookupServiceProvider.GetCountAsync(input.Filter);
} }
public virtual async Task<ListResultDto<RoleData>> SearchRoleAsync(RoleLookupSearchInputDto input)
{
using (RoleRepository.DisableTracking())
{
var roles = await RoleRepository.GetListAsync(input.Filter);
return new ListResultDto<RoleData>(roles.Select(r => new RoleData(r.Id, r.Name, r.IsDefault, r.IsStatic, r.IsPublic, r.TenantId, r.ExtraProperties)).ToList());
}
}
public virtual async Task<ListResultDto<RoleData>> SearchRoleByNamesAsync(string[] names)
{
using (RoleRepository.DisableTracking())
{
var roles = await RoleRepository.GetListAsync(names);
return new ListResultDto<RoleData>(roles.Select(r => new RoleData(r.Id, r.Name, r.IsDefault, r.IsStatic, r.IsPublic, r.TenantId, r.ExtraProperties)).ToList());
}
}
public virtual async Task<long> GetRoleCountAsync(RoleLookupCountInputDto input)
{
return await RoleRepository.GetCountAsync(input.Filter);
}
} }

12
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IUserRoleFinder.cs

@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Volo.Abp.Identity; namespace Volo.Abp.Identity;
@ -7,6 +9,14 @@ public interface IUserRoleFinder
{ {
[Obsolete("Use GetRoleNamesAsync instead.")] [Obsolete("Use GetRoleNamesAsync instead.")]
Task<string[]> GetRolesAsync(Guid userId); Task<string[]> GetRolesAsync(Guid userId);
Task<string[]> GetRoleNamesAsync(Guid userId); Task<string[]> GetRoleNamesAsync(Guid userId);
Task<List<UserFinderResult>> SearchUserAsync(string filter, int page = 1);
Task<List<RoleFinderResult>> SearchRoleAsync(string filter, int page = 1);
Task<List<UserFinderResult>> SearchUserByIdsAsync(Guid[] ids);
Task<List<RoleFinderResult>> SearchRoleByNamesAsync(string[] names);
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json

@ -135,6 +135,8 @@
"ModificationTime": "وقت التعديل", "ModificationTime": "وقت التعديل",
"PasswordUpdateTime": "وقت تحديث كلمة المرور", "PasswordUpdateTime": "وقت تحديث كلمة المرور",
"LockoutEndTime": "وقت انتهاء القفل", "LockoutEndTime": "وقت انتهاء القفل",
"FailedAccessCount": "فشل عدد الوصول" "FailedAccessCount": "فشل عدد الوصول",
"UserResourcePermissionProviderKeyLookupService": "المستخدم",
"RoleResourcePermissionProviderKeyLookupService": "الدور"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json

@ -135,6 +135,8 @@
"ModificationTime": "Doba úpravy", "ModificationTime": "Doba úpravy",
"PasswordUpdateTime": "Čas aktualizace hesla", "PasswordUpdateTime": "Čas aktualizace hesla",
"LockoutEndTime": "Čas konce uzamčení", "LockoutEndTime": "Čas konce uzamčení",
"FailedAccessCount": "Počet neúspěšných přístupů" "FailedAccessCount": "Počet neúspěšných přístupů",
"UserResourcePermissionProviderKeyLookupService": "Uživatel",
"RoleResourcePermissionProviderKeyLookupService": "Role"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json

@ -135,6 +135,8 @@
"LockoutEndTime": "Endzeit der Sperrung", "LockoutEndTime": "Endzeit der Sperrung",
"FailedAccessCount": "Anzahl der fehlgeschlagenen Zugriffe", "FailedAccessCount": "Anzahl der fehlgeschlagenen Zugriffe",
"DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "E-Mail-Verifizierung für die Registrierung erzwingen", "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "E-Mail-Verifizierung für die Registrierung erzwingen",
"Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Benutzerkonten werden nicht erstellt, es sei denn, sie verifizieren ihre E-Mail-Adressen." "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Benutzerkonten werden nicht erstellt, es sei denn, sie verifizieren ihre E-Mail-Adressen.",
"UserResourcePermissionProviderKeyLookupService": "Benutzer",
"RoleResourcePermissionProviderKeyLookupService": "Rolle"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json

@ -128,6 +128,8 @@
"Description:Abp.Identity.User.IsEmailUpdateEnabled": "Εάν το email μπορεί να ενημερωθεί από τον χρήστη.", "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Εάν το email μπορεί να ενημερωθεί από τον χρήστη.",
"DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Επιβολή επαλήθευσης email για εγγραφή", "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Επιβολή επαλήθευσης email για εγγραφή",
"Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Οι λογαριασμοί χρηστών δεν θα δημιουργηθούν εκτός αν επαληθεύσουν τις διευθύνσεις email τους.", "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Οι λογαριασμοί χρηστών δεν θα δημιουργηθούν εκτός αν επαληθεύσουν τις διευθύνσεις email τους.",
"Details": "Λεπτομέρειες" "Details": "Λεπτομέρειες",
"UserResourcePermissionProviderKeyLookupService": "Χρήστης",
"RoleResourcePermissionProviderKeyLookupService": "Ρόλος"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json

@ -137,6 +137,8 @@
"Description:Abp.Identity.UsersCanChange": "Allow users to change their Two Factor.", "Description:Abp.Identity.UsersCanChange": "Allow users to change their Two Factor.",
"DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Enforce email verification to register", "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Enforce email verification to register",
"Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "User accounts will not be created unless they verify their email addresses.", "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "User accounts will not be created unless they verify their email addresses.",
"Details": "Details" "Details": "Details",
"UserResourcePermissionProviderKeyLookupService": "User",
"RoleResourcePermissionProviderKeyLookupService": "Role"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json

@ -135,6 +135,8 @@
"ModificationTime": "Modification time", "ModificationTime": "Modification time",
"PasswordUpdateTime": "Password update time", "PasswordUpdateTime": "Password update time",
"LockoutEndTime": "Lockout end time", "LockoutEndTime": "Lockout end time",
"FailedAccessCount": "Failed access count" "FailedAccessCount": "Failed access count",
"UserResourcePermissionProviderKeyLookupService": "User",
"RoleResourcePermissionProviderKeyLookupService": "Role"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json

@ -135,6 +135,8 @@
"ModificationTime": "tiempo de modificación", "ModificationTime": "tiempo de modificación",
"PasswordUpdateTime": "Hora de actualización de contraseña", "PasswordUpdateTime": "Hora de actualización de contraseña",
"LockoutEndTime": "Hora de finalización del bloqueo", "LockoutEndTime": "Hora de finalización del bloqueo",
"FailedAccessCount": "Recuento de acceso fallido" "FailedAccessCount": "Recuento de acceso fallido",
"UserResourcePermissionProviderKeyLookupService": "Usuario",
"RoleResourcePermissionProviderKeyLookupService": "Rol"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json

@ -139,6 +139,8 @@
"Description:Abp.Identity.SignIn.RequireConfirmedEmail": "کاربران می‌توانند حساب ایجاد کنند اما تا زمانی که آدرس ایمیل خود را تایید نکنند نمی‌توانند وارد شوند.", "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "کاربران می‌توانند حساب ایجاد کنند اما تا زمانی که آدرس ایمیل خود را تایید نکنند نمی‌توانند وارد شوند.",
"Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "کاربران می‌توانند حساب ایجاد کنند اما تا زمانی که شماره تلفن خود را تایید نکنند نمی‌توانند وارد شوند.", "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "کاربران می‌توانند حساب ایجاد کنند اما تا زمانی که شماره تلفن خود را تایید نکنند نمی‌توانند وارد شوند.",
"DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "اجباری کردن تایید ایمیل برای ثبت‌نام", "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "اجباری کردن تایید ایمیل برای ثبت‌نام",
"Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "حساب‌های کاربری ایجاد نخواهند شد مگر اینکه آدرس ایمیل خود را تایید کنند." "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "حساب‌های کاربری ایجاد نخواهند شد مگر اینکه آدرس ایمیل خود را تایید کنند.",
"UserResourcePermissionProviderKeyLookupService": "کاربر",
"RoleResourcePermissionProviderKeyLookupService": "نقش"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json

@ -135,6 +135,8 @@
"ModificationTime": "Muutosaika", "ModificationTime": "Muutosaika",
"PasswordUpdateTime": "Salasanan päivityksen aika", "PasswordUpdateTime": "Salasanan päivityksen aika",
"LockoutEndTime": "Lukituksen päättymisaika", "LockoutEndTime": "Lukituksen päättymisaika",
"FailedAccessCount": "Epäonnistuneet käyttöoikeudet" "FailedAccessCount": "Epäonnistuneet käyttöoikeudet",
"UserResourcePermissionProviderKeyLookupService": "Käyttäjä",
"RoleResourcePermissionProviderKeyLookupService": "Rooli"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json

@ -135,6 +135,8 @@
"LockoutEndTime": "Heure de fin du verrouillage", "LockoutEndTime": "Heure de fin du verrouillage",
"FailedAccessCount": "Nombre d&#39;accès ayant échoué", "FailedAccessCount": "Nombre d&#39;accès ayant échoué",
"DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Exiger la vérification de l'e-mail pour s'inscrire", "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Exiger la vérification de l'e-mail pour s'inscrire",
"Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Les comptes d’utilisateurs ne seront pas créés à moins qu’ils ne vérifient leurs adresses e-mail." "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Les comptes d’utilisateurs ne seront pas créés à moins qu’ils ne vérifient leurs adresses e-mail.",
"UserResourcePermissionProviderKeyLookupService": "Utilisateur",
"RoleResourcePermissionProviderKeyLookupService": "Rôle"
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json

@ -135,6 +135,8 @@
"ModificationTime": "संशोधन का समय", "ModificationTime": "संशोधन का समय",
"PasswordUpdateTime": "पासवर्ड अद्यतन समय", "PasswordUpdateTime": "पासवर्ड अद्यतन समय",
"LockoutEndTime": "तालाबंदी समाप्ति समय", "LockoutEndTime": "तालाबंदी समाप्ति समय",
"FailedAccessCount": "विफल पहुंच गणना" "FailedAccessCount": "विफल पहुंच गणना",
"UserResourcePermissionProviderKeyLookupService": "उपयोगकर्ता",
"RoleResourcePermissionProviderKeyLookupService": "भूमिका"
} }
} }

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save