From 1493b3ff63c63757b6c09f8d91dd3c7ab8b553d9 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 20 Jun 2025 13:25:14 +0800 Subject: [PATCH 1/4] Enhance AbpHangfireAuthorizationFilter to support policy requirements --- .../background-jobs/hangfire.md | 16 ++++-- .../AbpHangfireAuthorizationFilter.cs | 50 +++++++++---------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/docs/en/framework/infrastructure/background-jobs/hangfire.md b/docs/en/framework/infrastructure/background-jobs/hangfire.md index f5991ee19b..87fa96fcae 100644 --- a/docs/en/framework/infrastructure/background-jobs/hangfire.md +++ b/docs/en/framework/infrastructure/background-jobs/hangfire.md @@ -159,14 +159,24 @@ app.UseAbpHangfireDashboard("/hangfire", options => `AbpHangfireAuthorizationFilter` class has the following fields: * **`enableTenant` (`bool`, default: `false`):** Enables/disables accessing the Hangfire dashboard on tenant users. -* **`requiredPermissionName` (`string`, default: `null`):** Hangfire dashboard is accessible only if the current user has the specified permission. In this case, if we specify a permission name, we don't need to set `enableTenant` `true` because the permission system already does it. +* **`requiredPermissionName` (`string`, default: `null`):** Hangfire dashboard is accessible only if the current user has the specified permission. +* **`requiredRoleNames` (`string[]`, default: `null`):** Hangfire dashboard is accessible only if the current user has one of the specified roles. -If you want to require an additional permission, you can pass it into the constructor as below: +If you want to require more policies you can use the `PolicyBuilder` property of the `AbpHangfireAuthorizationFilter` class. ```csharp app.UseAbpHangfireDashboard("/hangfire", options => { - options.AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter(requiredPermissionName: "MyHangFireDashboardPermissionName") }; + var hangfireAuthorizationFilter = new AbpHangfireAuthorizationFilter(requiredPermissionName: "MyHangFireDashboardPermissionName"); + + //hangfireAuthorizationFilter.PolicyBuilder.RequireClaim("my_custom_claim", "my_custom_value"); + //hangfireAuthorizationFilter.PolicyBuilder.RequireRole(); + //hangfireAuthorizationFilter.PolicyBuilder.Requirements.Add(new YourCustomRequirement()); + + options.AsyncAuthorization = new[] + { + hangfireAuthorizationFilter + }; }); ``` diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs index bd65b22dba..d49c211ee5 100644 --- a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs +++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs @@ -1,53 +1,49 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Hangfire.Dashboard; +using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Authorization.Permissions; -using Volo.Abp.Users; +using Volo.Abp.Authorization; +using Volo.Abp.MultiTenancy; namespace Volo.Abp.Hangfire; public class AbpHangfireAuthorizationFilter : IDashboardAsyncAuthorizationFilter { private readonly bool _enableTenant; - private readonly string? _requiredPermissionName; + private readonly AuthorizationPolicyBuilder _policyBuilder; - public AbpHangfireAuthorizationFilter(bool enableTenant = false, string? requiredPermissionName = null) - { - _enableTenant = requiredPermissionName.IsNullOrWhiteSpace() ? enableTenant : true; - _requiredPermissionName = requiredPermissionName; - } + public virtual AuthorizationPolicyBuilder PolicyBuilder => _policyBuilder; - public async Task AuthorizeAsync(DashboardContext context) + public AbpHangfireAuthorizationFilter(bool enableTenant = false, string? requiredPermissionName = null, params string[]? requiredRoleNames) { - if (!IsLoggedIn(context, _enableTenant)) + _enableTenant = enableTenant; + _policyBuilder = new AuthorizationPolicyBuilder().RequireAuthenticatedUser(); + if (!requiredPermissionName.IsNullOrWhiteSpace()) { - return false; + _policyBuilder.Requirements.Add(new PermissionRequirement(requiredPermissionName)); } - if (_requiredPermissionName.IsNullOrEmpty()) + if (!requiredRoleNames.IsNullOrEmpty()) { - return true; + foreach (var roleName in requiredRoleNames!) + { + _policyBuilder.RequireRole(roleName); + } } - - return await IsPermissionGrantedAsync(context, _requiredPermissionName!); } - private static bool IsLoggedIn(DashboardContext context, bool enableTenant) + public virtual async Task AuthorizeAsync(DashboardContext context) { - var currentUser = context.GetHttpContext().RequestServices.GetRequiredService(); - - if (!enableTenant) + var currentTenant = context.GetHttpContext().RequestServices.GetRequiredService(); + if (currentTenant.IsAvailable && !_enableTenant) { - return currentUser.IsAuthenticated && !currentUser.TenantId.HasValue; + return false; } - return currentUser.IsAuthenticated; - } - - private static async Task IsPermissionGrantedAsync(DashboardContext context, string requiredPermissionName) - { - var permissionChecker = context.GetHttpContext().RequestServices.GetRequiredService(); - return await permissionChecker.IsGrantedAsync(requiredPermissionName); + var authorizationService = context.GetHttpContext().RequestServices.GetRequiredService(); + var authorizationPolicy = _policyBuilder.Build(); + return (await authorizationService.AuthorizeAsync(context.GetHttpContext().User, authorizationPolicy)).Succeeded; } } From 713cd3782c413118ff4a7bd58d67f1f51ac6727f Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 20 Jun 2025 13:30:19 +0800 Subject: [PATCH 2/4] Update hangfire.md --- .../en/framework/infrastructure/background-jobs/hangfire.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/framework/infrastructure/background-jobs/hangfire.md b/docs/en/framework/infrastructure/background-jobs/hangfire.md index 87fa96fcae..43029647f5 100644 --- a/docs/en/framework/infrastructure/background-jobs/hangfire.md +++ b/docs/en/framework/infrastructure/background-jobs/hangfire.md @@ -162,15 +162,15 @@ app.UseAbpHangfireDashboard("/hangfire", options => * **`requiredPermissionName` (`string`, default: `null`):** Hangfire dashboard is accessible only if the current user has the specified permission. * **`requiredRoleNames` (`string[]`, default: `null`):** Hangfire dashboard is accessible only if the current user has one of the specified roles. -If you want to require more policies you can use the `PolicyBuilder` property of the `AbpHangfireAuthorizationFilter` class. +If you want to require more policies, You can use the `PolicyBuilder` property of the `AbpHangfireAuthorizationFilter` class. ```csharp app.UseAbpHangfireDashboard("/hangfire", options => { var hangfireAuthorizationFilter = new AbpHangfireAuthorizationFilter(requiredPermissionName: "MyHangFireDashboardPermissionName"); - //hangfireAuthorizationFilter.PolicyBuilder.RequireClaim("my_custom_claim", "my_custom_value"); - //hangfireAuthorizationFilter.PolicyBuilder.RequireRole(); + //hangfireAuthorizationFilter.PolicyBuilder.AddRequirements(new PermissionRequirement("YourPermissionName")); + //hangfireAuthorizationFilter.PolicyBuilder.RequireRole("YourCustomRole"); //hangfireAuthorizationFilter.PolicyBuilder.Requirements.Add(new YourCustomRequirement()); options.AsyncAuthorization = new[] From 35db2e0c43e057a7a2f51d5dda733118b58cdcd8 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 20 Jun 2025 13:31:22 +0800 Subject: [PATCH 3/4] Update hangfire.md --- docs/en/framework/infrastructure/background-jobs/hangfire.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/framework/infrastructure/background-jobs/hangfire.md b/docs/en/framework/infrastructure/background-jobs/hangfire.md index 43029647f5..23c9c5ccd7 100644 --- a/docs/en/framework/infrastructure/background-jobs/hangfire.md +++ b/docs/en/framework/infrastructure/background-jobs/hangfire.md @@ -160,7 +160,7 @@ app.UseAbpHangfireDashboard("/hangfire", options => * **`enableTenant` (`bool`, default: `false`):** Enables/disables accessing the Hangfire dashboard on tenant users. * **`requiredPermissionName` (`string`, default: `null`):** Hangfire dashboard is accessible only if the current user has the specified permission. -* **`requiredRoleNames` (`string[]`, default: `null`):** Hangfire dashboard is accessible only if the current user has one of the specified roles. +* **`requiredRoleNames` (`string[]`, default: `[]`):** Hangfire dashboard is accessible only if the current user has one of the specified roles. If you want to require more policies, You can use the `PolicyBuilder` property of the `AbpHangfireAuthorizationFilter` class. From ea41c1ba79a907d73b3a677f4d241608b6ac315d Mon Sep 17 00:00:00 2001 From: EngincanV Date: Fri, 20 Jun 2025 11:05:22 +0300 Subject: [PATCH 4/4] Update hangfire.md --- docs/en/framework/infrastructure/background-jobs/hangfire.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/framework/infrastructure/background-jobs/hangfire.md b/docs/en/framework/infrastructure/background-jobs/hangfire.md index 23c9c5ccd7..3d10866208 100644 --- a/docs/en/framework/infrastructure/background-jobs/hangfire.md +++ b/docs/en/framework/infrastructure/background-jobs/hangfire.md @@ -162,7 +162,7 @@ app.UseAbpHangfireDashboard("/hangfire", options => * **`requiredPermissionName` (`string`, default: `null`):** Hangfire dashboard is accessible only if the current user has the specified permission. * **`requiredRoleNames` (`string[]`, default: `[]`):** Hangfire dashboard is accessible only if the current user has one of the specified roles. -If you want to require more policies, You can use the `PolicyBuilder` property of the `AbpHangfireAuthorizationFilter` class. +If you want to require more policies, you can use the `PolicyBuilder` property of the `AbpHangfireAuthorizationFilter` class. ```csharp app.UseAbpHangfireDashboard("/hangfire", options =>