refactor permission system

This commit is contained in:
Timi
2026-08-11 23:57:59 +08:00
parent 6e43ff349d
commit 39ac73dc66
60 changed files with 2300 additions and 335 deletions
@@ -0,0 +1,39 @@
ALTER TABLE `role`
ADD COLUMN `builtin` BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'true 为系统内置角色' AFTER `description`,
ADD COLUMN `protected_role` BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'true 为受保护角色' AFTER `builtin`,
ADD COLUMN `parent_role_id` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '管理父角色 ID' AFTER `protected_role`,
ADD COLUMN `owner_type` VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'MODULE' COMMENT '归属类型' AFTER `parent_role_id`,
ADD COLUMN `owner_id` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '归属 ID' AFTER `owner_type`,
ADD COLUMN `created_by` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '创建人用户 ID' AFTER `owner_id`,
ADD INDEX `idx_role_parent_role_id` (`parent_role_id`),
ADD INDEX `idx_role_owner` (`owner_type`, `owner_id`);
ALTER TABLE `permission`
ADD COLUMN `builtin` BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'true 为系统内置权限' AFTER `description`,
ADD COLUMN `protected_permission` BOOLEAN NOT NULL DEFAULT FALSE COMMENT 'true 为受保护权限' AFTER `builtin`,
ADD COLUMN `owner_type` VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'MODULE' COMMENT '归属类型' AFTER `protected_permission`,
ADD COLUMN `owner_id` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '归属 ID' AFTER `owner_type`,
ADD COLUMN `created_by` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '创建人用户 ID' AFTER `owner_id`,
ADD INDEX `idx_permission_owner` (`owner_type`, `owner_id`);
RENAME TABLE `role_relation` TO `role_permission_inherit`;
ALTER TABLE `role_permission_inherit`
DROP INDEX `idx_role_relation`,
DROP INDEX `idx_child_role_id`,
ADD INDEX `idx_role_permission_inherit` (`parent_role_id`, `child_role_id`),
ADD INDEX `idx_role_permission_inherit_child_role_id` (`child_role_id`);
ALTER TABLE `role_permission_inherit`
ADD COLUMN `owner_type` VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'MODULE' COMMENT '归属类型' AFTER `child_role_id`,
ADD COLUMN `owner_id` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '归属 ID' AFTER `owner_type`,
ADD COLUMN `created_by` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '创建人用户 ID' AFTER `owner_id`,
ADD INDEX `idx_role_permission_inherit_owner` (`owner_type`, `owner_id`);
UPDATE `role_permission_inherit` inherit
INNER JOIN `role` child_role ON inherit.`child_role_id` = child_role.`id`
SET inherit.`owner_id` = child_role.`module_code`
WHERE
inherit.`owner_type` = 'MODULE'
AND inherit.`owner_id` IS NULL
AND inherit.`deleted_at` IS NULL;
@@ -0,0 +1,11 @@
CREATE TABLE `role_permission_delegation` (
`id` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`role_id` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '角色 ID',
`permission_id` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '允许转授的权限 ID',
`created_by` VARCHAR(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '创建人用户 ID',
`created_at` BIGINT(20) COMMENT '创建时间',
`deleted_at` BIGINT(20) COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_role_permission_delegation` (`role_id` ASC, `permission_id` ASC) USING BTREE,
INDEX `idx_permission_id` (`permission_id` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色转授权限' ROW_FORMAT = Dynamic;
@@ -0,0 +1,40 @@
UPDATE `role_permission_delegation` target
JOIN (
SELECT
id,
ROW_NUMBER() OVER (
PARTITION BY role_id, permission_id
ORDER BY created_at DESC, id DESC
) AS rn
FROM `role_permission_delegation`
WHERE deleted_at IS NULL
) duplicate ON duplicate.id = target.id
SET target.deleted_at = UNIX_TIMESTAMP() * 1000
WHERE duplicate.rn > 1;
ALTER TABLE `role_permission_delegation`
ADD COLUMN `active_key` TINYINT(1) GENERATED ALWAYS AS (IF(`deleted_at` IS NULL, 1, NULL)) STORED COMMENT '未删除唯一键';
CREATE UNIQUE INDEX `uk_role_permission_delegation`
ON `role_permission_delegation` (`role_id`, `permission_id`, `active_key`);
UPDATE `role_permission_inherit` target
JOIN (
SELECT
id,
ROW_NUMBER() OVER (
PARTITION BY parent_role_id, child_role_id, owner_type, IFNULL(owner_id, '')
ORDER BY created_at DESC, id DESC
) AS rn
FROM `role_permission_inherit`
WHERE deleted_at IS NULL
) duplicate ON duplicate.id = target.id
SET target.deleted_at = UNIX_TIMESTAMP() * 1000
WHERE duplicate.rn > 1;
ALTER TABLE `role_permission_inherit`
ADD COLUMN `active_key` TINYINT(1) GENERATED ALWAYS AS (IF(`deleted_at` IS NULL, 1, NULL)) STORED COMMENT '未删除唯一键',
ADD COLUMN `owner_key` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (IFNULL(`owner_id`, '')) STORED COMMENT '归属唯一键';
CREATE UNIQUE INDEX `uk_role_permission_inherit`
ON `role_permission_inherit` (`parent_role_id`, `child_role_id`, `owner_type`, `owner_key`, `active_key`);
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.imyeyu.api.modules.user.mapper.PermissionMapper">
<select id="selectByIdList" resultType="com.imyeyu.api.modules.user.entity.Permission">
SELECT
*
FROM `permission`
WHERE
TRUE
<if test="idList != null and !idList.isEmpty()">
AND `id` IN
<foreach collection="idList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</if>
<if test="idList == null or idList.isEmpty()">
AND FALSE
</if>
AND `deleted_at` IS NULL
</select>
<select id="selectByModuleCode" resultType="com.imyeyu.api.modules.user.entity.Permission">
SELECT
*
FROM `permission`
WHERE
`module_code` = #{moduleCode}
AND `deleted_at` IS NULL
ORDER BY `code`
</select>
</mapper>
@@ -1,6 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.imyeyu.api.modules.user.mapper.RoleMapper">
<select id="selectById" resultType="com.imyeyu.api.modules.user.entity.Role">
SELECT
*
FROM `role`
WHERE
`id` = #{id}
AND `deleted_at` IS NULL
LIMIT 1
</select>
<select id="selectByIdList" resultType="com.imyeyu.api.modules.user.entity.Role">
SELECT
*
@@ -27,4 +36,26 @@
AND `deleted_at` IS NULL
ORDER BY `created_at`
</select>
<select id="selectByParentRoleId" resultType="com.imyeyu.api.modules.user.entity.Role">
SELECT
*
FROM `role`
WHERE
<if test="parentRoleId != null">
`parent_role_id` = #{parentRoleId}
</if>
<if test="parentRoleId == null">
`parent_role_id` IS NULL
</if>
AND `deleted_at` IS NULL
ORDER BY `module_code`, `created_at`
</select>
<select id="selectAll" resultType="com.imyeyu.api.modules.user.entity.Role">
SELECT
*
FROM `role`
WHERE
`deleted_at` IS NULL
ORDER BY `module_code`, `created_at`
</select>
</mapper>
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.imyeyu.api.modules.user.mapper.RolePermissionDelegationMapper">
<select id="selectByRoleIdList" resultType="com.imyeyu.api.modules.user.entity.RolePermissionDelegation">
SELECT
*
FROM `role_permission_delegation`
WHERE
`role_id` IN
<foreach collection="roleIdList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
AND `deleted_at` IS NULL
</select>
<select id="selectPermissionByRoleIdList" resultType="com.imyeyu.api.modules.user.entity.Permission">
SELECT DISTINCT
permission.*
FROM `role_permission_delegation`
LEFT JOIN `permission` ON permission.id = role_permission_delegation.permission_id
WHERE
`role_permission_delegation`.`role_id` IN
<foreach collection="roleIdList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
AND `role_permission_delegation`.`deleted_at` IS NULL
AND `permission`.`deleted_at` IS NULL
ORDER BY
`permission`.code ASC
</select>
<insert id="createBatch">
INSERT INTO `role_permission_delegation` (
id,
role_id,
permission_id,
created_by,
created_at
) VALUES
<foreach collection="rolePermissionDelegationList" item="item" separator=",">
(#{item.id}, #{item.roleId}, #{item.permissionId}, #{item.createdBy}, #{item.createdAt})
</foreach>
</insert>
<update id="deleteByPermissionIdList">
UPDATE `role_permission_delegation`
SET `deleted_at` = UNIX_TIMESTAMP()
WHERE
`role_id` = #{roleId}
AND `permission_id` IN
<foreach collection="permissionIdList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
AND `deleted_at` IS NULL
</update>
</mapper>
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.imyeyu.api.modules.user.mapper.RoleRelationMapper">
<select id="selectByParentRoleId" resultType="com.imyeyu.api.modules.user.entity.RoleRelation">
<mapper namespace="com.imyeyu.api.modules.user.mapper.RolePermissionInheritMapper">
<select id="selectByParentRoleId" resultType="com.imyeyu.api.modules.user.entity.RolePermissionInherit">
SELECT
*
FROM `role_relation`
FROM `role_permission_inherit`
WHERE
`parent_role_id` = #{parentRoleId}
AND `deleted_at` IS NULL
@@ -12,15 +12,26 @@
<select id="selectChildRoleIdListByParentRoleId" resultType="java.lang.String">
SELECT
`child_role_id`
FROM `role_relation`
FROM `role_permission_inherit`
WHERE
`parent_role_id` = #{parentRoleId}
AND `deleted_at` IS NULL
</select>
<select id="selectByParentRoleIdList" resultType="com.imyeyu.api.modules.user.entity.RolePermissionInherit">
SELECT
*
FROM `role_permission_inherit`
WHERE
`parent_role_id` IN
<foreach collection="parentRoleIdList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
AND `deleted_at` IS NULL
</select>
<select id="selectChildRoleIdListByParentRoleIdList" resultType="java.lang.String">
SELECT
`child_role_id`
FROM `role_relation`
FROM `role_permission_inherit`
WHERE
`parent_role_id` IN
<foreach collection="parentRoleIdList" item="item" separator="," open="(" close=")">
@@ -29,24 +40,34 @@
AND `deleted_at` IS NULL
</select>
<insert id="createBatch">
INSERT INTO `role_relation` (
INSERT INTO `role_permission_inherit` (
id,
parent_role_id,
child_role_id,
owner_type,
owner_id,
created_by,
created_at
) VALUES
<foreach collection="roleRelationList" item="item" separator=",">
(#{item.id}, #{item.parentRoleId}, #{item.childRoleId}, #{item.createdAt})
<foreach collection="rolePermissionInheritList" item="item" separator=",">
(#{item.id}, #{item.parentRoleId}, #{item.childRoleId}, #{item.ownerType}, #{item.ownerId}, #{item.createdBy}, #{item.createdAt})
</foreach>
</insert>
<update id="deleteByChildRoleIdList">
UPDATE `role_relation`
SET `deleted_at` = UNIX_TIMESTAMP()
UPDATE `role_permission_inherit`
SET `deleted_at` = UNIX_TIMESTAMP() * 1000
WHERE
`parent_role_id` = #{parentRoleId}
AND `child_role_id` IN
<foreach collection="childRoleIdList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
AND `owner_type` = #{ownerType}
<if test="ownerId != null">
AND `owner_id` = #{ownerId}
</if>
<if test="ownerId == null">
AND `owner_id` IS NULL
</if>
</update>
</mapper>
@@ -13,7 +13,7 @@
AND `role_permission`.`deleted_at` IS NULL
</select>
<select id="selectPermissionByRoleIdList" resultType="com.imyeyu.api.modules.user.entity.Permission">
SELECT
SELECT DISTINCT
permission.*
FROM `role_permission`
LEFT JOIN `permission` ON permission.id = role_permission.permission_id