api: metadatas

This commit is contained in:
oahzeved 2020-05-14 16:48:35 +08:00
parent b2a2c213ed
commit c09818a7a8
25 changed files with 465 additions and 206 deletions

View file

@ -127,7 +127,7 @@
<dependency>
<groupId>com.github.devezhao</groupId>
<artifactId>persist4j</artifactId>
<version>3aa38dabbd</version>
<version>1beaf8f565</version>
</dependency>
<dependency>
<groupId>junit</groupId>

View file

@ -0,0 +1,97 @@
/*
Copyright (c) REBUILD <https://getrebuild.com/> and 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.api.metadata;
import cn.devezhao.persist4j.Field;
import cn.devezhao.persist4j.engine.ID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.api.ApiContext;
import com.rebuild.api.ApiInvokeException;
import com.rebuild.api.BaseApi;
import com.rebuild.server.Application;
import com.rebuild.server.configuration.portals.ClassificationManager;
import com.rebuild.server.metadata.MetadataHelper;
import com.rebuild.server.metadata.entity.DisplayType;
import com.rebuild.server.metadata.entity.EasyMeta;
import com.rebuild.utils.JSONUtils;
/**
* 分类数据
*
* @author devezhao
* @since 2020/5/14
*/
public class ClassificationData extends BaseApi {
private ID dataId;
private int openLevel;
@Override
protected String getApiName() {
return "metadata/classification-data";
}
@Override
public JSON execute(ApiContext context) throws ApiInvokeException {
String entity = context.getParameterNotBlank("entity");
String field = context.getParameterNotBlank("field");
Field thatField = MetadataHelper.getField(entity, field);
if (EasyMeta.getDisplayType(thatField) != DisplayType.CLASSIFICATION) {
return formatFailure("None CLASSIFICATION field : " + entity + "." + field);
}
dataId = ClassificationManager.instance.getUseClassification(thatField, true);
if (dataId == null) {
return formatFailure("Bad CLASSIFICATION field : " + entity + "." + field);
}
openLevel = ClassificationManager.instance.getOpenLevel(thatField);
Object[][] array = Application.createQueryNoFilter(
"select itemId,name from ClassificationData where level = 0 and dataId = ?")
.setParameter(1, dataId)
.array();
JSONArray dest = new JSONArray();
for (Object[] o : array) {
JSONObject item = buildItem(o);
appendChildren((ID) o[0], item, 1);
dest.add(item);
}
return formatSuccess(dest);
}
private void appendChildren(ID itemId, JSONObject into, int level) {
if (level > openLevel) {
return;
}
Object[][] array = Application.createQueryNoFilter(
"select itemId,name from ClassificationData where dataId = ? and parent = ?")
.setParameter(1, dataId)
.setParameter(2, itemId)
.array();
JSONArray children = new JSONArray();
for (Object[] o : array) {
JSONObject item = buildItem(o);
appendChildren((ID) o[0], item, level + 1);
children.add(item);
}
into.put("children", children);
}
private JSONObject buildItem(Object[] o) {
return JSONUtils.toJSONObject(
new String[] { "id", "text" },
new Object[] { o[0], o[1] });
}
}

View file

@ -0,0 +1,61 @@
/*
Copyright (c) REBUILD <https://getrebuild.com/> and 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.api.metadata;
import cn.devezhao.persist4j.Entity;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.api.ApiContext;
import com.rebuild.api.ApiInvokeException;
import com.rebuild.api.BaseApi;
import com.rebuild.server.metadata.MetadataSorter;
import com.rebuild.server.metadata.entity.EasyMeta;
/**
* 获取实体列表
*
* @author devezhao
* @since 2020/5/14
*/
public class EntityList extends BaseApi {
@Override
protected String getApiName() {
return "metadata/entities";
}
@Override
public JSON execute(ApiContext context) throws ApiInvokeException {
JSONArray array = new JSONArray();
for (Entity e : MetadataSorter.sortEntities()) {
array.add(buildEntity(e));
}
return formatSuccess(array);
}
private JSONObject buildEntity(Entity entity) {
JSONObject o = new JSONObject();
o.put("type_code", entity.getEntityCode());
o.put("entity_name", entity.getName());
o.put("entity_label", EasyMeta.getLabel(entity));
o.put("creatable", entity.isCreatable());
o.put("updatable", entity.isUpdatable());
o.put("queryable", entity.isQueryable());
o.put("deletable", entity.isDeletable());
if (entity.getMasterEntity() != null) {
o.put("master_entity", entity.getMasterEntity().getName());
}
if (entity.getSlaveEntity() != null) {
o.put("slave_entity", entity.getSlaveEntity().getName());
}
return o;
}
}

