feat(database): 重构用户角色关联及权限体系

- 新增 BizException 构造函数支持自定义消息
- 优化 SQL 脚本结构,明确表设计最佳实践
- 修改 t_user、t_role 等表字段类型与索引策略
- 引入代理主键 id 到关联表 t_user_role 和 t_role_permission
- 更新 UserRole 实体类适配 MyBatis-Plus 主键策略
- 增强 UserRoleService 接口功能,支持分配和撤销角色
- 实现批量操作和事务控制提升数据一致性
- 添加安全注解 @PreAuthorize 控制接口访问权限
- 修正 Mapper 注解并优化参数命名提高可读性
- 扩展 ErrorCode 常量增强错误描述准确性
This commit is contained in:
chaos
2025-11-20 23:01:30 +08:00
parent e46b820fca
commit 8dd0efa09e
9 changed files with 273 additions and 132 deletions

View File

@@ -6,6 +6,7 @@ import cn.nopj.chaos_api.model.ApiResult;
import cn.nopj.chaos_api.service.UserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -28,9 +29,20 @@ public class RoleController {
* @param request 请求参数
* @return 处理结果
*/
@PreAuthorize("hasAuthority('admin')")
@RequestMapping("/setUserRole")
public ApiResult<String> setUserRole(@RequestBody SetUserRoleRequest request) {
userRoleService.setUserRole(request);
userRoleService.assignRolesToUser(request);
return ApiResult.success("用户角色设置成功");
}
/**
* 取消用户角色
* @param request 请求参数
* @return 处理结果
*/
@PreAuthorize("hasAuthority('admin')")
@RequestMapping("/cancelUserRole")
public ApiResult<?> cancelUserRole(@RequestBody SetUserRoleRequest request) {
return ApiResult.success("用户角色取消成功",userRoleService.revokeRolesFromUser(request));
}
}

View File

