Commit b0855cc626d2b9eb4495ea9e2d996df11d8dd090

Authored by YunaiV
1 parent f9b15fe7

实现 DataPermissionRuleFactoryImpl,并增加相关单测

yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionAnnotationInterceptor.java
@@ -34,7 +34,7 @@ public class DataPermissionAnnotationInterceptor implements MethodInterceptor { @@ -34,7 +34,7 @@ public class DataPermissionAnnotationInterceptor implements MethodInterceptor {
34 // 入栈 34 // 入栈
35 DataPermission dataPermission = this.findAnnotation(methodInvocation); 35 DataPermission dataPermission = this.findAnnotation(methodInvocation);
36 if (dataPermission != null) { 36 if (dataPermission != null) {
37 - DataPermissionContextHolder.push(dataPermission); 37 + DataPermissionContextHolder.add(dataPermission);
38 } 38 }
39 try { 39 try {
40 // 执行逻辑 40 // 执行逻辑
@@ -42,7 +42,7 @@ public class DataPermissionAnnotationInterceptor implements MethodInterceptor { @@ -42,7 +42,7 @@ public class DataPermissionAnnotationInterceptor implements MethodInterceptor {
42 } finally { 42 } finally {
43 // 出栈 43 // 出栈
44 if (dataPermission != null) { 44 if (dataPermission != null) {
45 - DataPermissionContextHolder.poll(); 45 + DataPermissionContextHolder.remove();
46 } 46 }
47 } 47 }
48 } 48 }
yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionContextHolder.java
@@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.datapermission.core.aop; @@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.datapermission.core.aop;
3 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; 3 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
4 import com.alibaba.ttl.TransmittableThreadLocal; 4 import com.alibaba.ttl.TransmittableThreadLocal;
5 5
6 -import java.util.ArrayDeque;  
7 -import java.util.Deque; 6 +import java.util.LinkedList;
  7 +import java.util.List;
8 8
9 /** 9 /**
10 * {@link DataPermission} 注解的 Context 上下文 10 * {@link DataPermission} 注解的 Context 上下文
@@ -13,16 +13,19 @@ import java.util.Deque; @@ -13,16 +13,19 @@ import java.util.Deque;
13 */ 13 */
14 public class DataPermissionContextHolder { 14 public class DataPermissionContextHolder {
15 15
16 - private static final ThreadLocal<Deque<DataPermission>> DATA_PERMISSIONS =  
17 - TransmittableThreadLocal.withInitial(ArrayDeque::new); 16 + /**
  17 + * 使用 List 的原因,可能存在方法的嵌套调用
  18 + */
  19 + private static final ThreadLocal<LinkedList<DataPermission>> DATA_PERMISSIONS =
  20 + TransmittableThreadLocal.withInitial(LinkedList::new);
18 21
19 /** 22 /**
20 * 获得当前的 DataPermission 注解 23 * 获得当前的 DataPermission 注解
21 * 24 *
22 * @return DataPermission 注解 25 * @return DataPermission 注解
23 */ 26 */
24 - public static DataPermission peek() {  
25 - return DATA_PERMISSIONS.get().remove(); 27 + public static DataPermission get() {
  28 + return DATA_PERMISSIONS.get().peekLast();
26 } 29 }
27 30
28 /** 31 /**
@@ -30,8 +33,8 @@ public class DataPermissionContextHolder { @@ -30,8 +33,8 @@ public class DataPermissionContextHolder {
30 * 33 *
31 * @param dataPermission DataPermission 注解 34 * @param dataPermission DataPermission 注解
32 */ 35 */
33 - public static void push(DataPermission dataPermission) {  
34 - DATA_PERMISSIONS.get().push(dataPermission); 36 + public static void add(DataPermission dataPermission) {
  37 + DATA_PERMISSIONS.get().addLast(dataPermission);
35 } 38 }
36 39
37 /** 40 /**
@@ -39,13 +42,31 @@ public class DataPermissionContextHolder { @@ -39,13 +42,31 @@ public class DataPermissionContextHolder {
39 * 42 *
40 * @return DataPermission 注解 43 * @return DataPermission 注解
41 */ 44 */
42 - public static DataPermission poll() {  
43 - DataPermission dataPermission = DATA_PERMISSIONS.get().poll(); 45 + public static DataPermission remove() {
  46 + DataPermission dataPermission = DATA_PERMISSIONS.get().removeLast();
44 // 无元素时,清空 ThreadLocal 47 // 无元素时,清空 ThreadLocal
45 - if (dataPermission == null) { 48 + if (DATA_PERMISSIONS.get().isEmpty()) {
46 DATA_PERMISSIONS.remove(); 49 DATA_PERMISSIONS.remove();
47 } 50 }
48 return dataPermission; 51 return dataPermission;
49 } 52 }
50 53
  54 + /**
  55 + * 获得所有 DataPermission
  56 + *
  57 + * @return DataPermission 队列
  58 + */
  59 + public static List<DataPermission> getAll() {
  60 + return DATA_PERMISSIONS.get();
  61 + }
  62 +
  63 + /**
  64 + * 清空上下文
  65 + *
  66 + * 目前仅仅用于单测
  67 + */
  68 + public static void clear() {
  69 + DATA_PERMISSIONS.remove();
  70 + }
  71 +
51 } 72 }
yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/DataPermissionRuleFactoryImpl.java
1 package cn.iocoder.yudao.framework.datapermission.core.rule; 1 package cn.iocoder.yudao.framework.datapermission.core.rule;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ArrayUtil;
  5 +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
  6 +import cn.iocoder.yudao.framework.datapermission.core.aop.DataPermissionContextHolder;
3 import lombok.RequiredArgsConstructor; 7 import lombok.RequiredArgsConstructor;
4 8
  9 +import java.util.Collections;
5 import java.util.List; 10 import java.util.List;
  11 +import java.util.stream.Collectors;
6 12
  13 +/**
  14 + * 默认的 DataPermissionRuleFactoryImpl 实现类
  15 + * 支持通过 {@link DataPermissionContextHolder} 过滤数据权限
  16 + *
  17 + * @author 芋道源码
  18 + */
7 @RequiredArgsConstructor 19 @RequiredArgsConstructor
8 public class DataPermissionRuleFactoryImpl implements DataPermissionRuleFactory { 20 public class DataPermissionRuleFactoryImpl implements DataPermissionRuleFactory {
9 21
@@ -17,9 +29,34 @@ public class DataPermissionRuleFactoryImpl implements DataPermissionRuleFactory @@ -17,9 +29,34 @@ public class DataPermissionRuleFactoryImpl implements DataPermissionRuleFactory
17 return rules; 29 return rules;
18 } 30 }
19 31
20 - @Override 32 + @Override // mappedStatementId 参数,暂时没有用。以后,可以基于 mappedStatementId + DataPermission 进行缓存
21 public List<DataPermissionRule> getDataPermissionRule(String mappedStatementId) { 33 public List<DataPermissionRule> getDataPermissionRule(String mappedStatementId) {
22 - return null; 34 + // 1. 无数据权限
  35 + if (CollUtil.isEmpty(rules)) {
  36 + return Collections.emptyList();
  37 + }
  38 + // 2. 未配置,则默认开启
  39 + DataPermission dataPermission = DataPermissionContextHolder.get();
  40 + if (dataPermission == null) {
  41 + return rules;
  42 + }
  43 + // 3. 已配置,但禁用
  44 + if (!dataPermission.enable()) {
  45 + return Collections.emptyList();
  46 + }
  47 +
  48 + // 4. 已配置,只选择部分规则
  49 + if (ArrayUtil.isNotEmpty(dataPermission.includeRules())) {
  50 + return rules.stream().filter(rule -> ArrayUtil.contains(dataPermission.includeRules(), rule.getClass()))
  51 + .collect(Collectors.toList()); // 一般规则不会太多,所以不采用 HashSet 查询
  52 + }
  53 + // 5. 已配置,只排除部分规则
  54 + if (ArrayUtil.isNotEmpty(dataPermission.excludeRules())) {
  55 + return rules.stream().filter(rule -> !ArrayUtil.contains(dataPermission.excludeRules(), rule.getClass()))
  56 + .collect(Collectors.toList()); // 一般规则不会太多,所以不采用 HashSet 查询
  57 + }
  58 + // 6. 已配置,全部规则
  59 + return rules;
23 } 60 }
24 61
25 } 62 }
yudao-framework/yudao-spring-boot-starter-data-permission/src/test/resources/META-INF/spring.factories renamed to yudao-framework/yudao-spring-boot-starter-data-permission/src/main/resources/META-INF/spring.factories
yudao-framework/yudao-spring-boot-starter-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionContextHolderTest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.datapermission.core.aop;
  2 +
  3 +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
  4 +import org.junit.jupiter.api.BeforeEach;
  5 +import org.junit.jupiter.api.Test;
  6 +
  7 +import static org.junit.jupiter.api.Assertions.assertEquals;
  8 +import static org.junit.jupiter.api.Assertions.assertSame;
  9 +import static org.mockito.Mockito.mock;
  10 +
  11 +/**
  12 + * {@link DataPermissionContextHolder} 的单元测试
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +class DataPermissionContextHolderTest {
  17 +
  18 + @BeforeEach
  19 + public void setUp() {
  20 + DataPermissionContextHolder.clear();
  21 + }
  22 +
  23 + @Test
  24 + public void testGet() {
  25 + // mock 方法
  26 + DataPermission dataPermission01 = mock(DataPermission.class);
  27 + DataPermissionContextHolder.add(dataPermission01);
  28 + DataPermission dataPermission02 = mock(DataPermission.class);
  29 + DataPermissionContextHolder.add(dataPermission02);
  30 +
  31 + // 调用
  32 + DataPermission result = DataPermissionContextHolder.get();
  33 + // 断言
  34 + assertSame(result, dataPermission02);
  35 + }
  36 +
  37 + @Test
  38 + public void testPush() {
  39 + // 调用
  40 + DataPermission dataPermission01 = mock(DataPermission.class);
  41 + DataPermissionContextHolder.add(dataPermission01);
  42 + DataPermission dataPermission02 = mock(DataPermission.class);
  43 + DataPermissionContextHolder.add(dataPermission02);
  44 + // 断言
  45 + DataPermission first = DataPermissionContextHolder.getAll().get(0);
  46 + DataPermission second = DataPermissionContextHolder.getAll().get(1);
  47 + assertSame(dataPermission01, first);
  48 + assertSame(dataPermission02, second);
  49 + }
  50 +
  51 + @Test
  52 + public void testRemove() {
  53 + // mock 方法
  54 + DataPermission dataPermission01 = mock(DataPermission.class);
  55 + DataPermissionContextHolder.add(dataPermission01);
  56 + DataPermission dataPermission02 = mock(DataPermission.class);
  57 + DataPermissionContextHolder.add(dataPermission02);
  58 +
  59 + // 调用
  60 + DataPermission result = DataPermissionContextHolder.remove();
  61 + // 断言
  62 + assertSame(result, dataPermission02);
  63 + assertEquals(1, DataPermissionContextHolder.getAll().size());
  64 + }
  65 +
  66 +}
yudao-framework/yudao-spring-boot-starter-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/DataPermissionRuleFactoryImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.datapermission.core.rule;
  2 +
  3 +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
  4 +import cn.iocoder.yudao.framework.datapermission.core.aop.DataPermissionContextHolder;
  5 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  6 +import net.sf.jsqlparser.expression.Alias;
  7 +import net.sf.jsqlparser.expression.Expression;
  8 +import org.junit.jupiter.api.BeforeEach;
  9 +import org.junit.jupiter.api.Test;
  10 +import org.mockito.InjectMocks;
  11 +import org.mockito.Spy;
  12 +import org.springframework.core.annotation.AnnotationUtils;
  13 +
  14 +import java.util.Arrays;
  15 +import java.util.List;
  16 +import java.util.Set;
  17 +
  18 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
  19 +import static org.junit.jupiter.api.Assertions.*;
  20 +
  21 +/**
  22 + * {@link DataPermissionRuleFactoryImpl} 单元测试
  23 + *
  24 + * @author 芋道源码
  25 + */
  26 +class DataPermissionRuleFactoryImplTest extends BaseMockitoUnitTest {
  27 +
  28 + @InjectMocks
  29 + private DataPermissionRuleFactoryImpl dataPermissionRuleFactory;
  30 +
  31 + @Spy
  32 + private List<DataPermissionRule> rules = Arrays.asList(new DataPermissionRule01(),
  33 + new DataPermissionRule02());
  34 +
  35 + @BeforeEach
  36 + public void setUp() {
  37 + DataPermissionContextHolder.clear();
  38 + }
  39 +
  40 + @Test
  41 + public void testGetDataPermissionRule_02() {
  42 + // 准备参数
  43 + String mappedStatementId = randomString();
  44 +
  45 + // 调用
  46 + List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
  47 + // 断言
  48 + assertSame(rules, result);
  49 + }
  50 +
  51 + @Test
  52 + public void testGetDataPermissionRule_03() {
  53 + // 准备参数
  54 + String mappedStatementId = randomString();
  55 + // mock 方法
  56 + DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass03.class, DataPermission.class));
  57 +
  58 + // 调用
  59 + List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
  60 + // 断言
  61 + assertTrue(result.isEmpty());
  62 + }
  63 +
  64 + @Test
  65 + public void testGetDataPermissionRule_04() {
  66 + // 准备参数
  67 + String mappedStatementId = randomString();
  68 + // mock 方法
  69 + DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass04.class, DataPermission.class));
  70 +
  71 + // 调用
  72 + List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
  73 + // 断言
  74 + assertEquals(1, result.size());
  75 + assertEquals(DataPermissionRule01.class, result.get(0).getClass());
  76 + }
  77 +
  78 + @Test
  79 + public void testGetDataPermissionRule_05() {
  80 + // 准备参数
  81 + String mappedStatementId = randomString();
  82 + // mock 方法
  83 + DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass05.class, DataPermission.class));
  84 +
  85 + // 调用
  86 + List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
  87 + // 断言
  88 + assertEquals(1, result.size());
  89 + assertEquals(DataPermissionRule02.class, result.get(0).getClass());
  90 + }
  91 +
  92 + @Test
  93 + public void testGetDataPermissionRule_06() {
  94 + // 准备参数
  95 + String mappedStatementId = randomString();
  96 + // mock 方法
  97 + DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass06.class, DataPermission.class));
  98 +
  99 + // 调用
  100 + List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
  101 + // 断言
  102 + assertSame(rules, result);
  103 + }
  104 +
  105 + @DataPermission(enable = false)
  106 + static class TestClass03 {}
  107 +
  108 + @DataPermission(includeRules = DataPermissionRule01.class)
  109 + static class TestClass04 {}
  110 +
  111 + @DataPermission(excludeRules = DataPermissionRule01.class)
  112 + static class TestClass05 {}
  113 +
  114 + @DataPermission
  115 + static class TestClass06 {}
  116 +
  117 + static class DataPermissionRule01 implements DataPermissionRule {
  118 +
  119 + @Override
  120 + public Set<String> getTableNames() {
  121 + return null;
  122 + }
  123 +
  124 + @Override
  125 + public Expression getExpression(String tableName, Alias tableAlias) {
  126 + return null;
  127 + }
  128 +
  129 + }
  130 +
  131 + static class DataPermissionRule02 implements DataPermissionRule {
  132 +
  133 + @Override
  134 + public Set<String> getTableNames() {
  135 + return null;
  136 + }
  137 +
  138 + @Override
  139 + public Expression getExpression(String tableName, Alias tableAlias) {
  140 + return null;
  141 + }
  142 +
  143 + }
  144 +
  145 +}