AdoS8ConfigDataSourcesController.cs 4.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using Admin.NET.Plugin.AiDOP.Infrastructure.S8;
  2. using Admin.NET.Plugin.AiDOP.Const.S8;
  3. using Admin.NET.Plugin.AiDOP.Entity.S8;
  4. using Admin.NET.Plugin.AiDOP.Infrastructure;
  5. using Admin.NET.Plugin.AiDOP.Service.S8;
  6. namespace Admin.NET.Plugin.AiDOP.Controllers.S8;
  7. [ApiController]
  8. [Route("api/aidop/s8/config/data-sources")]
  9. [NonUnify]
  10. public class AdoS8ConfigDataSourcesController : ControllerBase
  11. {
  12. private readonly S8DataSourceService _svc;
  13. private readonly S8TrustedScopeResolver _scope;
  14. public AdoS8ConfigDataSourcesController(S8DataSourceService svc, S8TrustedScopeResolver scope)
  15. {
  16. _svc = svc;
  17. _scope = scope;
  18. }
  19. [HttpGet]
  20. [S8Permission(S8PermissionCatalog.ConfigRead)]
  21. public async Task<IActionResult> ListAsync([FromQuery] long tenantId = 1, [FromQuery] long factoryId = 1)
  22. {
  23. // Compatibility-only. Security scope is resolved server-side.
  24. _ = tenantId; _ = factoryId;
  25. var scope = await _scope.ResolveAsync();
  26. return Ok(await _svc.ListAsync(scope.TenantId, scope.FactoryId));
  27. }
  28. // ================================================================================
  29. // S8-LEGACY-RUNTIME-RETIREMENT-1:POST / PUT / DELETE / POST test 已退役 → 410 Gone。
  30. //
  31. // 410 而非 400/403/404 是刻意选择:语义为「该能力曾经存在、现已永久退役」。
  32. // 400 会暗示「改对入参还能存」,404 会暗示「换个 Id 还能存」,都与事实不符。
  33. //
  34. // ⚠️ catch 顺序:S8WriteRetiredException 必须排在 S8NotFoundException / S8BizException 之前,
  35. // 否则会被基类分支先接住、降级成 404/400。
  36. // 返回固定文案常量(不是 ex.ToString()/堆栈/类型名),避免泄漏内部实现。
  37. // GET 保持不变,存量 Legacy 规则绑定的数据源行仍可读(endpoint 已脱敏)。
  38. //
  39. // 作用域改用 RetiredWriteScope 占位而非 await _scope.ResolveAsync():
  40. // 能力既已退役,就不该为一个注定 410 的请求再去解析租户上下文。
  41. // Service 写方法必须在读取该占位值或访问任何仓储前抛 S8WriteRetiredException。
  42. // ================================================================================
  43. private static readonly S8TrustedScope RetiredWriteScope = new(0, 0);
  44. private IActionResult Retired() =>
  45. StatusCode(Microsoft.AspNetCore.Http.StatusCodes.Status410Gone,
  46. new { message = S8DataSourceService.RetiredMessage });
  47. [HttpPost]
  48. [S8Permission(S8PermissionCatalog.ConfigDataSource)]
  49. public async Task<IActionResult> CreateAsync([FromBody] AdoS8DataSource body)
  50. {
  51. try { return Ok(await _svc.CreateAsync(body, RetiredWriteScope)); }
  52. catch (S8WriteRetiredException) { return Retired(); }
  53. catch (S8NotFoundException) { return NotFound(); }
  54. catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); }
  55. }
  56. [HttpPut("{id:long}")]
  57. [S8Permission(S8PermissionCatalog.ConfigDataSource)]
  58. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS8DataSource body)
  59. {
  60. try { return Ok(await _svc.UpdateAsync(id, body, RetiredWriteScope)); }
  61. catch (S8WriteRetiredException) { return Retired(); }
  62. catch (S8NotFoundException) { return NotFound(); }
  63. catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); }
  64. }
  65. [HttpDelete("{id:long}")]
  66. [S8Permission(S8PermissionCatalog.ConfigDataSource)]
  67. public async Task<IActionResult> DeleteAsync(long id)
  68. {
  69. try { await _svc.DeleteAsync(id, RetiredWriteScope); }
  70. catch (S8WriteRetiredException) { return Retired(); }
  71. catch (S8NotFoundException) { return NotFound(); }
  72. return Ok();
  73. }
  74. [HttpPost("{id:long}/test")]
  75. [S8Permission(S8PermissionCatalog.ConfigDataSource)]
  76. public async Task<IActionResult> TestAsync(long id)
  77. {
  78. try { return Ok(await _svc.TestAsync(id, RetiredWriteScope)); }
  79. catch (S8WriteRetiredException) { return Retired(); }
  80. catch (S8NotFoundException) { return NotFound(); }
  81. catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); }
  82. }
  83. }