浏览代码

增加 DeptDataPermissionRuleTest 单元测试

YunaiV 3 年之前
父节点
当前提交
619a7b73c3

+ 15 - 2
yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java

@@ -91,7 +91,8 @@ public class DeptDataPermissionRule implements DataPermissionRule {
         DeptDataPermissionRespDTO deptDataPermission = deptDataPermissionService.getDeptDataPermission(loginUser);
         DeptDataPermissionRespDTO deptDataPermission = deptDataPermissionService.getDeptDataPermission(loginUser);
         if (deptDataPermission == null) {
         if (deptDataPermission == null) {
             log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
             log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
-            return null;
+            throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限",
+                    loginUser.getId(), tableName, tableAlias.getName()));
         }
         }
 
 
         // 情况一,如果是 ALL 可查看全部,则无需拼接条件
         // 情况一,如果是 ALL 可查看全部,则无需拼接条件
@@ -111,7 +112,7 @@ public class DeptDataPermissionRule implements DataPermissionRule {
         if (deptExpression == null && userExpression == null) {
         if (deptExpression == null && userExpression == null) {
             log.error("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
             log.error("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
                     JsonUtils.toJsonString(loginUser), tableName, tableAlias, JsonUtils.toJsonString(deptDataPermission));
                     JsonUtils.toJsonString(loginUser), tableName, tableAlias, JsonUtils.toJsonString(deptDataPermission));
-            throw new NullPointerException(String.format("LoginUser(%d) tableName(%s) tableAlias(%s) 构建的条件为空",
+            throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 构建的条件为空",
                     loginUser.getId(), tableName, tableAlias.getName()));
                     loginUser.getId(), tableName, tableAlias.getName()));
         }
         }
         if (deptExpression == null) {
         if (deptExpression == null) {
@@ -130,6 +131,10 @@ public class DeptDataPermissionRule implements DataPermissionRule {
         if (StrUtil.isEmpty(columnName)) {
         if (StrUtil.isEmpty(columnName)) {
             return null;
             return null;
         }
         }
+        // 如果为空,则无条件
+        if (CollUtil.isEmpty(deptIds)) {
+            return null;
+        }
         // 拼接条件
         // 拼接条件
         return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName),
         return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName),
                 new ExpressionList(CollectionUtils.convertList(deptIds, LongValue::new)));
                 new ExpressionList(CollectionUtils.convertList(deptIds, LongValue::new)));
