[field] Open advDesensitized and advPattern

This commit is contained in:
devezhao 2022-02-07 17:31:02 +08:00
parent 73ae9b8387
commit 3f7599dc6a
9 changed files with 100 additions and 42 deletions

2
@rbv

@ -1 +1 @@
Subproject commit 56614d32f64d7f34cb542ab63e5cf4226c739309 Subproject commit 704e1a970c0f43b65bfec66d79100d9f00dace8d

View file

@ -12,7 +12,6 @@ import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field; import cn.devezhao.persist4j.Field;
import cn.devezhao.persist4j.Record; import cn.devezhao.persist4j.Record;
import cn.devezhao.persist4j.dialect.FieldType; import cn.devezhao.persist4j.dialect.FieldType;
import cn.devezhao.persist4j.dialect.Type;
import cn.devezhao.persist4j.engine.ID; import cn.devezhao.persist4j.engine.ID;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
@ -24,6 +23,7 @@ import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.metadata.easymeta.DisplayType; import com.rebuild.core.metadata.easymeta.DisplayType;
import com.rebuild.core.metadata.easymeta.EasyField; import com.rebuild.core.metadata.easymeta.EasyField;
import com.rebuild.core.metadata.easymeta.EasyMetaFactory; import com.rebuild.core.metadata.easymeta.EasyMetaFactory;
import com.rebuild.core.metadata.easymeta.EasyText;
import com.rebuild.core.metadata.impl.EasyFieldConfigProps; import com.rebuild.core.metadata.impl.EasyFieldConfigProps;
import com.rebuild.core.privileges.bizz.Department; import com.rebuild.core.privileges.bizz.Department;
import com.rebuild.core.privileges.bizz.User; import com.rebuild.core.privileges.bizz.User;
@ -37,7 +37,6 @@ import com.rebuild.core.support.i18n.Language;
import com.rebuild.core.support.state.StateManager; import com.rebuild.core.support.state.StateManager;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import java.util.*; import java.util.*;
@ -494,8 +493,8 @@ public class FormsBuilder extends FormsManager {
} }
private boolean isUseDesensitized(EasyField field, ID user) { private boolean isUseDesensitized(EasyField field, ID user) {
if (user == null) return false; if (user == null || !(field instanceof EasyText)) return false;
return BooleanUtils.toBoolean(field.getExtraAttr(EasyFieldConfigProps.ADV_DESENSITIZED)) return ((EasyText) field).isDesensitized()
&& !Application.getPrivilegesManager().allow(user, ZeroEntry.AllowNoDesensitized); && !Application.getPrivilegesManager().allow(user, ZeroEntry.AllowNoDesensitized);
} }

View file

@ -28,7 +28,9 @@ public class EasyPhone extends EasyText {
return patt == null ? PATT_PHONE : patt; return patt == null ? PATT_PHONE : patt;
} }
// 兼容电话手机 // --
// 兼容电话手机国际区号
public static Pattern PATT_PHONE = Pattern.compile( public static Pattern PATT_PHONE = Pattern.compile(
"((\\(\\d{1,5}\\))?(\\d{3,4}-)?\\d{7,8}(-\\d{1,6})?)|(1[356789]\\d{9})"); "((\\(\\d{1,5}\\))?(\\d{3,4}-)?\\d{7,8}(-\\d{1,6})?)|(1[356789]\\d{9})");

View file

@ -11,6 +11,7 @@ import cn.devezhao.persist4j.Field;
import com.rebuild.core.metadata.impl.EasyFieldConfigProps; import com.rebuild.core.metadata.impl.EasyFieldConfigProps;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.BooleanUtils;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; import java.util.regex.PatternSyntaxException;
@ -43,4 +44,13 @@ public class EasyText extends EasyField {
} }
return null; return null;
} }
/**
* 信息脱敏
*
* @return
*/
public boolean isDesensitized() {
return BooleanUtils.toBoolean(getExtraAttr(EasyFieldConfigProps.ADV_DESENSITIZED));
}
} }

View file

