Selaa lähdekoodia

fix(s8): 修复种子租户被误判「未配置有效工厂」导致工作台不可用

SmartOpsTrustedScopeRules.ResolveFactory 原判据 `orgId == tenantId` 会把
种子/SQL 脚本建的租户全部拒绝。Admin.NET 官方约定中,脚本建租户的根组织 Id
与租户 Id 同号(SysTenantSeedData「Id=OrgId=DefaultTenantId」+ SysOrgSeedData
根组织),只有界面 AddTenant 建的租户才另发雪花号。该形态属于「已配置组织」,
误判后「Ai-DOP 演示公司」等租户打开工作台直接抛异常、页面白板。

改动:
- ResolveFactory 判据收敛为仅 `orgId <= 0`,并补 remarks 说明同号约定
- 异常文案改为面向使用者:「当前租户尚未配置所属机构,请联系管理员在
  「租户管理」中完成配置」,S8ManualReportService 同口径同步
- 测试 MissingOrSelfFactory_IsRejected 拆分为 MissingOrg_IsRejected,
  新增 SeededTenant_WhoseRootOrgSharesTenantId_IsAccepted 锁定同号租户放行

chore: bump version server 1.0.383
YY968XX 1 kuukausi sitten
vanhempi
commit
12acf6f16e

+ 3 - 3
server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj

@@ -11,9 +11,9 @@
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <Copyright>Admin.NET</Copyright>
     <Description>Admin.NET 通用权限开发平台</Description>
-    <AssemblyVersion>1.0.382</AssemblyVersion>
-    <FileVersion>1.0.382</FileVersion>
-    <Version>1.0.382</Version>
+    <AssemblyVersion>1.0.383</AssemblyVersion>
+    <FileVersion>1.0.383</FileVersion>
+    <Version>1.0.383</Version>
   </PropertyGroup>
 
   <ItemGroup>

+ 16 - 3
server/Plugins/Admin.NET.Plugin.AiDOP.Tests/SmartOps/SmartOpsTrustedScopeTests.cs

@@ -12,6 +12,9 @@ public class SmartOpsTrustedScopeTests
     private const long FactoryA = 838257186320453;
     private const long FactoryB = 838257212858437;
 
+    /// <summary>种子/脚本建的租户(如 Ai-DOP 演示公司),根组织与租户同号。</summary>
+    private const long SeededTenant = 1300000000777;
+
     [Fact]
     public void PlatformTenant_IsRejected()
     {
@@ -41,12 +44,22 @@ public class SmartOpsTrustedScopeTests
     }
 
     [Fact]
-    public void MissingOrSelfFactory_IsRejected()
+    public void MissingOrg_IsRejected()
     {
         Assert.Throws<InvalidOperationException>(() =>
             SmartOpsTrustedScopeRules.ResolveFactory(TenantA, 0, FactoryA));
-        Assert.Throws<InvalidOperationException>(() =>
-            SmartOpsTrustedScopeRules.ResolveFactory(TenantA, TenantA, FactoryA));
+    }
+
+    /// <summary>
+    /// 种子/SQL 脚本建的租户,其根组织 Id 与租户 Id 同号(Admin.NET 官方约定,
+    /// 见 SysTenantSeedData「Id=OrgId=DefaultTenantId」与 SysOrgSeedData 根组织)。
+    /// 该形态是「已配置组织」,不得当成「未配置」拒绝。
+    /// </summary>
+    [Fact]
+    public void SeededTenant_WhoseRootOrgSharesTenantId_IsAccepted()
+    {
+        Assert.Equal(SeededTenant, SmartOpsTrustedScopeRules.ResolveFactory(SeededTenant, SeededTenant, null));
+        Assert.Equal(SeededTenant, SmartOpsTrustedScopeRules.ResolveFactory(SeededTenant, SeededTenant, FactoryA));
     }
 
     [Fact]

+ 10 - 2
server/Plugins/Admin.NET.Plugin.AiDOP/Infrastructure/SmartOpsTrustedScopeResolver.cs

@@ -52,10 +52,18 @@ public static class SmartOpsTrustedScopeRules
     /// <summary>
     /// 客户端工厂只是筛选建议。未授权或不存在时回落到租户 OrgId,不得使用外租户工厂。
     /// </summary>
+    /// <remarks>
+    /// 只判 <paramref name="orgId"/> 是否为空。
+    /// 不得再用 <c>orgId == tenantId</c> 判「未配置」:Admin.NET 种子/SQL 脚本建的租户
+    /// 其根组织 Id 与租户 Id 同号是官方约定(见 SysTenantSeedData「Id=OrgId=DefaultTenantId」
+    /// 与 SysOrgSeedData 根组织),只有界面 AddTenant 建的租户才另发雪花号。
+    /// 旧判据会把系统默认 / Ai-DOP 演示公司等种子租户全部误判为「未配置有效工厂」而拒绝服务。
+    /// </remarks>
     public static long ResolveFactory(long tenantId, long orgId, long? candidateFactoryId)
     {
-        if (orgId <= 0 || orgId == tenantId)
-            throw new InvalidOperationException("当前租户未配置有效工厂");
+        // 文案面向使用者:说清「是什么状态、该找谁、去哪里配」,不暴露表名/列名。
+        if (orgId <= 0)
+            throw new InvalidOperationException("当前租户尚未配置所属机构,请联系管理员在「租户管理」中完成配置");
 
         if (candidateFactoryId is > 0
             && candidateFactoryId.Value != tenantId

+ 1 - 1
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/S8ManualReportService.cs

@@ -127,7 +127,7 @@ public class S8ManualReportService : ITransient
             .Select(x => x.OrgId)
             .FirstAsync();
         if (factoryId <= 0)
-            throw new S8BizException("当前租户未配置有效工厂");
+            throw new S8BizException("当前租户尚未配置所属机构,请联系管理员在「租户管理」中完成配置");
         return (tenantId, factoryId);
     }