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.
- package/package.json +5 -5
- package/src/controllers/auth.js +11 -0
- package/src/controllers/cloud.js +261 -0
- package/src/controllers/config.js +2 -1
- package/src/controllers/connections.js +20 -0
- package/src/controllers/databaseConnections.js +3 -0
- package/src/controllers/files.js +33 -0
- package/src/controllers/jsldata.js +26 -0
- package/src/controllers/runners.js +12 -0
- package/src/controllers/serverConnections.js +1 -1
- package/src/controllers/sessions.js +7 -2
- package/src/controllers/storage.js +9 -0
- package/src/controllers/uploads.js +4 -0
- package/src/currentVersion.js +2 -2
- package/src/main.js +5 -0
- package/src/proc/connectProcess.js +1 -8
- package/src/proc/sessionProcess.js +2 -2
- package/src/shell/deployDb.js +10 -1
- package/src/shell/executeQuery.js +3 -1
- package/src/shell/generateDeploySql.js +4 -1
- package/src/utility/authProxy.js +16 -1
- package/src/utility/checkLicense.js +11 -13
- package/src/utility/cloudIntf.js +399 -0
- package/src/utility/crypting.js +6 -6
- package/src/utility/handleQueryStream.js +64 -5
- package/src/utility/hardwareFingerprint.js +1 -0
- package/src/utility/security.js +52 -0
|
@@ -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(
|
|
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(
|
|
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(
|
|
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
|
}
|
|
@@ -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
|
+
};
|