@ -19,10 +19,8 @@ import com.rebuild.core.Initialization;
import com.rebuild.core.metadata.EntityHelper; import com.rebuild.core.metadata.EntityHelper;
import com.rebuild.core.privileges.bizz.User; import com.rebuild.core.privileges.bizz.User;
import com.rebuild.core.privileges.bizz.*; import com.rebuild.core.privileges.bizz.*;
import com.rebuild.core.support.License; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.security.Principal; import java.security.Principal;
@ -35,11 +33,10 @@ import java.util.concurrent.ConcurrentHashMap;
* @author zhaofang123@gmail.com * @author zhaofang123@gmail.com
* @since 09/16/2018 * @since 09/16/2018
*/ */
@Slf4j
@Component @Component
public class UserStore implements Initialization { public class UserStore implements Initialization {
private static final Logger LOG = LoggerFactory.getLogger(UserStore.class);
final private Map<ID, User> USERS = new ConcurrentHashMap<>(); final private Map<ID, User> USERS = new ConcurrentHashMap<>();
final private Map<ID, Role> ROLES = new ConcurrentHashMap<>(); final private Map<ID, Role> ROLES = new ConcurrentHashMap<>();
final private Map<ID, Department> DEPTS = new ConcurrentHashMap<>(); final private Map<ID, Department> DEPTS = new ConcurrentHashMap<>();
@ -504,7 +501,6 @@ public class UserStore implements Initialization {
* @param user * @param user
*/ */
private void refreshUserRoleAppends(User user) { private void refreshUserRoleAppends(User user) {
if (!License.isCommercial()) return;
// 最高权限无需合并 // 最高权限无需合并
if (user.getMainRole().getIdentity().equals(RoleService.ADMIN_ROLE)) { if (user.getMainRole().getIdentity().equals(RoleService.ADMIN_ROLE)) {
return; return;
@ -557,7 +553,7 @@ public class UserStore implements Initialization {
userId, (String) o[1], (String) o[2], (String) o[8], (String) o[3], (String) o[4], (Boolean) o[5]); userId, (String) o[1], (String) o[2], (String) o[8], (String) o[3], (String) o[4], (Boolean) o[5]);
store(user); store(user);
} }
LOG.info("Loaded [ " + USERS.size() + " ] users."); log.info("Loaded [ " + USERS.size() + " ] users.");
// 角色 // 角色
@ -565,7 +561,7 @@ public class UserStore implements Initialization {
for (Object[] o : array) { for (Object[] o : array) {
this.refreshRole((ID) o[0]); this.refreshRole((ID) o[0]);
} }
LOG.info("Loaded [ " + ROLES.size() + " ] roles."); log.info("Loaded [ " + ROLES.size() + " ] roles.");
// 附加角色 // 附加角色
for (User user : USERS.values()) { for (User user : USERS.values()) {
@ -597,7 +593,7 @@ public class UserStore implements Initialization {
} }
} }
LOG.info("Loaded [ " + DEPTS.size() + " ] departments."); log.info("Loaded [ " + DEPTS.size() + " ] departments.");
// 团队 // 团队
@ -605,7 +601,7 @@ public class UserStore implements Initialization {
for (Object[] o : array) { for (Object[] o : array) {
this.refreshTeam((ID) o[0]); this.refreshTeam((ID) o[0]);
} }
LOG.info("Loaded [ " + TEAMS.size() + " ] teams."); log.info("Loaded [ " + TEAMS.size() + " ] teams.");
isLoaded = true; isLoaded = true;
} }

View file

@ -17,12 +17,11 @@ import com.rebuild.core.Application;
import com.rebuild.core.metadata.easymeta.DisplayType; import com.rebuild.core.metadata.easymeta.DisplayType;
import com.rebuild.core.metadata.easymeta.EasyField; import com.rebuild.core.metadata.easymeta.EasyField;
import com.rebuild.core.metadata.easymeta.EasyMetaFactory; import com.rebuild.core.metadata.easymeta.EasyMetaFactory;
import com.rebuild.core.metadata.impl.EasyFieldConfigProps; import com.rebuild.core.metadata.easymeta.EasyText;
import com.rebuild.core.privileges.UserHelper; import com.rebuild.core.privileges.UserHelper;
import com.rebuild.core.privileges.bizz.ZeroEntry; import com.rebuild.core.privileges.bizz.ZeroEntry;
import com.rebuild.utils.JSONUtils; import com.rebuild.utils.JSONUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.BooleanUtils;
import java.util.Map; import java.util.Map;
@ -44,7 +43,7 @@ public class DataListWrapper {
private Map<String, Integer> queryJoinFields; private Map<String, Integer> queryJoinFields;
// 信息脱敏 // 信息脱敏
private boolean useDesensitized = true; private boolean useDesensitized = false;
/** /**
* @param total * @param total
@ -69,6 +68,9 @@ public class DataListWrapper {
if (user != null && joinFields != null && !joinFields.isEmpty()) { if (user != null && joinFields != null && !joinFields.isEmpty()) {
this.user = user; this.user = user;
this.queryJoinFields = joinFields; this.queryJoinFields = joinFields;
}
if (user != null) {
this.useDesensitized = !Application.getPrivilegesManager().allow(user, ZeroEntry.AllowNoDesensitized); this.useDesensitized = !Application.getPrivilegesManager().allow(user, ZeroEntry.AllowNoDesensitized);
} }
} }
@ -163,7 +165,7 @@ public class DataListWrapper {
private boolean isUseDesensitized(EasyField easyField) { private boolean isUseDesensitized(EasyField easyField) {
return this.useDesensitized return this.useDesensitized
&& BooleanUtils.toBoolean(easyField.getExtraAttr(EasyFieldConfigProps.ADV_DESENSITIZED)); && easyField instanceof EasyText && ((EasyText) easyField).isDesensitized();
} }
/** /**

View file

@ -310,10 +310,10 @@
</label> </label>
</div> </div>
</div> </div>
<div class="form-group row bosskey-show"> <div class="form-group row hide J_advOpt">
<label class="col-md-12 col-xl-3 col-lg-4 col-form-label text-lg-right pt-1">[[${bundle.L('高级配置')}]]</label> <label class="col-md-12 col-xl-3 col-lg-4 col-form-label text-lg-right pt-1">[[${bundle.L('高级')}]] <sup class="rbv"></sup></label>
<div class="col-md-12 col-xl-6 col-lg-8"> <div class="col-md-12 col-xl-6 col-lg-8">
<label class="custom-control custom-control-sm custom-checkbox"> <label class="custom-control custom-control-sm custom-checkbox bosskey-show">
<input class="custom-control-input" type="checkbox" id="fieldQueryable" th:data-o="${fieldQueryable}" /> <input class="custom-control-input" type="checkbox" id="fieldQueryable" th:data-o="${fieldQueryable}" />
<span class="custom-control-label"> <span class="custom-control-label">
[[${bundle.L('允许使用')}]] [[${bundle.L('允许使用')}]]
@ -328,7 +328,16 @@
</span> </span>
</label> </label>
<div> <div>
<input type="text" class="form-control form-control-sm" id="advPattern" th:placeholder="${bundle.L('正则表达式')}" /> <input type="text" class="form-control form-control-sm" id="advPattern" th:placeholder="${bundle.L('正则表达式')}" data-toggle="dropdown" autocomplete="off" />
<div class="dropdown-menu common-patt">
<h5>[[${bundle.L('常用')}]]</h5>
<a class="badge" data-patt="^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$">[[${bundle.L('身份证')}]]</a>
<a class="badge" data-patt="^[1-9][0-9]{4,}$">[[${bundle.L('QQ号')}]]</a>
<a class="badge" data-patt="^[1-9][0-9]{5}$">[[${bundle.L('邮编')}]]</a>
<a class="badge" data-patt="^[\u4e00-\u9fa5]{0,}$">[[${bundle.L('仅中文')}]]</a>
<a class="badge" data-patt="^[A-Za-z]{0,}$">[[${bundle.L('仅英文')}]]</a>
<a class="badge" data-patt="^.{10,20}$">[[${bundle.L('限制字数')}]]</a>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -212,3 +212,26 @@ a#entityIcon:hover {
border-radius: 2px; border-radius: 2px;
padding: 1px 2px; padding: 1px 2px;
} }
.common-patt {
padding: 15px;
}
.common-patt > h5 {
margin: 0;
color: #777;
}
.common-patt .badge {
margin: 0;
margin-right: 3px;
margin-top: 6px;
font-weight: normal;
border: 0 none;
background-color: #eee;
background-color: rgb(245, 247, 249);
}
.common-patt .badge:hover {
color: #4285f4 !important;
}

View file

@ -9,11 +9,10 @@ See LICENSE and COMMERCIAL in the project root for license information.
const wpc = window.__PageConfig const wpc = window.__PageConfig
const __gExtConfig = {} const __gExtConfig = {}
const SHOW_REPEATABLE = ['TEXT', 'DATE', 'DATETIME', 'EMAIL', 'URL', 'PHONE', 'REFERENCE', 'CLASSIFICATION'] const SHOW_REPEATABLE = ['TEXT', 'DATE', 'EMAIL', 'URL', 'PHONE', 'REFERENCE', 'CLASSIFICATION']
const SHOW_DEFAULTVALUE = ['TEXT', 'NTEXT', 'EMAIL', 'PHONE', 'URL', 'NUMBER', 'DECIMAL', 'DATE', 'DATETIME', 'BOOL', 'CLASSIFICATION', 'REFERENCE', 'N2NREFERENCE'] const SHOW_DEFAULTVALUE = ['TEXT', 'NTEXT', 'EMAIL', 'PHONE', 'URL', 'NUMBER', 'DECIMAL', 'DATE', 'DATETIME', 'BOOL', 'CLASSIFICATION', 'REFERENCE', 'N2NREFERENCE']
const SHOW_ADVDESENSITIZED = ['TEXT', 'EMAIL', 'PHONE'] const SHOW_ADVDESENSITIZED = ['TEXT', 'PHONE', 'EMAIL']
const SHOW_ADVPATTERN = [...SHOW_ADVDESENSITIZED, 'URL', 'NTEXT'] const SHOW_ADVPATTERN = ['TEXT']
$(document).ready(function () { $(document).ready(function () {
const dt = wpc.fieldType const dt = wpc.fieldType
@ -29,12 +28,25 @@ $(document).ready(function () {
} }
// 默认值 // 默认值
if (!SHOW_DEFAULTVALUE.includes(dt)) $('#defaultValue').remove() if (!SHOW_DEFAULTVALUE.includes(dt)) $('#defaultValue').remove()
// 脱敏
if (!SHOW_ADVDESENSITIZED.includes(dt)) $('#advDesensitized').parent().remove()
// 正则
if (!SHOW_ADVPATTERN.includes(dt)) $('#advPattern').parent().remove()
const $btn = $('.J_save').click(function () { // 脱敏
if (SHOW_ADVDESENSITIZED.includes(dt)) {
$('.J_advOpt').removeClass('hide')
} else {
$('#advDesensitized').parent().remove()
}
// 正则
if (SHOW_ADVPATTERN.includes(dt)) {
$('.J_advOpt').removeClass('hide')
$('.common-patt .badge').on('click', function () {
$('#advPattern').val($(this).data('patt'))
})
} else {
$('#advPattern').parent().remove()
}
const $btn = $('.J_save').on('click', function () {
if (!wpc.metaId) return if (!wpc.metaId) return
let data = { let data = {
fieldLabel: $val('#fieldLabel'), fieldLabel: $val('#fieldLabel'),
@ -82,6 +94,11 @@ $(document).ready(function () {
if (SHOW_ADVDESENSITIZED.includes(dt)) extConfigNew['advDesensitized'] = $val('#advDesensitized') if (SHOW_ADVDESENSITIZED.includes(dt)) extConfigNew['advDesensitized'] = $val('#advDesensitized')
if (SHOW_ADVPATTERN.includes(dt)) extConfigNew['advPattern'] = $val('#advPattern') if (SHOW_ADVPATTERN.includes(dt)) extConfigNew['advPattern'] = $val('#advPattern')
if ((extConfigNew['advDesensitized'] || extConfigNew['advPattern']) && rb.commercial < 1) {
RbHighbar.error(WrapHtml($L('免费版不支持高级功能 [(查看详情)](https://getrebuild.com/docs/rbv-features)')))
return
}
if (!$same(extConfigNew, extConfig)) { if (!$same(extConfigNew, extConfig)) {
data['extConfig'] = JSON.stringify(extConfigNew) data['extConfig'] = JSON.stringify(extConfigNew)
if (Object.keys(extConfigNew).length === 0) data['extConfig'] = '' if (Object.keys(extConfigNew).length === 0) data['extConfig'] = ''
@ -172,7 +189,7 @@ $(document).ready(function () {
// delete extConfig['classification'] // delete extConfig['classification']
// delete extConfig['stateClass'] // delete extConfig['stateClass']
$('.J_del').click(function () { $('.J_del').on('click', function () {
if (!wpc.isSuperAdmin) { if (!wpc.isSuperAdmin) {
RbHighbar.error($L('仅超级管理员可删除字段')) RbHighbar.error($L('仅超级管理员可删除字段'))
return return
@ -235,7 +252,7 @@ const _handlePicklist = function (dt) {
}) })
if (res.data.length > 5) $('#picklist-items').parent().removeClass('autoh') if (res.data.length > 5) $('#picklist-items').parent().removeClass('autoh')
}) })
$('.J_picklist-edit').click(() => RbModal.create(`/p/admin/metadata/picklist-editor?entity=${wpc.entityName}&field=${wpc.fieldName}&multi=${dt === 'MULTISELECT'}`, $L('选项配置'))) $('.J_picklist-edit').on('click', () => RbModal.create(`/p/admin/metadata/picklist-editor?entity=${wpc.entityName}&field=${wpc.fieldName}&multi=${dt === 'MULTISELECT'}`, $L('选项配置')))
} }
const _handleSeries = function () { const _handleSeries = function () {
@ -271,7 +288,7 @@ const _handleDate = function (dt) {
$(`<button class="btn btn-secondary mw-auto" type="button" title="${$L('日期公式')}"><i class="icon zmdi zmdi-settings-square"></i></button>`) $(`<button class="btn btn-secondary mw-auto" type="button" title="${$L('日期公式')}"><i class="icon zmdi zmdi-settings-square"></i></button>`)
.appendTo('.J_defaultValue-append') .appendTo('.J_defaultValue-append')
.click(() => renderRbcomp(<FormulaDate type={dt} onConfirm={(expr) => $('.J_defaultValue').val(expr)} />)) .on('click', () => renderRbcomp(<FormulaDate type={dt} onConfirm={(expr) => $('.J_defaultValue').val(expr)} />))
} }
const _handleFile = function (uploadNumber) { const _handleFile = function (uploadNumber) {
@ -304,7 +321,7 @@ const _handleFile = function (uploadNumber) {
const _handleClassification = function (useClassification) { const _handleClassification = function (useClassification) {
const $dv = $('.J_defaultValue') const $dv = $('.J_defaultValue')
const $dvClear = $('.J_defaultValue-clear').click(() => { const $dvClear = $('.J_defaultValue-clear').on('click', () => {
$dv.attr('data-value-id', '').val('') $dv.attr('data-value-id', '').val('')
$dvClear.addClass('hide') $dvClear.addClass('hide')
}) })
@ -342,7 +359,7 @@ const _handleClassification = function (useClassification) {
.text(res.data.name) .text(res.data.name)
$dv.attr('readonly', true) $dv.attr('readonly', true)
$append.click(() => _showSelector(res.data)) $append.on('click', () => _showSelector(res.data))
}) })
_loadRefsLabel($dv, $dvClear) _loadRefsLabel($dv, $dvClear)
@ -375,7 +392,7 @@ const _handleReference = function (isN2N) {
dataFilter && saveFilter(dataFilter) dataFilter && saveFilter(dataFilter)
let advFilter let advFilter
$('#referenceDataFilter').click(() => { $('#referenceDataFilter').on('click', () => {
if (advFilter) { if (advFilter) {
advFilter.show() advFilter.show()
} else { } else {
@ -387,7 +404,7 @@ const _handleReference = function (isN2N) {
// 默认值 // 默认值
const $dv = $('.J_defaultValue') const $dv = $('.J_defaultValue')
const $dvClear = $('.J_defaultValue-clear').click(() => { const $dvClear = $('.J_defaultValue-clear').on('click', () => {
$dv.attr('data-value-id', '').val('') $dv.attr('data-value-id', '').val('')
$dvClear.addClass('hide') $dvClear.addClass('hide')
}) })
@ -407,7 +424,7 @@ const _handleReference = function (isN2N) {
const $append = $(`<button class="btn btn-secondary mw-auto" type="button" title="${$L('选择默认值')}"><i class="icon zmdi zmdi-search"></i></button>`).appendTo('.J_defaultValue-append') const $append = $(`<button class="btn btn-secondary mw-auto" type="button" title="${$L('选择默认值')}"><i class="icon zmdi zmdi-search"></i></button>`).appendTo('.J_defaultValue-append')
$dv.attr('readonly', true) $dv.attr('readonly', true)
$append.click(() => _showSearcher()) $append.on('click', () => _showSearcher())
window.referenceSearch__call = function (selected) { window.referenceSearch__call = function (selected) {
let val let val
@ -475,5 +492,5 @@ const _handleNumber = function (calcFormula) {
}) })
} }
$el.click(() => renderRbcomp(<FormulaCalc onConfirm={_call} fields={FIELDS_CACHE} />)) $el.on('click', () => renderRbcomp(<FormulaCalc onConfirm={_call} fields={FIELDS_CACHE} />))
} }