@steedos/standard-object-database 2.5.0-beta.9 → 2.5.0

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 (26) hide show
  1. package/main/default/objectTranslations/object_fields.en/object_fields.en.objectTranslation.yml +2 -2
  2. package/main/default/objectTranslations/object_fields.zh-CN/object_fields.zh-CN.objectTranslation.yml +2 -2
  3. package/main/default/objectTranslations/object_triggers.zh-CN/object_triggers.zh-CN.objectTranslation.yml +3 -5
  4. package/main/default/objects/13.permission_fields.observe.object.js +3 -0
  5. package/main/default/objects/14.object_fields.observe.object.js +3 -3
  6. package/main/default/objects/15.permission_objects.observe.object.js +5 -2
  7. package/main/default/objects/2.object_triggers.observe.object.js +42 -34
  8. package/main/default/objects/3.permission_objects.observe.object.js +39 -6
  9. package/main/default/objects/datasources.object.js +4 -0
  10. package/main/default/objects/datasources.object.yml +10 -0
  11. package/main/default/objects/object_actions.object.yml +16 -10
  12. package/main/default/objects/object_fields.object.js +1 -1
  13. package/main/default/objects/object_fields.object.yml +142 -25
  14. package/main/default/objects/object_triggers.object.yml +56 -52
  15. package/main/default/objects/objects.core.js +0 -28
  16. package/main/default/objects/objects.object.yml +1 -1
  17. package/main/default/pages/object_detail.page.amis.json +37 -3
  18. package/main/default/routes/amis_button_design.ejs +6 -5
  19. package/main/default/routes/amis_listview_design.router.js +1 -1
  20. package/main/default/services/database-objects.service.js +137 -0
  21. package/main/default/services/suggestions.service.js +187 -0
  22. package/main/default/triggers/datasources.trigger.js +16 -29
  23. package/main/default/triggers/object_triggers.trigger.js +78 -33
  24. package/package.json +2 -2
  25. package/main/default/objects/object_triggers.core.js +0 -58
  26. package/main/default/objects/object_triggers.object.js +0 -65
@@ -9,23 +9,30 @@ const auth = require('@steedos/auth');
9
9
  const _ = require('underscore');
10
10
  //由于新版lookup 组件限制。需编写trigger处理在只读页面不显示已选中项的问题
11
11
  //由于lookup组件强依赖_id 字段,所以必须返回_id
