-- ============================================================================ -- 1.0.431 verify:租户 A 的 UAT_FUNCTION_USER 必须精确持有 sysOrg:list。 -- -- 为什么不能沿用 1.0.386.verify.sql 的口径: -- 旧断言是 `JOIN SysRole r ON ... WHERE r.Code = 'UAT_FUNCTION_USER' -- AND m.Permission = 'sysOrg:list'` 然后 COUNT(*)——按 RoleCode 跨租户聚合。 -- 同名角色在租户 A / B 各有一个(RoleId 838258976469061 / 838259499909189); -- 只要任一租户还留着这条绑定,COUNT 就 >0 判真。 -- 实测结果:租户 A 的绑定已被 GrantRoleMenu 全量覆盖删除,而旧 verify 因租户 B -- 仍在而一直判 Success —— 跨租户假阳性,权限二次丢失全程无告警。 -- -- 新口径:全部断言绑定到精确的 TenantId / RoleId / MenuId,且校验绑定确实归属 -- 租户 A,避免「错误 RoleId 恰好有该菜单」被误判成功。 -- -- 约定(AutoVersionUpdate.RunVerifyScriptIfExists,Core/Update/AutoVersionUpdate.cs:224): -- 每条语句取「首行首列」当布尔断言,必须为真;返回 0 行会得到 NULL 判假并中断启动。 -- 故每条断言一律返回标量真值,且不使用 SET(SET 不返回行 → 必然判假)。 -- -- 环境容错:目标 RoleId 不存在的库(非 UAT 夹具库)上主脚本为空操作, -- 四条断言同步短路为真。注意短路条件是精确 RoleId 缺失,不是 RoleCode。 -- ============================================================================ -- 1) 角色存在,且确实属于租户 A(RoleId 存在但租户不符 → 判假,不放行) SELECT IF( (SELECT COUNT(*) FROM SysRole WHERE Id = 838258976469061) = 0, 1, (SELECT COUNT(*) FROM SysRole WHERE Id = 838258976469061 AND TenantId = 838257186181189 AND Code = 'UAT_FUNCTION_USER' AND Status = 1) ) AS ok_role_in_tenant_a; -- 2) 菜单存在,且确实是 sysOrg:list 按钮(Type=3 Btn / 启用) SELECT IF( (SELECT COUNT(*) FROM SysRole WHERE Id = 838258976469061) = 0, 1, (SELECT COUNT(*) FROM SysMenu WHERE Id = 1300200030201 AND Permission = 'sysOrg:list' AND Type = 3 AND Status = 1) ) AS ok_menu_is_sysorg_list; -- 3) 租户 A 的 SysTenantMenu 允许该菜单(GetOwnBtnPermList 会 InnerJoin 它) SELECT IF( (SELECT COUNT(*) FROM SysRole WHERE Id = 838258976469061) = 0, 1, (SELECT COUNT(*) FROM SysTenantMenu WHERE TenantId = 838257186181189 AND MenuId = 1300200030201) ) AS ok_tenant_a_allows_menu; -- 4) SysRoleMenu 精确存在 1 条(既非缺失也非重复),且该绑定归属租户 A SELECT IF( (SELECT COUNT(*) FROM SysRole WHERE Id = 838258976469061) = 0, 1, (SELECT COUNT(*) = 1 FROM SysRoleMenu rm JOIN SysRole r ON r.Id = rm.RoleId JOIN SysMenu m ON m.Id = rm.MenuId WHERE rm.RoleId = 838258976469061 AND rm.MenuId = 1300200030201 AND r.TenantId = 838257186181189 AND m.Permission = 'sysOrg:list') ) AS ok_rolemenu_exactly_one_in_tenant_a;