Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Pig
提交
3f3def6f
P
Pig
项目概览
int
/
Pig
上一次同步 大约 1 年
通知
8
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Pig
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3f3def6f
编写于
9月 12, 2021
作者:
云
云彩ing
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'dev' of git.zhlh6.cn:pig-mesh/pig into dev
上级
828d4e15
62342a04
变更
49
隐藏空白更改
内联
并排
Showing
49 changed file
with
2080 addition
and
27 deletion
+2080
-27
pig-auth/src/main/java/com/pig4cloud/pig/auth/config/AuthorizationServerConfig.java
.../pig4cloud/pig/auth/config/AuthorizationServerConfig.java
+12
-5
pig-auth/src/main/java/com/pig4cloud/pig/auth/converter/CustomAccessTokenConverter.java
...4cloud/pig/auth/converter/CustomAccessTokenConverter.java
+37
-0
pig-common/pig-common-bom/pom.xml
pig-common/pig-common-bom/pom.xml
+19
-1
pig-common/pig-common-core/src/main/java/com/pig4cloud/pig/common/core/constant/SecurityConstants.java
...pig4cloud/pig/common/core/constant/SecurityConstants.java
+5
-0
pig-common/pig-common-core/src/main/java/com/pig4cloud/pig/common/core/constant/enums/DataScopeTypeEnum.java
...oud/pig/common/core/constant/enums/DataScopeTypeEnum.java
+49
-0
pig-common/pig-common-datascope/pom.xml
pig-common/pig-common-datascope/pom.xml
+38
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/DataScope.java
...ain/java/com/pigcloud/pig/common/datascope/DataScope.java
+36
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/DataScopeAutoConfiguration.java
...loud/pig/common/datascope/DataScopeAutoConfiguration.java
+54
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/annotation/DataPermission.java
...cloud/pig/common/datascope/annotation/DataPermission.java
+35
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/handler/DataPermissionHandler.java
...d/pig/common/datascope/handler/DataPermissionHandler.java
+35
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/handler/DefaultDataPermissionHandler.java
...ommon/datascope/handler/DefaultDataPermissionHandler.java
+76
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/holder/DataPermissionAnnotationHolder.java
...mmon/datascope/holder/DataPermissionAnnotationHolder.java
+58
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/holder/DataScopeHolder.java
...pigcloud/pig/common/datascope/holder/DataScopeHolder.java
+41
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/interceptor/DataPermissionAnnotationAdvisor.java
...atascope/interceptor/DataPermissionAnnotationAdvisor.java
+34
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/interceptor/DataPermissionAnnotationInterceptor.java
...cope/interceptor/DataPermissionAnnotationInterceptor.java
+35
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/interceptor/DataPermissionFinder.java
...ig/common/datascope/interceptor/DataPermissionFinder.java
+65
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/interceptor/DataPermissionInterceptor.java
...mmon/datascope/interceptor/DataPermissionInterceptor.java
+72
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/parser/JsqlParserSupport.java
...gcloud/pig/common/datascope/parser/JsqlParserSupport.java
+114
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/processor/DataScopeSqlProcessor.java
...pig/common/datascope/processor/DataScopeSqlProcessor.java
+321
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/util/AnnotationUtil.java
...om/pigcloud/pig/common/datascope/util/AnnotationUtil.java
+64
-0
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/util/PluginUtils.java
...a/com/pigcloud/pig/common/datascope/util/PluginUtils.java
+163
-0
pig-common/pig-common-datascope/src/main/resources/META-INF/spring.factories
...on-datascope/src/main/resources/META-INF/spring.factories
+3
-0
pig-common/pig-common-datascope/src/test/java/com/pigcloud/pig/common/datascope/test/SqlParseTest.java
.../com/pigcloud/pig/common/datascope/test/SqlParseTest.java
+75
-0
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigUserAuthenticationConverter.java
...on/security/component/PigUserAuthenticationConverter.java
+15
-1
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/datascope/DataScopeProcessor.java
...oud/pig/common/security/datascope/DataScopeProcessor.java
+21
-0
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/datascope/PigDataScopeProcessor.java
.../pig/common/security/datascope/PigDataScopeProcessor.java
+119
-0
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/datascope/UserDataScope.java
...ig4cloud/pig/common/security/datascope/UserDataScope.java
+35
-0
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigUser.java
...va/com/pig4cloud/pig/common/security/service/PigUser.java
+11
-3
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigUserDetailsServiceImpl.java
...ig/common/security/service/PigUserDetailsServiceImpl.java
+11
-3
pig-common/pig-common-security/src/main/resources/META-INF/spring.factories
...mon-security/src/main/resources/META-INF/spring.factories
+2
-1
pig-common/pom.xml
pig-common/pom.xml
+2
-1
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/dto/UserInfo.java
...c/main/java/com/pig4cloud/pig/admin/api/dto/UserInfo.java
+9
-0
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/entity/SysRole.java
...main/java/com/pig4cloud/pig/admin/api/entity/SysRole.java
+8
-0
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/RemoteDeptService.java
.../com/pig4cloud/pig/admin/api/feign/RemoteDeptService.java
+45
-0
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/RemoteUserService.java
.../com/pig4cloud/pig/admin/api/feign/RemoteUserService.java
+14
-0
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/factory/RemoteDeptServiceFallbackFactory.java
...n/api/feign/factory/RemoteDeptServiceFallbackFactory.java
+37
-0
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/fallback/RemoteDeptServiceFallbackImpl.java
...min/api/feign/fallback/RemoteDeptServiceFallbackImpl.java
+45
-0
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java
...min/api/feign/fallback/RemoteUserServiceFallbackImpl.java
+9
-0
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/vo/UserInfoVO.java
.../main/java/com/pig4cloud/pig/admin/api/vo/UserInfoVO.java
+49
-0
pig-upms/pig-upms-api/src/main/resources/META-INF/spring.factories
...pig-upms-api/src/main/resources/META-INF/spring.factories
+3
-1
pig-upms/pig-upms-biz/pom.xml
pig-upms/pig-upms-biz/pom.xml
+5
-0
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/controller/DeptController.java
...va/com/pig4cloud/pig/admin/controller/DeptController.java
+12
-0
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/controller/UserController.java
...va/com/pig4cloud/pig/admin/controller/UserController.java
+29
-2
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/datascope/PigDataScope.java
.../java/com/pig4cloud/pig/admin/datascope/PigDataScope.java
+115
-0
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/service/SysDeptService.java
.../java/com/pig4cloud/pig/admin/service/SysDeptService.java
+7
-0
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/service/SysUserService.java
.../java/com/pig4cloud/pig/admin/service/SysUserService.java
+8
-0
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/service/impl/SysDeptServiceImpl.java
.../pig4cloud/pig/admin/service/impl/SysDeptServiceImpl.java
+11
-0
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/service/impl/SysUserServiceImpl.java
.../pig4cloud/pig/admin/service/impl/SysUserServiceImpl.java
+17
-3
pig-visual/pig-xxl-job-admin/pom.xml
pig-visual/pig-xxl-job-admin/pom.xml
+0
-6
未找到文件。
pig-auth/src/main/java/com/pig4cloud/pig/auth/config/AuthorizationServerConfig.java
浏览文件 @
3f3def6f
...
...
@@ -16,6 +16,7 @@
package
com.pig4cloud.pig.auth.config
;
import
com.pig4cloud.pig.auth.converter.CustomAccessTokenConverter
;
import
com.pig4cloud.pig.common.core.constant.CacheConstants
;
import
com.pig4cloud.pig.common.core.constant.SecurityConstants
;
import
com.pig4cloud.pig.common.security.component.PigWebResponseExceptionTranslator
;
...
...
@@ -63,10 +64,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
@Override
@SneakyThrows
public
void
configure
(
ClientDetailsServiceConfigurer
clients
)
{
PigClientDetailsService
clientDetailsService
=
new
PigClientDetailsService
(
dataSource
);
clientDetailsService
.
setSelectClientDetailsSql
(
SecurityConstants
.
DEFAULT_SELECT_STATEMENT
);
clientDetailsService
.
setFindClientDetailsSql
(
SecurityConstants
.
DEFAULT_FIND_STATEMENT
);
clients
.
withClientDetails
(
clientDetailsService
);
clients
.
withClientDetails
(
pigClientDetailsService
());
}
@Override
...
...
@@ -80,7 +78,8 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
.
tokenEnhancer
(
tokenEnhancer
()).
userDetailsService
(
userDetailsService
)
.
authenticationManager
(
authenticationManager
).
reuseRefreshTokens
(
false
)
.
pathMapping
(
"/oauth/confirm_access"
,
"/token/confirm_access"
)
.
exceptionTranslator
(
new
PigWebResponseExceptionTranslator
());
.
exceptionTranslator
(
new
PigWebResponseExceptionTranslator
())
.
accessTokenConverter
(
new
CustomAccessTokenConverter
(
pigClientDetailsService
()));
}
@Bean
...
...
@@ -104,4 +103,12 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
};
}
@Bean
public
PigClientDetailsService
pigClientDetailsService
()
{
PigClientDetailsService
clientDetailsService
=
new
PigClientDetailsService
(
dataSource
);
clientDetailsService
.
setSelectClientDetailsSql
(
SecurityConstants
.
DEFAULT_SELECT_STATEMENT
);
clientDetailsService
.
setFindClientDetailsSql
(
SecurityConstants
.
DEFAULT_FIND_STATEMENT
);
return
clientDetailsService
;
}
}
pig-auth/src/main/java/com/pig4cloud/pig/auth/converter/CustomAccessTokenConverter.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pig4cloud.pig.auth.converter
;
import
com.pig4cloud.pig.common.core.constant.SecurityConstants
;
import
com.pig4cloud.pig.common.security.service.PigClientDetailsService
;
import
com.pig4cloud.pig.common.security.service.PigUser
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.security.oauth2.common.OAuth2AccessToken
;
import
org.springframework.security.oauth2.provider.ClientDetails
;
import
org.springframework.security.oauth2.provider.OAuth2Authentication
;
import
org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter
;
import
java.util.Map
;
/**
* @author hccake
*/
@RequiredArgsConstructor
public
class
CustomAccessTokenConverter
extends
DefaultAccessTokenConverter
{
final
PigClientDetailsService
pigClientDetailsService
;
@Override
@SuppressWarnings
(
"unchecked"
)
public
Map
<
String
,
?>
convertAccessToken
(
OAuth2AccessToken
token
,
OAuth2Authentication
authentication
)
{
Map
<
String
,
Object
>
response
=
(
Map
<
String
,
Object
>)
super
.
convertAccessToken
(
token
,
authentication
);
ClientDetails
clientDetails
=
pigClientDetailsService
.
loadClientByClientId
(
authentication
.
getOAuth2Request
().
getClientId
());
if
(
clientDetails
!=
null
&&
clientDetails
.
getScope
().
contains
(
"read_data_scope"
))
{
PigUser
principal
=
(
PigUser
)
authentication
.
getPrincipal
();
response
.
put
(
SecurityConstants
.
DETAILS_USER_DATA_SCOPE
,
principal
.
getUserDataScope
());
}
return
response
;
}
}
pig-common/pig-common-bom/pom.xml
浏览文件 @
3f3def6f
...
...
@@ -25,6 +25,9 @@
<fastjson.version>
1.2.75
</fastjson.version>
<swagger.core.version>
1.5.24
</swagger.core.version>
<mybatis-plus.version>
3.4.3.3
</mybatis-plus.version>
<mybatis.version>
3.5.7
</mybatis.version>
<jsqlparser.version>
4.1
</jsqlparser.version>
<rocksdbjni.version>
5.18.3
</rocksdbjni.version>
<nacos.version>
2.0.3
</nacos.version>
<excel.version>
1.0.0
</excel.version>
<oss.version>
1.0.1
</oss.version>
...
...
@@ -38,6 +41,11 @@
<artifactId>
pig-common-core
</artifactId>
<version>
${pig.common.version}
</version>
</dependency>
<dependency>
<groupId>
com.pig4cloud
</groupId>
<artifactId>
pig-common-datascope
</artifactId>
<version>
${pig.common.version}
</version>
</dependency>
<dependency>
<groupId>
com.pig4cloud
</groupId>
<artifactId>
pig-common-datasource
</artifactId>
...
...
@@ -123,12 +131,22 @@
<artifactId>
oss-spring-boot-starter
</artifactId>
<version>
${oss.version}
</version>
</dependency>
<!--
mybatis-plus
-->
<!--
orm 相关
-->
<dependency>
<groupId>
com.baomidou
</groupId>
<artifactId>
mybatis-plus-boot-starter
</artifactId>
<version>
${mybatis-plus.version}
</version>
</dependency>
<dependency>
<groupId>
org.mybatis
</groupId>
<artifactId>
mybatis
</artifactId>
<version>
${mybatis.version}
</version>
</dependency>
<dependency>
<groupId>
com.github.jsqlparser
</groupId>
<artifactId>
jsqlparser
</artifactId>
<version>
${jsqlparser.version}
</version>
</dependency>
<!--web 模块-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
...
...
pig-common/pig-common-core/src/main/java/com/pig4cloud/pig/common/core/constant/SecurityConstants.java
浏览文件 @
3f3def6f
...
...
@@ -109,6 +109,11 @@ public interface SecurityConstants {
*/
String
DETAILS_LICENSE
=
"license"
;
/**
* 用户数据权限信息
*/
String
DETAILS_USER_DATA_SCOPE
=
"user_data_scope"
;
/**
* 验证码有效期,默认 60秒
*/
...
...
pig-common/pig-common-core/src/main/java/com/pig4cloud/pig/common/core/constant/enums/DataScopeTypeEnum.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pig4cloud.pig.common.core.constant.enums
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
/**
* 数据权限范围类型
* @author hccake
*/
@Getter
@AllArgsConstructor
public
enum
DataScopeTypeEnum
{
/**
* 查询全部数据
*/
ALL
(
0
),
/**
* 本人
*/
SELF
(
1
),
/**
* 本人及子级
*/
SELF_CHILD_LEVEL
(
2
),
/**
* 本级
*/
LEVEL
(
3
),
/**
* 本级及子级
*/
LEVEL_CHILD_LEVEL
(
4
),
/**
* 自定义
*/
CUSTOM
(
5
);
/**
* 类型
*/
private
final
Integer
type
;
}
pig-common/pig-common-datascope/pom.xml
0 → 100644
浏览文件 @
3f3def6f
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<parent>
<artifactId>
pig-common
</artifactId>
<groupId>
com.pig4cloud
</groupId>
<version>
3.3.4
</version>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
pig-common-datascope
</artifactId>
<dependencies>
<!-- slf4j日志 -->
<dependency>
<groupId>
org.slf4j
</groupId>
<artifactId>
slf4j-api
</artifactId>
</dependency>
<dependency>
<groupId>
com.github.jsqlparser
</groupId>
<artifactId>
jsqlparser
</artifactId>
</dependency>
<dependency>
<groupId>
org.mybatis
</groupId>
<artifactId>
mybatis
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-context
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-autoconfigure
</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/DataScope.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope
;
import
net.sf.jsqlparser.expression.Alias
;
import
net.sf.jsqlparser.expression.Expression
;
import
java.util.Collection
;
/**
* @author Hccake 2020/9/28
* @version 1.0
*/
public
interface
DataScope
{
/**
* 数据所对应的资源
* @return 资源标识
*/
String
getResource
();
/**
* 该资源相关的所有表,推荐使用 Set 类型。 <br/>
* 如需忽略表名大小写判断,则可以使用 TreeSet,并设置忽略大小写的自定义Comparator。 <br/>
* eg. new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
* @return tableNames
*/
Collection
<
String
>
getTableNames
();
/**
* 根据表名和表别名,动态生成的 where/or 筛选条件
* @param tableName 表名
* @param tableAlias 表别名,可能为空
* @return 数据规则表达式
*/
Expression
getExpression
(
String
tableName
,
Alias
tableAlias
);
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/DataScopeAutoConfiguration.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope
;
import
com.pigcloud.pig.common.datascope.handler.DataPermissionHandler
;
import
com.pigcloud.pig.common.datascope.handler.DefaultDataPermissionHandler
;
import
com.pigcloud.pig.common.datascope.interceptor.DataPermissionAnnotationAdvisor
;
import
com.pigcloud.pig.common.datascope.interceptor.DataPermissionInterceptor
;
import
com.pigcloud.pig.common.datascope.processor.DataScopeSqlProcessor
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.context.annotation.Bean
;
import
java.util.List
;
/**
* @author hccake
*/
@RequiredArgsConstructor
@ConditionalOnBean
(
DataScope
.
class
)
public
class
DataScopeAutoConfiguration
{
/**
* 数据权限处理器
* @param dataScopeList 需要控制的数据范围集合
* @return DataPermissionHandler
*/
@Bean
@ConditionalOnMissingBean
public
DataPermissionHandler
dataPermissionHandler
(
List
<
DataScope
>
dataScopeList
)
{
return
new
DefaultDataPermissionHandler
(
dataScopeList
);
}
/**
* 数据权限注解 Advisor,用于处理数据权限的链式调用关系
* @return DataPermissionAnnotationAdvisor
*/
@Bean
@ConditionalOnMissingBean
(
DataPermissionAnnotationAdvisor
.
class
)
public
DataPermissionAnnotationAdvisor
dataPermissionAnnotationAdvisor
()
{
return
new
DataPermissionAnnotationAdvisor
();
}
/**
* mybatis 拦截器,用于拦截处理 sql
* @param dataPermissionHandler 数据权限处理器
* @return DataPermissionInterceptor
*/
@Bean
@ConditionalOnMissingBean
public
DataPermissionInterceptor
dataPermissionInterceptor
(
DataPermissionHandler
dataPermissionHandler
)
{
return
new
DataPermissionInterceptor
(
new
DataScopeSqlProcessor
(),
dataPermissionHandler
);
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/annotation/DataPermission.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.annotation
;
import
java.lang.annotation.*
;
/**
* 数据权限注解,注解在 Mapper类 或者 对应方法上 用于提供该 mapper 对应表,所需控制的实体信息
* @author Hccake 2020/9/27
* @version 1.0
*/
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
DataPermission
{
/**
* 当前类或方法是否忽略数据权限
* @return boolean 默认返回 false
*/
boolean
ignore
()
default
false
;
/**
* 仅对指定资源类型进行数据权限控制,只在开启情况下有效,当该数组有值时,exclude不生效
* @see DataPermission#excludeResources
* @return 资源类型数组
*/
String
[]
includeResources
()
default
{};
/**
* 对指定资源类型跳过数据权限控制,只在开启情况下有效,当该includeResources有值时,exclude不生效
* @see DataPermission#includeResources
* @return 资源类型数组
*/
String
[]
excludeResources
()
default
{};
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/handler/DataPermissionHandler.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.handler
;
import
com.pigcloud.pig.common.datascope.DataScope
;
import
java.util.List
;
/**
* 数据权限处理器
*
* @author Hccake 2020/9/28
* @version 1.0
*/
public
interface
DataPermissionHandler
{
/**
* 系统配置的所有的数据范围
* @return 数据范围集合
*/
List
<
DataScope
>
dataScopes
();
/**
* 根据权限注解过滤后的数据范围集合
* @param mappedStatementId Mapper方法ID
* @return 数据范围集合
*/
List
<
DataScope
>
filterDataScopes
(
String
mappedStatementId
);
/**
* 是否忽略权限控制,用于及早的忽略控制,例如管理员直接放行,而不必等到DataScope中再进行过滤处理,提升效率
* @return boolean true: 忽略,false: 进行权限控制
* @param mappedStatementId Mapper方法ID
*/
boolean
ignorePermissionControl
(
String
mappedStatementId
);
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/handler/DefaultDataPermissionHandler.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.handler
;
import
com.pigcloud.pig.common.datascope.DataScope
;
import
com.pigcloud.pig.common.datascope.annotation.DataPermission
;
import
com.pigcloud.pig.common.datascope.holder.DataPermissionAnnotationHolder
;
import
lombok.RequiredArgsConstructor
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* 默认的数据权限控制处理器
*
* @author Hccake 2021/1/27
* @version 1.0
*/
@RequiredArgsConstructor
public
class
DefaultDataPermissionHandler
implements
DataPermissionHandler
{
private
final
List
<
DataScope
>
dataScopes
;
/**
* 系统配置的所有的数据范围
* @return 数据范围集合
*/
@Override
public
List
<
DataScope
>
dataScopes
()
{
return
dataScopes
;
}
/**
* 系统配置的所有的数据范围
* @param mappedStatementId Mapper方法ID
* @return 数据范围集合
*/
@Override
public
List
<
DataScope
>
filterDataScopes
(
String
mappedStatementId
)
{
if
(
this
.
dataScopes
==
null
||
this
.
dataScopes
.
isEmpty
())
{
return
new
ArrayList
<>();
}
// 获取当前方法对应的权限注解,根据注解进行数据范围控制的过滤
DataPermission
dataPermission
=
DataPermissionAnnotationHolder
.
peek
();
if
(
dataPermission
==
null
)
{
return
dataScopes
;
}
if
(
dataPermission
.
ignore
())
{
return
new
ArrayList
<>();
}
// 当指定了只包含的资源时,只对该资源的DataScope
if
(
dataPermission
.
includeResources
().
length
>
0
)
{
Set
<
String
>
a
=
new
HashSet
<>(
Arrays
.
asList
(
dataPermission
.
includeResources
()));
return
dataScopes
.
stream
().
filter
(
x
->
a
.
contains
(
x
.
getResource
())).
collect
(
Collectors
.
toList
());
}
// 当未指定只包含的资源,且指定了排除的资源时,则排除此部分资源的 DataScope
if
(
dataPermission
.
excludeResources
().
length
>
0
)
{
Set
<
String
>
a
=
new
HashSet
<>(
Arrays
.
asList
(
dataPermission
.
excludeResources
()));
return
dataScopes
.
stream
().
filter
(
x
->
!
a
.
contains
(
x
.
getResource
())).
collect
(
Collectors
.
toList
());
}
return
dataScopes
;
}
/**
* 是否忽略权限控制,默认不忽略
* @param mappedStatementId Mapper方法ID
* @return always false
*/
@Override
public
boolean
ignorePermissionControl
(
String
mappedStatementId
)
{
return
false
;
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/holder/DataPermissionAnnotationHolder.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.holder
;
import
com.pigcloud.pig.common.datascope.annotation.DataPermission
;
import
java.util.ArrayDeque
;
import
java.util.Deque
;
/**
* 数据权限注解的持有者,使用栈存储调用链中各方法对应数据权限注解
*
* @author hccake
*/
public
final
class
DataPermissionAnnotationHolder
{
private
DataPermissionAnnotationHolder
()
{
}
/**
* 使用栈存储 DataPermission,便于在方法嵌套调用时使用不同的数据权限控制。
*/
private
static
final
ThreadLocal
<
Deque
<
DataPermission
>>
DATA_PERMISSIONS
=
ThreadLocal
.
withInitial
(
ArrayDeque:
:
new
);
/**
* 获取当前的 DataPermission 注解
* @return DataPermission
*/
public
static
DataPermission
peek
()
{
return
DATA_PERMISSIONS
.
get
().
peek
();
}
/**
* 入栈一个 DataPermission 注解
* @return DataPermission
*/
public
static
DataPermission
push
(
DataPermission
dataPermission
)
{
DATA_PERMISSIONS
.
get
().
push
(
dataPermission
);
return
dataPermission
;
}
/**
* 弹出最顶部 DataPermission
*/
public
static
void
poll
()
{
Deque
<
DataPermission
>
deque
=
DATA_PERMISSIONS
.
get
();
// 当没有元素时,清空 ThreadLocal
if
(
deque
.
poll
()
==
null
)
{
DATA_PERMISSIONS
.
remove
();
}
}
/**
* 清除 TreadLocal
*/
public
static
void
clear
()
{
DATA_PERMISSIONS
.
remove
();
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/holder/DataScopeHolder.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.holder
;
import
com.pigcloud.pig.common.datascope.DataScope
;
import
java.util.List
;
/**
* DataScope 持有者。 方便解析 SQL 时的参数透传
*
* @author hccake
*/
public
final
class
DataScopeHolder
{
private
DataScopeHolder
()
{
}
private
static
final
ThreadLocal
<
List
<
DataScope
>>
DATA_SCOPES
=
new
ThreadLocal
<>();
/**
* get dataScope
* @return dataScopes
*/
public
static
List
<
DataScope
>
get
()
{
return
DATA_SCOPES
.
get
();
}
/**
* 添加 dataScope
*/
public
static
void
set
(
List
<
DataScope
>
dataScopes
)
{
DATA_SCOPES
.
set
(
dataScopes
);
}
/**
* 删除 dataScope
*/
public
static
void
remove
()
{
DATA_SCOPES
.
remove
();
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/interceptor/DataPermissionAnnotationAdvisor.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.interceptor
;
import
com.pigcloud.pig.common.datascope.annotation.DataPermission
;
import
lombok.EqualsAndHashCode
;
import
lombok.Getter
;
import
org.aopalliance.aop.Advice
;
import
org.springframework.aop.Pointcut
;
import
org.springframework.aop.support.AbstractPointcutAdvisor
;
import
org.springframework.aop.support.ComposablePointcut
;
import
org.springframework.aop.support.annotation.AnnotationMatchingPointcut
;
/**
* @author hccake
*/
@Getter
@EqualsAndHashCode
(
callSuper
=
true
)
public
class
DataPermissionAnnotationAdvisor
extends
AbstractPointcutAdvisor
{
private
final
Advice
advice
;
private
final
Pointcut
pointcut
;
public
DataPermissionAnnotationAdvisor
()
{
this
.
advice
=
new
DataPermissionAnnotationInterceptor
();
this
.
pointcut
=
buildPointcut
();
}
protected
Pointcut
buildPointcut
()
{
Pointcut
cpc
=
new
AnnotationMatchingPointcut
(
DataPermission
.
class
,
true
);
Pointcut
mpc
=
new
AnnotationMatchingPointcut
(
null
,
DataPermission
.
class
,
true
);
return
new
ComposablePointcut
(
cpc
).
union
(
mpc
);
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/interceptor/DataPermissionAnnotationInterceptor.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.interceptor
;
import
com.pigcloud.pig.common.datascope.annotation.DataPermission
;
import
com.pigcloud.pig.common.datascope.holder.DataPermissionAnnotationHolder
;
import
org.aopalliance.intercept.MethodInterceptor
;
import
org.aopalliance.intercept.MethodInvocation
;
import
java.lang.reflect.Method
;
/**
* DataPermission注解的拦截器,在执行方法前将当前方法的对应注解压栈,执行后弹出注解
*
* @author hccake
*/
public
class
DataPermissionAnnotationInterceptor
implements
MethodInterceptor
{
@Override
public
Object
invoke
(
MethodInvocation
methodInvocation
)
throws
Throwable
{
// 当前方法
Method
method
=
methodInvocation
.
getMethod
();
// 获取执行类
Object
invocationThis
=
methodInvocation
.
getThis
();
Class
<?>
clazz
=
invocationThis
!=
null
?
invocationThis
.
getClass
()
:
method
.
getDeclaringClass
();
// 寻找对应的 DataPermission 注解属性
DataPermission
dataPermission
=
DataPermissionFinder
.
findDataPermission
(
method
,
clazz
);
DataPermissionAnnotationHolder
.
push
(
dataPermission
);
try
{
return
methodInvocation
.
proceed
();
}
finally
{
DataPermissionAnnotationHolder
.
poll
();
}
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/interceptor/DataPermissionFinder.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.interceptor
;
import
com.pigcloud.pig.common.datascope.annotation.DataPermission
;
import
org.springframework.core.MethodClassKey
;
import
org.springframework.core.annotation.AnnotatedElementUtils
;
import
java.lang.reflect.Method
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* {@link DataPermission} 注解的查找者。用于查询当前方法对应的 DataPermission 注解环境,当方法上没有找到时,会去类上寻找。
*
* @author hccake
*/
@DataPermission
public
final
class
DataPermissionFinder
{
private
DataPermissionFinder
()
{
}
private
static
final
Map
<
Object
,
DataPermission
>
DATA_PERMISSION_CACHE
=
new
ConcurrentHashMap
<>(
1024
);
/**
* 提供一个默认的空值注解,用于缓存空值占位使用
*/
private
static
final
DataPermission
EMPTY_DATA_PERMISSION
=
DataPermissionFinder
.
class
.
getAnnotation
(
DataPermission
.
class
);
/**
* 缓存的 key 值
* @param method 方法
* @param clazz 类
* @return key
*/
private
static
Object
getCacheKey
(
Method
method
,
Class
<?>
clazz
)
{
return
new
MethodClassKey
(
method
,
clazz
);
}
/**
* 从缓存中获取数据权限注解 优先获取方法上的注解,再获取类上的注解
* @param method 当前方法
* @param clazz 当前类
* @return 当前方法有效的数据权限注解
*/
public
static
DataPermission
findDataPermission
(
Method
method
,
Class
<?>
clazz
)
{
Object
methodKey
=
getCacheKey
(
method
,
clazz
);
if
(
DATA_PERMISSION_CACHE
.
containsKey
(
methodKey
))
{
DataPermission
dataPermission
=
DATA_PERMISSION_CACHE
.
get
(
methodKey
);
// 判断是否和缓存的空注解是同一个对象
return
EMPTY_DATA_PERMISSION
==
dataPermission
?
null
:
dataPermission
;
}
// 先查方法,如果方法上没有,则使用类上
DataPermission
dataPermission
=
AnnotatedElementUtils
.
findMergedAnnotation
(
method
,
DataPermission
.
class
);
if
(
dataPermission
==
null
)
{
dataPermission
=
AnnotatedElementUtils
.
findMergedAnnotation
(
clazz
,
DataPermission
.
class
);
}
DATA_PERMISSION_CACHE
.
put
(
methodKey
,
dataPermission
==
null
?
EMPTY_DATA_PERMISSION
:
dataPermission
);
return
dataPermission
;
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/interceptor/DataPermissionInterceptor.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.interceptor
;
import
com.pigcloud.pig.common.datascope.DataScope
;
import
com.pigcloud.pig.common.datascope.handler.DataPermissionHandler
;
import
com.pigcloud.pig.common.datascope.processor.DataScopeSqlProcessor
;
import
com.pigcloud.pig.common.datascope.util.PluginUtils
;
import
lombok.RequiredArgsConstructor
;
import
org.apache.ibatis.executor.statement.StatementHandler
;
import
org.apache.ibatis.mapping.MappedStatement
;
import
org.apache.ibatis.mapping.SqlCommandType
;
import
org.apache.ibatis.plugin.*
;
import
java.sql.Connection
;
import
java.util.List
;
/**
* 数据权限拦截器
*
* @author Hccake 2020/9/28
* @version 1.0
*/
@RequiredArgsConstructor
@Intercepts
({
@Signature
(
type
=
StatementHandler
.
class
,
method
=
"prepare"
,
args
=
{
Connection
.
class
,
Integer
.
class
})
})
public
class
DataPermissionInterceptor
implements
Interceptor
{
private
final
DataScopeSqlProcessor
dataScopeSqlProcessor
;
private
final
DataPermissionHandler
dataPermissionHandler
;
@Override
public
Object
intercept
(
Invocation
invocation
)
throws
Throwable
{
// 第一版,测试用
Object
target
=
invocation
.
getTarget
();
StatementHandler
sh
=
(
StatementHandler
)
target
;
PluginUtils
.
MPStatementHandler
mpSh
=
PluginUtils
.
mpStatementHandler
(
sh
);
MappedStatement
ms
=
mpSh
.
mappedStatement
();
SqlCommandType
sct
=
ms
.
getSqlCommandType
();
PluginUtils
.
MPBoundSql
mpBs
=
mpSh
.
mPBoundSql
();
String
mappedStatementId
=
ms
.
getId
();
// 根据用户权限判断是否需要拦截,例如管理员可以查看所有,则直接放行
if
(
dataPermissionHandler
.
ignorePermissionControl
(
mappedStatementId
))
{
return
invocation
.
proceed
();
}
List
<
DataScope
>
dataScopes
=
dataPermissionHandler
.
filterDataScopes
(
mappedStatementId
);
if
(
dataScopes
==
null
||
dataScopes
.
isEmpty
())
{
return
invocation
.
proceed
();
}
// 根据 DataScopes 进行数据权限的 sql 处理
if
(
sct
==
SqlCommandType
.
SELECT
)
{
mpBs
.
sql
(
dataScopeSqlProcessor
.
parserSingle
(
mpBs
.
sql
(),
dataScopes
));
}
else
if
(
sct
==
SqlCommandType
.
INSERT
||
sct
==
SqlCommandType
.
UPDATE
||
sct
==
SqlCommandType
.
DELETE
)
{
mpBs
.
sql
(
dataScopeSqlProcessor
.
parserMulti
(
mpBs
.
sql
(),
dataScopes
));
}
// 执行 sql
return
invocation
.
proceed
();
}
@Override
public
Object
plugin
(
Object
target
)
{
if
(
target
instanceof
StatementHandler
)
{
return
Plugin
.
wrap
(
target
,
this
);
}
return
target
;
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/parser/JsqlParserSupport.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.parser
;
import
lombok.extern.slf4j.Slf4j
;
import
net.sf.jsqlparser.JSQLParserException
;
import
net.sf.jsqlparser.parser.CCJSqlParserUtil
;
import
net.sf.jsqlparser.statement.Statement
;
import
net.sf.jsqlparser.statement.Statements
;
import
net.sf.jsqlparser.statement.delete.Delete
;
import
net.sf.jsqlparser.statement.insert.Insert
;
import
net.sf.jsqlparser.statement.select.Select
;
import
net.sf.jsqlparser.statement.update.Update
;
/**
* https://github.com/JSQLParser/JSqlParser
*
* @author miemie hccake
* @since 2020-06-22
*/
@Slf4j
public
abstract
class
JsqlParserSupport
{
public
String
parserSingle
(
String
sql
,
Object
obj
)
{
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"original SQL: "
+
sql
);
}
try
{
Statement
statement
=
CCJSqlParserUtil
.
parse
(
sql
);
return
processParser
(
statement
,
0
,
sql
,
obj
);
}
catch
(
JSQLParserException
e
)
{
throw
new
RuntimeException
(
String
.
format
(
"Failed to process, Error SQL: %s"
,
sql
),
e
);
}
}
public
String
parserMulti
(
String
sql
,
Object
obj
)
{
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"original SQL: "
+
sql
);
}
try
{
// fixed github pull/295
StringBuilder
sb
=
new
StringBuilder
();
Statements
statements
=
CCJSqlParserUtil
.
parseStatements
(
sql
);
int
i
=
0
;
for
(
Statement
statement
:
statements
.
getStatements
())
{
if
(
i
>
0
)
{
sb
.
append
(
";"
);
}
sb
.
append
(
processParser
(
statement
,
i
,
sql
,
obj
));
i
++;
}
return
sb
.
toString
();
}
catch
(
JSQLParserException
e
)
{
throw
new
RuntimeException
(
String
.
format
(
"Failed to process, Error SQL: %s"
,
sql
),
e
);
}
}
/**
* 执行 SQL 解析
* @param statement JsqlParser Statement
* @return sql
*/
protected
String
processParser
(
Statement
statement
,
int
index
,
String
sql
,
Object
obj
)
{
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"SQL to parse, SQL: "
+
sql
);
}
if
(
statement
instanceof
Insert
)
{
this
.
processInsert
((
Insert
)
statement
,
index
,
sql
,
obj
);
}
else
if
(
statement
instanceof
Select
)
{
this
.
processSelect
((
Select
)
statement
,
index
,
sql
,
obj
);
}
else
if
(
statement
instanceof
Update
)
{
this
.
processUpdate
((
Update
)
statement
,
index
,
sql
,
obj
);
}
else
if
(
statement
instanceof
Delete
)
{
this
.
processDelete
((
Delete
)
statement
,
index
,
sql
,
obj
);
}
sql
=
statement
.
toString
();
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"parse the finished SQL: "
+
sql
);
}
return
sql
;
}
/**
* 新增
*/
protected
void
processInsert
(
Insert
insert
,
int
index
,
String
sql
,
Object
obj
)
{
throw
new
UnsupportedOperationException
();
}
/**
* 删除
*/
protected
void
processDelete
(
Delete
delete
,
int
index
,
String
sql
,
Object
obj
)
{
throw
new
UnsupportedOperationException
();
}
/**
* 更新
*/
protected
void
processUpdate
(
Update
update
,
int
index
,
String
sql
,
Object
obj
)
{
throw
new
UnsupportedOperationException
();
}
/**
* 查询
*/
protected
void
processSelect
(
Select
select
,
int
index
,
String
sql
,
Object
obj
)
{
throw
new
UnsupportedOperationException
();
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/processor/DataScopeSqlProcessor.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.processor
;
import
com.pigcloud.pig.common.datascope.DataScope
;
import
com.pigcloud.pig.common.datascope.holder.DataScopeHolder
;
import
com.pigcloud.pig.common.datascope.parser.JsqlParserSupport
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
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.ExistsExpression
;
import
net.sf.jsqlparser.expression.operators.relational.ExpressionList
;
import
net.sf.jsqlparser.expression.operators.relational.InExpression
;
import
net.sf.jsqlparser.expression.operators.relational.ItemsList
;
import
net.sf.jsqlparser.schema.Column
;
import
net.sf.jsqlparser.schema.Table
;
import
net.sf.jsqlparser.statement.delete.Delete
;
import
net.sf.jsqlparser.statement.insert.Insert
;
import
net.sf.jsqlparser.statement.select.*
;
import
net.sf.jsqlparser.statement.update.Update
;
import
java.util.List
;
import
java.util.Objects
;
/**
* 数据权限 sql 处理器 参考 mybatis-plus 租户拦截器,解析 sql where 部分,进行查询表达式注入
*
* @author Hccake 2020/9/26
* @version 1.0
*/
@RequiredArgsConstructor
@Slf4j
public
class
DataScopeSqlProcessor
extends
JsqlParserSupport
{
/**
* select 类型SQL处理
* @param select jsqlparser Statement Select
*/
@Override
protected
void
processSelect
(
Select
select
,
int
index
,
String
sql
,
Object
obj
)
{
List
<
DataScope
>
dataScopes
=
(
List
<
DataScope
>)
obj
;
try
{
// dataScopes 放入 ThreadLocal 方便透传
DataScopeHolder
.
set
(
dataScopes
);
processSelectBody
(
select
.
getSelectBody
());
List
<
WithItem
>
withItemsList
=
select
.
getWithItemsList
();
if
(
withItemsList
!=
null
&&
!
withItemsList
.
isEmpty
())
{
withItemsList
.
forEach
(
this
::
processSelectBody
);
}
}
finally
{
// 必须清空 ThreadLocal
DataScopeHolder
.
remove
();
}
}
protected
void
processSelectBody
(
SelectBody
selectBody
)
{
if
(
selectBody
==
null
)
{
return
;
}
if
(
selectBody
instanceof
PlainSelect
)
{
processPlainSelect
((
PlainSelect
)
selectBody
);
}
else
if
(
selectBody
instanceof
WithItem
)
{
WithItem
withItem
=
(
WithItem
)
selectBody
;
processSelectBody
(
withItem
.
getSubSelect
().
getSelectBody
());
}
else
{
SetOperationList
operationList
=
(
SetOperationList
)
selectBody
;
List
<
SelectBody
>
selectBodys
=
operationList
.
getSelects
();
if
(
selectBodys
!=
null
&&
!
selectBodys
.
isEmpty
())
{
selectBodys
.
forEach
(
this
::
processSelectBody
);
}
}
}
/**
* insert 类型SQL处理
* @param insert jsqlparser Statement Insert
*/
@Override
protected
void
processInsert
(
Insert
insert
,
int
index
,
String
sql
,
Object
obj
)
{
// insert 暂时不处理
}
/**
* update 类型SQL处理
* @param update jsqlparser Statement Update
*/
@Override
protected
void
processUpdate
(
Update
update
,
int
index
,
String
sql
,
Object
obj
)
{
List
<
DataScope
>
dataScopes
=
(
List
<
DataScope
>)
obj
;
try
{
// dataScopes 放入 ThreadLocal 方便透传
DataScopeHolder
.
set
(
dataScopes
);
update
.
setWhere
(
this
.
injectExpression
(
update
.
getWhere
(),
update
.
getTable
()));
}
finally
{
// 必须清空 ThreadLocal
DataScopeHolder
.
remove
();
}
}
/**
* delete 类型SQL处理
* @param delete jsqlparser Statement Delete
*/
@Override
protected
void
processDelete
(
Delete
delete
,
int
index
,
String
sql
,
Object
obj
)
{
List
<
DataScope
>
dataScopes
=
(
List
<
DataScope
>)
obj
;
try
{
// dataScopes 放入 ThreadLocal 方便透传
DataScopeHolder
.
set
(
dataScopes
);
delete
.
setWhere
(
this
.
injectExpression
(
delete
.
getWhere
(),
delete
.
getTable
()));
}
finally
{
// 必须清空 ThreadLocal
DataScopeHolder
.
remove
();
}
}
/**
* 处理 PlainSelect
*/
protected
void
processPlainSelect
(
PlainSelect
plainSelect
)
{
FromItem
fromItem
=
plainSelect
.
getFromItem
();
Expression
where
=
plainSelect
.
getWhere
();
processWhereSubSelect
(
where
);
if
(
fromItem
instanceof
Table
)
{
Table
fromTable
=
(
Table
)
fromItem
;
// #1186 github
plainSelect
.
setWhere
(
injectExpression
(
where
,
fromTable
));
}
else
{
processFromItem
(
fromItem
);
}
// #3087 github
List
<
SelectItem
>
selectItems
=
plainSelect
.
getSelectItems
();
if
(
selectItems
!=
null
&&
!
selectItems
.
isEmpty
())
{
selectItems
.
forEach
(
this
::
processSelectItem
);
}
List
<
Join
>
joins
=
plainSelect
.
getJoins
();
if
(
joins
!=
null
&&
!
joins
.
isEmpty
())
{
joins
.
forEach
(
j
->
{
processJoin
(
j
);
processFromItem
(
j
.
getRightItem
());
});
}
}
/**
* 处理where条件内的子查询
* <p>
* 支持如下: 1. in 2. = 3. > 4. < 5. >= 6. <= 7. <> 8. EXISTS 9. NOT EXISTS
* <p>
* 前提条件: 1. 子查询必须放在小括号中 2. 子查询一般放在比较操作符的右边
* @param where where 条件
*/
protected
void
processWhereSubSelect
(
Expression
where
)
{
if
(
where
==
null
)
{
return
;
}
if
(
where
instanceof
FromItem
)
{
processFromItem
((
FromItem
)
where
);
return
;
}
if
(
where
.
toString
().
indexOf
(
"SELECT"
)
>
0
)
{
// 有子查询
if
(
where
instanceof
BinaryExpression
)
{
// 比较符号 , and , or , 等等
BinaryExpression
expression
=
(
BinaryExpression
)
where
;
processWhereSubSelect
(
expression
.
getLeftExpression
());
processWhereSubSelect
(
expression
.
getRightExpression
());
}
else
if
(
where
instanceof
InExpression
)
{
// in
InExpression
expression
=
(
InExpression
)
where
;
ItemsList
itemsList
=
expression
.
getRightItemsList
();
if
(
itemsList
instanceof
SubSelect
)
{
processSelectBody
(((
SubSelect
)
itemsList
).
getSelectBody
());
}
}
else
if
(
where
instanceof
ExistsExpression
)
{
// exists
ExistsExpression
expression
=
(
ExistsExpression
)
where
;
processWhereSubSelect
(
expression
.
getRightExpression
());
}
else
if
(
where
instanceof
NotExpression
)
{
// not exists
NotExpression
expression
=
(
NotExpression
)
where
;
processWhereSubSelect
(
expression
.
getExpression
());
}
else
if
(
where
instanceof
Parenthesis
)
{
Parenthesis
expression
=
(
Parenthesis
)
where
;
processWhereSubSelect
(
expression
.
getExpression
());
}
}
}
protected
void
processSelectItem
(
SelectItem
selectItem
)
{
if
(
selectItem
instanceof
SelectExpressionItem
)
{
SelectExpressionItem
selectExpressionItem
=
(
SelectExpressionItem
)
selectItem
;
if
(
selectExpressionItem
.
getExpression
()
instanceof
SubSelect
)
{
processSelectBody
(((
SubSelect
)
selectExpressionItem
.
getExpression
()).
getSelectBody
());
}
else
if
(
selectExpressionItem
.
getExpression
()
instanceof
Function
)
{
processFunction
((
Function
)
selectExpressionItem
.
getExpression
());
}
}
}
/**
* 处理函数
* <p>
* 支持: 1. select fun(args..) 2. select fun1(fun2(args..),args..)
* <p>
* <p>
* fixed gitee pulls/141
* </p>
* @param function
*/
protected
void
processFunction
(
Function
function
)
{
ExpressionList
parameters
=
function
.
getParameters
();
if
(
parameters
!=
null
)
{
parameters
.
getExpressions
().
forEach
(
expression
->
{
if
(
expression
instanceof
SubSelect
)
{
processSelectBody
(((
SubSelect
)
expression
).
getSelectBody
());
}
else
if
(
expression
instanceof
Function
)
{
processFunction
((
Function
)
expression
);
}
});
}
}
/**
* 处理子查询等
*/
protected
void
processFromItem
(
FromItem
fromItem
)
{
if
(
fromItem
instanceof
SubJoin
)
{
SubJoin
subJoin
=
(
SubJoin
)
fromItem
;
if
(
subJoin
.
getJoinList
()
!=
null
)
{
subJoin
.
getJoinList
().
forEach
(
this
::
processJoin
);
}
if
(
subJoin
.
getLeft
()
!=
null
)
{
processFromItem
(
subJoin
.
getLeft
());
}
}
else
if
(
fromItem
instanceof
SubSelect
)
{
SubSelect
subSelect
=
(
SubSelect
)
fromItem
;
if
(
subSelect
.
getSelectBody
()
!=
null
)
{
processSelectBody
(
subSelect
.
getSelectBody
());
}
}
else
if
(
fromItem
instanceof
ValuesList
)
{
log
.
debug
(
"Perform a subquery, if you do not give us feedback"
);
}
else
if
(
fromItem
instanceof
LateralSubSelect
)
{
LateralSubSelect
lateralSubSelect
=
(
LateralSubSelect
)
fromItem
;
if
(
lateralSubSelect
.
getSubSelect
()
!=
null
)
{
SubSelect
subSelect
=
lateralSubSelect
.
getSubSelect
();
if
(
subSelect
.
getSelectBody
()
!=
null
)
{
processSelectBody
(
subSelect
.
getSelectBody
());
}
}
}
}
/**
* 处理联接语句
*/
protected
void
processJoin
(
Join
join
)
{
if
(
join
.
getRightItem
()
instanceof
Table
)
{
Table
fromTable
=
(
Table
)
join
.
getRightItem
();
join
.
setOnExpression
(
injectExpression
(
join
.
getOnExpression
(),
fromTable
));
}
}
/**
* 根据 DataScope ,将数据过滤的表达式注入原本的 where/or 条件
* @param currentExpression Expression where/or
* @param table 表信息
* @return 修改后的 where/or 条件
*/
private
Expression
injectExpression
(
Expression
currentExpression
,
Table
table
)
{
String
tableName
=
table
.
getName
();
List
<
DataScope
>
dataScopes
=
DataScopeHolder
.
get
();
Expression
dataFilterExpression
=
dataScopes
.
stream
().
filter
(
x
->
x
.
getTableNames
().
contains
(
tableName
))
.
map
(
x
->
x
.
getExpression
(
tableName
,
table
.
getAlias
())).
filter
(
Objects:
:
nonNull
)
.
reduce
(
AndExpression:
:
new
).
orElse
(
null
);
if
(
currentExpression
==
null
)
{
return
dataFilterExpression
;
}
if
(
dataFilterExpression
==
null
)
{
return
currentExpression
;
}
if
(
currentExpression
instanceof
OrExpression
)
{
return
new
AndExpression
(
new
Parenthesis
(
currentExpression
),
dataFilterExpression
);
}
else
{
return
new
AndExpression
(
currentExpression
,
dataFilterExpression
);
}
}
/**
* 根据当前表是否有别名,动态对字段名前添加表别名 eg. 表名: table_1 as t 原始字段:column1 返回: t.column1
* @param table 表信息
* @param column 字段名
* @return 原始字段名,或者添加了表别名的字段名
*/
protected
Column
getAliasColumn
(
Table
table
,
String
column
)
{
StringBuilder
columnBuilder
=
new
StringBuilder
();
if
(
table
.
getAlias
()
!=
null
)
{
columnBuilder
.
append
(
table
.
getAlias
().
getName
()).
append
(
"."
);
}
columnBuilder
.
append
(
column
);
return
new
Column
(
columnBuilder
.
toString
());
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/util/AnnotationUtil.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.util
;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.Method
;
/**
* @author Hccake 2021/1/27
* @version 1.0
*/
public
final
class
AnnotationUtil
{
private
AnnotationUtil
()
{
}
/**
* 获取数据权限注解 优先获取方法上的注解,再获取类上的注解
* @param mappedStatementId 类名.方法名
* @return 数据权限注解
*/
public
static
<
A
extends
Annotation
>
A
findAnnotationByMappedStatementId
(
String
mappedStatementId
,
Class
<
A
>
aClass
)
{
if
(
mappedStatementId
==
null
||
""
.
equals
(
mappedStatementId
))
{
return
null
;
}
// 1.得到类路径和方法路径
int
lastIndexOfDot
=
mappedStatementId
.
lastIndexOf
(
"."
);
if
(
lastIndexOfDot
<
0
)
{
return
null
;
}
String
className
=
mappedStatementId
.
substring
(
0
,
lastIndexOfDot
);
String
methodName
=
mappedStatementId
.
substring
(
lastIndexOfDot
+
1
);
if
(
""
.
equals
(
className
)
||
""
.
equals
(
methodName
))
{
return
null
;
}
// 2.字节码
Class
<?>
clazz
=
null
;
try
{
clazz
=
Class
.
forName
(
className
);
}
catch
(
ClassNotFoundException
e
)
{
e
.
printStackTrace
();
}
if
(
clazz
==
null
)
{
return
null
;
}
A
annotation
=
null
;
// 3.得到方法上的注解
Method
[]
methods
=
clazz
.
getMethods
();
for
(
Method
method
:
methods
)
{
String
name
=
method
.
getName
();
if
(
methodName
.
equals
(
name
))
{
annotation
=
method
.
getAnnotation
(
aClass
);
break
;
}
}
if
(
annotation
==
null
)
{
annotation
=
clazz
.
getAnnotation
(
aClass
);
}
return
annotation
;
}
}
pig-common/pig-common-datascope/src/main/java/com/pigcloud/pig/common/datascope/util/PluginUtils.java
0 → 100644
浏览文件 @
3f3def6f
/*
* Copyright (c) 2011-2020, baomidou (jobob@qq.com).
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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
com.pigcloud.pig.common.datascope.util
;
import
org.apache.ibatis.executor.Executor
;
import
org.apache.ibatis.executor.parameter.ParameterHandler
;
import
org.apache.ibatis.executor.statement.StatementHandler
;
import
org.apache.ibatis.mapping.BoundSql
;
import
org.apache.ibatis.mapping.MappedStatement
;
import
org.apache.ibatis.mapping.ParameterMapping
;
import
org.apache.ibatis.reflection.MetaObject
;
import
org.apache.ibatis.reflection.SystemMetaObject
;
import
org.apache.ibatis.session.Configuration
;
import
java.lang.reflect.Proxy
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
/**
* 插件工具类
*
* @author TaoYu , hubin
* @since 2017-06-20
*/
public
abstract
class
PluginUtils
{
public
static
final
String
DELEGATE_BOUNDSQL_SQL
=
"delegate.boundSql.sql"
;
/**
* 获得真正的处理对象,可能多层代理.
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
T
>
T
realTarget
(
Object
target
)
{
if
(
Proxy
.
isProxyClass
(
target
.
getClass
()))
{
MetaObject
metaObject
=
SystemMetaObject
.
forObject
(
target
);
return
realTarget
(
metaObject
.
getValue
(
"h.target"
));
}
return
(
T
)
target
;
}
/**
* 给 BoundSql 设置 additionalParameters
* @param boundSql BoundSql
* @param additionalParameters additionalParameters
*/
public
static
void
setAdditionalParameter
(
BoundSql
boundSql
,
Map
<
String
,
Object
>
additionalParameters
)
{
additionalParameters
.
forEach
(
boundSql:
:
setAdditionalParameter
);
}
public
static
MPBoundSql
mpBoundSql
(
BoundSql
boundSql
)
{
return
new
MPBoundSql
(
boundSql
);
}
public
static
MPStatementHandler
mpStatementHandler
(
StatementHandler
statementHandler
)
{
statementHandler
=
realTarget
(
statementHandler
);
MetaObject
object
=
SystemMetaObject
.
forObject
(
statementHandler
);
return
new
MPStatementHandler
(
SystemMetaObject
.
forObject
(
object
.
getValue
(
"delegate"
)));
}
/**
* {@link org.apache.ibatis.executor.statement.BaseStatementHandler}
*/
public
static
class
MPStatementHandler
{
private
final
MetaObject
statementHandler
;
MPStatementHandler
(
MetaObject
statementHandler
)
{
this
.
statementHandler
=
statementHandler
;
}
public
ParameterHandler
parameterHandler
()
{
return
get
(
"parameterHandler"
);
}
public
MappedStatement
mappedStatement
()
{
return
get
(
"mappedStatement"
);
}
public
Executor
executor
()
{
return
get
(
"executor"
);
}
public
MPBoundSql
mPBoundSql
()
{
return
new
MPBoundSql
(
boundSql
());
}
public
BoundSql
boundSql
()
{
return
get
(
"boundSql"
);
}
public
Configuration
configuration
()
{
return
get
(
"configuration"
);
}
@SuppressWarnings
(
"unchecked"
)
private
<
T
>
T
get
(
String
property
)
{
return
(
T
)
statementHandler
.
getValue
(
property
);
}
}
/**
* {@link BoundSql}
*/
public
static
class
MPBoundSql
{
private
final
MetaObject
boundSql
;
private
final
BoundSql
delegate
;
MPBoundSql
(
BoundSql
boundSql
)
{
this
.
delegate
=
boundSql
;
this
.
boundSql
=
SystemMetaObject
.
forObject
(
boundSql
);
}
public
String
sql
()
{
return
delegate
.
getSql
();
}
public
void
sql
(
String
sql
)
{
boundSql
.
setValue
(
"sql"
,
sql
);
}
public
List
<
ParameterMapping
>
parameterMappings
()
{
List
<
ParameterMapping
>
parameterMappings
=
delegate
.
getParameterMappings
();
return
new
ArrayList
<>(
parameterMappings
);
}
public
void
parameterMappings
(
List
<
ParameterMapping
>
parameterMappings
)
{
boundSql
.
setValue
(
"parameterMappings"
,
Collections
.
unmodifiableList
(
parameterMappings
));
}
public
Object
parameterObject
()
{
return
get
(
"parameterObject"
);
}
public
Map
<
String
,
Object
>
additionalParameters
()
{
return
get
(
"additionalParameters"
);
}
@SuppressWarnings
(
"unchecked"
)
private
<
T
>
T
get
(
String
property
)
{
return
(
T
)
boundSql
.
getValue
(
property
);
}
}
}
pig-common/pig-common-datascope/src/main/resources/META-INF/spring.factories
0 → 100644
浏览文件 @
3f3def6f
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pigcloud.pig.common.datascope.DataScopeAutoConfiguration
pig-common/pig-common-datascope/src/test/java/com/pigcloud/pig/common/datascope/test/SqlParseTest.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pigcloud.pig.common.datascope.test
;
import
com.pigcloud.pig.common.datascope.DataScope
;
import
com.pigcloud.pig.common.datascope.handler.DefaultDataPermissionHandler
;
import
com.pigcloud.pig.common.datascope.handler.DataPermissionHandler
;
import
com.pigcloud.pig.common.datascope.processor.DataScopeSqlProcessor
;
import
net.sf.jsqlparser.expression.Alias
;
import
net.sf.jsqlparser.expression.Expression
;
import
net.sf.jsqlparser.expression.StringValue
;
import
net.sf.jsqlparser.expression.operators.relational.ExpressionList
;
import
net.sf.jsqlparser.expression.operators.relational.InExpression
;
import
net.sf.jsqlparser.schema.Column
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.util.Assert
;
import
java.util.*
;
/**
* @author Hccake 2020/9/28
* @version 1.0
*/
class
SqlParseTest
{
@Test
void
test
()
{
DataScope
dataScope
=
new
DataScope
()
{
final
String
columnId
=
"order_id"
;
@Override
public
String
getResource
()
{
return
"order"
;
}
@Override
public
Collection
<
String
>
getTableNames
()
{
Set
<
String
>
tableNames
=
new
TreeSet
<>(
String
.
CASE_INSENSITIVE_ORDER
);
tableNames
.
addAll
(
Arrays
.
asList
(
"t_order"
,
"t_order_info"
));
return
tableNames
;
}
@Override
public
Expression
getExpression
(
String
tableName
,
Alias
tableAlias
)
{
Column
column
=
new
Column
(
tableAlias
==
null
?
columnId
:
tableAlias
.
getName
()
+
"."
+
columnId
);
ExpressionList
expressionList
=
new
ExpressionList
();
expressionList
.
setExpressions
(
Arrays
.
asList
(
new
StringValue
(
"1"
),
new
StringValue
(
"2"
)));
return
new
InExpression
(
column
,
expressionList
);
}
};
List
<
DataScope
>
dataScopes
=
new
ArrayList
<>();
dataScopes
.
add
(
dataScope
);
DataPermissionHandler
dataPermissionHandler
=
new
DefaultDataPermissionHandler
(
dataScopes
)
{
@Override
public
boolean
ignorePermissionControl
(
String
mappedStatementId
)
{
return
false
;
}
};
DataScopeSqlProcessor
dataScopeSqlProcessor
=
new
DataScopeSqlProcessor
();
// DataScopeHolder.putDataScope("order", dataScope);
String
sql
=
"select o.order_id,o.order_name,oi.order_price "
+
"from t_ORDER o left join t_order_info oi on o.order_id = oi.order_id "
+
"where oi.order_price > 100"
;
String
parseSql
=
dataScopeSqlProcessor
.
parserSingle
(
sql
,
dataPermissionHandler
.
dataScopes
());
System
.
out
.
println
(
parseSql
);
String
trueSql
=
"SELECT o.order_id, o.order_name, oi.order_price FROM t_ORDER o LEFT JOIN t_order_info oi ON o.order_id = oi.order_id AND oi.order_id IN ('1', '2') WHERE oi.order_price > 100 AND o.order_id IN ('1', '2')"
;
Assert
.
isTrue
(
trueSql
.
equals
(
parseSql
),
"sql 数据权限解析异常"
);
}
}
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigUserAuthenticationConverter.java
浏览文件 @
3f3def6f
...
...
@@ -17,6 +17,7 @@
package
com.pig4cloud.pig.common.security.component
;
import
com.pig4cloud.pig.common.core.constant.SecurityConstants
;
import
com.pig4cloud.pig.common.security.datascope.UserDataScope
;
import
com.pig4cloud.pig.common.security.service.PigUser
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
...
...
@@ -26,8 +27,11 @@ import org.springframework.security.oauth2.provider.token.UserAuthenticationConv
import
org.springframework.util.StringUtils
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
/**
* @author lengleng
...
...
@@ -69,7 +73,17 @@ public class PigUserAuthenticationConverter implements UserAuthenticationConvert
String
username
=
(
String
)
map
.
get
(
SecurityConstants
.
DETAILS_USERNAME
);
Integer
id
=
(
Integer
)
map
.
get
(
SecurityConstants
.
DETAILS_USER_ID
);
Integer
deptId
=
(
Integer
)
map
.
get
(
SecurityConstants
.
DETAILS_DEPT_ID
);
PigUser
user
=
new
PigUser
(
id
,
deptId
,
username
,
N_A
,
true
,
true
,
true
,
true
,
authorities
);
UserDataScope
userDataScope
=
new
UserDataScope
();
Object
value
=
map
.
get
(
SecurityConstants
.
DETAILS_USER_DATA_SCOPE
);
if
(
value
!=
null
)
{
Map
<
String
,
?>
userDataScopeMap
=
(
Map
)
value
;
userDataScope
.
setAllScope
((
boolean
)
userDataScopeMap
.
get
(
"allScope"
));
userDataScope
.
setOnlySelf
((
boolean
)
userDataScopeMap
.
get
(
"onlySelf"
));
userDataScope
.
setScopeUserIds
(
new
HashSet
<>((
List
)
userDataScopeMap
.
get
(
"scopeUserIds"
)));
userDataScope
.
setScopeDeptIds
(
new
HashSet
<>((
List
)
userDataScopeMap
.
get
(
"scopeDeptIds"
)));
}
PigUser
user
=
new
PigUser
(
id
,
deptId
,
username
,
N_A
,
true
,
true
,
true
,
true
,
authorities
,
userDataScope
);
return
new
UsernamePasswordAuthenticationToken
(
user
,
N_A
,
authorities
);
}
return
null
;
...
...
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/datascope/DataScopeProcessor.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pig4cloud.pig.common.security.datascope
;
import
com.pig4cloud.pig.admin.api.entity.SysRole
;
import
com.pig4cloud.pig.admin.api.entity.SysUser
;
import
java.util.List
;
/**
* @author hccake
*/
public
interface
DataScopeProcessor
{
/**
* 根据用户和角色信息,合并用户最终的数据权限
* @param user 用户
* @param roles 角色列表
* @return UserDataScope
*/
UserDataScope
mergeScopeType
(
SysUser
user
,
List
<
SysRole
>
roles
);
}
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/datascope/PigDataScopeProcessor.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pig4cloud.pig.common.security.datascope
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.pig4cloud.pig.admin.api.entity.SysRole
;
import
com.pig4cloud.pig.admin.api.entity.SysUser
;
import
com.pig4cloud.pig.admin.api.feign.RemoteDeptService
;
import
com.pig4cloud.pig.admin.api.feign.RemoteUserService
;
import
com.pig4cloud.pig.common.core.constant.SecurityConstants
;
import
com.pig4cloud.pig.common.core.constant.enums.DataScopeTypeEnum
;
import
com.pig4cloud.pig.common.core.util.R
;
import
lombok.RequiredArgsConstructor
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* @author hccake
*/
@RequiredArgsConstructor
public
class
PigDataScopeProcessor
implements
DataScopeProcessor
{
private
final
RemoteDeptService
remoteDeptService
;
private
final
RemoteUserService
remoteUserService
;
/**
* 合并角色的数据权限类型,排除相同的权限后,大的权限覆盖小的
* @param user 用户
* @param roles 角色列表
* @return List<Integer> 合并后的权限
*/
@Override
public
UserDataScope
mergeScopeType
(
SysUser
user
,
List
<
SysRole
>
roles
)
{
UserDataScope
userDataScope
=
new
UserDataScope
();
Set
<
Integer
>
scopeUserIds
=
userDataScope
.
getScopeUserIds
();
Set
<
Integer
>
scopeDeptIds
=
userDataScope
.
getScopeDeptIds
();
// 任何用户都应该可以看到自己的数据
Integer
userId
=
user
.
getUserId
();
scopeUserIds
.
add
(
userId
);
if
(
CollectionUtil
.
isEmpty
(
roles
))
{
return
userDataScope
;
}
// 根据角色的权限返回进行分组
Map
<
Integer
,
List
<
SysRole
>>
map
=
roles
.
stream
().
collect
(
Collectors
.
groupingBy
(
SysRole:
:
getScopeType
));
// 如果有全部权限,直接返回
if
(
map
.
containsKey
(
DataScopeTypeEnum
.
ALL
.
getType
()))
{
userDataScope
.
setAllScope
(
true
);
return
userDataScope
;
}
// 如果有本级及子级,删除其包含的几类数据权限
boolean
hasLevelChildLevel
=
map
.
containsKey
(
DataScopeTypeEnum
.
LEVEL_CHILD_LEVEL
.
getType
());
if
(
hasLevelChildLevel
)
{
map
.
remove
(
DataScopeTypeEnum
.
SELF
.
getType
());
map
.
remove
(
DataScopeTypeEnum
.
SELF_CHILD_LEVEL
.
getType
());
map
.
remove
(
DataScopeTypeEnum
.
LEVEL
.
getType
());
}
// 是否有本人及子级权限
boolean
hasSelfChildLevel
=
map
.
containsKey
(
DataScopeTypeEnum
.
SELF_CHILD_LEVEL
.
getType
());
// 是否有本级权限
boolean
hasLevel
=
map
.
containsKey
(
DataScopeTypeEnum
.
LEVEL
.
getType
());
if
(
hasSelfChildLevel
||
hasLevel
)
{
// 如果有本人及子级或者本级,都删除本人的数据权限
map
.
remove
(
DataScopeTypeEnum
.
SELF
.
getType
());
// 如果同时拥有,则等于本级及子级权限
if
(
hasSelfChildLevel
&&
hasLevel
)
{
map
.
remove
(
DataScopeTypeEnum
.
SELF_CHILD_LEVEL
.
getType
());
map
.
remove
(
DataScopeTypeEnum
.
LEVEL
.
getType
());
map
.
put
(
DataScopeTypeEnum
.
LEVEL_CHILD_LEVEL
.
getType
(),
new
ArrayList
<>());
}
}
// 这时如果仅仅只能看个人的,直接返回
if
(
map
.
size
()
==
1
&&
map
.
containsKey
(
DataScopeTypeEnum
.
SELF
.
getType
()))
{
userDataScope
.
setOnlySelf
(
true
);
return
userDataScope
;
}
// 如果有 本级及子级 或者 本级,都把自己的 deptId 加进去
Integer
deptId
=
user
.
getDeptId
();
if
(
hasLevelChildLevel
||
hasLevel
)
{
scopeDeptIds
.
add
(
deptId
);
}
// 如果有 本级及子级 或者 本人及子级,都把下级组织的 deptId 加进去
if
(
hasLevelChildLevel
||
hasSelfChildLevel
)
{
List
<
Integer
>
childDeptIdList
=
remoteDeptService
.
listChildDeptId
(
deptId
,
SecurityConstants
.
FROM_IN
)
.
getData
();
if
(
CollectionUtil
.
isNotEmpty
(
childDeptIdList
))
{
scopeDeptIds
.
addAll
(
childDeptIdList
);
}
}
// 自定义部门
List
<
SysRole
>
sysRoles
=
map
.
get
(
DataScopeTypeEnum
.
CUSTOM
.
getType
());
if
(
CollectionUtil
.
isNotEmpty
(
sysRoles
))
{
Set
<
Integer
>
customDeptIds
=
sysRoles
.
stream
().
map
(
SysRole:
:
getScopeResources
).
filter
(
Objects:
:
nonNull
)
.
flatMap
(
x
->
Arrays
.
stream
(
x
.
split
(
StrUtil
.
COMMA
))).
map
(
Integer:
:
parseInt
)
.
collect
(
Collectors
.
toSet
());
scopeDeptIds
.
addAll
(
customDeptIds
);
}
// 把部门对应的用户id都放入集合中
if
(
CollectionUtil
.
isNotEmpty
(
scopeDeptIds
))
{
R
<
List
<
Integer
>>
r
=
remoteUserService
.
listUserIdByDeptIds
(
scopeDeptIds
,
SecurityConstants
.
FROM_IN
);
List
<
Integer
>
userIds
=
r
.
getData
();
if
(
CollectionUtil
.
isNotEmpty
(
userIds
))
{
scopeUserIds
.
addAll
(
userIds
);
}
}
return
userDataScope
;
}
}
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/datascope/UserDataScope.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pig4cloud.pig.common.security.datascope
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.util.HashSet
;
import
java.util.Set
;
/**
* @author hccake
*/
@Data
public
class
UserDataScope
implements
Serializable
{
/**
* 是否是全部数据权限
*/
private
boolean
allScope
=
false
;
/**
* 是否仅能看自己
*/
private
boolean
onlySelf
=
false
;
/**
* 数据权限范围,用户所能查看的用户id 集合
*/
private
Set
<
Integer
>
scopeUserIds
=
new
HashSet
<>();
/**
* 数据权限范围,用户所能查看的部门id 集合
*/
private
Set
<
Integer
>
scopeDeptIds
=
new
HashSet
<>();
}
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigUser.java
浏览文件 @
3f3def6f
...
...
@@ -16,6 +16,7 @@
package
com.pig4cloud.pig.common.security.service
;
import
com.pig4cloud.pig.common.security.datascope.UserDataScope
;
import
lombok.Getter
;
import
org.springframework.security.authentication.dao.DaoAuthenticationProvider
;
import
org.springframework.security.core.GrantedAuthority
;
...
...
@@ -33,13 +34,19 @@ public class PigUser extends User {
* 用户ID
*/
@Getter
private
Integer
id
;
private
final
Integer
id
;
/**
* 部门ID
*/
@Getter
private
Integer
deptId
;
private
final
Integer
deptId
;
/**
* 用户数据权限信息
*/
@Getter
private
final
UserDataScope
userDataScope
;
/**
* Construct the <code>User</code> with the details required by
...
...
@@ -62,10 +69,11 @@ public class PigUser extends User {
*/
public
PigUser
(
Integer
id
,
Integer
deptId
,
String
username
,
String
password
,
boolean
enabled
,
boolean
accountNonExpired
,
boolean
credentialsNonExpired
,
boolean
accountNonLocked
,
Collection
<?
extends
GrantedAuthority
>
authorities
)
{
Collection
<?
extends
GrantedAuthority
>
authorities
,
UserDataScope
userDataScope
)
{
super
(
username
,
password
,
enabled
,
accountNonExpired
,
credentialsNonExpired
,
accountNonLocked
,
authorities
);
this
.
id
=
id
;
this
.
deptId
=
deptId
;
this
.
userDataScope
=
userDataScope
;
}
}
pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigUserDetailsServiceImpl.java
浏览文件 @
3f3def6f
...
...
@@ -25,6 +25,8 @@ import com.pig4cloud.pig.common.core.constant.CacheConstants;
import
com.pig4cloud.pig.common.core.constant.CommonConstants
;
import
com.pig4cloud.pig.common.core.constant.SecurityConstants
;
import
com.pig4cloud.pig.common.core.util.R
;
import
com.pig4cloud.pig.common.security.datascope.DataScopeProcessor
;
import
com.pig4cloud.pig.common.security.datascope.UserDataScope
;
import
lombok.RequiredArgsConstructor
;
import
lombok.SneakyThrows
;
import
lombok.extern.slf4j.Slf4j
;
...
...
@@ -45,7 +47,7 @@ import java.util.Set;
/**
* 用户详细信息
*
* @author lengleng
* @author lengleng
hccake
*/
@Slf4j
@Service
...
...
@@ -56,6 +58,8 @@ public class PigUserDetailsServiceImpl implements UserDetailsService {
private
final
CacheManager
cacheManager
;
private
final
DataScopeProcessor
dataScopeProcessor
;
/**
* 用户密码登录
* @param username 用户名
...
...
@@ -80,7 +84,7 @@ public class PigUserDetailsServiceImpl implements UserDetailsService {
/**
* 构建userdetails
* @param result 用户信息
* @return
* @return
UserDetails
*/
private
UserDetails
getUserDetails
(
R
<
UserInfo
>
result
)
{
if
(
result
==
null
||
result
.
getData
()
==
null
)
{
...
...
@@ -100,10 +104,14 @@ public class PigUserDetailsServiceImpl implements UserDetailsService {
.
createAuthorityList
(
dbAuthsSet
.
toArray
(
new
String
[
0
]));
SysUser
user
=
info
.
getSysUser
();
// 数据权限填充
UserDataScope
userDataScope
=
dataScopeProcessor
.
mergeScopeType
(
user
,
info
.
getRoleList
());
// 构造security用户
return
new
PigUser
(
user
.
getUserId
(),
user
.
getDeptId
(),
user
.
getUsername
(),
SecurityConstants
.
BCRYPT
+
user
.
getPassword
(),
StrUtil
.
equals
(
user
.
getLockFlag
(),
CommonConstants
.
STATUS_NORMAL
),
true
,
true
,
true
,
authorities
);
StrUtil
.
equals
(
user
.
getLockFlag
(),
CommonConstants
.
STATUS_NORMAL
),
true
,
true
,
true
,
authorities
,
userDataScope
);
}
}
pig-common/pig-common-security/src/main/resources/META-INF/spring.factories
浏览文件 @
3f3def6f
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pig4cloud.pig.common.security.service.PigUserDetailsServiceImpl,\
com.pig4cloud.pig.common.security.component.PigSecurityInnerAspect
com.pig4cloud.pig.common.security.component.PigSecurityInnerAspect,\
com.pig4cloud.pig.common.security.datascope.PigDataScopeProcessor
pig-common/pom.xml
浏览文件 @
3f3def6f
...
...
@@ -40,5 +40,6 @@
<module>
pig-common-feign
</module>
<module>
pig-common-swagger
</module>
<module>
pig-common-test
</module>
</modules>
<module>
pig-common-datascope
</module>
</modules>
</project>
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/dto/UserInfo.java
浏览文件 @
3f3def6f
...
...
@@ -16,10 +16,14 @@
package
com.pig4cloud.pig.admin.api.dto
;
import
com.pig4cloud.pig.admin.api.entity.SysMenu
;
import
com.pig4cloud.pig.admin.api.entity.SysRole
;
import
com.pig4cloud.pig.admin.api.entity.SysUser
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.util.List
;
import
java.util.Set
;
/**
* @author lengleng
...
...
@@ -46,4 +50,9 @@ public class UserInfo implements Serializable {
*/
private
Integer
[]
roles
;
/**
* 角色集合
*/
private
List
<
SysRole
>
roleList
;
}
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/entity/SysRole.java
浏览文件 @
3f3def6f
...
...
@@ -25,6 +25,7 @@ import lombok.Data;
import
lombok.EqualsAndHashCode
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.NotNull
;
/**
* <p>
...
...
@@ -56,6 +57,13 @@ public class SysRole extends BaseEntity {
@ApiModelProperty
(
value
=
"角色描述"
)
private
String
roleDesc
;
@NotNull
(
message
=
"数据范围类型 不能为null"
)
@ApiModelProperty
(
value
=
"数据范围类型"
)
private
Integer
scopeType
;
@ApiModelProperty
(
value
=
"数据范围资源"
)
private
String
scopeResources
;
/**
* 删除标识(0-正常,1-删除)
*/
...
...
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/RemoteDeptService.java
0 → 100644
浏览文件 @
3f3def6f
/*
* Copyright (c) 2020 pig4cloud 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
com.pig4cloud.pig.admin.api.feign
;
import
com.pig4cloud.pig.admin.api.feign.factory.RemoteDeptServiceFallbackFactory
;
import
com.pig4cloud.pig.common.core.constant.SecurityConstants
;
import
com.pig4cloud.pig.common.core.constant.ServiceNameConstants
;
import
com.pig4cloud.pig.common.core.util.R
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestHeader
;
import
java.util.List
;
/**
* @author hccake
*/
@FeignClient
(
contextId
=
"remoteDeptService"
,
value
=
ServiceNameConstants
.
UMPS_SERVICE
,
fallbackFactory
=
RemoteDeptServiceFallbackFactory
.
class
)
public
interface
RemoteDeptService
{
/**
* 查收子级id列表
* @return 返回子级id列表
*/
@GetMapping
(
"/dept/child-id/{deptId}"
)
R
<
List
<
Integer
>>
listChildDeptId
(
@PathVariable
(
"deptId"
)
Integer
deptId
,
@RequestHeader
(
SecurityConstants
.
FROM
)
String
from
);
}
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/RemoteUserService.java
浏览文件 @
3f3def6f
...
...
@@ -25,6 +25,10 @@ import org.springframework.cloud.openfeign.FeignClient;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestHeader
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
java.util.List
;
import
java.util.Set
;
/**
* @author lengleng
...
...
@@ -51,4 +55,14 @@ public interface RemoteUserService {
@GetMapping
(
"/social/info/{inStr}"
)
R
<
UserInfo
>
social
(
@PathVariable
(
"inStr"
)
String
inStr
);
/**
* 根据部门id,查询对应的用户 id 集合
* @param deptIds 部门id 集合
* @param from 调用标志
* @return 用户 id 集合
*/
@GetMapping
(
"/user/ids"
)
R
<
List
<
Integer
>>
listUserIdByDeptIds
(
@RequestParam
(
"deptIds"
)
Set
<
Integer
>
deptIds
,
@RequestHeader
(
SecurityConstants
.
FROM
)
String
from
);
}
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/factory/RemoteDeptServiceFallbackFactory.java
0 → 100644
浏览文件 @
3f3def6f
/*
* Copyright (c) 2020 pig4cloud 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
com.pig4cloud.pig.admin.api.feign.factory
;
import
com.pig4cloud.pig.admin.api.feign.RemoteDeptService
;
import
com.pig4cloud.pig.admin.api.feign.fallback.RemoteDeptServiceFallbackImpl
;
import
org.springframework.cloud.openfeign.FallbackFactory
;
import
org.springframework.stereotype.Component
;
/**
* @author hccake
*/
@Component
public
class
RemoteDeptServiceFallbackFactory
implements
FallbackFactory
<
RemoteDeptService
>
{
@Override
public
RemoteDeptService
create
(
Throwable
throwable
)
{
RemoteDeptServiceFallbackImpl
remoteDeptServiceFallback
=
new
RemoteDeptServiceFallbackImpl
();
remoteDeptServiceFallback
.
setCause
(
throwable
);
return
remoteDeptServiceFallback
;
}
}
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/fallback/RemoteDeptServiceFallbackImpl.java
0 → 100644
浏览文件 @
3f3def6f
/*
* Copyright (c) 2020 pig4cloud 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
com.pig4cloud.pig.admin.api.feign.fallback
;
import
com.pig4cloud.pig.admin.api.dto.UserInfo
;
import
com.pig4cloud.pig.admin.api.feign.RemoteDeptService
;
import
com.pig4cloud.pig.admin.api.feign.RemoteUserService
;
import
com.pig4cloud.pig.common.core.util.R
;
import
lombok.Setter
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
java.util.List
;
/**
* @author hccake
*/
@Slf4j
@Component
public
class
RemoteDeptServiceFallbackImpl
implements
RemoteDeptService
{
@Setter
private
Throwable
cause
;
@Override
public
R
<
List
<
Integer
>>
listChildDeptId
(
Integer
deptId
,
String
from
)
{
log
.
error
(
"[listChildDeptId] feign 查询子级部门id列表失败"
,
cause
);
return
null
;
}
}
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java
浏览文件 @
3f3def6f
...
...
@@ -23,6 +23,9 @@ import lombok.Setter;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
java.util.List
;
import
java.util.Set
;
/**
* @author lengleng
* @date 2019/2/1
...
...
@@ -57,4 +60,10 @@ public class RemoteUserServiceFallbackImpl implements RemoteUserService {
return
null
;
}
@Override
public
R
<
List
<
Integer
>>
listUserIdByDeptIds
(
Set
<
Integer
>
deptIds
,
String
from
)
{
log
.
error
(
"feign 根据部门ids查询用户Id集合失败:{}"
,
deptIds
,
cause
);
return
null
;
}
}
pig-upms/pig-upms-api/src/main/java/com/pig4cloud/pig/admin/api/vo/UserInfoVO.java
0 → 100644
浏览文件 @
3f3def6f
/*
* Copyright (c) 2020 pig4cloud 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
com.pig4cloud.pig.admin.api.vo
;
import
com.pig4cloud.pig.admin.api.entity.SysUser
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* @author lengleng
* @date 2019/2/1
* <p>
* commit('SET_ROLES', data) commit('SET_NAME', data) commit('SET_AVATAR', data)
* commit('SET_INTRODUCTION', data) commit('SET_PERMISSIONS', data)
*/
@Data
public
class
UserInfoVO
implements
Serializable
{
/**
* 用户基本信息
*/
private
SysUser
sysUser
;
/**
* 权限标识集合
*/
private
String
[]
permissions
;
/**
* 角色集合
*/
private
Integer
[]
roles
;
}
pig-upms/pig-upms-api/src/main/resources/META-INF/spring.factories
浏览文件 @
3f3def6f
...
...
@@ -2,6 +2,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pig4cloud.pig.admin.api.feign.fallback.RemoteUserServiceFallbackImpl,\
com.pig4cloud.pig.admin.api.feign.fallback.RemoteLogServiceFallbackImpl,\
com.pig4cloud.pig.admin.api.feign.fallback.RemoteTokenServiceFallbackImpl,\
com.pig4cloud.pig.admin.api.feign.fallback.RemoteDeptServiceFallbackImpl,\
com.pig4cloud.pig.admin.api.feign.factory.RemoteUserServiceFallbackFactory,\
com.pig4cloud.pig.admin.api.feign.factory.RemoteLogServiceFallbackFactory,\
com.pig4cloud.pig.admin.api.feign.factory.RemoteTokenServiceFallbackFactory
com.pig4cloud.pig.admin.api.feign.factory.RemoteTokenServiceFallbackFactory,\
com.pig4cloud.pig.admin.api.feign.factory.RemoteDeptServiceFallbackFactory
pig-upms/pig-upms-biz/pom.xml
浏览文件 @
3f3def6f
...
...
@@ -60,6 +60,11 @@
<groupId>
com.pig4cloud
</groupId>
<artifactId>
pig-common-mybatis
</artifactId>
</dependency>
<!--数据权限 模块-->
<dependency>
<groupId>
com.pig4cloud
</groupId>
<artifactId>
pig-common-datascope
</artifactId>
</dependency>
<!--注册中心客户端-->
<dependency>
<groupId>
com.alibaba.cloud
</groupId>
...
...
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/controller/DeptController.java
浏览文件 @
3f3def6f
...
...
@@ -20,6 +20,7 @@ import com.pig4cloud.pig.admin.api.entity.SysDept;
import
com.pig4cloud.pig.admin.service.SysDeptService
;
import
com.pig4cloud.pig.common.core.util.R
;
import
com.pig4cloud.pig.common.log.annotation.SysLog
;
import
com.pig4cloud.pig.common.security.annotation.Inner
;
import
io.swagger.annotations.Api
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.security.access.prepost.PreAuthorize
;
...
...
@@ -27,6 +28,7 @@ import org.springframework.web.bind.annotation.*;
import
javax.validation.Valid
;
import
java.time.LocalDateTime
;
import
java.util.List
;
/**
* <p>
...
...
@@ -121,4 +123,14 @@ public class DeptController {
return
R
.
ok
(
sysDeptService
.
getOne
(
new
QueryWrapper
<>(
condition
)));
}
/**
* 查收子级id列表
* @return 返回子级id列表
*/
@Inner
@GetMapping
(
value
=
"/child-id/{deptId}"
)
public
R
<
List
<
Integer
>>
listChildDeptId
(
@PathVariable
Integer
deptId
)
{
return
R
.
ok
(
sysDeptService
.
listChildDeptId
(
deptId
));
}
}
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/controller/UserController.java
浏览文件 @
3f3def6f
...
...
@@ -20,8 +20,10 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.pig4cloud.pig.admin.api.dto.UserDTO
;
import
com.pig4cloud.pig.admin.api.dto.UserInfo
;
import
com.pig4cloud.pig.admin.api.entity.SysUser
;
import
com.pig4cloud.pig.admin.api.vo.UserExcelVO
;
import
com.pig4cloud.pig.admin.api.vo.UserInfoVO
;
import
com.pig4cloud.pig.admin.service.SysUserService
;
import
com.pig4cloud.pig.common.core.util.R
;
import
com.pig4cloud.pig.common.log.annotation.SysLog
;
...
...
@@ -33,10 +35,19 @@ import io.swagger.annotations.Api;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.validation.BindingResult
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.DeleteMapping
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.PutMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
import
javax.validation.Valid
;
import
java.util.List
;
import
java.util.Set
;
/**
* @author lengleng
...
...
@@ -61,7 +72,12 @@ public class UserController {
if
(
user
==
null
)
{
return
R
.
failed
(
"获取当前用户信息失败"
);
}
return
R
.
ok
(
userService
.
getUserInfo
(
user
));
UserInfo
userInfo
=
userService
.
getUserInfo
(
user
);
UserInfoVO
vo
=
new
UserInfoVO
();
vo
.
setSysUser
(
userInfo
.
getSysUser
());
vo
.
setRoles
(
userInfo
.
getRoles
());
vo
.
setPermissions
(
userInfo
.
getPermissions
());
return
R
.
ok
(
vo
);
}
/**
...
...
@@ -78,6 +94,17 @@ public class UserController {
return
R
.
ok
(
userService
.
getUserInfo
(
user
));
}
/**
* 根据部门id,查询对应的用户 id 集合
* @param deptIds 部门id 集合
* @return 用户 id 集合
*/
@Inner
@GetMapping
(
"/ids"
)
public
R
<
List
<
Integer
>>
listUserIdByDeptIds
(
@RequestParam
(
"deptIds"
)
Set
<
Integer
>
deptIds
)
{
return
R
.
ok
(
userService
.
listUserIdByDeptIds
(
deptIds
));
}
/**
* 通过ID查询用户信息
* @param id ID
...
...
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/datascope/PigDataScope.java
0 → 100644
浏览文件 @
3f3def6f
package
com.pig4cloud.pig.admin.datascope
;
import
cn.hutool.core.collection.CollectionUtil
;
import
com.pig4cloud.pig.common.security.datascope.UserDataScope
;
import
com.pig4cloud.pig.common.security.service.PigUser
;
import
com.pig4cloud.pig.common.security.util.SecurityUtils
;
import
com.pigcloud.pig.common.datascope.DataScope
;
import
net.sf.jsqlparser.expression.Alias
;
import
net.sf.jsqlparser.expression.Expression
;
import
net.sf.jsqlparser.expression.LongValue
;
import
net.sf.jsqlparser.expression.Parenthesis
;
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
org.springframework.stereotype.Component
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.TreeSet
;
import
java.util.stream.Collectors
;
/**
* 数据权限控制,要求表至少有个 user_id 字段
*
* @author hccake
*/
@Component
public
class
PigDataScope
implements
DataScope
{
private
static
final
String
USER_ID
=
"user_id"
;
private
static
final
String
DEPT_ID
=
"dept_id"
;
/**
* 拥有 dept_id 字段的表名集合
*/
private
static
final
Set
<
String
>
DEPT_ID_TABLE_NAMES
=
CollectionUtil
.
newHashSet
(
"sys_user"
);
/**
* 仅拥有 user_id 字段的表名集合
*/
private
static
final
Set
<
String
>
USER_ID_TABLE_NAMES
=
CollectionUtil
.
newHashSet
();
private
final
Set
<
String
>
tableNames
;
public
PigDataScope
()
{
Set
<
String
>
set
=
new
TreeSet
<>(
String
.
CASE_INSENSITIVE_ORDER
);
set
.
addAll
(
DEPT_ID_TABLE_NAMES
);
set
.
addAll
(
USER_ID_TABLE_NAMES
);
this
.
tableNames
=
Collections
.
unmodifiableSet
(
set
);
}
@Override
public
String
getResource
()
{
return
"userData"
;
}
@Override
public
Collection
<
String
>
getTableNames
()
{
return
this
.
tableNames
;
}
@Override
public
Expression
getExpression
(
String
tableName
,
Alias
tableAlias
)
{
// 获取当前登录用户
PigUser
user
=
SecurityUtils
.
getUser
();
if
(
user
==
null
)
{
return
null
;
}
UserDataScope
userDataScope
=
user
.
getUserDataScope
();
// 如果数据权限是全部,直接放行
if
(
userDataScope
.
isAllScope
())
{
return
null
;
}
// 如果数据权限是仅自己
if
(
userDataScope
.
isOnlySelf
())
{
// 数据权限规则,where user_id = xx
return
userIdEqualsToExpression
(
tableAlias
,
user
.
getId
());
}
// 如果当前表有部门字段,则优先使用部门字段控制范围
if
(
DEPT_ID_TABLE_NAMES
.
contains
(
tableName
))
{
// 数据权限规则,where (user_id =xx or dept_id in ("x","y"))
EqualsTo
equalsTo
=
userIdEqualsToExpression
(
tableAlias
,
user
.
getId
());
Expression
inExpression
=
getInExpression
(
tableAlias
,
DEPT_ID
,
userDataScope
.
getScopeDeptIds
());
// 这里一定要加括号,否则如果有其他查询条件,or 会出问题
return
new
Parenthesis
(
new
OrExpression
(
equalsTo
,
inExpression
));
}
else
{
// 数据权限规则,where user_id in ("x","y")
return
getInExpression
(
tableAlias
,
USER_ID
,
userDataScope
.
getScopeUserIds
());
}
}
private
EqualsTo
userIdEqualsToExpression
(
Alias
tableAlias
,
Integer
userId
)
{
Column
column
=
new
Column
(
tableAlias
==
null
?
USER_ID
:
tableAlias
.
getName
()
+
"."
+
USER_ID
);
return
new
EqualsTo
(
column
,
new
LongValue
(
userId
));
}
private
Expression
getInExpression
(
Alias
tableAlias
,
String
columnName
,
Set
<
Integer
>
scopeUserIds
)
{
Column
column
=
new
Column
(
tableAlias
==
null
?
columnName
:
tableAlias
.
getName
()
+
"."
+
columnName
);
ExpressionList
expressionList
=
new
ExpressionList
();
List
<
Expression
>
list
=
scopeUserIds
.
stream
().
map
(
LongValue:
:
new
).
collect
(
Collectors
.
toList
());
expressionList
.
setExpressions
(
list
);
return
new
InExpression
(
column
,
expressionList
);
}
}
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/service/SysDeptService.java
浏览文件 @
3f3def6f
...
...
@@ -65,4 +65,11 @@ public interface SysDeptService extends IService<SysDept> {
*/
Boolean
updateDeptById
(
SysDept
sysDept
);
/**
* 查找指定部门的子部门id列表
* @param deptId 部门id
* @return List<Integer>
*/
List
<
Integer
>
listChildDeptId
(
Integer
deptId
);
}
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/service/SysUserService.java
浏览文件 @
3f3def6f
...
...
@@ -28,6 +28,7 @@ import com.pig4cloud.pig.common.core.util.R;
import
org.springframework.validation.BindingResult
;
import
java.util.List
;
import
java.util.Set
;
/**
* @author lengleng
...
...
@@ -107,4 +108,11 @@ public interface SysUserService extends IService<SysUser> {
*/
R
importUser
(
List
<
UserExcelVO
>
excelVOList
,
BindingResult
bindingResult
);
/**
* 根据部门 id 列表查询对应的用户 id 集合
* @param deptIds 部门 id 列表
* @return userIdList
*/
List
<
Integer
>
listUserIdByDeptIds
(
Set
<
Integer
>
deptIds
);
}
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/service/impl/SysDeptServiceImpl.java
浏览文件 @
3f3def6f
...
...
@@ -33,6 +33,7 @@ import org.springframework.beans.BeanUtils;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.ArrayList
;
import
java.util.Comparator
;
import
java.util.HashMap
;
import
java.util.List
;
...
...
@@ -108,6 +109,16 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
return
Boolean
.
TRUE
;
}
@Override
public
List
<
Integer
>
listChildDeptId
(
Integer
deptId
)
{
List
<
SysDeptRelation
>
deptRelations
=
sysDeptRelationService
.
list
(
Wrappers
.<
SysDeptRelation
>
lambdaQuery
()
.
eq
(
SysDeptRelation:
:
getAncestor
,
deptId
).
ne
(
SysDeptRelation:
:
getDescendant
,
deptId
));
if
(
CollUtil
.
isNotEmpty
(
deptRelations
))
{
return
deptRelations
.
stream
().
map
(
SysDeptRelation:
:
getDescendant
).
collect
(
Collectors
.
toList
());
}
return
new
ArrayList
<>();
}
/**
* 查询全部部门树
* @return 树
...
...
pig-upms/pig-upms-biz/src/main/java/com/pig4cloud/pig/admin/service/impl/SysUserServiceImpl.java
浏览文件 @
3f3def6f
...
...
@@ -25,7 +25,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.pig4cloud.pig.admin.api.dto.UserDTO
;
import
com.pig4cloud.pig.admin.api.dto.UserInfo
;
import
com.pig4cloud.pig.admin.api.entity.*
;
import
com.pig4cloud.pig.admin.api.entity.SysDept
;
import
com.pig4cloud.pig.admin.api.entity.SysMenu
;
import
com.pig4cloud.pig.admin.api.entity.SysRole
;
import
com.pig4cloud.pig.admin.api.entity.SysUser
;
import
com.pig4cloud.pig.admin.api.entity.SysUserRole
;
import
com.pig4cloud.pig.admin.api.vo.UserExcelVO
;
import
com.pig4cloud.pig.admin.api.vo.UserVO
;
import
com.pig4cloud.pig.admin.mapper.SysDeptMapper
;
...
...
@@ -107,9 +111,11 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
public
UserInfo
getUserInfo
(
SysUser
sysUser
)
{
UserInfo
userInfo
=
new
UserInfo
();
userInfo
.
setSysUser
(
sysUser
);
// 设置角色列表
List
<
SysRole
>
roleList
=
sysRoleMapper
.
listRolesByUserId
(
sysUser
.
getUserId
());
userInfo
.
setRoleList
(
roleList
);
// 设置角色列表 (ID)
List
<
Integer
>
roleIds
=
sysRoleMapper
.
listRolesByUserId
(
sysUser
.
getUserId
()).
stream
().
map
(
SysRole:
:
getRoleId
)
.
collect
(
Collectors
.
toList
());
List
<
Integer
>
roleIds
=
roleList
.
stream
().
map
(
SysRole:
:
getRoleId
).
collect
(
Collectors
.
toList
());
userInfo
.
setRoles
(
ArrayUtil
.
toArray
(
roleIds
,
Integer
.
class
));
// 设置权限列表(menu.permission)
Set
<
String
>
permissions
=
sysMenuService
.
findMenuByRoleId
(
CollUtil
.
join
(
roleIds
,
StrUtil
.
COMMA
)).
stream
()
...
...
@@ -117,6 +123,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
.
filter
(
m
->
StrUtil
.
isNotBlank
(
m
.
getPermission
())).
map
(
SysMenu:
:
getPermission
)
.
collect
(
Collectors
.
toSet
());
userInfo
.
setPermissions
(
ArrayUtil
.
toArray
(
permissions
,
String
.
class
));
return
userInfo
;
}
...
...
@@ -295,6 +302,13 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
return
R
.
ok
();
}
@Override
public
List
<
Integer
>
listUserIdByDeptIds
(
Set
<
Integer
>
deptIds
)
{
return
this
.
listObjs
(
Wrappers
.
lambdaQuery
(
SysUser
.
class
).
select
(
SysUser:
:
getUserId
).
in
(
SysUser:
:
getDeptId
,
deptIds
),
Integer
.
class
::
cast
);
}
/**
* 插入excel User
*/
...
...
pig-visual/pig-xxl-job-admin/pom.xml
浏览文件 @
3f3def6f
...
...
@@ -47,12 +47,6 @@
<artifactId>
spring-boot-starter-mail
</artifactId>
</dependency>
<!-- starter-actuator -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-actuator
</artifactId>
</dependency>
<!-- mybatis-starter:mybatis + mybatis-spring + hikari(default) -->
<dependency>
<groupId>
org.mybatis.spring.boot
</groupId>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录