!389 数据权限处理添加统一入口

Merge pull request !389 from bf109f/main
This commit is contained in:
Michael Yang 2023-12-19 07:04:58 +00:00 committed by Gitee
commit ab7e3a4526
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 276 additions and 6 deletions

View File

@ -91,4 +91,32 @@ public interface IDialect {
String forSelectEntityListByIds(TableInfo tableInfo, Object[] primaryValues);
/**
* 权限处理
*
* @param queryWrapper queryWrapper
* @param operateType 操作类型
*/
default void prepareAuth(QueryWrapper queryWrapper, OperateType operateType) {
}
/**
* 权限处理
*
* @param schema schema
* @param tableName 表名
* @param sql sql
* @param operateType 操作类型
*/
default void prepareAuth(String schema, String tableName, StringBuilder sql, OperateType operateType) {
}
/**
* 权限处理
* @param tableInfo tableInfo
* @param sql sql
* @param operateType 操作类型
*/
default void prepareAuth(TableInfo tableInfo, StringBuilder sql, OperateType operateType) {
}
}

View File

@ -0,0 +1,22 @@
package com.mybatisflex.core.dialect;
/**
* 操作类型
*/
public enum OperateType {
/**
* 查询
*/
SELECT,
/**
* 更新
*/
UPDATE,
/**
* 删除
*/
DELETE,
;
}

View File

