diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/datascope/DataScope.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/datascope/DataScope.java new file mode 100644 index 000000000..758fb6a66 --- /dev/null +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/datascope/DataScope.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.common.core.datascope; + +import lombok.Data; + +import java.util.HashMap; +import java.util.List; + +/** + * @author lengleng + * @date 2018/8/30 + * 数据权限查询参数 + */ +@Data +public class DataScope extends HashMap { + /** + * 限制范围的字段名称 + */ + private String scopeName = "deptId"; + + /** + * 具体的数据范围 + */ + private List deptIds; + + /** + * 是否只查询本部门 + */ + private Boolean isOnly = false; +} diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/datascope/DataScopeInterceptor.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/datascope/DataScopeInterceptor.java new file mode 100644 index 000000000..cb741a176 --- /dev/null +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/datascope/DataScopeInterceptor.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.common.core.datascope; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.plugins.SqlParserHandler; +import com.baomidou.mybatisplus.toolkit.PluginUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.executor.statement.StatementHandler; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlCommandType; +import org.apache.ibatis.plugin.*; +import org.apache.ibatis.reflection.MetaObject; +import org.apache.ibatis.reflection.SystemMetaObject; + +import java.sql.Connection; +import java.util.List; +import java.util.Map; +import java.util.Properties; + + +/** + * @author lengleng + * @date 2018/8/30 + *

+ * mybatis 数据权限拦截器 + */ +@Slf4j +@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})}) +public class DataScopeInterceptor extends SqlParserHandler implements Interceptor { + + @Override + public Object intercept(Invocation invocation) throws Throwable { + StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget()); + MetaObject metaObject = SystemMetaObject.forObject(statementHandler); + this.sqlParser(metaObject); + // 先判断是不是SELECT操作 + MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement"); + if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) { + return invocation.proceed(); + } + + BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql"); + String originalSql = boundSql.getSql(); + Object parameterObject = boundSql.getParameterObject(); + + //查找参数中包含DataScope类型的参数 + DataScope dataScope = findDataScopeObject(parameterObject); + + if (dataScope == null) { + return invocation.proceed(); + } else { + String scopeName = dataScope.getScopeName(); + List deptIds = dataScope.getDeptIds(); + if (StrUtil.isNotBlank(scopeName) && CollectionUtil.isNotEmpty(deptIds)) { + String join = CollectionUtil.join(deptIds, ","); + originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + scopeName + " in (" + join + ")"; + metaObject.setValue("delegate.boundSql.sql", originalSql); + } + return invocation.proceed(); + } + } + + /** + * 生成拦截对象的代理 + * + * @param target 目标对象 + * @return 代理对象 + */ + @Override + public Object plugin(Object target) { + if (target instanceof StatementHandler) { + return Plugin.wrap(target, this); + } + return target; + } + + /** + * mybatis配置的属性 + * + * @param properties mybatis配置的属性 + */ + @Override + public void setProperties(Properties properties) { + + } + + /** + * 查找参数是否包括DataScope对象 + * + * @param parameterObj 参数列表 + * @return DataScope + */ + private DataScope findDataScopeObject(Object parameterObj) { + if (parameterObj instanceof DataScope) { + return (DataScope) parameterObj; + } else if (parameterObj instanceof Map) { + for (Object val : ((Map) parameterObj).values()) { + if (val instanceof DataScope) { + return (DataScope) val; + } + } + } + return null; + } + +} diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/GlobalExceptionHandler.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/GlobalExceptionHandler.java new file mode 100644 index 000000000..84e520e81 --- /dev/null +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/exception/GlobalExceptionHandler.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.common.core.exception; + +import com.pig4cloud.pigx.common.core.util.R; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * @author lengleng + * @date 2018/8/30 + * 全局的的异常处理器 + */ +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + /** + * 全局异常. + * + * @param e the e + * @return R + */ + @ExceptionHandler(Exception.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ResponseBody + public R exception(Exception e) { + log.info("全局异常信息 ex={}", e.getMessage(), e); + return new R<>(e); + } +} diff --git a/pigx-common/pigx-common-core/src/main/resources/META-INF/spring.factories b/pigx-common/pigx-common-core/src/main/resources/META-INF/spring.factories index d7e609cc1..403ef275d 100644 --- a/pigx-common/pigx-common-core/src/main/resources/META-INF/spring.factories +++ b/pigx-common/pigx-common-core/src/main/resources/META-INF/spring.factories @@ -2,4 +2,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.pig4cloud.pigx.common.core.config.JacksonConfig,\ com.pig4cloud.pigx.common.core.config.RedisConfig,\ com.pig4cloud.pigx.common.core.config.RestTemplateConfig,\ + com.pig4cloud.pigx.common.core.exception.GlobalExceptionHandler,\ com.pig4cloud.pigx.common.core.util.SpringContextHolder diff --git a/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java b/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java index aac5ee234..d62361653 100644 --- a/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java +++ b/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java @@ -38,7 +38,7 @@ import org.aspectj.lang.annotation.Aspect; public class SysLogAspect { @Around("@annotation(sysLog)") - public Object aroundWxApi(ProceedingJoinPoint point, SysLog sysLog) throws Throwable { + public Object around(ProceedingJoinPoint point, SysLog sysLog) throws Throwable { String strClassName = point.getTarget().getClass().getName(); String strMethodName = point.getSignature().getName(); log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName); diff --git a/pigx-config/src/main/resources/config/pigx-codegen-dev.yml b/pigx-config/src/main/resources/config/pigx-codegen-dev.yml index cbfb4984c..46304f871 100644 --- a/pigx-config/src/main/resources/config/pigx-codegen-dev.yml +++ b/pigx-config/src/main/resources/config/pigx-codegen-dev.yml @@ -2,8 +2,8 @@ security: oauth2: client: - client-id: ENC(xD1AY92cohwLfefsXett5Q==) - client-secret: ENC(xD1AY92cohwLfefsXett5Q==) + client-id: ENC(gPFcUOmJm8WqM3k3eSqS0Q==) + client-secret: ENC(gPFcUOmJm8WqM3k3eSqS0Q==) scope: server # 数据源配置 diff --git a/pigx-config/src/main/resources/config/pigx-daemon-dev.yml b/pigx-config/src/main/resources/config/pigx-daemon-dev.yml index fa0c91c7f..effd2ac2c 100644 --- a/pigx-config/src/main/resources/config/pigx-daemon-dev.yml +++ b/pigx-config/src/main/resources/config/pigx-daemon-dev.yml @@ -2,8 +2,8 @@ security: oauth2: client: - client-id: ENC(Y91StLXT8tX5TwpcTSR2kg==) - client-secret: ENC(Y91StLXT8tX5TwpcTSR2kg==) + client-id: ENC(tz2NM4GcmnE7sNJTYL8ZSg==) + client-secret: ENC(tz2NM4GcmnE7sNJTYL8ZSg==) scope: server ## 定时任务 diff --git a/pigx-config/src/main/resources/config/pigx-upms-dev.yml b/pigx-config/src/main/resources/config/pigx-upms-dev.yml index 2529c5085..541b41bde 100644 --- a/pigx-config/src/main/resources/config/pigx-upms-dev.yml +++ b/pigx-config/src/main/resources/config/pigx-upms-dev.yml @@ -2,8 +2,8 @@ security: oauth2: client: - client-id: ENC(iVEZk4Gdt0UXDlX7ZN9J5g==) - client-secret: ENC(iVEZk4Gdt0UXDlX7ZN9J5g==) + client-id: ENC(ltJPpR50wT0oIY9kfOe1Iw==) + client-secret: ENC(ltJPpR50wT0oIY9kfOe1Iw==) scope: server # 数据源 diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/config/MybatisPlusConfigurer.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/config/MybatisPlusConfigurer.java index 9fd5436b4..9e3bbacd4 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/config/MybatisPlusConfigurer.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/config/MybatisPlusConfigurer.java @@ -20,6 +20,7 @@ package com.pig4cloud.pigx.admin.config; import com.baomidou.mybatisplus.plugins.PaginationInterceptor; +import com.pig4cloud.pigx.common.core.datascope.DataScopeInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -40,4 +41,14 @@ public class MybatisPlusConfigurer { public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } + + /** + * 数据权限插件 + * + * @return DataScopeInterceptor + */ + @Bean + public DataScopeInterceptor dataScopeInterceptor() { + return new DataScopeInterceptor(); + } } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserMapper.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserMapper.java index 18dc81e8b..880419e45 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserMapper.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/mapper/SysUserMapper.java @@ -22,6 +22,7 @@ package com.pig4cloud.pigx.admin.mapper; import com.baomidou.mybatisplus.mapper.BaseMapper; import com.pig4cloud.pigx.admin.api.entity.SysUser; import com.pig4cloud.pigx.admin.api.vo.UserVO; +import com.pig4cloud.pigx.common.core.datascope.DataScope; import com.pig4cloud.pigx.common.core.util.Query; import org.apache.ibatis.annotations.Param; @@ -49,9 +50,10 @@ public interface SysUserMapper extends BaseMapper { * * @param query 查询条件 * @param username 用户名 + * @param dataScope * @return list */ - List selectUserVoPage(Query query, @Param("username") Object username); + List selectUserVoPage(Query query, @Param("username") Object username, DataScope dataScope); /** * 通过ID查询用户信息 diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java index fcc4f8a61..5bbacedff 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java @@ -27,19 +27,19 @@ import com.baomidou.mybatisplus.plugins.Page; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.pig4cloud.pigx.admin.api.dto.UserDTO; import com.pig4cloud.pigx.admin.api.dto.UserInfo; +import com.pig4cloud.pigx.admin.api.entity.SysDeptRelation; import com.pig4cloud.pigx.admin.api.entity.SysRole; import com.pig4cloud.pigx.admin.api.entity.SysUser; import com.pig4cloud.pigx.admin.api.entity.SysUserRole; import com.pig4cloud.pigx.admin.api.vo.MenuVO; import com.pig4cloud.pigx.admin.api.vo.UserVO; import com.pig4cloud.pigx.admin.mapper.SysUserMapper; -import com.pig4cloud.pigx.admin.service.SysMenuService; -import com.pig4cloud.pigx.admin.service.SysRoleService; -import com.pig4cloud.pigx.admin.service.SysUserRoleService; -import com.pig4cloud.pigx.admin.service.SysUserService; +import com.pig4cloud.pigx.admin.service.*; import com.pig4cloud.pigx.common.core.constant.enums.EnumLoginType; +import com.pig4cloud.pigx.common.core.datascope.DataScope; import com.pig4cloud.pigx.common.core.util.Query; import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.security.util.SecurityUtils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; @@ -69,6 +69,7 @@ public class SysUserServiceImpl extends ServiceImpl impl private final SysUserMapper sysUserMapper; private final SysRoleService sysRoleService; private final SysUserRoleService sysUserRoleService; + private final SysDeptRelationService sysDeptRelationService; /** * 通过用户名查用户的全部信息 @@ -121,8 +122,12 @@ public class SysUserServiceImpl extends ServiceImpl impl @Override public Page selectWithRolePage(Query query) { + DataScope dataScope = new DataScope(); + dataScope.setScopeName("deptId"); + dataScope.setIsOnly(true); + dataScope.setDeptIds(getChildDepts()); Object username = query.getCondition().get("username"); - query.setRecords(sysUserMapper.selectUserVoPage(query, username)); + query.setRecords(sysUserMapper.selectUserVoPage(query, username, dataScope)); return query; } @@ -151,13 +156,14 @@ public class SysUserServiceImpl extends ServiceImpl impl /** * 根据用户名删除用户(真实删除) + * * @param username * @return */ @Override - public Boolean deleteSysUserByUsernameAndUserId(String username,Integer userId) { + public Boolean deleteSysUserByUsernameAndUserId(String username, Integer userId) { - sysUserMapper.deleteSysUserByUsernameAndUserId(username,userId); + sysUserMapper.deleteSysUserByUsernameAndUserId(username, userId); SysUserRole condition = new SysUserRole(); condition.setUserId(userId); sysUserRoleService.delete(new EntityWrapper<>(condition)); @@ -218,4 +224,23 @@ public class SysUserServiceImpl extends ServiceImpl impl return Boolean.TRUE; } + /** + * 获取当前用户的子部门信息 + * + * @return 子部门列表 + */ + private List getChildDepts() { + Integer deptId = SecurityUtils.getUser().getDeptId(); + + //获取当前部门的子部门 + SysDeptRelation deptRelation = new SysDeptRelation(); + deptRelation.setAncestor(deptId); + List deptRelationList = sysDeptRelationService.selectList(new EntityWrapper<>(deptRelation)); + List deptIds = new ArrayList<>(); + for (SysDeptRelation sysDeptRelation : deptRelationList) { + deptIds.add(sysDeptRelation.getDescendant()); + } + return deptIds; + } + }