View file

@ -0,0 +1,83 @@
/*
Copyright (c) REBUILD <https://getrebuild.com/> and 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.api.metadata;
import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.api.ApiContext;
import com.rebuild.api.ApiInvokeException;
import com.rebuild.api.BaseApi;
import com.rebuild.server.configuration.portals.ClassificationManager;
import com.rebuild.server.configuration.portals.MultiSelectManager;
import com.rebuild.server.configuration.portals.PickListManager;
import com.rebuild.server.metadata.MetadataHelper;
import com.rebuild.server.metadata.entity.DisplayType;
import com.rebuild.server.metadata.entity.EasyMeta;
/**
* 获取字段列表
*
* @author devezhao
* @since 2020/5/14
*/
public class FieldList extends BaseApi {
@Override
protected String getApiName() {
return "metadata/fields";
}
@Override
public JSON execute(ApiContext context) throws ApiInvokeException {
String entity = context.getParameterNotBlank("entity");
Entity thatEntity = MetadataHelper.getEntity(entity);
JSONArray array = new JSONArray();
for (Field field : thatEntity.getFields()) {
if (MetadataHelper.isSystemField(field) || !field.isQueryable()) {
continue;
}
array.add(buildField(field));
}
return formatSuccess(array);
}
private JSONObject buildField(Field field) {
final EasyMeta easyMeta = EasyMeta.valueOf(field);
final DisplayType dt = easyMeta.getDisplayType();
JSONObject o = new JSONObject();
o.put("field_name", field.getName());
o.put("field_label", easyMeta.getLabel());
o.put("display_type", dt.name());
o.put("creatable", field.isCreatable());
o.put("updatable", field.isUpdatable());
o.put("nullable", field.isNullable());
o.put("repeatable", field.isRepeatable());
o.put("queryable", field.isQueryable());
if (dt == DisplayType.REFERENCE) {
o.put("reference_entity", field.getReferenceEntity().getName());
}
if (dt == DisplayType.CLASSIFICATION) {
o.put("use_classification", ClassificationManager.instance.getUseClassification(field, true));
}
if (dt == DisplayType.MULTISELECT) {
o.put("options", MultiSelectManager.instance.getSelectList(field));
}
if (dt == DisplayType.PICKLIST) {
o.put("options", PickListManager.instance.getPickList(field));
}
return o;
}
}

View file

@ -64,7 +64,7 @@ public class FieldPortalAttrs {
* @return
*/
public boolean allowDataList(Field field) {
return !disallowAll(field) && !isPasswd(field);
return !disallowAll(field) && field.isQueryable();
}
/**
@ -72,7 +72,7 @@ public class FieldPortalAttrs {
* @return
*/
public boolean allowSearch(Field field) {
return !disallowAll(field) && !isPasswd(field);
return !disallowAll(field) && field.isQueryable();
}
/**
@ -84,13 +84,4 @@ public class FieldPortalAttrs {
return field.getType() == FieldType.ANY_REFERENCE
|| EntityHelper.ApprovalStepNode.equalsIgnoreCase(fieldName);
}
/**
* @param field
* @return
*/
private boolean isPasswd(Field field) {
String fieldName = field.getName();
return fieldName.contains("password") || fieldName.contains("passwd");
}
}

View file