@@ -1,132 +1,172 @@
/**
* 数据库名称: chaos
* 编码和排序规则: UTF8MB4 / utf8mb4_general_ci (支持中文和Emoji)
* 存储引擎: InnoDB (支持事务和外键)
* 最佳实践调整:
* 1. 自动管理 create_time 和 update_time
* 2. 状态/布尔字段使用 TINYINT UNSIGNED 提高语义和效率
* 3. 明确定义外键约束 (FK)
* 4. 关联表新增代理主键 (id),以支持 Mybatis-Plus 等 ORM 框架,并将原复合主键降级为 UNIQUE KEY。
*/
-- 设置默认编码和排序规则
-- USE chaos; -- 假设 chaos 数据库已存在且当前已选中
-- ----------------------------
-- 1. 系统用户表 (t_user)
-- ----------------------------
DROP TABLE IF EXISTS chaos.t_user;
CREATE TABLE chaos.t_user (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
username VARCHAR(64) NOT NULL COMMENT '用户名/登录名',
password VARCHAR(255) NOT NULL COMMENT '密码加密存储建议BCrypt',
nickname VARCHAR(64) DEFAULT '' COMMENT '用户昵称',
enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态 (1:启用, 0:禁用)',
account_non_expired TINYINT(1) NOT NULL DEFAULT 1 COMMENT '账号未过期 (1:是, 0:否)',
credentials_non_expired TINYINT(1) NOT NULL DEFAULT 1 COMMENT '凭证未过期 (1:是, 0:否)',
account_non_locked TINYINT(1) NOT NULL DEFAULT 1 COMMENT '账号未锁定 (1:是, 0:否)',
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除 (1:已删除, 0:未删除)',
remark VARCHAR(500) DEFAULT '' COMMENT '备注信息',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY uk_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统管理-用户表';
DROP TABLE IF EXISTS t_user;
CREATE TABLE t_user (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
username VARCHAR(64) NOT NULL COMMENT '用户名/登录名',
password VARCHAR(255) NOT NULL COMMENT '密码加密存储建议BCrypt或Argon2',
nickname VARCHAR(64) DEFAULT '' COMMENT '用户昵称',
enabled TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态 (1:启用, 0:禁用)',
account_non_expired TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '账号未过期 (1:是, 0:否)',
credentials_non_expired TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '凭证未过期 (1:是, 0:否)',
account_non_locked TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '账号未锁定 (1:是, 0:否)',
deleted TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '逻辑删除 (1:已删除, 0:未删除)',
remark VARCHAR(500) DEFAULT '' COMMENT '备注信息',
-- 最佳实践: 自动维护时间戳
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY uk_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统管理-用户表';
-- ----------------------------
-- 2. 角色/用户组表 (t_role)
-- ----------------------------
DROP TABLE IF EXISTS chaos.t_role;
CREATE TABLE chaos.t_role (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
name VARCHAR(64) NOT NULL COMMENT '角色名称 (如: 管理员)',
code VARCHAR(64) NOT NULL COMMENT '角色标识 (如: admin)',
status TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态 (1:正常, 0:停用)',
remark VARCHAR(500) DEFAULT '' COMMENT '备注',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY uk_code (code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统管理-角色表';
DROP TABLE IF EXISTS t_role;
CREATE TABLE t_role (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
name VARCHAR(64) NOT NULL COMMENT '角色名称 (如: 管理员)',
code VARCHAR(64) NOT NULL COMMENT '角色标识 (如: admin)',
status TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态 (1:正常, 0:停用)',
remark VARCHAR(500) DEFAULT '' COMMENT '备注',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY uk_code (code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统管理-角色表';
-- ----------------------------
-- 3. 权限表 (t_permission)
-- ----------------------------
DROP TABLE IF EXISTS chaos.t_permission;
CREATE TABLE chaos.t_permission (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
parent_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '父权限ID (0为顶级)',
name VARCHAR(64) NOT NULL COMMENT '权限名称',
code VARCHAR(128) NOT NULL COMMENT '权限标识/资源路径',
type TINYINT(1) NOT NULL DEFAULT 1 COMMENT '类型 (1:目录, 2:菜单, 3:按钮)',
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序 (数值越小越靠前)',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY uk_code (code),
INDEX idx_parent_id (parent_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统管理-权限表';
DROP TABLE IF EXISTS t_permission;
CREATE TABLE t_permission (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
parent_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '父权限ID (0为顶级)',
name VARCHAR(64) NOT NULL COMMENT '权限名称',
code VARCHAR(128) NOT NULL COMMENT '权限标识/资源路径 (RESTful 风格或权限点)',
type TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '类型 (1:目录, 2:菜单, 3:按钮)',
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序 (数值越小越靠前)',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY uk_code (code),
INDEX idx_parent_id (parent_id) -- 父节点查询优化
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统管理-权限表';
-- ----------------------------
-- 4. 用户-角色关联表 (t_user_role)
-- ----------------------------
DROP TABLE IF EXISTS chaos.t_user_role;
CREATE TABLE chaos.t_user_role (
user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
role_id BIGINT UNSIGNED NOT NULL COMMENT '角色ID',
PRIMARY KEY (user_id, role_id),
CONSTRAINT fk_ur_user_id FOREIGN KEY (user_id) REFERENCES chaos.t_user (id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_ur_role_id FOREIGN KEY (role_id) REFERENCES chaos.t_role (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统管理-用户角色关联表';
DROP TABLE IF EXISTS t_user_role;
CREATE TABLE t_user_role (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID (代理键)',
user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
role_id BIGINT UNSIGNED NOT NULL COMMENT '角色ID',
PRIMARY KEY (id),
UNIQUE KEY uk_user_role (user_id, role_id), -- 保持业务唯一性约束
-- 外键约束: 引用 t_user.id
CONSTRAINT fk_ur_user_id FOREIGN KEY (user_id) REFERENCES t_user (id) ON DELETE CASCADE ON UPDATE CASCADE,
-- 外键约束: 引用 t_role.id
CONSTRAINT fk_ur_role_id FOREIGN KEY (role_id) REFERENCES t_role (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统管理-用户角色关联表';
-- ----------------------------
-- 5. 角色-权限关联表 (t_role_permission)
-- ----------------------------
DROP TABLE IF EXISTS chaos.t_role_permission;
CREATE TABLE chaos.t_role_permission (
role_id BIGINT UNSIGNED NOT NULL COMMENT '角色ID',
permission_id BIGINT UNSIGNED NOT NULL COMMENT '权限ID',
PRIMARY KEY (role_id, permission_id),
CONSTRAINT fk_rp_role_id FOREIGN KEY (role_id) REFERENCES chaos.t_role (id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_rp_permission_id FOREIGN KEY (permission_id) REFERENCES chaos.t_permission (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统管理-角色权限关联表';
DROP TABLE IF EXISTS t_role_permission;
CREATE TABLE t_role_permission (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID (代理键)',
role_id BIGINT UNSIGNED NOT NULL COMMENT '角色ID',
permission_id BIGINT UNSIGNED NOT NULL COMMENT '权限ID',
PRIMARY KEY (id),
UNIQUE KEY uk_role_permission (role_id, permission_id), -- 保持业务唯一性约束
-- 外键约束: 引用 t_role.id
CONSTRAINT fk_rp_role_id FOREIGN KEY (role_id) REFERENCES t_role (id) ON DELETE CASCADE ON UPDATE CASCADE,
-- 外键约束: 引用 t_permission.id
CONSTRAINT fk_rp_permission_id FOREIGN KEY (permission_id) REFERENCES t_permission (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统管理-角色权限关联表';
-- ----------------------------
-- 6. 基础设备表 (t_device)
-- ----------------------------
DROP TABLE IF EXISTS chaos.t_device;
CREATE TABLE chaos.t_device (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
name VARCHAR(128) NOT NULL COMMENT '设备名称',
model VARCHAR(128) DEFAULT NULL COMMENT '设备型号',
type_id BIGINT UNSIGNED DEFAULT NULL COMMENT '设备类型ID (关联类型表)',
location_id BIGINT UNSIGNED DEFAULT NULL COMMENT '位置ID (关联位置表)',
snmp_community VARCHAR(128) DEFAULT NULL COMMENT 'SNMP团体名 (加密存储建议)',
manufacturer VARCHAR(128) DEFAULT NULL COMMENT '设备制造商',
purchase_date DATE DEFAULT NULL COMMENT '采购日期',
status TINYINT DEFAULT 1 COMMENT '设备状态 (1:在线, 0:离线, 2:维护中)',
remark VARCHAR(500) DEFAULT '' COMMENT '备注',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
INDEX idx_type_id (type_id),
INDEX idx_location_id (location_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资产管理-设备信息表';
DROP TABLE IF EXISTS t_device;
CREATE TABLE t_device (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
name VARCHAR(128) NOT NULL COMMENT '设备名称',
model VARCHAR(128) DEFAULT NULL COMMENT '设备型号',
type_id BIGINT UNSIGNED DEFAULT NULL COMMENT '设备类型ID (外键关联设备类型表)',
location_id BIGINT UNSIGNED DEFAULT NULL COMMENT '位置ID (外键关联位置表)',
snmp_community VARCHAR(128) DEFAULT NULL COMMENT 'SNMP团体名 (建议加密或隐藏)',
manufacturer VARCHAR(128) DEFAULT NULL COMMENT '设备制造商',
purchase_date DATE DEFAULT NULL COMMENT '采购日期',
status TINYINT UNSIGNED DEFAULT 1 COMMENT '设备状态 (1:在线, 0:离线, 2:维护中)',
remark VARCHAR(500) DEFAULT '' COMMENT '备注',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
INDEX idx_type_id (type_id),
INDEX idx_location_id (location_id)
-- 注意: 如果 t_device_type 和 t_location 表存在,需要在此处添加相应的 FOREIGN KEY 约束
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='资产管理-设备信息表';
-- ----------------------------
-- 7. 网络接口表 (t_network_interface)
-- ----------------------------
DROP TABLE IF EXISTS chaos.t_network_interface;
CREATE TABLE chaos.t_network_interface (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
device_id BIGINT UNSIGNED NOT NULL COMMENT '设备ID',
parent_id BIGINT UNSIGNED DEFAULT NULL COMMENT '父接口ID (用于子接口/聚合口)',
name VARCHAR(64) NOT NULL COMMENT '接口名称 (如: eth0, GE0/0/1)',
mac_address VARCHAR(17) DEFAULT NULL COMMENT 'MAC地址 (格式: AA:BB:CC:DD:EE:FF)',
ip_address VARCHAR(45) DEFAULT NULL COMMENT 'IP地址 (支持IPv4/IPv6)',
subnet_mask VARCHAR(45) DEFAULT NULL COMMENT '子网掩码/前缀长度',
gateway_ip VARCHAR(45) DEFAULT NULL COMMENT '网关IP地址',
vlan_id INT DEFAULT NULL COMMENT 'VLAN ID (1-4094)',
port_speed INT DEFAULT 0 COMMENT '端口速率 (Mbps)',
status TINYINT DEFAULT 1 COMMENT '接口状态 (1:UP, 0:DOWN)',
remark VARCHAR(500) DEFAULT '' COMMENT '备注',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
CONSTRAINT fk_ni_device_id FOREIGN KEY (device_id) REFERENCES chaos.t_device (id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_ni_parent_id FOREIGN KEY (parent_id) REFERENCES chaos.t_network_interface (id) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资产管理-网络接口表';
DROP TABLE IF EXISTS t_network_interface;
CREATE TABLE t_network_interface (
id BIGINT UNSIGNED AUTO_INCREMENT COMMENT '主键ID',
device_id BIGINT UNSIGNED NOT NULL COMMENT '设备ID',
parent_id BIGINT UNSIGNED DEFAULT NULL COMMENT '父接口ID (用于子接口/聚合口,自关联)',
name VARCHAR(64) NOT NULL COMMENT '接口名称 (如: eth0, GE0/0/1)',
mac_address VARCHAR(17) DEFAULT NULL COMMENT 'MAC地址 (格式: AA:BB:CC:DD:EE:FF)',
ip_address VARCHAR(45) DEFAULT NULL COMMENT 'IP地址 (支持IPv4/IPv6)',
subnet_mask VARCHAR(45) DEFAULT NULL COMMENT '子网掩码/前缀长度',
gateway_ip VARCHAR(45) DEFAULT NULL COMMENT '网关IP地址',
vlan_id SMALLINT UNSIGNED DEFAULT NULL COMMENT 'VLAN ID (1-4094, SMALLINT更合适)',
port_speed INT UNSIGNED DEFAULT 0 COMMENT '端口速率 (Mbps)',
status TINYINT UNSIGNED DEFAULT 1 COMMENT '接口状态 (1:UP, 0:DOWN)',
remark VARCHAR(500) DEFAULT '' COMMENT '备注',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
INDEX idx_mac_address (mac_address),
INDEX idx_ip_address (ip_address),
-- 外键约束: 引用 t_device.id
CONSTRAINT fk_ni_device_id FOREIGN KEY (device_id) REFERENCES t_device (id) ON DELETE CASCADE ON UPDATE CASCADE,
-- 外键约束: 引用自身 (自关联)
CONSTRAINT fk_ni_parent_id FOREIGN KEY (parent_id) REFERENCES t_network_interface (id) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='资产管理-网络接口表';