@ -18,6 +18,7 @@ package com.mybatisflex.core.dialect.impl;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.dialect.KeywordWrap;
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
import com.mybatisflex.core.dialect.OperateType;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.exception.locale.LocalizedFormats;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
@ -164,6 +165,7 @@ public class CommonsDialectImpl implements IDialect {
}
sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER);
}
prepareAuth(schema, table, sql, OperateType.DELETE);
return sql.toString();
}
@ -205,11 +207,13 @@ public class CommonsDialectImpl implements IDialect {
sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER);
}
}
prepareAuth(schema, table, sql, OperateType.DELETE);
return sql.toString();
}
@Override
public String forDeleteByQuery(QueryWrapper queryWrapper) {
prepareAuth(queryWrapper, OperateType.DELETE);
return buildDeleteSql(queryWrapper);
}
@ -252,12 +256,13 @@ public class CommonsDialectImpl implements IDialect {
}
sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER);
}
prepareAuth(schema, table, sql, OperateType.UPDATE);
return sql.toString();
}
@Override
public String forUpdateByQuery(QueryWrapper queryWrapper, Row row) {
prepareAuth(queryWrapper, OperateType.UPDATE);
StringBuilder sqlBuilder = new StringBuilder();
Set<String> modifyAttrs = RowCPI.getModifyAttrs(row);
@ -332,11 +337,13 @@ public class CommonsDialectImpl implements IDialect {
}
sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER);
}
prepareAuth(schema, table, sql, OperateType.SELECT);
return sql.toString();
}
@Override
public String forSelectByQuery(QueryWrapper queryWrapper) {
prepareAuth(queryWrapper, OperateType.SELECT);
return buildSelectSql(queryWrapper);
}
@ -664,6 +671,7 @@ public class CommonsDialectImpl implements IDialect {
//租户ID
tableInfo.buildTenantCondition(sql, tenantIdArgs, this);
prepareAuth(tableInfo, sql, OperateType.DELETE);
return sql.toString();
}
@ -723,7 +731,7 @@ public class CommonsDialectImpl implements IDialect {
sql.append(BRACKET_RIGHT).append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo));
tableInfo.buildTenantCondition(sql, tenantIdArgs, this);
prepareAuth(tableInfo, sql, OperateType.DELETE);
return sql.toString();
}
@ -738,6 +746,7 @@ public class CommonsDialectImpl implements IDialect {
}
prepareAuth(queryWrapper, OperateType.DELETE);
//逻辑删除
List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper);
List<QueryTable> joinTables = CPI.getJoinTables(queryWrapper);
@ -823,12 +832,13 @@ public class CommonsDialectImpl implements IDialect {
sql.append(AND).append(wrap(versionColumn)).append(EQUALS).append(versionValue);
}
prepareAuth(tableInfo, sql, OperateType.UPDATE);
return sql.toString();
}
@Override
public String forUpdateEntityByQuery(TableInfo tableInfo, Object entity, boolean ignoreNulls, QueryWrapper queryWrapper) {
prepareAuth(queryWrapper, OperateType.UPDATE);
StringBuilder sqlBuilder = new StringBuilder();
Set<String> updateColumns = tableInfo.obtainUpdateColumns(entity, ignoreNulls, true);
@ -916,7 +926,7 @@ public class CommonsDialectImpl implements IDialect {
//多租户
Object[] tenantIdArgs = tableInfo.buildTenantIdArgs();
tableInfo.buildTenantCondition(sql, tenantIdArgs, this);
prepareAuth(tableInfo, sql, OperateType.SELECT);
return sql.toString();
}
@ -972,7 +982,7 @@ public class CommonsDialectImpl implements IDialect {
//多租户
tableInfo.buildTenantCondition(sql, tenantIdArgs, this);
prepareAuth(tableInfo, sql, OperateType.SELECT);
return sql.toString();
}

View File

@ -98,5 +98,4 @@ public class Account {
public void setDelete(Boolean delete) {
isDelete = delete;
}
}

View File

@ -0,0 +1,97 @@
package com.mybatisflex.coretest;
import com.mybatisflex.core.dialect.DbType;
import com.mybatisflex.core.dialect.DialectFactory;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.row.RowKey;
import com.mybatisflex.core.table.TableInfoFactory;
import com.mybatisflex.coretest.auth.AuthDialectImpl;
import com.mybatisflex.coretest.auth.Project;
import com.mybatisflex.coretest.auth.table.ProjectTableDef;
import org.junit.Before;
import org.junit.Test;
import static com.mybatisflex.coretest.auth.table.ProjectTableDef.PROJECT;
import static com.mybatisflex.coretest.table.AccountTableDef.ACCOUNT;
/**
* 权限测试
* @author zhang
* @since 2023/12/17
*/
public class AuthTest {
private IDialect dialect;
@Before
public void init() {
DialectFactory.registerDialect(DbType.MYSQL, new AuthDialectImpl());
dialect = DialectFactory.getDialect();
}
@Test
public void test() {
// 1.单个删除
assert "DELETE FROM `tb_project` WHERE `id` = ? AND `insert_user_id` = 1"
.equals(dialect.forDeleteById(PROJECT.getSchema(), PROJECT.getTableName(), new String[]{PROJECT.ID.getName()}));
// 2.批量删除
assert "DELETE FROM `tb_project` WHERE `id` = ? AND `insert_user_id` = 1"
.equals(dialect.forDeleteBatchByIds(PROJECT.getSchema(), PROJECT.getTableName(), new String[]{PROJECT.ID.getName()}, new Object[]{1L}));
// 3.查询
QueryWrapper deleteWrapper =
QueryWrapper.create(new Project()).where(PROJECT.ID.eq(1));
assert "DELETE FROM `tb_project` WHERE `id` = ? AND `insert_user_id` = ?"
.equals(dialect.forDeleteByQuery(deleteWrapper));
// 4.更新
assert "UPDATE `tb_project` SET `name` = ? WHERE `id` = ? AND `insert_user_id` = 1"
.equals(dialect.forUpdateById(PROJECT.getSchema(), PROJECT.getTableName(),
Row.ofKey(RowKey.AUTO).set(PROJECT.NAME, "项目")));
// 5.更新
Row row = new Row();
row.set(PROJECT.NAME, "项目");
QueryWrapper updateWrapper =
QueryWrapper.create(new Project()).where(PROJECT.ID.eq(1));
assert "UPDATE `tb_project` SET `name` = ? WHERE `id` = ? AND `insert_user_id` = ?"
.equals(dialect.forUpdateByQuery(updateWrapper, row));
// 6.ID查询
assert "SELECT * FROM `tb_project` WHERE `id` = ? AND `insert_user_id` = 1"
.equals(dialect.forSelectOneById(PROJECT.getSchema(), PROJECT.getTableName(), new String[]{PROJECT.ID.getName()}, new Object[]{1L}));
QueryWrapper queryWrapper = QueryWrapper.create(new Project()).where(PROJECT.ID.eq(1));
// 7.query查询
assert "SELECT `id`, `name`, `insert_user_id`, `is_delete` FROM `tb_project` WHERE `id` = ? AND `insert_user_id` = ?"
.equals(dialect.forSelectByQuery(queryWrapper));
// 8.删除
assert "UPDATE `tb_project` SET `is_delete` = 1 WHERE `id` = ? AND `is_delete` = 0 AND `insert_user_id` = 1"
.equals(dialect.forDeleteEntityById(TableInfoFactory.ofEntityClass(Project.class)));
// 9.批量删除
assert "UPDATE `tb_project` SET `is_delete` = 1 WHERE (`id` = ? ) AND `is_delete` = 0 AND `insert_user_id` = 1"
.equals(dialect.forDeleteEntityBatchByIds(TableInfoFactory.ofEntityClass(Project.class), new String[]{PROJECT.ID.getName()}));
// 10.query删除
assert "UPDATE `tb_project` SET `is_delete` = 1 WHERE `id` = ? AND `insert_user_id` = ? AND `insert_user_id` = ?"
.equals(dialect.forDeleteEntityBatchByQuery(TableInfoFactory.ofEntityClass(Project.class), queryWrapper));
// 11.更新
Project project = new Project();
project.setName("项目名称");
assert "UPDATE `tb_project` SET `name` = ? WHERE `id` = ? AND `is_delete` = 0 AND `insert_user_id` = 1"
.equals(dialect.forUpdateEntity(TableInfoFactory.ofEntityClass(Project.class), project, true));
// 12.更新
assert "UPDATE `tb_project` SET `name` = ? WHERE `id` = ? AND `insert_user_id` = ? AND `insert_user_id` = ? AND `insert_user_id` = ?"
.equals(dialect.forUpdateEntityByQuery(TableInfoFactory.ofEntityClass(Project.class), project, true, queryWrapper));
// 13.ID查询
assert "SELECT * FROM `tb_project` WHERE `id` = ? AND `is_delete` = 0 AND `insert_user_id` = 1"
.equals(dialect.forSelectOneEntityById(TableInfoFactory.ofEntityClass(Project.class)));
// 14.查询
assert "SELECT `id`, `name`, `insert_user_id`, `is_delete` FROM `tb_project` WHERE (`id` = ? ) AND `is_delete` = 0 AND `insert_user_id` = 1"
.equals(dialect.forSelectEntityListByIds(TableInfoFactory.ofEntityClass(Project.class), new String[]{PROJECT.ID.getName()}));
}
@Test
public void testWrapper() {
// (为什么打印的sql是这样的 DELETE FROM WHERE `id` = ? AND `insert_user_id` = ?)
QueryWrapper deleteWrapper =
QueryWrapper.create().where(ACCOUNT.ID.eq(1));
System.out.println(dialect.forDeleteByQuery(deleteWrapper));
}
}

View File

@ -0,0 +1,50 @@
package com.mybatisflex.coretest.auth;
import com.mybatisflex.core.dialect.OperateType;
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
import com.mybatisflex.core.query.CPI;
import com.mybatisflex.core.query.QueryTable;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.table.TableInfo;
import java.util.List;
import static com.mybatisflex.core.constant.SqlConsts.AND;
import static com.mybatisflex.core.constant.SqlConsts.EQUALS;
import static com.mybatisflex.coretest.auth.table.ProjectTableDef.PROJECT;
/**
* 权限处理
*/
public class AuthDialectImpl extends CommonsDialectImpl {
@Override
public void prepareAuth(QueryWrapper queryWrapper, OperateType operateType) {
List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper);
if (queryTables == null || queryTables.isEmpty()) {
return;
}
for (QueryTable queryTable : queryTables) {
if (PROJECT.getTableName().equals(queryTable.getName())) {
queryWrapper.and(PROJECT.INSERT_USER_ID.eq(1));
}
}
super.prepareAuth(queryWrapper, operateType);
}
@Override
public void prepareAuth(String schema, String tableName, StringBuilder sql, OperateType operateType) {
if (PROJECT.getTableName().equals(tableName)) {
sql.append(AND).append(wrap("insert_user_id")).append(EQUALS).append(1);
}
super.prepareAuth(schema, tableName, sql, operateType);
}
@Override
public void prepareAuth(TableInfo tableInfo, StringBuilder sql, OperateType operateType) {
if (PROJECT.getTableName().equals(tableInfo.getTableName())) {
sql.append(AND).append(wrap("insert_user_id")).append(EQUALS).append(1);
}
super.prepareAuth(tableInfo, sql, operateType);
}
}

View File

@ -0,0 +1,64 @@
package com.mybatisflex.coretest.auth;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.NoneListener;
import com.mybatisflex.annotation.Table;
/**
* 权限测试类
*
* @author zhang
* @since 2023-12-17
*/
@Table(value = "tb_project", onUpdate = NoneListener.class)
public class Project {
@Id
private Long id;
/**
* 项目名称
*/
private String name;
/**
* 创建人
*/
private String insertUserId;
@Column(isLogicDelete = true)
private Boolean isDelete;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInsertUserId() {
return insertUserId;
}
public void setInsertUserId(String insertUserId) {
this.insertUserId = insertUserId;
}
public Boolean getDelete() {
return isDelete;
}
public void setDelete(Boolean delete) {
isDelete = delete;
}
}