committed by
GitHub
20 changed files with 265 additions and 277 deletions
@ -1,36 +1,22 @@ |
|||||
using LINGYUN.Abp.Hangfire.Dashboard.Localization; |
using Microsoft.Extensions.DependencyInjection; |
||||
using Microsoft.Extensions.DependencyInjection; |
using Volo.Abp.Authorization; |
||||
using Volo.Abp.Authorization; |
using Volo.Abp.Hangfire; |
||||
using Volo.Abp.Hangfire; |
using Volo.Abp.Modularity; |
||||
using Volo.Abp.Localization; |
|
||||
using Volo.Abp.Modularity; |
namespace LINGYUN.Abp.Hangfire.Dashboard |
||||
using Volo.Abp.VirtualFileSystem; |
{ |
||||
|
[DependsOn( |
||||
namespace LINGYUN.Abp.Hangfire.Dashboard |
typeof(AbpAuthorizationModule), |
||||
{ |
typeof(AbpHangfireModule))] |
||||
[DependsOn( |
public class AbpHangfireDashboardModule : AbpModule |
||||
typeof(AbpLocalizationModule), |
{ |
||||
typeof(AbpAuthorizationModule), |
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
typeof(AbpHangfireModule))] |
{ |
||||
public class AbpHangfireDashboardModule : AbpModule |
context.Services.AddTransient(serviceProvider => |
||||
{ |
{ |
||||
public override void ConfigureServices(ServiceConfigurationContext context) |
var options = serviceProvider.GetRequiredService<AbpHangfireDashboardOptionsProvider>().Get(); |
||||
{ |
return context.Services.ExecutePreConfiguredActions(options); |
||||
Configure<AbpVirtualFileSystemOptions>(options => |
}); |
||||
{ |
} |
||||
options.FileSets.AddEmbedded<AbpHangfireDashboardModule>(); |
} |
||||
}); |
} |
||||
|
|
||||
Configure<AbpLocalizationOptions>(options => |
|
||||
{ |
|
||||
options.Resources.Add<HangfireDashboardResource>(); |
|
||||
}); |
|
||||
|
|
||||
context.Services.AddTransient(serviceProvider => |
|
||||
{ |
|
||||
var options = serviceProvider.GetRequiredService<AbpHangfireDashboardOptionsProvider>().Get(); |
|
||||
return context.Services.ExecutePreConfiguredActions(options); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|||||
@ -1,32 +1,13 @@ |
|||||
using Hangfire; |
using Hangfire; |
||||
using Hangfire.Dashboard; |
using Volo.Abp.DependencyInjection; |
||||
using LINGYUN.Abp.Hangfire.Dashboard.Authorization; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
namespace LINGYUN.Abp.Hangfire.Dashboard |
||||
using Volo.Abp.Authorization.Permissions; |
{ |
||||
using Volo.Abp.DependencyInjection; |
public class AbpHangfireDashboardOptionsProvider : ITransientDependency |
||||
using Volo.Abp.Threading; |
{ |
||||
|
public virtual DashboardOptions Get() |
||||
namespace LINGYUN.Abp.Hangfire.Dashboard |
{ |
||||
{ |
return new DashboardOptions(); |
||||
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<IPermissionChecker>(); |
|
||||
|
|
||||
return !AsyncHelper.RunSync(async () => |
|
||||
await permissionChecker.IsGrantedAsync(HangfireDashboardPermissions.Dashboard.ManageJobs)); |
|
||||
} |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|||||
@ -1,32 +1,46 @@ |
|||||
using Hangfire.Annotations; |
using Hangfire.Dashboard; |
||||
using Hangfire.Dashboard; |
using Microsoft.Extensions.DependencyInjection; |
||||
using Microsoft.Extensions.DependencyInjection; |
using System; |
||||
using System.Linq; |
using System.Collections.Generic; |
||||
using Volo.Abp.Authorization.Permissions; |
using System.Threading.Tasks; |
||||
using Volo.Abp.Threading; |
using Volo.Abp.Users; |
||||
|
|
||||
namespace LINGYUN.Abp.Hangfire.Dashboard.Authorization |
namespace LINGYUN.Abp.Hangfire.Dashboard.Authorization |
||||
{ |
{ |
||||
public class DashboardAuthorizationFilter : IDashboardAuthorizationFilter |
public class DashboardAuthorizationFilter : IDashboardAsyncAuthorizationFilter |
||||
{ |
{ |
||||
internal readonly static string[] AllowRoutePrefixs = new string[] |
private readonly string[] _requiredPermissionNames; |
||||
{ |
|
||||
"/stats", |
public DashboardAuthorizationFilter(params string[] requiredPermissionNames) |
||||
"/js", |
{ |
||||
"/css", |
_requiredPermissionNames = requiredPermissionNames; |
||||
"/fonts" |
} |
||||
}; |
|
||||
public bool Authorize([NotNull] DashboardContext context) |
public async Task<bool> AuthorizeAsync(DashboardContext context) |
||||
{ |
{ |
||||
if (AllowRoutePrefixs.Any(url => context.Request.Path.StartsWith(url))) |
if (!IsLoggedIn(context)) |
||||
{ |
{ |
||||
return true; |
return false; |
||||
} |
} |
||||
|
|
||||
var httpContext = context.GetHttpContext(); |
if (_requiredPermissionNames.IsNullOrEmpty()) |
||||
var permissionChecker = httpContext.RequestServices.GetRequiredService<IPermissionChecker>(); |
{ |
||||
return AsyncHelper.RunSync(async () => |
return true; |
||||
await permissionChecker.IsGrantedAsync(httpContext.User, HangfireDashboardPermissions.Dashboard.Default)); |
} |
||||
} |
|
||||
} |
return await IsPermissionGrantedAsync(context, _requiredPermissionNames); |
||||
} |
} |
||||
|
|
||||
|
private static bool IsLoggedIn(DashboardContext context) |
||||
|
{ |
||||
|
var currentUser = context.GetHttpContext().RequestServices.GetRequiredService<ICurrentUser>(); |
||||
|
return currentUser.IsAuthenticated; |
||||
|
} |
||||
|
|
||||
|
private static async Task<bool> IsPermissionGrantedAsync(DashboardContext context, string[] requiredPermissionNames) |
||||
|
{ |
||||
|
var permissionChecker = context.GetHttpContext().RequestServices.GetRequiredService<IDashboardPermissionChecker>(); |
||||
|
return await permissionChecker.IsGrantedAsync(context, requiredPermissionNames); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -0,0 +1,48 @@ |
|||||
|
using Hangfire.Dashboard; |
||||
|
using Microsoft.Extensions.Caching.Memory; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Hangfire.Dashboard.Authorization |
||||
|
{ |
||||
|
public class DashboardPermissionChecker : IDashboardPermissionChecker, ITransientDependency |
||||
|
{ |
||||
|
// 仪表板属于高频访问, 设定有效期的二级权限缓存
|
||||
|
private readonly IMemoryCache _memoryCache; |
||||
|
private readonly IPermissionChecker _permissionChecker; |
||||
|
|
||||
|
public DashboardPermissionChecker( |
||||
|
IMemoryCache memoryCache, |
||||
|
IPermissionChecker permissionChecker) |
||||
|
{ |
||||
|
_memoryCache = memoryCache; |
||||
|
_permissionChecker = permissionChecker; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<bool> IsGrantedAsync(DashboardContext context, string[] requiredPermissionNames) |
||||
|
{ |
||||
|
var localPermissionKey = $"_HDPS:{requiredPermissionNames.JoinAsString(";")}"; |
||||
|
|
||||
|
if (_memoryCache.TryGetValue(localPermissionKey, out MultiplePermissionGrantResult cacheItem)) |
||||
|
{ |
||||
|
return cacheItem.AllGranted; |
||||
|
} |
||||
|
|
||||
|
cacheItem = await _permissionChecker.IsGrantedAsync(requiredPermissionNames); |
||||
|
|
||||
|
_memoryCache.Set( |
||||
|
localPermissionKey, |
||||
|
cacheItem, |
||||
|
new MemoryCacheEntryOptions |
||||
|
{ |
||||
|
// 5分钟过期
|
||||
|
AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(5d), |
||||
|
}); |
||||
|
|
||||
|
return cacheItem.AllGranted; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,33 +0,0 @@ |
|||||
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<HangfireDashboardResource>(name); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,15 +0,0 @@ |
|||||
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...
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,10 @@ |
|||||
|
using Hangfire.Dashboard; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Hangfire.Dashboard.Authorization |
||||
|
{ |
||||
|
public interface IDashboardPermissionChecker |
||||
|
{ |
||||
|
Task<bool> IsGrantedAsync(DashboardContext context, string[] requiredPermissionNames); |
||||
|
} |
||||
|
} |
||||
@ -1,9 +0,0 @@ |
|||||
using Volo.Abp.Localization; |
|
||||
|
|
||||
namespace LINGYUN.Abp.Hangfire.Dashboard.Localization |
|
||||
{ |
|
||||
[LocalizationResourceName("HangfireDashboard")] |
|
||||
public class HangfireDashboardResource |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
@ -1,7 +0,0 @@ |
|||||
{ |
|
||||
"culture": "en", |
|
||||
"texts": { |
|
||||
"Permission:Hangfire": "Hangfire", |
|
||||
"Permission:Dashboard": "Dashboard" |
|
||||
} |
|
||||
} |
|
||||
@ -1,7 +0,0 @@ |
|||||
{ |
|
||||
"culture": "zh-Hans", |
|
||||
"texts": { |
|
||||
"Permission:Hangfire": "Hangfire", |
|
||||
"Permission:Dashboard": "仪表板" |
|
||||
} |
|
||||
} |
|
||||
@ -1,27 +1,27 @@ |
|||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
namespace Microsoft.AspNetCore.Http |
namespace Microsoft.AspNetCore.Http |
||||
{ |
{ |
||||
public class HangfireAuthoricationMiddleware : IMiddleware, ITransientDependency |
public class HangfireAuthoricationMiddleware : IMiddleware, ITransientDependency |
||||
{ |
{ |
||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next) |
public async Task InvokeAsync(HttpContext context, RequestDelegate next) |
||||
{ |
{ |
||||
// 通过 iframe 加载页面的话,需要手动传递 access_token 到参数列表
|
// 通过 iframe 加载页面的话,初次传递 access_token 到 QueryString
|
||||
if (context.Request.Path.StartsWithSegments("/hangfire") && |
if (context.Request.Path.StartsWithSegments("/hangfire") && |
||||
context.User.Identity?.IsAuthenticated != true) |
context.User.Identity?.IsAuthenticated != true) |
||||
{ |
{ |
||||
if (context.Request.Query.TryGetValue("access_token", out var accessTokens)) |
if (context.Request.Query.TryGetValue("access_token", out var accessTokens)) |
||||
{ |
{ |
||||
context.Request.Headers.Add("Authorization", accessTokens); |
context.Request.Headers.Add("Authorization", accessTokens); |
||||
context.Response.Cookies.Append("access_token", accessTokens); |
context.Response.Cookies.Append("access_token", accessTokens); |
||||
} |
} |
||||
else if (context.Request.Cookies.TryGetValue("access_token", out string tokens)) |
else if (context.Request.Cookies.TryGetValue("access_token", out string tokens)) |
||||
{ |
{ |
||||
context.Request.Headers.Add("Authorization", tokens); |
context.Request.Headers.Add("Authorization", tokens); |
||||
} |
} |
||||
} |
} |
||||
await next(context); |
await next(context); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,21 +1,23 @@ |
|||||
namespace LINGYUN.Abp.MessageService.Permissions |
namespace LINGYUN.Abp.MessageService.Permissions |
||||
{ |
{ |
||||
public class MessageServicePermissions |
public class MessageServicePermissions |
||||
{ |
{ |
||||
public const string GroupName = "MessageService"; |
public const string GroupName = "MessageService"; |
||||
|
|
||||
public class Notification |
public class Notification |
||||
{ |
{ |
||||
public const string Default = GroupName + ".Notification"; |
public const string Default = GroupName + ".Notification"; |
||||
|
|
||||
public const string Delete = Default + ".Delete"; |
public const string Delete = Default + ".Delete"; |
||||
} |
} |
||||
|
|
||||
public class Hangfire |
public class Hangfire |
||||
{ |
{ |
||||
public const string Default = GroupName + ".Hangfire"; |
public const string Default = GroupName + ".Hangfire"; |
||||
|
|
||||
public const string ManageQueue = Default + ".ManageQueue"; |
public const string Dashboard = Default + ".Dashboard"; |
||||
} |
|
||||
} |
public const string ManageQueue = Default + ".ManageQueue"; |
||||
} |
} |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -1,25 +1,26 @@ |
|||||
using LINGYUN.Abp.MessageService.Localization; |
using LINGYUN.Abp.MessageService.Localization; |
||||
using Volo.Abp.Authorization.Permissions; |
using Volo.Abp.Authorization.Permissions; |
||||
using Volo.Abp.Localization; |
using Volo.Abp.Localization; |
||||
|
|
||||
namespace LINGYUN.Abp.MessageService.Permissions |
namespace LINGYUN.Abp.MessageService.Permissions |
||||
{ |
{ |
||||
public class MessageServicePermissionsDefinitionProvider : PermissionDefinitionProvider |
public class MessageServicePermissionsDefinitionProvider : PermissionDefinitionProvider |
||||
{ |
{ |
||||
public override void Define(IPermissionDefinitionContext context) |
public override void Define(IPermissionDefinitionContext context) |
||||
{ |
{ |
||||
var group = context.AddGroup(MessageServicePermissions.GroupName, L("Permission:MessageService")); |
var group = context.AddGroup(MessageServicePermissions.GroupName, L("Permission:MessageService")); |
||||
|
|
||||
var noticeGroup = group.AddPermission(MessageServicePermissions.Notification.Default, L("Permission:Notification")); |
var noticeGroup = group.AddPermission(MessageServicePermissions.Notification.Default, L("Permission:Notification")); |
||||
noticeGroup.AddChild(MessageServicePermissions.Notification.Delete, L("Permission:Delete")); |
noticeGroup.AddChild(MessageServicePermissions.Notification.Delete, L("Permission:Delete")); |
||||
|
|
||||
var hangfirePermission = group.AddPermission(MessageServicePermissions.Hangfire.Default, L("Permission:Hangfire")); |
var hangfirePermission = group.AddPermission(MessageServicePermissions.Hangfire.Default, L("Permission:Hangfire")); |
||||
hangfirePermission.AddChild(MessageServicePermissions.Hangfire.ManageQueue, L("Permission:ManageQueue")); |
hangfirePermission.AddChild(MessageServicePermissions.Hangfire.Dashboard, L("Permission:Dashboard")); |
||||
} |
hangfirePermission.AddChild(MessageServicePermissions.Hangfire.ManageQueue, L("Permission:ManageQueue")); |
||||
|
} |
||||
private static LocalizableString L(string name) |
|
||||
{ |
private static LocalizableString L(string name) |
||||
return LocalizableString.Create<MessageServiceResource>(name); |
{ |
||||
} |
return LocalizableString.Create<MessageServiceResource>(name); |
||||
} |
} |
||||
} |
} |
||||
|
} |
||||
|
|||||
@ -1,20 +1,20 @@ |
|||||
{ |
{ |
||||
"iisSettings": { |
"iisSettings": { |
||||
"windowsAuthentication": false, |
"windowsAuthentication": false, |
||||
"anonymousAuthentication": true, |
"anonymousAuthentication": true, |
||||
"iisExpress": { |
"iisExpress": { |
||||
"applicationUrl": "http://localhost:63963", |
"applicationUrl": "http://localhost:63963", |
||||
"sslPort": 0 |
"sslPort": 0 |
||||
} |
} |
||||
}, |
}, |
||||
"profiles": { |
"profiles": { |
||||
"LINGYUN.Abp.MessageService.HttpApi.Host": { |
"LINGYUN.Abp.MessageService.HttpApi.Host": { |
||||
"commandName": "Project", |
"commandName": "Project", |
||||
"launchBrowser": false, |
"launchBrowser": false, |
||||
"applicationUrl": "http://localhost:30020", |
"applicationUrl": "http://localhost:30020", |
||||
"environmentVariables": { |
"environmentVariables": { |
||||
"ASPNETCORE_ENVIRONMENT": "Development" |
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
Loading…
Reference in new issue