package com.qianwen.core.tenant; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils; import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Deque; import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; import net.sf.jsqlparser.expression.BinaryExpression; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.Parenthesis; import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; 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.MultiExpressionList; import net.sf.jsqlparser.parser.ASTNodeAccessImpl; 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.FromItem; import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.ParenthesisFromItem; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SubJoin; import net.sf.jsqlparser.statement.update.Update; import com.qianwen.core.secure.utils.AuthUtil; import com.qianwen.core.tool.utils.CollectionUtil; import net.sf.jsqlparser.expression.operators.relational.ItemsList; public class BladeTenantInterceptor extends TenantLineInnerInterceptor { private TenantLineHandler tenantLineHandler; private BladeTenantProperties tenantProperties; private List adminTenantTables = Arrays.asList("blade_top_menu", "blade_dict_biz"); public void setTenantProperties(final BladeTenantProperties tenantProperties) { this.tenantProperties = tenantProperties; } public void setAdminTenantTables(final List adminTenantTables) { this.adminTenantTables = adminTenantTables; } public String toString() { return "BladeTenantInterceptor(super=" + super.toString() + ", tenantLineHandler=" + getTenantLineHandler() + ", tenantProperties=" + getTenantProperties() + ", adminTenantTables=" + getAdminTenantTables() + ")"; } public boolean equals(final Object o) { if (o == this) { return true; } if (o instanceof BladeTenantInterceptor) { BladeTenantInterceptor other = (BladeTenantInterceptor) o; if (other.canEqual(this) && super.equals(o)) { Object this$tenantLineHandler = getTenantLineHandler(); Object other$tenantLineHandler = other.getTenantLineHandler(); if (this$tenantLineHandler == null) { if (other$tenantLineHandler != null) { return false; } } else if (!this$tenantLineHandler.equals(other$tenantLineHandler)) { return false; } Object this$tenantProperties = getTenantProperties(); Object other$tenantProperties = other.getTenantProperties(); if (this$tenantProperties == null) { if (other$tenantProperties != null) { return false; } } else if (!this$tenantProperties.equals(other$tenantProperties)) { return false; } Object this$adminTenantTables = getAdminTenantTables(); Object other$adminTenantTables = other.getAdminTenantTables(); return this$adminTenantTables == null ? other$adminTenantTables == null : this$adminTenantTables.equals(other$adminTenantTables); } return false; } return false; } protected boolean canEqual(final Object other) { return other instanceof BladeTenantInterceptor; } public int hashCode() { int result = super.hashCode(); Object $tenantLineHandler = getTenantLineHandler(); int result2 = (result * 59) + ($tenantLineHandler == null ? 43 : $tenantLineHandler.hashCode()); Object $tenantProperties = getTenantProperties(); int result3 = (result2 * 59) + ($tenantProperties == null ? 43 : $tenantProperties.hashCode()); Object $adminTenantTables = getAdminTenantTables(); return (result3 * 59) + ($adminTenantTables == null ? 43 : $adminTenantTables.hashCode()); } public TenantLineHandler getTenantLineHandler() { return this.tenantLineHandler; } public BladeTenantProperties getTenantProperties() { return this.tenantProperties; } public List getAdminTenantTables() { return this.adminTenantTables; } public void setTenantLineHandler(TenantLineHandler tenantLineHandler) { super.setTenantLineHandler(tenantLineHandler); this.tenantLineHandler = tenantLineHandler; } protected void processInsert(Insert insert, int index, String sql, Object obj) { if (!this.tenantProperties.getEnhance().booleanValue()) { super.processInsert(insert, index, sql, obj); return; } if (this.tenantLineHandler.ignoreTable(insert.getTable().getName())) return; List columns = insert.getColumns(); if (CollectionUtils.isEmpty(columns)) return; String tenantIdColumn = this.tenantLineHandler.getTenantIdColumn(); if (columns.stream().map(Column::getColumnName).anyMatch(i -> i.equals(tenantIdColumn))) return; columns.add(new Column(tenantIdColumn)); List duplicateUpdateColumns = insert.getDuplicateUpdateExpressionList(); if (CollectionUtils.isNotEmpty(duplicateUpdateColumns)) { EqualsTo equalsTo = new EqualsTo(); equalsTo.setLeftExpression((Expression)new StringValue(tenantIdColumn)); equalsTo.setRightExpression(this.tenantLineHandler.getTenantId()); duplicateUpdateColumns.add(equalsTo); } Select select = insert.getSelect(); if (select != null) { processInsertSelect(select.getSelectBody()); } else if (insert.getItemsList() != null) { ItemsList itemsList = insert.getItemsList(); if (itemsList instanceof MultiExpressionList) { ((MultiExpressionList)itemsList).getExpressionLists().forEach(el -> el.getExpressions().add(this.tenantLineHandler.getTenantId())); } else { ((ExpressionList)itemsList).getExpressions().add(this.tenantLineHandler.getTenantId()); } } else { throw ExceptionUtils.mpe("Failed to process multiple-table update, please exclude the tableName or statementId", new Object[0]); } } protected void processPlainSelect(PlainSelect plainSelect) { List selectItems = plainSelect.getSelectItems(); if (CollectionUtils.isNotEmpty(selectItems)) { selectItems.forEach(this::processSelectItem); } Expression where = plainSelect.getWhere(); processWhereSubSelect(where); FromItem fromItem = plainSelect.getFromItem(); List list = processFromItem(fromItem); List
mainTables = new ArrayList<>(list); List joins = plainSelect.getJoins(); if (CollectionUtils.isNotEmpty(joins)) { mainTables = processJoins(mainTables, joins); } if (CollectionUtils.isNotEmpty(mainTables) && !doTenantFilters(mainTables)) { plainSelect.setWhere(builderExpression(where, mainTables)); } } protected void processUpdate(Update update, int index, String sql, Object obj) { Table table = update.getTable(); if (this.tenantLineHandler.ignoreTable(table.getName()) || doTenantFilter(table.getName())) { return; } update.setWhere(andExpression(table, update.getWhere())); } protected void processDelete(Delete delete, int index, String sql, Object obj) { Table table = delete.getTable(); if (this.tenantLineHandler.ignoreTable(table.getName()) || doTenantFilter(table.getName())) { return; } delete.setWhere(andExpression(table, delete.getWhere())); } protected BinaryExpression andExpression(Table table, Expression where) { EqualsTo equalsTo = new EqualsTo(); Expression aliasColumn = getAliasColumn(table); //Column tenantId = this.tenantLineHandler.getTenantId(); // Column extends ASTNodeAccessImpl implements Expression Expression tenantId = this.tenantLineHandler.getTenantId(); if (doTenantFilter(table.getName())) { Expression stringValue = new StringValue("1"); tenantId = stringValue; aliasColumn = stringValue; } equalsTo.setLeftExpression(aliasColumn); equalsTo.setRightExpression(tenantId); if (null != where) { if (where instanceof OrExpression) { return new AndExpression(equalsTo, new Parenthesis(where)); } return new AndExpression(equalsTo, where); } return equalsTo; } protected Expression builderExpression(Expression currentExpression, List
tables) { if (CollectionUtils.isEmpty(tables)) { return currentExpression; } Expression tenantId = this.tenantLineHandler.getTenantId(); List equalsTos = (List) tables.stream().filter(x -> { return !this.tenantLineHandler.ignoreTable(x.getName()); }).filter(x2 -> { return !doTenantFilter(x2.getName()); }).map(item -> { return new EqualsTo(getAliasColumn(item), tenantId); }).collect(Collectors.toList()); if (CollectionUtils.isEmpty(equalsTos)) { return currentExpression; } Expression injectExpression = (Expression) equalsTos.get(0); if (equalsTos.size() > 1) { for (int i = 1; i < equalsTos.size(); i++) { injectExpression = new AndExpression(injectExpression, (Expression) equalsTos.get(i)); } } if (currentExpression == null) { return injectExpression; } if (currentExpression instanceof OrExpression) { return new AndExpression(new Parenthesis(currentExpression), injectExpression); } return new AndExpression(currentExpression, injectExpression); } private List
processFromItem(FromItem fromItem) { while (fromItem instanceof ParenthesisFromItem) { fromItem = ((ParenthesisFromItem) fromItem).getFromItem(); } List
mainTables = new ArrayList<>(); if (fromItem instanceof Table) { Table fromTable = (Table) fromItem; mainTables.add(fromTable); } else if (fromItem instanceof SubJoin) { List
tables = processSubJoin((SubJoin) fromItem); mainTables.addAll(tables); } else { processOtherFromItem(fromItem); } return mainTables; } private List
processSubJoin(SubJoin subJoin) { List
mainTables = new ArrayList<>(); if (subJoin.getJoinList() != null) { List
list = processFromItem(subJoin.getLeft()); mainTables.addAll(list); mainTables = processJoins(mainTables, subJoin.getJoinList()); } return mainTables; } private List
processJoins(List
mainTables, List joins) { Table mainTable = null; Table leftTable = null; if (mainTables == null) { mainTables = new ArrayList<>(); } else if (mainTables.size() == 1) { mainTable = mainTables.get(0); leftTable = mainTable; } Deque> onTableDeque = new LinkedList<>(); for (Join join : joins) { FromItem joinItem = join.getRightItem(); List
joinTables = null; if (joinItem instanceof Table) { joinTables = new ArrayList<>(); joinTables.add((Table) joinItem); } else if (joinItem instanceof SubJoin) { joinTables = processSubJoin((SubJoin) joinItem); } if (joinTables != null) { if (join.isSimple()) { mainTables.addAll(joinTables); } else { Table joinTable = joinTables.get(0); List
onTables = null; if (join.isRight()) { mainTable = joinTable; if (leftTable != null) { onTables = Collections.singletonList(leftTable); } } else if (join.isLeft()) { onTables = Collections.singletonList(joinTable); } else if (join.isInner()) { onTables = mainTable == null ? Collections.singletonList(joinTable) : Arrays.asList(mainTable, joinTable); mainTable = null; } mainTables = new ArrayList<>(); if (mainTable != null) { mainTables.add(mainTable); } Collection originOnExpressions = join.getOnExpressions(); if (originOnExpressions.size() == 1 && onTables != null) { List onExpressions = new LinkedList<>(); onExpressions.add(builderExpression(originOnExpressions.iterator().next(), onTables)); join.setOnExpressions(onExpressions); leftTable = joinTable; } else { onTableDeque.push(onTables); if (originOnExpressions.size() > 1) { Collection onExpressions2 = new LinkedList<>(); for (Expression originOnExpression : originOnExpressions) { List
currentTableList = onTableDeque.poll(); if (CollectionUtils.isEmpty(currentTableList)) { onExpressions2.add(originOnExpression); } else { onExpressions2.add(builderExpression(originOnExpression, currentTableList)); } } join.setOnExpressions(onExpressions2); } leftTable = joinTable; } } } else { processOtherFromItem(joinItem); leftTable = null; } } return mainTables; } public boolean doTenantFilter(String tableName) { return AuthUtil.isAdministrator() && !this.adminTenantTables.contains(tableName); } public boolean doTenantFilters(List
tables) { List tableNames = (List) tables.stream().map((v0) -> { return v0.getName(); }).collect(Collectors.toList()); return AuthUtil.isAdministrator() && !CollectionUtil.containsAny(this.adminTenantTables, tableNames); } }