@frangoteam/fuxa-min 1.2.11 → 1.3.1

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 (67) hide show
  1. package/api/auth/index.js +141 -3
  2. package/api/command/index.js +1 -1
  3. package/api/index.js +21 -2
  4. package/api/jwt-helper.js +3 -1
  5. package/api/resources/index.js +19 -2
  6. package/api/scripts/index.js +7 -3
  7. package/dist/3rdpartylicenses.txt +139 -7
  8. package/dist/assets/i18n/de.json +10 -0
  9. package/dist/assets/i18n/en.json +21 -3
  10. package/dist/assets/i18n/es.json +12 -0
  11. package/dist/assets/i18n/fr.json +11 -0
  12. package/dist/assets/i18n/ja.json +16 -6
  13. package/dist/assets/i18n/ko.json +12 -0
  14. package/dist/assets/i18n/pt.json +9 -2
  15. package/dist/assets/i18n/ru.json +11 -0
  16. package/dist/assets/i18n/sv.json +11 -1
  17. package/dist/assets/i18n/tr.json +8 -1
  18. package/dist/assets/i18n/ua.json +9 -2
  19. package/dist/assets/i18n/zh-cn.json +11 -0
  20. package/dist/assets/i18n/zh-tw.json +12 -1
  21. package/dist/assets/lib/svgeditor/fuxa-editor.min.js +17 -23
  22. package/dist/index.html +2 -2
  23. package/dist/main.72bdfed42c527918.js +329 -0
  24. package/dist/polyfills.d7de05f9af2fb559.js +1 -0
  25. package/dist/{runtime.8ef63094e52a66ba.js → runtime.9136a61a9b98f987.js} +1 -1
  26. package/dist/{scripts.40b60f02658462e4.js → scripts.d9e6ee984bf6f3b7.js} +1 -1
  27. package/dist/styles.545e37beb3e671ba.css +1 -0
  28. package/docs/openapi.yaml +3 -0
  29. package/integrations/node-red/index.js +4 -5
  30. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-daq.html +56 -5
  31. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-daq.js +8 -2
  32. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-change.html +56 -5
  33. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-change.js +12 -12
  34. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-daq-settings.html +56 -5
  35. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag-daq-settings.js +14 -10
  36. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag.html +69 -14
  37. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-get-tag.js +44 -12
  38. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag-daq-settings.html +56 -5
  39. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag-daq-settings.js +24 -20
  40. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag.html +72 -13
  41. package/integrations/node-red/node-red-contrib-fuxa/nodes/fuxa-set-tag.js +33 -7
  42. package/main.js +38 -17
  43. package/package.json +10 -5
  44. package/runtime/alarms/alarmstorage.js +45 -30
  45. package/runtime/apikeys/apiKeysStorage.js +34 -22
  46. package/runtime/devices/adsclient/index.js +1 -1
  47. package/runtime/devices/ethernetip/index.js +1 -1
  48. package/runtime/devices/gpio/index.js +1 -1
  49. package/runtime/devices/odbc/index.js +14 -9
  50. package/runtime/devices/s7/index.js +2 -2
  51. package/runtime/devices/template/index.js +14 -14
  52. package/runtime/notificator/notifystorage.js +34 -23
  53. package/runtime/project/index.js +16 -0
  54. package/runtime/project/prjstorage.js +78 -40
  55. package/runtime/scripts/index.js +6 -2
  56. package/runtime/storage/calculator.js +17 -13
  57. package/runtime/storage/daqstorage.js +28 -2
  58. package/runtime/storage/influxdb/index.js +8 -3
  59. package/runtime/storage/questdb/index.js +224 -0
  60. package/runtime/storage/sqlite/index.js +11 -8
  61. package/runtime/storage/tdengine/index.js +24 -9
  62. package/runtime/users/usrstorage.js +65 -61
  63. package/runtime/utils.js +5 -0
  64. package/settings.default.js +8 -2
  65. package/dist/main.92522279642ef880.js +0 -329
  66. package/dist/polyfills.c8e7db9850a3ad8b.js +0 -1
  67. package/dist/styles.03cc550382689976.css +0 -1
