AdoS0TenantScope.cs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. using Microsoft.AspNetCore.Mvc;
  2. namespace Admin.NET.Plugin.AiDOP.Infrastructure;
  3. /// <summary>
  4. /// S0 仓储基础资料的可信租户解析(写/读业务表统一取此值)。
  5. ///
  6. /// 铁律(W-01/02/03 修复):
  7. /// - 租户只来自认证后的 JWT claim(UserManager.TenantId),前端 payload 的 tenantId 一律忽略;
  8. /// - 不使用任何固定默认租户兜底(区别于 QmsTenantScope.Current() 会回落 DefaultTenantId);
  9. /// - 无有效租户(无 token → App.User 空 → TenantId=0)→ 拒绝;
  10. /// - 超级管理员未显式选择目标租户(其 claim 即自身主租户 <see cref="MainTenantId"/>)→ 拒绝,
  11. /// 必须在登录时选择目标租户(SysAuthService 支持超管登录传 tenantId 覆盖)。
  12. /// </summary>
  13. public static class AdoS0TenantScope
  14. {
  15. /// <summary>主/系统租户(超管自身归属,== QmsTenantScope.DefaultTenantId)。仅用作"超管未选租户"的拒绝哨兵,绝不作为业务数据归属。</summary>
  16. public const long MainTenantId = 1300000000001L;
  17. /// <summary>
  18. /// 解析当前请求的可信目标租户。成功返回 true 且 tenantId 为非空非 0 的有效租户;
  19. /// 失败返回 false 且 error 为明确业务错误(调用方直接 return error)。
  20. /// </summary>
  21. public static bool TryResolveRequired(out long tenantId, out IActionResult? error)
  22. {
  23. tenantId = 0;
  24. error = null;
  25. var um = App.GetRequiredService<UserManager>();
  26. var tid = um.TenantId; // 认证后的 JWT claim;无 token 时为 0
  27. if (tid <= 0)
  28. {
  29. error = AdoS0ApiErrors.InvalidRequest("无法确定当前租户,请重新登录或选择目标租户");
  30. return false;
  31. }
  32. // 超管的 claim 若等于自身主租户,视为"未选择目标租户"(不允许自动用超管自身/固定默认租户写业务数据)
  33. if (um.SuperAdmin && tid == MainTenantId)
  34. {
  35. error = AdoS0ApiErrors.InvalidRequest("超级管理员操作前必须选择目标租户");
  36. return false;
  37. }
  38. tenantId = tid;
  39. return true;
  40. }
  41. }