using Admin.NET.Plugin.AiDOP.Const.S8; using Admin.NET.Plugin.AiDOP.Infrastructure; using Admin.NET.Plugin.AiDOP.Infrastructure.S8; using Admin.NET.Plugin.AiDOP.Service.S8; using Microsoft.AspNetCore.Mvc; namespace Admin.NET.Plugin.AiDOP.Controllers.S8; /// /// S8-ACTION-PERMISSION-1:「异常操作权限」配置。 /// /// 这是 S8 全局配置,不属于某一条规则 —— 它回答的是 /// 「哪些角色能对异常单做哪些动作」,与「这条规则由谁负责」(Rule Handler Pool) /// 是两个正交问题。刻意不放进规则弹窗:混在一起会让管理员以为改的是这条规则的权限, /// 实际改的是全租户。 /// [ApiController] [Route("api/aidop/s8/config/action-permissions")] [NonUnify] public class AdoS8ConfigActionPermissionController : ControllerBase { private readonly S8ExceptionActionRoleService _svc; private readonly S8TrustedScopeResolver _scope; private readonly IS8ExceptionActionAuthorizer _authorizer; public AdoS8ConfigActionPermissionController( S8ExceptionActionRoleService svc, S8TrustedScopeResolver scope, IS8ExceptionActionAuthorizer authorizer) { _svc = svc; _scope = scope; _authorizer = authorizer; } /// 权限矩阵(目录内每个动作一行,未配置的也返回,前端要能显示"未配置")。 [HttpGet] [S8Permission(S8PermissionCatalog.ConfigRead)] public async Task MatrixAsync() { try { return Ok(await _svc.GetMatrixAsync(await _scope.ResolveAsync())); } catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); } } /// 可授权角色(只列与 S8 相关的本租户角色,不机械返回全部)。 [HttpGet("roles")] [S8Permission(S8PermissionCatalog.ConfigRead)] public async Task RolesAsync() { try { return Ok(await _svc.GetAssignableRolesAsync(await _scope.ResolveAsync())); } catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); } } /// 当前账号被允许的动作码 —— 前端据此控制按钮可见性,避免点了才 403。 [HttpGet("mine")] [S8ExceptionAction(S8ExceptionActionCode.View)] public async Task MineAsync() { try { var allowed = await _svc.GetMyAllowedActionsAsync(await _scope.ResolveAsync(), _authorizer); return Ok(allowed.ToList()); } catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); } } /// 覆盖某动作的授权角色(全量替换)。角色必须属于当前租户。 [HttpPut("{actionCode}")] [S8Permission(S8PermissionCatalog.ConfigRoleWrite)] public async Task SetAsync(string actionCode, [FromBody] AdoS8ActionRoleSetDto? body) { try { await _svc.SetActionRolesAsync(await _scope.ResolveAsync(), actionCode, body?.RoleIds); return Ok(new { actionCode, roleCount = body?.RoleIds?.Count ?? 0 }); } catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); } } } public class AdoS8ActionRoleSetDto { /// 该动作的完整授权角色集合。传空数组 = 关闭该动作(fail closed)。 public List? RoleIds { get; set; } }