dbgate-api-premium 6.4.2 → 6.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.
@@ -5,6 +5,8 @@ const _ = require('lodash');
5
5
 
6
6
  const { jsldir } = require('../utility/directories');
7
7
  const { serializeJsTypesReplacer } = require('dbgate-tools');
8
+ const { ChartProcessor } = require('dbgate-datalib');
9
+ const { isProApp } = require('./checkLicense');
8
10
 
9
11
  class QueryStreamTableWriter {
10
12
  constructor(sesid = undefined) {
@@ -12,9 +14,13 @@ class QueryStreamTableWriter {
12
14
  this.currentChangeIndex = 1;
13
15
  this.initializedFile = false;
14
16
  this.sesid = sesid;
17
+ // if (isProApp()) {
18
+ // this.chartProcessor = new ChartProcessor();
19
+ // }
20
+ this.chartProcessor = new ChartProcessor();
15
21
  }
16
22
 
17
- initializeFromQuery(structure, resultIndex) {
23
+ initializeFromQuery(structure, resultIndex, chartDefinition) {
18
24
  this.jslid = crypto.randomUUID();
19
25
  this.currentFile = path.join(jsldir(), `${this.jslid}.jsonl`);
20
26
  fs.writeFileSync(
@@ -28,6 +34,9 @@ class QueryStreamTableWriter {
28
34
  this.writeCurrentStats(false, false);
29
35
  this.resultIndex = resultIndex;
30
36
  this.initializedFile = true;
37
+ if (isProApp() && chartDefinition) {
38
+ this.chartProcessor = new ChartProcessor([chartDefinition]);
39
+ }
31
40
  process.send({ msgtype: 'recordset', jslid: this.jslid, resultIndex, sesid: this.sesid });
32
41
  }
33
42
 
@@ -40,6 +49,15 @@ class QueryStreamTableWriter {
40
49
  row(row) {
41
50
  // console.log('ACCEPT ROW', row);
42
51
  this.currentStream.write(JSON.stringify(row, serializeJsTypesReplacer) + '\n');
52
+ try {
53
+ if (this.chartProcessor) {
54
+ this.chartProcessor.addRow(row);
55
+ }
56
+ } catch (e) {
57
+ console.error('Error processing chart row', e);
58
+ this.chartProcessor = null;
59
+ }
60
+
43
61
  this.currentRowCount += 1;
44
62
 
45
63
  if (!this.plannedStats) {
@@ -87,6 +105,23 @@ class QueryStreamTableWriter {
87
105
  this.currentStream.end(() => {
88
106
  this.writeCurrentStats(true, true);
89
107
  if (afterClose) afterClose();
108
+ if (this.chartProcessor) {
109
+ try {
110
+ this.chartProcessor.finalize();
111
+ if (isProApp() && this.chartProcessor.charts.length > 0) {
112
+ process.send({
113
+ msgtype: 'charts',
114
+ sesid: this.sesid,
115
+ jslid: this.jslid,
116
+ charts: this.chartProcessor.charts,
117
+ resultIndex: this.resultIndex,
118
+ });
119
+ }
120
+ } catch (e) {
121
+ console.error('Error finalizing chart processor', e);
122
+ this.chartProcessor = null;
123
+ }
124
+ }
90
125
  resolve();
91
126
  });
92
127
  } else {
@@ -97,10 +132,18 @@ class QueryStreamTableWriter {
97
132
  }
98
133
 
99
134
  class StreamHandler {
100
- constructor(queryStreamInfoHolder, resolve, startLine, sesid = undefined, limitRows = undefined) {
135
+ constructor(
136
+ queryStreamInfoHolder,
137
+ resolve,
138
+ startLine,
139
+ sesid = undefined,
140
+ limitRows = undefined,
141
+ frontMatter = undefined
142
+ ) {
101
143
  this.recordset = this.recordset.bind(this);
102
144
  this.startLine = startLine;
103
145
  this.sesid = sesid;
146
+ this.frontMatter = frontMatter;
104
147
  this.limitRows = limitRows;
105
148
  this.rowsLimitOverflow = false;
106
149
  this.row = this.row.bind(this);
@@ -133,7 +176,8 @@ class StreamHandler {
133
176
  this.currentWriter = new QueryStreamTableWriter(this.sesid);
134
177
  this.currentWriter.initializeFromQuery(
135
178
  Array.isArray(columns) ? { columns } : columns,
136
- this.queryStreamInfoHolder.resultIndex
179
+ this.queryStreamInfoHolder.resultIndex,
180
+ this.frontMatter?.[`chart-${this.queryStreamInfoHolder.resultIndex + 1}`]
137
181
  );
138
182
  this.queryStreamInfoHolder.resultIndex += 1;
139
183
  this.rowCounter = 0;
@@ -201,10 +245,25 @@ class StreamHandler {
201
245
  }
202
246
  }
203
247
 
204
- function handleQueryStream(dbhan, driver, queryStreamInfoHolder, sqlItem, sesid = undefined, limitRows = undefined) {
248
+ function handleQueryStream(
249
+ dbhan,
250
+ driver,
251
+ queryStreamInfoHolder,
252
+ sqlItem,
253
+ sesid = undefined,
254
+ limitRows = undefined,
255
+ frontMatter = undefined
256
+ ) {
205
257
  return new Promise((resolve, reject) => {
206
258
  const start = sqlItem.trimStart || sqlItem.start;
207
- const handler = new StreamHandler(queryStreamInfoHolder, resolve, start && start.line, sesid, limitRows);
259
+ const handler = new StreamHandler(
260
+ queryStreamInfoHolder,
261
+ resolve,
262
+ start && start.line,
263
+ sesid,
264
+ limitRows,
265
+ frontMatter
266
+ );
208
267
  driver.stream(dbhan, sqlItem.text, handler);
209
268
  });
210
269
  }
@@ -87,4 +87,5 @@ module.exports = {
87
87
  getHardwareFingerprint,
88
88
  getHardwareFingerprintHash,
89
89
  getPublicHardwareFingerprint,
90
+ getPublicIpInfo,
90
91
  };
@@ -0,0 +1,52 @@
1
+ const path = require('path');
2
+ const { filesdir, archivedir, uploadsdir, appdir } = require('../utility/directories');
3
+
4
+ function checkSecureFilePathsWithoutDirectory(...filePaths) {
5
+ for (const filePath of filePaths) {
6
+ if (filePath.includes('..') || filePath.includes('/') || filePath.includes('\\')) {
7
+ return false;
8
+ }
9
+ }
10
+ return true;
11
+ }
12
+
13
+ function checkSecureDirectories(...filePaths) {
14
+ for (const filePath of filePaths) {
15
+ if (!filePath.includes('/') && !filePath.includes('\\')) {
16
+ // If the filePath does not contain any directory separators, it is considered secure
17
+ continue;
18
+ }
19
+ const directory = path.dirname(filePath);
20
+ if (directory != filesdir() && directory != uploadsdir() && directory != archivedir() && directory != appdir()) {
21
+ return false;
22
+ }
23
+ }
24
+ return true;
25
+ }
26
+
27
+ function findDisallowedFileNames(node, isAllowed, trace = '$', out = []) {
28
+ if (node && typeof node === 'object') {
29
+ if (node?.props?.fileName) {
30
+ const name = node.props.fileName;
31
+ const ok = isAllowed(name);
32
+ if (!ok) out.push({ path: `${trace}.props.fileName`, value: name });
33
+ }
34
+
35
+ // depth-first scan of every property / array index
36
+ for (const [key, val] of Object.entries(node)) {
37
+ findDisallowedFileNames(val, isAllowed, `${trace}.${key}`, out);
38
+ }
39
+ }
40
+ return out;
41
+ }
42
+
43
+ function checkSecureDirectoriesInScript(script) {
44
+ const disallowed = findDisallowedFileNames(script, checkSecureDirectories);
45
+ return disallowed.length == 0;
46
+ }
47
+
48
+ module.exports = {
49
+ checkSecureDirectories,
50
+ checkSecureFilePathsWithoutDirectory,
51
+ checkSecureDirectoriesInScript,
52
+ };