Fix 4.1.5 (#948)

* Improve entity creation checks and logging

* Update @rbv

* 4.1.5

* BOOTING_TIME415


* Add includeHide parameter to picklist and multiselect methods
This commit is contained in:
REBUILD 企业管理系统 2025-08-23 14:09:12 +08:00 committed by GitHub
parent 256a977e3b
commit 7bbee82e13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 59 additions and 23 deletions

2
@rbv

@ -1 +1 @@
Subproject commit 41eb5c36ae11dd4703a5969a3feef93dd25409d7
Subproject commit d938751dea6125086bec9ea09bc95e9430475da6

View file

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

View file

@ -76,11 +76,11 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
/**
* Rebuild Version
*/
public static final String VER = "4.1.4";
public static final String VER = "4.1.5";
/**
* Rebuild Build [MAJOR]{1}[MINOR]{2}[PATCH]{2}[BUILD]{2}
*/
public static final int BUILD = 4010409;
public static final int BUILD = 4010510;
static {
// Driver for DB
@ -129,7 +129,7 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
_CONTEXT = event.getApplicationContext();
long time = System.currentTimeMillis();
long time = BootApplication.BOOTING_TIME415;
boolean started = false;
final Timer timer = new Timer("Boot-Timer");

View file

@ -62,6 +62,7 @@ public class BootApplication extends SpringBootServletInitializer {
private static String CONTEXT_PATH;
private static String TOMCAT_PORT;
protected static long BOOTING_TIME415 = System.currentTimeMillis();
/**
* 获取上下文地址注意此地址尾部不含 `/`
@ -107,6 +108,7 @@ public class BootApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
log.info("REBUILD starting ...");
BOOTING_TIME415 = System.currentTimeMillis();
if (devMode()) System.setProperty("spring.profiles.active", "dev");
// kill -15 `cat ~/.rebuild/rebuild.pid`
@ -123,6 +125,7 @@ public class BootApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
log.info("REBUILD starting ...");
BOOTING_TIME415 = System.currentTimeMillis();
if (SystemUtils.IS_OS_WINDOWS) AnsiConsole.systemInstall();
if (devMode()) System.setProperty("spring.profiles.active", "dev");

View file

@ -497,14 +497,14 @@ public class FormsBuilder extends FormsManager {
// 不同字段类型的处理
if (dt == DisplayType.PICKLIST) {
JSONArray options = PickListManager.instance.getPickList(fieldMeta);
JSONArray options = PickListManager.instance.getPickList(fieldMeta, true);
field.put("options", options);
} else if (dt == DisplayType.STATE) {
JSONArray options = StateManager.instance.getStateOptions(fieldMeta);
field.put("options", options);
field.remove(EasyFieldConfigProps.STATE_CLASS);
} else if (dt == DisplayType.MULTISELECT) {
JSONArray options = MultiSelectManager.instance.getSelectList(fieldMeta);
JSONArray options = MultiSelectManager.instance.getSelectList(fieldMeta, true);
field.put("options", options);
} else if (dt == DisplayType.TAG) {
field.put("options", ObjectUtils.defaultIfNull(field.remove("tagList"), JSONUtils.EMPTY_ARRAY));
@ -525,7 +525,7 @@ public class FormsBuilder extends FormsManager {
} else if (dt == DisplayType.REFERENCE || dt == DisplayType.N2NREFERENCE) {
Entity refEntity = fieldMeta.getReferenceEntity();
boolean quickNew = field.getBooleanValue(EasyFieldConfigProps.REFERENCE_QUICKNEW);
if (quickNew) {
if (quickNew && refEntity.isCreatable() && refEntity.getMainEntity() == null) {
field.put(EasyFieldConfigProps.REFERENCE_QUICKNEW,
Application.getPrivilegesManager().allowCreate(user, refEntity.getEntityCode()));
field.put("referenceEntity", EasyMetaFactory.toJSON(refEntity));

View file

@ -27,15 +27,23 @@ public class MultiSelectManager extends PickListManager {
public static final MultiSelectManager instance = new MultiSelectManager();
private MultiSelectManager() {
}
private MultiSelectManager() {}
/**
* @param field
* @return
*/
public JSONArray getSelectList(Field field) {
ConfigBean[] entries = getPickListRaw(field, true);
return getSelectList(field, false);
}
/**
* @param field
* @param includeHide
* @return
*/
public JSONArray getSelectList(Field field, boolean includeHide) {
ConfigBean[] entries = getPickListRaw(field, includeHide);
for (ConfigBean e : entries) {
e.remove("id");
}

View file

@ -30,14 +30,23 @@ public class PickListManager implements ConfigManager {
public static final PickListManager instance = new PickListManager();
protected PickListManager() { }
protected PickListManager() {}
/**
* @param field
* @return
*/
public JSONArray getPickList(Field field) {
ConfigBean[] entries = getPickListRaw(field, true);
return getPickList(field, false);
}
/**
* @param field
* @param includeHide
* @return
*/
public JSONArray getPickList(Field field, boolean includeHide) {
ConfigBean[] entries = getPickListRaw(field, includeHide);
for (ConfigBean e : entries) {
e.remove("mask");
}

View file

@ -31,6 +31,7 @@ import com.rebuild.core.privileges.bizz.User;
import com.rebuild.core.privileges.bizz.ZeroEntry;
import com.rebuild.core.privileges.bizz.ZeroPrivileges;
import com.rebuild.core.service.NoRecordFoundException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
@ -45,6 +46,7 @@ import java.text.MessageFormat;
* @see BizzDepthEntry
* @see CustomEntityPrivileges
*/
@Slf4j
@Service
public class PrivilegesManager {
@ -243,7 +245,8 @@ public class PrivilegesManager {
// 明细实体不能使用此方法检查创建权限
// 明细实体创建 = 主实体更新因此应该检查主实体记录是否有更新权限
if (action == BizzPermission.CREATE) {
throw new PrivilegesException("Unsupported checks detail-entity : " + entity);
log.warn("Unsupported checks detail-entity : {}", entity);
return false; // be:4.1.5
}
// 明细无分配/共享
else if (action == BizzPermission.ASSIGN || action == BizzPermission.SHARE) {

View file

@ -17,6 +17,8 @@ import cn.devezhao.persist4j.engine.ID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import java.io.Serializable;
@ -129,17 +131,25 @@ public class CombinedRole extends Role {
if (p instanceof ZeroPrivileges) continue;
System.out.println();
System.out.println("Combined Privileges : " + p.getIdentity());
System.out.println("MAIN. " + roleMain.getPrivileges(p.getIdentity()));
System.out.println("MAIN. " + descPrivileges(roleMain.getPrivileges(p.getIdentity())));
for (Role ra : roleAppends) {
System.out.println("APPE. " + ra.getPrivileges(p.getIdentity()));
System.out.println("APPE. " + descPrivileges(ra.getPrivileges(p.getIdentity())));
}
System.out.println("--");
System.out.println("MERG. " + getPrivileges(p.getIdentity()));
System.out.println("MERG. " + descPrivileges(getPrivileges(p.getIdentity())));
}
System.out.println();
}
}
private String descPrivileges(Privileges p) {
String d = p.getIdentity().toString();
if (p instanceof CustomEntityPrivileges) {
d += "; FP:" + ObjectUtils.defaultIfNull(((CustomEntityPrivileges) p).getFpDefinition(), "N");
}
return d;
}
private Privileges mergePrivileges(Privileges a, Privileges b) {
if (b == null || b == Privileges.NONE) return a;
if (b == Privileges.ROOT) return b;
@ -191,11 +201,12 @@ public class CombinedRole extends Role {
// 字段权限
Map<String, Object> useFpDefinition;
Map<String, Object> aFpDefinition = ((CustomEntityPrivileges) a).getFpDefinition();
Map<String, Object> bFpDefinition = ((CustomEntityPrivileges) b).getFpDefinition();
if (aFpDefinition == null || bFpDefinition == null) useFpDefinition = null;
else useFpDefinition = aFpDefinition; // 无法比较字段权限高低因此随便选一个
// be:4.1.5 无法比较字段权限高低因此随便选一个非空的更合理
Map<String, Object> useFpDefinition = null;
if (MapUtils.isEmpty(aFpDefinition)) useFpDefinition = bFpDefinition;
else if (MapUtils.isEmpty(bFpDefinition)) useFpDefinition = aFpDefinition;
String definition = StringUtils.join(defs.iterator(), ",");
return new CustomEntityPrivileges(((EntityPrivileges) a).getEntity(), definition, useCustomFilters, useFpDefinition);

View file

@ -97,7 +97,7 @@ public class ProtectedAdmin {
EXF("/extform", "外部表单"),
PRO("/project", "项目"),
FJS("/frontjs-code", "FrontJS"),
USR("/bizuser/users;bizuser/departments", "部门用户"),
USR("/bizuser/users;/bizuser/departments", "部门用户"),
ROL("/bizuser/role-privileges;/bizuser/role", "角色权限"),
TEM("/bizuser/teams", "团队"),
LLG("/audit/login-logs", "登录日志"),

View file

@ -53,7 +53,7 @@
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="create*" no-rollback-for="DataSpecificationNoRollbackException,RepeatedRecordsException"/>
<tx:method name="create*" no-rollback-for="DataSpecificationNoRollbackException"/>
<tx:method name="update*" no-rollback-for="DataSpecificationNoRollbackException"/>
<tx:method name="delete*" no-rollback-for="DataSpecificationNoRollbackException"/>
<tx:method name="assign*" no-rollback-for="DataSpecificationNoRollbackException"/>

View file

@ -1171,7 +1171,9 @@ class Md2Html extends React.Component {
md = md.replace(/>/g, '&gt;').replace(/</g, '&lt;')
md = md.replace(/&gt; /g, '> ')
}
let cHtml = marked.parse(md.replace(/\n/g, '<br/>'))
// 替换换行并保持表格换行
let cHtml = marked.parse(md.replace(/(?<!\|)\n(?!\|)/g, '\n\n'))
cHtml = cHtml.replace(/<img src="([^"]+)"/g, function (s, src) {
let srcNew = src + (src.includes('?') ? '&' : '?') + 'imageView2/2/w/1000/interlace/1/q/100'
return s.replace(src, srcNew)