dbgate-api 6.3.0 → 6.3.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/controllers/auth.js +3 -1
- package/src/controllers/connections.js +10 -1
- package/src/controllers/databaseConnections.js +25 -1
- package/src/controllers/files.js +2 -2
- package/src/controllers/serverConnections.js +5 -0
- package/src/currentVersion.js +2 -2
- package/src/main.js +7 -1
- package/src/proc/connectProcess.js +2 -0
- package/src/utility/DatastoreProxy.js +4 -0
- package/src/utility/connectUtility.js +3 -1
- package/src/utility/crypting.js +85 -21
- package/src/utility/getDiagramExport.js +43 -2
- package/src/utility/getMapExport.js +2 -0
- package/src/utility/healthStatus.js +12 -1
- package/src/utility/processArgs.js +5 -0
- package/src/utility/sshTunnel.js +13 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbgate-api",
|
|
3
3
|
"main": "src/index.js",
|
|
4
|
-
"version": "6.3.
|
|
4
|
+
"version": "6.3.3",
|
|
5
5
|
"homepage": "https://dbgate.org/",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"compare-versions": "^3.6.0",
|
|
30
30
|
"cors": "^2.8.5",
|
|
31
31
|
"cross-env": "^6.0.3",
|
|
32
|
-
"dbgate-datalib": "^6.3.
|
|
32
|
+
"dbgate-datalib": "^6.3.3",
|
|
33
33
|
"dbgate-query-splitter": "^4.11.3",
|
|
34
|
-
"dbgate-sqltree": "^6.3.
|
|
35
|
-
"dbgate-tools": "^6.3.
|
|
34
|
+
"dbgate-sqltree": "^6.3.3",
|
|
35
|
+
"dbgate-tools": "^6.3.3",
|
|
36
36
|
"debug": "^4.3.4",
|
|
37
37
|
"diff": "^5.0.0",
|
|
38
38
|
"diff2html": "^3.4.13",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@types/fs-extra": "^9.0.11",
|
|
85
85
|
"@types/lodash": "^4.14.149",
|
|
86
|
-
"dbgate-types": "^6.3.
|
|
86
|
+
"dbgate-types": "^6.3.3",
|
|
87
87
|
"env-cmd": "^10.1.0",
|
|
88
88
|
"jsdoc-to-markdown": "^9.0.5",
|
|
89
89
|
"node-loader": "^1.0.2",
|
package/src/controllers/auth.js
CHANGED
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
getAuthProviderById,
|
|
13
13
|
} = require('../auth/authProvider');
|
|
14
14
|
const storage = require('./storage');
|
|
15
|
+
const { decryptPasswordString } = require('../utility/crypting');
|
|
15
16
|
|
|
16
17
|
const logger = getLogger('auth');
|
|
17
18
|
|
|
@@ -44,6 +45,7 @@ function authMiddleware(req, res, next) {
|
|
|
44
45
|
'/connections/dblogin-auth',
|
|
45
46
|
'/connections/dblogin-auth-token',
|
|
46
47
|
'/health',
|
|
48
|
+
'/__health',
|
|
47
49
|
];
|
|
48
50
|
|
|
49
51
|
// console.log('********************* getAuthProvider()', getAuthProvider());
|
|
@@ -95,7 +97,7 @@ module.exports = {
|
|
|
95
97
|
let adminPassword = process.env.ADMIN_PASSWORD;
|
|
96
98
|
if (!adminPassword) {
|
|
97
99
|
const adminConfig = await storage.readConfig({ group: 'admin' });
|
|
98
|
-
adminPassword = adminConfig?.adminPassword;
|
|
100
|
+
adminPassword = decryptPasswordString(adminConfig?.adminPassword);
|
|
99
101
|
}
|
|
100
102
|
if (adminPassword && adminPassword == password) {
|
|
101
103
|
return {
|
|
@@ -102,12 +102,21 @@ function getPortalCollections() {
|
|
|
102
102
|
trustServerCertificate: process.env[`SSL_TRUST_CERTIFICATE_${id}`],
|
|
103
103
|
}));
|
|
104
104
|
|
|
105
|
+
for(const conn of connections) {
|
|
106
|
+
for(const prop in process.env) {
|
|
107
|
+
if (prop.startsWith(`CONNECTION_${conn._id}_`)) {
|
|
108
|
+
const name = prop.substring(`CONNECTION_${conn._id}_`.length);
|
|
109
|
+
conn[name] = process.env[prop];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
105
114
|
logger.info({ connections: connections.map(pickSafeConnectionInfo) }, 'Using connections from ENV variables');
|
|
106
115
|
const noengine = connections.filter(x => !x.engine);
|
|
107
116
|
if (noengine.length > 0) {
|
|
108
117
|
logger.warn(
|
|
109
118
|
{ connections: noengine.map(x => x._id) },
|
|
110
|
-
'Invalid CONNECTIONS
|
|
119
|
+
'Invalid CONNECTIONS configuration, missing ENGINE for connection ID'
|
|
111
120
|
);
|
|
112
121
|
}
|
|
113
122
|
return connections;
|
|
@@ -37,6 +37,8 @@ const loadModelTransform = require('../utility/loadModelTransform');
|
|
|
37
37
|
const exportDbModelSql = require('../utility/exportDbModelSql');
|
|
38
38
|
const axios = require('axios');
|
|
39
39
|
const { callTextToSqlApi, callCompleteOnCursorApi, callRefactorSqlQueryApi } = require('../utility/authProxy');
|
|
40
|
+
const { decryptConnection } = require('../utility/crypting');
|
|
41
|
+
const { getSshTunnel } = require('../utility/sshTunnel');
|
|
40
42
|
|
|
41
43
|
const logger = getLogger('databaseConnections');
|
|
42
44
|
|
|
@@ -140,6 +142,11 @@ module.exports = {
|
|
|
140
142
|
if (newOpened.disconnected) return;
|
|
141
143
|
this.close(conid, database, false);
|
|
142
144
|
});
|
|
145
|
+
subprocess.on('error', err => {
|
|
146
|
+
logger.error(extractErrorLogData(err), 'Error in database connection subprocess');
|
|
147
|
+
if (newOpened.disconnected) return;
|
|
148
|
+
this.close(conid, database, false);
|
|
149
|
+
});
|
|
143
150
|
|
|
144
151
|
subprocess.send({
|
|
145
152
|
msgtype: 'connect',
|
|
@@ -619,9 +626,26 @@ module.exports = {
|
|
|
619
626
|
command,
|
|
620
627
|
{ conid, database, outputFile, inputFile, options, selectedTables, skippedTables, argsFormat }
|
|
621
628
|
) {
|
|
622
|
-
const
|
|
629
|
+
const sourceConnection = await connections.getCore({ conid });
|
|
630
|
+
const connection = {
|
|
631
|
+
...decryptConnection(sourceConnection),
|
|
632
|
+
};
|
|
623
633
|
const driver = requireEngineDriver(connection);
|
|
624
634
|
|
|
635
|
+
if (!connection.port && driver.defaultPort) {
|
|
636
|
+
connection.port = driver.defaultPort.toString();
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
if (connection.useSshTunnel) {
|
|
640
|
+
const tunnel = await getSshTunnel(connection);
|
|
641
|
+
if (tunnel.state == 'error') {
|
|
642
|
+
throw new Error(tunnel.message);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
connection.server = tunnel.localHost;
|
|
646
|
+
connection.port = tunnel.localPort;
|
|
647
|
+
}
|
|
648
|
+
|
|
625
649
|
const settingsValue = await config.getSettings();
|
|
626
650
|
|
|
627
651
|
const externalTools = {};
|
package/src/controllers/files.js
CHANGED
|
@@ -195,8 +195,8 @@ module.exports = {
|
|
|
195
195
|
},
|
|
196
196
|
|
|
197
197
|
exportDiagram_meta: true,
|
|
198
|
-
async exportDiagram({ filePath, html, css, themeType, themeClassName }) {
|
|
199
|
-
await fs.writeFile(filePath, getDiagramExport(html, css, themeType, themeClassName));
|
|
198
|
+
async exportDiagram({ filePath, html, css, themeType, themeClassName, watermark }) {
|
|
199
|
+
await fs.writeFile(filePath, getDiagramExport(html, css, themeType, themeClassName, watermark));
|
|
200
200
|
return true;
|
|
201
201
|
},
|
|
202
202
|
|
|
@@ -98,6 +98,11 @@ module.exports = {
|
|
|
98
98
|
if (newOpened.disconnected) return;
|
|
99
99
|
this.close(conid, false);
|
|
100
100
|
});
|
|
101
|
+
subprocess.on('error', err => {
|
|
102
|
+
logger.error(extractErrorLogData(err), 'Error in server connection subprocess');
|
|
103
|
+
if (newOpened.disconnected) return;
|
|
104
|
+
this.close(conid, false);
|
|
105
|
+
});
|
|
101
106
|
subprocess.send({ msgtype: 'connect', ...connection, globalSettings: await config.getSettings() });
|
|
102
107
|
return newOpened;
|
|
103
108
|
});
|
package/src/currentVersion.js
CHANGED
package/src/main.js
CHANGED
|
@@ -38,7 +38,7 @@ const { getLogger } = require('dbgate-tools');
|
|
|
38
38
|
const { getDefaultAuthProvider } = require('./auth/authProvider');
|
|
39
39
|
const startCloudUpgradeTimer = require('./utility/cloudUpgrade');
|
|
40
40
|
const { isProApp } = require('./utility/checkLicense');
|
|
41
|
-
const getHealthStatus = require('./utility/healthStatus');
|
|
41
|
+
const { getHealthStatus, getHealthStatusSprinx } = require('./utility/healthStatus');
|
|
42
42
|
|
|
43
43
|
const logger = getLogger('main');
|
|
44
44
|
|
|
@@ -124,6 +124,12 @@ function start() {
|
|
|
124
124
|
res.end(JSON.stringify(health, null, 2));
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
+
app.get(getExpressPath('/__health'), async function (req, res) {
|
|
128
|
+
res.setHeader('Content-Type', 'application/json');
|
|
129
|
+
const health = await getHealthStatusSprinx();
|
|
130
|
+
res.end(JSON.stringify(health, null, 2));
|
|
131
|
+
});
|
|
132
|
+
|
|
127
133
|
app.use(bodyParser.json({ limit: '50mb' }));
|
|
128
134
|
|
|
129
135
|
app.use(
|
|
@@ -60,6 +60,10 @@ class DatastoreProxy {
|
|
|
60
60
|
// if (this.disconnected) return;
|
|
61
61
|
this.subprocess = null;
|
|
62
62
|
});
|
|
63
|
+
this.subprocess.on('error', err => {
|
|
64
|
+
logger.error(extractErrorLogData(err), 'Error in data store subprocess');
|
|
65
|
+
this.subprocess = null;
|
|
66
|
+
});
|
|
63
67
|
this.subprocess.send({ msgtype: 'open', file: this.file });
|
|
64
68
|
}
|
|
65
69
|
return this.subprocess;
|
|
@@ -96,7 +96,9 @@ async function connectUtility(driver, storedConnection, connectionMode, addition
|
|
|
96
96
|
...decryptConnection(connectionLoaded),
|
|
97
97
|
};
|
|
98
98
|
|
|
99
|
-
if (!connection.port && driver.defaultPort)
|
|
99
|
+
if (!connection.port && driver.defaultPort) {
|
|
100
|
+
connection.port = driver.defaultPort.toString();
|
|
101
|
+
}
|
|
100
102
|
|
|
101
103
|
if (connection.useSshTunnel) {
|
|
102
104
|
const tunnel = await getSshTunnelProxy(connection);
|
package/src/utility/crypting.js
CHANGED
|
@@ -5,12 +5,16 @@ const path = require('path');
|
|
|
5
5
|
const _ = require('lodash');
|
|
6
6
|
|
|
7
7
|
const { datadir } = require('./directories');
|
|
8
|
+
const { encryptionKeyArg } = require('./processArgs');
|
|
8
9
|
|
|
9
10
|
const defaultEncryptionKey = 'mQAUaXhavRGJDxDTXSCg7Ej0xMmGCrx6OKA07DIMBiDcYYkvkaXjTAzPUEHEHEf9';
|
|
10
11
|
|
|
11
12
|
let _encryptionKey = null;
|
|
12
13
|
|
|
13
14
|
function loadEncryptionKey() {
|
|
15
|
+
if (encryptionKeyArg) {
|
|
16
|
+
return encryptionKeyArg;
|
|
17
|
+
}
|
|
14
18
|
if (_encryptionKey) {
|
|
15
19
|
return _encryptionKey;
|
|
16
20
|
}
|
|
@@ -33,6 +37,26 @@ function loadEncryptionKey() {
|
|
|
33
37
|
return _encryptionKey;
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
async function loadEncryptionKeyFromExternal(storedValue, setStoredValue) {
|
|
41
|
+
const encryptor = simpleEncryptor.createEncryptor(defaultEncryptionKey);
|
|
42
|
+
|
|
43
|
+
if (!storedValue) {
|
|
44
|
+
const generatedKey = crypto.randomBytes(32);
|
|
45
|
+
const newKey = generatedKey.toString('hex');
|
|
46
|
+
const result = {
|
|
47
|
+
encryptionKey: newKey,
|
|
48
|
+
};
|
|
49
|
+
await setStoredValue(encryptor.encrypt(result));
|
|
50
|
+
|
|
51
|
+
setEncryptionKey(newKey);
|
|
52
|
+
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const data = encryptor.decrypt(storedValue);
|
|
57
|
+
setEncryptionKey(data['encryptionKey']);
|
|
58
|
+
}
|
|
59
|
+
|
|
36
60
|
let _encryptor = null;
|
|
37
61
|
|
|
38
62
|
function getEncryptor() {
|
|
@@ -43,35 +67,46 @@ function getEncryptor() {
|
|
|
43
67
|
return _encryptor;
|
|
44
68
|
}
|
|
45
69
|
|
|
46
|
-
function
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
70
|
+
function encryptPasswordString(password) {
|
|
71
|
+
if (password && !password.startsWith('crypt:')) {
|
|
72
|
+
return 'crypt:' + getEncryptor().encrypt(password);
|
|
73
|
+
}
|
|
74
|
+
return password;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function decryptPasswordString(password) {
|
|
78
|
+
if (password && password.startsWith('crypt:')) {
|
|
79
|
+
return getEncryptor().decrypt(password.substring('crypt:'.length));
|
|
80
|
+
}
|
|
81
|
+
return password;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function encryptObjectPasswordField(obj, field) {
|
|
85
|
+
if (obj && obj[field] && !obj[field].startsWith('crypt:')) {
|
|
53
86
|
return {
|
|
54
|
-
...
|
|
55
|
-
[field]: 'crypt:' + getEncryptor().encrypt(
|
|
87
|
+
...obj,
|
|
88
|
+
[field]: 'crypt:' + getEncryptor().encrypt(obj[field]),
|
|
56
89
|
};
|
|
57
90
|
}
|
|
58
|
-
return
|
|
91
|
+
return obj;
|
|
59
92
|
}
|
|
60
93
|
|
|
61
|
-
function
|
|
62
|
-
if (
|
|
94
|
+
function decryptObjectPasswordField(obj, field) {
|
|
95
|
+
if (obj && obj[field] && obj[field].startsWith('crypt:')) {
|
|
63
96
|
return {
|
|
64
|
-
...
|
|
65
|
-
[field]: getEncryptor().decrypt(
|
|
97
|
+
...obj,
|
|
98
|
+
[field]: getEncryptor().decrypt(obj[field].substring('crypt:'.length)),
|
|
66
99
|
};
|
|
67
100
|
}
|
|
68
|
-
return
|
|
101
|
+
return obj;
|
|
69
102
|
}
|
|
70
103
|
|
|
71
104
|
function encryptConnection(connection) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
105
|
+
if (connection.passwordMode != 'saveRaw') {
|
|
106
|
+
connection = encryptObjectPasswordField(connection, 'password');
|
|
107
|
+
connection = encryptObjectPasswordField(connection, 'sshPassword');
|
|
108
|
+
connection = encryptObjectPasswordField(connection, 'sshKeyfilePassword');
|
|
109
|
+
}
|
|
75
110
|
return connection;
|
|
76
111
|
}
|
|
77
112
|
|
|
@@ -81,12 +116,24 @@ function maskConnection(connection) {
|
|
|
81
116
|
}
|
|
82
117
|
|
|
83
118
|
function decryptConnection(connection) {
|
|
84
|
-
connection =
|
|
85
|
-
connection =
|
|
86
|
-
connection =
|
|
119
|
+
connection = decryptObjectPasswordField(connection, 'password');
|
|
120
|
+
connection = decryptObjectPasswordField(connection, 'sshPassword');
|
|
121
|
+
connection = decryptObjectPasswordField(connection, 'sshKeyfilePassword');
|
|
87
122
|
return connection;
|
|
88
123
|
}
|
|
89
124
|
|
|
125
|
+
function encryptUser(user) {
|
|
126
|
+
if (user.encryptPassword) {
|
|
127
|
+
user = encryptObjectPasswordField(user, 'password');
|
|
128
|
+
}
|
|
129
|
+
return user;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function decryptUser(user) {
|
|
133
|
+
user = decryptObjectPasswordField(user, 'password');
|
|
134
|
+
return user;
|
|
135
|
+
}
|
|
136
|
+
|
|
90
137
|
function pickSafeConnectionInfo(connection) {
|
|
91
138
|
if (process.env.LOG_CONNECTION_SENSITIVE_VALUES) {
|
|
92
139
|
return connection;
|
|
@@ -99,10 +146,27 @@ function pickSafeConnectionInfo(connection) {
|
|
|
99
146
|
});
|
|
100
147
|
}
|
|
101
148
|
|
|
149
|
+
function setEncryptionKey(encryptionKey) {
|
|
150
|
+
_encryptionKey = encryptionKey;
|
|
151
|
+
_encryptor = null;
|
|
152
|
+
global.ENCRYPTION_KEY = encryptionKey;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function getEncryptionKey() {
|
|
156
|
+
return _encryptionKey;
|
|
157
|
+
}
|
|
158
|
+
|
|
102
159
|
module.exports = {
|
|
103
160
|
loadEncryptionKey,
|
|
104
161
|
encryptConnection,
|
|
162
|
+
encryptUser,
|
|
163
|
+
decryptUser,
|
|
105
164
|
decryptConnection,
|
|
106
165
|
maskConnection,
|
|
107
166
|
pickSafeConnectionInfo,
|
|
167
|
+
loadEncryptionKeyFromExternal,
|
|
168
|
+
getEncryptionKey,
|
|
169
|
+
setEncryptionKey,
|
|
170
|
+
encryptPasswordString,
|
|
171
|
+
decryptPasswordString,
|
|
108
172
|
};
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
const getDiagramExport = (html, css, themeType, themeClassName) => {
|
|
1
|
+
const getDiagramExport = (html, css, themeType, themeClassName, watermark) => {
|
|
2
|
+
const watermarkHtml = watermark
|
|
3
|
+
? `
|
|
4
|
+
<div style="position: fixed; bottom: 0; right: 0; padding: 5px; font-size: 12px; color: var(--theme-font-2); background-color: var(--theme-bg-2); border-top-left-radius: 5px; border: 1px solid var(--theme-border);">
|
|
5
|
+
${watermark}
|
|
6
|
+
</div>
|
|
7
|
+
`
|
|
8
|
+
: '';
|
|
2
9
|
return `<html>
|
|
3
10
|
<meta charset='utf-8'>
|
|
4
11
|
|
|
@@ -13,10 +20,44 @@ const getDiagramExport = (html, css, themeType, themeClassName) => {
|
|
|
13
20
|
</style>
|
|
14
21
|
|
|
15
22
|
<link rel="stylesheet" href='https://cdn.jsdelivr.net/npm/@mdi/font@6.5.95/css/materialdesignicons.css' />
|
|
23
|
+
|
|
24
|
+
<script>
|
|
25
|
+
let lastX = null;
|
|
26
|
+
let lastY = null;
|
|
27
|
+
|
|
28
|
+
const handleMoveDown = e => {
|
|
29
|
+
lastX = e.clientX;
|
|
30
|
+
lastY = e.clientY;
|
|
31
|
+
document.addEventListener('mousemove', handleMoveMove, true);
|
|
32
|
+
document.addEventListener('mouseup', handleMoveEnd, true);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const handleMoveMove = e => {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
|
|
38
|
+
document.body.scrollLeft -= e.clientX - lastX;
|
|
39
|
+
document.body.scrollTop -= e.clientY - lastY;
|
|
40
|
+
|
|
41
|
+
lastX = e.clientX;
|
|
42
|
+
lastY = e.clientY;
|
|
43
|
+
};
|
|
44
|
+
const handleMoveEnd = e => {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
e.stopPropagation();
|
|
47
|
+
|
|
48
|
+
lastX = null;
|
|
49
|
+
lastY = null;
|
|
50
|
+
document.removeEventListener('mousemove', handleMoveMove, true);
|
|
51
|
+
document.removeEventListener('mouseup', handleMoveEnd, true);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
document.addEventListener('mousedown', handleMoveDown);
|
|
55
|
+
</script>
|
|
16
56
|
</head>
|
|
17
57
|
|
|
18
|
-
<body class='${themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'} ${themeClassName}'>
|
|
58
|
+
<body class='${themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'} ${themeClassName}' style='user-select:none; cursor:pointer'>
|
|
19
59
|
${html}
|
|
60
|
+
${watermarkHtml}
|
|
20
61
|
</body>
|
|
21
62
|
|
|
22
63
|
</html>`;
|
|
@@ -24,4 +24,15 @@ async function getHealthStatus() {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
async function getHealthStatusSprinx() {
|
|
28
|
+
return {
|
|
29
|
+
overallStatus: 'OK',
|
|
30
|
+
timeStamp: new Date().toISOString(),
|
|
31
|
+
timeStampUnix: Math.floor(Date.now() / 1000),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
getHealthStatus,
|
|
37
|
+
getHealthStatusSprinx,
|
|
38
|
+
};
|
|
@@ -17,6 +17,7 @@ const processDisplayName = getNamedArg('--process-display-name');
|
|
|
17
17
|
const listenApi = process.argv.includes('--listen-api');
|
|
18
18
|
const listenApiChild = process.argv.includes('--listen-api-child') || listenApi;
|
|
19
19
|
const runE2eTests = process.argv.includes('--run-e2e-tests');
|
|
20
|
+
const encryptionKeyArg = getNamedArg('--encryption-key');
|
|
20
21
|
|
|
21
22
|
function getPassArgs() {
|
|
22
23
|
const res = [];
|
|
@@ -31,6 +32,9 @@ function getPassArgs() {
|
|
|
31
32
|
if (runE2eTests) {
|
|
32
33
|
res.push('--run-e2e-tests');
|
|
33
34
|
}
|
|
35
|
+
if (global['ENCRYPTION_KEY']) {
|
|
36
|
+
res.push('--encryption-key', global['ENCRYPTION_KEY']);
|
|
37
|
+
}
|
|
34
38
|
return res;
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -45,4 +49,5 @@ module.exports = {
|
|
|
45
49
|
listenApiChild,
|
|
46
50
|
processDisplayName,
|
|
47
51
|
runE2eTests,
|
|
52
|
+
encryptionKeyArg,
|
|
48
53
|
};
|
package/src/utility/sshTunnel.js
CHANGED
|
@@ -57,10 +57,21 @@ function callForwardProcess(connection, tunnelConfig, tunnelCacheKey) {
|
|
|
57
57
|
}
|
|
58
58
|
});
|
|
59
59
|
subprocess.on('exit', code => {
|
|
60
|
-
logger.info(
|
|
60
|
+
logger.info(`SSH forward process exited with code ${code}`);
|
|
61
61
|
delete sshTunnelCache[tunnelCacheKey];
|
|
62
62
|
if (!promiseHandled) {
|
|
63
|
-
reject(
|
|
63
|
+
reject(
|
|
64
|
+
new Error(
|
|
65
|
+
'SSH forward process exited, try to change "Local host address for SSH connections" in Settings/Connections'
|
|
66
|
+
)
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
subprocess.on('error', error => {
|
|
71
|
+
logger.error(extractErrorLogData(error), 'SSH forward process error');
|
|
72
|
+
delete sshTunnelCache[tunnelCacheKey];
|
|
73
|
+
if (!promiseHandled) {
|
|
74
|
+
reject(error);
|
|
64
75
|
}
|
|
65
76
|
});
|
|
66
77
|
});
|