@@ -13,6 +13,18 @@ var settings // Application settings
13
13
  var logger; // Application logger
14
14
  var db_apikeys; // Database of apikeys
15
15
 
16
+ function _run(sql, params = []) {
17
+ return new Promise((resolve, reject) => {
18
+ db_apikeys.run(sql, params, function (err) {
19
+ if (err) {
20
+ reject(err);
21
+ } else {
22
+ resolve(this);
23
+ }
24
+ });
25
+ });
26
+ }
27
+
16
28
  /**
17
29
  * Init and bind the database resource
18
30
  * @param {*} _settings
@@ -73,18 +85,18 @@ function getApiKeys() {
73
85
  */
74
86
  function setApiKeys(apiKeys) {
75
87
  return new Promise(async function (resolve, reject) {
76
- for (var i = 0; i < apiKeys.length; i++) {
77
- const apiKey = apiKeys[i];
78
- var value = JSON.stringify(apiKey).replace(/\'/g,"''");
79
- var sql = "INSERT OR REPLACE INTO apikeys (name, value) VALUES('" + apiKey.id + "','"+ value + "');";
80
- await db_apikeys.exec(sql, function (err) {
81
- if (err) {
82
- logger.error(`apiKeysStorage.set apikeys failed! ${err}`);
83
- reject();
84
- }
85
- });
88
+ try {
89
+ const sql = "INSERT OR REPLACE INTO apikeys (name, value) VALUES(?, ?)";
90
+ for (var i = 0; i < apiKeys.length; i++) {
91
+ const apiKey = apiKeys[i];
92
+ var value = JSON.stringify(apiKey);
93
+ await _run(sql, [apiKey.id, value]);
94
+ }
95
+ resolve();
96
+ } catch (err) {
97
+ logger.error(`apiKeysStorage.set apikeys failed! ${err}`);
98
+ reject();
86
99
  }
87
- resolve();
88
100
  });
89
101
  }
90
102
 
@@ -93,17 +105,17 @@ function setApiKeys(apiKeys) {
93
105
  */
94
106
  function removeApiKeys(apiKeys) {
95
107
  return new Promise(async function (resolve, reject) {
96
- for (var i = 0; i < apiKeys.length; i++) {
97
- const apiKey = apiKeys[i];
98
- var sql = "DELETE FROM apikeys WHERE name = '" + apiKey.id + "'";
99
- await db_apikeys.exec(sql, function (err) {
100
- if (err) {
101
- logger.error(`apiKeysStorage.remove apikeys failed! ${err}`);
102
- reject();
103
- }
104
- });
108
+ try {
109
+ const sql = "DELETE FROM apikeys WHERE name = ?";
110
+ for (var i = 0; i < apiKeys.length; i++) {
111
+ const apiKey = apiKeys[i];
112
+ await _run(sql, [apiKey.id]);
113
+ }
114
+ resolve();
115
+ } catch (err) {
116
+ logger.error(`apiKeysStorage.remove apikeys failed! ${err}`);
117
+ reject();
105
118
  }
106
- resolve();
107
119
  });
108
120
  }
109
121
 
@@ -122,4 +134,4 @@ module.exports = {
122
134
  getApiKeys: getApiKeys,
123
135
  setApiKeys: setApiKeys,
124
136
  removeApiKeys: removeApiKeys
125
- };
137
+ };
@@ -26,7 +26,7 @@ function ADSclient(_data, _logger, _events, _runtime) {
26
26
  * initialize the device type
27
27
  */
28
28
  this.init = function (_type) {
29
- console.error('Not supported!');
29
+ console.error('Not supported! (adsclient.init)');
30
30
  }
31
31
 
32
32
  /**
@@ -28,7 +28,7 @@ function EthernetIPclient(_data, _logger, _events, _runtime) {
28
28
  * initialize the device type
29
29
  */
30
30
  this.init = function (_type) {
31
- console.error('Not supported!');
31
+ console.error('Not supported! (ethernetip.init)');
32
32
  }
33
33
 
34
34
  /**
@@ -198,7 +198,7 @@ function GpioClient(_data, _logger, _events, _runtime) {
198
198
  */
199
199
  this.lastReadTimestamp = () => {
200
200
  return lastTimestampValue;
201
- console.error('Not supported!');
201
+ console.error('Not supported! (gpio.lastReadTimestamp)');
202
202
  }
203
203
 
204
204
  /**
@@ -24,7 +24,7 @@ function ODBCclient(_data, _logger, _events) {
24
24
  * initialize the device type
25
25
  */
26
26
  this.init = function (_type) {
27
- console.error('Not supported!');
27
+ console.error('Not supported! (odbc.init)');
28
28
  }
29
29
 
30
30
  /**
@@ -165,14 +165,14 @@ function ODBCclient(_data, _logger, _events) {
165
165
  * Return Tags values array { id: <name>, value: <value> }
166
166
  */
167
167
  this.getValues = function () {
168
- console.error('Not supported!');
168
+ console.error('Not supported! (odbc.getValues)');
169
169
  }
170
170
 
171
171
  /**
172
172
  * Return Tag value { id: <name>, value: <value>, ts: <lastTimestampValue> }
173
173
  */
174
174
  this.getValue = function (tagid) {
175
- console.error('Not supported!');
175
+ console.error(`Not supported! (odbc.getValue) (TagID: ${tagid})`);
176
176
  }
177
177
 
178
178
  /**
@@ -186,14 +186,14 @@ function ODBCclient(_data, _logger, _events) {
186
186
  * Return Tag property to show in frontend
187
187
  */
188
188
  this.getTagProperty = function (tagid) {
189
- console.error('Not supported!');
189
+ console.error(`Not supported! (odbc.getTagProperty) (TagID: ${tagid})`);
190
190
  }
191
191
 
192
192
  /**
193
193
  * Set the Tag value to device
194
194
  */
195
195
  this.setValue = function (tagid, value) {
196
- console.error('Not supported!');
196
+ console.error(`Not supported! (odbc.setValue) (TagID: ${tagid}, Value: ${value})`);
197
197
  }
198
198
 
199
199
  /**
@@ -263,12 +263,12 @@ function ODBCclient(_data, _logger, _events) {
263
263
  * Return tables list
264
264
  */
265
265
  function getTables(endpoint, fncGetProperty, packagerManager) {
266
- return new Promise( async function (resolve, reject) {
267
- if (loadOdbcLib(packagerManager)) {
266
+ return new Promise(async function (resolve, reject) {
267
+ if (loadOdbcLib(packagerManager)) {
268
268
  var connection;
269
269
  try {
270
270
  var security
271
- await fncGetProperty({query: 'security', name: endpoint.id}).then((result, error) => {
271
+ await fncGetProperty({ query: 'security', name: endpoint.id }).then((result, error) => {
272
272
  if (result) {
273
273
  security = utils.JsonTryToParse(result.value);
274
274
  }
@@ -286,7 +286,12 @@ function getTables(endpoint, fncGetProperty, packagerManager) {
286
286
  loginTimeout: 10,
287
287
  }
288
288
  connection = await odbc.connect(connectionConfig)
289
- var tables = await connection.tables(null, 'dbo', null, null);
289
+ var tables = [];
290
+
291
+ try {
292
+ tables = await connection.tables(null, 'dbo', null, null);
293
+ } catch (err) { }
294
+
290
295
  if (tables.length <= 0) {
291
296
  tables = await connection.tables(null, null, null, null);
292
297
  }
@@ -348,7 +348,7 @@ function S7client(_data, _logger, _events, _runtime) {
348
348
  type: items[itemidx].type,
349
349
  daq: items[itemidx].daq,
350
350
  changed: changed,
351
- tagref: items[itemidx]
351
+ tagref: data.tags[items[itemidx].id] // <--- Passes full tag config including scaling
352
352
  };
353
353
  someval = true;
354
354
  }
@@ -701,4 +701,4 @@ function DbItems(dbnum) {
701
701
  this.DBNumber = dbnum;
702
702
  this.MaxSize = 0;
703
703
  this.Items = {};
704
- }
704
+ }
@@ -14,7 +14,7 @@ function DeviceTemplate(_data, _logger, _events) {
14
14
  * initialize the device type
15
15
  */
16
16
  this.init = function (_type) {
17
- console.error('Not supported!');
17
+ console.error('Not supported! (template.init)');
18
18
  }
19
19
 
20
20
  /**
@@ -22,7 +22,7 @@ function DeviceTemplate(_data, _logger, _events) {
22
22
  * Emit connection status to clients, clear all Tags values
23
23
  */
24
24
  this.connect = function () {
25
- console.error('Not supported!');
25
+ console.error('Not supported! (template.connect)');
26
26
  // events.emit('device-status:changed', { id: data.id, status: 'connect-ok' });
27
27
  // events.emit('device-status:changed', { id: data.id, status: 'connect-error' });
28
28
  }
@@ -33,7 +33,7 @@ function DeviceTemplate(_data, _logger, _events) {
33
33
  * Emit connection status to clients, clear all Tags values
34
34
  */
35
35
  this.disconnect = function () {
36
- console.error('Not supported!');
36
+ console.error('Not supported! (template.disconnect)');
37
37
  // events.emit('device-status:changed', { id: data.id, status: 'connect-off' });
38
38
  }
39
39
 
@@ -42,7 +42,7 @@ function DeviceTemplate(_data, _logger, _events) {
42
42
  * Update the tags values list, save in DAQ if value changed or in interval and emit values to clients
43
43
  */
44
44
  this.polling = async function () {
45
- console.error('Not supported!');
45
+ console.error('Not supported! (template.polling)');
46
46
  // events.emit('device-value:changed', { id: data.name, values: values });
47
47
  }
48
48
 
@@ -50,49 +50,49 @@ function DeviceTemplate(_data, _logger, _events) {
50
50
  * Load Tags attribute to read with polling
51
51
  */
52
52
  this.load = function (_data) {
53
- console.error('Not supported!');
53
+ console.error(`Not supported! (template.load) (Data: ${_data})`);
54
54
  }
55
55
 
56
56
  /**
57
57
  * Return Tags values array { id: <name>, value: <value> }
58
58
  */
59
59
  this.getValues = function () {
60
- console.error('Not supported!');
60
+ console.error('Not supported! (template.getValues)');
61
61
  }
62
62
 
63
63
  /**
64
64
  * Return Tag value { id: <name>, value: <value>, ts: <lastTimestampValue> }
65
65
  */
66
66
  this.getValue = function (tagid) {
67
- console.error('Not supported!');
67
+ console.error(`Not supported! (template.getValue) (TagID: ${tagid})`);
68
68
  }
69
69
 
70
70
  /**
71
71
  * Return connection status 'connect-off', 'connect-ok', 'connect-error', 'connect-busy'
72
72
  */
73
73
  this.getStatus = function () {
74
- console.error('Not supported!');
74
+ console.error('Not supported! (template.getStatus)');
75
75
  }
76
76
 
77
77
  /**
78
78
  * Return Tag property to show in frontend
79
79
  */
80
80
  this.getTagProperty = function (tagid) {
81
- console.error('Not supported!');
81
+ console.error(`Not supported! (template.getTagProperty) (TagID: ${tagid})`);
82
82
  }
83
83
 
84
84
  /**
85
85
  * Set the Tag value to device
86
86
  */
87
87
  this.setValue = function (tagid, value) {
88
- console.error('Not supported!');
88
+ console.error(`Not supported! (template.setValue) (TagID: ${tagid}, Value: ${value})`);
89
89
  }
90
90
 
91
91
  /**
92
92
  * Return if device is connected
93
93
  */
94
94
  this.isConnected = function () {
95
- console.error('Not supported!');
95
+ console.error('Not supported! (template.isConnected)');
96
96
  }
97
97
 
98
98
  /**
@@ -107,7 +107,7 @@ function DeviceTemplate(_data, _logger, _events) {
107
107
  * @returns
108
108
  */
109
109
  this.lastReadTimestamp = () => {
110
- console.error('Not supported!');
110
+ console.error('Not supported! (template.lastReadTimestamp)');
111
111
  }
112
112
 
113
113
  /**
@@ -115,7 +115,7 @@ function DeviceTemplate(_data, _logger, _events) {
115
115
  * @returns
116
116
  */
117
117
  this.getTagDaqSettings = (tagId) => {
118
- console.error('Not supported!');
118
+ console.error(`Not supported! (template.getTagDaqSettings) (TagID: ${tagId})`);
119
119
  }
120
120
 
121
121
  /**
@@ -123,7 +123,7 @@ function DeviceTemplate(_data, _logger, _events) {
123
123
  * @returns
124
124
  */
125
125
  this.setTagDaqSettings = (tagId, settings) => {
126
- console.error('Not supported!');
126
+ console.error(`Not supported! (template.setTagDaqSettings) (TagID: ${tagId}, Settings: ${settings})`);
127
127
  }
128
128
  }
129
129
 
@@ -13,6 +13,18 @@ var settings // Application settings
13
13
  var logger; // Application logger
14
14
  var db_notifications; // Database of notifications
15
15
 
16
+ function _run(sql, params = []) {
17
+ return new Promise((resolve, reject) => {
18
+ db_notifications.run(sql, params, function (err) {
19
+ if (err) {
20
+ reject(err);
21
+ } else {
22
+ resolve(this);
23
+ }
24
+ });
25
+ });
26
+ }
27
+
16
28
  /**
17
29
  * Init and bind the database resource
18
30
  * @param {*} _settings
@@ -120,23 +132,24 @@ function getNotifications() {
120
132
  */
121
133
  function setNotification(notification) {
122
134
  return new Promise(function (resolve, reject) {
123
- // prepare query
124
135
  if (notification) {
125
- var sql = "";
126
- //is notification is changed insert or update record
127
- // sql += "INSERT OR REPLACE INTO notifications (id, name, type, ontime, notifytime, notifytype) VALUES('" + notification.id + "','" +
128
- // notification.type + "','" + notification.name + "','" + notification.ontime + "','" + notification.notifytime + "','" + notification.notifytype + "');";
129
- sql += "INSERT OR REPLACE INTO chronicle (id, name, type, receiver, text, notifytime, notifytype) VALUES('" +
130
- notification.id + "','" + notification.name + "','" + notification.type + "','" + notification.receiver + "','" +
131
- notification.text + "','" + notification.notifytime + "','" + notification.notifytype + "');";
132
- db_notifications.exec(sql, function (err) {
133
- if (err) {
134
- logger.error('notifystorage.failed-to-set: ' + err);
135
- reject();
136
- } else {
137
- resolve();
138
- }
136
+ const sql = "INSERT OR REPLACE INTO chronicle (id, name, type, receiver, text, notifytime, notifytype) VALUES(?, ?, ?, ?, ?, ?, ?)";
137
+ _run(sql, [
138
+ notification.id,
139
+ notification.name,
140
+ notification.type,
141
+ notification.receiver,
142
+ notification.text,
143
+ notification.notifytime,
144
+ notification.notifytype
145
+ ]).then(function () {
146
+ resolve();
147
+ }).catch(function (err) {
148
+ logger.error('notifystorage.failed-to-set: ' + err);
149
+ reject();
139
150
  });
151
+ } else {
152
+ resolve();
140
153
  }
141
154
  });
142
155
  }
@@ -156,14 +169,12 @@ function close() {
156
169
  function removeNotification(notification) {
157
170
  return new Promise(function (resolve, reject) {
158
171
  // prepare query
159
- var sql = "DELETE FROM notifications WHERE id = '" + notification.id + "'";
160
- db_notifications.exec(sql, function (err) {
161
- if (err) {
162
- logger.error('notificationsstorage.failed-to-remove: ' + err);
163
- reject();
164
- } else {
165
- resolve();
166
- }
172
+ var sql = "DELETE FROM notifications WHERE id = ?";
173
+ _run(sql, [notification.id]).then(function () {
174
+ resolve();
175
+ }).catch(function (err) {
176
+ logger.error('notificationsstorage.failed-to-remove: ' + err);
177
+ reject();
167
178
  });
168
179
  });
169
180
  }
@@ -928,6 +928,22 @@ function _filterProjectPermission(userPermission) {
928
928
  // from device remove the not used (no permission)
929
929
  // delete result.devices;
930
930
  delete result.server;
931
+ if (Array.isArray(result.scripts)) {
932
+ // Keep only scripts authorised for the current user. For authorised
933
+ // server-side scripts, retain just the metadata needed for event
934
+ // bindings and execution requests; do not expose source code.
935
+ result.scripts = result.scripts.filter(script => {
936
+ return script && runtime.scriptsMgr.isAuthorised(script, userPermission);
937
+ }).map(script => {
938
+ delete script.permission;
939
+ delete script.permissionRoles;
940
+ if (script.mode === 'CLIENT') {
941
+ return script;
942
+ }
943
+ delete script.code;
944
+ return script;
945
+ });
946
+ }
931
947
  // check navigation permission
932
948
  if (result.hmi.layout && result.hmi.layout.navigation.items) {
933
949
  for (var i = result.hmi.layout.navigation.items.length - 1; i >= 0; i--) {
@@ -13,6 +13,38 @@ var settings // Application settings
13
13
  var logger; // Application logger
14
14
  var db_prj; // Database of project
15
15
 
16
+ function _run(sql, params = []) {
17
+ return new Promise((resolve, reject) => {
18
+ db_prj.run(sql, params, function (err) {
19
+ if (err) {
20
+ reject(err);
21
+ } else {
22
+ resolve(this);
23
+ }
24
+ });
25
+ });
26
+ }
27
+
28
+ function _all(sql, params = []) {
29
+ return new Promise((resolve, reject) => {
30
+ db_prj.all(sql, params, function (err, rows) {
31
+ if (err) {
32
+ reject(err);
33
+ } else {
34
+ resolve(rows);
35
+ }
36
+ });
37
+ });
38
+ }
39
+
40
+ function _ensureValidTable(table) {
41
+ const tables = Object.values(TableType);
42
+ if (!tables.includes(table)) {
43
+ throw new Error(`invalid table '${table}'`);
44
+ }
45
+ return table;
46
+ }
47
+
16
48
  /**
17
49
  * Init and bind the database resource
18
50
  * @param {*} _settings
@@ -83,21 +115,23 @@ function setDefault() {
83
115
  * @param {*} sections
84
116
  */
85
117
  function setSections(sections) {
86
- return new Promise(function (resolve, reject) {
87
- // prepare query
88
- var sql = "";
89
- for(var i = 0; i < sections.length; i++) {
90
- var value = JSON.stringify(sections[i].value).replace(/\'/g,"''");
91
- sql += "INSERT OR REPLACE INTO " + sections[i].table + " (name, value) VALUES('" + sections[i].name + "','"+ value + "');";
92
- }
93
- db_prj.exec(sql, function (err) {
94
- if (err) {
95
- logger.error(`prjstorage.set failed! ${err}`);
96
- reject();
97
- } else {
98
- resolve();
118
+ return new Promise(async function (resolve, reject) {
119
+ try {
120
+ await _run('BEGIN TRANSACTION');
121
+ for (var i = 0; i < sections.length; i++) {
122
+ var table = _ensureValidTable(sections[i].table);
123
+ var value = JSON.stringify(sections[i].value);
124
+ await _run(`INSERT OR REPLACE INTO ${table} (name, value) VALUES(?, ?)`, [sections[i].name, value]);
99
125
  }
100
- });
126
+ await _run('COMMIT');
127
+ resolve();
128
+ } catch (err) {
129
+ try {
130
+ await _run('ROLLBACK');
131
+ } catch (_) {}
132
+ logger.error(`prjstorage.set failed! ${err}`);
133
+ reject();
134
+ }
101
135
  });
102
136
  }
103
137
 
@@ -108,16 +142,19 @@ function setSections(sections) {
108
142
  */
109
143
  function setSection(section) {
110
144
  return new Promise(function (resolve, reject) {
111
- var value = JSON.stringify(section.value).replace(/\'/g,"''");
112
- var sql = "INSERT OR REPLACE INTO " + section.table + " (name, value) VALUES('" + section.name + "','"+ value + "');";
113
- db_prj.exec(sql, function (err) {
114
- if (err) {
145
+ try {
146
+ var table = _ensureValidTable(section.table);
147
+ var value = JSON.stringify(section.value);
148
+ _run(`INSERT OR REPLACE INTO ${table} (name, value) VALUES(?, ?)`, [section.name, value]).then(function () {
149
+ resolve();
150
+ }).catch(function (err) {
115
151
  logger.error(`prjstorage.set failed! ${err}`);
116
152
  reject();
117
- } else {
118
- resolve();
119
- }
120
- });
153
+ });
154
+ } catch (err) {
155
+ logger.error(`prjstorage.set failed! ${err}`);
156
+ reject();
157
+ }
121
158
  });
122
159
  }
123
160
 
@@ -129,17 +166,18 @@ function setSection(section) {
129
166
  */
130
167
  function getSection(table, name) {
131
168
  return new Promise(function (resolve, reject) {
132
- var sql = "SELECT name, value FROM " + table;
133
- if (name) {
134
- sql += " WHERE name = '" + name + "'";
135
- }
136
- db_prj.all(sql, function (err, rows) {
137
- if (err) {
138
- reject(err);
139
- } else {
140
- resolve(rows);
169
+ try {
170
+ var safeTable = _ensureValidTable(table);
171
+ var sql = `SELECT name, value FROM ${safeTable}`;
172
+ var params = [];
173
+ if (name) {
174
+ sql += " WHERE name = ?";
175
+ params.push(name);
141
176
  }
142
- });
177
+ _all(sql, params).then(resolve).catch(reject);
178
+ } catch (err) {
179
+ reject(err);
180
+ }
143
181
  });
144
182
  }
145
183
 
@@ -150,14 +188,14 @@ function getSection(table, name) {
150
188
  */
151
189
  function deleteSection(section) {
152
190
  return new Promise(function (resolve, reject) {
153
- var sql = "DELETE FROM " + section.table + " WHERE name = '" + section.name + "'";
154
- db_prj.run(sql, function (err, rows) {
155
- if (err) {
156
- reject(err);
157
- } else {
191
+ try {
192
+ var table = _ensureValidTable(section.table);
193
+ _run(`DELETE FROM ${table} WHERE name = ?`, [section.name]).then(function () {
158
194
  resolve();
159
- }
160
- });
195
+ }).catch(reject);
196
+ } catch (err) {
197
+ reject(err);
198
+ }
161
199
  });
162
200
  }
163
201
 
@@ -222,4 +260,4 @@ module.exports = {
222
260
  deleteSection: deleteSection,
223
261
  setDefault: setDefault,
224
262
  TableType: TableType,
225
- };
263
+ };
@@ -88,6 +88,10 @@ function ScriptsManager(_runtime) {
88
88
  const st = scriptModule.getScript(_script);
89
89
  var admin = (permission === -1 || permission === 255) ? true : false;
90
90
  if (runtime.settings.userRole) {
91
+ admin = admin || permission?.groups === -1 || permission?.groups === 255;
92
+ if (admin) {
93
+ return true;
94
+ }
91
95
  if (!st.permissionRoles || !st.permissionRoles.enabled) {
92
96
  return true;
93
97
  }
@@ -106,7 +110,7 @@ function ScriptsManager(_runtime) {
106
110
  this.isAuthorisedByScriptName = function (scriptName, permission) {
107
111
  const script = scriptModule.getScriptByName(scriptName);
108
112
  if (!script) {
109
- return true;
113
+ return false;
110
114
  }
111
115
  return this.isAuthorised(script, permission);
112
116
  }
@@ -366,4 +370,4 @@ const ScriptSchedulingMode = {
366
370
  const SchedulerType = {
367
371
  weekly: 0,
368
372
  date: 1,
369
- }
373
+ }