From fb0effed9a2b36f94576ee3626bba9d9b8cdca58 Mon Sep 17 00:00:00 2001 From: Charles7c Date: Tue, 7 Mar 2023 23:55:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=A7=92=E8=89=B2=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=88=E5=9F=BA=E4=BA=8E=20MyBatis=20Plus=20DataPer?= =?UTF-8?q?missionInterceptor=20=E6=8F=92=E4=BB=B6=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.基于 MyBatis Plus DataPermissionInterceptor 插件实现的数据权限功能 2.通过在指定 Mapper 接口层方法添加 @DataPermission 注解实现数据权限 --- .../common/annotation/DataPermission.java | 36 ++++ .../cnadmin/common/base/BaseMapper.java | 11 ++ .../mybatis/DataPermissionHandlerImpl.java | 187 ++++++++++++++++++ .../mybatis/MybatisPlusConfiguration.java | 3 + .../cnadmin/common/constant/SysConsts.java | 14 +- .../cnadmin/common/model/dto/LoginUser.java | 20 ++ .../cnadmin/common/model/dto/RoleDTO.java | 50 +++++ .../auth/service/impl/LoginServiceImpl.java | 3 + .../service/impl/PermissionServiceImpl.java | 2 +- .../cnadmin/system/model/entity/DeptDO.java | 5 + .../system/model/request/DeptRequest.java | 6 + .../cnadmin/system/model/vo/RoleVO.java | 2 +- .../cnadmin/system/service/RoleService.java | 10 + .../system/service/impl/DeptServiceImpl.java | 40 ++++ .../system/service/impl/RoleServiceImpl.java | 12 +- .../changelog/v0.0.1/continew-admin_data.sql | 16 +- .../changelog/v0.0.1/continew-admin_table.sql | 1 + 17 files changed, 400 insertions(+), 18 deletions(-) create mode 100644 continew-admin-common/src/main/java/top/charles7c/cnadmin/common/annotation/DataPermission.java create mode 100644 continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/mybatis/DataPermissionHandlerImpl.java create mode 100644 continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/RoleDTO.java diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/annotation/DataPermission.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/annotation/DataPermission.java new file mode 100644 index 00000000..34df4be8 --- /dev/null +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/annotation/DataPermission.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.charles7c.cnadmin.common.annotation; + +import java.lang.annotation.*; + +/** + * 数据权限注解 + * + * @author Charles7c + * @since 2023/3/6 23:34 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataPermission { + + /** + * 表别名 + */ + String value() default ""; +} diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/base/BaseMapper.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/base/BaseMapper.java index 30e34a7b..631176fa 100644 --- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/base/BaseMapper.java +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/base/BaseMapper.java @@ -47,6 +47,17 @@ public interface BaseMapper extends com.baomidou.mybatisplus.core.mapper.Base return Db.saveBatch(entityList); } + /** + * 批量更新记录 + * + * @param entityList + * 实体列表 + * @return 是否成功 + */ + default boolean updateBatchById(Collection entityList) { + return Db.updateBatchById(entityList); + } + /** * 链式查询 * diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/mybatis/DataPermissionHandlerImpl.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/mybatis/DataPermissionHandlerImpl.java new file mode 100644 index 00000000..21c43137 --- /dev/null +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/mybatis/DataPermissionHandlerImpl.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.charles7c.cnadmin.common.config.mybatis; + +import java.lang.reflect.Method; +import java.util.Collections; + +import lombok.extern.slf4j.Slf4j; + +import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler; + +import top.charles7c.cnadmin.common.annotation.DataPermission; +import top.charles7c.cnadmin.common.constant.StringConsts; +import top.charles7c.cnadmin.common.enums.DataScopeEnum; +import top.charles7c.cnadmin.common.model.dto.LoginUser; +import top.charles7c.cnadmin.common.model.dto.RoleDTO; +import top.charles7c.cnadmin.common.util.helper.LoginHelper; + +import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.EqualsTo; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.SelectExpressionItem; +import net.sf.jsqlparser.statement.select.SubSelect; + +/** + * 数据权限处理器实现类 + *

+ * 来源:DataPermissionInterceptor 如何使用? + *

+ * + * @author Charles7c + * @since 2023/3/6 23:19 + */ +@Slf4j +public class DataPermissionHandlerImpl implements DataPermissionHandler { + + /** ID */ + private static final String ID = "id"; + /** 部门 ID */ + private static final String DEPT_ID = "dept_id"; + /** 创建人 */ + private static final String CREATE_USER = "create_user"; + /** 部门表 */ + private static final String DEPT_TABLE = "sys_dept"; + /** 角色和部门关联表 */ + private static final String ROLE_DEPT_TABLE = "sys_role_dept"; + /** 角色和部门关联表:角色 ID */ + private static final String ROLE_ID = "role_id"; + + @Override + public Expression getSqlSegment(Expression where, String mappedStatementId) { + try { + Class clazz = + Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(StringConsts.DOT))); + String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(StringConsts.DOT) + 1); + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + DataPermission annotation = method.getAnnotation(DataPermission.class); + if (ObjectUtils.isNotEmpty(annotation) + && (method.getName().equals(methodName) || (method.getName() + "_COUNT").equals(methodName))) { + // 获取当前登录用户 + LoginUser loginUser = LoginHelper.getLoginUser(); + if (ObjectUtils.isNotEmpty(loginUser) && !loginUser.isAdmin()) { + return buildDataScopeFilter(loginUser, annotation.value(), where); + } + } + } + } catch (ClassNotFoundException e) { + log.error("Data permission handler build data scope filter occurred an error: {}.", e.getMessage(), e); + } + return where; + } + + /** + * 构建数据范围过滤条件 + * + * @param user + * 当前登录用户 + * @param tableAlias + * 表别名 + * @param where + * 当前查询条件 + * @return 构建后查询条件 + */ + private static Expression buildDataScopeFilter(LoginUser user, String tableAlias, Expression where) { + Expression expression = null; + for (RoleDTO role : user.getRoleSet()) { + DataScopeEnum dataScope = role.getDataScope(); + if (DataScopeEnum.ALL.equals(dataScope)) { + return where; + } + if (DataScopeEnum.DEPT_AND_CHILD.equals(dataScope)) { + // select t1.* from table as t1 where t1.`dept_id` in (select `id` from `sys_dept` where `id` = xxx or + // find_in_set(xxx, `ancestors`)); + // 构建子查询 + SubSelect subSelect = new SubSelect(); + PlainSelect select = new PlainSelect(); + select.setSelectItems(Collections.singletonList(new SelectExpressionItem(new Column(ID)))); + select.setFromItem(new Table(DEPT_TABLE)); + EqualsTo equalsTo = new EqualsTo(); + equalsTo.setLeftExpression(new Column(ID)); + equalsTo.setRightExpression(new LongValue(user.getDeptId())); + Function function = new Function(); + function.setName("find_in_set"); + function.setParameters(new ExpressionList(new LongValue(user.getDeptId()), new Column("ancestors"))); + select.setWhere(new OrExpression(equalsTo, function)); + subSelect.setSelectBody(select); + // 构建父查询 + InExpression inExpression = new InExpression(); + inExpression.setLeftExpression(buildColumn(tableAlias, DEPT_ID)); + inExpression.setRightExpression(subSelect); + expression = + ObjectUtils.isNotEmpty(expression) ? new OrExpression(expression, inExpression) : inExpression; + } else if (DataScopeEnum.DEPT.equals(dataScope)) { + // select t1.* from table as t1 where t1.`dept_id` = xxx; + EqualsTo equalsTo = new EqualsTo(); + equalsTo.setLeftExpression(buildColumn(tableAlias, DEPT_ID)); + equalsTo.setRightExpression(new LongValue(user.getDeptId())); + expression = ObjectUtils.isNotEmpty(expression) ? new OrExpression(expression, equalsTo) : equalsTo; + } else if (DataScopeEnum.SELF.equals(dataScope)) { + // select t1.* from table as t1 where t1.`create_user` = xxx; + EqualsTo equalsTo = new EqualsTo(); + equalsTo.setLeftExpression(buildColumn(tableAlias, CREATE_USER)); + equalsTo.setRightExpression(new LongValue(user.getId())); + expression = ObjectUtils.isNotEmpty(expression) ? new OrExpression(expression, equalsTo) : equalsTo; + } else if (DataScopeEnum.CUSTOM.equals(dataScope)) { + // select t1.* from table as t1 where t1.`dept_id` in (select `dept_id` from `sys_role_dept` where + // `role_id` = xxx); + // 构建子查询 + SubSelect subSelect = new SubSelect(); + PlainSelect select = new PlainSelect(); + select.setSelectItems(Collections.singletonList(new SelectExpressionItem(new Column(DEPT_ID)))); + select.setFromItem(new Table(ROLE_DEPT_TABLE)); + EqualsTo equalsTo = new EqualsTo(); + equalsTo.setLeftExpression(new Column(ROLE_ID)); + equalsTo.setRightExpression(new LongValue(role.getId())); + select.setWhere(equalsTo); + subSelect.setSelectBody(select); + // 构建父查询 + InExpression inExpression = new InExpression(); + inExpression.setLeftExpression(buildColumn(tableAlias, DEPT_ID)); + inExpression.setRightExpression(subSelect); + expression = + ObjectUtils.isNotEmpty(expression) ? new OrExpression(expression, inExpression) : inExpression; + } + } + return ObjectUtils.isNotEmpty(where) ? new AndExpression(where, new Parenthesis(expression)) : expression; + } + + /** + * 构建 Column + * + * @param tableAlias + * 表别名 + * @param columnName + * 字段名称 + * @return 带表别名字段 + */ + private static Column buildColumn(String tableAlias, String columnName) { + if (StringUtils.isNotEmpty(tableAlias)) { + columnName = String.format("%s.%s", tableAlias, columnName); + } + return new Column(columnName); + } +} diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/mybatis/MybatisPlusConfiguration.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/mybatis/MybatisPlusConfiguration.java index f61faf9f..ba4a5629 100644 --- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/mybatis/MybatisPlusConfiguration.java +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/mybatis/MybatisPlusConfiguration.java @@ -26,6 +26,7 @@ import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator; import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import cn.hutool.core.net.NetUtil; @@ -48,6 +49,8 @@ public class MybatisPlusConfiguration { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 数据权限插件 + interceptor.addInnerInterceptor(new DataPermissionInterceptor(new DataPermissionHandlerImpl())); // 分页插件 interceptor.addInnerInterceptor(paginationInnerInterceptor()); // 防全表更新与删除插件 diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/constant/SysConsts.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/constant/SysConsts.java index d18ab62d..fccf8a6f 100644 --- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/constant/SysConsts.java +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/constant/SysConsts.java @@ -29,20 +29,20 @@ import lombok.NoArgsConstructor; public class SysConsts { /** - * 超级管理员角色编码 + * 管理员角色编码 */ - public static final String SUPER_ADMIN = "admin"; - - /** - * 全部权限标识 - */ - public static final String ALL_PERMISSION = "*"; + public static final String ADMIN_ROLE_CODE = "admin"; /** * 顶级父 ID */ public static final Long SUPER_PARENT_ID = 0L; + /** + * 全部权限标识 + */ + public static final String ALL_PERMISSION = "*"; + /** * 默认密码 */ diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/LoginUser.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/LoginUser.java index 0492c682..74f43864 100644 --- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/LoginUser.java +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/LoginUser.java @@ -22,6 +22,9 @@ import java.util.Set; import lombok.Data; +import cn.hutool.core.collection.CollUtil; + +import top.charles7c.cnadmin.common.constant.SysConsts; import top.charles7c.cnadmin.common.enums.GenderEnum; /** @@ -129,4 +132,21 @@ public class LoginUser implements Serializable { * 角色编码集合 */ private Set roles; + + /** + * 角色集合 + */ + private Set roleSet; + + /** + * 是否为管理员 + * + * @return true:是,false:否 + */ + public boolean isAdmin() { + if (CollUtil.isEmpty(roles)) { + return false; + } + return roles.contains(SysConsts.ADMIN_ROLE_CODE); + } } diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/RoleDTO.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/RoleDTO.java new file mode 100644 index 00000000..3a7d949a --- /dev/null +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/dto/RoleDTO.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.charles7c.cnadmin.common.model.dto; + +import java.io.Serializable; + +import lombok.Data; + +import top.charles7c.cnadmin.common.enums.DataScopeEnum; + +/** + * 角色信息 + * + * @author Charles7c + * @since 2023/3/7 22:08 + */ +@Data +public class RoleDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * 角色编码 + */ + private String code; + + /** + * 数据权限(1:全部数据权限,2:本部门及以下数据权限,3:本部门数据权限,4:仅本人数据权限,5:自定义数据权限) + */ + private DataScopeEnum dataScope; +} diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java index fa9a61cf..00e7683d 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java @@ -33,6 +33,7 @@ import top.charles7c.cnadmin.common.util.helper.LoginHelper; import top.charles7c.cnadmin.common.util.validate.CheckUtils; import top.charles7c.cnadmin.system.model.entity.UserDO; import top.charles7c.cnadmin.system.service.DeptService; +import top.charles7c.cnadmin.system.service.RoleService; import top.charles7c.cnadmin.system.service.UserService; /** @@ -47,6 +48,7 @@ public class LoginServiceImpl implements LoginService { private final UserService userService; private final DeptService deptService; + private final RoleService roleService; private final PermissionService permissionService; @Override @@ -62,6 +64,7 @@ public class LoginServiceImpl implements LoginService { loginUser.setDeptName(ExceptionUtils.exToNull(() -> deptService.get(loginUser.getDeptId()).getName())); loginUser.setPermissions(permissionService.listPermissionByUserId(userId)); loginUser.setRoles(permissionService.listRoleCodeByUserId(userId)); + loginUser.setRoleSet(roleService.listByUserId(userId)); LoginHelper.login(loginUser); // 返回令牌 diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/PermissionServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/PermissionServiceImpl.java index 3007f0ba..daafa551 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/PermissionServiceImpl.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/PermissionServiceImpl.java @@ -46,7 +46,7 @@ public class PermissionServiceImpl implements PermissionService { public Set listPermissionByUserId(Long userId) { Set roleCodeSet = this.listRoleCodeByUserId(userId); // 超级管理员赋予全部权限 - if (roleCodeSet.contains(SysConsts.SUPER_ADMIN)) { + if (roleCodeSet.contains(SysConsts.ADMIN_ROLE_CODE)) { return CollUtil.newHashSet(SysConsts.ALL_PERMISSION); } return menuService.listPermissionByUserId(userId); diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/entity/DeptDO.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/entity/DeptDO.java index 3e7e1a95..36d43bfa 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/entity/DeptDO.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/entity/DeptDO.java @@ -45,6 +45,11 @@ public class DeptDO extends BaseDO { */ private Long parentId; + /** + * 祖级列表 + */ + private String ancestors; + /** * 描述 */ diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/DeptRequest.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/DeptRequest.java index b22555a3..f69b9b4b 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/DeptRequest.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/DeptRequest.java @@ -72,4 +72,10 @@ public class DeptRequest extends BaseRequest { */ @Schema(description = "状态(1启用 2禁用)", type = "Integer", allowableValues = {"1", "2"}) private DisEnableStatusEnum status; + + /** + * 祖级列表 + */ + @Schema(description = "祖级列表") + private String ancestors; } diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/vo/RoleVO.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/vo/RoleVO.java index cb9fa08f..47c9cbb1 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/vo/RoleVO.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/vo/RoleVO.java @@ -84,7 +84,7 @@ public class RoleVO extends BaseVO { private Boolean disabled; public Boolean getDisabled() { - if (SysConsts.SUPER_ADMIN.equals(code)) { + if (SysConsts.ADMIN_ROLE_CODE.equals(code)) { return true; } return disabled; diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/RoleService.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/RoleService.java index 814d7bfb..8f1d0e72 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/RoleService.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/RoleService.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Set; import top.charles7c.cnadmin.common.base.BaseService; +import top.charles7c.cnadmin.common.model.dto.RoleDTO; import top.charles7c.cnadmin.common.model.vo.LabelValueVO; import top.charles7c.cnadmin.system.model.query.RoleQuery; import top.charles7c.cnadmin.system.model.request.RoleRequest; @@ -60,4 +61,13 @@ public interface RoleService extends BaseService listCodeByUserId(Long userId); + + /** + * 根据用户 ID 查询角色 + * + * @param userId + * 用户 ID + * @return 角色集合 + */ + Set listByUserId(Long userId); } diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/DeptServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/DeptServiceImpl.java index 86214f62..98c2710a 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/DeptServiceImpl.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/DeptServiceImpl.java @@ -16,6 +16,7 @@ package top.charles7c.cnadmin.system.service.impl; +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -26,6 +27,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import cn.hutool.core.collection.CollUtil; + import top.charles7c.cnadmin.common.base.BaseServiceImpl; import top.charles7c.cnadmin.common.constant.SysConsts; import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; @@ -62,6 +65,9 @@ public class DeptServiceImpl extends BaseServiceImpl isExists, String.format("新增失败,'%s'已存在", name)); request.setStatus(DisEnableStatusEnum.ENABLE); + DeptDO parentDept = baseMapper.selectById(request.getParentId()); + CheckUtils.throwIfNull(parentDept, "上级部门不存在"); + request.setAncestors(String.format("%s,%s", parentDept.getAncestors(), request.getParentId())); return super.add(request); } @@ -72,6 +78,14 @@ public class DeptServiceImpl extends BaseServiceImpl isExists, String.format("修改失败,'%s'已存在", name)); + DeptDO oldDept = baseMapper.selectById(request.getId()); + // 更新祖级列表 + if (!Objects.equals(oldDept.getParentId(), request.getParentId())) { + DeptDO newParentDept = baseMapper.selectById(request.getParentId()); + CheckUtils.throwIfNull(newParentDept, "上级部门不存在"); + request.setAncestors(String.format("%s,%s", newParentDept.getAncestors(), request.getParentId())); + this.updateChildrenAncestors(request.getId(), request.getAncestors(), oldDept.getAncestors()); + } super.update(request); } @@ -110,4 +124,30 @@ public class DeptServiceImpl extends BaseServiceImpl children = + baseMapper.lambdaQuery().apply(String.format("find_in_set(%s, `ancestors`)", id)).list(); + if (CollUtil.isEmpty(children)) { + return; + } + List list = new ArrayList<>(children.size()); + for (DeptDO child : children) { + DeptDO dept = new DeptDO(); + dept.setId(child.getId()); + dept.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); + list.add(dept); + } + baseMapper.updateBatchById(list); + } } diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/RoleServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/RoleServiceImpl.java index fd79c5e2..33fb22cd 100644 --- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/RoleServiceImpl.java +++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/RoleServiceImpl.java @@ -17,6 +17,7 @@ package top.charles7c.cnadmin.system.service.impl; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -26,11 +27,13 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import top.charles7c.cnadmin.common.base.BaseServiceImpl; import top.charles7c.cnadmin.common.constant.SysConsts; import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; +import top.charles7c.cnadmin.common.model.dto.RoleDTO; import top.charles7c.cnadmin.common.model.vo.LabelValueVO; import top.charles7c.cnadmin.common.util.validate.CheckUtils; import top.charles7c.cnadmin.system.mapper.RoleMapper; @@ -106,7 +109,7 @@ public class RoleServiceImpl extends BaseServiceImpl list = menuService.list(null, null); List menuIds = list.stream().map(MenuVO::getId).collect(Collectors.toList()); detailVO.setMenuIds(menuIds); @@ -138,6 +141,13 @@ public class RoleServiceImpl extends BaseServiceImpl listByUserId(Long userId) { + List roleIds = userRoleService.listRoleIdByUserId(userId); + List roleList = baseMapper.lambdaQuery().in(RoleDO::getId, roleIds).list(); + return new HashSet<>(BeanUtil.copyToList(roleList, RoleDTO.class)); + } + /** * 检查名称是否存在 * diff --git a/continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_data.sql b/continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_data.sql index e8c45d6d..89b0ba72 100644 --- a/continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_data.sql +++ b/continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_data.sql @@ -35,14 +35,14 @@ INSERT IGNORE INTO `sys_menu` VALUES (10000, 'Arco Design Vue', 0, 1, 'https://a INSERT IGNORE INTO `sys_menu` VALUES (10001, 'GitHub', 0, 1, 'https://github.com/Charles7c/continew-admin', NULL, NULL, 'github', b'1', b'0', b'0', NULL, 101, 1, 1, NOW(), 1, NOW()); -- 初始化默认部门 -INSERT IGNORE INTO `sys_dept` VALUES (1, 'Xxx科技有限公司', 0, '系统初始部门', 1, 1, 1, NOW(), 1, NOW()); -INSERT IGNORE INTO `sys_dept` VALUES (2, '天津总部', 1, '系统初始部门', 1, 1, 1, NOW(), 1, NOW()); -INSERT IGNORE INTO `sys_dept` VALUES (3, '研发部', 2, '系统初始部门', 1, 1, 1, NOW(), 1, NOW()); -INSERT IGNORE INTO `sys_dept` VALUES (4, 'UI部', 2, '系统初始部门', 2, 1, 1, NOW(), 1, NOW()); -INSERT IGNORE INTO `sys_dept` VALUES (5, '测试部', 2, '系统初始部门', 3, 1, 1, NOW(), 1, NOW()); -INSERT IGNORE INTO `sys_dept` VALUES (6, '运维部', 2, '系统初始部门', 4, 1, 1, NOW(), 1, NOW()); -INSERT IGNORE INTO `sys_dept` VALUES (7, '研发一组', 3, '系统初始部门', 1, 1, 1, NOW(), 1, NOW()); -INSERT IGNORE INTO `sys_dept` VALUES (8, '研发二组', 3, '系统初始部门', 2, 2, 1, NOW(), 1, NOW()); +INSERT IGNORE INTO `sys_dept` VALUES (1, 'Xxx科技有限公司', 0, '0', '系统初始部门', 1, 1, 1, NOW(), 1, NOW()); +INSERT IGNORE INTO `sys_dept` VALUES (2, '天津总部', 1, '0,1', '系统初始部门', 1, 1, 1, NOW(), 1, NOW()); +INSERT IGNORE INTO `sys_dept` VALUES (3, '研发部', 2, '0,1,2', '系统初始部门', 1, 1, 1, NOW(), 1, NOW()); +INSERT IGNORE INTO `sys_dept` VALUES (4, 'UI部', 2, '0,1,2', '系统初始部门', 2, 1, 1, NOW(), 1, NOW()); +INSERT IGNORE INTO `sys_dept` VALUES (5, '测试部', 2, '0,1,2', '系统初始部门', 3, 1, 1, NOW(), 1, NOW()); +INSERT IGNORE INTO `sys_dept` VALUES (6, '运维部', 2, '0,1,2', '系统初始部门', 4, 1, 1, NOW(), 1, NOW()); +INSERT IGNORE INTO `sys_dept` VALUES (7, '研发一组', 3, '0,1,2,3', '系统初始部门', 1, 1, 1, NOW(), 1, NOW()); +INSERT IGNORE INTO `sys_dept` VALUES (8, '研发二组', 3, '0,1,2,3', '系统初始部门', 2, 2, 1, NOW(), 1, NOW()); -- 初始化默认角色 INSERT IGNORE INTO `sys_role` VALUES (1, '超级管理员', 'admin', 1, '系统初始角色', 1, 1, 1, NOW(), 1, NOW()); diff --git a/continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_table.sql b/continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_table.sql index 6d034374..c8e908c8 100644 --- a/continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_table.sql +++ b/continew-admin-webapi/src/main/resources/db/changelog/v0.0.1/continew-admin_table.sql @@ -30,6 +30,7 @@ CREATE TABLE IF NOT EXISTS `sys_dept` ( `id` bigint(20) unsigned AUTO_INCREMENT COMMENT 'ID', `name` varchar(255) NOT NULL COMMENT '部门名称', `parent_id` bigint(20) unsigned DEFAULT 0 COMMENT '上级部门ID', + `ancestors` varchar(512) DEFAULT '' COMMENT '祖级列表', `description` varchar(512) DEFAULT NULL COMMENT '描述', `sort` int(11) unsigned DEFAULT 999 COMMENT '部门排序', `status` tinyint(1) unsigned DEFAULT 1 COMMENT '状态(1:启用,2:禁用)',