diff --git a/docs/en/Background-Jobs-Hangfire.md b/docs/en/Background-Jobs-Hangfire.md index cfa2e12a6b..a690d9d17b 100644 --- a/docs/en/Background-Jobs-Hangfire.md +++ b/docs/en/Background-Jobs-Hangfire.md @@ -79,3 +79,26 @@ After you have installed these NuGet packages, you need to configure your projec } ```` + +### Dashboard Authorization + +Hangfire Dashboard provides information about your background jobs, including method names and serialized arguments as well as gives you an opportunity to manage them by performing different actions – retry, delete, trigger, etc. So it is important to restrict access to the Dashboard. +To make it secure by default, only local requests are allowed, however you can change this by following the [official documentation](http://docs.hangfire.io/en/latest/configuration/using-dashboard.html) of Hangfire. + +You can integrate the Hangfire dashboard to [ABP authorization system](Authorization.md) using the **AbpHangfireAuthorizationFilter** +class. This class is defined in the `Volo.Abp.Hangfire` package. The following example, checks if the current user is logged in to the application: + + app.UseHangfireDashboard("/hangfire", new DashboardOptions + { + AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() } + }); + +If you want to require an additional permission, you can pass it into the constructor as below: + + app.UseHangfireDashboard("/hangfire", new DashboardOptions + { + AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter("MyHangFireDashboardPermissionName") } + }); + +**Important**: `UseHangfireDashboard` should be called after the authentication middleware in your `Startup` class (probably at the last line). Otherwise, +authorization will always fail! diff --git a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj index 4ec9d0a3b5..6b598d0edd 100644 --- a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj +++ b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj @@ -19,6 +19,7 @@ + diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs new file mode 100644 index 0000000000..15fbb4f60c --- /dev/null +++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs @@ -0,0 +1,46 @@ +using System; +using System.Threading.Tasks; +using Hangfire.Dashboard; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Users; + +namespace Volo.Abp.Hangfire +{ + public class AbpHangfireAuthorizationFilter : IDashboardAsyncAuthorizationFilter + { + private readonly string _requiredPermissionName; + + public AbpHangfireAuthorizationFilter(string requiredPermissionName = null) + { + _requiredPermissionName = requiredPermissionName; + } + + public async Task AuthorizeAsync(DashboardContext context) + { + if (!IsLoggedIn(context)) + { + return false; + } + + if (_requiredPermissionName.IsNullOrEmpty()) + { + return true; + } + + return await IsPermissionGrantedAsync(context, _requiredPermissionName); + } + + private static bool IsLoggedIn(DashboardContext context) + { + var currentUser = context.GetHttpContext().RequestServices.GetRequiredService(); + return currentUser.IsAuthenticated; + } + + private static async Task IsPermissionGrantedAsync(DashboardContext context, string requiredPermissionName) + { + var permissionChecker = context.GetHttpContext().RequestServices.GetRequiredService(); + return await permissionChecker.IsGrantedAsync(requiredPermissionName); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs index d69edb0b5d..1628d2f37f 100644 --- a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs +++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs @@ -1,10 +1,12 @@ using Hangfire; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Volo.Abp.Authorization; using Volo.Abp.Modularity; namespace Volo.Abp.Hangfire { + [DependsOn(typeof(AbpAuthorizationAbstractionsModule))] public class AbpHangfireModule : AbpModule { private BackgroundJobServer _backgroundJobServer;