1.0.431.sql 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. -- ============================================================================
  2. -- 1.0.431:恢复 UAT 租户 A 的 UAT_FUNCTION_USER 角色的 sysOrg:list 按钮权限
  3. --
  4. -- 症状:
  5. -- UATAdminA(Id=838257187360837,AccountType=777 普通账号,非超管)打开任意 S0
  6. -- 页面时弹两个「403 禁止访问,没有权限」。
  7. --
  8. -- 链路(CODE VERIFIED):
  9. -- Web/src/views/aidop/s0/sales/ProductDesignCycleList.vue → loadOptions()
  10. -- → loadOrgList('201') / loadOrgList('501')(s0SalesApi.ts:765)
  11. -- → 两次 GET /api/sysOrg/list
  12. -- JwtHandler.CheckAuthorizeAsync(Admin.NET.Web.Core/Handlers/JwtHandler.cs:85)
  13. -- 把路径映射为按钮权限名 sysOrg:list;非超管必须命中自有按钮权限,
  14. -- 未命中时仅当该权限「未登记为按钮权限」才兜底放行。
  15. -- sysOrg:list 已登记(SysMenu Id=1300200030201,Type=3 Btn),
  16. -- 而该角色未授权 → 授权失败 → AdminResultProvider.cs:84 返回
  17. -- 「403 禁止访问,没有权限」。两次请求 → 两个弹窗。
  18. --
  19. -- 为什么 1.0.386 补过又丢了(DB VERIFIED):
  20. -- 1.0.386 于 2026-08-24 13:21 Success(affected_rows=4),同时给 A/B 两个租户的
  21. -- 同名角色补了权限,Id 依次为 …807686(租户 A)与 …807687(租户 B)。
  22. -- 当前 …807687 仍在,…807686 已不存在;且租户 A 该角色现有 290 条 SysRoleMenu
  23. -- 的 Id 为一整段连续块(843881101070405~843881101086842),
  24. -- 是 SysRoleMenuService.GrantRoleMenu(Role/SysRoleMenuService.cs:73)
  25. -- 「先 DELETE 该角色全部 SysRoleMenu,再按 UI 勾选项全量 INSERT」的签名。
  26. -- → 管理员在「角色管理 → 授权菜单」重存该角色、未勾选机构管理,
  27. -- 把 migration 单独补的这条冲掉了。
  28. --
  29. -- 本脚本口径:精确到单租户单角色单菜单,不按 RoleCode 跨租户批量补。
  30. -- TenantId = 838257186181189(租户 A)
  31. -- RoleId = 838258976469061(租户 A 的 UAT_FUNCTION_USER)
  32. -- MenuId = 1300200030201(sysOrg:list,Type=3 Btn)
  33. --
  34. -- 明确不做:
  35. -- - 不按 RoleCode 给所有租户补权限(1.0.386 的口径,已证明会掩盖单租户丢失)
  36. -- - 不改租户 B 的 RoleId=838259499909189(仅作对照)
  37. -- - 不改其他任何角色
  38. -- - 不改 SysMenu、不改 SysTenantMenu
  39. -- - 不放开 sysOrg:add / sysOrg:update / sysOrg:delete
  40. -- - 无 DDL、无 DELETE、无业务数据写入
  41. --
  42. -- 已知连带影响(不可避免,且与对照租户 B 现状一致):
  43. -- SysMenuService.GetLoginMenuTree 在过滤 Type != Btn 之后,会对角色菜单集合做
  44. -- ExpandMenuIdsWithAncestorsAsync(SysMenuService.cs:65/441)祖先补全。
  45. -- 补入 Btn 1300200030201 后,其祖先「机构管理」(1300200030101, Type=2) 会被补进
  46. -- 菜单树;租户 A 的 SysTenantMenu 允许该菜单,故 UATAdminA 侧边栏会新增
  47. -- 「系统管理 / 机构管理」入口(只读可用,add/update/delete 仍会 403)。
  48. -- 租户 B 的同名角色已是同一形态,本脚本使 A 与 B 对齐。
  49. --
  50. -- ID 策略:沿用 UpdateScripts 既有写法(1.0.386 / 1.0.406)
  51. -- SET @base := (SELECT IFNULL(MAX(Id),0) FROM SysRoleMenu); INSERT ... @base + 1
  52. --
  53. -- 幂等:INSERT ... SELECT ... FROM DUAL WHERE <全部前置条件> AND NOT EXISTS(...)。
  54. -- 重复执行 affected rows = 0,不会产生第二条记录。
  55. --
  56. -- 环境容错:以上 Id 在不存在该 UAT 夹具的库上均查不到 → 整脚本为空操作,
  57. -- verify 同步短路为真(见 1.0.431.verify.sql)。
  58. --
  59. -- ⚠️ 缓存:GetOwnBtnPermList 结果按 sys_user_button:<userId> 缓存 7 天
  60. -- (SysMenuService.cs:355,CacheConst.KeyUserButton),当前 CacheType=Memory
  61. -- (Admin.NET.Application/Configuration/Cache.json:7)为进程内缓存,
  62. -- SQL 写库不会使其失效。AutoVersionUpdate 在应用启动时执行本脚本,
  63. -- 该进程缓存本就为空,故随发布重启天然生效;若在已运行实例上手工执行,
  64. -- 需另行清缓存(见报告「缓存处理」)。
  65. -- ============================================================================
  66. SET @orglist_tenant := 838257186181189;
  67. SET @orglist_role := (SELECT r.Id FROM SysRole r
  68. WHERE r.Id = 838258976469061
  69. AND r.TenantId = 838257186181189
  70. AND r.Code = 'UAT_FUNCTION_USER'
  71. AND r.Status = 1
  72. LIMIT 1);
  73. SET @orglist_menu := (SELECT m.Id FROM SysMenu m
  74. WHERE m.Id = 1300200030201
  75. AND m.Permission = 'sysOrg:list'
  76. AND m.Type = 3
  77. AND m.Status = 1
  78. LIMIT 1);
  79. SET @orglist_rm_base := (SELECT IFNULL(MAX(Id), 0) FROM SysRoleMenu);
  80. INSERT INTO SysRoleMenu (Id, RoleId, MenuId)
  81. SELECT @orglist_rm_base + 1, @orglist_role, @orglist_menu
  82. FROM DUAL
  83. WHERE @orglist_role IS NOT NULL
  84. AND @orglist_menu IS NOT NULL
  85. AND EXISTS (
  86. SELECT 1 FROM SysTenantMenu t
  87. WHERE t.TenantId = @orglist_tenant
  88. AND t.MenuId = @orglist_menu
  89. )
  90. AND NOT EXISTS (
  91. SELECT 1 FROM SysRoleMenu x
  92. WHERE x.RoleId = @orglist_role
  93. AND x.MenuId = @orglist_menu
  94. );