From 93d86728ab6b2c635168c3f3a205fc40e33f32e1 Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Wed, 16 Jun 2021 08:55:29 +0800 Subject: [PATCH] Enhanced configuration of Hangfire --- .gitignore | 1 + aspnet-core/LINGYUN.MicroService.Messages.sln | 39 +++- ...LINGYUN.Abp.BackgroundJobs.Hangfire.csproj | 4 + .../AbpBackgroundJobsHangfireModule.cs | 34 +++- .../Hangfire/HangfireBackgroundJobManager.cs | 4 +- .../Hangfire/HangfireJobExecutionAdapter.cs | 6 +- .../IBackgroundJobManagerExtensions.cs | 7 +- .../LINGYUN.Abp.BackgroundJobs.csproj | 14 -- .../RetryAsyncBackgroundJobArgs.cs | 43 ----- .../RetryAsyncBackgroundJobBase.cs | 80 -------- ...GYUN.Abp.BackgroundWorkers.Hangfire.csproj | 15 ++ .../AbpBackgroundWorkersHangfireModule.cs | 19 ++ .../Abp/BackgroundWorkers/Hangfire/Check.cs | 25 +++ .../Hangfire/CronGenerator.cs | 171 ++++++++++++++++++ .../HangfireBackgroundWorkerAdapter.cs | 47 +++++ .../HangfireBackgroundWorkerManager.cs | 63 +++++++ .../IHangfireBackgroundWorkerAdapter.cs | 10 + .../LINGYUN.Abp.Hangfire.Dashboard.csproj | 23 +++ .../Dashboard/AbpHangfireDashboardModule.cs | 36 ++++ .../AbpHangfireDashboardOptionsProvider.cs | 32 ++++ .../DashboardAuthorizationFilter.cs | 32 ++++ ...reDashboardPermissionDefinitionProvider.cs | 33 ++++ .../HangfireDashboardPermissions.cs | 15 ++ .../Localization/HangfireDashboardResource.cs | 9 + .../Dashboard/Localization/Resources/en.json | 7 + .../Localization/Resources/zh-Hans.json | 7 + ...angfireAuthoricationMiddlewareExtension.cs | 12 ++ .../Http/HangfireAuthoricationMiddleware.cs | 27 +++ .../MySql/AbpHangfireMySqlStorageModule.cs | 4 +- .../AbpHangfireSqlServerStorageModule.cs | 4 +- .../Class1.cs | 8 + .../LINGYUN.Abp.Notifications.Workers.csproj | 14 ++ .../Workers/AbpNotificationsWorkersModule.cs | 10 + .../LINGYUN.Abp.Notifications.csproj | 3 +- .../Notifications/AbpNotificationModule.cs | 5 +- .../AbpMessageServiceHttpApiHostModule.cs | 55 ++---- .../HangfireDashboardAuthorizationFilter.cs | 73 -------- .../NotificationCleanupExpritionJob.cs | 38 ---- .../NotificationCleanupExpritionJobArgs.cs | 23 --- .../Hangfire/DashboardOptionsExtensions.cs | 74 -------- .../HangfireApplicationBuilderExtensions.cs | 47 ----- .../Hangfire/HangfireDashboardRouteOptions.cs | 74 -------- .../Hangfire/HangfireJwtTokenMiddleware.cs | 31 ---- ...YUN.Abp.MessageService.HttpApi.Host.csproj | 1 + 44 files changed, 720 insertions(+), 559 deletions(-) rename aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/{LINGYUN/Abp/BackgroundJobs/Hangfire => Volo/Abp/BackgroundJobs}/IBackgroundJobManagerExtensions.cs (86%) delete mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN.Abp.BackgroundJobs.csproj delete mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobArgs.cs delete mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobBase.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/Check.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/CronGenerator.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerAdapter.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/IHangfireBackgroundWorkerAdapter.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN.Abp.Hangfire.Dashboard.csproj create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/AbpHangfireDashboardModule.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/AbpHangfireDashboardOptionsProvider.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/DashboardAuthorizationFilter.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/HangfireDashboardPermissionDefinitionProvider.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/HangfireDashboardPermissions.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/HangfireDashboardResource.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/Resources/en.json create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/Resources/zh-Hans.json create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/Microsoft/AspNetCore/Builder/ApplicationBuilderAbpHangfireAuthoricationMiddlewareExtension.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/Microsoft/AspNetCore/Http/HangfireAuthoricationMiddleware.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/Class1.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/LINGYUN.Abp.Notifications.Workers.csproj create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/LINGYUN/Abp/Notifications/Workers/AbpNotificationsWorkersModule.cs delete mode 100644 aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Authorization/HangfireDashboardAuthorizationFilter.cs delete mode 100644 aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/BackgroundJobs/NotificationCleanupExpritionJob.cs delete mode 100644 aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/BackgroundJobs/NotificationCleanupExpritionJobArgs.cs delete mode 100644 aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/DashboardOptionsExtensions.cs delete mode 100644 aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireApplicationBuilderExtensions.cs delete mode 100644 aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireDashboardRouteOptions.cs delete mode 100644 aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireJwtTokenMiddleware.cs diff --git a/.gitignore b/.gitignore index 5989a3cbc..a939b365f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ appsettings.json appsettings.*.json tempkey.jwk .vs +Publish /tests/e2e/videos/ /tests/e2e/screenshots/ diff --git a/aspnet-core/LINGYUN.MicroService.Messages.sln b/aspnet-core/LINGYUN.MicroService.Messages.sln index be9e5a1a2..87dd3b544 100644 --- a/aspnet-core/LINGYUN.MicroService.Messages.sln +++ b/aspnet-core/LINGYUN.MicroService.Messages.sln @@ -67,9 +67,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.W EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.EntityFrameworkCore.Tests\LINGYUN.Abp.EntityFrameworkCore.Tests.csproj", "{25267137-08BE-44A6-9F7E-7783CC8C62E8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests.csproj", "{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests.csproj", "{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.MessageService.Domain.Tests", "tests\LINGYUN.Abp.MessageService.Domain.Tests\LINGYUN.Abp.MessageService.Domain.Tests.csproj", "{097319B9-D062-4A54-8F8C-001C180E2CB3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Domain.Tests", "tests\LINGYUN.Abp.MessageService.Domain.Tests\LINGYUN.Abp.MessageService.Domain.Tests.csproj", "{097319B9-D062-4A54-8F8C-001C180E2CB3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundJobs.Hangfire", "modules\common\LINGYUN.Abp.BackgroundJobs.Hangfire\LINGYUN.Abp.BackgroundJobs.Hangfire.csproj", "{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Hangfire.Storage.MySql", "modules\common\LINGYUN.Abp.Hangfire.MySqlStorage\LINGYUN.Abp.Hangfire.Storage.MySql.csproj", "{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Hangfire.Dashboard", "modules\common\LINGYUN.Abp.Hangfire.Dashboard\LINGYUN.Abp.Hangfire.Dashboard.csproj", "{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundWorkers.Hangfire", "modules\common\LINGYUN.Abp.BackgroundWorkers.Hangfire\LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj", "{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EventBus.CAP", "modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj", "{C49B50D4-5D63-47E6-82F7-E742181CF9DE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -189,6 +199,26 @@ Global {097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU {097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU {097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.Build.0 = Release|Any CPU + {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.Build.0 = Release|Any CPU + {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.Build.0 = Release|Any CPU + {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.Build.0 = Release|Any CPU + {32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.Build.0 = Release|Any CPU + {C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -225,6 +255,11 @@ Global {25267137-08BE-44A6-9F7E-7783CC8C62E8} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {097319B9-D062-4A54-8F8C-001C180E2CB3} = {42800C56-9473-4B96-BF29-1B0F25C867F4} + {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97} = {C00828FB-E7D5-4086-BA50-02022594AB73} + {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4} = {C00828FB-E7D5-4086-BA50-02022594AB73} + {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48} = {C00828FB-E7D5-4086-BA50-02022594AB73} + {32D4DB5D-74D1-4166-85EA-B2D8F14B8058} = {C00828FB-E7D5-4086-BA50-02022594AB73} + {C49B50D4-5D63-47E6-82F7-E742181CF9DE} = {C00828FB-E7D5-4086-BA50-02022594AB73} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6238659A-7267-49B9-A499-8746BDEED6B8} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN.Abp.BackgroundJobs.Hangfire.csproj b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN.Abp.BackgroundJobs.Hangfire.csproj index 90daaaa9a..ac4893217 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN.Abp.BackgroundJobs.Hangfire.csproj +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN.Abp.BackgroundJobs.Hangfire.csproj @@ -11,5 +11,9 @@ + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs index 0fc08ae96..436b606b8 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs @@ -1,7 +1,10 @@ using Hangfire; +using Hangfire.Dashboard; +using LINGYUN.Abp.Hangfire.Dashboard; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System; +using System.Linq; using Volo.Abp; using Volo.Abp.BackgroundJobs; using Volo.Abp.Hangfire; @@ -11,14 +14,39 @@ namespace LINGYUN.Abp.BackgroundJobs.Hangfire { [DependsOn( typeof(AbpBackgroundJobsAbstractionsModule), - typeof(AbpHangfireModule) + typeof(AbpHangfireModule), + typeof(AbpHangfireDashboardModule) )] public class AbpBackgroundJobsHangfireModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.DisplayNameFunc = (dashboardContext, job) => + { + if (job.Args.Count == 0) + { + return job.Type.FullName; + + //if (job.Type.GenericTypeArguments.Length == 0) + //{ + // return job.Type.FullName; + //} + //// TODO: 把特性作为任务名称? + //return BackgroundJobNameAttribute.GetName(job.Type.GenericTypeArguments[0]); + } + var context = dashboardContext.GetHttpContext(); + var options = context.RequestServices.GetRequiredService>().Value; + return options.GetJob(job.Args.First().GetType()).JobName; + }; + }); + } + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) { - var options = context.ServiceProvider.GetRequiredService>().Value; - if (!options.IsJobExecutionEnabled) + var jobOptions = context.ServiceProvider.GetRequiredService>().Value; + if (!jobOptions.IsJobExecutionEnabled) { var hangfireOptions = context.ServiceProvider.GetRequiredService>().Value; hangfireOptions.BackgroundJobServerFactory = CreateOnlyEnqueueJobServer; diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs index 435f0192f..6012742e1 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs @@ -16,7 +16,7 @@ namespace LINGYUN.Abp.BackgroundJobs.Hangfire { return Task.FromResult( BackgroundJob.Enqueue>( - adapter => adapter.Execute(args) + adapter => adapter.ExecuteAsync(args) ) ); } @@ -24,7 +24,7 @@ namespace LINGYUN.Abp.BackgroundJobs.Hangfire { return Task.FromResult( BackgroundJob.Schedule>( - adapter => adapter.Execute(args), + adapter => adapter.ExecuteAsync(args), delay.Value ) ); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs index 97cb8dc4a..588c4cff0 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs @@ -1,8 +1,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.BackgroundJobs; -using Volo.Abp.Threading; namespace LINGYUN.Abp.BackgroundJobs.Hangfire { @@ -22,7 +22,7 @@ namespace LINGYUN.Abp.BackgroundJobs.Hangfire Options = options.Value; } - public void Execute(TArgs args) + public async Task ExecuteAsync(TArgs args) { if (!Options.IsJobExecutionEnabled) { @@ -39,7 +39,7 @@ namespace LINGYUN.Abp.BackgroundJobs.Hangfire { var jobType = Options.GetJob(typeof(TArgs)).JobType; var context = new JobExecutionContext(scope.ServiceProvider, jobType, args); - AsyncHelper.RunSync(() => JobExecuter.ExecuteAsync(context)); + await JobExecuter.ExecuteAsync(context); } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/IBackgroundJobManagerExtensions.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/Volo/Abp/BackgroundJobs/IBackgroundJobManagerExtensions.cs similarity index 86% rename from aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/IBackgroundJobManagerExtensions.cs rename to aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/Volo/Abp/BackgroundJobs/IBackgroundJobManagerExtensions.cs index aca3a52ea..3615e3053 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN/Abp/BackgroundJobs/Hangfire/IBackgroundJobManagerExtensions.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/Volo/Abp/BackgroundJobs/IBackgroundJobManagerExtensions.cs @@ -1,10 +1,9 @@ using Hangfire; using JetBrains.Annotations; +using LINGYUN.Abp.BackgroundJobs.Hangfire; using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.BackgroundJobs; -namespace LINGYUN.Abp.BackgroundJobs.Hangfire +namespace Volo.Abp.BackgroundJobs { public static class IBackgroundJobManagerExtensions { @@ -27,7 +26,7 @@ namespace LINGYUN.Abp.BackgroundJobs.Hangfire var jobName = BackgroundJobNameAttribute.GetName(); - RecurringJob.AddOrUpdate>(jobName, adapter => adapter.Execute(args), cron); + RecurringJob.AddOrUpdate>(jobName, adapter => adapter.ExecuteAsync(args), cron); return Task.CompletedTask; } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN.Abp.BackgroundJobs.csproj b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN.Abp.BackgroundJobs.csproj deleted file mode 100644 index 009d6c445..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN.Abp.BackgroundJobs.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - netstandard2.0 - - - - - - - - diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobArgs.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobArgs.cs deleted file mode 100644 index 369ccaf12..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobArgs.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace LINGYUN.Abp.BackgroundJobs -{ - public class RetryAsyncBackgroundJobArgs - { - /// - /// 重试次数 - /// - public int RetryCount { get; set; } = 0; - /// - /// 重试间隔(毫秒) - /// 默认 300000ms = 5min - /// - public double RetryIntervalMillisecond { get; set; } = 300000d; - /// - /// 最大重试次数 - /// 默认 20 - /// - public int MaxRetryCount { get; set; } = 20; - /// - /// 作业参数 - /// - public TArgs JobArgs { get; set; } - - public RetryAsyncBackgroundJobArgs() - { - - } - - public RetryAsyncBackgroundJobArgs(TArgs jobArgs) - { - JobArgs = jobArgs; - } - - public RetryAsyncBackgroundJobArgs(TArgs jobArgs, int retryCount = 0, double interval = 300000d, int maxRetryCount = 20) - { - JobArgs = jobArgs; - - RetryCount = retryCount; - RetryIntervalMillisecond = interval; - MaxRetryCount = maxRetryCount; - } - } -} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobBase.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobBase.cs deleted file mode 100644 index e309e8bbd..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobBase.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using System; -using System.Threading.Tasks; -using Volo.Abp.BackgroundJobs; - -namespace LINGYUN.Abp.BackgroundJobs -{ - public abstract class RetryAsyncBackgroundJobBase : IAsyncBackgroundJob> - { - public ILogger> Logger { get; set; } - - protected IBackgroundJobManager BackgroundJobManager { get; } - - protected RetryAsyncBackgroundJobBase( - IBackgroundJobManager backgroundJobManager) - { - BackgroundJobManager = backgroundJobManager; - - Logger = NullLogger>.Instance; - } - - public async Task ExecuteAsync(RetryAsyncBackgroundJobArgs args) - { - if (args.RetryCount > args.MaxRetryCount) - { - Logger.LogWarning("Job has failed and the maximum number of retries has been reached. The failure callback is about to enter"); - // 任务执行失败次数已达上限,调用用户定义回调,并不再执行 - await OnJobExecuteFailedAsync(args.JobArgs); - return; - } - try - { - // 执行任务 - await ExecuteAsync(args.JobArgs, args.RetryCount); - // 执行完成后回调 - await OnJobExecuteCompletedAsync(args.JobArgs); - } - catch(Exception ex) - { - Logger.LogWarning("Job execution has failed and a retry is imminent"); - Logger.LogWarning("Job running error:{0}", ex.Message); - - // 每次重试 间隔时间增加1.1倍 - var retryInterval = args.RetryIntervalMillisecond * 1.1; - var retryJobArgs = new RetryAsyncBackgroundJobArgs(args.JobArgs, - args.RetryCount + 1, retryInterval, args.MaxRetryCount); - - Logger.LogDebug("Job task is queued for the next execution"); - - // 计算优先级 - BackgroundJobPriority priority = BackgroundJobPriority.Normal; - - if (args.RetryCount <= (args.MaxRetryCount / 2) && - args.RetryCount > (args.MaxRetryCount / 3)) - { - priority = BackgroundJobPriority.BelowNormal; - } - else if (args.RetryCount > (args.MaxRetryCount / 1.5)) - { - priority = BackgroundJobPriority.Low; - } - // 延迟入队,等待下一次运行 - await BackgroundJobManager.EnqueueAsync(retryJobArgs, priority, delay: TimeSpan.FromMilliseconds(retryInterval)); - } - } - - protected abstract Task ExecuteAsync(TArgs args, int retryCount); - - protected virtual Task OnJobExecuteFailedAsync(TArgs args) - { - return Task.CompletedTask; - } - - protected virtual Task OnJobExecuteCompletedAsync(TArgs args) - { - return Task.CompletedTask; - } - } -} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj new file mode 100644 index 000000000..f83b1c87b --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj @@ -0,0 +1,15 @@ + + + + + + netstandard2.0 + + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs new file mode 100644 index 000000000..b1014c313 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.BackgroundWorkers; +using Volo.Abp.Hangfire; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.BackgroundWorkers.Hangfire +{ + [DependsOn( + typeof(AbpBackgroundWorkersModule), + typeof(AbpHangfireModule) + )] + public class AbpBackgroundWorkersHangfireModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSingleton(typeof(HangfireBackgroundWorkerAdapter<>)); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/Check.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/Check.cs new file mode 100644 index 000000000..bf5fc8955 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/Check.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using System; + +namespace LINGYUN.Abp.BackgroundWorkers.Hangfire +{ + internal static class Check + { + public static int Range( + int value, + [InvokerParameterName][NotNull] string parameterName, + int minimum = int.MinValue, + int maximum = int.MaxValue) + { + if (value < minimum) + { + throw new ArgumentException($"{parameterName} must be equal to or lower than {minimum}!", parameterName); + } + if (value > maximum) + { + throw new ArgumentException($"{parameterName} must be equal to or greater than {maximum}!", parameterName); + } + return value; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/CronGenerator.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/CronGenerator.cs new file mode 100644 index 000000000..5d811a383 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/CronGenerator.cs @@ -0,0 +1,171 @@ +using System; + +namespace LINGYUN.Abp.BackgroundWorkers.Hangfire +{ + public class CronGenerator + { + public const long MilliSecondsOfYear = 315_3600_0000L; + public const long MilliSecondsOfMonth = 26_7840_0000L; + public const int MilliSecondsOfWeek = 6_0480_0000; + public const int MilliSecondsOfDays = 8640_0000; + public const int MilliSecondsOfHours = 360_0000; + public const int MilliSecondsOfMinutes = 60000; + + /// + /// 从毫秒计算Cron表达式 + /// + /// + /// + public static string FormMilliseconds(long milliseconds = 1000) + { + if (milliseconds <= 1000) + { + return Seconds(0, 1); + } + + if (milliseconds >= MilliSecondsOfYear) + { + return Year(1, 1, 0, 0, 2001, (int)(milliseconds / MilliSecondsOfYear)); + } + + if (milliseconds >= MilliSecondsOfMonth) + { + return Month(1, 0, 0, 1, (int)(milliseconds / MilliSecondsOfMonth)); + } + + // TODO: 以周为单位的任务Cron + if (milliseconds >= MilliSecondsOfWeek) + { + return Day(0, 0, 1, (int)(milliseconds / MilliSecondsOfWeek)); + } + + if (milliseconds >= MilliSecondsOfDays) + { + return Day(0, 0, 1, (int)(milliseconds / MilliSecondsOfDays)); + } + + if (milliseconds >= MilliSecondsOfHours) + { + return Hour(0, 0, (int)(milliseconds / MilliSecondsOfHours)); + } + + if (milliseconds >= MilliSecondsOfMinutes) + { + return Minute(0, 0, (int)(milliseconds / MilliSecondsOfMinutes)); + } + + return Seconds(0, (int)(milliseconds / 1000)); + } + /// + /// 周期性为秒钟的任务 + /// + /// 第几秒开始,默认为第0秒 + /// 执行周期的间隔,默认为每5秒一次 + /// + public static string Seconds(int second = 0, int interval = 5) + { + Check.Range(second, nameof(second), 0, 59); + + return $"{second}/{interval} * * * * ? "; + } + + /// + /// 周期性为分钟的任务 + /// + /// 第几秒开始,默认为第0秒 + /// 第几分钟开始,默认为第0分钟 + /// 执行周期的间隔,默认为每分钟一次 + /// + public static string Minute(int second = 0, int minute = 0, int interval = 1) + { + Check.Range(second, nameof(second), 0, 59); + Check.Range(minute, nameof(minute), 0, 59); + + return $"{second} {minute}/{interval} * * * ? "; + } + + /// + /// 周期性为小时的任务 + /// + /// 第几分钟开始,默认为第0分钟 + /// 第几小时开始,默认为0点 + /// 执行周期的间隔,默认为每小时一次 + /// + public static string Hour(int minute = 0, int hour = 0, int interval = 1) + { + Check.Range(hour, nameof(hour), 0, 23); + Check.Range(minute, nameof(minute), 0, 59); + + return $"0 {minute} {hour}/{interval} * * ? "; + } + + /// + /// 周期性为天的任务 + /// + /// 第几小时开始,默认从0点开始 + /// 第几分钟开始,默认从第0分钟开始 + /// 第几天开始,默认从第1天开始 + /// 执行周期的间隔,默认为每天一次 + /// + public static string Day(int hour = 0, int minute = 0, int day = 1, int interval = 1) + { + Check.Range(hour, nameof(hour), 0, 23); + Check.Range(minute, nameof(minute), 0, 59); + Check.Range(day, nameof(day), 1, 31); + + return $"0 {minute} {hour} {day}/{interval} * ? "; + } + + /// + /// 周期性为周的任务 + /// + /// 星期几开始,默认从星期一点开始 + /// 第几小时开始,默认从0点开始 + /// 第几分钟开始,默认从第0分钟开始 + /// + public static string Week(DayOfWeek dayOfWeek = DayOfWeek.Monday, int hour = 0, int minute = 0) + { + Check.Range(hour, nameof(hour), 0, 23); + Check.Range(minute, nameof(minute), 0, 59); + + return $"{minute} {hour} * * {dayOfWeek.ToString().Substring(0, 3)}"; + } + + /// + /// 周期性为月的任务 + /// + /// 几号开始,默认从一号开始 + /// 第几小时开始,默认从0点开始 + /// 第几分钟开始,默认从第0分钟开始 + /// 第几月开始,默认从第1月开始 + /// 月份间隔 + /// + public static string Month(int day = 1, int hour = 0, int minute = 0, int month = 1, int interval = 1) + { + Check.Range(hour, nameof(hour), 0, 23); + Check.Range(minute, nameof(minute), 0, 59); + Check.Range(day, nameof(day), 1, 31); + + return $"0 {minute} {hour} {day} {month}/{interval} ?"; + } + + /// + /// 周期性为年的任务 + /// + /// 几月开始,默认从一月开始 + /// 几号开始,默认从一号开始 + /// 第几小时开始,默认从0点开始 + /// 第几年开始,默认从2001年开始 + /// 第几分钟开始,默认从第0分钟开始 + /// + public static string Year(int month = 1, int day = 1, int hour = 0, int minute = 0, int year = 2001, int interval = 1) + { + Check.Range(hour, nameof(hour), 0, 23); + Check.Range(minute, nameof(minute), 0, 59); + Check.Range(day, nameof(day), 1, 31); + Check.Range(month, nameof(month), 1, 12); + + return $"0 {minute} {hour} {day} {month} ? {year}/{interval}"; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerAdapter.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerAdapter.cs new file mode 100644 index 000000000..d8a8c84e5 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerAdapter.cs @@ -0,0 +1,47 @@ +using System.Reflection; +using System.Threading.Tasks; +using Volo.Abp.BackgroundWorkers; + +namespace LINGYUN.Abp.BackgroundWorkers.Hangfire +{ + public class HangfireBackgroundWorkerAdapter : BackgroundWorkerBase, IHangfireBackgroundWorkerAdapter + where TWorker : IBackgroundWorker + { + private readonly MethodInfo _doWorkAsyncMethod; + private readonly MethodInfo _doWorkMethod; + + public HangfireBackgroundWorkerAdapter() + { + _doWorkAsyncMethod = typeof(TWorker).GetMethod("DoWorkAsync", BindingFlags.Instance | BindingFlags.NonPublic); + _doWorkMethod = typeof(TWorker).GetMethod("DoWork", BindingFlags.Instance | BindingFlags.NonPublic); + } + + public virtual async Task ExecuteAsync() + { + var worker = (IBackgroundWorker)ServiceProvider.GetService(typeof(TWorker)); + var workerContext = new PeriodicBackgroundWorkerContext(ServiceProvider); + + switch (worker) + { + case AsyncPeriodicBackgroundWorkerBase asyncWorker: + { + if (_doWorkAsyncMethod != null) + { + await (Task)_doWorkAsyncMethod.Invoke(asyncWorker, new object[] { workerContext }); + } + + break; + } + case PeriodicBackgroundWorkerBase syncWorker: + { + if (_doWorkMethod != null) + { + _doWorkMethod.Invoke(syncWorker, new object[] { workerContext }); + } + + break; + } + } + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs new file mode 100644 index 000000000..b43e4c50b --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs @@ -0,0 +1,63 @@ +using Hangfire; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.BackgroundWorkers; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.BackgroundWorkers.Hangfire +{ + [Dependency(ReplaceServices = true)] + public class HangfireBackgroundWorkerManager : IBackgroundWorkerManager, ISingletonDependency + { + protected IServiceProvider ServiceProvider { get; } + + public HangfireBackgroundWorkerManager( + IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + } + + public void Add(IBackgroundWorker worker) + { + var timer = worker.GetType() + .GetProperty("Timer", BindingFlags.NonPublic | BindingFlags.Instance)? + .GetValue(worker); + + if (timer == null) + { + return; + } + + var period = timer.GetType() + .GetProperty("Period", BindingFlags.Public | BindingFlags.Instance)? + .GetValue(timer)? + .To(); + + if (!period.HasValue) + { + return; + } + + var adapterType = typeof(HangfireBackgroundWorkerAdapter<>).MakeGenericType(worker.GetType()); + var workerAdapter = ServiceProvider.GetRequiredService(adapterType) as IHangfireBackgroundWorkerAdapter; + + RecurringJob.AddOrUpdate( + recurringJobId: worker.GetType().FullName, + methodCall: () => workerAdapter.ExecuteAsync(), + cronExpression: CronGenerator.FormMilliseconds(period.Value)); + } + + public Task StartAsync(CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/IHangfireBackgroundWorkerAdapter.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/IHangfireBackgroundWorkerAdapter.cs new file mode 100644 index 000000000..bda227ea3 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundWorkers.Hangfire/LINGYUN/Abp/BackgroundWorkers/Hangfire/IHangfireBackgroundWorkerAdapter.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using Volo.Abp.BackgroundWorkers; + +namespace LINGYUN.Abp.BackgroundWorkers.Hangfire +{ + public interface IHangfireBackgroundWorkerAdapter : IBackgroundWorker + { + Task ExecuteAsync(); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN.Abp.Hangfire.Dashboard.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN.Abp.Hangfire.Dashboard.csproj new file mode 100644 index 000000000..b203dec70 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN.Abp.Hangfire.Dashboard.csproj @@ -0,0 +1,23 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/AbpHangfireDashboardModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/AbpHangfireDashboardModule.cs new file mode 100644 index 000000000..e43e56759 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/AbpHangfireDashboardModule.cs @@ -0,0 +1,36 @@ +using LINGYUN.Abp.Hangfire.Dashboard.Localization; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Authorization; +using Volo.Abp.Hangfire; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.Hangfire.Dashboard +{ + [DependsOn( + typeof(AbpLocalizationModule), + typeof(AbpAuthorizationModule), + typeof(AbpHangfireModule))] + public class AbpHangfireDashboardModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources.Add(); + }); + + context.Services.AddTransient(serviceProvider => + { + var options = serviceProvider.GetRequiredService().Get(); + return context.Services.ExecutePreConfiguredActions(options); + }); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/AbpHangfireDashboardOptionsProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/AbpHangfireDashboardOptionsProvider.cs new file mode 100644 index 000000000..dd3884fde --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/AbpHangfireDashboardOptionsProvider.cs @@ -0,0 +1,32 @@ +using Hangfire; +using Hangfire.Dashboard; +using LINGYUN.Abp.Hangfire.Dashboard.Authorization; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.Hangfire.Dashboard +{ + public class AbpHangfireDashboardOptionsProvider : ITransientDependency + { + public virtual DashboardOptions Get() + { + return new DashboardOptions + { + Authorization = new IDashboardAuthorizationFilter[] + { + new DashboardAuthorizationFilter() + }, + IsReadOnlyFunc = (context) => + { + var httpContext = context.GetHttpContext(); + var permissionChecker = httpContext.RequestServices.GetRequiredService(); + + return !AsyncHelper.RunSync(async () => + await permissionChecker.IsGrantedAsync(HangfireDashboardPermissions.Dashboard.ManageJobs)); + } + }; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/DashboardAuthorizationFilter.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/DashboardAuthorizationFilter.cs new file mode 100644 index 000000000..acd9b292a --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/DashboardAuthorizationFilter.cs @@ -0,0 +1,32 @@ +using Hangfire.Annotations; +using Hangfire.Dashboard; +using Microsoft.Extensions.DependencyInjection; +using System.Linq; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.Hangfire.Dashboard.Authorization +{ + public class DashboardAuthorizationFilter : IDashboardAuthorizationFilter + { + internal readonly static string[] AllowRoutePrefixs = new string[] + { + "/stats", + "/js", + "/css", + "/fonts" + }; + public bool Authorize([NotNull] DashboardContext context) + { + if (AllowRoutePrefixs.Any(url => context.Request.Path.StartsWith(url))) + { + return true; + } + + var httpContext = context.GetHttpContext(); + var permissionChecker = httpContext.RequestServices.GetRequiredService(); + return AsyncHelper.RunSync(async () => + await permissionChecker.IsGrantedAsync(httpContext.User, HangfireDashboardPermissions.Dashboard.Default)); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/HangfireDashboardPermissionDefinitionProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/HangfireDashboardPermissionDefinitionProvider.cs new file mode 100644 index 000000000..ea092817a --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/HangfireDashboardPermissionDefinitionProvider.cs @@ -0,0 +1,33 @@ +using LINGYUN.Abp.Hangfire.Dashboard.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.Hangfire.Dashboard.Authorization +{ + public class HangfireDashboardPermissionDefinitionProvider : PermissionDefinitionProvider + { + public override void Define(IPermissionDefinitionContext context) + { + var group = context.AddGroup( + HangfireDashboardPermissions.GroupName, + L("Permission:Hangfire"), + MultiTenancySides.Host); // 除非对Hangfire Api进行改造,否则不能区分租户 + + var dashboard = group.AddPermission( + HangfireDashboardPermissions.Dashboard.Default, + L("Permission:Dashboard"), + MultiTenancySides.Host); + + dashboard.AddChild( + HangfireDashboardPermissions.Dashboard.ManageJobs, + L("Permission:ManageJobs"), + MultiTenancySides.Host); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/HangfireDashboardPermissions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/HangfireDashboardPermissions.cs new file mode 100644 index 000000000..fbacbf385 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Authorization/HangfireDashboardPermissions.cs @@ -0,0 +1,15 @@ +namespace LINGYUN.Abp.Hangfire.Dashboard.Authorization +{ + public static class HangfireDashboardPermissions + { + public const string GroupName = "Hangfire"; + + public static class Dashboard + { + public const string Default = GroupName + ".Dashboard"; + + public const string ManageJobs = Default + ".ManageJobs"; + // TODO: other pages... + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/HangfireDashboardResource.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/HangfireDashboardResource.cs new file mode 100644 index 000000000..b2f90e1ae --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/HangfireDashboardResource.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.Hangfire.Dashboard.Localization +{ + [LocalizationResourceName("HangfireDashboard")] + public class HangfireDashboardResource + { + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/Resources/en.json b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/Resources/en.json new file mode 100644 index 000000000..833cc61ff --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/Resources/en.json @@ -0,0 +1,7 @@ +{ + "culture": "en", + "texts": { + "Permission:Hangfire": "Hangfire", + "Permission:Dashboard": "Dashboard" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/Resources/zh-Hans.json b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..cae00e4a4 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/LINGYUN/Abp/Hangfire/Dashboard/Localization/Resources/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "culture": "zh-Hans", + "texts": { + "Permission:Hangfire": "Hangfire", + "Permission:Dashboard": "仪表板" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/Microsoft/AspNetCore/Builder/ApplicationBuilderAbpHangfireAuthoricationMiddlewareExtension.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/Microsoft/AspNetCore/Builder/ApplicationBuilderAbpHangfireAuthoricationMiddlewareExtension.cs new file mode 100644 index 000000000..885017397 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/Microsoft/AspNetCore/Builder/ApplicationBuilderAbpHangfireAuthoricationMiddlewareExtension.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Builder +{ + public static class ApplicationBuilderAbpHangfireAuthoricationMiddlewareExtension + { + public static IApplicationBuilder UseHangfireAuthorication(this IApplicationBuilder app) + { + return app.UseMiddleware(); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/Microsoft/AspNetCore/Http/HangfireAuthoricationMiddleware.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/Microsoft/AspNetCore/Http/HangfireAuthoricationMiddleware.cs new file mode 100644 index 000000000..5d1eb378d --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Dashboard/Microsoft/AspNetCore/Http/HangfireAuthoricationMiddleware.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Microsoft.AspNetCore.Http +{ + public class HangfireAuthoricationMiddleware : IMiddleware, ITransientDependency + { + public async Task InvokeAsync(HttpContext context, RequestDelegate next) + { + // 通过 iframe 加载页面的话,需要手动传递 access_token 到参数列表 + if (context.Request.Path.StartsWithSegments("/hangfire") && + context.User.Identity?.IsAuthenticated != true) + { + if (context.Request.Query.TryGetValue("access_token", out var accessTokens)) + { + context.Request.Headers.Add("Authorization", accessTokens); + context.Response.Cookies.Append("access_token", accessTokens); + } + else if (context.Request.Cookies.TryGetValue("access_token", out string tokens)) + { + context.Request.Headers.Add("Authorization", tokens); + } + } + await next(context); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.MySqlStorage/LINGYUN/Abp/Hangfire/Storage/MySql/AbpHangfireMySqlStorageModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.MySqlStorage/LINGYUN/Abp/Hangfire/Storage/MySql/AbpHangfireMySqlStorageModule.cs index e6cc4da13..5249708bf 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.MySqlStorage/LINGYUN/Abp/Hangfire/Storage/MySql/AbpHangfireMySqlStorageModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.MySqlStorage/LINGYUN/Abp/Hangfire/Storage/MySql/AbpHangfireMySqlStorageModule.cs @@ -13,7 +13,7 @@ namespace LINGYUN.Abp.Hangfire.Storage.MySql { private MySqlStorage _jobStorage; - public override void ConfigureServices(ServiceConfigurationContext context) + public override void PreConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); @@ -30,7 +30,7 @@ namespace LINGYUN.Abp.Hangfire.Storage.MySql return _jobStorage; }); - context.Services.AddHangfire(config => + PreConfigure(config => { config.UseStorage(_jobStorage); }); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Storage.SqlServer/LINGYUN/Abp/Hangfire/Storage/SqlServer/AbpHangfireSqlServerStorageModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Storage.SqlServer/LINGYUN/Abp/Hangfire/Storage/SqlServer/AbpHangfireSqlServerStorageModule.cs index 42e4ff8db..4152078ab 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Storage.SqlServer/LINGYUN/Abp/Hangfire/Storage/SqlServer/AbpHangfireSqlServerStorageModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Hangfire.Storage.SqlServer/LINGYUN/Abp/Hangfire/Storage/SqlServer/AbpHangfireSqlServerStorageModule.cs @@ -12,7 +12,7 @@ namespace LINGYUN.Abp.Hangfire.Storage.SqlServer { private SqlServerStorage _jobStorage; - public override void ConfigureServices(ServiceConfigurationContext context) + public override void PreConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); @@ -29,7 +29,7 @@ namespace LINGYUN.Abp.Hangfire.Storage.SqlServer return _jobStorage; }); - context.Services.AddHangfire(config => + PreConfigure(config => { config.UseStorage(_jobStorage); }); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/Class1.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/Class1.cs new file mode 100644 index 000000000..f4c995fea --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace LINGYUN.Abp.Notifications.Workers +{ + public class Class1 + { + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/LINGYUN.Abp.Notifications.Workers.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/LINGYUN.Abp.Notifications.Workers.csproj new file mode 100644 index 000000000..c45d87d03 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/LINGYUN.Abp.Notifications.Workers.csproj @@ -0,0 +1,14 @@ + + + + + + netstandard2.0 + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/LINGYUN/Abp/Notifications/Workers/AbpNotificationsWorkersModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/LINGYUN/Abp/Notifications/Workers/AbpNotificationsWorkersModule.cs new file mode 100644 index 000000000..3f513fa52 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.Workers/LINGYUN/Abp/Notifications/Workers/AbpNotificationsWorkersModule.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace LINGYUN.Abp.Notifications.Workers.LINGYUN.Abp.Notifications.Workers +{ + class AbpNotificationsWorkersModule + { + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj index 7541516cd..bb8312af4 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj @@ -10,7 +10,8 @@ - + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs index c08113184..940a5ba86 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs @@ -13,7 +13,8 @@ namespace LINGYUN.Abp.Notifications { // TODO: 需要重命名 AbpNotificationsModule [DependsOn( - typeof(AbpBackgroundJobsModule), + typeof(AbpBackgroundWorkersModule), + typeof(AbpBackgroundJobsAbstractionsModule), typeof(AbpJsonModule))] public class AbpNotificationModule : AbpModule { @@ -23,7 +24,7 @@ namespace LINGYUN.Abp.Notifications AutoAddDefinitionProviders(context.Services); } - public override void OnApplicationInitialization(ApplicationInitializationContext context) + public override void OnPostApplicationInitialization(ApplicationInitializationContext context) { var options = context.ServiceProvider.GetRequiredService>().Value; if (options.IsEnabled) diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/AbpMessageServiceHttpApiHostModule.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/AbpMessageServiceHttpApiHostModule.cs index 716ae3ba6..afea4572c 100644 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/AbpMessageServiceHttpApiHostModule.cs +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/AbpMessageServiceHttpApiHostModule.cs @@ -8,7 +8,6 @@ using LINGYUN.Abp.ExceptionHandling; using LINGYUN.Abp.ExceptionHandling.Notifications; using LINGYUN.Abp.Hangfire.Storage.MySql; using LINGYUN.Abp.IM.SignalR; -using LINGYUN.Abp.MessageService.Authorization; using LINGYUN.Abp.MessageService.EntityFrameworkCore; using LINGYUN.Abp.MessageService.Localization; using LINGYUN.Abp.MultiTenancy.DbFinder; @@ -27,13 +26,17 @@ using Microsoft.Extensions.Hosting; using Microsoft.OpenApi.Models; using StackExchange.Redis; using System; +using System.Collections.Generic; using System.Linq; using System.Text; using Volo.Abp; +using Volo.Abp.AspNetCore.Auditing; using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.AspNetCore.Security.Claims; +using Volo.Abp.AspNetCore.Uow; using Volo.Abp.Autofac; +using Volo.Abp.BackgroundWorkers; using Volo.Abp.Caching; using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.EntityFrameworkCore; @@ -59,6 +62,9 @@ namespace LINGYUN.Abp.MessageService typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpHangfireMySqlStorageModule), + typeof(AbpBackgroundJobsHangfireModule), + typeof(AbpBackgroundWorkersModule), typeof(AbpIMSignalRModule), typeof(AbpNotificationsSmsModule), typeof(AbpNotificationsSignalRModule), @@ -66,8 +72,6 @@ namespace LINGYUN.Abp.MessageService typeof(AbpNotificationsExceptionHandlingModule), typeof(AbpAspNetCoreSignalRProtocolJsonModule), typeof(AbpCAPEventBusModule), - typeof(AbpBackgroundJobsHangfireModule), - typeof(AbpHangfireMySqlStorageModule), typeof(AbpDbFinderMultiTenancyModule), typeof(AbpCachingStackExchangeRedisModule), typeof(AbpAspNetCoreHttpOverridesModule), @@ -104,6 +108,11 @@ namespace LINGYUN.Abp.MessageService options.UseMySQL(); }); + Configure(options => + { + options.IgnoredUrls.AddIfNotContains("/hangfire"); + }); + // 解决某些不支持类型的序列化 Configure(options => { @@ -233,25 +242,6 @@ namespace LINGYUN.Abp.MessageService }); }); - Configure(options => - { - if (configuration.GetSection("Hangfire:Dashboard:WhiteList").Exists()) - { - options.WithWhite( - configuration["Hangfire:Dashboard:WhiteList"] - .Split(",", StringSplitOptions.RemoveEmptyEntries) - .Select(o => o.RemovePostFix("/")) - .ToArray()); - } - - options.WithOrigins( - configuration["App:CorsOrigins"] - .Split(",", StringSplitOptions.RemoveEmptyEntries) - .Select(o => o.RemovePostFix("/")) - .ToArray() - ); - }); - // 支持本地化语言类型 Configure(options => { @@ -263,11 +253,6 @@ namespace LINGYUN.Abp.MessageService .AddVirtualJson("/Localization/HttpApiHost"); }); - Configure(options => - { - options.Maps.TryAdd("name", () => AbpClaimTypes.UserName); - }); - context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { @@ -285,14 +270,6 @@ namespace LINGYUN.Abp.MessageService } } - //public override void OnPostApplicationInitialization(ApplicationInitializationContext context) - //{ - // var backgroundJobManager = context.ServiceProvider.GetRequiredService(); - // // 五分钟执行一次的定时任务 - // AsyncHelper.RunSync(async () => await - // backgroundJobManager.EnqueueAsync(CronGenerator.Minute(5), new NotificationCleanupExpritionJobArgs(200))); - //} - public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); @@ -309,7 +286,7 @@ namespace LINGYUN.Abp.MessageService // 加入自定义中间件 app.UseSignalRJwtToken(); // TODO: 还有没有其他方法在iframe中传递身份令牌? - app.UseHangfireJwtToken(); + app.UseHangfireAuthorication(); // 认证 app.UseAuthentication(); // jwt @@ -328,11 +305,7 @@ namespace LINGYUN.Abp.MessageService // 审计日志 app.UseAuditing(); app.UseHangfireServer(); - app.UseHangfireDashboard(options => - { - options.IgnoreAntiforgeryToken = true; - options.UseAuthorization(new HangfireDashboardAuthorizationFilter()); - }); + app.UseHangfireDashboard(); // 路由 app.UseConfiguredEndpoints(); } diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Authorization/HangfireDashboardAuthorizationFilter.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Authorization/HangfireDashboardAuthorizationFilter.cs deleted file mode 100644 index 88eccea47..000000000 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Authorization/HangfireDashboardAuthorizationFilter.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Hangfire; -using Hangfire.Annotations; -using Hangfire.Dashboard; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using NUglify.Helpers; -using System.Linq; -using Volo.Abp.Authorization.Permissions; -using Volo.Abp.Threading; - -namespace LINGYUN.Abp.MessageService.Authorization -{ - public class HangfireDashboardAuthorizationFilter : IDashboardAuthorizationFilter - { - protected string[] AllowGrantPath { get; } - public HangfireDashboardAuthorizationFilter() - { - AllowGrantPath = new string[] { "/css", "/js", "/fonts", "/stats" }; - } - - public bool Authorize([NotNull] DashboardContext context) - { - // 放行路径 - if (AllowGrantPath.Contains(context.Request.Path)) - { - return true; - } - var httpContext = context.GetHttpContext(); - - var options = httpContext.RequestServices.GetService>()?.Value; - - if (options != null) - { - // 白名单检查 - if (!context.Request.RemoteIpAddress.IsNullOrWhiteSpace() - && options.IpAllow(context.Request.RemoteIpAddress)) - { - return true; - } - // 请求路径对应的权限检查 - // TODO: 怎么来传递用户身份令牌? - var permission = options.GetPermission(context.Request.Path); - if (!permission.IsNullOrWhiteSpace()) - { - var permissionChecker = httpContext.RequestServices.GetRequiredService(); - return AsyncHelper.RunSync(async () => await permissionChecker.IsGrantedAsync(permission)); - } - } - - return false; - } - - public override int GetHashCode() - { - // 类型相同就行了 - return GetType().FullName.GetHashCode(); - } - - public override bool Equals(object obj) - { - if (obj == null) - { - return false; - } - // 类型相同就行了 - if (GetType().Equals(obj.GetType())) - { - return true; - } - return base.Equals(obj); - } - } -} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/BackgroundJobs/NotificationCleanupExpritionJob.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/BackgroundJobs/NotificationCleanupExpritionJob.cs deleted file mode 100644 index 591ced1b8..000000000 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/BackgroundJobs/NotificationCleanupExpritionJob.cs +++ /dev/null @@ -1,38 +0,0 @@ -using LINGYUN.Abp.Notifications; -using Microsoft.Extensions.Logging; -using System; -using System.Threading.Tasks; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.DependencyInjection; - -namespace LINGYUN.Abp.MessageService.BackgroundJobs -{ - internal class NotificationCleanupExpritionJob : AsyncBackgroundJob, ITransientDependency - { - protected INotificationStore Store { get; } - protected IServiceProvider ServiceProvider { get; } - - public NotificationCleanupExpritionJob( - INotificationStore store, - IServiceProvider serviceProvider) - { - Store = store; - ServiceProvider = serviceProvider; - } - - public override async Task ExecuteAsync(NotificationCleanupExpritionJobArgs args) - { - try - { - Logger.LogDebug("Before cleanup exprition jobs..."); - await Store.DeleteNotificationAsync(args.Count); - Logger.LogDebug("Exprition jobs cleanup job was successful..."); - } - catch (Exception ex) - { - Logger.LogWarning("Exprition jobs cleanup job was failed..."); - Logger.LogWarning("Error:{0}", ex.Message); - } - } - } -} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/BackgroundJobs/NotificationCleanupExpritionJobArgs.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/BackgroundJobs/NotificationCleanupExpritionJobArgs.cs deleted file mode 100644 index 73b57110a..000000000 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/BackgroundJobs/NotificationCleanupExpritionJobArgs.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Volo.Abp.BackgroundJobs; - -namespace LINGYUN.Abp.MessageService.BackgroundJobs -{ - [BackgroundJobName("定时清理过期通知消息任务")] - internal class NotificationCleanupExpritionJobArgs - { - /// - /// 清理大小 - /// - public int Count { get; set; } - - public NotificationCleanupExpritionJobArgs() - { - - } - - public NotificationCleanupExpritionJobArgs(int count = 200) - { - Count = count; - } - } -} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/DashboardOptionsExtensions.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/DashboardOptionsExtensions.cs deleted file mode 100644 index 9b8374fe3..000000000 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/DashboardOptionsExtensions.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Hangfire.Dashboard; -using JetBrains.Annotations; -using System.Collections.Generic; -using Volo.Abp; - -namespace Hangfire -{ - public static class DashboardOptionsExtensions - { - public static DashboardOptions AddAuthorization( - [NotNull] this DashboardOptions options, - [NotNull] IDashboardAuthorizationFilter authorizationFilter) - { - Check.NotNull(options, nameof(options)); - Check.NotNull(authorizationFilter, nameof(authorizationFilter)); - - List filters = new List(); - filters.AddRange(options.Authorization); - filters.AddIfNotContains(authorizationFilter); - - options.Authorization = filters; - - return options; - } - - public static DashboardOptions AddAuthorizations( - [NotNull] this DashboardOptions options, - [NotNull] IEnumerable authorizationFilters) - { - Check.NotNull(options, nameof(options)); - Check.NotNull(authorizationFilters, nameof(authorizationFilters)); - - List filters = new List(); - filters.AddRange(options.Authorization); - filters.AddIfNotContains(authorizationFilters); - - options.Authorization = filters; - - return options; - } - - public static DashboardOptions UseAuthorization( - [NotNull] this DashboardOptions options, - [NotNull] IDashboardAuthorizationFilter authorizationFilter) - { - Check.NotNull(options, nameof(options)); - Check.NotNull(authorizationFilter, nameof(authorizationFilter)); - - List filters = new List - { - authorizationFilter - }; - - options.Authorization = filters; - - return options; - } - - public static DashboardOptions UseAuthorizations( - [NotNull] this DashboardOptions options, - [NotNull] IEnumerable authorizationFilters) - { - Check.NotNull(options, nameof(options)); - Check.NotNull(authorizationFilters, nameof(authorizationFilters)); - - List filters = new List(); - filters.AddRange(authorizationFilters); - - options.Authorization = filters; - - return options; - } - } -} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireApplicationBuilderExtensions.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireApplicationBuilderExtensions.cs deleted file mode 100644 index dedf71955..000000000 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireApplicationBuilderExtensions.cs +++ /dev/null @@ -1,47 +0,0 @@ -using JetBrains.Annotations; -using Microsoft.AspNetCore.Builder; -using System; -using Volo.Abp; - -namespace Hangfire -{ - public static class HangfireApplicationBuilderExtensions - { - public static IApplicationBuilder UseHangfireJwtToken( - [NotNull] this IApplicationBuilder app) - { - return app.UseMiddleware(); - } - - public static IApplicationBuilder UseHangfireDashboard( - [NotNull] this IApplicationBuilder app, - [CanBeNull] Action setup = null) - { - Check.NotNull(app, nameof(app)); - return app.UseHangfireDashboard("/hangfire", setup, null); - } - - public static IApplicationBuilder UseHangfireDashboard( - [NotNull] this IApplicationBuilder app, - [CanBeNull] string pathMatch = "/hangfire", - [CanBeNull] Action setup = null) - { - Check.NotNull(app, nameof(app)); - return app.UseHangfireDashboard(pathMatch, setup, null); - } - - public static IApplicationBuilder UseHangfireDashboard( - [NotNull] this IApplicationBuilder app, - [CanBeNull] string pathMatch = "/hangfire", - [CanBeNull] Action setup = null, - [CanBeNull] JobStorage storage = null) - { - Check.NotNull(app, nameof(app)); - - var options = new DashboardOptions(); - setup?.Invoke(options); - - return app.UseHangfireDashboard(pathMatch: pathMatch, options: options, storage: storage); - } - } -} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireDashboardRouteOptions.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireDashboardRouteOptions.cs deleted file mode 100644 index 596fbd634..000000000 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireDashboardRouteOptions.cs +++ /dev/null @@ -1,74 +0,0 @@ -using LINGYUN.Abp.MessageService.Permissions; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Hangfire -{ - public class HangfireDashboardRouteOptions - { - public IList AllowFrameOrigins { get; } - /// - /// 白名单 - /// 添加网关地址 - /// - public IList WhiteList { get; } - public IDictionary RoutePermissions { get; } - public HangfireDashboardRouteOptions() - { - WhiteList = new List(); - AllowFrameOrigins = new List(); - RoutePermissions = new Dictionary(); - InitDefaultRoutes(); - WithWhite("127.0.0.1"); - WithWhite("::1"); - } - - public bool IpAllow(string ipaddress) - { - return WhiteList.Any(ip => ip == ipaddress); - } - - public void WithWhite(params string[] wgites) - { - WhiteList.AddIfNotContains(wgites); - } - - public void WithOrigins(params string[] origins) - { - AllowFrameOrigins.AddIfNotContains(origins); - } - - public void WithPermission(string route, string permission) - { - RoutePermissions.Add(route, permission); - } - - public string GetPermission(string route) - { - var permission = RoutePermissions - .Where(x => x.Key.StartsWith(route)) - .Select(x => x.Value) - .FirstOrDefault(); - - return permission; - } - - private void InitDefaultRoutes() - { - WithPermission("/hangfire", MessageServicePermissions.Hangfire.Default); - WithPermission("/stats", MessageServicePermissions.Hangfire.Default); - WithPermission("/servers", MessageServicePermissions.Hangfire.Default); - WithPermission("/retries", MessageServicePermissions.Hangfire.Default); - WithPermission("/recurring", MessageServicePermissions.Hangfire.Default); - WithPermission("/jobs/enqueued", MessageServicePermissions.Hangfire.ManageQueue); - WithPermission("/jobs/processing", MessageServicePermissions.Hangfire.ManageQueue); - WithPermission("/jobs/scheduled", MessageServicePermissions.Hangfire.ManageQueue); - WithPermission("/jobs/failed", MessageServicePermissions.Hangfire.ManageQueue); - WithPermission("/jobs/deleted", MessageServicePermissions.Hangfire.ManageQueue); - WithPermission("/jobs/awaiting", MessageServicePermissions.Hangfire.ManageQueue); - WithPermission("/jobs/actions", MessageServicePermissions.Hangfire.ManageQueue); - WithPermission("/jobs/details", MessageServicePermissions.Hangfire.ManageQueue); - } - } -} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireJwtTokenMiddleware.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireJwtTokenMiddleware.cs deleted file mode 100644 index 708fc1407..000000000 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Hangfire/HangfireJwtTokenMiddleware.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; - -namespace Hangfire -{ - public class HangfireJwtTokenMiddleware : IMiddleware, ITransientDependency - { - public async Task InvokeAsync(HttpContext context, RequestDelegate next) - { - // 通过 iframe 加载页面的话,需要手动传递 access_token 到参数列表 - if (context.Request.Path.StartsWithSegments("/hangfire") && context.User.Identity?.IsAuthenticated != true) - { - if (context.Request.Query.TryGetValue("access_token", out var accessTokens)) - { - context.Request.Headers.Add("Authorization", accessTokens); - } - var options = context.RequestServices.GetService>()?.Value; - if (options != null && options.AllowFrameOrigins.Count > 0) - { - // 跨域 iframe - context.Response.Headers.TryAdd("X-Frame-Options", $"\"ALLOW-FROM {options.AllowFrameOrigins.JoinAsString(",")}\""); - } - } - await next(context); - } - } -} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj index 1f40bc8af..6a15a0b68 100644 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj @@ -45,6 +45,7 @@ +