dbgate-api-premium 7.0.0 → 7.0.2
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbgate-api-premium",
|
|
3
3
|
"main": "src/index.js",
|
|
4
|
-
"version": "7.0.
|
|
4
|
+
"version": "7.0.2",
|
|
5
5
|
"homepage": "https://dbgate.org/",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -24,16 +24,16 @@
|
|
|
24
24
|
"activedirectory2": "^2.1.0",
|
|
25
25
|
"archiver": "^7.0.1",
|
|
26
26
|
"async-lock": "^1.2.6",
|
|
27
|
-
"axios": "^
|
|
27
|
+
"axios": "^1.13.2",
|
|
28
28
|
"body-parser": "^1.19.0",
|
|
29
29
|
"byline": "^5.0.0",
|
|
30
30
|
"compare-versions": "^3.6.0",
|
|
31
31
|
"cors": "^2.8.5",
|
|
32
32
|
"cross-env": "^6.0.3",
|
|
33
|
-
"dbgate-datalib": "^7.0.
|
|
33
|
+
"dbgate-datalib": "^7.0.2",
|
|
34
34
|
"dbgate-query-splitter": "^4.11.9",
|
|
35
|
-
"dbgate-sqltree": "^7.0.
|
|
36
|
-
"dbgate-tools": "^7.0.
|
|
35
|
+
"dbgate-sqltree": "^7.0.2",
|
|
36
|
+
"dbgate-tools": "^7.0.2",
|
|
37
37
|
"debug": "^4.3.4",
|
|
38
38
|
"diff": "^5.0.0",
|
|
39
39
|
"diff2html": "^3.4.13",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@types/fs-extra": "^9.0.11",
|
|
89
89
|
"@types/lodash": "^4.14.149",
|
|
90
|
-
"dbgate-types": "^7.0.
|
|
90
|
+
"dbgate-types": "^7.0.2",
|
|
91
91
|
"env-cmd": "^10.1.0",
|
|
92
92
|
"jsdoc-to-markdown": "^9.0.5",
|
|
93
93
|
"node-loader": "^1.0.2",
|
|
@@ -24,10 +24,12 @@ const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
|
24
24
|
const { getAuthProviderById } = require('../auth/authProvider');
|
|
25
25
|
const { startTokenChecking } = require('../utility/authProxy');
|
|
26
26
|
const { extractConnectionsFromEnv } = require('../utility/envtools');
|
|
27
|
+
const { MissingCredentialsError } = require('../utility/exceptions');
|
|
27
28
|
|
|
28
29
|
const logger = getLogger('connections');
|
|
29
30
|
|
|
30
31
|
let volatileConnections = {};
|
|
32
|
+
let pendingTestSubprocesses = {}; // Map of conid -> subprocess for MS Entra auth flows
|
|
31
33
|
|
|
32
34
|
function getNamedArgs() {
|
|
33
35
|
const res = {};
|
|
@@ -239,14 +241,60 @@ module.exports = {
|
|
|
239
241
|
);
|
|
240
242
|
pipeForkLogs(subprocess);
|
|
241
243
|
subprocess.send({ ...connection, requestDbList });
|
|
242
|
-
return new Promise(resolve => {
|
|
244
|
+
return new Promise((resolve, reject) => {
|
|
245
|
+
let isWaitingForVolatile = false;
|
|
246
|
+
|
|
247
|
+
const cleanup = () => {
|
|
248
|
+
if (connection._id && pendingTestSubprocesses[connection._id]) {
|
|
249
|
+
delete pendingTestSubprocesses[connection._id];
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
243
253
|
subprocess.on('message', resp => {
|
|
244
254
|
if (handleProcessCommunication(resp, subprocess)) return;
|
|
245
255
|
// @ts-ignore
|
|
246
|
-
const { msgtype } = resp;
|
|
256
|
+
const { msgtype, missingCredentialsDetail } = resp;
|
|
247
257
|
if (msgtype == 'connected' || msgtype == 'error') {
|
|
258
|
+
cleanup();
|
|
248
259
|
resolve(resp);
|
|
249
260
|
}
|
|
261
|
+
if (msgtype == 'missingCredentials') {
|
|
262
|
+
if (missingCredentialsDetail?.redirectToDbLogin) {
|
|
263
|
+
// Store the subprocess for later when volatile connection is ready
|
|
264
|
+
isWaitingForVolatile = true;
|
|
265
|
+
pendingTestSubprocesses[connection._id] = {
|
|
266
|
+
subprocess,
|
|
267
|
+
requestDbList,
|
|
268
|
+
};
|
|
269
|
+
// Return immediately with redirectToDbLogin status in the old format
|
|
270
|
+
resolve({
|
|
271
|
+
missingCredentials: true,
|
|
272
|
+
detail: {
|
|
273
|
+
...missingCredentialsDetail,
|
|
274
|
+
keepErrorResponseFromApi: true,
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
reject(new MissingCredentialsError(missingCredentialsDetail));
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
subprocess.on('exit', (code) => {
|
|
284
|
+
// If exit happens while waiting for volatile, that's expected
|
|
285
|
+
if (isWaitingForVolatile && code === 0) {
|
|
286
|
+
cleanup();
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
cleanup();
|
|
290
|
+
if (code !== 0) {
|
|
291
|
+
reject(new Error(`Test subprocess exited with code ${code}`));
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
subprocess.on('error', (err) => {
|
|
296
|
+
cleanup();
|
|
297
|
+
reject(err);
|
|
250
298
|
});
|
|
251
299
|
});
|
|
252
300
|
},
|
|
@@ -279,6 +327,38 @@ module.exports = {
|
|
|
279
327
|
return testRes;
|
|
280
328
|
} else {
|
|
281
329
|
volatileConnections[res._id] = res;
|
|
330
|
+
|
|
331
|
+
// Check if there's a pending test subprocess waiting for this volatile connection
|
|
332
|
+
const pendingTest = pendingTestSubprocesses[conid];
|
|
333
|
+
if (pendingTest) {
|
|
334
|
+
const { subprocess, requestDbList } = pendingTest;
|
|
335
|
+
try {
|
|
336
|
+
// Send the volatile connection to the waiting subprocess
|
|
337
|
+
subprocess.send({ ...res, requestDbList, isVolatileResolved: true });
|
|
338
|
+
|
|
339
|
+
// Wait for the test result and emit it as an event
|
|
340
|
+
subprocess.once('message', resp => {
|
|
341
|
+
if (handleProcessCommunication(resp, subprocess)) return;
|
|
342
|
+
const { msgtype } = resp;
|
|
343
|
+
if (msgtype == 'connected' || msgtype == 'error') {
|
|
344
|
+
// Emit SSE event with test result
|
|
345
|
+
socket.emit(`connection-test-result-${conid}`, {
|
|
346
|
+
...resp,
|
|
347
|
+
volatileConId: res._id,
|
|
348
|
+
});
|
|
349
|
+
delete pendingTestSubprocesses[conid];
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
} catch (err) {
|
|
353
|
+
logger.error(extractErrorLogData(err), 'DBGM-00118 Error sending volatile connection to test subprocess');
|
|
354
|
+
socket.emit(`connection-test-result-${conid}`, {
|
|
355
|
+
msgtype: 'error',
|
|
356
|
+
error: err.message,
|
|
357
|
+
});
|
|
358
|
+
delete pendingTestSubprocesses[conid];
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
282
362
|
return res;
|
|
283
363
|
}
|
|
284
364
|
},
|
|
@@ -957,12 +957,20 @@ async function storageUpdateTeamFile({ teamFileId, data, name, metadata }) {
|
|
|
957
957
|
return true;
|
|
958
958
|
}
|
|
959
959
|
|
|
960
|
-
async function storageUpdateTeamFileAdmin({ teamFileId, name }) {
|
|
960
|
+
async function storageUpdateTeamFileAdmin({ teamFileId, name, teamFolderId, changedContent }) {
|
|
961
961
|
const [conn, driver] = await getStorageConnection();
|
|
962
962
|
if (!conn) {
|
|
963
963
|
return null;
|
|
964
964
|
}
|
|
965
|
-
await storageSqlCommandFmt(
|
|
965
|
+
await storageSqlCommandFmt(
|
|
966
|
+
'update ~team_files set ~file_name = %v, ~team_folder_id = %v where ~id = %v',
|
|
967
|
+
name,
|
|
968
|
+
teamFolderId,
|
|
969
|
+
teamFileId
|
|
970
|
+
);
|
|
971
|
+
if (changedContent != null) {
|
|
972
|
+
await storageSqlCommandFmt('update ~team_files set ~file_content = %v where ~id = %v', changedContent, teamFileId);
|
|
973
|
+
}
|
|
966
974
|
return true;
|
|
967
975
|
}
|
|
968
976
|
|
|
@@ -991,7 +999,7 @@ async function storageListAllAdminFolders() {
|
|
|
991
999
|
|
|
992
1000
|
const resp = await storageSelectFmt(`select ~team_folders.~id, ~team_folders.~folder_name,
|
|
993
1001
|
(select count(*) from ~team_files where ~team_files.~team_folder_id = ~team_folders.~id) as ~file_count
|
|
994
|
-
from ~team_folders`);
|
|
1002
|
+
from ~team_folders order by ~team_folders.~folder_name, ~team_folders.~id`);
|
|
995
1003
|
return resp;
|
|
996
1004
|
}
|
|
997
1005
|
|
|
@@ -1020,6 +1028,7 @@ async function storageListAllAdminFiles() {
|
|
|
1020
1028
|
from ~team_files
|
|
1021
1029
|
inner join ~team_file_types on ~team_files.~file_type_id = ~team_file_types.~id
|
|
1022
1030
|
inner join ~team_folders on ~team_files.~team_folder_id = ~team_folders.~id
|
|
1031
|
+
order by ~team_files.~file_name, ~team_files.~id
|
|
1023
1032
|
`);
|
|
1024
1033
|
return resp;
|
|
1025
1034
|
}
|
|
@@ -375,6 +375,7 @@ module.exports = {
|
|
|
375
375
|
ownerEmail: item.owner_email,
|
|
376
376
|
typeName: item.type_name,
|
|
377
377
|
folderName: item.folder_name,
|
|
378
|
+
teamFolderId: item.team_folder_id,
|
|
378
379
|
}));
|
|
379
380
|
},
|
|
380
381
|
|
|
@@ -392,14 +393,15 @@ module.exports = {
|
|
|
392
393
|
ownerName: existingFile.owner_login,
|
|
393
394
|
ownerEmail: existingFile.owner_email,
|
|
394
395
|
typeName: existingFile.type_name,
|
|
396
|
+
teamFolderId: existingFile.team_folder_id?.toString(),
|
|
395
397
|
};
|
|
396
398
|
},
|
|
397
399
|
|
|
398
400
|
setAdminFile_meta: true,
|
|
399
|
-
async setAdminFile({ id, name }, req) {
|
|
401
|
+
async setAdminFile({ id, name, teamFolderId, changedContent }, req) {
|
|
400
402
|
const loadedPermissions = await loadPermissionsFromRequest(req);
|
|
401
403
|
if (!hasPermission(`admin/team-files`, loadedPermissions)) return false;
|
|
402
|
-
await storageUpdateTeamFileAdmin({ teamFileId: id, name });
|
|
404
|
+
await storageUpdateTeamFileAdmin({ teamFileId: id, name, teamFolderId, changedContent });
|
|
403
405
|
socket.emitChanged('team-files-changed');
|
|
404
406
|
return true;
|
|
405
407
|
},
|
package/src/currentVersion.js
CHANGED
|
@@ -18,13 +18,36 @@ Platform: ${process.platform}
|
|
|
18
18
|
|
|
19
19
|
function start() {
|
|
20
20
|
childProcessChecker();
|
|
21
|
-
|
|
21
|
+
|
|
22
|
+
let isWaitingForVolatile = false;
|
|
23
|
+
|
|
24
|
+
const handleConnection = async connection => {
|
|
22
25
|
// @ts-ignore
|
|
23
26
|
const { requestDbList } = connection;
|
|
24
27
|
if (handleProcessCommunication(connection)) return;
|
|
28
|
+
|
|
25
29
|
try {
|
|
26
30
|
const driver = requireEngineDriver(connection);
|
|
27
|
-
const
|
|
31
|
+
const connectionChanged = driver?.beforeConnectionSave ? driver.beforeConnectionSave(connection) : connection;
|
|
32
|
+
|
|
33
|
+
if (!connection.isVolatileResolved) {
|
|
34
|
+
if (connectionChanged.useRedirectDbLogin) {
|
|
35
|
+
process.send({
|
|
36
|
+
msgtype: 'missingCredentials',
|
|
37
|
+
missingCredentialsDetail: {
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
conid: connection._id,
|
|
40
|
+
redirectToDbLogin: true,
|
|
41
|
+
keepErrorResponseFromApi: true,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
// Don't exit - wait for volatile connection to be sent
|
|
45
|
+
isWaitingForVolatile = true;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const dbhan = await connectUtility(driver, connectionChanged, 'app');
|
|
28
51
|
let version = {
|
|
29
52
|
version: 'Unknown',
|
|
30
53
|
};
|
|
@@ -45,6 +68,16 @@ function start() {
|
|
|
45
68
|
}
|
|
46
69
|
|
|
47
70
|
process.exit(0);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
process.on('message', async connection => {
|
|
74
|
+
// If we're waiting for volatile and receive a new connection, use it
|
|
75
|
+
if (isWaitingForVolatile) {
|
|
76
|
+
isWaitingForVolatile = false;
|
|
77
|
+
await handleConnection(connection);
|
|
78
|
+
} else {
|
|
79
|
+
await handleConnection(connection);
|
|
80
|
+
}
|
|
48
81
|
});
|
|
49
82
|
}
|
|
50
83
|
|