2025-01-24 22:42:26 +08:00
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
|
|
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
|
|
|
|
|
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
|
|
|
|
|
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
|
|
|
|
|
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
|
|
|
|
|
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
|
|
|
|
|
// 使用文档:https://thingsgateway.cn/
|
|
|
|
|
|
// QQ群:605534569
|
|
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
|
|
|
|
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
|
|
|
|
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
|
|
|
|
|
|
|
|
|
|
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
|
|
|
|
|
|
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
|
2025-07-13 22:47:14 +08:00
|
|
|
|
using ThingsGateway.Common.Extension;
|
2025-01-24 22:42:26 +08:00
|
|
|
|
|
|
|
|
|
|
namespace ThingsGateway.Admin.Application;
|
|
|
|
|
|
|
|
|
|
|
|
internal sealed class ApiPermissionService : IApiPermissionService
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly IApiDescriptionGroupCollectionProvider _apiDescriptionGroupCollectionProvider;
|
|
|
|
|
|
|
|
|
|
|
|
public ApiPermissionService(
|
|
|
|
|
|
IOptions<SwaggerGeneratorOptions> generatorOptions,
|
|
|
|
|
|
IApiDescriptionGroupCollectionProvider apiDescriptionGroupCollectionProvider)
|
|
|
|
|
|
{
|
|
|
|
|
|
_apiDescriptionGroupCollectionProvider = apiDescriptionGroupCollectionProvider;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
|
public List<OpenApiPermissionTreeSelector> ApiPermissionTreeSelector()
|
|
|
|
|
|
{
|
|
|
|
|
|
var cacheKey = $"{nameof(ApiPermissionTreeSelector)}-{CultureInfo.CurrentUICulture.Name}";
|
|
|
|
|
|
var permissions = App.CacheService.Get<List<OpenApiPermissionTreeSelector>>(cacheKey);
|
|
|
|
|
|
if (permissions == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
permissions = new();
|
|
|
|
|
|
|
|
|
|
|
|
Dictionary<string, OpenApiPermissionTreeSelector> groupOpenApis = new();
|
2025-05-12 10:21:41 +08:00
|
|
|
|
|
|
|
|
|
|
var apiDescriptions = _apiDescriptionGroupCollectionProvider.ApiDescriptionGroups.Items;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item1 in apiDescriptions)
|
2025-01-24 22:42:26 +08:00
|
|
|
|
{
|
2025-05-12 10:21:41 +08:00
|
|
|
|
foreach (var item in item1.Items)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (item.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
|
|
|
|
|
|
{
|
|
|
|
|
|
OpenApiPermissionTreeSelector openApiPermissionTreeSelector = new() { ApiName = controllerActionDescriptor.ControllerName ?? "Default" };
|
|
|
|
|
|
groupOpenApis.TryAdd(openApiPermissionTreeSelector.ApiName, openApiPermissionTreeSelector);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取所有需要数据权限的控制器
|
|
|
|
|
|
var controllerTypes =
|
|
|
|
|
|
App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(RolePermissionAttribute), false));
|
|
|
|
|
|
|
2025-05-12 10:21:41 +08:00
|
|
|
|
//foreach (var groupOpenApi in groupOpenApis)
|
2025-01-24 22:42:26 +08:00
|
|
|
|
{
|
|
|
|
|
|
foreach (var apiDescriptionGroup in apiDescriptions)
|
|
|
|
|
|
{
|
|
|
|
|
|
var routes = apiDescriptionGroup.Items.Where(api => api.ActionDescriptor is ControllerActionDescriptor);
|
|
|
|
|
|
|
|
|
|
|
|
Dictionary<string, OpenApiPermissionTreeSelector> openApiPermissionTreeSelectorDict = new();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var route in routes)
|
|
|
|
|
|
{
|
|
|
|
|
|
var actionDesc = (ControllerActionDescriptor)route.ActionDescriptor;
|
|
|
|
|
|
if (!actionDesc.ControllerTypeInfo.CustomAttributes.Any(a => a.AttributeType == typeof(RolePermissionAttribute)))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
var controllerDescription = actionDesc.ControllerTypeInfo.GetTypeDisplayName();
|
|
|
|
|
|
|
|
|
|
|
|
if (openApiPermissionTreeSelectorDict.TryGetValue(actionDesc.ControllerName, out var openApiControllerGroup))
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
openApiControllerGroup = new() { ApiName = controllerDescription, ApiRoute = actionDesc.ControllerName };
|
|
|
|
|
|
|
|
|
|
|
|
openApiPermissionTreeSelectorDict.Add(actionDesc.ControllerName, openApiControllerGroup);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var ignoreRolePermission = actionDesc.MethodInfo.CustomAttributes.Any(a => a.AttributeType == typeof(IgnoreRolePermissionAttribute));
|
|
|
|
|
|
if (ignoreRolePermission)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
var routePath = route.RelativePath;
|
|
|
|
|
|
var methodDesc = actionDesc.MethodInfo.DeclaringType.GetMethodDisplayName(actionDesc.MethodInfo.Name);
|
|
|
|
|
|
|
|
|
|
|
|
//添加到权限列表
|
|
|
|
|
|
openApiControllerGroup.Children ??= new();
|
|
|
|
|
|
openApiControllerGroup.Children.Add(new OpenApiPermissionTreeSelector
|
|
|
|
|
|
{
|
|
|
|
|
|
ApiName = methodDesc,
|
|
|
|
|
|
ApiRoute = routePath,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-12 10:21:41 +08:00
|
|
|
|
if (openApiPermissionTreeSelectorDict.Values.Any(a => a.Children.Count > 0))
|
|
|
|
|
|
permissions.AddRange(openApiPermissionTreeSelectorDict.Values);
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
App.CacheService.Set(cacheKey, permissions);
|
|
|
|
|
|
}
|
|
|
|
|
|
return permissions;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取路由地址名称
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="controllerName">控制器地址</param>
|
|
|
|
|
|
/// <param name="template">路由名称</param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public string GetRouteName(string controllerName, string template)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!template.StartsWith('/'))
|
|
|
|
|
|
template = "/" + template;//如果路由名称不是/开头则加上/防止控制器没写
|
|
|
|
|
|
if (template.Contains("[controller]"))
|
|
|
|
|
|
{
|
|
|
|
|
|
controllerName = controllerName.Replace("Controller", "");//去掉Controller
|
|
|
|
|
|
controllerName = controllerName.ToLowerCamelCase();//转首字母小写写
|
|
|
|
|
|
template = template.Replace("[controller]", controllerName);//替换[controller]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return template;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
|
public IEnumerable<PermissionTreeSelector> PermissionTreeSelector(IEnumerable<string> routes)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<PermissionTreeSelector> permissions = PermissionTreeSelector();
|
2025-03-09 10:22:05 +08:00
|
|
|
|
var hashSet = routes.ToHashSet();
|
|
|
|
|
|
return permissions.Where(a => hashSet.Contains(a.ApiRoute));
|
2025-01-24 22:42:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
|
public List<PermissionTreeSelector> PermissionTreeSelector()
|
|
|
|
|
|
{
|
|
|
|
|
|
var cacheKey = $"{nameof(PermissionTreeSelector)}-{CultureInfo.CurrentUICulture.Name}";
|
|
|
|
|
|
var permissions = App.CacheService.GetOrAdd(cacheKey, entry =>
|
|
|
|
|
|
{
|
|
|
|
|
|
List<PermissionTreeSelector> permissions = new();//权限列表
|
|
|
|
|
|
|
|
|
|
|
|
// 获取所有需要数据权限的控制器
|
|
|
|
|
|
var controllerTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
|
|
|
|
|
|
&& u.IsDefined(typeof(AuthorizeAttribute), false)
|
|
|
|
|
|
&& u.IsDefined(typeof(Microsoft.AspNetCore.Components.RouteAttribute), false));
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var controller in controllerTypes)
|
|
|
|
|
|
{
|
|
|
|
|
|
//获取数据权限特性
|
|
|
|
|
|
var route = controller.GetCustomAttributes<Microsoft.AspNetCore.Components.RouteAttribute>().FirstOrDefault();
|
|
|
|
|
|
if (route == null) continue;
|
|
|
|
|
|
var apiRoute = GetRouteName(controller.Name, route.Template);//赋值路由名称
|
|
|
|
|
|
|
|
|
|
|
|
var desc = controller.GetTypeDisplayName();
|
|
|
|
|
|
//添加到权限列表
|
|
|
|
|
|
permissions.Add(new PermissionTreeSelector
|
|
|
|
|
|
{
|
|
|
|
|
|
ApiName = desc,
|
|
|
|
|
|
ApiRoute = apiRoute,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
return permissions;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return permissions;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|