@@ -156,6 +161,10 @@ public class DeptDataPermissionRule implements DataPermissionRule {
 
 
     public void addDeptColumn(Class<? extends BaseDO> entityClass, String columnName) {
     public void addDeptColumn(Class<? extends BaseDO> entityClass, String columnName) {
         String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
         String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
+       addDeptColumn(tableName, columnName);
+    }
+
+    public void addDeptColumn(String tableName, String columnName) {
         deptColumns.put(tableName, columnName);
         deptColumns.put(tableName, columnName);
         TABLE_NAMES.add(tableName);
         TABLE_NAMES.add(tableName);
     }
     }
@@ -166,6 +175,10 @@ public class DeptDataPermissionRule implements DataPermissionRule {
 
 
     public void addUserColumn(Class<? extends BaseDO> entityClass, String columnName) {
     public void addUserColumn(Class<? extends BaseDO> entityClass, String columnName) {
         String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
         String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
+        addUserColumn(tableName, columnName);
+    }
+
+    public void addUserColumn(String tableName, String columnName) {
         userColumns.put(tableName, columnName);
         userColumns.put(tableName, columnName);
         TABLE_NAMES.add(tableName);
         TABLE_NAMES.add(tableName);
     }
     }

+ 221 - 0
yudao-framework/yudao-spring-boot-starter-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRuleTest.java

@@ -0,0 +1,221 @@
+package cn.iocoder.yudao.framework.datapermission.core.dept.rule;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
+import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
+import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
+import cn.iocoder.yudao.framework.security.core.LoginUser;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import net.sf.jsqlparser.expression.Alias;
+import net.sf.jsqlparser.expression.Expression;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+
+/**
+ * {@link DeptDataPermissionRule} 的单元测试
+ *
+ * @author 芋道源码
+ */
+class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
+
+    @InjectMocks
+    private DeptDataPermissionRule rule;
+
+    @Mock
+    private DeptDataPermissionFrameworkService deptDataPermissionFrameworkService;
+
+    @BeforeEach
+    @SuppressWarnings("unchecked")
+    public void setUp() {
+        // 清空 rule
+        rule.getTableNames().clear();
+        ((Map<String, String>) ReflectUtil.getFieldValue(rule, "deptColumns")).clear();
+        ((Map<String, String>) ReflectUtil.getFieldValue(rule, "deptColumns")).clear();
+    }
+
+    @Test // 无 LoginUser
+    public void testGetExpression_noLoginUser() {
+        // 准备参数
+        String tableName = randomString();
+        Alias tableAlias = new Alias(randomString());
+        // mock 方法
+
+        // 调用
+        Expression expression = rule.getExpression(tableName, tableAlias);
+        // 断言
+        assertNull(expression);
+    }
+
+    @Test // 无数据权限时
+    public void testGetExpression_noDeptDataPermission() {
+        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
+                     = mockStatic(SecurityFrameworkUtils.class)) {
+            // 准备参数
+            String tableName = "t_user";
+            Alias tableAlias = new Alias("u");
+            // mock 方法
+            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
+
+            // 调用
+            NullPointerException exception = assertThrows(NullPointerException.class,
+                    () -> rule.getExpression(tableName, tableAlias));
+            // 断言
+            assertEquals("LoginUser(1) Table(t_user/u) 未返回数据权限", exception.getMessage());
+        }
+    }
+
+    @Test // 全部数据权限
+    public void testGetExpression_allDeptDataPermission() {
+        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
+                     = mockStatic(SecurityFrameworkUtils.class)) {
+            // 准备参数
+            String tableName = "t_user";
+            Alias tableAlias = new Alias("u");
+            // mock 方法(LoginUser)
+            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
+            // mock 方法(DeptDataPermissionRespDTO)
+            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO().setAll(true);
+            when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+
+            // 调用
+            Expression expression = rule.getExpression(tableName, tableAlias);
+            // 断言
+            assertNull(expression);
+        }
+    }
+
+    @Test // 即不能查看部门,又不能查看自己,则说明 100% 无权限
+    public void testGetExpression_noDept_noSelf() {
+        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
+                     = mockStatic(SecurityFrameworkUtils.class)) {
+            // 准备参数
+            String tableName = "t_user";
+            Alias tableAlias = new Alias("u");
+            // mock 方法(LoginUser)
+            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
+            // mock 方法(DeptDataPermissionRespDTO)
+            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO();
+            when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+
+            // 调用
+            Expression expression = rule.getExpression(tableName, tableAlias);
+            // 断言
+            assertEquals("null = null", expression.toString());
+        }
+    }
+
+    @Test // 拼接 Dept 和 User 的条件(字段都不符合)
+    public void testGetExpression_noDeptColumn_noSelfColumn() {
+        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
+                     = mockStatic(SecurityFrameworkUtils.class)) {
+            // 准备参数
+            String tableName = "t_user";
+            Alias tableAlias = new Alias("u");
+            // mock 方法(LoginUser)
+            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
+            // mock 方法(DeptDataPermissionRespDTO)
+            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
+                    .setDeptIds(SetUtils.asSet(10L, 20L)).setSelf(true);
+            when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+
+            // 调用
+            NullPointerException exception = assertThrows(NullPointerException.class,
+                    () -> rule.getExpression(tableName, tableAlias));
+            // 断言
+            assertEquals("LoginUser(1) Table(t_user/u) 构建的条件为空", exception.getMessage());
+        }
+    }
+
+    @Test // 拼接 Dept 和 User 的条件(self 符合)
+    public void testGetExpression_noDeptColumn_yesSelfColumn() {
+        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
+                     = mockStatic(SecurityFrameworkUtils.class)) {
+            // 准备参数
+            String tableName = "t_user";
+            Alias tableAlias = new Alias("u");
+            // mock 方法(LoginUser)
+            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
+            // mock 方法(DeptDataPermissionRespDTO)
+            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
+                    .setSelf(true);
+            when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+            // 添加 user 字段配置
+            rule.addUserColumn("t_user", "id");
+
+            // 调用
+            Expression expression = rule.getExpression(tableName, tableAlias);
+            // 断言
+            assertEquals("u.id = 1", expression.toString());
+        }
+    }
+
+    @Test // 拼接 Dept 和 User 的条件(dept 符合)
+    public void testGetExpression_yesDeptColumn_noSelfColumn() {
+        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
+                     = mockStatic(SecurityFrameworkUtils.class)) {
+            // 准备参数
+            String tableName = "t_user";
+            Alias tableAlias = new Alias("u");
+            // mock 方法(LoginUser)
+            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
+            // mock 方法(DeptDataPermissionRespDTO)
+            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
+                    .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L));
+            when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+            // 添加 dept 字段配置
+            rule.addDeptColumn("t_user", "dept_id");
+
+            // 调用
+            Expression expression = rule.getExpression(tableName, tableAlias);
+            // 断言
+            assertEquals("u.dept_id IN (10, 20)", expression.toString());
+        }
+    }
+
+    @Test // 拼接 Dept 和 User 的条件(dept + self 符合)
+    public void testGetExpression_yesDeptColumn_yesSelfColumn() {
+        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
+                     = mockStatic(SecurityFrameworkUtils.class)) {
+            // 准备参数
+            String tableName = "t_user";
+            Alias tableAlias = new Alias("u");
+            // mock 方法(LoginUser)
+            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L));
+            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
+            // mock 方法(DeptDataPermissionRespDTO)
+            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
+                    .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L)).setSelf(true);
+            when(deptDataPermissionFrameworkService.getDeptDataPermission(same(loginUser))).thenReturn(deptDataPermission);
+            // 添加 user 字段配置
+            rule.addUserColumn("t_user", "id");
+            // 添加 dept 字段配置
+            rule.addDeptColumn("t_user", "dept_id");
+
+            // 调用
+            Expression expression = rule.getExpression(tableName, tableAlias);
+            // 断言
+            assertEquals("u.dept_id IN (10, 20) OR u.id = 1", expression.toString());
+        }
+    }
+
+}