1.0.433.sql 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. -- ============================================================================
  2. -- 1.0.433:把 S5 库存冷链入站管理接口纳入按钮权限管控(P0 权限治理)
  3. --
  4. -- 缺陷(CODE VERIFIED + RUNTIME VERIFIED):
  5. -- JwtHandler.CheckAuthorizeAsync(Admin.NET.Web.Core/Handlers/JwtHandler.cs:74-97)
  6. -- 的判定是:
  7. -- ① 超管(AccountType=999) 直接放行;
  8. -- ② 命中「自有按钮权限」放行;
  9. -- ③ 否则——**只要该路由名未登记为任何按钮权限,就兜底放行**。
  10. -- /api/S5InventoryInbound/* 六个 POST 管理接口全部未登记,一律走 ③ 兜底放行,
  11. -- 任何已登录用户(含 AccountType=777 普通业务账号)都能触发库存贴源/物化/重建。
  12. -- 实测:UATAdminA(777 普通用户)成功调用 reconcile 与 transform-inventory-std。
  13. --
  14. -- 权限名为什么必须是路由派生名:
  15. -- JwtHandler 把 /api/A/B 映射为权限名 A:B(Path.Value[5..] 把 '/' 换成 ':'),
  16. -- 再与用户自有权限做**忽略大小写的全等比较**。因此单个 s5InventoryInbound:admin
  17. -- 无法覆盖多个路由——必须逐接口登记,权限名等于各自路由派生名。
  18. -- 参照系统内已生效的先例 sysOrg:list ← /api/sysOrg/list(SysMenu Id=1300200030201)。
  19. -- 注:S8 的 s8:exception:* 属前端 v-auth 权限点,其路由为 /api/aidop/s8/...
  20. -- (派生名 aidop:s8:...),并不参与 JwtHandler 鉴权,不能作为本次命名依据。
  21. --
  22. -- 授权对象(依据真实 AccountType / RoleId,不按账号名猜):
  23. -- SysMenuService.GetOwnBtnPermList(Service/Menu/SysMenuService.cs:336-357)对
  24. -- AccountType=888(SysAdmin) 且未绑定任何角色的账号,返回「该租户 SysTenantMenu
  25. -- 允许的全部按钮权限」。租户 797403760988229 的 AIDopAdmin 正是此形态(888、无角色),
  26. -- 故只需给该租户加租户级菜单授权即可获得管理能力。
  27. -- → 本脚本**不新建角色、不写任何 SysRoleMenu**,普通业务角色一律无权。
  28. --
  29. -- 明确不做:
  30. -- - 不给 UAT 租户(838257186181189)加租户级授权(该租户 6 个账号全为 777 普通用户,
  31. -- 无任何 SysAdmin,不应具备库存重建能力)
  32. -- - 不给 UAT_FUNCTION_USER / ROLE_WH_* / ROLE_QC 等任何业务角色授权
  33. -- - 不使用 GrantRoleMenu(其语义是「删角色全部 SysRoleMenu 再全量重建」)
  34. -- - 不按 RoleCode 跨租户模糊授权
  35. -- - 不改任何既有菜单、不改任何既有角色权限
  36. -- - 不改库存同步/STD/LIVE 数据逻辑
  37. --
  38. -- 幂等:全部 INSERT 带 NOT EXISTS(菜单按 Permission,租户授权按 TenantId+MenuId)。
  39. -- 重复执行 affected rows = 0。
  40. --
  41. -- ⚠️ 缓存:JwtHandler 用 GetAllBtnPermList(缓存键 sys_user_button:0)判断「是否已登记」,
  42. -- GetOwnBtnPermList 缓存键 sys_user_button:<userId>,均为进程内 Memory 缓存
  43. -- (Cache.json:7 CacheType=Memory),SQL 写库不会使其失效。
  44. -- AutoVersionUpdate 在应用启动时执行本脚本,该进程缓存本就为空,随发布重启天然生效;
  45. -- 若在已运行实例上手工执行,必须重启后端。
  46. -- ============================================================================
  47. -- ---------------------------------------------------------------------------
  48. -- 0. 作用域解析(不硬编码租户 Id,按 SysOrg.Code 反查,与 1.0.402/1.0.408 一致)
  49. -- ---------------------------------------------------------------------------
  50. SET @admin_tenant := (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id = t.OrgId
  51. WHERE o.Code = 'AIDOP' AND t.Status = 1 LIMIT 1);
  52. -- 挂载点:S5 / 库存数据 / 库存查询(Type=2 页面菜单)。冷链入站即该页数据的来源。
  53. SET @parent_menu := (SELECT Id FROM SysMenu
  54. WHERE Name = 'aidopS5InventoryStockQuery' AND Type = 2 LIMIT 1);
  55. -- ---------------------------------------------------------------------------
  56. -- 1. 登记 6 个按钮权限(权限名 = 路由派生名,逐接口)
  57. -- ---------------------------------------------------------------------------
  58. INSERT INTO SysMenu (Id, Pid, Type, Name, Permission, Title, Icon,
  59. IsIframe, IsHide, IsKeepAlive, IsAffix, OrderNo, Status, Remark, CreateTime)
  60. SELECT s.Id, @parent_menu, 3, s.Name, s.Permission, s.Title, 'ele-Menu',
  61. 0, 0, 1, 0, s.OrderNo, 1, s.Remark, NOW()
  62. FROM (
  63. SELECT 1329015030101 AS Id, 'aidopS5InvInboundBtn01' AS Name,
  64. 's5InventoryInbound:bootstrap' AS Permission,
  65. '库存冷链首刷' AS Title, 910 AS OrderNo,
  66. 'S5 冷链管理权限点 POST /api/S5InventoryInbound/bootstrap(写 STG + 全量替换 STD)' AS Remark
  67. UNION ALL SELECT 1329015030102, 'aidopS5InvInboundBtn02',
  68. 's5InventoryInbound:run-once',
  69. '库存冷链跑一轮', 920,
  70. 'S5 冷链管理权限点 POST /api/S5InventoryInbound/run-once(写 STG + UPSERT STD)'
  71. UNION ALL SELECT 1329015030103, 'aidopS5InvInboundBtn03',
  72. 's5InventoryInbound:reconcile',
  73. '库存冷链全量校准', 930,
  74. 'S5 冷链管理权限点 POST /api/S5InventoryInbound/reconcile(写 STG + 全量替换 STD)'
  75. UNION ALL SELECT 1329015030104, 'aidopS5InvInboundBtn04',
  76. 's5InventoryInbound:transform-std',
  77. '库存流水 stg→std 补转换', 940,
  78. 'S5 冷链管理权限点 POST /api/S5InventoryInbound/transform-std(写 mdp_std_inv_trans)'
  79. UNION ALL SELECT 1329015030105, 'aidopS5InvInboundBtn05',
  80. 's5InventoryInbound:transform-inventory-std',
  81. '库存余额 stg→std 补物化', 950,
  82. 'S5 冷链管理权限点 POST /api/S5InventoryInbound/transform-inventory-std(写 mdp_std_inventory)'
  83. UNION ALL SELECT 1329015030106, 'aidopS5InvInboundBtn06',
  84. 's5InventoryInbound:daily-recon',
  85. '库存日终对账(手工)', 960,
  86. 'S5 冷链管理权限点 POST /api/S5InventoryInbound/daily-recon(写 ado_inventory_recon_diff)'
  87. ) s
  88. WHERE @parent_menu IS NOT NULL
  89. AND NOT EXISTS (SELECT 1 FROM SysMenu m WHERE m.Permission = s.Permission AND m.Type = 3);
  90. -- ---------------------------------------------------------------------------
  91. -- 2. 租户级授权:只给拥有真实 SysAdmin 运维账号的租户(AIDOP)
  92. -- 不给 UAT 租户,不给默认租户(超管走 AccountType=999 旁路,无需授权)
  93. -- ---------------------------------------------------------------------------
  94. SET @tm_base := (SELECT IFNULL(MAX(Id), 0) FROM SysTenantMenu);
  95. INSERT INTO SysTenantMenu (Id, TenantId, MenuId)
  96. SELECT @tm_base + ROW_NUMBER() OVER (ORDER BY m.Id), @admin_tenant, m.Id
  97. FROM SysMenu m
  98. WHERE @admin_tenant IS NOT NULL
  99. AND m.Type = 3
  100. AND m.Permission IN (
  101. 's5InventoryInbound:bootstrap',
  102. 's5InventoryInbound:run-once',
  103. 's5InventoryInbound:reconcile',
  104. 's5InventoryInbound:transform-std',
  105. 's5InventoryInbound:transform-inventory-std',
  106. 's5InventoryInbound:daily-recon')
  107. AND NOT EXISTS (
  108. SELECT 1 FROM SysTenantMenu tm
  109. WHERE tm.TenantId = @admin_tenant AND tm.MenuId = m.Id);