Fix 3.6.5 (#763)

* fix: clearFields N2N

* fix: v3.7 BW 无需修正,值由用户提供

* be: isEnableBizzPart

* be: dbInfo, allowPublicKeyRetrieval

* 3.6.5

* be
This commit is contained in:
REBUILD 企业管理系统 2024-05-22 19:48:47 +08:00 committed by GitHub
parent ba912dcb7a
commit bcdd1e0292
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 172 additions and 38 deletions

View file

@ -10,7 +10,7 @@
</parent>
<groupId>com.rebuild</groupId>
<artifactId>rebuild</artifactId>
<version>3.6.4</version>
<version>3.6.5</version>
<name>rebuild</name>
<description>Building your business-systems freely!</description>
<url>https://getrebuild.com/</url>

View file

@ -74,11 +74,11 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
/**
* Rebuild Version
*/
public static final String VER = "3.6.4";
public static final String VER = "3.6.5";
/**
* Rebuild Build [MAJOR]{1}[MINOR]{2}[PATCH]{2}[BUILD]{2}
*/
public static final int BUILD = 3060409;
public static final int BUILD = 3060510;
static {
// Driver for DB

View file

@ -42,7 +42,7 @@ public class UserFilters {
}
/**
* 是否允许访问
* 指定用户是否允许访问
*
* @param user
* @param bizzId
@ -55,20 +55,32 @@ public class UserFilters {
if (isEnableBizzPart(user)) {
final User ub = Application.getUserStore().getUser(user);
if (bizzId.getEntityCode() == EntityHelper.Department) {
return ub.getOwningDept() != null && bizzId.equals(ub.getOwningDept().getIdentity());
// 本部门及子部门的用户
if (bizzId.getEntityCode() == EntityHelper.User) {
if (user.equals(bizzId)) return true;
if (ub.getOwningDept() == null) return false;
// 可访问部门就是可访问部门下的用户
Department dept = UserHelper.getDepartment(bizzId);
if (dept == null) return false;
bizzId = (ID) dept.getIdentity();
}
// 本部门及子部门
if (bizzId.getEntityCode() == EntityHelper.Department) {
Department dept = ub.getOwningDept();
if (dept == null) return false;
if (bizzId.equals(dept.getIdentity())) return true;
return UserHelper.getAllChildren(dept).contains(bizzId);
}
// 所在团队
if (bizzId.getEntityCode() == EntityHelper.Team) {
for (Team m : ub.getOwningTeams()) {
if (bizzId.equals(m.getIdentity())) return true;
}
return false;
}
if (bizzId.getEntityCode() == EntityHelper.User) {
return user.equals(bizzId);
}
}
return true;

View file

@ -657,6 +657,9 @@ public class AdvFilterParser extends SetUser {
EasyMetaFactory.valueOf(field).getExtraAttr(EasyFieldConfigProps.DATE_FORMAT),
DisplayType.DATE.getDefaultFormat());
// v3.7 BW 无需修正值由用户提供
if (ParseHelper.BW.equals(op)) dateFormat = "0";
if (dateFormat.length() == 4) {
value = value.substring(0, 4) + "-01-01";
} else if (dateFormat.length() == 7) {

View file

@ -233,13 +233,12 @@ public class FieldWriteback extends FieldAggregation {
}
// v3.3 修改/清空时修改前值
// TODO N2N 是否也需要???
boolean clearFields = ((JSONObject) actionContext.getActionContent()).getBooleanValue("clearFields");
if (clearFields) {
Record beforeRecord = operatingContext.getBeforeRecord();
Object beforeValue = beforeRecord == null ? null : beforeRecord.getObjectValue(targetFieldEntity[0]);
if (beforeValue != null && !beforeValue.equals(o)) {
fieldWritebackRefresh = new FieldWritebackRefresh(this, (ID) beforeValue);
fieldWritebackRefresh = new FieldWritebackRefresh(this, beforeValue);
}
}

View file

@ -16,8 +16,9 @@ import com.rebuild.core.privileges.UserService;
import com.rebuild.core.service.general.OperatingContext;
import com.rebuild.core.service.trigger.ActionContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import java.util.Collections;
import java.util.HashSet;
/**
* @author RB
@ -27,9 +28,10 @@ import java.util.Collections;
public class FieldWritebackRefresh {
final private FieldWriteback parent;
final private ID beforeValue;
// ID or ID[]
final private Object beforeValue;
protected FieldWritebackRefresh(FieldWriteback parent, ID beforeValue) {
protected FieldWritebackRefresh(FieldWriteback parent, Object beforeValue) {
this.parent = parent;
this.beforeValue = beforeValue;
}
@ -37,6 +39,7 @@ public class FieldWritebackRefresh {
/**
*/
public void refresh() {
if (beforeValue instanceof ID[] && ((ID[]) beforeValue).length == 0) return;
if (NullValue.isNull(beforeValue)) return;
ID triggerUser = UserService.SYSTEM_USER;
@ -48,7 +51,10 @@ public class FieldWritebackRefresh {
FieldWriteback fa = new FieldWriteback(actionContext);
fa.sourceEntity = parent.sourceEntity;
fa.targetEntity = parent.targetEntity;
fa.targetRecordIds = Collections.singleton(beforeValue);
fa.targetRecordIds = new HashSet<>();
if (beforeValue instanceof ID[]) CollectionUtils.addAll(fa.targetRecordIds, (ID[]) beforeValue);
else fa.targetRecordIds.add((ID) beforeValue);
ID fakeSourceId = EntityHelper.newUnsavedId(fa.sourceEntity.getEntityCode());
Record fakeSourceRecord = EntityHelper.forUpdate(fakeSourceId, triggerUser, false);

View file

@ -0,0 +1,61 @@
/*!
Copyright (c) REBUILD <https://getrebuild.com/> and/or its owners. All rights reserved.
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
See LICENSE and COMMERCIAL in the project root for license information.
*/
package com.rebuild.core.support.setup;
/**
* @author RB
* @since 2024/4/10
*/
public class DbInfo {
final private String desc;
protected DbInfo(String desc) {
this.desc = desc;
}
public boolean isOceanBase() {
return desc.contains("OceanBase");
}
public boolean isH2() {
return desc.contains("H2");
}
public boolean isMySQL56() {
if (isOceanBase()) return false;
return desc.contains("5.6.");
}
public boolean isMySQL80() {
if (isOceanBase()) return false;
return desc.contains("8.0.") || desc.contains("8.1.");
}
/**
* @param L
* @return
*/
protected boolean isIgnoredSqlLine(String L) {
if (isH2()) {
// NOTE `double` 字段也不支持
return L.startsWith("fulltext ") || L.startsWith("unique ") || L.startsWith("index ");
}
if (isOceanBase()) {
return L.startsWith("fulltext ");
}
if (isMySQL56()) {
// FIXME 针对实体注意后续添加
return L.startsWith("index IX0_attachment_folder");
}
return false;
}
}

View file

@ -80,6 +80,11 @@ public class Installer implements InstallState {
private JSONObject installProps;
private DbInfo dbInfo;
// for MySQL8
private boolean allowPublicKeyRetrieval = false;
private String EXISTS_SN;
private Installer() { }
@ -107,6 +112,15 @@ public class Installer implements InstallState {
installProps.put("db.passwd", String.format("AES(%s)", AES.encrypt(dbPasswd)));
}
if (dbInfo.isOceanBase()) {
installProps.put("db.type", "OceanBase");
} else if (dbInfo.isMySQL80()) {
// https://www.cnblogs.com/lusaisai/p/13372763.html
String dbUrl8 = installProps.getProperty("db.url");
if (!dbUrl8.contains("allowPublicKeyRetrieval")) dbUrl8 += "&allowPublicKeyRetrieval=true";
installProps.put("db.url", dbUrl8);
}
// Redis
JSONObject cacheProps = this.installProps.getJSONObject("cacheProps");
if (cacheProps != null && !cacheProps.isEmpty()) {
@ -127,8 +141,8 @@ public class Installer implements InstallState {
try {
FileUtils.deleteQuietly(dest);
try (OutputStream os = Files.newOutputStream(dest.toPath())) {
installProps.store(os, "REBUILD (v2) INSTALLER MAGIC !!! DO NOT EDIT !!!");
log.info("Saved installation file : " + dest);
installProps.store(os, "REBUILD INSTALLER MAGIC !!! DO NOT EDIT !!!");
log.info("Saved installation file : {}", dest);
}
} catch (IOException e) {
@ -211,9 +225,22 @@ public class Installer implements InstallState {
* @throws SQLException
*/
public Connection getConnection(String dbName) throws SQLException {
Properties props = this.buildConnectionProps(dbName);
return DriverManager.getConnection(
props.getProperty("db.url"), props.getProperty("db.user"), props.getProperty("db.passwd"));
Properties props = buildConnectionProps(dbName);
try {
return DriverManager.getConnection(
props.getProperty("db.url"), props.getProperty("db.user"), props.getProperty("db.passwd"));
} catch (SQLException ex) {
// Plugin 'mysql_native_password' is not loaded
allowPublicKeyRetrieval = ex.getMessage().contains("Public Key Retrieval is not allowed");
if (allowPublicKeyRetrieval) {
props = buildConnectionProps(dbName);
return DriverManager.getConnection(
props.getProperty("db.url"), props.getProperty("db.user"), props.getProperty("db.passwd"));
}
throw ex;
}
}
/**
@ -230,7 +257,7 @@ public class Installer implements InstallState {
Properties props = new Properties();
dbName = StringUtils.defaultIfBlank(dbName, "H2DB");
File dbFile = RebuildConfiguration.getFileOfData(dbName);
log.warn("Use H2 database : " + dbFile);
log.warn("Use H2 database : {}", dbFile);
props.put("db.url", String.format("jdbc:h2:file:%s;MODE=MYSQL;DATABASE_TO_LOWER=TRUE;IGNORECASE=TRUE",
dbFile.getAbsolutePath()));
@ -249,7 +276,7 @@ public class Installer implements InstallState {
getTimeZoneId());
// https://www.cnblogs.com/lusaisai/p/13372763.html
// allowPublicKeyRetrieval=true
if (allowPublicKeyRetrieval) dbUrl += "&allowPublicKeyRetrieval=true";
String dbUser = dbProps.getString("dbUser");
String dbPassword = dbProps.getString("dbPassword");
@ -268,6 +295,8 @@ public class Installer implements InstallState {
* @return
*/
protected boolean installDatabase() {
dbInfo = getDbInfo();
// 本身就是 RB 数据库无需创建
if (isRbDatabase()) {
log.warn("Use exists REBUILD database without create");
@ -280,7 +309,7 @@ public class Installer implements InstallState {
try (Connection ignored = getConnection(null)) {
// NOOP
} catch (SQLException e) {
if (!e.getLocalizedMessage().contains("Unknown database")) {
if (!e.getMessage().contains("Unknown database")) {
throw new SetupException(e);
}
@ -290,7 +319,7 @@ public class Installer implements InstallState {
try (Connection conn = getConnection("mysql")) {
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate(createDb);
log.warn("Database created : " + createDb);
log.warn("Database created : {}", createDb);
}
} catch (SQLException sqlex) {
@ -302,13 +331,13 @@ public class Installer implements InstallState {
// 初始化数据库
try (Connection conn = getConnection(null)) {
int affetced = 0;
for (final String sql : getDbInitScript()) {
for (final String s : getDbInitScript()) {
try (Statement stmt = conn.createStatement()) {
stmt.execute(sql);
stmt.execute(s);
affetced++;
}
}
log.info("Schemes of database created : " + affetced);
log.info("Database schemes init : {}", affetced);
} catch (SQLException | IOException e) {
throw new SetupException(e);
@ -317,6 +346,23 @@ public class Installer implements InstallState {
return true;
}
/**
* @return
*/
public DbInfo getDbInfo() {
if (quickMode) return new DbInfo("H2");
try (Connection conn = getConnection("mysql")) {
try (Statement stmt = conn.createStatement()) {
try (ResultSet rs = stmt.executeQuery("select version()")) {
if (rs.next()) return new DbInfo(rs.getString(1));
}
}
} catch (SQLException ignored) {
}
return null;
}
/**
* @return
* @throws IOException
@ -332,13 +378,9 @@ public class Installer implements InstallState {
boolean ignoreTerms = false;
for (Object L : LS) {
String L2 = L.toString().trim();
// NOTE double 字段也不支持
boolean H2Unsupported = quickMode
&& (L2.startsWith("fulltext ") || L2.startsWith("unique ") || L2.startsWith("index "));
// Ignore comments and line of blank
if (StringUtils.isEmpty(L2) || L2.startsWith("--") || H2Unsupported) {
// IGNORED
if (StringUtils.isEmpty(L2) || L2.startsWith("--")
|| (dbInfo != null && dbInfo.isIgnoredSqlLine(L2))) {
continue;
}
if (L2.startsWith("/*") || L2.endsWith("*/")) {
@ -396,7 +438,7 @@ public class Installer implements InstallState {
}
} catch (SQLException sqlex) {
log.error("Cannot execute SQL : " + sql, sqlex);
log.error("Cannot execute SQL : {}", sql, sqlex);
}
}
@ -476,12 +518,13 @@ public class Installer implements InstallState {
EXISTS_SN = value;
}
}
return true;
}
}
} catch (SQLException ex) {
log.error("Check REBUILD database error : " + ex.getLocalizedMessage());
log.info("Check REBUILD database error : {}", ex.getLocalizedMessage());
}
return false;
}
@ -519,6 +562,16 @@ public class Installer implements InstallState {
return dbUrl != null && dbUrl.startsWith("jdbc:h2:");
}
/**
* 是否 OceanBase 数据库
*
* @return
*/
public static boolean isUseOceanBase() {
String dbType = BootEnvironmentPostProcessor.getProperty("db.type");
return dbType != null && dbType.contains("OceanBase");
}
/**
* @return
*/

View file

@ -102,7 +102,7 @@ public class InstallController extends BaseController implements InstallState {
return RespBody.ok(okMsg);
} catch (SQLException ex) {
if (ex.getLocalizedMessage().contains("Unknown database")) {
if (ex.getMessage().contains("Unknown database")) {
String okMsg = Language.L("连接成功 : 数据库 **%s** 不存在,系统将自动创建", dbProps.getString("dbName"));
return RespBody.ok(okMsg);
} else {