dbgate-api 6.6.1 → 6.6.3
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/auth/authProvider.js +13 -1
- package/src/controllers/auth.js +2 -1
- package/src/controllers/config.js +8 -5
- package/src/controllers/connections.js +8 -7
- package/src/controllers/databaseConnections.js +137 -72
- package/src/controllers/files.js +25 -15
- package/src/controllers/plugins.js +7 -4
- package/src/controllers/runners.js +3 -0
- package/src/controllers/scheduler.js +3 -2
- package/src/controllers/serverConnections.js +65 -10
- package/src/controllers/sessions.js +4 -1
- package/src/controllers/storage.js +0 -4
- package/src/currentVersion.js +2 -2
- package/src/index.js +2 -1
- package/src/proc/databaseConnectionProcess.js +24 -1
- package/src/proc/serverConnectionProcess.js +26 -0
- package/src/storageModel.js +726 -105
- package/src/utility/hasPermission.js +286 -71
package/src/controllers/files.js
CHANGED
|
@@ -3,7 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
4
|
const { filesdir, archivedir, resolveArchiveFolder, uploadsdir, appdir, jsldir } = require('../utility/directories');
|
|
5
5
|
const getChartExport = require('../utility/getChartExport');
|
|
6
|
-
const { hasPermission } = require('../utility/hasPermission');
|
|
6
|
+
const { hasPermission, loadPermissionsFromRequest } = require('../utility/hasPermission');
|
|
7
7
|
const socket = require('../utility/socket');
|
|
8
8
|
const scheduler = require('./scheduler');
|
|
9
9
|
const getDiagramExport = require('../utility/getDiagramExport');
|
|
@@ -31,7 +31,8 @@ function deserialize(format, text) {
|
|
|
31
31
|
module.exports = {
|
|
32
32
|
list_meta: true,
|
|
33
33
|
async list({ folder }, req) {
|
|
34
|
-
|
|
34
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
35
|
+
if (!hasPermission(`files/${folder}/read`, loadedPermissions)) return [];
|
|
35
36
|
const dir = path.join(filesdir(), folder);
|
|
36
37
|
if (!(await fs.exists(dir))) return [];
|
|
37
38
|
const files = (await fs.readdir(dir)).map(file => ({ folder, file }));
|
|
@@ -40,10 +41,11 @@ module.exports = {
|
|
|
40
41
|
|
|
41
42
|
listAll_meta: true,
|
|
42
43
|
async listAll(_params, req) {
|
|
44
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
43
45
|
const folders = await fs.readdir(filesdir());
|
|
44
46
|
const res = [];
|
|
45
47
|
for (const folder of folders) {
|
|
46
|
-
if (!hasPermission(`files/${folder}/read`,
|
|
48
|
+
if (!hasPermission(`files/${folder}/read`, loadedPermissions)) continue;
|
|
47
49
|
const dir = path.join(filesdir(), folder);
|
|
48
50
|
const files = (await fs.readdir(dir)).map(file => ({ folder, file }));
|
|
49
51
|
res.push(...files);
|
|
@@ -53,7 +55,8 @@ module.exports = {
|
|
|
53
55
|
|
|
54
56
|
delete_meta: true,
|
|
55
57
|
async delete({ folder, file }, req) {
|
|
56
|
-
|
|
58
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
59
|
+
if (!hasPermission(`files/${folder}/write`, loadedPermissions)) return false;
|
|
57
60
|
if (!checkSecureFilePathsWithoutDirectory(folder, file)) {
|
|
58
61
|
return false;
|
|
59
62
|
}
|
|
@@ -65,7 +68,8 @@ module.exports = {
|
|
|
65
68
|
|
|
66
69
|
rename_meta: true,
|
|
67
70
|
async rename({ folder, file, newFile }, req) {
|
|
68
|
-
|
|
71
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
72
|
+
if (!hasPermission(`files/${folder}/write`, loadedPermissions)) return false;
|
|
69
73
|
if (!checkSecureFilePathsWithoutDirectory(folder, file, newFile)) {
|
|
70
74
|
return false;
|
|
71
75
|
}
|
|
@@ -86,10 +90,11 @@ module.exports = {
|
|
|
86
90
|
|
|
87
91
|
copy_meta: true,
|
|
88
92
|
async copy({ folder, file, newFile }, req) {
|
|
93
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
89
94
|
if (!checkSecureFilePathsWithoutDirectory(folder, file, newFile)) {
|
|
90
95
|
return false;
|
|
91
96
|
}
|
|
92
|
-
if (!hasPermission(`files/${folder}/write`,
|
|
97
|
+
if (!hasPermission(`files/${folder}/write`, loadedPermissions)) return false;
|
|
93
98
|
await fs.copyFile(path.join(filesdir(), folder, file), path.join(filesdir(), folder, newFile));
|
|
94
99
|
socket.emitChanged(`files-changed`, { folder });
|
|
95
100
|
socket.emitChanged(`all-files-changed`);
|
|
@@ -113,7 +118,8 @@ module.exports = {
|
|
|
113
118
|
});
|
|
114
119
|
return deserialize(format, text);
|
|
115
120
|
} else {
|
|
116
|
-
|
|
121
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
122
|
+
if (!hasPermission(`files/${folder}/read`, loadedPermissions)) return null;
|
|
117
123
|
const text = await fs.readFile(path.join(filesdir(), folder, file), { encoding: 'utf-8' });
|
|
118
124
|
return deserialize(format, text);
|
|
119
125
|
}
|
|
@@ -131,18 +137,19 @@ module.exports = {
|
|
|
131
137
|
|
|
132
138
|
save_meta: true,
|
|
133
139
|
async save({ folder, file, data, format }, req) {
|
|
140
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
134
141
|
if (!checkSecureFilePathsWithoutDirectory(folder, file)) {
|
|
135
142
|
return false;
|
|
136
143
|
}
|
|
137
144
|
|
|
138
145
|
if (folder.startsWith('archive:')) {
|
|
139
|
-
if (!hasPermission(`archive/write`,
|
|
146
|
+
if (!hasPermission(`archive/write`, loadedPermissions)) return false;
|
|
140
147
|
const dir = resolveArchiveFolder(folder.substring('archive:'.length));
|
|
141
148
|
await fs.writeFile(path.join(dir, file), serialize(format, data));
|
|
142
149
|
socket.emitChanged(`archive-files-changed`, { folder: folder.substring('archive:'.length) });
|
|
143
150
|
return true;
|
|
144
151
|
} else if (folder.startsWith('app:')) {
|
|
145
|
-
if (!hasPermission(`apps/write`,
|
|
152
|
+
if (!hasPermission(`apps/write`, loadedPermissions)) return false;
|
|
146
153
|
const app = folder.substring('app:'.length);
|
|
147
154
|
await fs.writeFile(path.join(appdir(), app, file), serialize(format, data));
|
|
148
155
|
socket.emitChanged(`app-files-changed`, { app });
|
|
@@ -150,7 +157,7 @@ module.exports = {
|
|
|
150
157
|
apps.emitChangedDbApp(folder);
|
|
151
158
|
return true;
|
|
152
159
|
} else {
|
|
153
|
-
if (!hasPermission(`files/${folder}/write`,
|
|
160
|
+
if (!hasPermission(`files/${folder}/write`, loadedPermissions)) return false;
|
|
154
161
|
const dir = path.join(filesdir(), folder);
|
|
155
162
|
if (!(await fs.exists(dir))) {
|
|
156
163
|
await fs.mkdir(dir);
|
|
@@ -177,7 +184,8 @@ module.exports = {
|
|
|
177
184
|
|
|
178
185
|
favorites_meta: true,
|
|
179
186
|
async favorites(_params, req) {
|
|
180
|
-
|
|
187
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
188
|
+
if (!hasPermission(`files/favorites/read`, loadedPermissions)) return [];
|
|
181
189
|
const dir = path.join(filesdir(), 'favorites');
|
|
182
190
|
if (!(await fs.exists(dir))) return [];
|
|
183
191
|
const files = await fs.readdir(dir);
|
|
@@ -234,16 +242,17 @@ module.exports = {
|
|
|
234
242
|
|
|
235
243
|
getFileRealPath_meta: true,
|
|
236
244
|
async getFileRealPath({ folder, file }, req) {
|
|
245
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
237
246
|
if (folder.startsWith('archive:')) {
|
|
238
|
-
if (!hasPermission(`archive/write`,
|
|
247
|
+
if (!hasPermission(`archive/write`, loadedPermissions)) return false;
|
|
239
248
|
const dir = resolveArchiveFolder(folder.substring('archive:'.length));
|
|
240
249
|
return path.join(dir, file);
|
|
241
250
|
} else if (folder.startsWith('app:')) {
|
|
242
|
-
if (!hasPermission(`apps/write`,
|
|
251
|
+
if (!hasPermission(`apps/write`, loadedPermissions)) return false;
|
|
243
252
|
const app = folder.substring('app:'.length);
|
|
244
253
|
return path.join(appdir(), app, file);
|
|
245
254
|
} else {
|
|
246
|
-
if (!hasPermission(`files/${folder}/write`,
|
|
255
|
+
if (!hasPermission(`files/${folder}/write`, loadedPermissions)) return false;
|
|
247
256
|
const dir = path.join(filesdir(), folder);
|
|
248
257
|
if (!(await fs.exists(dir))) {
|
|
249
258
|
await fs.mkdir(dir);
|
|
@@ -297,7 +306,8 @@ module.exports = {
|
|
|
297
306
|
|
|
298
307
|
exportFile_meta: true,
|
|
299
308
|
async exportFile({ folder, file, filePath }, req) {
|
|
300
|
-
|
|
309
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
310
|
+
if (!hasPermission(`files/${folder}/read`, loadedPermissions)) return false;
|
|
301
311
|
await fs.copyFile(path.join(filesdir(), folder, file), filePath);
|
|
302
312
|
return true;
|
|
303
313
|
},
|
|
@@ -7,7 +7,7 @@ const socket = require('../utility/socket');
|
|
|
7
7
|
const compareVersions = require('compare-versions');
|
|
8
8
|
const requirePlugin = require('../shell/requirePlugin');
|
|
9
9
|
const downloadPackage = require('../utility/downloadPackage');
|
|
10
|
-
const { hasPermission } = require('../utility/hasPermission');
|
|
10
|
+
const { hasPermission, loadPermissionsFromRequest } = require('../utility/hasPermission');
|
|
11
11
|
const _ = require('lodash');
|
|
12
12
|
const packagedPluginsContent = require('../packagedPluginsContent');
|
|
13
13
|
|
|
@@ -118,7 +118,8 @@ module.exports = {
|
|
|
118
118
|
|
|
119
119
|
install_meta: true,
|
|
120
120
|
async install({ packageName }, req) {
|
|
121
|
-
|
|
121
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
122
|
+
if (!hasPermission(`plugins/install`, loadedPermissions)) return;
|
|
122
123
|
const dir = path.join(pluginsdir(), packageName);
|
|
123
124
|
// @ts-ignore
|
|
124
125
|
if (!(await fs.exists(dir))) {
|
|
@@ -132,7 +133,8 @@ module.exports = {
|
|
|
132
133
|
|
|
133
134
|
uninstall_meta: true,
|
|
134
135
|
async uninstall({ packageName }, req) {
|
|
135
|
-
|
|
136
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
137
|
+
if (!hasPermission(`plugins/install`, loadedPermissions)) return;
|
|
136
138
|
const dir = path.join(pluginsdir(), packageName);
|
|
137
139
|
await fs.rmdir(dir, { recursive: true });
|
|
138
140
|
socket.emitChanged(`installed-plugins-changed`);
|
|
@@ -143,7 +145,8 @@ module.exports = {
|
|
|
143
145
|
|
|
144
146
|
upgrade_meta: true,
|
|
145
147
|
async upgrade({ packageName }, req) {
|
|
146
|
-
|
|
148
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
149
|
+
if (!hasPermission(`plugins/install`, loadedPermissions)) return;
|
|
147
150
|
const dir = path.join(pluginsdir(), packageName);
|
|
148
151
|
// @ts-ignore
|
|
149
152
|
if (await fs.exists(dir)) {
|
|
@@ -21,6 +21,7 @@ const processArgs = require('../utility/processArgs');
|
|
|
21
21
|
const platformInfo = require('../utility/platformInfo');
|
|
22
22
|
const { checkSecureDirectories, checkSecureDirectoriesInScript } = require('../utility/security');
|
|
23
23
|
const { sendToAuditLog, logJsonRunnerScript } = require('../utility/auditlog');
|
|
24
|
+
const { testStandardPermission } = require('../utility/hasPermission');
|
|
24
25
|
const logger = getLogger('runners');
|
|
25
26
|
|
|
26
27
|
function extractPlugins(script) {
|
|
@@ -273,6 +274,8 @@ module.exports = {
|
|
|
273
274
|
|
|
274
275
|
start_meta: true,
|
|
275
276
|
async start({ script }, req) {
|
|
277
|
+
await testStandardPermission('run-shell-script', req);
|
|
278
|
+
|
|
276
279
|
const runid = crypto.randomUUID();
|
|
277
280
|
|
|
278
281
|
if (script.type == 'json') {
|
|
@@ -3,7 +3,7 @@ const fs = require('fs-extra');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const cron = require('node-cron');
|
|
5
5
|
const runners = require('./runners');
|
|
6
|
-
const { hasPermission } = require('../utility/hasPermission');
|
|
6
|
+
const { hasPermission, loadPermissionsFromRequest } = require('../utility/hasPermission');
|
|
7
7
|
const { getLogger } = require('dbgate-tools');
|
|
8
8
|
|
|
9
9
|
const logger = getLogger('scheduler');
|
|
@@ -30,7 +30,8 @@ module.exports = {
|
|
|
30
30
|
},
|
|
31
31
|
|
|
32
32
|
async reload(_params, req) {
|
|
33
|
-
|
|
33
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
34
|
+
if (!hasPermission('files/shell/read', loadedPermissions)) return;
|
|
34
35
|
const shellDir = path.join(filesdir(), 'shell');
|
|
35
36
|
await this.unload();
|
|
36
37
|
if (!(await fs.exists(shellDir))) return;
|
|
@@ -8,7 +8,13 @@ const { handleProcessCommunication } = require('../utility/processComm');
|
|
|
8
8
|
const lock = new AsyncLock();
|
|
9
9
|
const config = require('./config');
|
|
10
10
|
const processArgs = require('../utility/processArgs');
|
|
11
|
-
const {
|
|
11
|
+
const {
|
|
12
|
+
testConnectionPermission,
|
|
13
|
+
loadPermissionsFromRequest,
|
|
14
|
+
hasPermission,
|
|
15
|
+
loadDatabasePermissionsFromRequest,
|
|
16
|
+
getDatabasePermissionRole,
|
|
17
|
+
} = require('../utility/hasPermission');
|
|
12
18
|
const { MissingCredentialsError } = require('../utility/exceptions');
|
|
13
19
|
const pipeForkLogs = require('../utility/pipeForkLogs');
|
|
14
20
|
const { getLogger, extractErrorLogData } = require('dbgate-tools');
|
|
@@ -40,7 +46,7 @@ module.exports = {
|
|
|
40
46
|
existing.status = status;
|
|
41
47
|
socket.emitChanged(`server-status-changed`);
|
|
42
48
|
},
|
|
43
|
-
handle_ping() {},
|
|
49
|
+
handle_ping() { },
|
|
44
50
|
handle_response(conid, { msgid, ...response }) {
|
|
45
51
|
const [resolve, reject] = this.requests[msgid];
|
|
46
52
|
resolve(response);
|
|
@@ -135,7 +141,7 @@ module.exports = {
|
|
|
135
141
|
|
|
136
142
|
disconnect_meta: true,
|
|
137
143
|
async disconnect({ conid }, req) {
|
|
138
|
-
testConnectionPermission(conid, req);
|
|
144
|
+
await testConnectionPermission(conid, req);
|
|
139
145
|
await this.close(conid, true);
|
|
140
146
|
return { status: 'ok' };
|
|
141
147
|
},
|
|
@@ -144,7 +150,9 @@ module.exports = {
|
|
|
144
150
|
async listDatabases({ conid }, req) {
|
|
145
151
|
if (!conid) return [];
|
|
146
152
|
if (conid == '__model') return [];
|
|
147
|
-
|
|
153
|
+
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
154
|
+
|
|
155
|
+
await testConnectionPermission(conid, req, loadedPermissions);
|
|
148
156
|
const opened = await this.ensureOpened(conid);
|
|
149
157
|
sendToAuditLog(req, {
|
|
150
158
|
category: 'serverop',
|
|
@@ -157,12 +165,29 @@ module.exports = {
|
|
|
157
165
|
sessionGroup: 'listDatabases',
|
|
158
166
|
message: `Loaded databases for connection`,
|
|
159
167
|
});
|
|
168
|
+
|
|
169
|
+
if (!hasPermission(`all-databases`, loadedPermissions)) {
|
|
170
|
+
// filter databases by permissions
|
|
171
|
+
const databasePermissions = await loadDatabasePermissionsFromRequest(req);
|
|
172
|
+
const res = [];
|
|
173
|
+
for (const db of opened?.databases ?? []) {
|
|
174
|
+
const databasePermissionRole = getDatabasePermissionRole(db.id, db.name, databasePermissions);
|
|
175
|
+
if (databasePermissionRole != 'deny') {
|
|
176
|
+
res.push({
|
|
177
|
+
...db,
|
|
178
|
+
databasePermissionRole,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return res;
|
|
183
|
+
}
|
|
184
|
+
|
|
160
185
|
return opened?.databases ?? [];
|
|
161
186
|
},
|
|
162
187
|
|
|
163
188
|
version_meta: true,
|
|
164
189
|
async version({ conid }, req) {
|
|
165
|
-
testConnectionPermission(conid, req);
|
|
190
|
+
await testConnectionPermission(conid, req);
|
|
166
191
|
const opened = await this.ensureOpened(conid);
|
|
167
192
|
return opened?.version ?? null;
|
|
168
193
|
},
|
|
@@ -202,7 +227,7 @@ module.exports = {
|
|
|
202
227
|
|
|
203
228
|
refresh_meta: true,
|
|
204
229
|
async refresh({ conid, keepOpen }, req) {
|
|
205
|
-
testConnectionPermission(conid, req);
|
|
230
|
+
await testConnectionPermission(conid, req);
|
|
206
231
|
if (!keepOpen) this.close(conid);
|
|
207
232
|
|
|
208
233
|
await this.ensureOpened(conid);
|
|
@@ -210,7 +235,7 @@ module.exports = {
|
|
|
210
235
|
},
|
|
211
236
|
|
|
212
237
|
async sendDatabaseOp({ conid, msgtype, name }, req) {
|
|
213
|
-
testConnectionPermission(conid, req);
|
|
238
|
+
await testConnectionPermission(conid, req);
|
|
214
239
|
const opened = await this.ensureOpened(conid);
|
|
215
240
|
if (!opened) {
|
|
216
241
|
return null;
|
|
@@ -252,7 +277,7 @@ module.exports = {
|
|
|
252
277
|
},
|
|
253
278
|
|
|
254
279
|
async loadDataCore(msgtype, { conid, ...args }, req) {
|
|
255
|
-
testConnectionPermission(conid, req);
|
|
280
|
+
await testConnectionPermission(conid, req);
|
|
256
281
|
const opened = await this.ensureOpened(conid);
|
|
257
282
|
if (!opened) {
|
|
258
283
|
return null;
|
|
@@ -270,13 +295,43 @@ module.exports = {
|
|
|
270
295
|
|
|
271
296
|
serverSummary_meta: true,
|
|
272
297
|
async serverSummary({ conid }, req) {
|
|
273
|
-
testConnectionPermission(conid, req);
|
|
298
|
+
await testConnectionPermission(conid, req);
|
|
299
|
+
logger.info({ conid }, 'DBGM-00260 Processing server summary');
|
|
274
300
|
return this.loadDataCore('serverSummary', { conid });
|
|
275
301
|
},
|
|
276
302
|
|
|
303
|
+
listDatabaseProcesses_meta: true,
|
|
304
|
+
async listDatabaseProcesses(ctx, req) {
|
|
305
|
+
const { conid } = ctx;
|
|
306
|
+
// logger.info({ conid }, 'DBGM-00261 Listing processes of database server');
|
|
307
|
+
testConnectionPermission(conid, req);
|
|
308
|
+
|
|
309
|
+
const opened = await this.ensureOpened(conid);
|
|
310
|
+
if (!opened) {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
if (opened.connection.isReadOnly) return false;
|
|
314
|
+
|
|
315
|
+
return this.sendRequest(opened, { msgtype: 'listDatabaseProcesses' });
|
|
316
|
+
},
|
|
317
|
+
|
|
318
|
+
killDatabaseProcess_meta: true,
|
|
319
|
+
async killDatabaseProcess(ctx, req) {
|
|
320
|
+
const { conid, pid } = ctx;
|
|
321
|
+
testConnectionPermission(conid, req);
|
|
322
|
+
|
|
323
|
+
const opened = await this.ensureOpened(conid);
|
|
324
|
+
if (!opened) {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
if (opened.connection.isReadOnly) return false;
|
|
328
|
+
|
|
329
|
+
return this.sendRequest(opened, { msgtype: 'killDatabaseProcess', pid });
|
|
330
|
+
},
|
|
331
|
+
|
|
277
332
|
summaryCommand_meta: true,
|
|
278
333
|
async summaryCommand({ conid, command, row }, req) {
|
|
279
|
-
testConnectionPermission(conid, req);
|
|
334
|
+
await testConnectionPermission(conid, req);
|
|
280
335
|
const opened = await this.ensureOpened(conid);
|
|
281
336
|
if (!opened) {
|
|
282
337
|
return null;
|
|
@@ -12,6 +12,7 @@ const { getLogger, extractErrorLogData } = require('dbgate-tools');
|
|
|
12
12
|
const pipeForkLogs = require('../utility/pipeForkLogs');
|
|
13
13
|
const config = require('./config');
|
|
14
14
|
const { sendToAuditLog } = require('../utility/auditlog');
|
|
15
|
+
const { testStandardPermission, testDatabaseRolePermission } = require('../utility/hasPermission');
|
|
15
16
|
|
|
16
17
|
const logger = getLogger('sessions');
|
|
17
18
|
|
|
@@ -94,7 +95,7 @@ module.exports = {
|
|
|
94
95
|
socket.emit(`session-initialize-file-${jslid}`);
|
|
95
96
|
},
|
|
96
97
|
|
|
97
|
-
handle_ping() {},
|
|
98
|
+
handle_ping() { },
|
|
98
99
|
|
|
99
100
|
create_meta: true,
|
|
100
101
|
async create({ conid, database }) {
|
|
@@ -148,10 +149,12 @@ module.exports = {
|
|
|
148
149
|
|
|
149
150
|
executeQuery_meta: true,
|
|
150
151
|
async executeQuery({ sesid, sql, autoCommit, autoDetectCharts, limitRows, frontMatter }, req) {
|
|
152
|
+
await testStandardPermission('dbops/query', req);
|
|
151
153
|
const session = this.opened.find(x => x.sesid == sesid);
|
|
152
154
|
if (!session) {
|
|
153
155
|
throw new Error('Invalid session');
|
|
154
156
|
}
|
|
157
|
+
await testDatabaseRolePermission(session.conid, session.database, 'run_script', req);
|
|
155
158
|
|
|
156
159
|
sendToAuditLog(req, {
|
|
157
160
|
category: 'dbop',
|
package/src/currentVersion.js
CHANGED
package/src/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const moment = require('moment');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const { logsdir, setLogsFilePath, getLogsFilePath } = require('./utility/directories');
|
|
7
7
|
const currentVersion = require('./currentVersion');
|
|
8
|
+
const _ = require('lodash');
|
|
8
9
|
|
|
9
10
|
const logger = getLogger('apiIndex');
|
|
10
11
|
|
|
@@ -68,7 +69,7 @@ function configureLogger() {
|
|
|
68
69
|
}
|
|
69
70
|
const additionals = {};
|
|
70
71
|
const finalMsg =
|
|
71
|
-
msg.msg && msg.msg.match(/^DBGM-\d\d\d\d\d/)
|
|
72
|
+
_.isString(msg.msg) && msg.msg.match(/^DBGM-\d\d\d\d\d/)
|
|
72
73
|
? {
|
|
73
74
|
...msg,
|
|
74
75
|
msg: msg.msg.substring(10).trimStart(),
|
|
@@ -17,13 +17,14 @@ const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
|
17
17
|
const { connectUtility } = require('../utility/connectUtility');
|
|
18
18
|
const { handleProcessCommunication } = require('../utility/processComm');
|
|
19
19
|
const generateDeploySql = require('../shell/generateDeploySql');
|
|
20
|
-
const { dumpSqlSelect } = require('dbgate-sqltree');
|
|
20
|
+
const { dumpSqlSelect, scriptToSql } = require('dbgate-sqltree');
|
|
21
21
|
const { allowExecuteCustomScript, handleQueryStream } = require('../utility/handleQueryStream');
|
|
22
22
|
const dbgateApi = require('../shell');
|
|
23
23
|
const requirePlugin = require('../shell/requirePlugin');
|
|
24
24
|
const path = require('path');
|
|
25
25
|
const { rundir } = require('../utility/directories');
|
|
26
26
|
const fs = require('fs-extra');
|
|
27
|
+
const { changeSetToSql } = require('dbgate-datalib');
|
|
27
28
|
|
|
28
29
|
const logger = getLogger('dbconnProcess');
|
|
29
30
|
|
|
@@ -348,6 +349,27 @@ async function handleUpdateCollection({ msgid, changeSet }) {
|
|
|
348
349
|
}
|
|
349
350
|
}
|
|
350
351
|
|
|
352
|
+
async function handleSaveTableData({ msgid, changeSet }) {
|
|
353
|
+
await waitStructure();
|
|
354
|
+
try {
|
|
355
|
+
const driver = requireEngineDriver(storedConnection);
|
|
356
|
+
const script = driver.createSaveChangeSetScript(changeSet, analysedStructure, () =>
|
|
357
|
+
changeSetToSql(changeSet, analysedStructure, driver.dialect)
|
|
358
|
+
);
|
|
359
|
+
const sql = scriptToSql(driver, script);
|
|
360
|
+
await driver.script(dbhan, sql, { useTransaction: true });
|
|
361
|
+
process.send({ msgtype: 'response', msgid });
|
|
362
|
+
} catch (err) {
|
|
363
|
+
process.send({
|
|
364
|
+
msgtype: 'response',
|
|
365
|
+
msgid,
|
|
366
|
+
errorMessage: extractErrorMessage(err, 'Error executing SQL script'),
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
}
|
|
372
|
+
|
|
351
373
|
async function handleSqlPreview({ msgid, objects, options }) {
|
|
352
374
|
await waitStructure();
|
|
353
375
|
const driver = requireEngineDriver(storedConnection);
|
|
@@ -464,6 +486,7 @@ const messageHandlers = {
|
|
|
464
486
|
runScript: handleRunScript,
|
|
465
487
|
runOperation: handleRunOperation,
|
|
466
488
|
updateCollection: handleUpdateCollection,
|
|
489
|
+
saveTableData: handleSaveTableData,
|
|
467
490
|
collectionData: handleCollectionData,
|
|
468
491
|
loadKeys: handleLoadKeys,
|
|
469
492
|
scanKeys: handleScanKeys,
|
|
@@ -146,6 +146,30 @@ async function handleServerSummary({ msgid }) {
|
|
|
146
146
|
return handleDriverDataCore(msgid, driver => driver.serverSummary(dbhan));
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
async function handleKillDatabaseProcess({ msgid, pid }) {
|
|
150
|
+
await waitConnected();
|
|
151
|
+
const driver = requireEngineDriver(storedConnection);
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
const result = await driver.killProcess(dbhan, Number(pid));
|
|
155
|
+
process.send({ msgtype: 'response', msgid, result });
|
|
156
|
+
} catch (err) {
|
|
157
|
+
process.send({ msgtype: 'response', msgid, errorMessage: err.message });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function handleListDatabaseProcesses({ msgid }) {
|
|
162
|
+
await waitConnected();
|
|
163
|
+
const driver = requireEngineDriver(storedConnection);
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const result = await driver.listProcesses(dbhan);
|
|
167
|
+
process.send({ msgtype: 'response', msgid, result });
|
|
168
|
+
} catch (err) {
|
|
169
|
+
process.send({ msgtype: 'response', msgid, errorMessage: err.message });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
149
173
|
async function handleSummaryCommand({ msgid, command, row }) {
|
|
150
174
|
return handleDriverDataCore(msgid, driver => driver.summaryCommand(dbhan, command, row));
|
|
151
175
|
}
|
|
@@ -154,6 +178,8 @@ const messageHandlers = {
|
|
|
154
178
|
connect: handleConnect,
|
|
155
179
|
ping: handlePing,
|
|
156
180
|
serverSummary: handleServerSummary,
|
|
181
|
+
killDatabaseProcess: handleKillDatabaseProcess,
|
|
182
|
+
listDatabaseProcesses: handleListDatabaseProcesses,
|
|
157
183
|
summaryCommand: handleSummaryCommand,
|
|
158
184
|
createDatabase: props => handleDatabaseOp('createDatabase', props),
|
|
159
185
|
dropDatabase: props => handleDatabaseOp('dropDatabase', props),
|