feat(system): 按 OAuth2 客户端 platform 过滤菜单,支持业务/物联双前端

问题:业务平台(biz)和物联运维平台(iot)共用一套用户体系和菜单表,但每个前端
只该看到自己域的菜单。原来没有按客户端过滤的机制。

方案:在 OAuth2 客户端维度打 platform 标签(biz/iot/NULL),菜单也打同样标签,
登录时下发菜单按二者匹配过滤。

链路:
- OAuth2AccessTokenCheckRespDTO / LoginUser(framework + gateway)新增 clientId 字段
- TokenAuthenticationFilter(framework + gateway)把 accessToken.clientId 带进 LoginUser
- WebFrameworkUtils.HEADER_CLIENT_ID="X-Client-Id":登录/refresh 等"无 token 入口"
  允许前端声明 client,避免硬编码 default
- AdminAuthServiceImpl.resolveClientId:未传 Header 时回退 OAuth2ClientConstants.CLIENT_ID_DEFAULT
- MenuDO / OAuth2ClientDO 各加 platform 列
- MenuService.filterMenusByPlatform:platform 为空(全平台共用)或匹配即保留

SQL 迁移按字母序编号:
- _01_oauth2_client_platform.sql:加列 + 给 default/iot-client 客户端打标 + 递归标
  IoT 菜单子树(root id=4000)为 iot
- _02_bulk_mark_biz_menus.sql:其余 platform=NULL 的菜单兜底标 biz
- 顺序依赖:_01 标完 iot 后 _02 才动剩余 NULL,避免 _02 把 IoT 菜单错标 biz

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
lzh
2026-04-24 13:32:26 +08:00
parent 4564eec893
commit cbbb048a4d
15 changed files with 729 additions and 559 deletions

View File

@@ -0,0 +1,51 @@
-- ============================================================
-- 多前端按 client → platform 过滤菜单
-- 配合后端代码AuthController.getPermissionInfo / MenuService.filterMenusByPlatform
-- 日期2026-04-20
--
-- platform 取值约定:
-- biz = 业务平台(对应 OAuth2 客户端 default
-- iot = 物联运维平台(对应 OAuth2 客户端 iot-client
-- NULL = 两个平台都展示(通用菜单,如系统管理、用户、部门等)
-- ============================================================
-- 1. system_oauth2_client 加 platform 列
ALTER TABLE `system_oauth2_client`
ADD COLUMN `platform` VARCHAR(10) NULL DEFAULT NULL
COMMENT '平台标识biz-业务平台iot-物联运维平台NULL-不按客户端过滤菜单'
AFTER `additional_information`;
-- 2. 矫正 system_menu.platform 列的注释(旧注释写的是 ops/sys与代码约定不一致更新为 biz/iot
ALTER TABLE `system_menu`
MODIFY COLUMN `platform` VARCHAR(10) NULL DEFAULT NULL
COMMENT '平台标识biz-业务平台iot-物联运维平台NULL-两个平台都展示';
-- 3. 给两个内部 SSO 客户端打 platform 标
-- 业务平台复用 yudao 默认 default 客户端 → biz
-- 物联运维平台用独立 iot-client → iot
UPDATE `system_oauth2_client` SET `platform` = 'biz' WHERE `client_id` = 'default';
UPDATE `system_oauth2_client` SET `platform` = 'iot' WHERE `client_id` = 'iot-client';
-- 4. 给 IoT 模块的菜单打 iot 标记。从 sql/mysql/system_menu.sql 看,
-- IoT 设备接入 root id=4000整个子树都属于 iot 平台。
UPDATE `system_menu` SET `platform` = 'iot'
WHERE `id` IN (
SELECT t.id FROM (
-- 递归取 4000 子树。MySQL 8 用 CTE旧版自行替换为多次 UPDATE
WITH RECURSIVE iot_tree(id) AS (
SELECT id FROM system_menu WHERE id = 4000
UNION ALL
SELECT m.id FROM system_menu m JOIN iot_tree it ON m.parent_id = it.id
)
SELECT id FROM iot_tree
) t
);
-- 5. 业务平台独有菜单标 biz可选不标的话默认 NULL = 两边都显示)
-- 例如 OA 示例id=5
-- UPDATE `system_menu` SET `platform` = 'biz' WHERE `id` IN (5);
-- 6. 系统管理 / 基础设施 / 用户 / 部门 / 字典 等通用菜单保持 NULL两边共用。
-- 7. 改完客户端后,记得在后台 OAuth2 客户端管理页面"保存"一次刷新缓存;
-- 或重启后端清缓存Redis key: oauth2_client

View File

@@ -0,0 +1,18 @@
-- ============================================================
-- 批量给「非 IoT 菜单」打上 platform='biz'
-- 策略iot 平台只看设备接入子树4000其余含系统管理、基础设施、OA、各 demo一律归业务平台
-- 日期2026-04-20
-- ============================================================
-- 所有 platform 还是 NULL 的,一律改为 biz
-- platform='iot' 的行已经在上一次迁移里设过,不会被动)
UPDATE system_menu
SET platform = 'biz'
WHERE deleted = 0 AND platform IS NULL;
-- 验证
SELECT platform, COUNT(*) AS cnt FROM system_menu WHERE deleted = 0 GROUP BY platform;
-- 预期:
-- biz = 大部分(系统管理/基础设施/OA/demos 等)
-- iot = 设备接入子树(~50
-- NULL = 0