| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- using Microsoft.AspNetCore.Mvc;
- namespace Admin.NET.Plugin.AiDOP.Infrastructure;
- /// <summary>
- /// S0 仓储基础资料的可信租户解析(写/读业务表统一取此值)。
- ///
- /// 铁律(W-01/02/03 修复):
- /// - 租户只来自认证后的 JWT claim(UserManager.TenantId),前端 payload 的 tenantId 一律忽略;
- /// - 不使用任何固定默认租户兜底(区别于 QmsTenantScope.Current() 会回落 DefaultTenantId);
- /// - 无有效租户(无 token → App.User 空 → TenantId=0)→ 拒绝;
- /// - 超级管理员未显式选择目标租户(其 claim 即自身主租户 <see cref="MainTenantId"/>)→ 拒绝,
- /// 必须在登录时选择目标租户(SysAuthService 支持超管登录传 tenantId 覆盖)。
- /// </summary>
- public static class AdoS0TenantScope
- {
- /// <summary>主/系统租户(超管自身归属,== QmsTenantScope.DefaultTenantId)。仅用作"超管未选租户"的拒绝哨兵,绝不作为业务数据归属。</summary>
- public const long MainTenantId = 1300000000001L;
- /// <summary>
- /// 解析当前请求的可信目标租户。成功返回 true 且 tenantId 为非空非 0 的有效租户;
- /// 失败返回 false 且 error 为明确业务错误(调用方直接 return error)。
- /// </summary>
- public static bool TryResolveRequired(out long tenantId, out IActionResult? error)
- {
- tenantId = 0;
- error = null;
- var um = App.GetRequiredService<UserManager>();
- var tid = um.TenantId; // 认证后的 JWT claim;无 token 时为 0
- if (tid <= 0)
- {
- error = AdoS0ApiErrors.InvalidRequest("无法确定当前租户,请重新登录或选择目标租户");
- return false;
- }
- // 超管的 claim 若等于自身主租户,视为"未选择目标租户"(不允许自动用超管自身/固定默认租户写业务数据)
- if (um.SuperAdmin && tid == MainTenantId)
- {
- error = AdoS0ApiErrors.InvalidRequest("超级管理员操作前必须选择目标租户");
- return false;
- }
- tenantId = tid;
- return true;
- }
- /// <summary>
- /// Service 层(无 IActionResult 上下文,如取号/编号服务)统一的可信租户解析。
- /// 语义与 <see cref="TryResolveRequired"/> 完全一致(同一 JWT 来源、同样拒绝无租户/超管未选),
- /// 但解析失败时抛出业务异常而非返回错误结果。绝不回退固定默认租户、绝不读前端 tenantId。
- /// </summary>
- public static long ResolveRequiredOrThrow()
- {
- var um = App.GetRequiredService<UserManager>();
- var tid = um.TenantId;
- if (tid <= 0)
- throw Oops.Oh("无法确定当前租户,请重新登录或选择目标租户");
- if (um.SuperAdmin && tid == MainTenantId)
- throw Oops.Oh("超级管理员操作前必须选择目标租户");
- return tid;
- }
- }
|