using Microsoft.AspNetCore.Mvc;
namespace Admin.NET.Plugin.AiDOP.Infrastructure;
///
/// S0 仓储基础资料的可信租户解析(写/读业务表统一取此值)。
///
/// 铁律(W-01/02/03 修复):
/// - 租户只来自认证后的 JWT claim(UserManager.TenantId),前端 payload 的 tenantId 一律忽略;
/// - 不使用任何固定默认租户兜底(区别于 QmsTenantScope.Current() 会回落 DefaultTenantId);
/// - 无有效租户(无 token → App.User 空 → TenantId=0)→ 拒绝;
/// - 超级管理员未显式选择目标租户(其 claim 即自身主租户 )→ 拒绝,
/// 必须在登录时选择目标租户(SysAuthService 支持超管登录传 tenantId 覆盖)。
///
public static class AdoS0TenantScope
{
/// 主/系统租户(超管自身归属,== QmsTenantScope.DefaultTenantId)。仅用作"超管未选租户"的拒绝哨兵,绝不作为业务数据归属。
public const long MainTenantId = 1300000000001L;
///
/// 解析当前请求的可信目标租户。成功返回 true 且 tenantId 为非空非 0 的有效租户;
/// 失败返回 false 且 error 为明确业务错误(调用方直接 return error)。
///
public static bool TryResolveRequired(out long tenantId, out IActionResult? error)
{
tenantId = 0;
error = null;
var um = App.GetRequiredService();
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;
}
}