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 }; }