AdoS8ConfigAlertRulesController.cs 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. using Admin.NET.Plugin.AiDOP.Entity.S8;
  2. using Admin.NET.Plugin.AiDOP.Infrastructure;
  3. using Admin.NET.Plugin.AiDOP.Service.S8;
  4. namespace Admin.NET.Plugin.AiDOP.Controllers.S8;
  5. [ApiController]
  6. [Route("api/aidop/s8/config/alert-rules")]
  7. [NonUnify]
  8. public class AdoS8ConfigAlertRulesController : ControllerBase
  9. {
  10. // 写能力已永久退役:不得为了构造一个不会被使用的 scope 而读取组织库。
  11. // Service 写方法必须在读取该占位值或访问任何仓储前抛 S8WriteRetiredException。
  12. private static readonly S8TrustedScope RetiredWriteScope = new(0, 0);
  13. private readonly S8AlertRuleService _svc;
  14. private readonly S8TrustedScopeResolver _scope;
  15. public AdoS8ConfigAlertRulesController(S8AlertRuleService svc, S8TrustedScopeResolver scope)
  16. {
  17. _svc = svc;
  18. _scope = scope;
  19. }
  20. [HttpGet]
  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-STEP6D-CFG-ALERT-LEGACY-WRITE-GUARD-CERT-1:POST / PUT / DELETE 已退役 → 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 保持不变,历史兼容数据仍可读。
  38. // ================================================================================
  39. private IActionResult Retired() =>
  40. StatusCode(Microsoft.AspNetCore.Http.StatusCodes.Status410Gone,
  41. new { message = S8WriteRetiredException.UserMessage });
  42. [HttpPost]
  43. public async Task<IActionResult> CreateAsync([FromBody] AdoS8AlertRule body)
  44. {
  45. try { return Ok(await _svc.CreateAsync(body, RetiredWriteScope)); }
  46. catch (S8WriteRetiredException) { return Retired(); }
  47. catch (S8NotFoundException) { return NotFound(); }
  48. catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); }
  49. }
  50. [HttpPut("{id:long}")]
  51. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS8AlertRule body)
  52. {
  53. try { return Ok(await _svc.UpdateAsync(id, body, RetiredWriteScope)); }
  54. catch (S8WriteRetiredException) { return Retired(); }
  55. catch (S8NotFoundException) { return NotFound(); }
  56. catch (S8BizException ex) { return BadRequest(new { message = ex.Message }); }
  57. }
  58. [HttpDelete("{id:long}")]
  59. public async Task<IActionResult> DeleteAsync(long id)
  60. {
  61. try { await _svc.DeleteAsync(id, RetiredWriteScope); }
  62. catch (S8WriteRetiredException) { return Retired(); }
  63. catch (S8NotFoundException) { return NotFound(); }
  64. return Ok();
  65. }
  66. }