@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.
Files changed (93) hide show
  1. package/lib/dynamic-load/preload_data.d.ts +3 -0
  2. package/lib/dynamic-load/preload_data.js +158 -1
  3. package/lib/dynamic-load/preload_data.js.map +1 -1
  4. package/lib/dynamic-load/restrictionRules.d.ts +1 -0
  5. package/lib/dynamic-load/restrictionRules.js +42 -0
  6. package/lib/dynamic-load/restrictionRules.js.map +1 -0
  7. package/lib/dynamic-load/shareRules.d.ts +1 -0
  8. package/lib/dynamic-load/shareRules.js +42 -0
  9. package/lib/dynamic-load/shareRules.js.map +1 -0
  10. package/lib/dynamic-load/trigger.d.ts +1 -3
  11. package/lib/dynamic-load/trigger.js +24 -14
  12. package/lib/dynamic-load/trigger.js.map +1 -1
  13. package/lib/formula/core.js +22 -5
  14. package/lib/formula/core.js.map +1 -1
  15. package/lib/formula/index.d.ts +2 -0
  16. package/lib/formula/index.js +28 -1
  17. package/lib/formula/index.js.map +1 -1
  18. package/lib/formula/simple_params.d.ts +2 -0
  19. package/lib/formula/simple_params.js +91 -0
  20. package/lib/formula/simple_params.js.map +1 -0
  21. package/lib/formula/type.d.ts +3 -2
  22. package/lib/formula/type.js.map +1 -1
  23. package/lib/index.d.ts +3 -0
  24. package/lib/index.js +3 -0
  25. package/lib/index.js.map +1 -1
  26. package/lib/metadata-register/_base.d.ts +3 -1
  27. package/lib/metadata-register/_base.js +16 -5
  28. package/lib/metadata-register/_base.js.map +1 -1
  29. package/lib/metadata-register/permissionFields.d.ts +7 -0
  30. package/lib/metadata-register/permissionFields.js +18 -0
  31. package/lib/metadata-register/permissionFields.js.map +1 -0
  32. package/lib/metadata-register/restrictionRules.d.ts +7 -0
  33. package/lib/metadata-register/restrictionRules.js +18 -0
  34. package/lib/metadata-register/restrictionRules.js.map +1 -0
  35. package/lib/metadata-register/shareRules.d.ts +7 -0
  36. package/lib/metadata-register/shareRules.js +18 -0
  37. package/lib/metadata-register/shareRules.js.map +1 -0
  38. package/lib/ts-types/triggerActionParams.d.ts +1 -0
  39. package/lib/types/field_permission.d.ts +4 -0
  40. package/lib/types/field_permission.js +50 -0
  41. package/lib/types/field_permission.js.map +1 -0
  42. package/lib/types/object.d.ts +1 -0
  43. package/lib/types/object.js +333 -163
  44. package/lib/types/object.js.map +1 -1
  45. package/lib/types/object_dynamic_load.js +13 -4
  46. package/lib/types/object_dynamic_load.js.map +1 -1
  47. package/lib/types/object_permission.d.ts +1 -0
  48. package/lib/types/object_permission.js +31 -0
  49. package/lib/types/object_permission.js.map +1 -1
  50. package/lib/types/restrictionRule.d.ts +13 -0
  51. package/lib/types/restrictionRule.js +75 -0
  52. package/lib/types/restrictionRule.js.map +1 -0
  53. package/lib/types/shareRule.d.ts +13 -0
  54. package/lib/types/shareRule.js +75 -0
  55. package/lib/types/shareRule.js.map +1 -0
  56. package/lib/types/trigger.d.ts +1 -0
  57. package/lib/types/trigger.js.map +1 -1
  58. package/lib/util/field.js +4 -4
  59. package/lib/util/field.js.map +1 -1
  60. package/lib/util/function_expression.d.ts +2 -0
  61. package/lib/util/function_expression.js +66 -0
  62. package/lib/util/function_expression.js.map +1 -0
  63. package/lib/util/index.d.ts +1 -0
  64. package/lib/util/index.js +1 -0
  65. package/lib/util/index.js.map +1 -1
  66. package/lib/util/transform.js +1 -1
  67. package/lib/util/transform.js.map +1 -1
  68. package/package.json +8 -8
  69. package/src/dynamic-load/preload_data.ts +44 -0
  70. package/src/dynamic-load/restrictionRules.ts +19 -0
  71. package/src/dynamic-load/shareRules.ts +19 -0
  72. package/src/dynamic-load/trigger.ts +22 -15
  73. package/src/formula/core.ts +19 -2
  74. package/src/formula/index.ts +21 -1
  75. package/src/formula/simple_params.ts +92 -0
  76. package/src/formula/type.ts +4 -3
  77. package/src/index.ts +4 -1
  78. package/src/metadata-register/_base.ts +14 -3
  79. package/src/metadata-register/permissionFields.ts +13 -0
  80. package/src/metadata-register/restrictionRules.ts +12 -0
  81. package/src/metadata-register/shareRules.ts +13 -0
  82. package/src/ts-types/triggerActionParams.ts +1 -0
  83. package/src/types/field_permission.ts +26 -0
  84. package/src/types/object.ts +207 -28
  85. package/src/types/object_dynamic_load.ts +4 -1
  86. package/src/types/object_permission.ts +32 -0
  87. package/src/types/restrictionRule.ts +57 -0
  88. package/src/types/shareRule.ts +57 -0
  89. package/src/types/trigger.ts +1 -0
  90. package/src/util/field.ts +4 -4
  91. package/src/util/function_expression.ts +63 -0
  92. package/src/util/index.ts +1 -0
  93. package/src/util/transform.ts +1 -1
@@ -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
- declare var Creator: any;
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
- try {
370
- await this._schema.metadataBroker.call(`${trigger.service.name}.${trigger.metadata.action}`, params)
371
- } catch (error) {
372
- console.error(error)
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 ((_.isArray(v) || _.isNull(v))) {
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
- userObjectPermission[k] = _.intersection(v, _v)
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
- if (!objPm.viewAllRecords) {
1548
- sharesFilter = getUserObjectSharesFilters(this.name, userSession);
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(' or ')})`);
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
- if (!objPm.allowEdit) {
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
- if (!objPm.allowDelete) {
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
+ }
@@ -12,6 +12,7 @@ export type SteedosTriggerContextConfig = {
12
12
  previousDoc?: JsonMap, //仅afterUpdate, afterDelete时存在此属性
13
13
  query?: SteedosQueryOptions,
14
14
  data?: JsonMap //仅afterFind,afterCount时存在此属性
15
+ objectName?: string
15
16
  }
16
17
 
17
18
  export type SteedosTriggerTypeConfig = {
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: true });
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: true });
79
- fields.push({ name: 'precision', required: false });
80
- fields.push({ name: 'scale', required: false });
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
+ };