@steedos/objectql 2.1.54 → 2.1.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dynamic-load/preload_data.d.ts +3 -0
- package/lib/dynamic-load/preload_data.js +158 -1
- package/lib/dynamic-load/preload_data.js.map +1 -1
- package/lib/dynamic-load/restrictionRules.d.ts +1 -0
- package/lib/dynamic-load/restrictionRules.js +42 -0
- package/lib/dynamic-load/restrictionRules.js.map +1 -0
- package/lib/dynamic-load/shareRules.d.ts +1 -0
- package/lib/dynamic-load/shareRules.js +42 -0
- package/lib/dynamic-load/shareRules.js.map +1 -0
- package/lib/dynamic-load/trigger.d.ts +1 -3
- package/lib/dynamic-load/trigger.js +24 -14
- package/lib/dynamic-load/trigger.js.map +1 -1
- package/lib/formula/core.js +22 -5
- package/lib/formula/core.js.map +1 -1
- package/lib/formula/index.d.ts +2 -0
- package/lib/formula/index.js +28 -1
- package/lib/formula/index.js.map +1 -1
- package/lib/formula/simple_params.d.ts +2 -0
- package/lib/formula/simple_params.js +91 -0
- package/lib/formula/simple_params.js.map +1 -0
- package/lib/formula/type.d.ts +3 -2
- package/lib/formula/type.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/metadata-register/_base.d.ts +3 -1
- package/lib/metadata-register/_base.js +16 -5
- package/lib/metadata-register/_base.js.map +1 -1
- package/lib/metadata-register/permissionFields.d.ts +7 -0
- package/lib/metadata-register/permissionFields.js +18 -0
- package/lib/metadata-register/permissionFields.js.map +1 -0
- package/lib/metadata-register/restrictionRules.d.ts +7 -0
- package/lib/metadata-register/restrictionRules.js +18 -0
- package/lib/metadata-register/restrictionRules.js.map +1 -0
- package/lib/metadata-register/shareRules.d.ts +7 -0
- package/lib/metadata-register/shareRules.js +18 -0
- package/lib/metadata-register/shareRules.js.map +1 -0
- package/lib/ts-types/triggerActionParams.d.ts +1 -0
- package/lib/types/field_permission.d.ts +4 -0
- package/lib/types/field_permission.js +50 -0
- package/lib/types/field_permission.js.map +1 -0
- package/lib/types/object.d.ts +1 -0
- package/lib/types/object.js +333 -163
- package/lib/types/object.js.map +1 -1
- package/lib/types/object_dynamic_load.js +13 -4
- package/lib/types/object_dynamic_load.js.map +1 -1
- package/lib/types/object_permission.d.ts +1 -0
- package/lib/types/object_permission.js +31 -0
- package/lib/types/object_permission.js.map +1 -1
- package/lib/types/restrictionRule.d.ts +13 -0
- package/lib/types/restrictionRule.js +75 -0
- package/lib/types/restrictionRule.js.map +1 -0
- package/lib/types/shareRule.d.ts +13 -0
- package/lib/types/shareRule.js +75 -0
- package/lib/types/shareRule.js.map +1 -0
- package/lib/types/trigger.d.ts +1 -0
- package/lib/types/trigger.js.map +1 -1
- package/lib/util/field.js +4 -4
- package/lib/util/field.js.map +1 -1
- package/lib/util/function_expression.d.ts +2 -0
- package/lib/util/function_expression.js +66 -0
- package/lib/util/function_expression.js.map +1 -0
- package/lib/util/index.d.ts +1 -0
- package/lib/util/index.js +1 -0
- package/lib/util/index.js.map +1 -1
- package/lib/util/transform.js +1 -1
- package/lib/util/transform.js.map +1 -1
- package/package.json +8 -8
- package/src/dynamic-load/preload_data.ts +44 -0
- package/src/dynamic-load/restrictionRules.ts +19 -0
- package/src/dynamic-load/shareRules.ts +19 -0
- package/src/dynamic-load/trigger.ts +22 -15
- package/src/formula/core.ts +19 -2
- package/src/formula/index.ts +21 -1
- package/src/formula/simple_params.ts +92 -0
- package/src/formula/type.ts +4 -3
- package/src/index.ts +4 -1
- package/src/metadata-register/_base.ts +14 -3
- package/src/metadata-register/permissionFields.ts +13 -0
- package/src/metadata-register/restrictionRules.ts +12 -0
- package/src/metadata-register/shareRules.ts +13 -0
- package/src/ts-types/triggerActionParams.ts +1 -0
- package/src/types/field_permission.ts +26 -0
- package/src/types/object.ts +207 -28
- package/src/types/object_dynamic_load.ts +4 -1
- package/src/types/object_permission.ts +32 -0
- package/src/types/restrictionRule.ts +57 -0
- package/src/types/shareRule.ts +57 -0
- package/src/types/trigger.ts +1 -0
- package/src/util/field.ts +4 -4
- package/src/util/function_expression.ts +63 -0
- package/src/util/index.ts +1 -0
- package/src/util/transform.ts +1 -1
package/src/types/object.ts
CHANGED
|
@@ -15,7 +15,10 @@ import { brokeEmitEvents } from "./object_events";
|
|
|
15
15
|
import { translationObject } from "@steedos/i18n";
|
|
16
16
|
import { getObjectLayouts } from "./object_layouts";
|
|
17
17
|
import { sortBy, forEach } from 'lodash';
|
|
18
|
-
|
|
18
|
+
import { ShareRules } from './shareRule';
|
|
19
|
+
import { RestrictionRule } from './restrictionRule';
|
|
20
|
+
import { FieldPermission } from './field_permission';
|
|
21
|
+
|
|
19
22
|
const clone = require('clone')
|
|
20
23
|
|
|
21
24
|
// 主子表有层级限制,超过3层就报错,该函数判断当前对象作为主表对象往下的层级最多不越过3层,
|
|
@@ -366,11 +369,14 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
366
369
|
|
|
367
370
|
for (const trigger of triggers) {
|
|
368
371
|
let params = generateActionParams(when, context); //参考sf
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
372
|
+
await this._schema.metadataBroker.call(`${trigger.service.name}.${trigger.metadata.action}`, params).catch((error)=>{
|
|
373
|
+
//如果action trigger 下线,则只打印error
|
|
374
|
+
if(error && _.isObject(error) && error.type === 'SERVICE_NOT_AVAILABLE'){
|
|
375
|
+
console.error(`runTriggerActions error`, error)
|
|
376
|
+
}else{
|
|
377
|
+
throw error
|
|
378
|
+
}
|
|
379
|
+
})
|
|
374
380
|
}
|
|
375
381
|
|
|
376
382
|
}
|
|
@@ -631,18 +637,27 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
631
637
|
disabled_actions: null,
|
|
632
638
|
unreadable_fields: null,
|
|
633
639
|
uneditable_fields: null,
|
|
634
|
-
unrelated_objects: null
|
|
640
|
+
unrelated_objects: null,
|
|
641
|
+
field_permissions: null,
|
|
642
|
+
// read_filters: [],
|
|
643
|
+
// edit_filters: []
|
|
635
644
|
}
|
|
636
645
|
|
|
637
646
|
if (_.isEmpty(roles)) {
|
|
638
647
|
throw new Error('not find user permission');
|
|
639
648
|
}
|
|
640
649
|
|
|
650
|
+
const rolesFieldsPermission = await FieldPermission.getObjectFieldsPermissionGroupRole(this.name);
|
|
651
|
+
|
|
641
652
|
roles.forEach((role) => {
|
|
642
|
-
let rolePermission = objectRolesPermission[role]
|
|
653
|
+
let rolePermission = objectRolesPermission[role];
|
|
643
654
|
if (rolePermission) {
|
|
655
|
+
let roleFieldsPermission = rolesFieldsPermission[role];
|
|
644
656
|
_.each(userObjectPermission, (v, k) => {
|
|
645
|
-
let _v = rolePermission[k]
|
|
657
|
+
let _v = rolePermission[k];
|
|
658
|
+
if (k === 'field_permissions') {
|
|
659
|
+
_v = roleFieldsPermission
|
|
660
|
+
}
|
|
646
661
|
if (_.isBoolean(v)) {
|
|
647
662
|
if (v === false && _v === true) {
|
|
648
663
|
userObjectPermission[k] = _v
|
|
@@ -651,20 +666,56 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
651
666
|
if(_.isBoolean(_v)){
|
|
652
667
|
userObjectPermission[k] = _v
|
|
653
668
|
}
|
|
654
|
-
} else if (
|
|
669
|
+
} else if (['read_filters', 'edit_filters'].indexOf(k) > -1) {
|
|
670
|
+
if ('edit_filters' === k) {
|
|
671
|
+
if (!_.isEmpty(_v)) {
|
|
672
|
+
userObjectPermission['read_filters'].push(_v);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
if (!_.isEmpty(_v)) {
|
|
676
|
+
userObjectPermission[k].push(_v);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
else if ((_.isArray(v) || _.isNull(v))) {
|
|
655
680
|
if (!_.isArray(_v)) {
|
|
656
681
|
_v = []
|
|
657
682
|
}
|
|
658
683
|
if (_.isNull(v)) {
|
|
659
684
|
userObjectPermission[k] = _v
|
|
660
685
|
} else {
|
|
661
|
-
|
|
686
|
+
if (k === 'field_permissions') {
|
|
687
|
+
userObjectPermission[k] = _.union(v, _v)
|
|
688
|
+
} else {
|
|
689
|
+
userObjectPermission[k] = _.intersection(v, _v)
|
|
690
|
+
}
|
|
662
691
|
}
|
|
663
692
|
}
|
|
664
693
|
})
|
|
665
694
|
}
|
|
666
|
-
})
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
const field_permissions = {};
|
|
698
|
+
if (userObjectPermission.field_permissions) {
|
|
699
|
+
_.each(userObjectPermission.field_permissions, (field_permission) => {
|
|
700
|
+
const { field, read, edit } = field_permission;
|
|
701
|
+
if (field_permissions[field]) {
|
|
702
|
+
field_permissions[field].edit = field_permissions[field].edit || edit;
|
|
703
|
+
if (field_permissions[field].edit) {
|
|
704
|
+
field_permissions[field].read = true
|
|
705
|
+
} else {
|
|
706
|
+
field_permissions[field].read = field_permissions[field].read || read;
|
|
707
|
+
}
|
|
708
|
+
} else {
|
|
709
|
+
field_permissions[field] = {
|
|
710
|
+
field: field,
|
|
711
|
+
read: edit || read,
|
|
712
|
+
edit: edit
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
})
|
|
716
|
+
}
|
|
667
717
|
|
|
718
|
+
userObjectPermission.field_permissions = field_permissions;
|
|
668
719
|
|
|
669
720
|
userObjectPermission.disabled_list_views = userObjectPermission.disabled_list_views || []
|
|
670
721
|
userObjectPermission.disabled_actions = userObjectPermission.disabled_actions || []
|
|
@@ -677,7 +728,6 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
677
728
|
return Object.assign({}, userObjectPermission, { allowRead: true, viewAllRecords: true, viewCompanyRecords: true })
|
|
678
729
|
}
|
|
679
730
|
|
|
680
|
-
Creator.processPermissions(userObjectPermission)
|
|
681
731
|
return userObjectPermission;
|
|
682
732
|
}
|
|
683
733
|
|
|
@@ -1018,6 +1068,27 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1018
1068
|
})
|
|
1019
1069
|
}
|
|
1020
1070
|
|
|
1071
|
+
// 使用字段级安全性作为限制用户对字段的访问权限的手段;然后使用页面布局主要在选项卡中组织详细信息和编辑页面。这可以减少需要维护的页面布局数量。
|
|
1072
|
+
// 例如,如果字段在页面布局中是必需的,并且在字段级安全性设置中是只读的,则字段级安全性将覆盖页面布局,并且该字段将对用户是只读的。
|
|
1073
|
+
const userObjectFields = objectConfig.fields;
|
|
1074
|
+
_.each(objectConfig.permissions.field_permissions, (field_permission, field) => {
|
|
1075
|
+
const { read, edit } = field_permission;
|
|
1076
|
+
if (read) {
|
|
1077
|
+
userObjectFields[field].omit = true;
|
|
1078
|
+
}
|
|
1079
|
+
if (edit) {
|
|
1080
|
+
userObjectFields[field].omit = false;
|
|
1081
|
+
userObjectFields[field].hidden = false;
|
|
1082
|
+
userObjectFields[field].readonly = false;
|
|
1083
|
+
userObjectFields[field].disabled = false;
|
|
1084
|
+
}
|
|
1085
|
+
if (!read && !edit) {
|
|
1086
|
+
delete userObjectFields[field]
|
|
1087
|
+
}
|
|
1088
|
+
})
|
|
1089
|
+
|
|
1090
|
+
objectConfig.fields = userObjectFields
|
|
1091
|
+
|
|
1021
1092
|
// TODO object layout 是否需要控制审批记录显示?
|
|
1022
1093
|
let spaceProcessDefinition = await getObject("process_definition").directFind({ filters: [['space', '=', userSession.spaceId], ['object_name', '=', this.name], ['active', '=', true]] })
|
|
1023
1094
|
if (spaceProcessDefinition.length > 0) {
|
|
@@ -1253,11 +1324,37 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1253
1324
|
return await this.runTriggerActions(when, context)
|
|
1254
1325
|
}
|
|
1255
1326
|
|
|
1327
|
+
// private async appendRecordPermission(records, userSession) {
|
|
1328
|
+
// const _ids = _.pluck(records, '_id');
|
|
1329
|
+
// const objPm = await this.getUserObjectPermission(userSession);
|
|
1330
|
+
// const permissionFilters = this.getObjectPermissionFilters(objPm, userSession, true);
|
|
1331
|
+
// if (_.isEmpty(permissionFilters)) {
|
|
1332
|
+
// return;
|
|
1333
|
+
// }
|
|
1334
|
+
// const filters = formatFiltersToODataQuery(['_id', 'in', _ids])
|
|
1335
|
+
|
|
1336
|
+
// const results = await this.directFind({
|
|
1337
|
+
// fields: ['_id'],
|
|
1338
|
+
// filters: `(${filters}) and (${permissionFilters.join(' or ')})`
|
|
1339
|
+
// });
|
|
1340
|
+
// const allowEditIds = _.pluck(results, '_id');
|
|
1341
|
+
// _.each(records, (record) => {
|
|
1342
|
+
// if (_.include(allowEditIds, record._id)) {
|
|
1343
|
+
// record.record_permissions = {
|
|
1344
|
+
// allowRead: true,
|
|
1345
|
+
// allowEdit: true,
|
|
1346
|
+
// allowDelete: true,
|
|
1347
|
+
// }
|
|
1348
|
+
// }
|
|
1349
|
+
// })
|
|
1350
|
+
|
|
1351
|
+
// }
|
|
1352
|
+
|
|
1256
1353
|
private async getTriggerContext(when: string, method: string, args: any[], recordId?: string) {
|
|
1257
1354
|
|
|
1258
1355
|
let userSession = args[args.length - 1]
|
|
1259
1356
|
|
|
1260
|
-
let context: SteedosTriggerContextConfig = { userId: userSession ? userSession.userId : undefined, spaceId: userSession ? userSession.spaceId : undefined }
|
|
1357
|
+
let context: SteedosTriggerContextConfig = { objectName: this.name, userId: userSession ? userSession.userId : undefined, spaceId: userSession ? userSession.spaceId : undefined }
|
|
1261
1358
|
|
|
1262
1359
|
if (method === 'find' || method === 'findOne' || method === 'count') {
|
|
1263
1360
|
context.query = args[args.length - 2]
|
|
@@ -1403,7 +1500,16 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1403
1500
|
let values = returnValue || {}
|
|
1404
1501
|
if (method === 'count') {
|
|
1405
1502
|
values = returnValue || 0
|
|
1406
|
-
}
|
|
1503
|
+
}
|
|
1504
|
+
// else{
|
|
1505
|
+
// if (userSession) {
|
|
1506
|
+
// let _records = returnValue
|
|
1507
|
+
// if (method == 'findOne' && returnValue) {
|
|
1508
|
+
// _records = [_records]
|
|
1509
|
+
// }
|
|
1510
|
+
// await this.appendRecordPermission(_records, userSession);
|
|
1511
|
+
// }
|
|
1512
|
+
// }
|
|
1407
1513
|
Object.assign(afterTriggerContext, { data: { values: values } })
|
|
1408
1514
|
}
|
|
1409
1515
|
// console.log("==returnValue==", returnValue);
|
|
@@ -1481,6 +1587,33 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1481
1587
|
}
|
|
1482
1588
|
}
|
|
1483
1589
|
|
|
1590
|
+
// private getObjectPermissionFilters(objectPermission, userSession, isEdit) {
|
|
1591
|
+
// const objectPermissionFilters = [];
|
|
1592
|
+
|
|
1593
|
+
// let permissionFiltersKey = 'read_filters';
|
|
1594
|
+
// if (isEdit) {
|
|
1595
|
+
// permissionFiltersKey = 'edit_filters';
|
|
1596
|
+
// }
|
|
1597
|
+
|
|
1598
|
+
// const globalData = Object.assign({}, userSession, { now: new Date() });
|
|
1599
|
+
|
|
1600
|
+
// let permissionFilters = objectPermission[permissionFiltersKey];
|
|
1601
|
+
|
|
1602
|
+
// _.each(permissionFilters, (permissionFilter) => {
|
|
1603
|
+
// if (_.isString(permissionFilter) && isExpression(permissionFilter.trim())) {
|
|
1604
|
+
// try {
|
|
1605
|
+
// const filters = parseSingleExpression(permissionFilter, {}, "#", globalData);
|
|
1606
|
+
// if (filters && !_.isString(filters)) {
|
|
1607
|
+
// objectPermissionFilters.push(`(${formatFiltersToODataQuery(filters, userSession)})`)
|
|
1608
|
+
// }
|
|
1609
|
+
// } catch (error) {
|
|
1610
|
+
// console.error(`getObjectPermissionFilters error`, permissionFilter, error.message);
|
|
1611
|
+
// }
|
|
1612
|
+
// }
|
|
1613
|
+
// })
|
|
1614
|
+
// return objectPermissionFilters;
|
|
1615
|
+
// }
|
|
1616
|
+
|
|
1484
1617
|
/**
|
|
1485
1618
|
* 把query.filters用formatFiltersToODataQuery转为odata query
|
|
1486
1619
|
* 主要是为了把userSession中的utcOffset逻辑传入formatFiltersToODataQuery函数处理
|
|
@@ -1511,7 +1644,6 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1511
1644
|
if (method === 'aggregate' || method === 'aggregatePrefixalPipeline') {
|
|
1512
1645
|
query = args[args.length - 3];
|
|
1513
1646
|
}
|
|
1514
|
-
|
|
1515
1647
|
if (query.filters && !_.isString(query.filters)) {
|
|
1516
1648
|
query.filters = formatFiltersToODataQuery(query.filters);
|
|
1517
1649
|
}
|
|
@@ -1524,7 +1656,7 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1524
1656
|
return
|
|
1525
1657
|
}
|
|
1526
1658
|
|
|
1527
|
-
let spaceFilter, companyFilter, ownerFilter, sharesFilter, clientFilter = query.filters, filters, permissionFilters = [], userFilters = [];
|
|
1659
|
+
let spaceFilter, companyFilter, ownerFilter, sharesFilter, shareRuleFilters, restrictionRuleFilters, clientFilter = query.filters, filters, permissionFilters = [], userFilters = [];
|
|
1528
1660
|
|
|
1529
1661
|
if (spaceId) {
|
|
1530
1662
|
spaceFilter = `(space eq '${spaceId}')`;
|
|
@@ -1544,12 +1676,27 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1544
1676
|
ownerFilter = `(owner eq '${userId}')`;
|
|
1545
1677
|
}
|
|
1546
1678
|
|
|
1547
|
-
|
|
1548
|
-
|
|
1679
|
+
shareRuleFilters = await ShareRules.getUserObjectFilters(this.name, userSession);
|
|
1680
|
+
|
|
1681
|
+
if (!_.isEmpty(shareRuleFilters)) {
|
|
1682
|
+
permissionFilters.push(`(${shareRuleFilters.join(' or ')})`);
|
|
1549
1683
|
}
|
|
1550
1684
|
|
|
1685
|
+
restrictionRuleFilters = await RestrictionRule.getUserObjectFilters(this.name, userSession);
|
|
1686
|
+
|
|
1687
|
+
if (!_.isEmpty(restrictionRuleFilters)) {
|
|
1688
|
+
userFilters.push(`(${restrictionRuleFilters.join(' or ')})`);
|
|
1689
|
+
}
|
|
1690
|
+
// objectPermissionFilters = this.getObjectPermissionFilters(objPm, userSession, false);
|
|
1691
|
+
|
|
1692
|
+
// if (!_.isEmpty(objectPermissionFilters)) {
|
|
1693
|
+
// permissionFilters.push(`(${objectPermissionFilters.join(' or ')})`);
|
|
1694
|
+
// }
|
|
1695
|
+
|
|
1696
|
+
sharesFilter = getUserObjectSharesFilters(this.name, userSession);
|
|
1697
|
+
|
|
1551
1698
|
if (!_.isEmpty(companyFilter)) {
|
|
1552
|
-
permissionFilters.push(`(${companyFilter.join('
|
|
1699
|
+
permissionFilters.push(`(${companyFilter.join(' and ')})`);
|
|
1553
1700
|
}
|
|
1554
1701
|
|
|
1555
1702
|
if (ownerFilter) {
|
|
@@ -1584,9 +1731,14 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1584
1731
|
}
|
|
1585
1732
|
}
|
|
1586
1733
|
else if (method === 'update' || method === 'updateOne') {
|
|
1587
|
-
|
|
1734
|
+
const permissionFilters = null; //this.getObjectPermissionFilters(objPm, userSession, true);
|
|
1735
|
+
if (!objPm.allowEdit && _.isEmpty(permissionFilters)) {
|
|
1588
1736
|
throw new Error(`no ${method} permission!`);
|
|
1589
1737
|
}
|
|
1738
|
+
let objectPermissionEditFilters = '';
|
|
1739
|
+
if (!_.isEmpty(permissionFilters)) {
|
|
1740
|
+
objectPermissionEditFilters = ` or (${permissionFilters.join(' or ')})`
|
|
1741
|
+
}
|
|
1590
1742
|
let id = args[args.length - 3];
|
|
1591
1743
|
if (!objPm.modifyAllRecords && objPm.modifyCompanyRecords) {
|
|
1592
1744
|
let companyFilters = _.map(userSession.companies, function (comp: any) {
|
|
@@ -1594,25 +1746,35 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1594
1746
|
}).join(' or ')
|
|
1595
1747
|
if (companyFilters) {
|
|
1596
1748
|
if (_.isString(id)) {
|
|
1597
|
-
id = { filters: `(_id eq \'${id}\') and (${companyFilters})` }
|
|
1749
|
+
id = { filters: `(_id eq \'${id}\') and (${companyFilters}${objectPermissionEditFilters})` }
|
|
1598
1750
|
}
|
|
1599
1751
|
else if (_.isObject(id)) {
|
|
1600
1752
|
if (id.filters && !_.isString(id.filters)) {
|
|
1601
1753
|
id.filters = formatFiltersToODataQuery(id.filters);
|
|
1602
1754
|
}
|
|
1603
|
-
id.filters = id.filters ? `(${id.filters}) and (${companyFilters})` : `(${companyFilters})`;
|
|
1755
|
+
id.filters = id.filters ? `(${id.filters}) and (${companyFilters}${objectPermissionEditFilters})` : `(${companyFilters}${objectPermissionEditFilters})`;
|
|
1604
1756
|
}
|
|
1605
1757
|
}
|
|
1606
1758
|
}
|
|
1607
1759
|
else if (!objPm.modifyAllRecords && !objPm.modifyCompanyRecords && objPm.allowEdit) {
|
|
1608
1760
|
if (_.isString(id)) {
|
|
1609
|
-
id = { filters: `(_id eq \'${id}\') and (owner eq \'${userId}\')` }
|
|
1761
|
+
id = { filters: `(_id eq \'${id}\') and (owner eq \'${userId}\' ${objectPermissionEditFilters})` }
|
|
1610
1762
|
}
|
|
1611
1763
|
else if (_.isObject(id)) {
|
|
1612
1764
|
if (id.filters && !_.isString(id.filters)) {
|
|
1613
1765
|
id.filters = formatFiltersToODataQuery(id.filters);
|
|
1614
1766
|
}
|
|
1615
|
-
id.filters = id.filters ? `(${id.filters}) and (owner eq \'${userId}\')` : `(owner eq \'${userId}\')`;
|
|
1767
|
+
id.filters = id.filters ? `(${id.filters}) and (owner eq \'${userId}\' ${objectPermissionEditFilters})` : `(owner eq \'${userId}\' ${objectPermissionEditFilters})`;
|
|
1768
|
+
}
|
|
1769
|
+
} else if (objectPermissionEditFilters) {
|
|
1770
|
+
if (_.isString(id)) {
|
|
1771
|
+
id = { filters: `(_id eq \'${id}\') and (${objectPermissionEditFilters})` }
|
|
1772
|
+
}
|
|
1773
|
+
else if (_.isObject(id)) {
|
|
1774
|
+
if (id.filters && !_.isString(id.filters)) {
|
|
1775
|
+
id.filters = formatFiltersToODataQuery(id.filters);
|
|
1776
|
+
}
|
|
1777
|
+
id.filters = id.filters ? `(${id.filters}) and (${objectPermissionEditFilters})` : `(${objectPermissionEditFilters})`;
|
|
1616
1778
|
}
|
|
1617
1779
|
}
|
|
1618
1780
|
args[args.length - 3] = id;
|
|
@@ -1636,20 +1798,37 @@ export class SteedosObjectType extends SteedosObjectProperties {
|
|
|
1636
1798
|
}
|
|
1637
1799
|
}
|
|
1638
1800
|
else if (method === 'delete') {
|
|
1639
|
-
|
|
1801
|
+
const permissionFilters = null; //this.getObjectPermissionFilters(objPm, userSession, true);
|
|
1802
|
+
if (!objPm.allowDelete && _.isEmpty(permissionFilters)) {
|
|
1640
1803
|
throw new Error(`no ${method} permission!`);
|
|
1641
1804
|
}
|
|
1805
|
+
|
|
1806
|
+
let objectPermissionEditFilters = '';
|
|
1807
|
+
if (!_.isEmpty(permissionFilters)) {
|
|
1808
|
+
objectPermissionEditFilters = ` or (${permissionFilters.join(' or ')})`
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1642
1811
|
let id = args[args.length - 2];
|
|
1643
1812
|
if (!objPm.modifyAllRecords && objPm.modifyCompanyRecords) {
|
|
1644
1813
|
let companyFilters = _.map(userSession.companies, function (comp: any) {
|
|
1645
1814
|
return `(company_id eq '${comp._id}') or (company_ids eq '${comp._id}')`
|
|
1646
1815
|
}).join(' or ')
|
|
1647
1816
|
if (companyFilters) {
|
|
1648
|
-
id = { filters: `(_id eq \'${id}\') and (${companyFilters})` };
|
|
1817
|
+
id = { filters: `(_id eq \'${id}\') and (${companyFilters}${objectPermissionEditFilters})` };
|
|
1649
1818
|
}
|
|
1650
1819
|
}
|
|
1651
1820
|
else if (!objPm.modifyAllRecords && !objPm.modifyCompanyRecords) {
|
|
1652
|
-
id = { filters: `(_id eq \'${id}\') and (owner eq \'${userId}\')` };
|
|
1821
|
+
id = { filters: `(_id eq \'${id}\') and (owner eq \'${userId}\'${objectPermissionEditFilters})` };
|
|
1822
|
+
} else if (objectPermissionEditFilters) {
|
|
1823
|
+
if (_.isString(id)) {
|
|
1824
|
+
id = { filters: `(_id eq \'${id}\') and (${objectPermissionEditFilters})` }
|
|
1825
|
+
}
|
|
1826
|
+
else if (_.isObject(id)) {
|
|
1827
|
+
if (id.filters && !_.isString(id.filters)) {
|
|
1828
|
+
id.filters = formatFiltersToODataQuery(id.filters);
|
|
1829
|
+
}
|
|
1830
|
+
id.filters = id.filters ? `(${id.filters}) and (${objectPermissionEditFilters})` : `(${objectPermissionEditFilters})`;
|
|
1831
|
+
}
|
|
1653
1832
|
}
|
|
1654
1833
|
args[args.length - 2] = id;
|
|
1655
1834
|
}
|
|
@@ -3,7 +3,7 @@ import path = require('path')
|
|
|
3
3
|
import { SteedosObjectTypeConfig, SteedosObjectPermissionTypeConfig, SteedosActionTypeConfig, getDataSource } from '.'
|
|
4
4
|
// import { isMeteor } from '../util'
|
|
5
5
|
import { Dictionary } from '@salesforce/ts-types';
|
|
6
|
-
import { loadObjectFields, loadObjectListViews, loadObjectButtons, loadObjectMethods, loadObjectActions, loadObjectTriggers, addObjectListenerConfig, loadObjectLayouts, getLazyLoadFields, getLazyLoadButtons, loadObjectPermissions, loadSourceProfiles, loadSourcePermissionset, loadObjectValidationRules, loadSourceRoles, loadSourceFlowRoles, loadSourceApprovalProcesses, loadSourceWorkflows, loadStandardProfiles, loadStandardPermissionsets, preloadDBObjectFields, preloadDBObjectButtons, preloadDBApps, preloadDBObjectLayouts, preloadDBTabs } from '../dynamic-load'
|
|
6
|
+
import { loadObjectFields, loadObjectListViews, loadObjectButtons, loadObjectMethods, loadObjectActions, loadObjectTriggers, addObjectListenerConfig, loadObjectLayouts, getLazyLoadFields, getLazyLoadButtons, loadObjectPermissions, loadSourceProfiles, loadSourcePermissionset, loadObjectValidationRules, loadSourceRoles, loadSourceFlowRoles, loadSourceApprovalProcesses, loadSourceWorkflows, loadStandardProfiles, loadStandardPermissionsets, preloadDBObjectFields, preloadDBObjectButtons, preloadDBApps, preloadDBObjectLayouts, preloadDBTabs, preloadDBShareRules, preloadDBRestrictionRules, preloadDBPermissionFields } from '../dynamic-load'
|
|
7
7
|
import { transformListenersToTriggers } from '..';
|
|
8
8
|
import { getSteedosSchema } from './schema';
|
|
9
9
|
|
|
@@ -338,6 +338,9 @@ export const loadStandardMetadata = async (serviceName: string, datasourceApiNam
|
|
|
338
338
|
await preloadDBObjectLayouts(datasource);
|
|
339
339
|
await preloadDBObjectFields(datasource);
|
|
340
340
|
await preloadDBObjectButtons(datasource);
|
|
341
|
+
await preloadDBShareRules(datasource);
|
|
342
|
+
await preloadDBRestrictionRules(datasource);
|
|
343
|
+
await preloadDBPermissionFields(datasource);
|
|
341
344
|
}
|
|
342
345
|
}
|
|
343
346
|
}
|
|
@@ -22,6 +22,7 @@ abstract class SteedosObjectPermissionTypeProperties {
|
|
|
22
22
|
unreadable_fields?: string[]
|
|
23
23
|
uneditable_fields?: string[]
|
|
24
24
|
unrelated_objects?: string[]
|
|
25
|
+
field_permissions?: any
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export interface SteedosObjectPermissionTypeConfig extends SteedosObjectPermissionTypeProperties { }
|
|
@@ -71,6 +72,37 @@ export class SteedosObjectPermissionType extends SteedosObjectPermissionTypeProp
|
|
|
71
72
|
this.allowRead = true;
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
if (this.allowRead) {
|
|
76
|
+
typeof this.allowReadFiles !== "boolean" && (this.allowReadFiles = true);
|
|
77
|
+
typeof this.viewAllFiles !== "boolean" && (this.viewAllFiles = true);
|
|
78
|
+
}
|
|
79
|
+
if (this.allowEdit) {
|
|
80
|
+
typeof this.allowCreateFiles !== "boolean" && (this.allowCreateFiles = true);
|
|
81
|
+
typeof this.allowEditFiles !== "boolean" && (this.allowEditFiles = true);
|
|
82
|
+
typeof this.allowDeleteFiles !== "boolean" && (this.allowDeleteFiles = true);
|
|
83
|
+
}
|
|
84
|
+
if (this.modifyAllRecords) {
|
|
85
|
+
typeof this.modifyAllFiles !== "boolean" && (this.modifyAllFiles = true);
|
|
86
|
+
}
|
|
87
|
+
if (this.allowCreateFiles) {
|
|
88
|
+
this.allowReadFiles = true;
|
|
89
|
+
}
|
|
90
|
+
if (this.allowEditFiles) {
|
|
91
|
+
this.allowReadFiles = true;
|
|
92
|
+
}
|
|
93
|
+
if (this.allowDeleteFiles) {
|
|
94
|
+
this.allowEditFiles = true;
|
|
95
|
+
this.allowReadFiles = true;
|
|
96
|
+
}
|
|
97
|
+
if (this.viewAllFiles) {
|
|
98
|
+
this.allowReadFiles = true;
|
|
99
|
+
}
|
|
100
|
+
if (this.modifyAllFiles) {
|
|
101
|
+
this.allowReadFiles = true;
|
|
102
|
+
this.allowEditFiles = true;
|
|
103
|
+
this.allowDeleteFiles = true;
|
|
104
|
+
this.viewAllFiles = true;
|
|
105
|
+
}
|
|
74
106
|
this.object_name = object_name
|
|
75
107
|
}
|
|
76
108
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { registerRestrictionRules } from '../metadata-register/restrictionRules';
|
|
2
|
+
import { getSteedosSchema } from '../types'
|
|
3
|
+
import * as _ from 'lodash'
|
|
4
|
+
import { isExpression, parseSingleExpression } from '../util'
|
|
5
|
+
import { formatFiltersToODataQuery } from "@steedos/filters";
|
|
6
|
+
|
|
7
|
+
export type SteedosRestrictionRuleConfig = {
|
|
8
|
+
_id: string,
|
|
9
|
+
name: string,
|
|
10
|
+
object_name: string,
|
|
11
|
+
active: boolean,
|
|
12
|
+
record_filter: string,
|
|
13
|
+
entry_criteria: string,
|
|
14
|
+
description: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class RestrictionRule {
|
|
18
|
+
static async find(objectApiName) {
|
|
19
|
+
const schema = getSteedosSchema();
|
|
20
|
+
return await registerRestrictionRules.find(schema.broker, {
|
|
21
|
+
pattern: `${objectApiName}.*`
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
static async getUserObjectFilters(objectApiName, userSession: any) {
|
|
25
|
+
const rules = await this.find(objectApiName);
|
|
26
|
+
if (_.isEmpty(rules)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const rulesFilters = [];
|
|
30
|
+
const globalData = { now: new Date() };
|
|
31
|
+
_.each(rules, (rule) => {
|
|
32
|
+
const { active, entry_criteria, record_filter } = rule.metadata;
|
|
33
|
+
if (active) {
|
|
34
|
+
if (_.isString(entry_criteria) && isExpression(entry_criteria.trim())) {
|
|
35
|
+
try {
|
|
36
|
+
const meetCriteria = parseSingleExpression(entry_criteria, {}, "#", globalData, userSession);
|
|
37
|
+
if (_.isBoolean(meetCriteria) && meetCriteria) {
|
|
38
|
+
if (_.isString(record_filter) && isExpression(record_filter.trim())) {
|
|
39
|
+
try {
|
|
40
|
+
const filters = parseSingleExpression(record_filter, {}, "#", globalData, userSession);
|
|
41
|
+
if (filters && !_.isString(filters)) {
|
|
42
|
+
rulesFilters.push(`(${formatFiltersToODataQuery(filters, userSession)})`)
|
|
43
|
+
}
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error(`RestrictionRule.getUserObjectFilters record_filter error`, objectApiName, record_filter, error.message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error(`RestrictionRule.getUserObjectFilters entry_criteria error`, objectApiName, entry_criteria, error.message);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
return rulesFilters;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { registerShareRules } from '../metadata-register/shareRules';
|
|
2
|
+
import { getSteedosSchema } from '../types'
|
|
3
|
+
import * as _ from 'lodash'
|
|
4
|
+
import { isExpression, parseSingleExpression } from '../util'
|
|
5
|
+
import { formatFiltersToODataQuery } from "@steedos/filters";
|
|
6
|
+
|
|
7
|
+
export type SteedosShareRuleConfig = {
|
|
8
|
+
_id: string,
|
|
9
|
+
name: string,
|
|
10
|
+
object_name: string,
|
|
11
|
+
active: boolean,
|
|
12
|
+
record_filter: string,
|
|
13
|
+
entry_criteria: string,
|
|
14
|
+
description: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class ShareRules {
|
|
18
|
+
static async find(objectApiName) {
|
|
19
|
+
const schema = getSteedosSchema();
|
|
20
|
+
return await registerShareRules.find(schema.broker, {
|
|
21
|
+
pattern: `${objectApiName}.*`
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
static async getUserObjectFilters(objectApiName, userSession: any) {
|
|
25
|
+
const rules = await this.find(objectApiName);
|
|
26
|
+
if (_.isEmpty(rules)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const rulesFilters = [];
|
|
30
|
+
const globalData = { now: new Date() };
|
|
31
|
+
_.each(rules, (rule) => {
|
|
32
|
+
const { active, entry_criteria, record_filter } = rule.metadata;
|
|
33
|
+
if (active) {
|
|
34
|
+
if (_.isString(entry_criteria) && isExpression(entry_criteria.trim())) {
|
|
35
|
+
try {
|
|
36
|
+
const meetCriteria = parseSingleExpression(entry_criteria, {}, "#", globalData, userSession);
|
|
37
|
+
if (_.isBoolean(meetCriteria) && meetCriteria) {
|
|
38
|
+
if (_.isString(record_filter) && isExpression(record_filter.trim())) {
|
|
39
|
+
try {
|
|
40
|
+
const filters = parseSingleExpression(record_filter, {}, "#", globalData, userSession);
|
|
41
|
+
if (filters && !_.isString(filters)) {
|
|
42
|
+
rulesFilters.push(`(${formatFiltersToODataQuery(filters, userSession)})`)
|
|
43
|
+
}
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error(`ShareRules.getUserObjectFilters record_filter error`, objectApiName, record_filter, error.message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error(`ShareRules.getUserObjectFilters entry_criteria error`, objectApiName, entry_criteria, error.message);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
return rulesFilters;
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/types/trigger.ts
CHANGED
package/src/util/field.ts
CHANGED
|
@@ -71,13 +71,13 @@ export const getFieldsByType = (doc, type: string, dataType?: string) => {
|
|
|
71
71
|
fields.push({ name: 'formula_blank_value', required: false });
|
|
72
72
|
fields.push({ name: 'summary_object', required: true });
|
|
73
73
|
fields.push({ name: 'summary_type', required: true });
|
|
74
|
-
fields.push({ name: 'summary_filters', required:
|
|
74
|
+
fields.push({ name: 'summary_filters', required: false });
|
|
75
75
|
if (doc.summary_type != 'count') {
|
|
76
76
|
fields.push({ name: 'summary_field', required: true });
|
|
77
77
|
}
|
|
78
|
-
fields.push({ name: 'data_type', required:
|
|
79
|
-
fields.push({ name: 'precision', required:
|
|
80
|
-
fields.push({ name: 'scale', required:
|
|
78
|
+
fields.push({ name: 'data_type', required: false });
|
|
79
|
+
fields.push({ name: 'precision', required: true });
|
|
80
|
+
fields.push({ name: 'scale', required: true });
|
|
81
81
|
fields.push({ name: 'filters' });
|
|
82
82
|
fields.push({ name: 'filters.$' });
|
|
83
83
|
fields.push({ name: 'filters.$.field' });
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as _ from 'lodash'
|
|
2
|
+
|
|
3
|
+
const globalTag = '__G_L_O_B_A_L__';
|
|
4
|
+
|
|
5
|
+
const getParentPath = function (path) {
|
|
6
|
+
var pathArr;
|
|
7
|
+
if (typeof path === 'string') {
|
|
8
|
+
pathArr = path.split('.');
|
|
9
|
+
if (pathArr.length === 1) {
|
|
10
|
+
return '#';
|
|
11
|
+
}
|
|
12
|
+
pathArr.pop();
|
|
13
|
+
return pathArr.join('.');
|
|
14
|
+
}
|
|
15
|
+
return '#';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const getValueByPath = function (formData, path) {
|
|
19
|
+
if (path === '#' || !path) {
|
|
20
|
+
return formData || {};
|
|
21
|
+
} else if (typeof path === 'string') {
|
|
22
|
+
return _.get(formData, path);
|
|
23
|
+
} else {
|
|
24
|
+
console.error('path has to be a string');
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const isExpression = function (func) {
|
|
29
|
+
var pattern, reg1, reg2;
|
|
30
|
+
if (typeof func !== 'string') {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
pattern = /^{{(.+)}}$/;
|
|
34
|
+
reg1 = /^{{(function.+)}}$/;
|
|
35
|
+
reg2 = /^{{(.+=>.+)}}$/;
|
|
36
|
+
if (typeof func === 'string' && func.match(pattern) && !func.match(reg1) && !func.match(reg2)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const parseSingleExpression = function (func, formData, dataPath, global, userSession = {}) {
|
|
43
|
+
var error, funcBody, parent, parentPath, str;
|
|
44
|
+
|
|
45
|
+
if (formData === void 0) {
|
|
46
|
+
formData = {};
|
|
47
|
+
}
|
|
48
|
+
parentPath = getParentPath(dataPath);
|
|
49
|
+
parent = getValueByPath(formData, parentPath) || {};
|
|
50
|
+
if (typeof func === 'string') {
|
|
51
|
+
funcBody = func.substring(2, func.length - 2);
|
|
52
|
+
str = `\n var $user=${JSON.stringify(userSession)}; return ` + funcBody.replace(/\bformData\b/g, JSON.stringify(formData).replace(/\bglobal\b/g, globalTag)).replace(/\bglobal\b/g, JSON.stringify(global)).replace(new RegExp('\\b' + globalTag + '\\b', 'g'), 'global').replace(/rootValue/g, JSON.stringify(parent));
|
|
53
|
+
try {
|
|
54
|
+
return Function(str)();
|
|
55
|
+
} catch (_error) {
|
|
56
|
+
error = _error;
|
|
57
|
+
console.log(error, func, dataPath);
|
|
58
|
+
return func;
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
return func;
|
|
62
|
+
}
|
|
63
|
+
};
|