dbgate-api-premium 6.1.6 → 6.2.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 +7 -5
- package/src/auth/storageAuthProvider.js +27 -22
- package/src/controllers/config.js +9 -3
- package/src/controllers/databaseConnections.js +56 -2
- package/src/controllers/storage.js +4 -8
- package/src/controllers/storageDb.js +54 -13
- package/src/currentVersion.js +2 -2
- package/src/main.js +6 -0
- package/src/proc/connectProcess.js +1 -1
- package/src/proc/databaseConnectionProcess.js +18 -10
- package/src/proc/serverConnectionProcess.js +1 -1
- package/src/proc/sessionProcess.js +1 -1
- package/src/shell/dataDuplicator.js +1 -1
- package/src/shell/deployDb.js +1 -1
- package/src/shell/dropAllDbObjects.js +1 -1
- package/src/shell/dumpDatabase.js +1 -1
- package/src/shell/executeQuery.js +1 -1
- package/src/shell/generateDeploySql.js +1 -1
- package/src/shell/importDatabase.js +1 -1
- package/src/shell/loadDatabase.js +1 -1
- package/src/shell/queryReader.js +1 -1
- package/src/shell/tableReader.js +1 -1
- package/src/shell/tableWriter.js +1 -1
- package/src/utility/authProxy.js +135 -20
- package/src/utility/checkLicense.js +31 -9
- package/src/utility/connectUtility.js +42 -33
- package/src/utility/directories.js +7 -2
- package/src/utility/hardwareFingerprint.js +1 -0
- package/src/utility/platformInfo.js +2 -0
- package/src/utility/processArgs.js +3 -3
- package/src/utility/useController.js +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbgate-api-premium",
|
|
3
3
|
"main": "src/index.js",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.2.0",
|
|
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.
|
|
32
|
+
"dbgate-datalib": "^6.2.0",
|
|
33
33
|
"dbgate-query-splitter": "^4.11.3",
|
|
34
|
-
"dbgate-sqltree": "^6.
|
|
35
|
-
"dbgate-tools": "^6.
|
|
34
|
+
"dbgate-sqltree": "^6.2.0",
|
|
35
|
+
"dbgate-tools": "^6.2.0",
|
|
36
36
|
"debug": "^4.3.4",
|
|
37
37
|
"diff": "^5.0.0",
|
|
38
38
|
"diff2html": "^3.4.13",
|
|
@@ -74,6 +74,8 @@
|
|
|
74
74
|
"start:storage": "env-cmd -f env/storage/.env node src/index.js --listen-api",
|
|
75
75
|
"start:storage:built": "env-cmd -f env/storage/.env cross-env DEVMODE= BUILTWEBMODE=1 node dist/bundle.js --listen-api",
|
|
76
76
|
"start:singleconn": "env-cmd node src/index.js --server localhost --user root --port 3307 --engine mysql@dbgate-plugin-mysql --password test --listen-api",
|
|
77
|
+
"start:azure": "env-cmd -f env/azure/.env node src/index.js --listen-api",
|
|
78
|
+
"start:e2e:team": "cross-env DEVWEB=1 DEVMODE=1 env-cmd -f ../../e2e-tests/env/team/.env node src/index.js --listen-api",
|
|
77
79
|
"ts": "tsc",
|
|
78
80
|
"build": "webpack",
|
|
79
81
|
"build:doc": "jsdoc2md --template doctpl.hbs ./src/shell/* > ../../../dbgate.github.io/_docs/apidoc.md"
|
|
@@ -81,7 +83,7 @@
|
|
|
81
83
|
"devDependencies": {
|
|
82
84
|
"@types/fs-extra": "^9.0.11",
|
|
83
85
|
"@types/lodash": "^4.14.149",
|
|
84
|
-
"dbgate-types": "^6.
|
|
86
|
+
"dbgate-types": "^6.2.0",
|
|
85
87
|
"env-cmd": "^10.1.0",
|
|
86
88
|
"jsdoc-to-markdown": "^9.0.5",
|
|
87
89
|
"node-loader": "^1.0.2",
|
|
@@ -3,12 +3,14 @@ const {
|
|
|
3
3
|
getPredefinedPermissions,
|
|
4
4
|
getLogger,
|
|
5
5
|
getConnectionLabel,
|
|
6
|
+
runQueryFmt,
|
|
6
7
|
} = require('dbgate-tools');
|
|
7
8
|
const {
|
|
8
9
|
storageSelectFmt,
|
|
9
10
|
storageReadUserRolePermissions,
|
|
10
11
|
storageReadUserPermissions,
|
|
11
12
|
storageReadRolePermissions,
|
|
13
|
+
storageSqlCommandFmt,
|
|
12
14
|
} = require('../controllers/storageDb');
|
|
13
15
|
const { getTokenSecret, getTokenLifetime } = require('./authCommon');
|
|
14
16
|
const { AuthProviderBase } = require('./authProvider');
|
|
@@ -129,9 +131,13 @@ class OauthProvider extends StorageProviderBase {
|
|
|
129
131
|
)}&client_id=${this.config.oauthClient}&client_secret=${this.config.oauthClientSecret}${scopeParam}`
|
|
130
132
|
);
|
|
131
133
|
|
|
132
|
-
const { access_token, refresh_token } = resp.data;
|
|
134
|
+
const { access_token, id_token, refresh_token } = resp.data;
|
|
133
135
|
|
|
134
|
-
|
|
136
|
+
if (!id_token && !access_token) {
|
|
137
|
+
return { error: 'Token not found' };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const payload = jwt.decode(id_token ?? access_token);
|
|
135
141
|
|
|
136
142
|
logger.info({ payload }, 'User payload returned from OAUTH');
|
|
137
143
|
|
|
@@ -143,10 +149,13 @@ class OauthProvider extends StorageProviderBase {
|
|
|
143
149
|
const loginRows = await storageSelectFmt('select * from ~users where ~login = %v', login);
|
|
144
150
|
const permissions = await loadPermissionsForUserId(loginRows[0]?.id ?? -1);
|
|
145
151
|
|
|
146
|
-
if (this.config.oauthOnlyDefinedLogins == 1) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
152
|
+
if (this.config.oauthOnlyDefinedLogins == 1 && loginRows.length == 0) {
|
|
153
|
+
return { error: `Username ${login} not allowed to log in` };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (this.config.oauthSaveNotDefinedLogins == 1 && loginRows.length == 0) {
|
|
157
|
+
const email = payload[this.config.oauthEmailField || 'email'] ?? null;
|
|
158
|
+
await storageSqlCommandFmt('insert into ~users (~login, ~email) values (%v, %v)', login, email);
|
|
150
159
|
}
|
|
151
160
|
|
|
152
161
|
let groups =
|
|
@@ -165,22 +174,18 @@ class OauthProvider extends StorageProviderBase {
|
|
|
165
174
|
}
|
|
166
175
|
}
|
|
167
176
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return { error: 'Token not found' };
|
|
177
|
+
return {
|
|
178
|
+
accessToken: jwt.sign(
|
|
179
|
+
{
|
|
180
|
+
amoid: this.amoid,
|
|
181
|
+
login,
|
|
182
|
+
permissions,
|
|
183
|
+
userId: loginRows[0]?.id,
|
|
184
|
+
},
|
|
185
|
+
getTokenSecret(),
|
|
186
|
+
{ expiresIn: getTokenLifetime() }
|
|
187
|
+
),
|
|
188
|
+
};
|
|
184
189
|
}
|
|
185
190
|
|
|
186
191
|
redirect({ state, redirectUri }) {
|
|
@@ -136,7 +136,7 @@ module.exports = {
|
|
|
136
136
|
|
|
137
137
|
deleteSettings_meta: true,
|
|
138
138
|
async deleteSettings() {
|
|
139
|
-
await fs.unlink(path.join(datadir(), 'settings.json'));
|
|
139
|
+
await fs.unlink(path.join(datadir(), processArgs.runE2eTests ? 'settings-e2etests.json' : 'settings.json'));
|
|
140
140
|
return true;
|
|
141
141
|
},
|
|
142
142
|
|
|
@@ -161,7 +161,10 @@ module.exports = {
|
|
|
161
161
|
|
|
162
162
|
async loadSettings() {
|
|
163
163
|
try {
|
|
164
|
-
const settingsText = await fs.readFile(
|
|
164
|
+
const settingsText = await fs.readFile(
|
|
165
|
+
path.join(datadir(), processArgs.runE2eTests ? 'settings-e2etests.json' : 'settings.json'),
|
|
166
|
+
{ encoding: 'utf-8' }
|
|
167
|
+
);
|
|
165
168
|
return {
|
|
166
169
|
...this.fillMissingSettings(JSON.parse(settingsText)),
|
|
167
170
|
'other.licenseKey': platformInfo.isElectron ? await this.loadLicenseKey() : undefined,
|
|
@@ -247,7 +250,10 @@ module.exports = {
|
|
|
247
250
|
...currentValue,
|
|
248
251
|
..._.omit(values, ['other.licenseKey']),
|
|
249
252
|
};
|
|
250
|
-
await fs.writeFile(
|
|
253
|
+
await fs.writeFile(
|
|
254
|
+
path.join(datadir(), processArgs.runE2eTests ? 'settings-e2etests.json' : 'settings.json'),
|
|
255
|
+
JSON.stringify(updated, undefined, 2)
|
|
256
|
+
);
|
|
251
257
|
// this.settingsValue = updated;
|
|
252
258
|
|
|
253
259
|
if (currentValue['other.licenseKey'] != values['other.licenseKey']) {
|
|
@@ -34,6 +34,8 @@ const pipeForkLogs = require('../utility/pipeForkLogs');
|
|
|
34
34
|
const crypto = require('crypto');
|
|
35
35
|
const loadModelTransform = require('../utility/loadModelTransform');
|
|
36
36
|
const exportDbModelSql = require('../utility/exportDbModelSql');
|
|
37
|
+
const axios = require('axios');
|
|
38
|
+
const { callTextToSqlApi, callCompleteOnCursorApi, callRefactorSqlQueryApi } = require('../utility/authProxy');
|
|
37
39
|
|
|
38
40
|
const logger = getLogger('databaseConnections');
|
|
39
41
|
|
|
@@ -69,6 +71,11 @@ module.exports = {
|
|
|
69
71
|
handle_error(conid, database, props) {
|
|
70
72
|
const { error } = props;
|
|
71
73
|
logger.error(`Error in database connection ${conid}, database ${database}: ${error}`);
|
|
74
|
+
if (props?.msgid) {
|
|
75
|
+
const [resolve, reject] = this.requests[props?.msgid];
|
|
76
|
+
reject(error);
|
|
77
|
+
delete this.requests[props?.msgid];
|
|
78
|
+
}
|
|
72
79
|
},
|
|
73
80
|
handle_response(conid, database, { msgid, ...response }) {
|
|
74
81
|
const [resolve, reject] = this.requests[msgid];
|
|
@@ -253,9 +260,9 @@ module.exports = {
|
|
|
253
260
|
},
|
|
254
261
|
|
|
255
262
|
loadFieldValues_meta: true,
|
|
256
|
-
async loadFieldValues({ conid, database, schemaName, pureName, field, search }, req) {
|
|
263
|
+
async loadFieldValues({ conid, database, schemaName, pureName, field, search, dataType }, req) {
|
|
257
264
|
testConnectionPermission(conid, req);
|
|
258
|
-
return this.loadDataCore('loadFieldValues', { conid, database, schemaName, pureName, field, search });
|
|
265
|
+
return this.loadDataCore('loadFieldValues', { conid, database, schemaName, pureName, field, search, dataType });
|
|
259
266
|
},
|
|
260
267
|
|
|
261
268
|
callMethod_meta: true,
|
|
@@ -401,6 +408,10 @@ module.exports = {
|
|
|
401
408
|
|
|
402
409
|
structure_meta: true,
|
|
403
410
|
async structure({ conid, database, modelTransFile = null }, req) {
|
|
411
|
+
if (!conid || !database) {
|
|
412
|
+
return {};
|
|
413
|
+
}
|
|
414
|
+
|
|
404
415
|
testConnectionPermission(conid, req);
|
|
405
416
|
if (conid == '__model') {
|
|
406
417
|
const model = await importDbModel(database);
|
|
@@ -558,4 +569,47 @@ module.exports = {
|
|
|
558
569
|
|
|
559
570
|
return true;
|
|
560
571
|
},
|
|
572
|
+
|
|
573
|
+
textToSql_meta: true,
|
|
574
|
+
async textToSql({ conid, database, text, dialect }) {
|
|
575
|
+
const existing = this.opened.find(x => x.conid == conid && x.database == database);
|
|
576
|
+
const { structure } = existing || {};
|
|
577
|
+
if (!structure) return { errorMessage: 'No database structure' };
|
|
578
|
+
|
|
579
|
+
const res = await callTextToSqlApi(text, structure, dialect);
|
|
580
|
+
|
|
581
|
+
if (!res?.sql) {
|
|
582
|
+
return { errorMessage: 'No SQL generated' };
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
return res;
|
|
586
|
+
},
|
|
587
|
+
|
|
588
|
+
completeOnCursor_meta: true,
|
|
589
|
+
async completeOnCursor({ conid, database, text, dialect, line }) {
|
|
590
|
+
const existing = this.opened.find(x => x.conid == conid && x.database == database);
|
|
591
|
+
const { structure } = existing || {};
|
|
592
|
+
if (!structure) return { errorMessage: 'No database structure' };
|
|
593
|
+
const res = await callCompleteOnCursorApi(text, structure, dialect, line);
|
|
594
|
+
|
|
595
|
+
if (!res?.variants) {
|
|
596
|
+
return { errorMessage: 'No SQL generated' };
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
return res;
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
refactorSqlQuery_meta: true,
|
|
603
|
+
async refactorSqlQuery({ conid, database, query, task, dialect }) {
|
|
604
|
+
const existing = this.opened.find(x => x.conid == conid && x.database == database);
|
|
605
|
+
const { structure } = existing || {};
|
|
606
|
+
if (!structure) return { errorMessage: 'No database structure' };
|
|
607
|
+
const res = await callRefactorSqlQueryApi(query, task, structure, dialect);
|
|
608
|
+
|
|
609
|
+
if (!res?.sql) {
|
|
610
|
+
return { errorMessage: 'No SQL generated' };
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return res;
|
|
614
|
+
},
|
|
561
615
|
};
|
|
@@ -17,7 +17,7 @@ const { hasPermission } = require('../utility/hasPermission');
|
|
|
17
17
|
const { changeSetToSql, removeSchemaFromChangeSet } = require('dbgate-datalib');
|
|
18
18
|
const storageModel = require('../storageModel');
|
|
19
19
|
const { dumpSqlCommand } = require('dbgate-sqltree');
|
|
20
|
-
const { runCommandOnDriver, getLogger } = require('dbgate-tools');
|
|
20
|
+
const { runCommandOnDriver, getLogger, runQueryFmt } = require('dbgate-tools');
|
|
21
21
|
const socket = require('../utility/socket');
|
|
22
22
|
const { obtainRefreshedLicense } = require('../utility/authProxy');
|
|
23
23
|
const { datadir } = require('../utility/directories');
|
|
@@ -31,11 +31,6 @@ function mapConnection(connnection) {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
async function runQueryFmt(driver, conn, query, ...args) {
|
|
35
|
-
const dmp = driver.createDumper();
|
|
36
|
-
dmp.put(query, ...args);
|
|
37
|
-
await driver.query(conn, dmp.s);
|
|
38
|
-
}
|
|
39
34
|
|
|
40
35
|
let refreshLicenseStarted = false;
|
|
41
36
|
|
|
@@ -140,7 +135,7 @@ module.exports = {
|
|
|
140
135
|
displayName: 'Internal storage',
|
|
141
136
|
defaultDatabase: process.env.STORAGE_DATABASE,
|
|
142
137
|
singleDatabase: true,
|
|
143
|
-
...getDbConnectionParams(),
|
|
138
|
+
...await getDbConnectionParams(),
|
|
144
139
|
};
|
|
145
140
|
}
|
|
146
141
|
|
|
@@ -197,7 +192,8 @@ module.exports = {
|
|
|
197
192
|
await runQueryFmt(
|
|
198
193
|
driver,
|
|
199
194
|
conn,
|
|
200
|
-
'update auth_methods set is_disabled=%v, is_default = %v, is_collapsed = %v where id = %v',
|
|
195
|
+
'update auth_methods set name=%v, is_disabled=%v, is_default = %v, is_collapsed = %v where id = %v',
|
|
196
|
+
method.name,
|
|
201
197
|
method.isDisabled,
|
|
202
198
|
method.isDefault,
|
|
203
199
|
method.isCollapsed,
|
|
@@ -4,8 +4,9 @@ const dbgateApi = require('../shell');
|
|
|
4
4
|
const { getPredefinedPermissions, getLogger, extractErrorLogData } = require('dbgate-tools');
|
|
5
5
|
const _ = require('lodash');
|
|
6
6
|
const logger = getLogger('storageDb');
|
|
7
|
+
const { extractConnectionSslParams } = require('../utility/connectUtility');
|
|
7
8
|
|
|
8
|
-
function getDbConnectionParams() {
|
|
9
|
+
async function getDbConnectionParams() {
|
|
9
10
|
const server = process.env.STORAGE_SERVER;
|
|
10
11
|
const port = process.env.STORAGE_PORT;
|
|
11
12
|
const user = process.env.STORAGE_USER;
|
|
@@ -13,21 +14,33 @@ function getDbConnectionParams() {
|
|
|
13
14
|
const database = process.env.STORAGE_DATABASE;
|
|
14
15
|
const engine = process.env.STORAGE_ENGINE;
|
|
15
16
|
const serviceName = process.env.STORAGE_SERVICE_NAME;
|
|
17
|
+
const socketPath = process.env.STORAGE_SOCKET_PATH;
|
|
18
|
+
const databaseUrl = process.env.STORAGE_DATABASE_URL;
|
|
19
|
+
const useDatabaseUrl = !!process.env.STORAGE_DATABASE_URL;
|
|
20
|
+
const authType = process.env.STORAGE_AUTH_TYPE;
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
const useSsl = process.env.STORAGE_USE_SSL;
|
|
23
|
+
const sslCaFile = process.env.STORAGE_SSL_CA_FILE;
|
|
24
|
+
const sslCertFile = process.env.STORAGE_SSL_CERT_FILE;
|
|
25
|
+
const sslCertFilePassword = process.env.STORAGE_SSL_CERT_FILE_PASSWORD;
|
|
26
|
+
const sslKeyFile = process.env.STORAGE_SSL_KEY_FILE;
|
|
27
|
+
const sslRejectUnauthorized = process.env.STORAGE_SSL_REJECT_UNAUTHORIZED;
|
|
28
|
+
const trustServerCertificate = process.env.STORAGE_SSL_TRUST_CERTIFICATE;
|
|
29
|
+
|
|
30
|
+
if (!server || !engine) {
|
|
18
31
|
if (database) {
|
|
19
32
|
if (!server) {
|
|
20
33
|
throw new Error('Incorrect storage configuration, missing env variable STORAGE_SERVER');
|
|
21
34
|
}
|
|
22
|
-
if (!port) {
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
if (!user) {
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
if (!password) {
|
|
29
|
-
|
|
30
|
-
}
|
|
35
|
+
// if (!port) {
|
|
36
|
+
// throw new Error('Incorrect storage configuration, missing env variable STORAGE_PORT');
|
|
37
|
+
// }
|
|
38
|
+
// if (!user) {
|
|
39
|
+
// throw new Error('Incorrect storage configuration, missing env variable STORAGE_USER');
|
|
40
|
+
// }
|
|
41
|
+
// if (!password) {
|
|
42
|
+
// throw new Error('Incorrect storage configuration, missing env variable STORAGE_PASSWORD');
|
|
43
|
+
// }
|
|
31
44
|
if (!engine) {
|
|
32
45
|
throw new Error('Incorrect storage configuration, missing env variable STORAGE_ENGINE');
|
|
33
46
|
}
|
|
@@ -35,7 +48,30 @@ function getDbConnectionParams() {
|
|
|
35
48
|
return null;
|
|
36
49
|
}
|
|
37
50
|
|
|
38
|
-
|
|
51
|
+
const res = {
|
|
52
|
+
server,
|
|
53
|
+
port,
|
|
54
|
+
user,
|
|
55
|
+
password,
|
|
56
|
+
database,
|
|
57
|
+
engine,
|
|
58
|
+
serviceName,
|
|
59
|
+
socketPath,
|
|
60
|
+
databaseUrl,
|
|
61
|
+
useDatabaseUrl,
|
|
62
|
+
authType,
|
|
63
|
+
useSsl,
|
|
64
|
+
sslCaFile,
|
|
65
|
+
sslCertFile,
|
|
66
|
+
sslCertFilePassword,
|
|
67
|
+
sslKeyFile,
|
|
68
|
+
sslRejectUnauthorized,
|
|
69
|
+
trustServerCertificate,
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
...res,
|
|
73
|
+
ssl: await extractConnectionSslParams(res),
|
|
74
|
+
};
|
|
39
75
|
}
|
|
40
76
|
|
|
41
77
|
let storageConnection = null;
|
|
@@ -47,7 +83,7 @@ async function getStorageConnectionCore() {
|
|
|
47
83
|
return [storageConnection, storageDriver];
|
|
48
84
|
}
|
|
49
85
|
|
|
50
|
-
const dbConnectionParams = getDbConnectionParams();
|
|
86
|
+
const dbConnectionParams = await getDbConnectionParams();
|
|
51
87
|
|
|
52
88
|
if (!dbConnectionParams) {
|
|
53
89
|
return [null, null];
|
|
@@ -125,6 +161,10 @@ async function storageSelectFmt(sql, ...params) {
|
|
|
125
161
|
return resp.rows;
|
|
126
162
|
}
|
|
127
163
|
|
|
164
|
+
async function storageSqlCommandFmt(sql, ...params) {
|
|
165
|
+
await storageSelectFmt(sql, ...params);
|
|
166
|
+
}
|
|
167
|
+
|
|
128
168
|
async function storageReadUserRolePermissions(userId) {
|
|
129
169
|
const resp = await storageSelectFmt(
|
|
130
170
|
`
|
|
@@ -213,4 +253,5 @@ module.exports = {
|
|
|
213
253
|
storageReadConfig,
|
|
214
254
|
storageWriteConfig,
|
|
215
255
|
getStorageConnectionError,
|
|
256
|
+
storageSqlCommandFmt,
|
|
216
257
|
};
|
package/src/currentVersion.js
CHANGED
package/src/main.js
CHANGED
|
@@ -78,6 +78,8 @@ function start() {
|
|
|
78
78
|
app.use(getExpressPath('/'), express.static('/home/dbgate-docker/public'));
|
|
79
79
|
} else if (platformInfo.isAwsUbuntuLayout) {
|
|
80
80
|
app.use(getExpressPath('/'), express.static('/home/ubuntu/build/public'));
|
|
81
|
+
} else if (platformInfo.isAzureUbuntuLayout) {
|
|
82
|
+
app.use(getExpressPath('/'), express.static('/home/azureuser/build/public'));
|
|
81
83
|
} else if (processArgs.runE2eTests) {
|
|
82
84
|
app.use(getExpressPath('/'), express.static(path.resolve('packer/build/public')));
|
|
83
85
|
} else if (platformInfo.isNpmDist) {
|
|
@@ -140,6 +142,10 @@ function start() {
|
|
|
140
142
|
const port = process.env.PORT || 3000;
|
|
141
143
|
logger.info(`DbGate API listening on port ${port} (AWS AMI build)`);
|
|
142
144
|
server.listen(port);
|
|
145
|
+
} else if (platformInfo.isAzureUbuntuLayout) {
|
|
146
|
+
const port = process.env.PORT || 3000;
|
|
147
|
+
logger.info(`DbGate API listening on port ${port} (Azure VM build)`);
|
|
148
|
+
server.listen(port);
|
|
143
149
|
} else if (platformInfo.isNpmDist) {
|
|
144
150
|
getPort({
|
|
145
151
|
port: parseInt(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const childProcessChecker = require('../utility/childProcessChecker');
|
|
2
2
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
3
|
-
const connectUtility = require('../utility/connectUtility');
|
|
3
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
4
4
|
const { handleProcessCommunication } = require('../utility/processComm');
|
|
5
5
|
const { pickSafeConnectionInfo } = require('../utility/crypting');
|
|
6
6
|
const _ = require('lodash');
|
|
@@ -11,7 +11,7 @@ const {
|
|
|
11
11
|
extractErrorLogData,
|
|
12
12
|
} = require('dbgate-tools');
|
|
13
13
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
14
|
-
const connectUtility = require('../utility/connectUtility');
|
|
14
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
15
15
|
const { handleProcessCommunication } = require('../utility/processComm');
|
|
16
16
|
const { SqlGenerator } = require('dbgate-tools');
|
|
17
17
|
const generateDeploySql = require('../shell/generateDeploySql');
|
|
@@ -213,13 +213,12 @@ async function handleRunOperation({ msgid, operation, useTransaction }, skipRead
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
async function handleQueryData({ msgid, sql }, skipReadonlyCheck = false) {
|
|
216
|
+
async function handleQueryData({ msgid, sql, range }, skipReadonlyCheck = false) {
|
|
217
217
|
await waitConnected();
|
|
218
218
|
const driver = requireEngineDriver(storedConnection);
|
|
219
219
|
try {
|
|
220
220
|
if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
|
|
221
|
-
|
|
222
|
-
const res = await driver.query(dbhan, sql);
|
|
221
|
+
const res = await driver.query(dbhan, sql, { range });
|
|
223
222
|
process.send({ msgtype: 'response', msgid, ...res });
|
|
224
223
|
} catch (err) {
|
|
225
224
|
process.send({
|
|
@@ -234,7 +233,7 @@ async function handleSqlSelect({ msgid, select }) {
|
|
|
234
233
|
const driver = requireEngineDriver(storedConnection);
|
|
235
234
|
const dmp = driver.createDumper();
|
|
236
235
|
dumpSqlSelect(dmp, select);
|
|
237
|
-
return handleQueryData({ msgid, sql: dmp.s }, true);
|
|
236
|
+
return handleQueryData({ msgid, sql: dmp.s, range: select.range }, true);
|
|
238
237
|
}
|
|
239
238
|
|
|
240
239
|
async function handleDriverDataCore(msgid, callMethod, { logName }) {
|
|
@@ -291,10 +290,14 @@ async function handleLoadKeyTableRange({ msgid, key, cursor, count }) {
|
|
|
291
290
|
});
|
|
292
291
|
}
|
|
293
292
|
|
|
294
|
-
async function handleLoadFieldValues({ msgid, schemaName, pureName, field, search }) {
|
|
295
|
-
return handleDriverDataCore(
|
|
296
|
-
|
|
297
|
-
|
|
293
|
+
async function handleLoadFieldValues({ msgid, schemaName, pureName, field, search, dataType }) {
|
|
294
|
+
return handleDriverDataCore(
|
|
295
|
+
msgid,
|
|
296
|
+
driver => driver.loadFieldValues(dbhan, { schemaName, pureName }, field, search, dataType),
|
|
297
|
+
{
|
|
298
|
+
logName: 'loadFieldValues',
|
|
299
|
+
}
|
|
300
|
+
);
|
|
298
301
|
}
|
|
299
302
|
|
|
300
303
|
function ensureExecuteCustomScript(driver) {
|
|
@@ -336,6 +339,7 @@ async function handleSqlPreview({ msgid, objects, options }) {
|
|
|
336
339
|
}, 500);
|
|
337
340
|
}
|
|
338
341
|
} catch (err) {
|
|
342
|
+
console.error(err);
|
|
339
343
|
process.send({
|
|
340
344
|
msgtype: 'response',
|
|
341
345
|
msgid,
|
|
@@ -423,7 +427,11 @@ function start() {
|
|
|
423
427
|
await handleMessage(message);
|
|
424
428
|
} catch (err) {
|
|
425
429
|
logger.error(extractErrorLogData(err), 'Error in DB connection');
|
|
426
|
-
process.send({
|
|
430
|
+
process.send({
|
|
431
|
+
msgtype: 'error',
|
|
432
|
+
error: extractErrorMessage(err, 'Error processing message'),
|
|
433
|
+
msgid: message?.msgid,
|
|
434
|
+
});
|
|
427
435
|
}
|
|
428
436
|
});
|
|
429
437
|
}
|
|
@@ -2,7 +2,7 @@ const stableStringify = require('json-stable-stringify');
|
|
|
2
2
|
const { extractBoolSettingsValue, extractIntSettingsValue, getLogger, extractErrorLogData } = require('dbgate-tools');
|
|
3
3
|
const childProcessChecker = require('../utility/childProcessChecker');
|
|
4
4
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
5
|
-
const connectUtility = require('../utility/connectUtility');
|
|
5
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
6
6
|
const { handleProcessCommunication } = require('../utility/processComm');
|
|
7
7
|
const logger = getLogger('srvconnProcess');
|
|
8
8
|
|
|
@@ -8,7 +8,7 @@ const { splitQuery } = require('dbgate-query-splitter');
|
|
|
8
8
|
const { jsldir } = require('../utility/directories');
|
|
9
9
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
10
10
|
const { decryptConnection } = require('../utility/crypting');
|
|
11
|
-
const connectUtility = require('../utility/connectUtility');
|
|
11
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
12
12
|
const { handleProcessCommunication } = require('../utility/processComm');
|
|
13
13
|
const { getLogger, extractIntSettingsValue, extractBoolSettingsValue } = require('dbgate-tools');
|
|
14
14
|
|
|
@@ -2,7 +2,7 @@ const stream = require('stream');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { quoteFullName, fullNameToString, getLogger } = require('dbgate-tools');
|
|
4
4
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
5
|
-
const connectUtility = require('../utility/connectUtility');
|
|
5
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
6
6
|
const logger = getLogger('dataDuplicator');
|
|
7
7
|
const { DataDuplicator } = require('dbgate-datalib');
|
|
8
8
|
const copyStream = require('./copyStream');
|
package/src/shell/deployDb.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const generateDeploySql = require('./generateDeploySql');
|
|
2
2
|
const executeQuery = require('./executeQuery');
|
|
3
3
|
const { ScriptDrivedDeployer } = require('dbgate-datalib');
|
|
4
|
-
const connectUtility = require('../utility/connectUtility');
|
|
4
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
5
5
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
6
6
|
const loadModelFolder = require('../utility/loadModelFolder');
|
|
7
7
|
const crypto = require('crypto');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const executeQuery = require('./executeQuery');
|
|
2
2
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
3
|
-
const connectUtility = require('../utility/connectUtility');
|
|
3
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
4
4
|
const { getLogger, extendDatabaseInfo } = require('dbgate-tools');
|
|
5
5
|
|
|
6
6
|
const logger = getLogger('dropAllDbObjects');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
2
|
-
const connectUtility = require('../utility/connectUtility');
|
|
2
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
3
3
|
const { getLogger } = require('dbgate-tools');
|
|
4
4
|
|
|
5
5
|
const logger = getLogger('dumpDb');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fs = require('fs-extra');
|
|
2
2
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
3
|
-
const connectUtility = require('../utility/connectUtility');
|
|
3
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
4
4
|
const { getLogger, getLimitedQuery } = require('dbgate-tools');
|
|
5
5
|
|
|
6
6
|
const logger = getLogger('execQuery');
|
|
@@ -13,7 +13,7 @@ const {
|
|
|
13
13
|
} = require('dbgate-tools');
|
|
14
14
|
const importDbModel = require('../utility/importDbModel');
|
|
15
15
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
16
|
-
const connectUtility = require('../utility/connectUtility');
|
|
16
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Generates query for deploying model into database
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
3
|
-
const connectUtility = require('../utility/connectUtility');
|
|
3
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
4
4
|
const { splitQueryStream } = require('dbgate-query-splitter/lib/splitQueryStream');
|
|
5
5
|
const download = require('./download');
|
|
6
6
|
const stream = require('stream');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
2
|
-
const connectUtility = require('../utility/connectUtility');
|
|
2
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
3
3
|
const { getLogger } = require('dbgate-tools');
|
|
4
4
|
const exportDbModel = require('../utility/exportDbModel');
|
|
5
5
|
|
package/src/shell/queryReader.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
2
|
-
const connectUtility = require('../utility/connectUtility');
|
|
2
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
3
3
|
const { getLogger } = require('dbgate-tools');
|
|
4
4
|
const logger = getLogger('queryReader');
|
|
5
5
|
|
package/src/shell/tableReader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { quoteFullName, fullNameToString, getLogger } = require('dbgate-tools');
|
|
2
2
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
3
|
-
const connectUtility = require('../utility/connectUtility');
|
|
3
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
4
4
|
const logger = getLogger('tableReader');
|
|
5
5
|
|
|
6
6
|
/**
|
package/src/shell/tableWriter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { fullNameToString, getLogger } = require('dbgate-tools');
|
|
2
2
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
3
|
-
const connectUtility = require('../utility/connectUtility');
|
|
3
|
+
const { connectUtility } = require('../utility/connectUtility');
|
|
4
4
|
const logger = getLogger('tableWriter');
|
|
5
5
|
|
|
6
6
|
/**
|
package/src/utility/authProxy.js
CHANGED
|
@@ -2,11 +2,24 @@ const axios = require('axios');
|
|
|
2
2
|
const { Signer } = require('@aws-sdk/rds-signer');
|
|
3
3
|
const jwt = require('jsonwebtoken');
|
|
4
4
|
const { getLogger, extractErrorLogData } = require('dbgate-tools');
|
|
5
|
+
const stableStringify = require('json-stable-stringify');
|
|
6
|
+
const crypto = require('crypto');
|
|
7
|
+
const _ = require('lodash');
|
|
8
|
+
const processArgs = require('./processArgs');
|
|
5
9
|
|
|
6
10
|
const logger = getLogger('authProxy');
|
|
7
11
|
|
|
8
|
-
const AUTH_PROXY_URL = process.env.
|
|
9
|
-
|
|
12
|
+
const AUTH_PROXY_URL = process.env.LOCAL_AUTH_PROXY
|
|
13
|
+
? 'http://localhost:3109'
|
|
14
|
+
: process.env.DEVWEB || process.env.DEVMODE
|
|
15
|
+
? 'https://auth-proxy.dbgate.udolni.net'
|
|
16
|
+
: 'https://auth.dbgate.eu';
|
|
17
|
+
|
|
18
|
+
const AI_GATEWAY_URL = process.env.LOCAL_AI_GATEWAY
|
|
19
|
+
? 'http://localhost:3110'
|
|
20
|
+
: process.env.DEVWEB || process.env.DEVMODE
|
|
21
|
+
? 'https://aigw.dbgate.udolni.net'
|
|
22
|
+
: 'https://aigw.dbgate.io';
|
|
10
23
|
|
|
11
24
|
let licenseKey = null;
|
|
12
25
|
|
|
@@ -18,6 +31,16 @@ function isAuthProxySupported() {
|
|
|
18
31
|
return true;
|
|
19
32
|
}
|
|
20
33
|
|
|
34
|
+
function getAxiosParamsWithLicense() {
|
|
35
|
+
return {
|
|
36
|
+
headers: {
|
|
37
|
+
'Content-Type': 'application/json',
|
|
38
|
+
Authorization: `Bearer ${licenseKey ?? process.env.DBGATE_LICENSE}`,
|
|
39
|
+
'x-api-key': processArgs.runE2eTests ? 'bcf6e1a0-5763-4060-9391-18fda005722d' : null,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
21
44
|
async function authProxyGetRedirectUrl({ client, type, state, redirectUri }) {
|
|
22
45
|
const respSession = await axios.default.post(
|
|
23
46
|
`${AUTH_PROXY_URL}/create-session`,
|
|
@@ -25,12 +48,7 @@ async function authProxyGetRedirectUrl({ client, type, state, redirectUri }) {
|
|
|
25
48
|
client,
|
|
26
49
|
type,
|
|
27
50
|
},
|
|
28
|
-
|
|
29
|
-
headers: {
|
|
30
|
-
'Content-Type': 'application/json',
|
|
31
|
-
Authorization: `Bearer ${licenseKey ?? process.env.DBGATE_LICENSE}`,
|
|
32
|
-
},
|
|
33
|
-
}
|
|
51
|
+
getAxiosParamsWithLicense()
|
|
34
52
|
);
|
|
35
53
|
|
|
36
54
|
const { sid } = respSession.data;
|
|
@@ -55,12 +73,7 @@ async function authProxyGetTokenFromCode({ sid, code }) {
|
|
|
55
73
|
sid,
|
|
56
74
|
code,
|
|
57
75
|
},
|
|
58
|
-
|
|
59
|
-
headers: {
|
|
60
|
-
'Content-Type': 'application/json',
|
|
61
|
-
Authorization: `Bearer ${licenseKey ?? process.env.DBGATE_LICENSE}`,
|
|
62
|
-
},
|
|
63
|
-
}
|
|
76
|
+
getAxiosParamsWithLicense()
|
|
64
77
|
);
|
|
65
78
|
return respToken.data.token;
|
|
66
79
|
} catch (err) {
|
|
@@ -82,12 +95,7 @@ function startTokenChecking(sid, callback) {
|
|
|
82
95
|
{
|
|
83
96
|
sid,
|
|
84
97
|
},
|
|
85
|
-
|
|
86
|
-
headers: {
|
|
87
|
-
'Content-Type': 'application/json',
|
|
88
|
-
Authorization: `Bearer ${licenseKey ?? process.env.DBGATE_LICENSE}`,
|
|
89
|
-
},
|
|
90
|
-
}
|
|
98
|
+
getAxiosParamsWithLicense()
|
|
91
99
|
);
|
|
92
100
|
|
|
93
101
|
if (resp.data.status == 'ok') {
|
|
@@ -156,6 +164,110 @@ async function obtainRefreshedLicense() {
|
|
|
156
164
|
}
|
|
157
165
|
}
|
|
158
166
|
|
|
167
|
+
/**
|
|
168
|
+
* @param {import('dbgate-types').DatabaseInfo} structure
|
|
169
|
+
* @returns {import('dbgate-types').DatabaseInfoTiny}
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
function extractTinyStructure(structure) {
|
|
173
|
+
return {
|
|
174
|
+
t: _.sortBy(structure.tables, x => x.pureName).map(table => ({
|
|
175
|
+
n: table.pureName,
|
|
176
|
+
o: table.objectComment,
|
|
177
|
+
c: table.columns.map(column => ({ n: column.columnName, t: column.dataType })),
|
|
178
|
+
p: table.primaryKey
|
|
179
|
+
? {
|
|
180
|
+
c: table.primaryKey?.columns?.map(column => ({ n: column.columnName })),
|
|
181
|
+
}
|
|
182
|
+
: undefined,
|
|
183
|
+
f: _.sortBy(table.foreignKeys, x => x.constraintName).map(fk => ({
|
|
184
|
+
r: fk.refTableName,
|
|
185
|
+
c: fk.columns.map(column => ({ n: column.columnName, r: column.refColumnName })),
|
|
186
|
+
})),
|
|
187
|
+
})),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function getSha256Hash(data) {
|
|
192
|
+
return crypto
|
|
193
|
+
.createHash('sha256') // volba hashovací funkce
|
|
194
|
+
.update(data, 'utf8') // aktualizace hashe o data (ve formátu UTF-8)
|
|
195
|
+
.digest('hex'); // získáme výsledek v hexadecimální reprezentaci
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function findModelOnProxy(hash) {
|
|
199
|
+
const resp = await axios.default.post(
|
|
200
|
+
`${AI_GATEWAY_URL}/find-db-model`,
|
|
201
|
+
{
|
|
202
|
+
hash,
|
|
203
|
+
},
|
|
204
|
+
getAxiosParamsWithLicense()
|
|
205
|
+
);
|
|
206
|
+
return resp.data.status == 'ok';
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function callTextToSqlApi(text, structure, dialect) {
|
|
210
|
+
const tinyStructure = extractTinyStructure(structure);
|
|
211
|
+
const json = stableStringify(tinyStructure);
|
|
212
|
+
const modelHash = getSha256Hash(json);
|
|
213
|
+
const isModelOnProxy = await findModelOnProxy(modelHash);
|
|
214
|
+
|
|
215
|
+
const resp = await axios.default.post(
|
|
216
|
+
`${AI_GATEWAY_URL}/text-to-sql`,
|
|
217
|
+
{
|
|
218
|
+
text,
|
|
219
|
+
modelHash,
|
|
220
|
+
model: isModelOnProxy ? null : tinyStructure,
|
|
221
|
+
dialect,
|
|
222
|
+
},
|
|
223
|
+
getAxiosParamsWithLicense()
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
return resp.data;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function callCompleteOnCursorApi(text, structure, dialect, line) {
|
|
230
|
+
const tinyStructure = extractTinyStructure(structure);
|
|
231
|
+
const json = stableStringify(tinyStructure);
|
|
232
|
+
const modelHash = getSha256Hash(json);
|
|
233
|
+
const isModelOnProxy = await findModelOnProxy(modelHash);
|
|
234
|
+
|
|
235
|
+
const resp = await axios.default.post(
|
|
236
|
+
`${AI_GATEWAY_URL}/complete-on-cursor`,
|
|
237
|
+
{
|
|
238
|
+
text,
|
|
239
|
+
modelHash,
|
|
240
|
+
model: isModelOnProxy ? null : tinyStructure,
|
|
241
|
+
dialect,
|
|
242
|
+
line,
|
|
243
|
+
},
|
|
244
|
+
getAxiosParamsWithLicense()
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
return resp.data;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
async function callRefactorSqlQueryApi(query, task, structure, dialect) {
|
|
251
|
+
const tinyStructure = extractTinyStructure(structure);
|
|
252
|
+
const json = stableStringify(tinyStructure);
|
|
253
|
+
const modelHash = getSha256Hash(json);
|
|
254
|
+
const isModelOnProxy = await findModelOnProxy(modelHash);
|
|
255
|
+
|
|
256
|
+
const resp = await axios.default.post(
|
|
257
|
+
`${AI_GATEWAY_URL}/refactor-sql-query`,
|
|
258
|
+
{
|
|
259
|
+
query,
|
|
260
|
+
task,
|
|
261
|
+
modelHash,
|
|
262
|
+
model: isModelOnProxy ? null : tinyStructure,
|
|
263
|
+
dialect,
|
|
264
|
+
},
|
|
265
|
+
getAxiosParamsWithLicense()
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
return resp.data;
|
|
269
|
+
}
|
|
270
|
+
|
|
159
271
|
module.exports = {
|
|
160
272
|
isAuthProxySupported,
|
|
161
273
|
authProxyGetRedirectUrl,
|
|
@@ -166,4 +278,7 @@ module.exports = {
|
|
|
166
278
|
supportsAwsIam,
|
|
167
279
|
getAwsIamToken,
|
|
168
280
|
obtainRefreshedLicense,
|
|
281
|
+
callTextToSqlApi,
|
|
282
|
+
callCompleteOnCursorApi,
|
|
283
|
+
callRefactorSqlQueryApi,
|
|
169
284
|
};
|
|
@@ -9,6 +9,7 @@ const { setAuthProxyLicense } = require('./authProxy');
|
|
|
9
9
|
const axios = require('axios');
|
|
10
10
|
const crypto = require('crypto');
|
|
11
11
|
const platformInfo = require('./platformInfo');
|
|
12
|
+
const processArgs = require('./processArgs');
|
|
12
13
|
|
|
13
14
|
const logger = getLogger('checkLicense');
|
|
14
15
|
|
|
@@ -107,6 +108,13 @@ async function getAwsMetadata() {
|
|
|
107
108
|
}
|
|
108
109
|
|
|
109
110
|
function checkLicenseKey(licenseKey) {
|
|
111
|
+
if (processArgs.runE2eTests) {
|
|
112
|
+
return {
|
|
113
|
+
status: 'ok',
|
|
114
|
+
type: 'premium',
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
110
118
|
try {
|
|
111
119
|
const decoded = jwt.verify(licenseKey, publicKey, {
|
|
112
120
|
algorithms: ['RS256'],
|
|
@@ -157,11 +165,11 @@ function checkLicenseKey(licenseKey) {
|
|
|
157
165
|
}
|
|
158
166
|
}
|
|
159
167
|
|
|
160
|
-
let
|
|
161
|
-
let
|
|
162
|
-
function
|
|
163
|
-
if (
|
|
164
|
-
return
|
|
168
|
+
let cloudTokenLoaded = false;
|
|
169
|
+
let cloudTokenHash = null;
|
|
170
|
+
function getCloudToken() {
|
|
171
|
+
if (cloudTokenLoaded) {
|
|
172
|
+
return cloudTokenHash;
|
|
165
173
|
}
|
|
166
174
|
try {
|
|
167
175
|
const token = fs
|
|
@@ -169,18 +177,25 @@ function getAwsToken() {
|
|
|
169
177
|
encoding: 'utf-8',
|
|
170
178
|
})
|
|
171
179
|
.trim();
|
|
172
|
-
|
|
180
|
+
cloudTokenHash = crypto.createHash('md5').update(token).digest('hex');
|
|
173
181
|
} catch (err) {}
|
|
174
|
-
|
|
175
|
-
return
|
|
182
|
+
cloudTokenLoaded = true;
|
|
183
|
+
return cloudTokenHash;
|
|
176
184
|
}
|
|
177
185
|
|
|
178
186
|
async function checkLicense() {
|
|
187
|
+
if (processArgs.runE2eTests) {
|
|
188
|
+
return {
|
|
189
|
+
status: 'ok',
|
|
190
|
+
type: 'premium',
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
179
194
|
if (process.env.DBGATE_LICENSE) {
|
|
180
195
|
return checkLicenseKey(process.env.DBGATE_LICENSE);
|
|
181
196
|
}
|
|
182
197
|
|
|
183
|
-
if (platformInfo.isAwsUbuntuLayout &&
|
|
198
|
+
if (platformInfo.isAwsUbuntuLayout && getCloudToken() == 'b93c7491890460063003a02de06ec84a') {
|
|
184
199
|
const metadata = await getAwsMetadata();
|
|
185
200
|
if (metadata?.amiId) {
|
|
186
201
|
return {
|
|
@@ -190,6 +205,13 @@ async function checkLicense() {
|
|
|
190
205
|
}
|
|
191
206
|
}
|
|
192
207
|
|
|
208
|
+
if (platformInfo.isAzureUbuntuLayout && getCloudToken() == 'b93c7491890460063003a02de06ec84a') {
|
|
209
|
+
return {
|
|
210
|
+
status: 'ok',
|
|
211
|
+
type: 'premium',
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
193
215
|
if (process.env.STORAGE_DATABASE) {
|
|
194
216
|
const licenseConfig = await storageReadConfig('license');
|
|
195
217
|
const key = licenseConfig?.licenseKey;
|
|
@@ -47,50 +47,32 @@ async function loadConnection(driver, storedConnection, connectionMode) {
|
|
|
47
47
|
return storedConnection;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
async function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const connection = {
|
|
54
|
-
database: connectionLoaded.defaultDatabase,
|
|
55
|
-
...decryptConnection(connectionLoaded),
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
if (!connection.port && driver.defaultPort) connection.port = driver.defaultPort.toString();
|
|
59
|
-
|
|
60
|
-
if (connection.useSshTunnel) {
|
|
61
|
-
const tunnel = await getSshTunnelProxy(connection);
|
|
62
|
-
if (tunnel.state == 'error') {
|
|
63
|
-
throw new Error(tunnel.message);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
connection.server = tunnel.localHost;
|
|
67
|
-
connection.port = tunnel.localPort;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// SSL functionality - copied from https://github.com/beekeeper-studio/beekeeper-studio
|
|
50
|
+
async function extractConnectionSslParams(connection) {
|
|
51
|
+
/** @type {any} */
|
|
52
|
+
let ssl = undefined;
|
|
71
53
|
if (connection.useSsl) {
|
|
72
|
-
|
|
54
|
+
ssl = {};
|
|
73
55
|
|
|
74
56
|
if (connection.sslCaFile) {
|
|
75
|
-
|
|
76
|
-
|
|
57
|
+
ssl.ca = await fs.readFile(connection.sslCaFile);
|
|
58
|
+
ssl.sslCaFile = connection.sslCaFile;
|
|
77
59
|
}
|
|
78
60
|
|
|
79
61
|
if (connection.sslCertFile) {
|
|
80
|
-
|
|
81
|
-
|
|
62
|
+
ssl.cert = await fs.readFile(connection.sslCertFile);
|
|
63
|
+
ssl.sslCertFile = connection.sslCertFile;
|
|
82
64
|
}
|
|
83
65
|
|
|
84
66
|
if (connection.sslKeyFile) {
|
|
85
|
-
|
|
86
|
-
|
|
67
|
+
ssl.key = await fs.readFile(connection.sslKeyFile);
|
|
68
|
+
ssl.sslKeyFile = connection.sslKeyFile;
|
|
87
69
|
}
|
|
88
70
|
|
|
89
71
|
if (connection.sslCertFilePassword) {
|
|
90
|
-
|
|
72
|
+
ssl.password = connection.sslCertFilePassword;
|
|
91
73
|
}
|
|
92
74
|
|
|
93
|
-
if (!
|
|
75
|
+
if (!ssl.key && !ssl.ca && !ssl.cert) {
|
|
94
76
|
// TODO: provide this as an option in settings
|
|
95
77
|
// or per-connection as 'reject self-signed certs'
|
|
96
78
|
// How it works:
|
|
@@ -98,14 +80,41 @@ async function connectUtility(driver, storedConnection, connectionMode, addition
|
|
|
98
80
|
// if true, has to be from a public CA
|
|
99
81
|
// Heroku certs are self-signed.
|
|
100
82
|
// if you provide ca/cert/key files, it overrides this
|
|
101
|
-
|
|
83
|
+
ssl.rejectUnauthorized = false;
|
|
102
84
|
} else {
|
|
103
|
-
|
|
85
|
+
ssl.rejectUnauthorized = connection.sslRejectUnauthorized;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return ssl;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function connectUtility(driver, storedConnection, connectionMode, additionalOptions = null) {
|
|
92
|
+
const connectionLoaded = await loadConnection(driver, storedConnection, connectionMode);
|
|
93
|
+
|
|
94
|
+
const connection = {
|
|
95
|
+
database: connectionLoaded.defaultDatabase,
|
|
96
|
+
...decryptConnection(connectionLoaded),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
if (!connection.port && driver.defaultPort) connection.port = driver.defaultPort.toString();
|
|
100
|
+
|
|
101
|
+
if (connection.useSshTunnel) {
|
|
102
|
+
const tunnel = await getSshTunnelProxy(connection);
|
|
103
|
+
if (tunnel.state == 'error') {
|
|
104
|
+
throw new Error(tunnel.message);
|
|
104
105
|
}
|
|
106
|
+
|
|
107
|
+
connection.server = tunnel.localHost;
|
|
108
|
+
connection.port = tunnel.localPort;
|
|
105
109
|
}
|
|
106
110
|
|
|
111
|
+
connection.ssl = await extractConnectionSslParams(connection);
|
|
112
|
+
|
|
107
113
|
const conn = await driver.connect({ ...connection, ...additionalOptions });
|
|
108
114
|
return conn;
|
|
109
115
|
}
|
|
110
116
|
|
|
111
|
-
module.exports =
|
|
117
|
+
module.exports = {
|
|
118
|
+
extractConnectionSslParams,
|
|
119
|
+
connectUtility,
|
|
120
|
+
};
|
|
@@ -58,9 +58,11 @@ const jsldir = dirFunc('jsl', true);
|
|
|
58
58
|
const rundir = dirFunc('run', true);
|
|
59
59
|
const uploadsdir = dirFunc('uploads', true);
|
|
60
60
|
const pluginsdir = dirFunc('plugins');
|
|
61
|
-
const archivedir =
|
|
61
|
+
const archivedir = processArgs.runE2eTests
|
|
62
|
+
? dirFunc('archive-e2etests', false, ['default'])
|
|
63
|
+
: dirFunc('archive', false, ['default']);
|
|
62
64
|
const appdir = dirFunc('apps');
|
|
63
|
-
const filesdir = dirFunc('files');
|
|
65
|
+
const filesdir = processArgs.runE2eTests ? dirFunc('files-e2etests') : dirFunc('files');
|
|
64
66
|
const logsdir = dirFunc('logs', 3600 * 24 * 7);
|
|
65
67
|
|
|
66
68
|
function packagedPluginsDir() {
|
|
@@ -80,6 +82,9 @@ function packagedPluginsDir() {
|
|
|
80
82
|
if (platformInfo.isAwsUbuntuLayout) {
|
|
81
83
|
return '/home/ubuntu/build/plugins';
|
|
82
84
|
}
|
|
85
|
+
if (platformInfo.isAzureUbuntuLayout) {
|
|
86
|
+
return '/home/azureuser/build/plugins';
|
|
87
|
+
}
|
|
83
88
|
if (platformInfo.isNpmDist) {
|
|
84
89
|
// node_modules
|
|
85
90
|
return global['PLUGINS_DIR'];
|
|
@@ -73,6 +73,7 @@ async function getPublicHardwareFingerprint() {
|
|
|
73
73
|
region: fingerprint.region,
|
|
74
74
|
isDocker: platformInfo.isDocker,
|
|
75
75
|
isAwsUbuntuLayout: platformInfo.isAwsUbuntuLayout,
|
|
76
|
+
isAzureUbuntuLayout: platformInfo.isAzureUbuntuLayout,
|
|
76
77
|
isElectron: platformInfo.isElectron,
|
|
77
78
|
},
|
|
78
79
|
};
|
|
@@ -15,6 +15,7 @@ const isNpmDist = !!global['IS_NPM_DIST'];
|
|
|
15
15
|
const isDbModel = !!global['IS_DB_MODEL'];
|
|
16
16
|
const isForkedApi = processArgs.isForkedApi;
|
|
17
17
|
const isAwsUbuntuLayout = fs.existsSync('/home/ubuntu/build/public');
|
|
18
|
+
const isAzureUbuntuLayout = fs.existsSync('/home/azureuser/build/public');
|
|
18
19
|
|
|
19
20
|
// function moduleAvailable(name) {
|
|
20
21
|
// try {
|
|
@@ -57,6 +58,7 @@ const platformInfo = {
|
|
|
57
58
|
allowConnectionFromEnvVariables: !!isDbModel,
|
|
58
59
|
defaultKeyfile: path.join(os.homedir(), '.ssh/id_rsa'),
|
|
59
60
|
isAwsUbuntuLayout,
|
|
61
|
+
isAzureUbuntuLayout,
|
|
60
62
|
};
|
|
61
63
|
|
|
62
64
|
module.exports = platformInfo;
|
|
@@ -86,7 +86,7 @@ module.exports = function useController(app, electron, route, controller) {
|
|
|
86
86
|
detail: err.detail,
|
|
87
87
|
});
|
|
88
88
|
} else {
|
|
89
|
-
res.status(500).json({ apiErrorMessage: err.message });
|
|
89
|
+
res.status(500).json({ apiErrorMessage: (_.isString(err) ? err : err.message) ?? 'Unknown error' });
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
});
|