-- 汇安融订单管理:新增「退款」权限点(2026-09-28) -- -- 执行人:用户。本平台没有直连该库的通道,所以这份脚本**由我编写、只由你执行**。 -- 本脚本是幂等的:重复执行不会产生第二行(两处 INSERT 都带 NOT EXISTS)。 -- -- 为什么是新增一个权限点,而不是复用 sync / create: -- PermissionCheck.hasAny 是按 authorities 集合做**精确匹配**(全等)。 -- 复用 sync 的后果不是「少一层保护」而是**放大权限** —— 能查一笔单的人就能把钱退了。 -- 后端那一侧由 HarOrderControllerTest#refund_hasItsOwnPermission_notReusedFromAnyOtherEndpoint -- 钉住,这里这一行必须与它逐字一致:module_payment:har:order:refund -- -- 谁拿到这个权限: -- role 1 = ADMIN、role 2 = tenant 都授予 —— 与现状一致,租户本来就能通过 -- 开放 API(POST /payment/openapi/alipay/refund)退自己商户的单,后台按钮只是同一能力的界面。 -- 若要**只给 ADMIN、不给租户**:执行完把最后那段 role 2 的 INSERT 换成它下面注释里的 DELETE。 -- ---------- 权限点:挂在「订单管理」页面下 ---------- -- type=3 = 按钮级权限点。parent 必须指向已存在的那一页,否则 UserService.buildMenuTree -- 会把父节点不在集合里的子节点**直接丢弃**(静默消失,不报错)。 INSERT INTO sys_menu (parent_id, name, title, permission, type, "order", hidden, keep_alive, always_show, affix, status, created_time, updated_time) SELECT (SELECT id FROM sys_menu WHERE route_path = '/payment/har/order' AND type = 2), '订单退款', '订单退款', 'module_payment:har:order:refund', 3, (SELECT COALESCE(MAX("order"), 0) + 1 FROM sys_menu WHERE parent_id = (SELECT id FROM sys_menu WHERE route_path = '/payment/har/order' AND type = 2)), false, false, false, false, '0', now(), now() WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE permission = 'module_payment:har:order:refund'); -- ---------- 角色授权 ---------- -- 只授权**这一个**权限点(不像 har-menu.sql 那样按 `module_payment:har:order:%` 通配), -- 免得将来加权限点时这份脚本被重跑一次就顺带全授出去。 INSERT INTO sys_role_menus (role_id, menu_id) SELECT 1, id FROM sys_menu WHERE permission = 'module_payment:har:order:refund' AND NOT EXISTS (SELECT 1 FROM sys_role_menus rm WHERE rm.role_id = 1 AND rm.menu_id = (SELECT id FROM sys_menu WHERE permission = 'module_payment:har:order:refund')); INSERT INTO sys_role_menus (role_id, menu_id) SELECT 2, id FROM sys_menu WHERE permission = 'module_payment:har:order:refund' AND NOT EXISTS (SELECT 1 FROM sys_role_menus rm WHERE rm.role_id = 2 AND rm.menu_id = (SELECT id FROM sys_menu WHERE permission = 'module_payment:har:order:refund')); -- 若不想给租户(role 2),改用下面这句代替上面那段 role 2 的 INSERT: -- DELETE FROM sys_role_menus -- WHERE role_id = 2 -- AND menu_id = (SELECT id FROM sys_menu WHERE permission = 'module_payment:har:order:refund'); -- ---------- 只读核对(可随时复量,不写任何数据)---------- -- 期望:一行,type=3,parent 指向 /payment/har/order 那一页,两个角色各有一条授权。 SELECT m.id, m.parent_id, m.title, m.permission, m.type, m."order", (SELECT string_agg(rm.role_id::text, ',' ORDER BY rm.role_id) FROM sys_role_menus rm WHERE rm.menu_id = m.id) AS granted_roles FROM sys_menu m WHERE m.permission = 'module_payment:har:order:refund'; -- ★ 执行后必须**重新登录**才生效:权限集合在登录时进 token / 权限 store, -- 不重登的话菜单里不会有这一项,后端也会照旧 403。