using Admin.NET.Plugin.AiDOP.Const.S8;
using Admin.NET.Plugin.AiDOP.Dto.S8;
using Admin.NET.Plugin.AiDOP.Infrastructure;
using Admin.NET.Plugin.AiDOP.Infrastructure.S8;
using Admin.NET.Plugin.AiDOP.Service.S8;
namespace Admin.NET.Plugin.AiDOP.Controllers.S8;
///
/// S8 配置页:操作员(员工)↔ 系统账号绑定 / 可绑账号查询。
/// 入口收口在 /aidop/s8/config/roles,与 S8 配置中心同源。
///
/// S8-P0-3-MASTERDATA-TRUSTED-SCOPE-1:本控制器原先是
/// KNOWN-ISSUES I-001 里「6 个未接入可信作用域解析」之一,且是其中**唯一被实测利用**的越权面
/// —— 普通租户账号调 GET /config/operator-bindings(不带任何参数)可拿到 500 条
/// 其它租户员工的工号与真实姓名。现已接入 。
///
/// 入参语义:factoryRefId 已从所有 Action 签名移除。客户端(含前端
/// withAidopTenantFactoryParams)仍可能继续携带该 query/body 字段,ASP.NET 会直接丢弃,
/// **不产生任何授权效果**。Body 里的 AdoS8OperatorBindingCreateDto.FactoryRefId 同理不被读取。
///
[ApiController]
[Route("api/aidop/s8/config")]
[NonUnify]
public class AdoS8ConfigBindingsController : ControllerBase
{
private readonly S8OperatorBindingService _svc;
private readonly S8TrustedScopeResolver _scope;
public AdoS8ConfigBindingsController(S8OperatorBindingService svc, S8TrustedScopeResolver scope)
{
_svc = svc;
_scope = scope;
}
[HttpGet("operator-bindings")]
[S8Permission(S8PermissionCatalog.ConfigRead)]
public async Task ListAsync(
[FromQuery] string? bindStatus = null,
[FromQuery] string? keyword = null)
{
try { return Ok(await _svc.ListAsync(await _scope.ResolveAsync(), bindStatus, keyword)); }
catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); }
}
[HttpPost("operator-bindings")]
[S8Permission(S8PermissionCatalog.ConfigOperatorBind)]
public async Task BindAsync([FromBody] AdoS8OperatorBindingCreateDto body)
{
try { return Ok(await _svc.BindAsync(await _scope.ResolveAsync(), body)); }
catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); }
}
[HttpDelete("operator-bindings/{employeeId:long}")]
[S8Permission(S8PermissionCatalog.ConfigOperatorBind)]
public async Task UnbindAsync(long employeeId)
{
try { await _svc.UnbindAsync(await _scope.ResolveAsync(), employeeId); return Ok(new { employeeId }); }
catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); }
}
[HttpGet("sys-users")]
[S8Permission(S8PermissionCatalog.ConfigRead)]
public async Task SysUsersAsync(
[FromQuery] string? keyword = null,
[FromQuery] long? excludeEmployeeId = null)
{
try { return Ok(await _svc.ListSysUsersAsync(await _scope.ResolveAsync(), keyword, excludeEmployeeId)); }
catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); }
}
}