✨ 添加新特性。数据权限,统一异常包装处理
This commit is contained in:
1 parent
018a625f56
commit
fe9283ddc2
11 files changed
+273
-15
No files matched your search
+46
@@ -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<Integer> deptIds;
|
||||
|
||||
/**
|
||||
* 是否只查询本部门
|
||||
*/
|
||||
private Boolean isOnly = false;
|
||||
}
|
||||
+124
@@ -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
|
||||
* <p>
|
||||
* 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<Integer> 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;
|
||||
}
|
||||
|
||||
}
|
||||
+49
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
# 数据源配置
|
||||
|
||||
@@ -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
|
||||
|
||||
## 定时任务
|
||||
|
||||
@@ -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
|
||||
|
||||
# 数据源
|
||||
|
||||
+11
@@ -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();
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -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<SysUser> {
|
||||
*
|
||||
* @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查询用户信息
|
||||
|
||||
+32
-7
@@ -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<SysUserMapper, SysUser> 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<SysUserMapper, SysUser> 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<SysUserMapper, SysUser> 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<SysUserMapper, SysUser> impl
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的子部门信息
|
||||
*
|
||||
* @return 子部门列表
|
||||
*/
|
||||
private List<Integer> getChildDepts() {
|
||||
Integer deptId = SecurityUtils.getUser().getDeptId();
|
||||
|
||||
//获取当前部门的子部门
|
||||
SysDeptRelation deptRelation = new SysDeptRelation();
|
||||
deptRelation.setAncestor(deptId);
|
||||
List<SysDeptRelation> deptRelationList = sysDeptRelationService.selectList(new EntityWrapper<>(deptRelation));
|
||||
List<Integer> deptIds = new ArrayList<>();
|
||||
for (SysDeptRelation sysDeptRelation : deptRelationList) {
|
||||
deptIds.add(sysDeptRelation.getDescendant());
|
||||
}
|
||||
return deptIds;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user