| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- -- ============================================================================
- -- 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
- );
|