瀏覽代碼

fix: 修复 user.lock 权限未写入,迁移脚本改为纯 SQL 且不写死主键

v23 的权限部分用 DELIMITER + 存储过程,且写死主键 id=95,会导致权限整段
被跳过或主键冲突失败,而 ALTER TABLE 在前、字段已加上,现象是「字段有了、
权限没了」。改为 INSERT IGNORE(依赖 uk_value 唯一索引、主键交 AUTO_INCREMENT)
+ 幂等 UPDATE,任意客户端均可执行。

新增 v25 修复脚本,供已执行过 v23 的库补齐权限;其中附带诊断查询,可核查
v21/v22 同期以相同方式加入的 settlement.modify / systemLog.clear 是否同样缺失
(权限校验读的是 t_role.permissions,t_permission 仅为角色管理界面的权限目录)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
skyline 1 月之前
父節點
當前提交
199dc828b4

+ 9 - 27
car-wash-entity/src/main/resources/sql/v23_add_user_lock.sql

@@ -14,34 +14,16 @@ ALTER TABLE `t_user`
     ADD COLUMN `lock_operator` VARCHAR(64)  DEFAULT NULL COMMENT '锁定操作人',
     ADD COLUMN `lock_time`     DATETIME     DEFAULT NULL COMMENT '锁定时间';
 
-DROP PROCEDURE IF EXISTS add_user_lock_permission;
-DELIMITER //
-CREATE PROCEDURE add_user_lock_permission()
-BEGIN
-    IF NOT EXISTS (
-        SELECT 1 FROM information_schema.TABLES
-        WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 't_permission'
-    ) THEN
-        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 't_permission 表不存在,请先执行 init.sql';
-    END IF;
+-- 1. 新增 user.lock 权限(幂等:依赖 uk_value 唯一索引,主键交由 AUTO_INCREMENT 分配;
+--    不写死主键,避免与既有数据主键冲突导致整段失败)
+INSERT IGNORE INTO `t_permission` (`company_id`, `name`, `value`, `pid`, `weight`)
+VALUES (NULL, '锁定用户', 'user.lock', 18, 2);
 
-    -- 1. 新增权限记录(幂等)
-    IF NOT EXISTS (
-        SELECT 1 FROM t_permission WHERE value = 'user.lock'
-    ) THEN
-        INSERT INTO `t_permission` (`id`, `company_id`, `name`, `value`, `pid`, `weight`)
-        VALUES (95, NULL, '锁定用户', 'user.lock', 18, 2);
-    END IF;
-
-    -- 2. 超管角色(id=1)补齐该权限(管道分隔权限字符串,幂等)
-    UPDATE `t_role`
-    SET `permissions` = CONCAT(IFNULL(`permissions`, ''), '|user.lock')
-    WHERE `id` = 1
-      AND FIND_IN_SET('user.lock', REPLACE(IFNULL(`permissions`, ''), '|', ',')) = 0;
-END //
-DELIMITER ;
-CALL add_user_lock_permission();
-DROP PROCEDURE IF EXISTS add_user_lock_permission;
+-- 2. 超管角色(id=1)补齐该权限(管道分隔权限字符串,幂等)
+UPDATE `t_role`
+SET `permissions` = CONCAT(IFNULL(`permissions`, ''), '|user.lock')
+WHERE `id` = 1
+  AND FIND_IN_SET('user.lock', REPLACE(IFNULL(`permissions`, ''), '|', ',')) = 0;
 
 -- ====================================================
 -- 验证:

+ 52 - 0
car-wash-entity/src/main/resources/sql/v25_fix_user_lock_permission.sql

@@ -0,0 +1,52 @@
+-- ====================================================
+-- v25: 修复 user.lock 权限未写入的问题
+--
+-- 背景:v23 的权限部分使用 DELIMITER + 存储过程,且写死了主键 id=95。
+--       1) DELIMITER 是 mysql 命令行客户端指令而非 SQL,DBeaver/JDBC 等
+--          客户端执行到该行会语法报错;由于它在 ALTER TABLE 之后,
+--          结果是字段加上了、权限整段被跳过;
+--       2) t_permission.id 是 AUTO_INCREMENT,写死 id 与既有数据主键冲突时
+--          INSERT 会失败(守卫条件只看 value,拦不住主键冲突)。
+--       本脚本改为纯 SQL,无需存储过程、不写死主键,可重复执行。
+--
+-- 适用:v23 已执行(t_user 锁定字段已存在)但权限未写入的库。
+--       全新环境直接执行修正后的 v23 即可,无需执行本脚本。
+--
+-- 注意:权限校验(@SaCheckPermission)读取的是 t_role.permissions 管道分隔字符串,
+--       t_permission 仅为权限目录(供角色管理界面勾选展示)。两者都要有:
+--       缺 t_permission → 角色管理界面看不到「锁定用户」勾选项;
+--       缺 t_role.permissions → 超管调用锁定接口会 403 无访问权限。
+-- ====================================================
+
+-- 1. 权限目录:新增 user.lock(幂等:依赖 uk_value 唯一索引,主键交由 AUTO_INCREMENT 分配)
+INSERT IGNORE INTO `t_permission` (`company_id`, `name`, `value`, `pid`, `weight`)
+VALUES (NULL, '锁定用户', 'user.lock', 18, 2);
+
+-- 2. 超管角色(id=1)补齐该权限(管道分隔权限字符串,幂等)
+UPDATE `t_role`
+SET `permissions` = CONCAT(IFNULL(`permissions`, ''), '|user.lock')
+WHERE `id` = 1
+  AND FIND_IN_SET('user.lock', REPLACE(IFNULL(`permissions`, ''), '|', ',')) = 0;
+
+-- 3. 诊断:核查 v21/v22 同期以同样方式加入的权限是否也缺失(只查询,不修改)
+--    若下面只返回 user.lock 一行,说明 settlement.modify / systemLog.clear 也未写入,
+--    超管使用「确认结算」「清空操作日志」时会 403,需照第 1 步同样方式补齐目录行,
+--    并按第 2 步把权限码追加到 t_role.permissions。
+SELECT `id`, `name`, `value`, `pid`, `weight` FROM `t_permission`
+WHERE `value` IN ('user.lock', 'settlement.modify', 'systemLog.clear')
+ORDER BY `id`;
+
+-- 3.1 若确认超管缺失较多权限,可用下面语句按目录重建超管权限(与 init.sql 的口径一致:
+--     超级管理员 = 全部权限)。执行前请确认这符合预期,默认注释不执行。
+-- SET SESSION group_concat_max_len = 10000;
+-- UPDATE `t_role` SET `permissions` = (
+--     SELECT GROUP_CONCAT(`value` SEPARATOR '|') FROM `t_permission` ORDER BY `id`
+-- ) WHERE `id` = 1;
+
+-- ====================================================
+-- 验证(两条都要有结果,功能才完整):
+--   1) 权限目录:  SELECT * FROM `t_permission` WHERE `value` = 'user.lock';
+--   2) 实际授权:  SELECT `permissions` FROM `t_role` WHERE `id` = 1;   -- 需包含 user.lock
+--   权限实时从库中读取(StpInterfaceImpl → listUserPermissions 直查数据库,无缓存),
+--   改完立即生效,管理员无需重新登录。
+-- ====================================================