using Admin.NET.Core;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
namespace Admin.NET.Plugin.AiDOP.Infrastructure;
///
/// 按动态看板路由中的 moduleCode 校验对应 PC 看板菜单。
/// 权限来源仍是 PC 的 SysMenu/SysRoleMenu;非法或未授权模块一律拒绝。
///
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class RequireSmartOpsModuleMenuAttribute : Attribute, IAsyncAuthorizationFilter
{
private static readonly HashSet SupportedModules = new(StringComparer.OrdinalIgnoreCase)
{
"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S9"
};
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if (context.HttpContext.User?.Identity?.IsAuthenticated != true)
{
context.Result = new UnauthorizedResult();
return;
}
var moduleCode = context.RouteData.Values["moduleCode"]?.ToString()?.Trim().ToUpperInvariant();
if (string.IsNullOrWhiteSpace(moduleCode) || !SupportedModules.Contains(moduleCode))
{
context.Result = Forbid();
return;
}
var accessService = context.HttpContext.RequestServices.GetService();
if (accessService == null)
{
context.Result = Forbid();
return;
}
try
{
var suffix = moduleCode.ToLowerInvariant();
if (await accessService.HasMenuPathAsync($"/aidop/smart-ops/{suffix}") ||
await accessService.HasMenuPathAsync($"/aidop/kanban/{suffix}"))
return;
}
catch
{
// 权限基础设施异常时 fail-closed。
}
context.Result = Forbid();
}
private static ObjectResult Forbid() => new(new { message = "没有权限访问该功能" })
{
StatusCode = StatusCodes.Status403Forbidden
};
}