diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs
index 7ff890bac7..e6c949429d 100644
--- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs
+++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs
@@ -1,5 +1,7 @@
using System;
+using JetBrains.Annotations;
using Volo.Abp.Localization;
+using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Authorization.Permissions;
@@ -46,4 +48,15 @@ public interface IPermissionDefinitionContext
/// Name of the permission
///
PermissionDefinition? GetPermissionOrNull(string name);
+
+ PermissionDefinition AddResourcePermission(
+ string name,
+ string resourceName,
+ ILocalizableString? displayName = null,
+ MultiTenancySides multiTenancySide = MultiTenancySides.Both,
+ bool isEnabled = true);
+
+ PermissionDefinition? GetResourcePermissionOrNull([NotNull] string name);
+
+ void RemoveResourcePermission([NotNull] string name);
}
diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionManager.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionManager.cs
index ca04b110f7..52afcbe6eb 100644
--- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionManager.cs
+++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionDefinitionManager.cs
@@ -11,7 +11,14 @@ public interface IPermissionDefinitionManager
Task GetOrNullAsync([NotNull] string name);
+ [ItemNotNull]
+ Task GetResourcePermissionAsync([NotNull] string name);
+
+ Task GetResourcePermissionOrNullAsync([NotNull] string name);
+
Task> GetPermissionsAsync();
+ Task> GetResourcePermissionsAsync();
+
Task> GetGroupsAsync();
}
diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs
index 9f527487e0..5e4cdac85a 100644
--- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs
+++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs
@@ -83,13 +83,22 @@ public class PermissionDefinition :
protected internal PermissionDefinition(
[NotNull] string name,
- string? resourceName = null,
+ string resourceName,
+ ILocalizableString? displayName = null,
+ MultiTenancySides multiTenancySide = MultiTenancySides.Both,
+ bool isEnabled = true)
+ : this(name, displayName, multiTenancySide, isEnabled)
+ {
+ ResourceName = Check.NotNull(resourceName, nameof(resourceName));
+ }
+
+ protected internal PermissionDefinition(
+ [NotNull] string name,
ILocalizableString? displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both,
bool isEnabled = true)
{
Name = Check.NotNull(name, nameof(name));
- ResourceName = resourceName;
DisplayName = displayName ?? new FixedLocalizableString(name);
MultiTenancySide = multiTenancySide;
IsEnabled = isEnabled;
@@ -108,7 +117,6 @@ public class PermissionDefinition :
{
var child = new PermissionDefinition(
name,
- null,
displayName,
multiTenancySide,
isEnabled)
diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs
index 394cdb9d82..83ffda1f80 100644
--- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs
+++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Localization;
+using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Authorization.Permissions;
@@ -11,17 +12,20 @@ public class PermissionDefinitionContext : IPermissionDefinitionContext
public Dictionary Groups { get; }
+ public Dictionary ResourcePermissions { get; }
+
internal IPermissionDefinitionProvider? CurrentProvider { get; set; }
public static class KnownPropertyNames
{
public const string CurrentProviderName = "_CurrentProviderName";
}
-
+
public PermissionDefinitionContext(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
Groups = new Dictionary();
+ ResourcePermissions = new Dictionary();
}
public virtual PermissionGroupDefinition AddGroup(
@@ -43,7 +47,7 @@ public class PermissionDefinitionContext : IPermissionDefinitionContext
}
Groups[name] = group;
-
+
return group;
}
@@ -51,37 +55,23 @@ public class PermissionDefinitionContext : IPermissionDefinitionContext
public virtual PermissionGroupDefinition GetGroup([NotNull] string name)
{
var group = GetGroupOrNull(name);
-
- if (group == null)
- {
- throw new AbpException($"Could not find a permission definition group with the given name: {name}");
- }
-
- return group;
+ return group ?? throw new AbpException($"Could not find a permission definition group with the given name: {name}");
}
public virtual PermissionGroupDefinition? GetGroupOrNull([NotNull] string name)
{
Check.NotNull(name, nameof(name));
-
- if (!Groups.ContainsKey(name))
- {
- return null;
- }
-
- return Groups[name];
+ return Groups.GetOrDefault(name);
}
public virtual void RemoveGroup(string name)
{
Check.NotNull(name, nameof(name));
- if (!Groups.ContainsKey(name))
+ if (!Groups.Remove(name))
{
throw new AbpException($"Not found permission group with name: {name}");
}
-
- Groups.Remove(name);
}
public virtual PermissionDefinition? GetPermissionOrNull([NotNull] string name)
@@ -100,4 +90,49 @@ public class PermissionDefinitionContext : IPermissionDefinitionContext
return null;
}
+
+ public virtual PermissionDefinition AddResourcePermission(
+ string name,
+ string resourceName,
+ ILocalizableString? displayName = null,
+ MultiTenancySides multiTenancySide = MultiTenancySides.Both,
+ bool isEnabled = true)
+ {
+ Check.NotNull(name, nameof(name));
+
+ if (ResourcePermissions.ContainsKey(name))
+ {
+ throw new AbpException($"There is already an existing resource permission with name: {name}");
+ }
+
+ var permission = new PermissionDefinition(
+ name,
+ resourceName,
+ displayName,
+ multiTenancySide,
+ isEnabled)
+ {
+ [KnownPropertyNames.CurrentProviderName] = CurrentProvider?.GetType().FullName
+ };
+
+ ResourcePermissions[name] = permission;
+
+ return permission;
+ }
+
+ public virtual PermissionDefinition? GetResourcePermissionOrNull([NotNull] string name)
+ {
+ Check.NotNull(name, nameof(name));
+ return ResourcePermissions.GetOrDefault(name);
+ }
+
+ public virtual void RemoveResourcePermission([NotNull] string name)
+ {
+ Check.NotNull(name, nameof(name));
+
+ if (!ResourcePermissions.Remove(name))
+ {
+ throw new AbpException($"Not found resource permission with name: {name}");
+ }
+ }
}
diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs
index a064245488..0ad2dca099 100644
--- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs
+++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionGroupDefinition.cs
@@ -53,40 +53,9 @@ public class PermissionGroupDefinition : ICanAddChildPermission
ILocalizableString? displayName = null,
MultiTenancySides multiTenancySide = MultiTenancySides.Both,
bool isEnabled = true)
- {
- return AddPermission(
- name,
- null,
- displayName,
- multiTenancySide,
- isEnabled);
- }
-
- public virtual PermissionDefinition AddResourcePermission(
- [NotNull] string name,
- [NotNull] string resourceName,
- ILocalizableString? displayName = null,
- MultiTenancySides multiTenancySide = MultiTenancySides.Both,
- bool isEnabled = true)
- {
- return AddPermission(
- name,
- resourceName,
- displayName,
- multiTenancySide,
- isEnabled);
- }
-
- protected virtual PermissionDefinition AddPermission(
- [NotNull] string name,
- string? resourceName,
- ILocalizableString? displayName = null,
- MultiTenancySides multiTenancySide = MultiTenancySides.Both,
- bool isEnabled = true)
{
var permission = new PermissionDefinition(
name,
- resourceName,
displayName,
multiTenancySide,
isEnabled
diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/ResourcePermissionRequirement.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/ResourcePermissionRequirement.cs
new file mode 100644
index 0000000000..03658f3e90
--- /dev/null
+++ b/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}";
+ }
+}
diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IDynamicPermissionDefinitionStore.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IDynamicPermissionDefinitionStore.cs
index 366ae2e58a..49f798675a 100644
--- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IDynamicPermissionDefinitionStore.cs
+++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IDynamicPermissionDefinitionStore.cs
@@ -8,6 +8,10 @@ public interface IDynamicPermissionDefinitionStore
Task GetOrNullAsync(string name);
Task> GetPermissionsAsync();
-
+
+ Task GetResourcePermissionOrNullAsync(string name);
+
+ Task> GetResourcePermissionsAsync();
+
Task> GetGroupsAsync();
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IStaticPermissionDefinitionStore.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IStaticPermissionDefinitionStore.cs
index 4da8423dd3..74899574e7 100644
--- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IStaticPermissionDefinitionStore.cs
+++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IStaticPermissionDefinitionStore.cs
@@ -8,6 +8,10 @@ public interface IStaticPermissionDefinitionStore
Task GetOrNullAsync(string name);
Task> GetPermissionsAsync();
-
+
+ Task GetResourcePermissionOrNullAsync(string name);
+
+ Task> GetResourcePermissionsAsync();
+
Task> GetGroupsAsync();
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullDynamicPermissionDefinitionStore.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullDynamicPermissionDefinitionStore.cs
index 5b13288153..4ea7990abd 100644
--- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullDynamicPermissionDefinitionStore.cs
+++ b/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
{
private readonly static Task CachedPermissionResult = Task.FromResult((PermissionDefinition?)null);
-
+
private readonly static Task> CachedPermissionsResult =
Task.FromResult((IReadOnlyList)Array.Empty().ToImmutableList());
+ private readonly static Task CachedResourcePermissionResult = Task.FromResult((PermissionDefinition?)null);
+
+ private readonly static Task> CachedResourcePermissionsResult =
+ Task.FromResult((IReadOnlyList)Array.Empty().ToImmutableList());
+
private readonly static Task> CachedGroupsResult =
Task.FromResult((IReadOnlyList)Array.Empty().ToImmutableList());
@@ -26,8 +31,18 @@ public class NullDynamicPermissionDefinitionStore : IDynamicPermissionDefinition
return CachedPermissionsResult;
}
+ public Task GetResourcePermissionOrNullAsync(string name)
+ {
+ return CachedResourcePermissionResult;
+ }
+
+ public Task> GetResourcePermissionsAsync()
+ {
+ return CachedResourcePermissionsResult;
+ }
+
public Task> GetGroupsAsync()
{
return CachedGroupsResult;
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionManager.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionManager.cs
index 23f9e7883e..41c261de49 100644
--- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionManager.cs
+++ b/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));
- return await _staticStore.GetOrNullAsync(name) ??
+ return await _staticStore.GetOrNullAsync(name) ??
await _dynamicStore.GetOrNullAsync(name);
}
+ public virtual async Task GetResourcePermissionAsync(string name)
+ {
+ var permission = await GetResourcePermissionOrNullAsync(name);
+ if (permission == null)
+ {
+ throw new AbpException("Undefined permission: " + name);
+ }
+
+ return permission;
+ }
+
+ public virtual async Task GetResourcePermissionOrNullAsync(string name)
+ {
+ Check.NotNull(name, nameof(name));
+
+ return await _staticStore.GetResourcePermissionOrNullAsync(name) ??
+ await _dynamicStore.GetResourcePermissionOrNullAsync(name);
+ }
+
public virtual async Task> GetPermissionsAsync()
{
var staticPermissions = await _staticStore.GetPermissionsAsync();
var staticPermissionNames = staticPermissions
.Select(p => p.Name)
.ToImmutableHashSet();
-
+
var dynamicPermissions = await _dynamicStore.GetPermissionsAsync();
/* We prefer static permissions over dynamics */
@@ -53,13 +72,28 @@ public class PermissionDefinitionManager : IPermissionDefinitionManager, ITransi
).ToImmutableList();
}
- public async Task> GetGroupsAsync()
+ public virtual async Task> 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> GetGroupsAsync()
{
var staticGroups = await _staticStore.GetGroupsAsync();
var staticGroupNames = staticGroups
.Select(p => p.Name)
.ToImmutableHashSet();
-
+
var dynamicGroups = await _dynamicStore.GetGroupsAsync();
/* We prefer static groups over dynamics */
@@ -67,4 +101,4 @@ public class PermissionDefinitionManager : IPermissionDefinitionManager, ITransi
dynamicGroups.Where(d => !staticGroupNames.Contains(d.Name))
).ToImmutableList();
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/StaticPermissionDefinitionStore.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/StaticPermissionDefinitionStore.cs
index 4e6ff0d11c..938aaf3440 100644
--- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/StaticPermissionDefinitionStore.cs
+++ b/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
{
- protected IDictionary PermissionGroupDefinitions => _lazyPermissionGroupDefinitions.Value;
- private readonly Lazy> _lazyPermissionGroupDefinitions;
+ protected IDictionary PermissionGroupDefinitions => _lazyPermissionGroupDefinitions.Value.Item1;
+ private readonly Lazy<(Dictionary, Dictionary)> _lazyPermissionGroupDefinitions;
protected IDictionary PermissionDefinitions => _lazyPermissionDefinitions.Value;
private readonly Lazy> _lazyPermissionDefinitions;
+ protected IDictionary ResourcePermissionDefinitions => _lazyPermissionGroupDefinitions.Value.Item2;
+
protected AbpPermissionOptions Options { get; }
private readonly IServiceProvider _serviceProvider;
@@ -33,12 +35,12 @@ public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore,
isThreadSafe: true
);
- _lazyPermissionGroupDefinitions = new Lazy>(
+ _lazyPermissionGroupDefinitions = new Lazy<(Dictionary, Dictionary)>(
CreatePermissionGroupDefinitions,
isThreadSafe: true
);
}
-
+
protected virtual Dictionary CreatePermissionDefinitions()
{
var permissions = new Dictionary();
@@ -71,7 +73,7 @@ public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore,
}
}
- protected virtual Dictionary CreatePermissionGroupDefinitions()
+ protected virtual (Dictionary, Dictionary) CreatePermissionGroupDefinitions()
{
using (var scope = _serviceProvider.CreateScope())
{
@@ -99,10 +101,10 @@ public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore,
context.CurrentProvider = provider;
provider.PostDefine(context);
}
-
+
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));
}
-
+
public virtual Task> GetPermissionsAsync()
{
return Task.FromResult>(
@@ -118,10 +120,22 @@ public class StaticPermissionDefinitionStore : IStaticPermissionDefinitionStore,
);
}
+ public virtual Task GetResourcePermissionOrNullAsync(string name)
+ {
+ return Task.FromResult(ResourcePermissionDefinitions.GetOrDefault(name));
+ }
+
+ public virtual Task> GetResourcePermissionsAsync()
+ {
+ return Task.FromResult>(
+ ResourcePermissionDefinitions.Values.ToImmutableList()
+ );
+ }
+
public Task> GetGroupsAsync()
{
return Task.FromResult>(
PermissionGroupDefinitions.Values.ToImmutableList()
);
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Microsoft/Extensions/DependencyInjection/EntityResourcePermissionAuthorizationExtensions.cs b/framework/src/Volo.Abp.Ddd.Domain/Microsoft/Extensions/DependencyInjection/EntityResourcePermissionAuthorizationExtensions.cs
new file mode 100644
index 0000000000..e392d6378d
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Microsoft/Extensions/DependencyInjection/EntityResourcePermissionAuthorizationExtensions.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Authorization;
+using Volo.Abp.Authorization.Permissions.Resources;
+
+namespace Microsoft.Extensions.DependencyInjection;
+
+public static class ResourcePermissionExtenstions
+{
+ public static IServiceCollection AddEntityResourcePermissionAuthorization(this IServiceCollection services)
+ {
+ services.AddSingleton();
+ return services;
+ }
+}
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionRequirementHandler.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionRequirementHandler.cs
new file mode 100644
index 0000000000..aff721d90e
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionRequirementHandler.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Volo.Abp.Domain.Entities;
+
+namespace Volo.Abp.Authorization.Permissions.Resources;
+
+public class EntityResourcePermissionRequirementHandler : AuthorizationHandler
+{
+ protected readonly IResourcePermissionChecker PermissionChecker;
+
+ protected EntityResourcePermissionRequirementHandler(IResourcePermissionChecker permissionChecker)
+ {
+ PermissionChecker = permissionChecker;
+ }
+ protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ResourcePermissionRequirement requirement, IEntity? resource)
+ {
+ if (resource == null)
+ {
+ return;
+ }
+
+ var resourceName = resource.GetType().FullName!;
+ var resourceKey = resource.GetKeys().JoinAsString(",");
+ if (await PermissionChecker.IsGrantedAsync(context.User, requirement.PermissionName, resourceName, resourceKey))
+ {
+ context.Succeed(requirement);
+ }
+ }
+}