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