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