12
+
13
+ const PERMISSIONS = {
14
+ allowEdit: false,
15
+ allowDelete: false,
16
+ allowRead: true,
17
+ };
18
+
19
+ const BASERECORD = {
20
+ is_system: true,
21
+ record_permissions: PERMISSIONS
22
+ };
23
+
12
24
  module.exports = {
13
25
 
14
26
  beforeFind: async function () {
15
27
  delete this.query.fields;
16
28
  },
17
-
18
- beforeAggregate: async function () {
19
- delete this.query.fields;
20
- },
21
-
22
29
  afterFind: async function(){
23
30
  const { spaceId } = this;
24
31
  let lng = Steedos.locale(this.userId, true);
25
- let dataList = [{_id: 'default', name: 'default', label: TAPi18n.__(`objects_field_datasource_defaultValue`, {}, lng)}];
32
+ let dataList = [{_id: 'default', name: 'default', label: TAPi18n.__(`objects_field_datasource_defaultValue`, {}, lng), ...BASERECORD}];
26
33
  let filters = InternalData.parserFilters(this.query.filters)
27
34
  if(filters._id === 'meteor'){
28
- dataList.push({_id: 'meteor', name: 'meteor', label: TAPi18n.__(`objects_field_datasource_meteor`, {}, lng)})
35
+ dataList.push({_id: 'meteor', name: 'meteor', label: TAPi18n.__(`objects_field_datasource_meteor`, {}, lng), ...BASERECORD})
29
36
  }
30
37
  if (!_.isEmpty(dataList)) {
31
38
  dataList.forEach((doc) => {
@@ -44,26 +51,6 @@ module.exports = {
44
51
  }
45
52
 
46
53
  },
47
- afterAggregate: async function(){
48
- const { spaceId } = this;
49
- let lng = Steedos.locale(this.userId, true)
50
- let dataList = [{_id: 'default', name: 'default', label: TAPi18n.__(`objects_field_datasource_defaultValue`, {}, lng)}];
51
- if (!_.isEmpty(dataList)) {
52
- dataList.forEach((doc) => {
53
- if (!_.find(this.data.values, (value) => {
54
- return value.name === doc.name
55
- })) {
56
- this.data.values.push(doc);
57
- }
58
- })
59
- const records = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, spaceId);
60
- if (records.length > 0) {
61
- this.data.values = records;
62
- } else {
63
- this.data.values.length = 0;
64
- }
65
- }
66
- },
67
54
  afterCount: async function(){
68
55
  delete this.query.fields;
69
56
  let result = await objectql.getObject(this.object_name).find(this.query, await auth.getSessionByUserId(this.userId, this.spaceId))
@@ -74,7 +61,7 @@ module.exports = {
74
61
  if(this.id === 'default'){
75
62
  try {
76
63
  let lng = Steedos.locale(this.userId, true)
77
- this.data.values = {_id: 'default', name: 'default', label: TAPi18n.__(`objects_field_datasource_defaultValue`, {}, lng)};
64
+ this.data.values = {_id: 'default', name: 'default', label: TAPi18n.__(`objects_field_datasource_defaultValue`, {}, lng), ...BASERECORD};
78
65
  } catch (error) {
79
66
 
80
67
  }
@@ -82,7 +69,7 @@ module.exports = {
82
69
  if(this.id === 'meteor'){
83
70
  try {
84
71
  let lng = Steedos.locale(this.userId, true)
85
- this.data.values = {_id: 'meteor', name: 'meteor', label: TAPi18n.__(`objects_field_datasource_meteor`, {}, lng)};
72
+ this.data.values = {_id: 'meteor', name: 'meteor', label: TAPi18n.__(`objects_field_datasource_meteor`, {}, lng), ...BASERECORD};
86
73
  } catch (error) {
87
74
 
88
75
  }
@@ -1,50 +1,95 @@
1
1
  /*
2
2
  * @Author: sunhaolin@hotoa.com
3
3
  * @Date: 2021-06-03 15:11:52
4
- * @LastEditors: sunhaolin@hotoa.com
5
- * @LastEditTime: 2022-07-29 11:31:59
4
+ * @LastEditors: baozhoutao@steedos.com
5
+ * @LastEditTime: 2023-05-15 09:26:19
6
6
  * @Description:
7
7
  */
8
- const InternalData = require('@steedos/standard-objects').internalData;
8
+ const Cache = require('@steedos/cachers');
9
+ const _ = require('lodash');
10
+ const objectql = require('@steedos/objectql');
11
+ const PERMISSIONS = {
12
+ allowEdit: false,
13
+ allowDelete: false,
14
+ allowRead: true,
15
+ };
16
+
17
+ const BASERECORD = {
18
+ is_system: true,
19
+ record_permissions: PERMISSIONS
20
+ };
21
+
22
+ const getSourceTriggers = async()=>{
23
+ const data = _.map(_.filter(Cache.getCacher('triggers').get('triggers'), (item)=>{
24
+ return !item.metadata._id || item.metadata._id == item.metadata.name
25
+ }), (item)=>{
26
+ return {
27
+ ...item.metadata,
28
+ _id: item.metadata.name,
29
+ ...BASERECORD
30
+ };
31
+ });
32
+ return data;
33
+ }
34
+
35
+ function checkVariableName(variableName){
36
+ if(variableName.length > 50){
37
+ throw new Error("名称长度不能大于50个字符");
38
+ }
39
+ var reg = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
40
+ if(reg.test(variableName)){
41
+ var keywords = ['break', 'case', 'catch', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'finally', 'for', 'function', 'if', 'in', 'instanceof', 'new', 'return', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with', 'true', 'false', 'null', 'undefined', 'NaN', 'Infinity'];
42
+ if(keywords.indexOf(variableName) === -1){
43
+ return true;
44
+ } else {
45
+ throw new Error("名称不能包含关键字");
46
+ }
47
+ } else {
48
+ throw new Error("名称只能包含字母、数字,必须以字母开头");
49
+ }
50
+ }
9
51
 
10
52
  module.exports = {
53
+ beforeFind: async function () {
54
+ delete this.query.fields;
55
+ },
11
56
  afterFind: async function(){
12
- let filters = InternalData.parserFilters(this.query.filters)
13
- if(filters.object){
14
- let triggers = await InternalData.getObjectTriggers(filters.object, this.userId);
15
- if(triggers){
16
- this.data.values = this.data.values.concat(triggers)
17
- }
18
- }
57
+ let spaceId = this.spaceId;
58
+ let sourceData = await getSourceTriggers();
59
+ this.data.values = this.data.values.concat(sourceData);
60
+ this.data.values = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, spaceId);
61
+ },
62
+ afterCount: async function(){
63
+ let spaceId = this.spaceId;
64
+ this.data.values = this.data.values + objectql.getSteedosSchema().metadataDriver.count(await getSourceTriggers(), this.query, spaceId);
19
65
  },
20
- afterAggregate: async function(){
21
- let filters = InternalData.parserFilters(this.query.filters)
22
- if(filters.object){
23
- let triggers = await InternalData.getObjectTriggers(filters.object, this.userId);
24
- if(triggers){
25
- this.data.values = this.data.values.concat(triggers)
66
+ afterFindOne: async function(){
67
+ let spaceId = this.spaceId;
68
+ if(_.isEmpty(this.data.values)){
69
+ const records = objectql.getSteedosSchema().metadataDriver.find(await getSourceTriggers(), {filters: ['_id', '=', this.id]}, spaceId);
70
+ if(records.length > 0){
71
+ this.data.values = records[0]
26
72
  }
27
73
  }
28
74
  },
29
- afterCount: async function(){
30
- let filters = InternalData.parserFilters(this.query.filters)
31
- if(filters.object){
32
- let triggers = await InternalData.getObjectTriggers(filters.object, this.userId);
33
- if(triggers){
34
- this.data.values = this.data.values + triggers.length
35
- }
75
+ beforeInsert: async function(){
76
+ const doc = this.doc;
77
+ checkVariableName(doc._name)
78
+ const count = await objectql.getObject('object_triggers').count({filters: [['_name', '=', doc._name], ['listenTo','=', doc.listenTo]]})
79
+ if(count > 0){
80
+ throw new Error('触发器名称不能重复')
36
81
  }
82
+ doc.name = `${doc.listenTo}_${doc._name}`
37
83
  },
38
- afterFindOne: async function(){
39
- if(_.isEmpty(this.data.values)){
40
- let id = this.id
41
- let objectName = id.substr(0, id.indexOf("."));
42
- if(objectName){
43
- let trigger = await InternalData.getObjectTrigger(objectName, this.userId, id);
44
- if(trigger){
45
- this.data.values = trigger;
46
- }
47
- }
84
+ beforeUpdate: async function () {
85
+ const doc = this.doc;
86
+ if(doc._name){
87
+ checkVariableName(doc._name)
88
+ }
89
+ const count = await objectql.getObject('object_triggers').count({filters: [['_name', '=', doc._name], ['listenTo','=', doc.listenTo], ['_id', '!=', this.id]]})
90
+ if(count > 0){
91
+ throw new Error('触发器名称不能重复')
48
92
  }
93
+ doc.name = `${doc.listenTo}_${doc._name}`
49
94
  }
50
95
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steedos/standard-object-database",
3
- "version": "2.5.0-beta.9",
3
+ "version": "2.5.0",
4
4
  "main": "package.service.js",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -15,5 +15,5 @@
15
15
  },
16
16
  "repository": {},
17
17
  "license": "MIT",
18
- "gitHead": "a2623b433dd42632dc54d23c51b718bd4d1a2fdc"
18
+ "gitHead": "c4b366d1366ab52eb53da1a3ff4a80b16fd73cc0"
19
19
  }
@@ -1,58 +0,0 @@
1
- var objectql = require('@steedos/objectql');
2
- var objectCore = require('./objects.lib.js');
3
- const defaultDatasourceName = 'default';
4
- function reloadObject(objectName, objectDataSourceName){
5
- const datasource = objectql.getDataSource(objectDataSourceName);
6
- if(!datasource){
7
- return
8
- }
9
- //获取到最新的对象
10
- const object = objectql.getObjectConfig(objectName);
11
- datasource.setObject(object.name, object);
12
- try {
13
- if(!objectDataSourceName || objectDataSourceName == defaultDatasourceName){
14
- Creator.Objects[object.name] = object;
15
- Creator.loadObjects(object, object.name);
16
- }
17
- } catch (error) {
18
- console.log('error', error);
19
- }
20
- }
21
-
22
- function loadObjectTrigger(doc){
23
- var dbObject = objectCore.getObjectFromDB(doc.object);
24
- var objectDataSourceName = objectCore.getDataSourceName(dbObject);
25
-
26
- if(!dbObject || !objectCore.canLoadObject(dbObject.name, objectDataSourceName)){
27
- console.warn('warn: Not loaded. Invalid custom object_triggers -> ', doc.name);
28
- return;
29
- }
30
- try {
31
- //给对象添加触发器
32
- objectql.addObjectListenerConfig({
33
- _id: doc._id,
34
- listenTo: doc.object,
35
- [doc.when]: eval(`(async function(){${doc.todo}})`)//warn: 此处代码存在风险
36
- });
37
- reloadObject(doc.object, objectDataSourceName);
38
- } catch (error) {
39
- console.log('info', error.message)
40
- }
41
- }
42
-
43
- function removeObjectTrigger(doc){
44
- var dbObject = objectCore.getObjectFromDB(doc.object);
45
- var objectDataSourceName = objectCore.getDataSourceName(dbObject);
46
- if(!objectCore.canLoadObject(dbObject.name, objectDataSourceName)){
47
- console.warn('warn: Not deleted. Invalid custom object -> ', doc.name);
48
- return;
49
- }
50
- console.log('remove object trigger', doc._id, doc.object, doc.when);
51
- objectql.removeObjectListenerConfig(doc._id, doc.object, doc.when);
52
- reloadObject(doc.object, objectDataSourceName);
53
- }
54
-
55
-
56
- module.exports = {
57
- loadObjectTrigger,removeObjectTrigger
58
- }
@@ -1,65 +0,0 @@
1
-
2
- function isRepeatedName(doc, name) {
3
- var other = Creator.getCollection("object_triggers").find({
4
- object: doc.object,
5
- space: doc.space,
6
- _id: {
7
- $ne: doc._id
8
- },
9
- name: name || doc.name
10
- }, {
11
- fields: {
12
- _id: 1
13
- }
14
- });
15
- if (other.count() > 0) {
16
- return true;
17
- }
18
- return false;
19
- };
20
-
21
- function check(userId, doc) {
22
- // if (Steedos.isSpaceAdmin(userId, doc.space)) {
23
- // throw new Meteor.Error(500, "只有工作区管理员才能配置触发器");
24
- // }
25
- // //TODO 校验关键字:remove、 drop、delete、db、collection、eval等,然后取消 企业版版限制
26
- // if (doc.on === 'server' && !Steedos.isLegalVersion(doc.space, "workflow.enterprise")) {
27
- // throw new Meteor.Error(500, "只有企业版支持配置服务端的触发器");
28
- // }
29
- return true;
30
- };
31
-
32
- Creator.Objects.object_triggers.triggers = {
33
-
34
- "before.delete.server.object_triggers": {
35
- on: "server",
36
- when: "before.remove",
37
- todo: function(userId, doc) {
38
- check(userId, doc);
39
- }
40
- },
41
- "before.update.server.object_triggers": {
42
- on: "server",
43
- when: "before.update",
44
- todo: function(userId, doc, fieldNames, modifier, options) {
45
- var ref;
46
- check(userId, doc);
47
- if ((modifier != null ? (ref = modifier.$set) != null ? ref.name : void 0 : void 0) && isRepeatedName(doc, modifier.$set.name)) {
48
- throw new Meteor.Error(500, `名称不能重复${doc.name}`);
49
- }
50
- }
51
- },
52
- "before.insert.server.object_triggers": {
53
- on: "server",
54
- when: "before.insert",
55
- todo: function(userId, doc) {
56
- check(userId, doc);
57
- if(true){
58
- throw new Meteor.Error(500, "请在代码中定义trigger");
59
- }
60
- if (isRepeatedName(doc)) {
61
- throw new Meteor.Error(500, "名称不能重复");
62
- }
63
- }
64
- }
65
- }