@ -280,21 +280,19 @@ public class FieldValueWrapper {
* @return
*/
protected Object wrapSpecialField(Object value, EasyMeta field) {
String fieldName = field.getName().toLowerCase();
// 密码型字段返回
if (fieldName.contains("password") || fieldName.contains("passwd")) {
if (!field.isQueryable()) {
return "******";
}
// 审批
if (fieldName.equalsIgnoreCase(EntityHelper.ApprovalState)) {
if (field.getName().equalsIgnoreCase(EntityHelper.ApprovalState)) {
if (value == null) {
return ApprovalState.DRAFT.getName();
} else {
return ApprovalState.valueOf((Integer) value).getName();
}
} else if (fieldName.equalsIgnoreCase(EntityHelper.ApprovalId) && value == null) {
} else if (field.getName().equalsIgnoreCase(EntityHelper.ApprovalId) && value == null) {
return wrapMixValue(null, APPROVAL_UNSUBMITTED);
}

View file

@ -39,7 +39,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
@ -242,9 +241,9 @@ public class FormsBuilder extends FormsManager {
ID masterRecordId = MASTERID4NEWSLAVE.get();
if (masterRecordId == null) {
Field stm = MetadataHelper.getSlaveToMasterField(entity);
Field stmField = MetadataHelper.getSlaveToMasterField(entity);
String sql = String.format("select %s from %s where %s = ?",
Objects.requireNonNull(stm).getName(), entity.getName(), entity.getPrimaryField().getName());
stmField.getName(), entity.getName(), entity.getPrimaryField().getName());
Object[] o = Application.createQueryNoFilter(sql).setParameter(1, recordId).unique();
if (o == null) {
return null;
@ -529,7 +528,7 @@ public class FormsBuilder extends FormsManager {
// 主实体字段
else if (field.equals(DV_MASTER)) {
Field stmField = MetadataHelper.getSlaveToMasterField(entity);
Object mixValue = inFormFields.contains(Objects.requireNonNull(stmField).getName()) ? readyReferenceValue(value) : value;
Object mixValue = inFormFields.contains(stmField.getName()) ? readyReferenceValue(value) : value;
if (mixValue != null) {
initialValReady.put(stmField.getName(), mixValue);
initialValKeeps.add(stmField.getName());

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2018-2019 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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.server.configuration.portals;
@ -46,8 +35,7 @@ public class MultiSelectManager extends PickListManager {
public JSONArray getSelectList(Field field) {
ConfigEntry[] entries = getPickListRaw(field, false);
for (ConfigEntry e : entries) {
e.set("hide", null);
e.set("id", null);
e.set("hide", null).set("id", null);
}
return JSONUtils.toJSONArray(entries);
}

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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.server.helper.cache;
@ -76,8 +65,8 @@ public class RecordOwningCache extends BaseCacheTemplate<ID> {
String sql = "select owningUser from %s where %s = '%s'";
// 使用主记录
if (useMaster != null) {
Field stm = MetadataHelper.getSlaveToMasterField(entity);
sql = sql.replaceFirst("owningUser", stm.getName() + ".owningUser");
Field stmField = MetadataHelper.getSlaveToMasterField(entity);
sql = sql.replaceFirst("owningUser", stmField.getName() + ".owningUser");
}
sql = String.format(sql, entity.getName(), entity.getPrimaryField().getName(), record.toLiteral());

View file

@ -72,7 +72,11 @@ public class DynamicMetadataFactory extends ConfigurationMetadataFactory {
.addAttribute("description", (String) custom[3])
.addAttribute("parent", "false")
.addAttribute("name-field", (String) custom[7])
.addAttribute("master", (String) custom[8]);
.addAttribute("master", (String) custom[8])
.addAttribute("creatable", "true")
.addAttribute("updatable", "true")
.addAttribute("queryable", "true")
.addAttribute("deletable", "true");
ENTITY_EXTMETA.put(name, new Object[] { custom[4], custom[5], custom[6] });
}
@ -93,12 +97,13 @@ public class DynamicMetadataFactory extends ConfigurationMetadataFactory {
field.addAttribute("name", fieldName)
.addAttribute("physical-name", (String) custom[2])
.addAttribute("description", (String) custom[3])
.addAttribute("max-length", String.valueOf(custom[8]))
.addAttribute("default-value", (String) custom[9])
.addAttribute("nullable", String.valueOf(custom[5])) // true
.addAttribute("creatable", String.valueOf(custom[6])) // true
.addAttribute("updatable", String.valueOf(custom[7])) // true
.addAttribute("max-length", String.valueOf(custom[8]))
.addAttribute("default-value", (String) custom[9])
.addAttribute("repeatable", String.valueOf(custom[15])); // true
.addAttribute("repeatable", String.valueOf(custom[15])) // true
.addAttribute("queryable", "true");
if (fieldName.equals(EntityHelper.AutoId)) {
field.addAttribute("auto-value", "true");
}

View file

@ -11,10 +11,10 @@ import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field;
import cn.devezhao.persist4j.dialect.FieldType;
import cn.devezhao.persist4j.engine.ID;
import cn.devezhao.persist4j.metadata.BaseMeta;
import cn.devezhao.persist4j.metadata.MetadataException;
import com.rebuild.server.Application;
import com.rebuild.server.metadata.entity.EasyMeta;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
@ -33,7 +33,7 @@ public class MetadataHelper {
private static final Log LOG = LogFactory.getLog(MetadataHelper.class);
/**
* 元数据
* 元数据工厂
*
* @return
*/
@ -42,6 +42,8 @@ public class MetadataHelper {
}
/**
* 全部实体
*
* @return
*/
public static Entity[] getEntities() {
@ -53,9 +55,6 @@ public class MetadataHelper {
* @return
*/
public static boolean containsEntity(String entityName) {
if (StringUtils.isBlank(entityName)) {
return false;
}
try {
getEntity(entityName);
return true;
@ -93,16 +92,18 @@ public class MetadataHelper {
/**
* @param entityName
* @return
* @throws MetadataException If not exists
*/
public static Entity getEntity(String entityName) {
public static Entity getEntity(String entityName) throws MetadataException {
return getMetadataFactory().getEntity(entityName);
}
/**
* @param entityCode
* @return
* @throws MetadataException If not exists
*/
public static Entity getEntity(int entityCode) {
public static Entity getEntity(int entityCode) throws MetadataException {
return getMetadataFactory().getEntity(entityCode);
}
@ -117,6 +118,7 @@ public class MetadataHelper {
/**
* @param record
* @return
* @see EasyMeta#getLabel(BaseMeta)
*/
public static String getEntityLabel(ID record) {
return EasyMeta.getLabel(getEntity(record.getEntityCode()));
@ -128,8 +130,7 @@ public class MetadataHelper {
* @return
*/
public static Field getField(String entityName, String fieldName) {
Entity entity = getEntity(entityName);
return entity.getField(fieldName);
return getEntity(entityName).getField(fieldName);
}
/**
@ -173,8 +174,7 @@ public class MetadataHelper {
continue;
}
Entity ref = field.getReferenceEntities()[0];
if (ref.getEntityCode().equals(source.getEntityCode())) {
if (field.getReferenceEntity().getEntityCode().equals(source.getEntityCode())) {
fields.add(field);
}
}
@ -299,7 +299,7 @@ public class MetadataHelper {
return field;
}
}
return null;
throw new MetadataException("Bad slave entity (No STM)");
}
/**

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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.server.metadata.entity;
@ -272,13 +261,9 @@ public class EasyMeta implements BaseMeta {
* @return
*/
private Object[] getMetaExt() {
Object[] ext;
if (isField()) {
ext = MetadataHelper.getMetadataFactory().getFieldExtmeta((Field) baseMeta);
} else {
ext = MetadataHelper.getMetadataFactory().getEntityExtmeta((Entity) baseMeta);
}
return ext;
return isField()
? MetadataHelper.getMetadataFactory().getFieldExtmeta((Field) baseMeta)
: MetadataHelper.getMetadataFactory().getEntityExtmeta((Entity) baseMeta);
}
/**
@ -315,7 +300,8 @@ public class EasyMeta implements BaseMeta {
return DisplayType.NUMBER;
} else if (ft == FieldType.DOUBLE || ft == FieldType.DECIMAL) {
return DisplayType.DECIMAL;
}
}
return null;
}

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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.server.service.base;
@ -62,7 +51,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Observer;
import java.util.Set;
@ -452,8 +440,8 @@ public class GeneralEntityService extends ObservableService {
// 验证新建明细相当于更新主记录
Entity masterEntity = entity.getMasterEntity();
if (masterEntity != null && masterEntity.containsField(EntityHelper.ApprovalId)) {
Field smt = MetadataHelper.getSlaveToMasterField(entity);
ApprovalState state = getApprovalState(newRecord.getID(Objects.requireNonNull(smt).getName()));
Field stmField = MetadataHelper.getSlaveToMasterField(entity);
ApprovalState state = getApprovalState(newRecord.getID(stmField.getName()));
if (state == ApprovalState.APPROVED || state == ApprovalState.PROCESSING) {
String stateType = state == ApprovalState.APPROVED ? "已完成审批" : "正在审批中";
throw new DataSpecificationException("主记录" + stateType + ",不能添加明细");
@ -513,8 +501,8 @@ public class GeneralEntityService extends ObservableService {
* @throws NoRecordFoundException
*/
private ID getMasterId(Entity slaveEntity, ID slaveId) throws NoRecordFoundException {
Field stm = MetadataHelper.getSlaveToMasterField(slaveEntity);
Object[] o = Application.getQueryFactory().uniqueNoFilter(slaveId, Objects.requireNonNull(stm).getName());
Field stmField = MetadataHelper.getSlaveToMasterField(slaveEntity);
Object[] o = Application.getQueryFactory().uniqueNoFilter(slaveId, stmField.getName());
if (o == null) {
throw new NoRecordFoundException(slaveId);
}

View file

@ -21,7 +21,6 @@ import com.rebuild.server.metadata.EntityHelper;
import com.rebuild.server.metadata.MetadataHelper;
import com.rebuild.server.metadata.entity.EasyMeta;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.Assert;
import java.util.HashSet;
import java.util.Set;
@ -113,16 +112,14 @@ public class EntityQueryFilter implements Filter, QueryFilter {
}
String ownFormat = "%s = '%s'";
Field toMasterField = null;
Field stmField = null;
if (useMaster != null) {
toMasterField = MetadataHelper.getSlaveToMasterField(entity);
Assert.notNull(toMasterField, "No STM field found : " + entity);
ownFormat = toMasterField.getName() + "." + ownFormat;
stmField = MetadataHelper.getSlaveToMasterField(entity);
ownFormat = stmField.getName() + "." + ownFormat;
}
if (de == BizzDepthEntry.PRIVATE) {
return appendShareFilter(entity, toMasterField,
return appendShareFilter(entity, stmField,
String.format(ownFormat, EntityHelper.OwningUser, user.getIdentity()));
}
@ -130,7 +127,7 @@ public class EntityQueryFilter implements Filter, QueryFilter {
String deptSql = String.format(ownFormat, EntityHelper.OwningDept, dept.getIdentity());
if (de == BizzDepthEntry.LOCAL) {
return appendShareFilter(entity, toMasterField, deptSql);
return appendShareFilter(entity, stmField, deptSql);
} else if (de == BizzDepthEntry.DEEPDOWN) {
Set<String> sqls = new HashSet<>();
sqls.add(deptSql);
@ -138,7 +135,7 @@ public class EntityQueryFilter implements Filter, QueryFilter {
for (BusinessUnit child : dept.getAllChildren()) {
sqls.add(String.format(ownFormat, EntityHelper.OwningDept, child.getIdentity()));
}
return appendShareFilter(entity, toMasterField, "(" + StringUtils.join(sqls, " or ") + ")");
return appendShareFilter(entity, stmField, "(" + StringUtils.join(sqls, " or ") + ")");
}
return DENIED.evaluate(null);

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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.server.service.bizz.privileges;
@ -123,15 +112,15 @@ public class PrivilegesGuardInterceptor implements MethodInterceptor, Guard {
if (action == BizzPermission.CREATE) {
// 明细实体
if (entity.getMasterEntity() != null) {
Field field = MetadataHelper.getSlaveToMasterField(entity);
Assert.notNull(field, "No STM field found : " + entity);
Assert.isTrue(Record.class.isAssignableFrom(idOrRecord.getClass()), "First argument must be Record!");
ID masterId = ((Record) idOrRecord).getID(field.getName());
Field stmField = MetadataHelper.getSlaveToMasterField(entity);
ID masterId = ((Record) idOrRecord).getID(stmField.getName());
if (masterId == null || !Application.getSecurityManager().allowUpdate(caller, masterId)) {
throw new AccessDeniedException("你没有添加明细的权限");
}
allowed = true;
} else {
allowed = Application.getSecurityManager().allow(caller, entity.getEntityCode(), action);
}

View file

@ -26,7 +26,6 @@ import com.rebuild.server.metadata.entity.EasyMeta;
import com.rebuild.server.service.EntityService;
import com.rebuild.server.service.bizz.RoleService;
import com.rebuild.server.service.bizz.UserService;
import org.springframework.util.Assert;
/**
* 实体安全/权限 管理
@ -412,8 +411,7 @@ public class SecurityManager {
private ID getMasterRecordId(ID slaveId) {
Entity entity = MetadataHelper.getEntity(slaveId.getEntityCode());
Field stmField = MetadataHelper.getSlaveToMasterField(entity);
Assert.isTrue(stmField != null, "Non slave entty : " + slaveId);
Object[] primary = Application.getQueryFactory().uniqueNoFilter(slaveId, stmField.getName());
return primary == null ? null : (ID) primary[0];
}

View file

@ -119,8 +119,8 @@ public class MetaFieldControll extends BasePageControll {
// 明细实体
if (((Entity) easyEntity.getBaseMeta()).getMasterEntity() != null) {
Field stf = MetadataHelper.getSlaveToMasterField((Entity) easyEntity.getBaseMeta());
mv.getModel().put("isSlaveToMasterField", stf.equals(fieldMeta));
Field stmField = MetadataHelper.getSlaveToMasterField((Entity) easyEntity.getBaseMeta());
mv.getModel().put("isSlaveToMasterField", stmField.equals(fieldMeta));
} else {
mv.getModel().put("isSlaveToMasterField", false);
}

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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.web.base.configuration;
@ -119,12 +108,12 @@ public class DataListSettingsControll extends BaseControll implements PortalsCon
}
// 明细关联字段
final Field stmfField = entityMeta.getMasterEntity() == null ? null : MetadataHelper.getSlaveToMasterField(entityMeta);
final Field stmField = entityMeta.getMasterEntity() == null ? null : MetadataHelper.getSlaveToMasterField(entityMeta);
// 引用实体的字段
for (Field field : MetadataSorter.sortFields(entityMeta, DisplayType.REFERENCE)) {
// 过滤所属用户/所属部门等系统字段除了明细引用主实体字段
if (EasyMeta.valueOf(field).isBuiltin() && (stmfField == null || !stmfField.equals(field))) {
if (EasyMeta.valueOf(field).isBuiltin() && (stmField == null || !stmField.equals(field))) {
continue;
}

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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.web.base.general;
@ -62,7 +51,13 @@ public class GeneralDataListControll extends BaseEntityControll {
return null;
}
Entity thatEntity = MetadataHelper.getEntity(entity);
final Entity thatEntity = MetadataHelper.getEntity(entity);
if (!thatEntity.isQueryable()) {
response.sendError(404);
return null;
}
if (!Application.getSecurityManager().allowRead(user, thatEntity.getEntityCode())) {
response.sendError(403, "你没有访问此实体的权限");
return null;

View file

@ -40,7 +40,7 @@ public class GeneralModelControll extends BaseEntityControll {
public ModelAndView pageView(@PathVariable String entity, @PathVariable String id,
HttpServletRequest request, HttpServletResponse response) throws IOException {
final ID user = getRequestUser(request);
Entity thatEntity = MetadataHelper.getEntity(entity);
final Entity thatEntity = MetadataHelper.getEntity(entity);
if (!Application.getSecurityManager().allowRead(user, thatEntity.getEntityCode())) {
response.sendError(403, "你没有访问此实体的权限");

View file

@ -13,7 +13,7 @@
<entity name="User" type-code="001" description="用户" name-field="fullName" extra-attrs="{icon:'account'}">
<field name="userId" type="primary" />
<field name="loginName" type="string" max-length="100" nullable="false" updatable="false" repeatable="false" description="登录名" />
<field name="password" type="string" max-length="100" nullable="false" updatable="false" description="登录密码" />
<field name="password" type="string" max-length="100" nullable="false" updatable="false" description="登录密码" queryable="false" />
<field name="email" type="string" max-length="100" description="邮箱" repeatable="false" extra-attrs="{displayType:'EMAIL'}" />
<field name="fullName" type="string" max-length="100" description="姓名" />
<field name="avatarUrl" type="string" max-length="200" description="头像" extra-attrs="{displayType:'AVATAR'}" />
@ -75,7 +75,7 @@
<index field-list="teamId,userId" type="unique" />
</entity>
<entity name="MetaEntity" type-code="010" name-field="entityName">
<entity name="MetaEntity" type-code="010" name-field="entityName" queryable="false">
<field name="entityId" type="primary" />
<field name="typeCode" type="small-int" nullable="false" updatable="false" />
<field name="entityName" type="string" max-length="100" nullable="false" updatable="false" />
@ -90,7 +90,7 @@
<index type="unique" field-list="physicalName" />
</entity>
<entity name="MetaField" type-code="011" name-field="fieldName">
<entity name="MetaField" type-code="011" name-field="fieldName" queryable="false">
<field name="fieldId" type="primary" />
<field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" />
<field name="fieldName" type="string" max-length="100" nullable="false" updatable="false" />
@ -111,7 +111,7 @@
<index type="unique" field-list="belongEntity,physicalName" />
</entity>
<entity name="PickList" type-code="012" name-field="text" description="下拉列表字段配置选项">
<entity name="PickList" type-code="012" name-field="text" description="下拉列表字段配置选项" queryable="false">
<field name="itemId" type="primary" />
<field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" />
<field name="belongField" type="string" max-length="100" nullable="false" updatable="false" />
@ -123,7 +123,7 @@
<index field-list="belongEntity,belongField" />
</entity>
<entity name="LayoutConfig" type-code="013" description="布局配置(表单/列表/导航/视图(相关项/新建))">
<entity name="LayoutConfig" type-code="013" description="布局配置(表单/列表/导航/视图(相关项/新建))" queryable="false">
<field name="configId" type="primary" />
<field name="config" type="text" description="JSON格式配置" nullable="false" />
<field name="shareTo" type="string" max-length="420" default-value="SELF" description="共享给哪些人, 可选值: ALL/SELF/$MemberID(U/D/R)" />
@ -132,7 +132,7 @@
<field name="configName" type="string" max-length="100" />
</entity>
<entity name="FilterConfig" type-code="014" description="过滤条件配置">
<entity name="FilterConfig" type-code="014" description="过滤条件配置" queryable="false">
<field name="configId" type="primary" />
<field name="config" type="text" description="JSON格式配置" nullable="false" />
<field name="shareTo" type="string" max-length="420" default-value="SELF" description="共享给哪些人, 可选值: ALL/SELF/$MemberID(U/D/R)" />
@ -140,14 +140,14 @@
<field name="filterName" type="string" max-length="100" nullable="false" />
</entity>
<entity name="DashboardConfig" type-code="016" description="仪表盘配置">
<entity name="DashboardConfig" type-code="016" description="仪表盘配置" queryable="false">
<field name="configId" type="primary" />
<field name="config" type="text" description="JSON格式配置" nullable="false" />
<field name="shareTo" type="string" max-length="420" default-value="SELF" description="共享给哪些人, 可选值: ALL/SELF/$MemberID(U/D/R)" />
<field name="title" type="string" max-length="100" nullable="false" />
</entity>
<entity name="ChartConfig" type-code="017" description="图表配置">
<entity name="ChartConfig" type-code="017" description="图表配置" queryable="false">
<field name="chartId" type="primary" />
<field name="config" type="text" description="JSON格式配置" nullable="false" />
<field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" />
@ -177,7 +177,7 @@
<index field-list="dataId,fullName,quickCode" />
</entity>
<entity name="ShareAccess" type-code="020" description="记录共享">
<entity name="ShareAccess" type-code="020" description="记录共享" queryable="false">
<field name="accessId" type="primary" />
<field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" description="哪个实体" />
<field name="recordId" type="any-reference" nullable="false" updatable="false" description="记录ID" cascade="ignore" />
@ -186,7 +186,7 @@
<index field-list="belongEntity,recordId,shareTo" />
</entity>
<entity name="SystemConfig" type-code="021" parent="false" description="系统全局配置">
<entity name="SystemConfig" type-code="021" parent="false" description="系统全局配置" queryable="false">
<field name="configId" type="primary" />
<field name="item" type="string" max-length="100" nullable="false" updatable="false" />
<field name="value" type="string" max-length="600" nullable="false" />
@ -238,7 +238,7 @@
<index field-list="user,loginTime" />
</entity>
<entity name="AutoFillinConfig" type-code="026" description="字段自动回填配置">
<entity name="AutoFillinConfig" type-code="026" description="字段自动回填配置" queryable="false">
<field name="configId" type="primary" />
<field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" />
<field name="belongField" type="string" max-length="100" nullable="false" updatable="false" />
@ -247,7 +247,7 @@
<field name="extConfig" type="string" max-length="700" description="更多扩展配置, JSON格式KV" />
</entity>
<entity name="RobotTriggerConfig" type-code="027" description="动作触发器">
<entity name="RobotTriggerConfig" type-code="027" description="动作触发器" queryable="false">
<field name="configId" type="primary" />
<field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" />
<field name="when" type="int" default-value="0" description="动作(累加值)" />
@ -259,7 +259,7 @@
<field name="isDisabled" type="bool" default-value="F" description="是否停用" />
</entity>
<entity name="RobotApprovalConfig" type-code="028" name-field="name" description="审批流程">
<entity name="RobotApprovalConfig" type-code="028" name-field="name" description="审批流程" queryable="false">
<field name="configId" type="primary" />
<field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" description="应用实体" />
<field name="name" type="string" max-length="100" nullable="false" description="流程名称" />
@ -267,7 +267,7 @@
<field name="isDisabled" type="bool" default-value="F" description="是否停用" />
</entity>
<entity name="RobotApprovalStep" type-code="029" description="审批步骤记录">
<entity name="RobotApprovalStep" type-code="029" description="审批步骤记录" queryable="false">
<field name="stepId" type="primary" />
<field name="recordId" type="any-reference" nullable="false" updatable="false" description="审批记录" />
<field name="approvalId" type="reference" ref-entity="RobotApprovalConfig" nullable="false" updatable="false" description="审批流程" />
@ -303,7 +303,7 @@
<index field-list="appId,remoteIp,requestUrl,requestTime" />
</entity>
<entity name="DataReportConfig" type-code="032" description="报表">
<entity name="DataReportConfig" type-code="032" description="报表" queryable="false">
<field name="configId" type="primary" />
<field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" description="应用实体" />
<field name="name" type="string" max-length="100" nullable="false" description="报表名称" />
@ -381,7 +381,7 @@
<index field-list="source,createdBy" />
</entity>
<entity name="FeedsMention" type-code="043" description="用户提及" parent="false">
<entity name="FeedsMention" type-code="043" description="用户提及" parent="false" queryable="false">
<field name="mentionId" type="primary" />
<field name="feedsId" type="reference" ref-entity="Feeds" nullable="false" updatable="false" description="哪个动态" cascade="delete" />
<field name="commentId" type="reference" ref-entity="FeedsComment" updatable="false" description="哪个评论" cascade="delete" />

View file

@ -0,0 +1,39 @@
/*
Copyright (c) REBUILD <https://getrebuild.com/> and 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.api.metadata;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.api.ApiContext;
import com.rebuild.server.TestSupport;
import com.rebuild.utils.JSONUtils;
import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.*;
/**
* @author devezhao
* @since 2020/5/14
*/
public class ClassificationDataTest extends TestSupport {
@Test
public void execute() {
Map<String, String> reqParams = new HashMap<>();
reqParams.put("entity", "TestAllFields");
reqParams.put("field", "CLASSIFICATION");
ApiContext apiContext = new ApiContext(reqParams, null);
JSONObject ret = (JSONObject) new ClassificationData().execute(apiContext);
System.out.println(JSONUtils.prettyPrint(ret));
Assert.assertNotNull(ret.get("error_code"));
}
}

View file

@ -0,0 +1,35 @@
/*
Copyright (c) REBUILD <https://getrebuild.com/> and 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.api.metadata;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.api.ApiContext;
import com.rebuild.server.TestSupport;
import com.rebuild.utils.JSONUtils;
import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @author devezhao
* @since 2020/5/14
*/
public class EntityListTest extends TestSupport {
@Test
public void execute() {
Map<String, String> reqParams = new HashMap<>();
ApiContext apiContext = new ApiContext(reqParams, null);
JSONObject ret = (JSONObject) new EntityList().execute(apiContext);
System.out.println(JSONUtils.prettyPrint(ret));
Assert.assertNotNull(ret.get("error_code"));
}
}

View file

@ -0,0 +1,36 @@
/*
Copyright (c) REBUILD <https://getrebuild.com/> and 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.api.metadata;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.api.ApiContext;
import com.rebuild.server.TestSupport;
import com.rebuild.utils.JSONUtils;
import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @author devezhao
* @since 2020/5/14
*/
public class FieldListTest extends TestSupport {
@Test
public void execute() {
Map<String, String> reqParams = new HashMap<>();
reqParams.put("entity", "TestAllFields");
ApiContext apiContext = new ApiContext(reqParams, null);
JSONObject ret = (JSONObject) new FieldList().execute(apiContext);
System.out.println(JSONUtils.prettyPrint(ret));
Assert.assertNotNull(ret.get("error_code"));
}
}

View file

@ -1,19 +1,8 @@
/*
rebuild - Building your business-systems freely.
Copyright (C) 2019 devezhao <zhaofang123@gmail.com>
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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.server.metadata.entity;
@ -30,9 +19,16 @@ import org.junit.Test;
public class EasyMetaTest extends TestSupport {
@Test
public void test() throws Exception {
public void getLabel() throws Exception {
Entity user = MetadataHelper.getEntity("User");
EasyMeta.getLabel(user, "roleId.name");
System.out.println(EasyMeta.getEntityShow(user));
}
@Test
public void testEntities() {
for (Entity entity : MetadataHelper.getEntities()) {
System.out.println(entity);
}
}
}