Commit 0f792c64e7bcbcc7bf601ff696b99f310aa11268
1 parent
e9385219
通过 MyBatis Plus 数据权限的单测
Showing
4 changed files
with
282 additions
and
45 deletions
yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/interceptor/DataPermissionInterceptor.java
| ... | ... | @@ -330,6 +330,7 @@ public class DataPermissionInterceptor extends JsqlParserSupport implements Inne |
| 330 | 330 | // boolean needIgnore = ignoreTable(fromTable.getName()); |
| 331 | 331 | // // 表名压栈,忽略的表压入 null,以便后续不处理 |
| 332 | 332 | // tables.push(needIgnore ? null : fromTable); |
| 333 | + tables.push(fromTable); | |
| 333 | 334 | // 尾缀多个 on 表达式的时候统一处理 |
| 334 | 335 | if (originOnExpressions.size() > 1) { |
| 335 | 336 | Collection<Expression> onExpressions = new LinkedList<>(); |
| ... | ... | @@ -457,7 +458,7 @@ public class DataPermissionInterceptor extends JsqlParserSupport implements Inne |
| 457 | 458 | * |
| 458 | 459 | * @author 芋道源码 |
| 459 | 460 | */ |
| 460 | - private static final class ContextHolder { | |
| 461 | + static final class ContextHolder { | |
| 461 | 462 | |
| 462 | 463 | /** |
| 463 | 464 | * 该 {@link MappedStatement} 对应的规则 | ... | ... |
yudao-framework/yudao-spring-boot-starter-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/interceptor/DataPermissionInterceptorTest.java deleted
| 1 | -package cn.iocoder.yudao.framework.datapermission.core.interceptor; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRuleFactory; | |
| 4 | -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | |
| 5 | -import org.junit.jupiter.api.Test; | |
| 6 | -import org.mockito.InjectMocks; | |
| 7 | -import org.mockito.Mock; | |
| 8 | - | |
| 9 | -import static org.assertj.core.api.Assertions.assertThat; | |
| 10 | - | |
| 11 | -public class DataPermissionInterceptorTest extends BaseMockitoUnitTest { | |
| 12 | - | |
| 13 | - @InjectMocks | |
| 14 | - private DataPermissionInterceptor interceptor; | |
| 15 | - | |
| 16 | - @Mock | |
| 17 | - private DataPermissionRuleFactory ruleFactory; | |
| 18 | - | |
| 19 | - @Test | |
| 20 | - public void selectSingle() { | |
| 21 | - // 单表 | |
| 22 | - assertSql("select * from entity where id = ?", | |
| 23 | - "SELECT * FROM entity WHERE id = ? AND tenant_id = 1"); | |
| 24 | - | |
| 25 | - assertSql("select * from entity where id = ? or name = ?", | |
| 26 | - "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1"); | |
| 27 | - | |
| 28 | - assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)", | |
| 29 | - "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1"); | |
| 30 | - | |
| 31 | - /* not */ | |
| 32 | - assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)", | |
| 33 | - "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND tenant_id = 1"); | |
| 34 | - } | |
| 35 | - | |
| 36 | - private void assertSql(String sql, String targetSql) { | |
| 37 | - assertThat(interceptor.parserSingle(sql, null)).isEqualTo(targetSql); | |
| 38 | - } | |
| 39 | - | |
| 40 | - public static void main(String[] args) { | |
| 41 | - System.out.println("123"); | |
| 42 | - } | |
| 43 | - | |
| 44 | -} |
yudao-framework/yudao-spring-boot-starter-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/interceptor/DataPermissionInterceptorTest2.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.datapermission.core.interceptor; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRule; | |
| 4 | +import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRuleFactory; | |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; | |
| 6 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | |
| 7 | +import net.sf.jsqlparser.expression.Alias; | |
| 8 | +import net.sf.jsqlparser.expression.Expression; | |
| 9 | +import net.sf.jsqlparser.expression.LongValue; | |
| 10 | +import net.sf.jsqlparser.expression.operators.relational.EqualsTo; | |
| 11 | +import net.sf.jsqlparser.schema.Column; | |
| 12 | +import org.junit.jupiter.api.BeforeEach; | |
| 13 | +import org.junit.jupiter.api.Test; | |
| 14 | +import org.mockito.InjectMocks; | |
| 15 | +import org.mockito.Mock; | |
| 16 | + | |
| 17 | +import java.util.Collections; | |
| 18 | +import java.util.Set; | |
| 19 | + | |
| 20 | +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; | |
| 21 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 22 | + | |
| 23 | +/** | |
| 24 | + * {@link DataPermissionInterceptor} 的单元测试 | |
| 25 | + * 主要复用了 MyBatis Plus 的 TenantLineInnerInterceptorTest 的单元测试 | |
| 26 | + * 不过它的单元测试不是很规范,考虑到是复用的,所以暂时不进行修改~ | |
| 27 | + * | |
| 28 | + * @author 芋道源码 | |
| 29 | + */ | |
| 30 | +public class DataPermissionInterceptorTest2 extends BaseMockitoUnitTest { | |
| 31 | + | |
| 32 | + @InjectMocks | |
| 33 | + private DataPermissionInterceptor interceptor; | |
| 34 | + | |
| 35 | + @Mock | |
| 36 | + private DataPermissionRuleFactory ruleFactory; | |
| 37 | + | |
| 38 | + @BeforeEach | |
| 39 | + public void setUp() { | |
| 40 | + // 租户的数据权限规则 | |
| 41 | + DataPermissionRule tenantRule = new DataPermissionRule() { | |
| 42 | + | |
| 43 | + private static final String COLUMN = "tenant_id"; | |
| 44 | + | |
| 45 | + @Override | |
| 46 | + public Set<String> getTableNames() { | |
| 47 | + return asSet("entity", "entity1", "entity2", "t1", "t2"); | |
| 48 | + } | |
| 49 | + | |
| 50 | + @Override | |
| 51 | + public Expression getExpression(String tableName, Alias tableAlias) { | |
| 52 | + Column column = MyBatisUtils.buildColumn(tableName, tableAlias, COLUMN); | |
| 53 | + LongValue value = new LongValue(1L); | |
| 54 | + return new EqualsTo(column, value); | |
| 55 | + } | |
| 56 | + | |
| 57 | + }; | |
| 58 | + // 设置到上下文,保证 | |
| 59 | + DataPermissionInterceptor.ContextHolder.init(Collections.singletonList(tenantRule)); | |
| 60 | + } | |
| 61 | + | |
| 62 | + @Test | |
| 63 | + void delete() { | |
| 64 | + assertSql("delete from entity where id = ?", | |
| 65 | + "DELETE FROM entity WHERE id = ? AND tenant_id = 1"); | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Test | |
| 69 | + void update() { | |
| 70 | + assertSql("update entity set name = ? where id = ?", | |
| 71 | + "UPDATE entity SET name = ? WHERE id = ? AND tenant_id = 1"); | |
| 72 | + } | |
| 73 | + | |
| 74 | + @Test | |
| 75 | + void selectSingle() { | |
| 76 | + // 单表 | |
| 77 | + assertSql("select * from entity where id = ?", | |
| 78 | + "SELECT * FROM entity WHERE id = ? AND tenant_id = 1"); | |
| 79 | + | |
| 80 | + assertSql("select * from entity where id = ? or name = ?", | |
| 81 | + "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1"); | |
| 82 | + | |
| 83 | + assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)", | |
| 84 | + "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1"); | |
| 85 | + | |
| 86 | + /* not */ | |
| 87 | + assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)", | |
| 88 | + "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND tenant_id = 1"); | |
| 89 | + } | |
| 90 | + | |
| 91 | + @Test | |
| 92 | + void selectSubSelectIn() { | |
| 93 | + /* in */ | |
| 94 | + assertSql("SELECT * FROM entity e WHERE e.id IN (select e1.id from entity1 e1 where e1.id = ?)", | |
| 95 | + "SELECT * FROM entity e WHERE e.id IN (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); | |
| 96 | + // 在最前 | |
| 97 | + assertSql("SELECT * FROM entity e WHERE e.id IN " + | |
| 98 | + "(select e1.id from entity1 e1 where e1.id = ?) and e.id = ?", | |
| 99 | + "SELECT * FROM entity e WHERE e.id IN " + | |
| 100 | + "(SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.id = ? AND e.tenant_id = 1"); | |
| 101 | + // 在最后 | |
| 102 | + assertSql("SELECT * FROM entity e WHERE e.id = ? and e.id IN " + | |
| 103 | + "(select e1.id from entity1 e1 where e1.id = ?)", | |
| 104 | + "SELECT * FROM entity e WHERE e.id = ? AND e.id IN " + | |
| 105 | + "(SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); | |
| 106 | + // 在中间 | |
| 107 | + assertSql("SELECT * FROM entity e WHERE e.id = ? and e.id IN " + | |
| 108 | + "(select e1.id from entity1 e1 where e1.id = ?) and e.id = ?", | |
| 109 | + "SELECT * FROM entity e WHERE e.id = ? AND e.id IN " + | |
| 110 | + "(SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.id = ? AND e.tenant_id = 1"); | |
| 111 | + } | |
| 112 | + | |
| 113 | + @Test | |
| 114 | + void selectSubSelectEq() { | |
| 115 | + /* = */ | |
| 116 | + assertSql("SELECT * FROM entity e WHERE e.id = (select e1.id from entity1 e1 where e1.id = ?)", | |
| 117 | + "SELECT * FROM entity e WHERE e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); | |
| 118 | + } | |
| 119 | + | |
| 120 | + @Test | |
| 121 | + void selectSubSelectInnerNotEq() { | |
| 122 | + /* inner not = */ | |
| 123 | + assertSql("SELECT * FROM entity e WHERE not (e.id = (select e1.id from entity1 e1 where e1.id = ?))", | |
| 124 | + "SELECT * FROM entity e WHERE NOT (e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1)) AND e.tenant_id = 1"); | |
| 125 | + | |
| 126 | + assertSql("SELECT * FROM entity e WHERE not (e.id = (select e1.id from entity1 e1 where e1.id = ?) and e.id = ?)", | |
| 127 | + "SELECT * FROM entity e WHERE NOT (e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.id = ?) AND e.tenant_id = 1"); | |
| 128 | + } | |
| 129 | + | |
| 130 | + @Test | |
| 131 | + void selectSubSelectExists() { | |
| 132 | + /* EXISTS */ | |
| 133 | + assertSql("SELECT * FROM entity e WHERE EXISTS (select e1.id from entity1 e1 where e1.id = ?)", | |
| 134 | + "SELECT * FROM entity e WHERE EXISTS (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); | |
| 135 | + | |
| 136 | + | |
| 137 | + /* NOT EXISTS */ | |
| 138 | + assertSql("SELECT * FROM entity e WHERE NOT EXISTS (select e1.id from entity1 e1 where e1.id = ?)", | |
| 139 | + "SELECT * FROM entity e WHERE NOT EXISTS (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); | |
| 140 | + } | |
| 141 | + | |
| 142 | + @Test | |
| 143 | + void selectSubSelect() { | |
| 144 | + /* >= */ | |
| 145 | + assertSql("SELECT * FROM entity e WHERE e.id >= (select e1.id from entity1 e1 where e1.id = ?)", | |
| 146 | + "SELECT * FROM entity e WHERE e.id >= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); | |
| 147 | + | |
| 148 | + /* <= */ | |
| 149 | + assertSql("SELECT * FROM entity e WHERE e.id <= (select e1.id from entity1 e1 where e1.id = ?)", | |
| 150 | + "SELECT * FROM entity e WHERE e.id <= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); | |
| 151 | + | |
| 152 | + /* <> */ | |
| 153 | + assertSql("SELECT * FROM entity e WHERE e.id <> (select e1.id from entity1 e1 where e1.id = ?)", | |
| 154 | + "SELECT * FROM entity e WHERE e.id <> (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); | |
| 155 | + } | |
| 156 | + | |
| 157 | + @Test | |
| 158 | + void selectFromSelect() { | |
| 159 | + assertSql("SELECT * FROM (select e.id from entity e WHERE e.id = (select e1.id from entity1 e1 where e1.id = ?))", | |
| 160 | + "SELECT * FROM (SELECT e.id FROM entity e WHERE e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1)"); | |
| 161 | + } | |
| 162 | + | |
| 163 | + @Test | |
| 164 | + void selectBodySubSelect() { | |
| 165 | + assertSql("select t1.col1,(select t2.col2 from t2 t2 where t1.col1=t2.col1) from t1 t1", | |
| 166 | + "SELECT t1.col1, (SELECT t2.col2 FROM t2 t2 WHERE t1.col1 = t2.col1 AND t2.tenant_id = 1) FROM t1 t1 WHERE t1.tenant_id = 1"); | |
| 167 | + } | |
| 168 | + | |
| 169 | + @Test | |
| 170 | + void selectLeftJoin() { | |
| 171 | + // left join | |
| 172 | + assertSql("SELECT * FROM entity e " + | |
| 173 | + "left join entity1 e1 on e1.id = e.id " + | |
| 174 | + "WHERE e.id = ? OR e.name = ?", | |
| 175 | + "SELECT * FROM entity e " + | |
| 176 | + "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + | |
| 177 | + "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); | |
| 178 | + | |
| 179 | + assertSql("SELECT * FROM entity e " + | |
| 180 | + "left join entity1 e1 on e1.id = e.id " + | |
| 181 | + "WHERE (e.id = ? OR e.name = ?)", | |
| 182 | + "SELECT * FROM entity e " + | |
| 183 | + "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + | |
| 184 | + "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); | |
| 185 | + } | |
| 186 | + | |
| 187 | + @Test | |
| 188 | + void selectRightJoin() { | |
| 189 | + // right join | |
| 190 | + assertSql("SELECT * FROM entity e " + | |
| 191 | + "right join entity1 e1 on e1.id = e.id", | |
| 192 | + "SELECT * FROM entity e " + | |
| 193 | + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + | |
| 194 | + "WHERE e.tenant_id = 1"); | |
| 195 | + | |
| 196 | + assertSql("SELECT * FROM entity e " + | |
| 197 | + "right join entity1 e1 on e1.id = e.id " + | |
| 198 | + "WHERE e.id = ? OR e.name = ?", | |
| 199 | + "SELECT * FROM entity e " + | |
| 200 | + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + | |
| 201 | + "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); | |
| 202 | + } | |
| 203 | + | |
| 204 | + @Test | |
| 205 | + void selectLeftJoinMultipleTrailingOn() { | |
| 206 | + // 多个 on 尾缀的 | |
| 207 | + assertSql("SELECT * FROM entity e " + | |
| 208 | + "LEFT JOIN entity1 e1 " + | |
| 209 | + "LEFT JOIN entity2 e2 ON e2.id = e1.id " + | |
| 210 | + "ON e1.id = e.id " + | |
| 211 | + "WHERE (e.id = ? OR e.NAME = ?)", | |
| 212 | + "SELECT * FROM entity e " + | |
| 213 | + "LEFT JOIN entity1 e1 " + | |
| 214 | + "LEFT JOIN entity2 e2 ON e2.id = e1.id AND e2.tenant_id = 1 " + | |
| 215 | + "ON e1.id = e.id AND e1.tenant_id = 1 " + | |
| 216 | + "WHERE (e.id = ? OR e.NAME = ?) AND e.tenant_id = 1"); | |
| 217 | + | |
| 218 | + assertSql("SELECT * FROM entity e " + | |
| 219 | + "LEFT JOIN entity1 e1 " + | |
| 220 | + "LEFT JOIN with_as_A e2 ON e2.id = e1.id " + | |
| 221 | + "ON e1.id = e.id " + | |
| 222 | + "WHERE (e.id = ? OR e.NAME = ?)", | |
| 223 | + "SELECT * FROM entity e " + | |
| 224 | + "LEFT JOIN entity1 e1 " + | |
| 225 | + "LEFT JOIN with_as_A e2 ON e2.id = e1.id " + | |
| 226 | + "ON e1.id = e.id AND e1.tenant_id = 1 " + | |
| 227 | + "WHERE (e.id = ? OR e.NAME = ?) AND e.tenant_id = 1"); | |
| 228 | + } | |
| 229 | + | |
| 230 | + @Test | |
| 231 | + void selectInnerJoin() { | |
| 232 | + // inner join | |
| 233 | + assertSql("SELECT * FROM entity e " + | |
| 234 | + "inner join entity1 e1 on e1.id = e.id " + | |
| 235 | + "WHERE e.id = ? OR e.name = ?", | |
| 236 | + "SELECT * FROM entity e " + | |
| 237 | + "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + | |
| 238 | + "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); | |
| 239 | + | |
| 240 | + assertSql("SELECT * FROM entity e " + | |
| 241 | + "inner join entity1 e1 on e1.id = e.id " + | |
| 242 | + "WHERE (e.id = ? OR e.name = ?)", | |
| 243 | + "SELECT * FROM entity e " + | |
| 244 | + "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + | |
| 245 | + "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); | |
| 246 | + | |
| 247 | + // 垃圾 inner join todo | |
| 248 | +// assertSql("SELECT * FROM entity,entity1 " + | |
| 249 | +// "WHERE entity.id = entity1.id", | |
| 250 | +// "SELECT * FROM entity e " + | |
| 251 | +// "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + | |
| 252 | +// "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); | |
| 253 | + } | |
| 254 | + | |
| 255 | + | |
| 256 | + @Test | |
| 257 | + void selectWithAs() { | |
| 258 | + assertSql("with with_as_A as (select * from entity) select * from with_as_A", | |
| 259 | + "WITH with_as_A AS (SELECT * FROM entity WHERE tenant_id = 1) SELECT * FROM with_as_A"); | |
| 260 | + } | |
| 261 | + | |
| 262 | + private void assertSql(String sql, String targetSql) { | |
| 263 | + assertEquals(targetSql, interceptor.parserSingle(sql, null)); | |
| 264 | + } | |
| 265 | + | |
| 266 | +} | ... | ... |
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java
| ... | ... | @@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.core.metadata.OrderItem; |
| 7 | 7 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
| 8 | 8 | import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; |
| 9 | 9 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| 10 | +import net.sf.jsqlparser.expression.Alias; | |
| 11 | +import net.sf.jsqlparser.schema.Column; | |
| 10 | 12 | import net.sf.jsqlparser.schema.Table; |
| 11 | 13 | |
| 12 | 14 | import java.util.ArrayList; |
| ... | ... | @@ -67,4 +69,16 @@ public class MyBatisUtils { |
| 67 | 69 | return tableName; |
| 68 | 70 | } |
| 69 | 71 | |
| 72 | + /** | |
| 73 | + * 构建 Column 对象 | |
| 74 | + * | |
| 75 | + * @param tableName 表名 | |
| 76 | + * @param tableAlias 别名 | |
| 77 | + * @param column 字段名 | |
| 78 | + * @return Column 对象 | |
| 79 | + */ | |
| 80 | + public static Column buildColumn(String tableName, Alias tableAlias, String column) { | |
| 81 | + return new Column(tableAlias != null ? tableAlias.getName() + "." + column : column); | |
| 82 | + } | |
| 83 | + | |
| 70 | 84 | } | ... | ... |