dengzedong
2024-12-19 85b2001c0ec2f1adc598db3bf47ad457dcca7074
提交 | 用户 | 时间
e7c126 1 package com.iailab.framework.datapermission.core.rule.dept;
H 2
3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ReflectUtil;
5 import com.iailab.framework.common.enums.UserTypeEnum;
6 import com.iailab.framework.common.util.collection.SetUtils;
7 import com.iailab.framework.security.core.LoginUser;
8 import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
9 import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
10 import com.iailab.module.system.api.permission.PermissionApi;
11 import com.iailab.module.system.api.permission.dto.DeptDataPermissionRespDTO;
12 import net.sf.jsqlparser.expression.Alias;
13 import net.sf.jsqlparser.expression.Expression;
14 import org.junit.jupiter.api.BeforeEach;
15 import org.junit.jupiter.api.Test;
16 import org.mockito.InjectMocks;
17 import org.mockito.Mock;
18 import org.mockito.MockedStatic;
19
20 import java.util.Map;
21
22 import static com.iailab.framework.common.pojo.CommonResult.success;
23 import static com.iailab.framework.datapermission.core.rule.dept.DeptDataPermissionRule.EXPRESSION_NULL;
24 import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
25 import static com.iailab.framework.test.core.util.RandomUtils.randomString;
26 import static org.junit.jupiter.api.Assertions.*;
27 import static org.mockito.ArgumentMatchers.eq;
28 import static org.mockito.ArgumentMatchers.same;
29 import static org.mockito.Mockito.mockStatic;
30 import static org.mockito.Mockito.when;
31
32 /**
33  * {@link DeptDataPermissionRule} 的单元测试
34  *
35  * @author iailab
36  */
37 class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
38
39     @InjectMocks
40     private DeptDataPermissionRule rule;
41
42     @Mock
43     private PermissionApi permissionApi;
44
45     @BeforeEach
46     @SuppressWarnings("unchecked")
47     public void setUp() {
48         // 清空 rule
49         rule.getTableNames().clear();
50         ((Map<String, String>) ReflectUtil.getFieldValue(rule, "deptColumns")).clear();
51         ((Map<String, String>) ReflectUtil.getFieldValue(rule, "deptColumns")).clear();
52     }
53
54     @Test // 无 LoginUser
55     public void testGetExpression_noLoginUser() {
56         // 准备参数
57         String tableName = randomString();
58         Alias tableAlias = new Alias(randomString());
59         // mock 方法
60
61         // 调用
62         Expression expression = rule.getExpression(tableName, tableAlias);
63         // 断言
64         assertNull(expression);
65     }
66
67     @Test // 无数据权限时
68     public void testGetExpression_noDeptDataPermission() {
69         try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
70                      = mockStatic(SecurityFrameworkUtils.class)) {
71             // 准备参数
72             String tableName = "t_user";
73             Alias tableAlias = new Alias("u");
74             // mock 方法
75             LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
76                     .setUserType(UserTypeEnum.ADMIN.getValue()));
77             securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
78             // mock 方法(permissionApi 返回 null)
79             when(permissionApi.getDeptDataPermission(eq(loginUser.getId()))).thenReturn(success(null));
80
81             // 调用
82             NullPointerException exception = assertThrows(NullPointerException.class,
83                     () -> rule.getExpression(tableName, tableAlias));
84             // 断言
85             assertEquals("LoginUser(1) Table(t_user/u) 未返回数据权限", exception.getMessage());
86         }
87     }
88
89     @Test // 全部数据权限
90     public void testGetExpression_allDeptDataPermission() {
91         try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
92                      = mockStatic(SecurityFrameworkUtils.class)) {
93             // 准备参数
94             String tableName = "t_user";
95             Alias tableAlias = new Alias("u");
96             // mock 方法(LoginUser)
97             LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
98                     .setUserType(UserTypeEnum.ADMIN.getValue()));
99             securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
100             // mock 方法(DeptDataPermissionRespDTO)
101             DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO().setAll(true);
102             when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
103
104             // 调用
105             Expression expression = rule.getExpression(tableName, tableAlias);
106             // 断言
107             assertNull(expression);
108             assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
109         }
110     }
111
112     @Test // 即不能查看部门,又不能查看自己,则说明 100% 无权限
113     public void testGetExpression_noDept_noSelf() {
114         try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
115                      = mockStatic(SecurityFrameworkUtils.class)) {
116             // 准备参数
117             String tableName = "t_user";
118             Alias tableAlias = new Alias("u");
119             // mock 方法(LoginUser)
120             LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
121                     .setUserType(UserTypeEnum.ADMIN.getValue()));
122             securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
123             // mock 方法(DeptDataPermissionRespDTO)
124             DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO();
125             when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
126
127             // 调用
128             Expression expression = rule.getExpression(tableName, tableAlias);
129             // 断言
130             assertEquals("null = null", expression.toString());
131             assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
132         }
133     }
134
135     @Test // 拼接 Dept 和 User 的条件(字段都不符合)
136     public void testGetExpression_noDeptColumn_noSelfColumn() {
137         try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
138                      = mockStatic(SecurityFrameworkUtils.class)) {
139             // 准备参数
140             String tableName = "t_user";
141             Alias tableAlias = new Alias("u");
142             // mock 方法(LoginUser)
143             LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
144                     .setUserType(UserTypeEnum.ADMIN.getValue()));
145             securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
146             // mock 方法(DeptDataPermissionRespDTO)
147             DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
148                     .setDeptIds(SetUtils.asSet(10L, 20L)).setSelf(true);
149             when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
150
151             // 调用
152             Expression expression = rule.getExpression(tableName, tableAlias);
153             // 断言
154             assertSame(EXPRESSION_NULL, expression);
155             assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
156         }
157     }
158
159     @Test // 拼接 Dept 和 User 的条件(self 符合)
160     public void testGetExpression_noDeptColumn_yesSelfColumn() {
161         try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
162                      = mockStatic(SecurityFrameworkUtils.class)) {
163             // 准备参数
164             String tableName = "t_user";
165             Alias tableAlias = new Alias("u");
166             // mock 方法(LoginUser)
167             LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
168                     .setUserType(UserTypeEnum.ADMIN.getValue()));
169             securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
170             // mock 方法(DeptDataPermissionRespDTO)
171             DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
172                     .setSelf(true);
173             when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
174             // 添加 user 字段配置
175             rule.addUserColumn("t_user", "id");
176
177             // 调用
178             Expression expression = rule.getExpression(tableName, tableAlias);
179             // 断言
180             assertEquals("u.id = 1", expression.toString());
181             assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
182         }
183     }
184
185     @Test // 拼接 Dept 和 User 的条件(dept 符合)
186     public void testGetExpression_yesDeptColumn_noSelfColumn() {
187         try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
188                      = mockStatic(SecurityFrameworkUtils.class)) {
189             // 准备参数
190             String tableName = "t_user";
191             Alias tableAlias = new Alias("u");
192             // mock 方法(LoginUser)
193             LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
194                     .setUserType(UserTypeEnum.ADMIN.getValue()));
195             securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
196             // mock 方法(DeptDataPermissionRespDTO)
197             DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
198                     .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L));
199             when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
200             // 添加 dept 字段配置
201             rule.addDeptColumn("t_user", "dept_id");
202
203             // 调用
204             Expression expression = rule.getExpression(tableName, tableAlias);
205             // 断言
206             assertEquals("u.dept_id IN (10, 20)", expression.toString());
207             assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
208         }
209     }
210
211     @Test // 拼接 Dept 和 User 的条件(dept + self 符合)
212     public void testGetExpression_yesDeptColumn_yesSelfColumn() {
213         try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
214                      = mockStatic(SecurityFrameworkUtils.class)) {
215             // 准备参数
216             String tableName = "t_user";
217             Alias tableAlias = new Alias("u");
218             // mock 方法(LoginUser)
219             LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
220                     .setUserType(UserTypeEnum.ADMIN.getValue()));
221             securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
222             // mock 方法(DeptDataPermissionRespDTO)
223             DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
224                     .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L)).setSelf(true);
225             when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
226             // 添加 user 字段配置
227             rule.addUserColumn("t_user", "id");
228             // 添加 dept 字段配置
229             rule.addDeptColumn("t_user", "dept_id");
230
231             // 调用
232             Expression expression = rule.getExpression(tableName, tableAlias);
233             // 断言
234             assertEquals("(u.dept_id IN (10, 20) OR u.id = 1)", expression.toString());
235             assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
236         }
237     }
238
239 }