forked from p85126437/datagear
解决系统切换部署数据库兼容性问题:PostgreSQL权限查询SQL语句报错、MySQL授权不起作用
This commit is contained in:
parent
161777634b
commit
36eecab78e
|
@ -752,32 +752,6 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
|
|||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义为SQL字符串值。
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
protected String escapeForSqlStringValue(String s)
|
||||
{
|
||||
if (s == null)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0, len = s.length(); i < len; i++)
|
||||
{
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == '\'')
|
||||
sb.append("''");
|
||||
else
|
||||
sb.append(c);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取sql语句的名字空间。
|
||||
*
|
||||
|
|
|
@ -113,14 +113,16 @@ public class AuthorizationServiceImpl extends AbstractMybatisDataPermissionEntit
|
|||
if (user.isAdmin())
|
||||
return Authorization.PERMISSION_MAX;
|
||||
|
||||
MbSqlDialect dialect = getDialect();
|
||||
|
||||
int unsetPermission = -9;
|
||||
|
||||
Map<String, Object> params = buildParamMap();
|
||||
addDataPermissionParameters(params, user, resourceType, true, false);
|
||||
params.put(DATA_PERMISSION_PARAM_UNSET_PERMISSION, unsetPermission);
|
||||
|
||||
params.put("placeholderId", IDUtil.uuid());
|
||||
params.put("patternSource", escapeForSqlStringValue(patternSource));
|
||||
params.put("placeholderId", dialect.toStringLiteral(IDUtil.uuid()));
|
||||
params.put("patternSource", dialect.toStringLiteral(patternSource));
|
||||
|
||||
List<DataIdPermission> dataIdPermissions = selectListMybatis("getDataIdPermissionForPatternSource", params);
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*/
|
||||
|
||||
package org.datagear.management.util;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.ibatis.type.BooleanTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
/**
|
||||
* 使用字面值{@code 'true'}或{@code 'false'}存储{@linkplain Boolean}类型的MyBatis类型映射器。
|
||||
* <p>
|
||||
* {@linkplain BooleanTypeHandler}的{@linkplain #setNonNullParameter(PreparedStatement, int, Boolean, JdbcType)}
|
||||
* 使用的是{@linkplain PreparedStatement#setBoolean(int, boolean)},对于不同数据库的驱动程序,当数据库列类型为VARCHAR时,
|
||||
* 存储的值可能为{@code 'true'}和{@code 'false'},也可能为{@code '1'}和{@code '0'},
|
||||
* 对于某些需要根据此列值进行判断处理的SQL语句,会出现数据库切换兼容问题。
|
||||
* </p>
|
||||
* <p>
|
||||
* 所以,这里定义此类,将{@linkplain Boolean}类型统一存储为{@code 'true'}和{@code 'false'}(要求数据库列类型为:VARCHAR)。
|
||||
* </p>
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class LiteralBooleanTypeHandler extends BooleanTypeHandler
|
||||
{
|
||||
public LiteralBooleanTypeHandler()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType)
|
||||
throws SQLException
|
||||
{
|
||||
String value = (Boolean.TRUE.equals(parameter) ? "true" : "false");
|
||||
ps.setString(i, value);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ import org.datagear.management.service.impl.AbstractMybatisService;
|
|||
* 此类仅用于为{@linkplain AbstractMybatisService}及其实现类提供多数据库部署支持。
|
||||
* </p>
|
||||
* <p>
|
||||
* 基本思路是:根据当前部署数据库,生成底层Mybatis所需的数据库方言SQL片段,然后以参数的方式传入底层SQL
|
||||
* 对于分页,基本思路是:根据当前部署数据库,生成底层Mybatis所需的数据库方言SQL片段,然后以参数的方式传入底层SQL
|
||||
* Mapper语境,组装成合规的SQL语句。
|
||||
* </p>
|
||||
*
|
||||
|
@ -47,6 +47,39 @@ public abstract class MbSqlDialect
|
|||
this.identifierQuote = identifierQuote;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换为SQL字符串字面值。
|
||||
* <p>
|
||||
* 例如:{@code "abc'def"}应转换为{@code "'abc''def'"}
|
||||
* </p>
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public String toStringLiteral(String value)
|
||||
{
|
||||
if (value == null)
|
||||
return "NULL";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append('\'');
|
||||
|
||||
for (int i = 0, len = value.length(); i < len; i++)
|
||||
{
|
||||
char c = value.charAt(i);
|
||||
|
||||
if (c == '\'')
|
||||
sb.append("''");
|
||||
else
|
||||
sb.append(c);
|
||||
}
|
||||
|
||||
sb.append('\'');
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持分页查询。
|
||||
*
|
||||
|
|
|
@ -31,6 +31,23 @@ public class PostgresqlMbSqlDialect extends MbSqlDialect
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringLiteral(String value)
|
||||
{
|
||||
String literal = super.toStringLiteral(value);
|
||||
|
||||
// PostgreSQL对于
|
||||
// SELECT 'abc' AS STR_LITERAL
|
||||
// 格式的SQL语句,查询结果中STR_LITERAL是unknown类型,这会导致如下类似查询语句
|
||||
// SELECT * FROM (SELECT 'abc' AS STR_LITERAL) A INNER JOIN SOME_TABLE B
|
||||
// ON A.STR_LITERAL = B.SOME_VARCHAR_COLUMN
|
||||
// 报
|
||||
// failed to find conversion function from unknown to text
|
||||
// 错误,无法执行,在末尾添加::text进行类型转换可解决。
|
||||
|
||||
return literal + "::text";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pagingSqlHead(int index, int fetchSize)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
VALUES
|
||||
(
|
||||
#{entity.id}, #{entity.resource}, #{entity.resourceType}, #{entity.principal}, #{entity.principalType},
|
||||
#{entity.permission}, #{entity.enabled},#{entity.createUser.id}
|
||||
#{entity.permission}, #{entity.enabled, jdbcType=VARCHAR},#{entity.createUser.id}
|
||||
)
|
||||
</insert>
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
|||
AUTH_PRINCIPAL = #{entity.principal},
|
||||
AUTH_PRINCIPAL_TYPE = #{entity.principalType},
|
||||
AUTH_PERMISSION = #{entity.permission},
|
||||
AUTH_ENABLED = #{entity.enabled}
|
||||
AUTH_ENABLED = #{entity.enabled, jdbcType=VARCHAR}
|
||||
WHERE
|
||||
AUTH_ID = #{entity.id}
|
||||
</update>
|
||||
|
@ -75,8 +75,8 @@
|
|||
(
|
||||
<include refid="commonDataPermission.dataIdPermissionQueryViewHead" />
|
||||
SELECT
|
||||
'${placeholderId}' AS DP_AUTH_DATA_ID,
|
||||
'${patternSource}' AS DP_AUTH_DATA_PATTERN_SRC,
|
||||
${placeholderId} AS DP_AUTH_DATA_ID,
|
||||
${patternSource} AS DP_AUTH_DATA_PATTERN_SRC,
|
||||
PLACEHOLDER_TABLE.PLACEHOLDER_COL
|
||||
FROM
|
||||
/*Derby没有类似from dual的语法,为了兼容其它数据库,这里采用了此种方法*/
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
)
|
||||
VALUES
|
||||
(
|
||||
#{entity.id}, #{entity.name}, #{entity.description}, #{entity.enabled}
|
||||
#{entity.id}, #{entity.name}, #{entity.description}, #{entity.enabled, jdbcType=VARCHAR}
|
||||
)
|
||||
</insert>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
|||
UPDATE DATAGEAR_ROLE SET
|
||||
ROLE_NAME = #{entity.name},
|
||||
ROLE_DESCRIPTION = #{entity.description},
|
||||
ROLE_ENABLED = #{entity.enabled}
|
||||
ROLE_ENABLED = #{entity.enabled, jdbcType=VARCHAR}
|
||||
WHERE
|
||||
ROLE_ID = #{entity.id}
|
||||
</update>
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
<insert id="insert">
|
||||
INSERT INTO DATAGEAR_USER
|
||||
(
|
||||
USER_ID, USER_NAME, USER_PASSWORD, USER_REAL_NAME, USER_EMAIL, USER_IS_ADMIN, USER_CREATE_TIME
|
||||
USER_ID, USER_NAME, USER_PASSWORD, USER_REAL_NAME, USER_EMAIL,
|
||||
USER_IS_ADMIN, USER_CREATE_TIME
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
#{entity.id}, #{entity.name}, #{entity.password}, #{entity.realName}, #{entity.email}, #{entity.admin}, #{entity.createTime}
|
||||
#{entity.id}, #{entity.name}, #{entity.password}, #{entity.realName}, #{entity.email},
|
||||
#{entity.admin, jdbcType=VARCHAR}, #{entity.createTime}
|
||||
)
|
||||
</insert>
|
||||
|
||||
|
@ -22,7 +24,7 @@
|
|||
</if>
|
||||
USER_REAL_NAME = #{entity.realName},
|
||||
USER_EMAIL = #{entity.email},
|
||||
USER_IS_ADMIN = #{entity.admin}
|
||||
USER_IS_ADMIN = #{entity.admin, jdbcType=VARCHAR}
|
||||
WHERE
|
||||
USER_ID = #{entity.id}
|
||||
</update>
|
||||
|
|
|
@ -91,59 +91,54 @@
|
|||
-->
|
||||
<sql id="userOnResourceTypePermissionQueryView">
|
||||
SELECT
|
||||
DG_AUTH.AUTH_RESOURCE,
|
||||
DG_AUTH.AUTH_RESOURCE_TYPE,
|
||||
AUTH.AUTH_RESOURCE,
|
||||
AUTH.AUTH_RESOURCE_TYPE,
|
||||
(
|
||||
/*最高级权限值加权,管理员授权始终高于普通用户授权*/
|
||||
CASE DG_AUTH.CREATOR_IS_ADMIN
|
||||
CASE USR.USER_IS_ADMIN
|
||||
WHEN 'true' THEN
|
||||
CASE DG_AUTH.AUTH_PRINCIPAL_TYPE
|
||||
WHEN 'ALL' THEN (5000000 + DG_AUTH.AUTH_PERMISSION)
|
||||
WHEN 'ANONYMOUS' THEN (6000000 + DG_AUTH.AUTH_PERMISSION)
|
||||
WHEN 'ROLE' THEN (7000000 + DG_AUTH.AUTH_PERMISSION)
|
||||
WHEN 'USER' THEN (8000000 + DG_AUTH.AUTH_PERMISSION)
|
||||
CASE AUTH.AUTH_PRINCIPAL_TYPE
|
||||
WHEN 'ALL' THEN (5000000 + AUTH.AUTH_PERMISSION)
|
||||
WHEN 'ANONYMOUS' THEN (6000000 + AUTH.AUTH_PERMISSION)
|
||||
WHEN 'ROLE' THEN (7000000 + AUTH.AUTH_PERMISSION)
|
||||
WHEN 'USER' THEN (8000000 + AUTH.AUTH_PERMISSION)
|
||||
ELSE 0
|
||||
END
|
||||
ELSE
|
||||
CASE DG_AUTH.AUTH_PRINCIPAL_TYPE
|
||||
WHEN 'ALL' THEN (1000000 + DG_AUTH.AUTH_PERMISSION)
|
||||
WHEN 'ANONYMOUS' THEN (2000000 + DG_AUTH.AUTH_PERMISSION)
|
||||
WHEN 'ROLE' THEN (3000000 + DG_AUTH.AUTH_PERMISSION)
|
||||
WHEN 'USER' THEN (4000000 + DG_AUTH.AUTH_PERMISSION)
|
||||
CASE AUTH.AUTH_PRINCIPAL_TYPE
|
||||
WHEN 'ALL' THEN (1000000 + AUTH.AUTH_PERMISSION)
|
||||
WHEN 'ANONYMOUS' THEN (2000000 + AUTH.AUTH_PERMISSION)
|
||||
WHEN 'ROLE' THEN (3000000 + AUTH.AUTH_PERMISSION)
|
||||
WHEN 'USER' THEN (4000000 + AUTH.AUTH_PERMISSION)
|
||||
ELSE 0
|
||||
END
|
||||
END
|
||||
) AS AUTH_PRIORITY_PERMISSION
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
A.*,
|
||||
U.USER_IS_ADMIN AS CREATOR_IS_ADMIN
|
||||
FROM
|
||||
DATAGEAR_AUTHORIZATION A,
|
||||
DATAGEAR_USER U
|
||||
WHERE
|
||||
A.AUTH_CREATE_USER_ID = U.USER_ID
|
||||
) DG_AUTH
|
||||
DATAGEAR_AUTHORIZATION AUTH
|
||||
INNER JOIN
|
||||
DATAGEAR_USER USR
|
||||
ON
|
||||
AUTH.AUTH_CREATE_USER_ID = USR.USER_ID
|
||||
WHERE
|
||||
DG_AUTH.AUTH_ENABLED = 'true'
|
||||
AUTH.AUTH_ENABLED = 'true'
|
||||
AND
|
||||
(
|
||||
DG_AUTH.AUTH_RESOURCE_TYPE = '${DP_RESOURCE_TYPE}'
|
||||
AUTH.AUTH_RESOURCE_TYPE = '${DP_RESOURCE_TYPE}'
|
||||
<if test='DP_RESOURCE_SUPPORT_PATTERN != null and DP_RESOURCE_SUPPORT_PATTERN == true'>
|
||||
OR DG_AUTH.AUTH_RESOURCE_TYPE = '${DP_RESOURCE_TYPE}_PATTERN'
|
||||
OR AUTH.AUTH_RESOURCE_TYPE = '${DP_RESOURCE_TYPE}_PATTERN'
|
||||
</if>
|
||||
)
|
||||
AND
|
||||
(
|
||||
DG_AUTH.AUTH_PRINCIPAL_TYPE = 'ALL'
|
||||
AUTH.AUTH_PRINCIPAL_TYPE = 'ALL'
|
||||
<choose><when test="DP_CURRENT_USER.anonymous == true">
|
||||
OR DG_AUTH.AUTH_PRINCIPAL_TYPE = 'ANONYMOUS'
|
||||
OR AUTH.AUTH_PRINCIPAL_TYPE = 'ANONYMOUS'
|
||||
</when><otherwise>
|
||||
OR
|
||||
(
|
||||
DG_AUTH.AUTH_PRINCIPAL_TYPE = 'ROLE'
|
||||
AND DG_AUTH.AUTH_PRINCIPAL IN
|
||||
AUTH.AUTH_PRINCIPAL_TYPE = 'ROLE'
|
||||
AND AUTH.AUTH_PRINCIPAL IN
|
||||
(
|
||||
SELECT
|
||||
RO.ROLE_ID
|
||||
|
@ -157,7 +152,7 @@
|
|||
RU.RU_USER_ID = '${DP_CURRENT_USER.id}' AND RO.ROLE_ENABLED = 'true'
|
||||
)
|
||||
)
|
||||
OR (DG_AUTH.AUTH_PRINCIPAL_TYPE = 'USER' AND DG_AUTH.AUTH_PRINCIPAL = '${DP_CURRENT_USER.id}')
|
||||
OR (AUTH.AUTH_PRINCIPAL_TYPE = 'USER' AND AUTH.AUTH_PRINCIPAL = '${DP_CURRENT_USER.id}')
|
||||
</otherwise></choose>
|
||||
)
|
||||
</sql>
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.util.List;
|
|||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.datagear.analysis.TemplateDashboardWidgetResManager;
|
||||
import org.datagear.analysis.support.FileTemplateDashboardWidgetResManager;
|
||||
import org.datagear.analysis.support.NameAsTemplateDashboardWidgetResManager;
|
||||
|
@ -70,6 +71,7 @@ import org.datagear.management.service.impl.SchemaServiceImpl;
|
|||
import org.datagear.management.service.impl.SqlHistoryServiceImpl;
|
||||
import org.datagear.management.service.impl.UserPasswordEncoder;
|
||||
import org.datagear.management.service.impl.UserServiceImpl;
|
||||
import org.datagear.management.util.LiteralBooleanTypeHandler;
|
||||
import org.datagear.management.util.dialect.MbSqlDialect;
|
||||
import org.datagear.management.util.dialect.MbSqlDialectBuilder;
|
||||
import org.datagear.meta.resolver.DBMetaResolver;
|
||||
|
@ -325,6 +327,7 @@ public class CoreConfig implements InitializingBean
|
|||
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
|
||||
bean.setDataSource(this.dataSourceConfig.dataSource());
|
||||
bean.setMapperLocations(mapperResources);
|
||||
bean.setTypeHandlers(new TypeHandler<?>[] { new LiteralBooleanTypeHandler() });
|
||||
return bean.getObject();
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
Loading…
Reference in New Issue