dbgate-api 6.5.4 → 6.5.5
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 +2 -2
- package/src/controllers/auth.js +51 -7
- package/src/controllers/cloud.js +18 -0
- package/src/controllers/config.js +16 -2
- package/src/controllers/connections.js +5 -5
- package/src/controllers/databaseConnections.js +102 -8
- package/src/controllers/files.js +2 -2
- package/src/controllers/runners.js +24 -1
- package/src/controllers/serverConnections.js +12 -0
- package/src/controllers/sessions.js +14 -1
- package/src/controllers/storage.js +7 -0
- package/src/currentVersion.js +2 -2
- package/src/shell/deployDb.js +1 -1
- package/src/shell/generateDeploySql.js +1 -1
- package/src/shell/importDbFromFolder.js +2 -5
- package/src/storageModel.js +304 -62
- package/src/utility/auditlog.js +9 -0
- package/src/utility/cloudIntf.js +33 -2
- package/src/utility/getChartExport.js +11 -3
- package/src/utility/getMapExport.js +1 -1
- package/src/utility/loginchecker.js +15 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbgate-api",
|
|
3
3
|
"main": "src/index.js",
|
|
4
|
-
"version": "6.5.
|
|
4
|
+
"version": "6.5.5",
|
|
5
5
|
"homepage": "https://dbgate.org/",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"compare-versions": "^3.6.0",
|
|
31
31
|
"cors": "^2.8.5",
|
|
32
32
|
"cross-env": "^6.0.3",
|
|
33
|
-
"dbgate-datalib": "^6.5.
|
|
33
|
+
"dbgate-datalib": "^6.5.5",
|
|
34
34
|
"dbgate-query-splitter": "^4.11.5",
|
|
35
|
-
"dbgate-sqltree": "^6.5.
|
|
36
|
-
"dbgate-tools": "^6.5.
|
|
35
|
+
"dbgate-sqltree": "^6.5.5",
|
|
36
|
+
"dbgate-tools": "^6.5.5",
|
|
37
37
|
"debug": "^4.3.4",
|
|
38
38
|
"diff": "^5.0.0",
|
|
39
39
|
"diff2html": "^3.4.13",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"@types/fs-extra": "^9.0.11",
|
|
87
87
|
"@types/lodash": "^4.14.149",
|
|
88
|
-
"dbgate-types": "^6.5.
|
|
88
|
+
"dbgate-types": "^6.5.5",
|
|
89
89
|
"env-cmd": "^10.1.0",
|
|
90
90
|
"jsdoc-to-markdown": "^9.0.5",
|
|
91
91
|
"node-loader": "^1.0.2",
|
package/src/auth/authProvider.js
CHANGED
|
@@ -11,7 +11,7 @@ const logger = getLogger('authProvider');
|
|
|
11
11
|
class AuthProviderBase {
|
|
12
12
|
amoid = 'none';
|
|
13
13
|
|
|
14
|
-
async login(login, password, options = undefined) {
|
|
14
|
+
async login(login, password, options = undefined, req = undefined) {
|
|
15
15
|
return {
|
|
16
16
|
accessToken: jwt.sign(
|
|
17
17
|
{
|
|
@@ -23,7 +23,7 @@ class AuthProviderBase {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
oauthToken(params) {
|
|
26
|
+
oauthToken(params, req) {
|
|
27
27
|
return {};
|
|
28
28
|
}
|
|
29
29
|
|
package/src/controllers/auth.js
CHANGED
|
@@ -13,8 +13,15 @@ const {
|
|
|
13
13
|
} = require('../auth/authProvider');
|
|
14
14
|
const storage = require('./storage');
|
|
15
15
|
const { decryptPasswordString } = require('../utility/crypting');
|
|
16
|
-
const {
|
|
16
|
+
const {
|
|
17
|
+
createDbGateIdentitySession,
|
|
18
|
+
startCloudTokenChecking,
|
|
19
|
+
readCloudTokenHolder,
|
|
20
|
+
readCloudTestTokenHolder,
|
|
21
|
+
} = require('../utility/cloudIntf');
|
|
17
22
|
const socket = require('../utility/socket');
|
|
23
|
+
const { sendToAuditLog } = require('../utility/auditlog');
|
|
24
|
+
const { isLoginLicensed, LOGIN_LIMIT_ERROR } = require('../utility/loginchecker');
|
|
18
25
|
|
|
19
26
|
const logger = getLogger('auth');
|
|
20
27
|
|
|
@@ -72,6 +79,8 @@ function authMiddleware(req, res, next) {
|
|
|
72
79
|
try {
|
|
73
80
|
const decoded = jwt.verify(token, getTokenSecret());
|
|
74
81
|
req.user = decoded;
|
|
82
|
+
storage.markUserAsActive(decoded.licenseUid);
|
|
83
|
+
|
|
75
84
|
return next();
|
|
76
85
|
} catch (err) {
|
|
77
86
|
if (skipAuth) {
|
|
@@ -87,12 +96,12 @@ function authMiddleware(req, res, next) {
|
|
|
87
96
|
|
|
88
97
|
module.exports = {
|
|
89
98
|
oauthToken_meta: true,
|
|
90
|
-
async oauthToken(params) {
|
|
99
|
+
async oauthToken(params, req) {
|
|
91
100
|
const { amoid } = params;
|
|
92
|
-
return getAuthProviderById(amoid).oauthToken(params);
|
|
101
|
+
return getAuthProviderById(amoid).oauthToken(params, req);
|
|
93
102
|
},
|
|
94
103
|
login_meta: true,
|
|
95
|
-
async login(params) {
|
|
104
|
+
async login(params, req) {
|
|
96
105
|
const { amoid, login, password, isAdminPage } = params;
|
|
97
106
|
|
|
98
107
|
if (isAdminPage) {
|
|
@@ -102,12 +111,26 @@ module.exports = {
|
|
|
102
111
|
adminPassword = decryptPasswordString(adminConfig?.adminPassword);
|
|
103
112
|
}
|
|
104
113
|
if (adminPassword && adminPassword == password) {
|
|
114
|
+
if (!(await isLoginLicensed(req, `superadmin`))) {
|
|
115
|
+
return { error: LOGIN_LIMIT_ERROR };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
sendToAuditLog(req, {
|
|
119
|
+
category: 'auth',
|
|
120
|
+
component: 'AuthController',
|
|
121
|
+
action: 'login',
|
|
122
|
+
event: 'login.admin',
|
|
123
|
+
severity: 'info',
|
|
124
|
+
message: 'Administration login successful',
|
|
125
|
+
});
|
|
126
|
+
|
|
105
127
|
return {
|
|
106
128
|
accessToken: jwt.sign(
|
|
107
129
|
{
|
|
108
130
|
login: 'superadmin',
|
|
109
131
|
permissions: await storage.loadSuperadminPermissions(),
|
|
110
132
|
roleId: -3,
|
|
133
|
+
licenseUid: `superadmin`,
|
|
111
134
|
},
|
|
112
135
|
getTokenSecret(),
|
|
113
136
|
{
|
|
@@ -117,10 +140,19 @@ module.exports = {
|
|
|
117
140
|
};
|
|
118
141
|
}
|
|
119
142
|
|
|
143
|
+
sendToAuditLog(req, {
|
|
144
|
+
category: 'auth',
|
|
145
|
+
component: 'AuthController',
|
|
146
|
+
action: 'loginFail',
|
|
147
|
+
event: 'login.adminFailed',
|
|
148
|
+
severity: 'warn',
|
|
149
|
+
message: 'Administraton login failed',
|
|
150
|
+
});
|
|
151
|
+
|
|
120
152
|
return { error: 'Login failed' };
|
|
121
153
|
}
|
|
122
154
|
|
|
123
|
-
return getAuthProviderById(amoid).login(login, password);
|
|
155
|
+
return getAuthProviderById(amoid).login(login, password, undefined, req);
|
|
124
156
|
},
|
|
125
157
|
|
|
126
158
|
getProviders_meta: true,
|
|
@@ -138,8 +170,8 @@ module.exports = {
|
|
|
138
170
|
},
|
|
139
171
|
|
|
140
172
|
createCloudLoginSession_meta: true,
|
|
141
|
-
async createCloudLoginSession({ client }) {
|
|
142
|
-
const res = await createDbGateIdentitySession(client);
|
|
173
|
+
async createCloudLoginSession({ client, redirectUri }) {
|
|
174
|
+
const res = await createDbGateIdentitySession(client, redirectUri);
|
|
143
175
|
startCloudTokenChecking(res.sid, tokenHolder => {
|
|
144
176
|
socket.emit('got-cloud-token', tokenHolder);
|
|
145
177
|
socket.emitChanged('cloud-content-changed');
|
|
@@ -148,5 +180,17 @@ module.exports = {
|
|
|
148
180
|
return res;
|
|
149
181
|
},
|
|
150
182
|
|
|
183
|
+
cloudLoginRedirected_meta: true,
|
|
184
|
+
async cloudLoginRedirected({ sid }) {
|
|
185
|
+
const tokenHolder = await readCloudTokenHolder(sid);
|
|
186
|
+
return tokenHolder;
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
cloudTestLogin_meta: true,
|
|
190
|
+
async cloudTestLogin({ email }) {
|
|
191
|
+
const tokenHolder = await readCloudTestTokenHolder(email);
|
|
192
|
+
return tokenHolder;
|
|
193
|
+
},
|
|
194
|
+
|
|
151
195
|
authMiddleware,
|
|
152
196
|
};
|
package/src/controllers/cloud.js
CHANGED
|
@@ -258,4 +258,22 @@ module.exports = {
|
|
|
258
258
|
await fs.writeFile(filePath, content);
|
|
259
259
|
return true;
|
|
260
260
|
},
|
|
261
|
+
|
|
262
|
+
folderUsers_meta: true,
|
|
263
|
+
async folderUsers({ folid }) {
|
|
264
|
+
const resp = await callCloudApiGet(`content-folders/users/${folid}`);
|
|
265
|
+
return resp;
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
setFolderUserRole_meta: true,
|
|
269
|
+
async setFolderUserRole({ folid, email, role }) {
|
|
270
|
+
const resp = await callCloudApiPost(`content-folders/set-user-role/${folid}`, { email, role });
|
|
271
|
+
return resp;
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
removeFolderUser_meta: true,
|
|
275
|
+
async removeFolderUser({ folid, email }) {
|
|
276
|
+
const resp = await callCloudApiPost(`content-folders/remove-user/${folid}`, { email });
|
|
277
|
+
return resp;
|
|
278
|
+
},
|
|
261
279
|
};
|
|
@@ -29,6 +29,7 @@ const {
|
|
|
29
29
|
} = require('../utility/crypting');
|
|
30
30
|
|
|
31
31
|
const lock = new AsyncLock();
|
|
32
|
+
let cachedSettingsValue = null;
|
|
32
33
|
|
|
33
34
|
module.exports = {
|
|
34
35
|
// settingsValue: {},
|
|
@@ -118,6 +119,7 @@ module.exports = {
|
|
|
118
119
|
supportCloudAutoUpgrade: !!process.env.CLOUD_UPGRADE_FILE,
|
|
119
120
|
allowPrivateCloud: platformInfo.isElectron || !!process.env.ALLOW_DBGATE_PRIVATE_CLOUD,
|
|
120
121
|
...currentVersion,
|
|
122
|
+
redirectToDbGateCloudLogin: !!process.env.REDIRECT_TO_DBGATE_CLOUD_LOGIN,
|
|
121
123
|
};
|
|
122
124
|
|
|
123
125
|
return configResult;
|
|
@@ -144,6 +146,13 @@ module.exports = {
|
|
|
144
146
|
return res;
|
|
145
147
|
},
|
|
146
148
|
|
|
149
|
+
async getCachedSettings() {
|
|
150
|
+
if (!cachedSettingsValue) {
|
|
151
|
+
cachedSettingsValue = await this.loadSettings();
|
|
152
|
+
}
|
|
153
|
+
return cachedSettingsValue;
|
|
154
|
+
},
|
|
155
|
+
|
|
147
156
|
deleteSettings_meta: true,
|
|
148
157
|
async deleteSettings() {
|
|
149
158
|
await fs.unlink(path.join(datadir(), processArgs.runE2eTests ? 'settings-e2etests.json' : 'settings.json'));
|
|
@@ -257,6 +266,7 @@ module.exports = {
|
|
|
257
266
|
updateSettings_meta: true,
|
|
258
267
|
async updateSettings(values, req) {
|
|
259
268
|
if (!hasPermission(`settings/change`, req)) return false;
|
|
269
|
+
cachedSettingsValue = null;
|
|
260
270
|
|
|
261
271
|
const res = await lock.acquire('settings', async () => {
|
|
262
272
|
const currentValue = await this.loadSettings();
|
|
@@ -265,7 +275,11 @@ module.exports = {
|
|
|
265
275
|
if (process.env.STORAGE_DATABASE) {
|
|
266
276
|
updated = {
|
|
267
277
|
...currentValue,
|
|
268
|
-
...values,
|
|
278
|
+
..._.mapValues(values, v => {
|
|
279
|
+
if (v === true) return 'true';
|
|
280
|
+
if (v === false) return 'false';
|
|
281
|
+
return v;
|
|
282
|
+
}),
|
|
269
283
|
};
|
|
270
284
|
await storage.writeConfig({
|
|
271
285
|
group: 'settings',
|
|
@@ -303,7 +317,7 @@ module.exports = {
|
|
|
303
317
|
const resp = await axios.default.get('https://raw.githubusercontent.com/dbgate/dbgate/master/CHANGELOG.md');
|
|
304
318
|
return resp.data;
|
|
305
319
|
} catch (err) {
|
|
306
|
-
return ''
|
|
320
|
+
return '';
|
|
307
321
|
}
|
|
308
322
|
},
|
|
309
323
|
|
|
@@ -536,14 +536,14 @@ module.exports = {
|
|
|
536
536
|
},
|
|
537
537
|
|
|
538
538
|
dbloginAuthToken_meta: true,
|
|
539
|
-
async dbloginAuthToken({ amoid, code, conid, redirectUri, sid }) {
|
|
539
|
+
async dbloginAuthToken({ amoid, code, conid, redirectUri, sid }, req) {
|
|
540
540
|
try {
|
|
541
541
|
const connection = await this.getCore({ conid });
|
|
542
542
|
const driver = requireEngineDriver(connection);
|
|
543
543
|
const accessToken = await driver.getAuthTokenFromCode(connection, { code, redirectUri, sid });
|
|
544
544
|
const volatile = await this.saveVolatile({ conid, accessToken });
|
|
545
545
|
const authProvider = getAuthProviderById(amoid);
|
|
546
|
-
const resp = await authProvider.login(null, null, { conid: volatile._id });
|
|
546
|
+
const resp = await authProvider.login(null, null, { conid: volatile._id }, req);
|
|
547
547
|
return resp;
|
|
548
548
|
} catch (err) {
|
|
549
549
|
logger.error(extractErrorLogData(err), 'Error getting DB token');
|
|
@@ -552,18 +552,18 @@ module.exports = {
|
|
|
552
552
|
},
|
|
553
553
|
|
|
554
554
|
dbloginAuth_meta: true,
|
|
555
|
-
async dbloginAuth({ amoid, conid, user, password }) {
|
|
555
|
+
async dbloginAuth({ amoid, conid, user, password }, req) {
|
|
556
556
|
if (user || password) {
|
|
557
557
|
const saveResp = await this.saveVolatile({ conid, user, password, test: true });
|
|
558
558
|
if (saveResp.msgtype == 'connected') {
|
|
559
|
-
const loginResp = await getAuthProviderById(amoid).login(user, password, { conid: saveResp._id });
|
|
559
|
+
const loginResp = await getAuthProviderById(amoid).login(user, password, { conid: saveResp._id }, req);
|
|
560
560
|
return loginResp;
|
|
561
561
|
}
|
|
562
562
|
return saveResp;
|
|
563
563
|
}
|
|
564
564
|
|
|
565
565
|
// user and password is stored in connection, volatile connection is not needed
|
|
566
|
-
const loginResp = await getAuthProviderById(amoid).login(null, null, { conid });
|
|
566
|
+
const loginResp = await getAuthProviderById(amoid).login(null, null, { conid }, req);
|
|
567
567
|
return loginResp;
|
|
568
568
|
},
|
|
569
569
|
|
|
@@ -41,6 +41,7 @@ const { decryptConnection } = require('../utility/crypting');
|
|
|
41
41
|
const { getSshTunnel } = require('../utility/sshTunnel');
|
|
42
42
|
const sessions = require('./sessions');
|
|
43
43
|
const jsldata = require('./jsldata');
|
|
44
|
+
const { sendToAuditLog } = require('../utility/auditlog');
|
|
44
45
|
|
|
45
46
|
const logger = getLogger('databaseConnections');
|
|
46
47
|
|
|
@@ -83,8 +84,11 @@ module.exports = {
|
|
|
83
84
|
}
|
|
84
85
|
},
|
|
85
86
|
handle_response(conid, database, { msgid, ...response }) {
|
|
86
|
-
const [resolve, reject] = this.requests[msgid];
|
|
87
|
+
const [resolve, reject, additionalData] = this.requests[msgid];
|
|
87
88
|
resolve(response);
|
|
89
|
+
if (additionalData?.auditLogger) {
|
|
90
|
+
additionalData?.auditLogger(response);
|
|
91
|
+
}
|
|
88
92
|
delete this.requests[msgid];
|
|
89
93
|
},
|
|
90
94
|
handle_status(conid, database, { status }) {
|
|
@@ -215,10 +219,10 @@ module.exports = {
|
|
|
215
219
|
},
|
|
216
220
|
|
|
217
221
|
/** @param {import('dbgate-types').OpenedDatabaseConnection} conn */
|
|
218
|
-
sendRequest(conn, message) {
|
|
222
|
+
sendRequest(conn, message, additionalData = {}) {
|
|
219
223
|
const msgid = crypto.randomUUID();
|
|
220
224
|
const promise = new Promise((resolve, reject) => {
|
|
221
|
-
this.requests[msgid] = [resolve, reject];
|
|
225
|
+
this.requests[msgid] = [resolve, reject, additionalData];
|
|
222
226
|
try {
|
|
223
227
|
conn.subprocess.send({ msgid, ...message });
|
|
224
228
|
} catch (err) {
|
|
@@ -242,18 +246,57 @@ module.exports = {
|
|
|
242
246
|
},
|
|
243
247
|
|
|
244
248
|
sqlSelect_meta: true,
|
|
245
|
-
async sqlSelect({ conid, database, select }, req) {
|
|
249
|
+
async sqlSelect({ conid, database, select, auditLogSessionGroup }, req) {
|
|
246
250
|
testConnectionPermission(conid, req);
|
|
247
251
|
const opened = await this.ensureOpened(conid, database);
|
|
248
|
-
const res = await this.sendRequest(
|
|
252
|
+
const res = await this.sendRequest(
|
|
253
|
+
opened,
|
|
254
|
+
{ msgtype: 'sqlSelect', select },
|
|
255
|
+
{
|
|
256
|
+
auditLogger:
|
|
257
|
+
auditLogSessionGroup && select?.from?.name?.pureName
|
|
258
|
+
? response => {
|
|
259
|
+
sendToAuditLog(req, {
|
|
260
|
+
category: 'dbop',
|
|
261
|
+
component: 'DatabaseConnectionsController',
|
|
262
|
+
event: 'sql.select',
|
|
263
|
+
action: 'select',
|
|
264
|
+
severity: 'info',
|
|
265
|
+
conid,
|
|
266
|
+
database,
|
|
267
|
+
schemaName: select?.from?.name?.schemaName,
|
|
268
|
+
pureName: select?.from?.name?.pureName,
|
|
269
|
+
sumint1: response?.rows?.length,
|
|
270
|
+
sessionParam: `${conid}::${database}::${select?.from?.name?.schemaName || '0'}::${
|
|
271
|
+
select?.from?.name?.pureName
|
|
272
|
+
}`,
|
|
273
|
+
sessionGroup: auditLogSessionGroup,
|
|
274
|
+
message: `Loaded table data from ${select?.from?.name?.pureName}`,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
: null,
|
|
278
|
+
}
|
|
279
|
+
);
|
|
249
280
|
return res;
|
|
250
281
|
},
|
|
251
282
|
|
|
252
283
|
runScript_meta: true,
|
|
253
|
-
async runScript({ conid, database, sql, useTransaction }, req) {
|
|
284
|
+
async runScript({ conid, database, sql, useTransaction, logMessage }, req) {
|
|
254
285
|
testConnectionPermission(conid, req);
|
|
255
286
|
logger.info({ conid, database, sql }, 'Processing script');
|
|
256
287
|
const opened = await this.ensureOpened(conid, database);
|
|
288
|
+
sendToAuditLog(req, {
|
|
289
|
+
category: 'dbop',
|
|
290
|
+
component: 'DatabaseConnectionsController',
|
|
291
|
+
event: 'sql.runscript',
|
|
292
|
+
action: 'runscript',
|
|
293
|
+
severity: 'info',
|
|
294
|
+
conid,
|
|
295
|
+
database,
|
|
296
|
+
detail: sql,
|
|
297
|
+
message: logMessage || `Running SQL script`,
|
|
298
|
+
});
|
|
299
|
+
|
|
257
300
|
const res = await this.sendRequest(opened, { msgtype: 'runScript', sql, useTransaction });
|
|
258
301
|
return res;
|
|
259
302
|
},
|
|
@@ -262,16 +305,53 @@ module.exports = {
|
|
|
262
305
|
async runOperation({ conid, database, operation, useTransaction }, req) {
|
|
263
306
|
testConnectionPermission(conid, req);
|
|
264
307
|
logger.info({ conid, database, operation }, 'Processing operation');
|
|
308
|
+
|
|
309
|
+
sendToAuditLog(req, {
|
|
310
|
+
category: 'dbop',
|
|
311
|
+
component: 'DatabaseConnectionsController',
|
|
312
|
+
event: 'sql.runoperation',
|
|
313
|
+
action: operation.type,
|
|
314
|
+
severity: 'info',
|
|
315
|
+
conid,
|
|
316
|
+
database,
|
|
317
|
+
detail: operation,
|
|
318
|
+
message: `Running DB operation: ${operation.type}`,
|
|
319
|
+
});
|
|
320
|
+
|
|
265
321
|
const opened = await this.ensureOpened(conid, database);
|
|
266
322
|
const res = await this.sendRequest(opened, { msgtype: 'runOperation', operation, useTransaction });
|
|
267
323
|
return res;
|
|
268
324
|
},
|
|
269
325
|
|
|
270
326
|
collectionData_meta: true,
|
|
271
|
-
async collectionData({ conid, database, options }, req) {
|
|
327
|
+
async collectionData({ conid, database, options, auditLogSessionGroup }, req) {
|
|
272
328
|
testConnectionPermission(conid, req);
|
|
273
329
|
const opened = await this.ensureOpened(conid, database);
|
|
274
|
-
const res = await this.sendRequest(
|
|
330
|
+
const res = await this.sendRequest(
|
|
331
|
+
opened,
|
|
332
|
+
{ msgtype: 'collectionData', options },
|
|
333
|
+
{
|
|
334
|
+
auditLogger:
|
|
335
|
+
auditLogSessionGroup && options?.pureName
|
|
336
|
+
? response => {
|
|
337
|
+
sendToAuditLog(req, {
|
|
338
|
+
category: 'dbop',
|
|
339
|
+
component: 'DatabaseConnectionsController',
|
|
340
|
+
event: 'nosql.collectionData',
|
|
341
|
+
action: 'select',
|
|
342
|
+
severity: 'info',
|
|
343
|
+
conid,
|
|
344
|
+
database,
|
|
345
|
+
pureName: options?.pureName,
|
|
346
|
+
sumint1: response?.result?.rows?.length,
|
|
347
|
+
sessionParam: `${conid}::${database}::${options?.pureName}`,
|
|
348
|
+
sessionGroup: auditLogSessionGroup,
|
|
349
|
+
message: `Loaded collection data ${options?.pureName}`,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
: null,
|
|
353
|
+
}
|
|
354
|
+
);
|
|
275
355
|
return res.result || null;
|
|
276
356
|
},
|
|
277
357
|
|
|
@@ -492,6 +572,20 @@ module.exports = {
|
|
|
492
572
|
}
|
|
493
573
|
|
|
494
574
|
const opened = await this.ensureOpened(conid, database);
|
|
575
|
+
|
|
576
|
+
sendToAuditLog(req, {
|
|
577
|
+
category: 'dbop',
|
|
578
|
+
component: 'DatabaseConnectionsController',
|
|
579
|
+
action: 'structure',
|
|
580
|
+
event: 'dbStructure.get',
|
|
581
|
+
severity: 'info',
|
|
582
|
+
conid,
|
|
583
|
+
database,
|
|
584
|
+
sessionParam: `${conid}::${database}`,
|
|
585
|
+
sessionGroup: 'getStructure',
|
|
586
|
+
message: `Loaded database structure for ${database}`,
|
|
587
|
+
});
|
|
588
|
+
|
|
495
589
|
return opened.structure;
|
|
496
590
|
// const existing = this.opened.find((x) => x.conid == conid && x.database == database);
|
|
497
591
|
// if (existing) return existing.status;
|
package/src/controllers/files.js
CHANGED
|
@@ -203,10 +203,10 @@ module.exports = {
|
|
|
203
203
|
},
|
|
204
204
|
|
|
205
205
|
exportChart_meta: true,
|
|
206
|
-
async exportChart({ filePath, title, config, image }) {
|
|
206
|
+
async exportChart({ filePath, title, config, image, plugins }) {
|
|
207
207
|
const fileName = path.parse(filePath).base;
|
|
208
208
|
const imageFile = fileName.replace('.html', '-preview.png');
|
|
209
|
-
const html = getChartExport(title, config, imageFile);
|
|
209
|
+
const html = getChartExport(title, config, imageFile, plugins);
|
|
210
210
|
await fs.writeFile(filePath, html);
|
|
211
211
|
if (image) {
|
|
212
212
|
const index = image.indexOf('base64,');
|
|
@@ -20,6 +20,7 @@ const { handleProcessCommunication } = require('../utility/processComm');
|
|
|
20
20
|
const processArgs = require('../utility/processArgs');
|
|
21
21
|
const platformInfo = require('../utility/platformInfo');
|
|
22
22
|
const { checkSecureDirectories, checkSecureDirectoriesInScript } = require('../utility/security');
|
|
23
|
+
const { sendToAuditLog, logJsonRunnerScript } = require('../utility/auditlog');
|
|
23
24
|
const logger = getLogger('runners');
|
|
24
25
|
|
|
25
26
|
function extractPlugins(script) {
|
|
@@ -270,7 +271,7 @@ module.exports = {
|
|
|
270
271
|
},
|
|
271
272
|
|
|
272
273
|
start_meta: true,
|
|
273
|
-
async start({ script }) {
|
|
274
|
+
async start({ script }, req) {
|
|
274
275
|
const runid = crypto.randomUUID();
|
|
275
276
|
|
|
276
277
|
if (script.type == 'json') {
|
|
@@ -280,14 +281,36 @@ module.exports = {
|
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
283
|
|
|
284
|
+
logJsonRunnerScript(req, script);
|
|
285
|
+
|
|
283
286
|
const js = await jsonScriptToJavascript(script);
|
|
284
287
|
return this.startCore(runid, scriptTemplate(js, false));
|
|
285
288
|
}
|
|
286
289
|
|
|
287
290
|
if (!platformInfo.allowShellScripting) {
|
|
291
|
+
sendToAuditLog(req, {
|
|
292
|
+
category: 'shell',
|
|
293
|
+
component: 'RunnersController',
|
|
294
|
+
event: 'script.runFailed',
|
|
295
|
+
action: 'script',
|
|
296
|
+
severity: 'warn',
|
|
297
|
+
detail: script,
|
|
298
|
+
message: 'Scripts are not allowed',
|
|
299
|
+
});
|
|
300
|
+
|
|
288
301
|
return { errorMessage: 'Shell scripting is not allowed' };
|
|
289
302
|
}
|
|
290
303
|
|
|
304
|
+
sendToAuditLog(req, {
|
|
305
|
+
category: 'shell',
|
|
306
|
+
component: 'RunnersController',
|
|
307
|
+
event: 'script.run.shell',
|
|
308
|
+
action: 'script',
|
|
309
|
+
severity: 'info',
|
|
310
|
+
detail: script,
|
|
311
|
+
message: 'Running JS script',
|
|
312
|
+
});
|
|
313
|
+
|
|
291
314
|
return this.startCore(runid, scriptTemplate(script, false));
|
|
292
315
|
},
|
|
293
316
|
|
|
@@ -12,6 +12,7 @@ const { testConnectionPermission } = require('../utility/hasPermission');
|
|
|
12
12
|
const { MissingCredentialsError } = require('../utility/exceptions');
|
|
13
13
|
const pipeForkLogs = require('../utility/pipeForkLogs');
|
|
14
14
|
const { getLogger, extractErrorLogData } = require('dbgate-tools');
|
|
15
|
+
const { sendToAuditLog } = require('../utility/auditlog');
|
|
15
16
|
|
|
16
17
|
const logger = getLogger('serverConnection');
|
|
17
18
|
|
|
@@ -145,6 +146,17 @@ module.exports = {
|
|
|
145
146
|
if (conid == '__model') return [];
|
|
146
147
|
testConnectionPermission(conid, req);
|
|
147
148
|
const opened = await this.ensureOpened(conid);
|
|
149
|
+
sendToAuditLog(req, {
|
|
150
|
+
category: 'serverop',
|
|
151
|
+
component: 'ServerConnectionsController',
|
|
152
|
+
action: 'listDatabases',
|
|
153
|
+
event: 'databases.list',
|
|
154
|
+
severity: 'info',
|
|
155
|
+
conid,
|
|
156
|
+
sessionParam: `${conid}`,
|
|
157
|
+
sessionGroup: 'listDatabases',
|
|
158
|
+
message: `Loaded databases for connection`,
|
|
159
|
+
});
|
|
148
160
|
return opened?.databases ?? [];
|
|
149
161
|
},
|
|
150
162
|
|
|
@@ -11,6 +11,7 @@ const { appdir } = require('../utility/directories');
|
|
|
11
11
|
const { getLogger, extractErrorLogData } = require('dbgate-tools');
|
|
12
12
|
const pipeForkLogs = require('../utility/pipeForkLogs');
|
|
13
13
|
const config = require('./config');
|
|
14
|
+
const { sendToAuditLog } = require('../utility/auditlog');
|
|
14
15
|
|
|
15
16
|
const logger = getLogger('sessions');
|
|
16
17
|
|
|
@@ -146,12 +147,24 @@ module.exports = {
|
|
|
146
147
|
},
|
|
147
148
|
|
|
148
149
|
executeQuery_meta: true,
|
|
149
|
-
async executeQuery({ sesid, sql, autoCommit, autoDetectCharts, limitRows, frontMatter }) {
|
|
150
|
+
async executeQuery({ sesid, sql, autoCommit, autoDetectCharts, limitRows, frontMatter }, req) {
|
|
150
151
|
const session = this.opened.find(x => x.sesid == sesid);
|
|
151
152
|
if (!session) {
|
|
152
153
|
throw new Error('Invalid session');
|
|
153
154
|
}
|
|
154
155
|
|
|
156
|
+
sendToAuditLog(req, {
|
|
157
|
+
category: 'dbop',
|
|
158
|
+
component: 'SessionController',
|
|
159
|
+
action: 'executeQuery',
|
|
160
|
+
event: 'query.execute',
|
|
161
|
+
severity: 'info',
|
|
162
|
+
detail: sql,
|
|
163
|
+
conid: session.conid,
|
|
164
|
+
database: session.database,
|
|
165
|
+
message: 'Executing query',
|
|
166
|
+
});
|
|
167
|
+
|
|
155
168
|
logger.info({ sesid, sql }, 'Processing query');
|
|
156
169
|
this.dispatchMessage(sesid, 'Query execution started');
|
|
157
170
|
session.subprocess.send({
|
|
@@ -31,9 +31,16 @@ module.exports = {
|
|
|
31
31
|
return {};
|
|
32
32
|
},
|
|
33
33
|
|
|
34
|
+
sendAuditLog_meta: true,
|
|
35
|
+
async sendAuditLog({}) {
|
|
36
|
+
return null;
|
|
37
|
+
},
|
|
38
|
+
|
|
34
39
|
startRefreshLicense() {},
|
|
35
40
|
|
|
36
41
|
async getUsedEngines() {
|
|
37
42
|
return null;
|
|
38
43
|
},
|
|
44
|
+
|
|
45
|
+
markUserAsActive(licenseUid) {},
|
|
39
46
|
};
|
package/src/currentVersion.js
CHANGED
package/src/shell/deployDb.js
CHANGED
|
@@ -14,7 +14,7 @@ const crypto = require('crypto');
|
|
|
14
14
|
* @param {object} options.driver - driver object. If not provided, it will be loaded from connection
|
|
15
15
|
* @param {object} options.analysedStructure - analysed structure of the database. If not provided, it will be loaded
|
|
16
16
|
* @param {string} options.modelFolder - folder with model files (YAML files for tables, SQL files for views, procedures, ...)
|
|
17
|
-
* @param {import('dbgate-tools').DatabaseModelFile[]} options.loadedDbModel - loaded database model - collection of yaml and SQL files loaded into array
|
|
17
|
+
* @param {import('dbgate-tools').DatabaseModelFile[] | import('dbgate-types').DatabaseInfo} options.loadedDbModel - loaded database model - collection of yaml and SQL files loaded into array
|
|
18
18
|
* @param {function[]} options.modelTransforms - array of functions for transforming model
|
|
19
19
|
* @param {object} options.dbdiffOptionsExtra - extra options for dbdiff
|
|
20
20
|
* @param {string} options.ignoreNameRegex - regex for ignoring objects by name
|
|
@@ -23,7 +23,7 @@ const { connectUtility } = require('../utility/connectUtility');
|
|
|
23
23
|
* @param {object} options.driver - driver object. If not provided, it will be loaded from connection
|
|
24
24
|
* @param {object} options.analysedStructure - analysed structure of the database. If not provided, it will be loaded
|
|
25
25
|
* @param {string} options.modelFolder - folder with model files (YAML files for tables, SQL files for views, procedures, ...)
|
|
26
|
-
* @param {import('dbgate-tools').DatabaseModelFile[]} options.loadedDbModel - loaded database model - collection of yaml and SQL files loaded into array
|
|
26
|
+
* @param {import('dbgate-tools').DatabaseModelFile[] | import('dbgate-types').DatabaseInfo} options.loadedDbModel - loaded database model - collection of yaml and SQL files loaded into array
|
|
27
27
|
* @param {function[]} options.modelTransforms - array of functions for transforming model
|
|
28
28
|
* @param {object} options.dbdiffOptionsExtra - extra options for dbdiff
|
|
29
29
|
* @param {string} options.ignoreNameRegex - regex for ignoring objects by name
|
|
@@ -3,7 +3,7 @@ const fs = require('fs-extra');
|
|
|
3
3
|
const executeQuery = require('./executeQuery');
|
|
4
4
|
const { connectUtility } = require('../utility/connectUtility');
|
|
5
5
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
6
|
-
const { getAlterDatabaseScript, DatabaseAnalyser, runCommandOnDriver } = require('dbgate-tools');
|
|
6
|
+
const { getAlterDatabaseScript, DatabaseAnalyser, runCommandOnDriver, adaptDatabaseInfo } = require('dbgate-tools');
|
|
7
7
|
const importDbModel = require('../utility/importDbModel');
|
|
8
8
|
const jsonLinesReader = require('./jsonLinesReader');
|
|
9
9
|
const tableWriter = require('./tableWriter');
|
|
@@ -26,10 +26,7 @@ async function importDbFromFolder({ connection, systemConnection, driver, folder
|
|
|
26
26
|
if (driver?.databaseEngineTypes?.includes('sql')) {
|
|
27
27
|
const model = await importDbModel(folder);
|
|
28
28
|
|
|
29
|
-
let modelAdapted =
|
|
30
|
-
...model,
|
|
31
|
-
tables: model.tables.map(table => driver.adaptTableInfo(table)),
|
|
32
|
-
};
|
|
29
|
+
let modelAdapted = adaptDatabaseInfo(model, driver);
|
|
33
30
|
for (const transform of modelTransforms || []) {
|
|
34
31
|
modelAdapted = transform(modelAdapted);
|
|
35
32
|
}
|
package/src/storageModel.js
CHANGED
|
@@ -1,5 +1,192 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
"tables": [
|
|
3
|
+
{
|
|
4
|
+
"pureName": "audit_log",
|
|
5
|
+
"columns": [
|
|
6
|
+
{
|
|
7
|
+
"pureName": "audit_log",
|
|
8
|
+
"columnName": "id",
|
|
9
|
+
"dataType": "int",
|
|
10
|
+
"autoIncrement": true,
|
|
11
|
+
"notNull": true
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"pureName": "audit_log",
|
|
15
|
+
"columnName": "created",
|
|
16
|
+
"dataType": "bigint",
|
|
17
|
+
"notNull": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"pureName": "audit_log",
|
|
21
|
+
"columnName": "modified",
|
|
22
|
+
"dataType": "bigint",
|
|
23
|
+
"notNull": false
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"pureName": "audit_log",
|
|
27
|
+
"columnName": "user_id",
|
|
28
|
+
"dataType": "int",
|
|
29
|
+
"notNull": false
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"pureName": "audit_log",
|
|
33
|
+
"columnName": "user_login",
|
|
34
|
+
"dataType": "varchar(250)",
|
|
35
|
+
"notNull": false
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"pureName": "audit_log",
|
|
39
|
+
"columnName": "category",
|
|
40
|
+
"dataType": "varchar(50)",
|
|
41
|
+
"notNull": false
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"pureName": "audit_log",
|
|
45
|
+
"columnName": "component",
|
|
46
|
+
"dataType": "varchar(50)",
|
|
47
|
+
"notNull": false
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"pureName": "audit_log",
|
|
51
|
+
"columnName": "action",
|
|
52
|
+
"dataType": "varchar(50)",
|
|
53
|
+
"notNull": false
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"pureName": "audit_log",
|
|
57
|
+
"columnName": "severity",
|
|
58
|
+
"dataType": "varchar(50)",
|
|
59
|
+
"notNull": false
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"pureName": "audit_log",
|
|
63
|
+
"columnName": "event",
|
|
64
|
+
"dataType": "varchar(100)",
|
|
65
|
+
"notNull": false
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"pureName": "audit_log",
|
|
69
|
+
"columnName": "message",
|
|
70
|
+
"dataType": "varchar(250)",
|
|
71
|
+
"notNull": false
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"pureName": "audit_log",
|
|
75
|
+
"columnName": "detail",
|
|
76
|
+
"dataType": "varchar(1000)",
|
|
77
|
+
"notNull": false
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"pureName": "audit_log",
|
|
81
|
+
"columnName": "detail_full_length",
|
|
82
|
+
"dataType": "int",
|
|
83
|
+
"notNull": false
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"pureName": "audit_log",
|
|
87
|
+
"columnName": "session_id",
|
|
88
|
+
"dataType": "varchar(200)",
|
|
89
|
+
"notNull": false
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"pureName": "audit_log",
|
|
93
|
+
"columnName": "session_group",
|
|
94
|
+
"dataType": "varchar(50)",
|
|
95
|
+
"notNull": false
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"pureName": "audit_log",
|
|
99
|
+
"columnName": "session_param",
|
|
100
|
+
"dataType": "varchar(200)",
|
|
101
|
+
"notNull": false
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"pureName": "audit_log",
|
|
105
|
+
"columnName": "conid",
|
|
106
|
+
"dataType": "varchar(100)",
|
|
107
|
+
"notNull": false
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"pureName": "audit_log",
|
|
111
|
+
"columnName": "connection_data",
|
|
112
|
+
"dataType": "varchar(1000)",
|
|
113
|
+
"notNull": false
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"pureName": "audit_log",
|
|
117
|
+
"columnName": "database",
|
|
118
|
+
"dataType": "varchar(200)",
|
|
119
|
+
"notNull": false
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"pureName": "audit_log",
|
|
123
|
+
"columnName": "schema_name",
|
|
124
|
+
"dataType": "varchar(100)",
|
|
125
|
+
"notNull": false
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"pureName": "audit_log",
|
|
129
|
+
"columnName": "pure_name",
|
|
130
|
+
"dataType": "varchar(100)",
|
|
131
|
+
"notNull": false
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"pureName": "audit_log",
|
|
135
|
+
"columnName": "sumint_1",
|
|
136
|
+
"dataType": "int",
|
|
137
|
+
"notNull": false
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"pureName": "audit_log",
|
|
141
|
+
"columnName": "sumint_2",
|
|
142
|
+
"dataType": "int",
|
|
143
|
+
"notNull": false
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
"foreignKeys": [
|
|
147
|
+
{
|
|
148
|
+
"constraintType": "foreignKey",
|
|
149
|
+
"constraintName": "FK_audit_log_user_id",
|
|
150
|
+
"pureName": "audit_log",
|
|
151
|
+
"refTableName": "users",
|
|
152
|
+
"deleteAction": "SET NULL",
|
|
153
|
+
"columns": [
|
|
154
|
+
{
|
|
155
|
+
"columnName": "user_id",
|
|
156
|
+
"refColumnName": "id"
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
"indexes": [
|
|
162
|
+
{
|
|
163
|
+
"constraintName": "idx_audit_log_session",
|
|
164
|
+
"pureName": "audit_log",
|
|
165
|
+
"constraintType": "index",
|
|
166
|
+
"columns": [
|
|
167
|
+
{
|
|
168
|
+
"columnName": "session_group"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"columnName": "session_id"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"columnName": "session_param"
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
"primaryKey": {
|
|
180
|
+
"pureName": "audit_log",
|
|
181
|
+
"constraintType": "primaryKey",
|
|
182
|
+
"constraintName": "PK_audit_log",
|
|
183
|
+
"columns": [
|
|
184
|
+
{
|
|
185
|
+
"columnName": "id"
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
},
|
|
3
190
|
{
|
|
4
191
|
"pureName": "auth_methods",
|
|
5
192
|
"columns": [
|
|
@@ -50,6 +237,7 @@ module.exports = {
|
|
|
50
237
|
"primaryKey": {
|
|
51
238
|
"pureName": "auth_methods",
|
|
52
239
|
"constraintType": "primaryKey",
|
|
240
|
+
"constraintName": "PK_auth_methods",
|
|
53
241
|
"columns": [
|
|
54
242
|
{
|
|
55
243
|
"columnName": "id"
|
|
@@ -61,7 +249,8 @@ module.exports = {
|
|
|
61
249
|
"id": -1,
|
|
62
250
|
"amoid": "790ca4d2-7f01-4800-955b-d691b890cc50",
|
|
63
251
|
"name": "Anonymous",
|
|
64
|
-
"type": "none"
|
|
252
|
+
"type": "none",
|
|
253
|
+
"is_disabled": 1
|
|
65
254
|
},
|
|
66
255
|
{
|
|
67
256
|
"id": -2,
|
|
@@ -69,6 +258,9 @@ module.exports = {
|
|
|
69
258
|
"name": "Local",
|
|
70
259
|
"type": "local"
|
|
71
260
|
}
|
|
261
|
+
],
|
|
262
|
+
"preloadedRowsInsertOnly": [
|
|
263
|
+
"is_disabled"
|
|
72
264
|
]
|
|
73
265
|
},
|
|
74
266
|
{
|
|
@@ -103,6 +295,7 @@ module.exports = {
|
|
|
103
295
|
"foreignKeys": [
|
|
104
296
|
{
|
|
105
297
|
"constraintType": "foreignKey",
|
|
298
|
+
"constraintName": "FK_auth_methods_config_auth_method_id",
|
|
106
299
|
"pureName": "auth_methods_config",
|
|
107
300
|
"refTableName": "auth_methods",
|
|
108
301
|
"deleteAction": "CASCADE",
|
|
@@ -114,9 +307,25 @@ module.exports = {
|
|
|
114
307
|
]
|
|
115
308
|
}
|
|
116
309
|
],
|
|
310
|
+
"uniques": [
|
|
311
|
+
{
|
|
312
|
+
"constraintName": "UQ_auth_methods_config_auth_method_id_key",
|
|
313
|
+
"pureName": "auth_methods_config",
|
|
314
|
+
"constraintType": "unique",
|
|
315
|
+
"columns": [
|
|
316
|
+
{
|
|
317
|
+
"columnName": "auth_method_id"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"columnName": "key"
|
|
321
|
+
}
|
|
322
|
+
]
|
|
323
|
+
}
|
|
324
|
+
],
|
|
117
325
|
"primaryKey": {
|
|
118
326
|
"pureName": "auth_methods_config",
|
|
119
327
|
"constraintType": "primaryKey",
|
|
328
|
+
"constraintName": "PK_auth_methods_config",
|
|
120
329
|
"columns": [
|
|
121
330
|
{
|
|
122
331
|
"columnName": "id"
|
|
@@ -154,9 +363,25 @@ module.exports = {
|
|
|
154
363
|
}
|
|
155
364
|
],
|
|
156
365
|
"foreignKeys": [],
|
|
366
|
+
"uniques": [
|
|
367
|
+
{
|
|
368
|
+
"constraintName": "UQ_config_group_key",
|
|
369
|
+
"pureName": "config",
|
|
370
|
+
"constraintType": "unique",
|
|
371
|
+
"columns": [
|
|
372
|
+
{
|
|
373
|
+
"columnName": "group"
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"columnName": "key"
|
|
377
|
+
}
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
],
|
|
157
381
|
"primaryKey": {
|
|
158
382
|
"pureName": "config",
|
|
159
383
|
"constraintType": "primaryKey",
|
|
384
|
+
"constraintName": "PK_config",
|
|
160
385
|
"columns": [
|
|
161
386
|
{
|
|
162
387
|
"columnName": "id"
|
|
@@ -449,6 +674,7 @@ module.exports = {
|
|
|
449
674
|
"primaryKey": {
|
|
450
675
|
"pureName": "connections",
|
|
451
676
|
"constraintType": "primaryKey",
|
|
677
|
+
"constraintName": "PK_connections",
|
|
452
678
|
"columns": [
|
|
453
679
|
{
|
|
454
680
|
"columnName": "id"
|
|
@@ -456,48 +682,6 @@ module.exports = {
|
|
|
456
682
|
]
|
|
457
683
|
}
|
|
458
684
|
},
|
|
459
|
-
{
|
|
460
|
-
"pureName": "roles",
|
|
461
|
-
"columns": [
|
|
462
|
-
{
|
|
463
|
-
"pureName": "roles",
|
|
464
|
-
"columnName": "id",
|
|
465
|
-
"dataType": "int",
|
|
466
|
-
"autoIncrement": true,
|
|
467
|
-
"notNull": true
|
|
468
|
-
},
|
|
469
|
-
{
|
|
470
|
-
"pureName": "roles",
|
|
471
|
-
"columnName": "name",
|
|
472
|
-
"dataType": "varchar(250)",
|
|
473
|
-
"notNull": false
|
|
474
|
-
}
|
|
475
|
-
],
|
|
476
|
-
"foreignKeys": [],
|
|
477
|
-
"primaryKey": {
|
|
478
|
-
"pureName": "roles",
|
|
479
|
-
"constraintType": "primaryKey",
|
|
480
|
-
"columns": [
|
|
481
|
-
{
|
|
482
|
-
"columnName": "id"
|
|
483
|
-
}
|
|
484
|
-
]
|
|
485
|
-
},
|
|
486
|
-
"preloadedRows": [
|
|
487
|
-
{
|
|
488
|
-
"id": -1,
|
|
489
|
-
"name": "anonymous-user"
|
|
490
|
-
},
|
|
491
|
-
{
|
|
492
|
-
"id": -2,
|
|
493
|
-
"name": "logged-user"
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
"id": -3,
|
|
497
|
-
"name": "superadmin"
|
|
498
|
-
}
|
|
499
|
-
]
|
|
500
|
-
},
|
|
501
685
|
{
|
|
502
686
|
"pureName": "role_connections",
|
|
503
687
|
"columns": [
|
|
@@ -524,6 +708,7 @@ module.exports = {
|
|
|
524
708
|
"foreignKeys": [
|
|
525
709
|
{
|
|
526
710
|
"constraintType": "foreignKey",
|
|
711
|
+
"constraintName": "FK_role_connections_role_id",
|
|
527
712
|
"pureName": "role_connections",
|
|
528
713
|
"refTableName": "roles",
|
|
529
714
|
"deleteAction": "CASCADE",
|
|
@@ -536,6 +721,7 @@ module.exports = {
|
|
|
536
721
|
},
|
|
537
722
|
{
|
|
538
723
|
"constraintType": "foreignKey",
|
|
724
|
+
"constraintName": "FK_role_connections_connection_id",
|
|
539
725
|
"pureName": "role_connections",
|
|
540
726
|
"refTableName": "connections",
|
|
541
727
|
"deleteAction": "CASCADE",
|
|
@@ -550,6 +736,7 @@ module.exports = {
|
|
|
550
736
|
"primaryKey": {
|
|
551
737
|
"pureName": "role_connections",
|
|
552
738
|
"constraintType": "primaryKey",
|
|
739
|
+
"constraintName": "PK_role_connections",
|
|
553
740
|
"columns": [
|
|
554
741
|
{
|
|
555
742
|
"columnName": "id"
|
|
@@ -583,6 +770,7 @@ module.exports = {
|
|
|
583
770
|
"foreignKeys": [
|
|
584
771
|
{
|
|
585
772
|
"constraintType": "foreignKey",
|
|
773
|
+
"constraintName": "FK_role_permissions_role_id",
|
|
586
774
|
"pureName": "role_permissions",
|
|
587
775
|
"refTableName": "roles",
|
|
588
776
|
"deleteAction": "CASCADE",
|
|
@@ -597,6 +785,7 @@ module.exports = {
|
|
|
597
785
|
"primaryKey": {
|
|
598
786
|
"pureName": "role_permissions",
|
|
599
787
|
"constraintType": "primaryKey",
|
|
788
|
+
"constraintName": "PK_role_permissions",
|
|
600
789
|
"columns": [
|
|
601
790
|
{
|
|
602
791
|
"columnName": "id"
|
|
@@ -605,44 +794,47 @@ module.exports = {
|
|
|
605
794
|
}
|
|
606
795
|
},
|
|
607
796
|
{
|
|
608
|
-
"pureName": "
|
|
797
|
+
"pureName": "roles",
|
|
609
798
|
"columns": [
|
|
610
799
|
{
|
|
611
|
-
"pureName": "
|
|
800
|
+
"pureName": "roles",
|
|
612
801
|
"columnName": "id",
|
|
613
802
|
"dataType": "int",
|
|
614
803
|
"autoIncrement": true,
|
|
615
804
|
"notNull": true
|
|
616
805
|
},
|
|
617
806
|
{
|
|
618
|
-
"pureName": "
|
|
619
|
-
"columnName": "
|
|
620
|
-
"dataType": "varchar(250)",
|
|
621
|
-
"notNull": false
|
|
622
|
-
},
|
|
623
|
-
{
|
|
624
|
-
"pureName": "users",
|
|
625
|
-
"columnName": "password",
|
|
626
|
-
"dataType": "varchar(250)",
|
|
627
|
-
"notNull": false
|
|
628
|
-
},
|
|
629
|
-
{
|
|
630
|
-
"pureName": "users",
|
|
631
|
-
"columnName": "email",
|
|
807
|
+
"pureName": "roles",
|
|
808
|
+
"columnName": "name",
|
|
632
809
|
"dataType": "varchar(250)",
|
|
633
810
|
"notNull": false
|
|
634
811
|
}
|
|
635
812
|
],
|
|
636
813
|
"foreignKeys": [],
|
|
637
814
|
"primaryKey": {
|
|
638
|
-
"pureName": "
|
|
815
|
+
"pureName": "roles",
|
|
639
816
|
"constraintType": "primaryKey",
|
|
817
|
+
"constraintName": "PK_roles",
|
|
640
818
|
"columns": [
|
|
641
819
|
{
|
|
642
820
|
"columnName": "id"
|
|
643
821
|
}
|
|
644
822
|
]
|
|
645
|
-
}
|
|
823
|
+
},
|
|
824
|
+
"preloadedRows": [
|
|
825
|
+
{
|
|
826
|
+
"id": -1,
|
|
827
|
+
"name": "anonymous-user"
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
"id": -2,
|
|
831
|
+
"name": "logged-user"
|
|
832
|
+
},
|
|
833
|
+
{
|
|
834
|
+
"id": -3,
|
|
835
|
+
"name": "superadmin"
|
|
836
|
+
}
|
|
837
|
+
]
|
|
646
838
|
},
|
|
647
839
|
{
|
|
648
840
|
"pureName": "user_connections",
|
|
@@ -670,6 +862,7 @@ module.exports = {
|
|
|
670
862
|
"foreignKeys": [
|
|
671
863
|
{
|
|
672
864
|
"constraintType": "foreignKey",
|
|
865
|
+
"constraintName": "FK_user_connections_user_id",
|
|
673
866
|
"pureName": "user_connections",
|
|
674
867
|
"refTableName": "users",
|
|
675
868
|
"deleteAction": "CASCADE",
|
|
@@ -682,6 +875,7 @@ module.exports = {
|
|
|
682
875
|
},
|
|
683
876
|
{
|
|
684
877
|
"constraintType": "foreignKey",
|
|
878
|
+
"constraintName": "FK_user_connections_connection_id",
|
|
685
879
|
"pureName": "user_connections",
|
|
686
880
|
"refTableName": "connections",
|
|
687
881
|
"deleteAction": "CASCADE",
|
|
@@ -696,6 +890,7 @@ module.exports = {
|
|
|
696
890
|
"primaryKey": {
|
|
697
891
|
"pureName": "user_connections",
|
|
698
892
|
"constraintType": "primaryKey",
|
|
893
|
+
"constraintName": "PK_user_connections",
|
|
699
894
|
"columns": [
|
|
700
895
|
{
|
|
701
896
|
"columnName": "id"
|
|
@@ -729,6 +924,7 @@ module.exports = {
|
|
|
729
924
|
"foreignKeys": [
|
|
730
925
|
{
|
|
731
926
|
"constraintType": "foreignKey",
|
|
927
|
+
"constraintName": "FK_user_permissions_user_id",
|
|
732
928
|
"pureName": "user_permissions",
|
|
733
929
|
"refTableName": "users",
|
|
734
930
|
"deleteAction": "CASCADE",
|
|
@@ -743,6 +939,7 @@ module.exports = {
|
|
|
743
939
|
"primaryKey": {
|
|
744
940
|
"pureName": "user_permissions",
|
|
745
941
|
"constraintType": "primaryKey",
|
|
942
|
+
"constraintName": "PK_user_permissions",
|
|
746
943
|
"columns": [
|
|
747
944
|
{
|
|
748
945
|
"columnName": "id"
|
|
@@ -776,6 +973,7 @@ module.exports = {
|
|
|
776
973
|
"foreignKeys": [
|
|
777
974
|
{
|
|
778
975
|
"constraintType": "foreignKey",
|
|
976
|
+
"constraintName": "FK_user_roles_user_id",
|
|
779
977
|
"pureName": "user_roles",
|
|
780
978
|
"refTableName": "users",
|
|
781
979
|
"deleteAction": "CASCADE",
|
|
@@ -788,6 +986,7 @@ module.exports = {
|
|
|
788
986
|
},
|
|
789
987
|
{
|
|
790
988
|
"constraintType": "foreignKey",
|
|
989
|
+
"constraintName": "FK_user_roles_role_id",
|
|
791
990
|
"pureName": "user_roles",
|
|
792
991
|
"refTableName": "roles",
|
|
793
992
|
"deleteAction": "CASCADE",
|
|
@@ -802,6 +1001,48 @@ module.exports = {
|
|
|
802
1001
|
"primaryKey": {
|
|
803
1002
|
"pureName": "user_roles",
|
|
804
1003
|
"constraintType": "primaryKey",
|
|
1004
|
+
"constraintName": "PK_user_roles",
|
|
1005
|
+
"columns": [
|
|
1006
|
+
{
|
|
1007
|
+
"columnName": "id"
|
|
1008
|
+
}
|
|
1009
|
+
]
|
|
1010
|
+
}
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
"pureName": "users",
|
|
1014
|
+
"columns": [
|
|
1015
|
+
{
|
|
1016
|
+
"pureName": "users",
|
|
1017
|
+
"columnName": "id",
|
|
1018
|
+
"dataType": "int",
|
|
1019
|
+
"autoIncrement": true,
|
|
1020
|
+
"notNull": true
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
"pureName": "users",
|
|
1024
|
+
"columnName": "login",
|
|
1025
|
+
"dataType": "varchar(250)",
|
|
1026
|
+
"notNull": false
|
|
1027
|
+
},
|
|
1028
|
+
{
|
|
1029
|
+
"pureName": "users",
|
|
1030
|
+
"columnName": "password",
|
|
1031
|
+
"dataType": "varchar(250)",
|
|
1032
|
+
"notNull": false
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
"pureName": "users",
|
|
1036
|
+
"columnName": "email",
|
|
1037
|
+
"dataType": "varchar(250)",
|
|
1038
|
+
"notNull": false
|
|
1039
|
+
}
|
|
1040
|
+
],
|
|
1041
|
+
"foreignKeys": [],
|
|
1042
|
+
"primaryKey": {
|
|
1043
|
+
"pureName": "users",
|
|
1044
|
+
"constraintType": "primaryKey",
|
|
1045
|
+
"constraintName": "PK_users",
|
|
805
1046
|
"columns": [
|
|
806
1047
|
{
|
|
807
1048
|
"columnName": "id"
|
|
@@ -815,5 +1056,6 @@ module.exports = {
|
|
|
815
1056
|
"matviews": [],
|
|
816
1057
|
"functions": [],
|
|
817
1058
|
"procedures": [],
|
|
818
|
-
"triggers": []
|
|
1059
|
+
"triggers": [],
|
|
1060
|
+
"schedulerEvents": []
|
|
819
1061
|
};
|
package/src/utility/cloudIntf.js
CHANGED
|
@@ -34,11 +34,12 @@ const DBGATE_CLOUD_URL = process.env.LOCAL_DBGATE_CLOUD
|
|
|
34
34
|
? 'https://cloud.dbgate.udolni.net'
|
|
35
35
|
: 'https://cloud.dbgate.io';
|
|
36
36
|
|
|
37
|
-
async function createDbGateIdentitySession(client) {
|
|
37
|
+
async function createDbGateIdentitySession(client, redirectUri) {
|
|
38
38
|
const resp = await axios.default.post(
|
|
39
39
|
`${DBGATE_IDENTITY_URL}/api/create-session`,
|
|
40
40
|
{
|
|
41
41
|
client,
|
|
42
|
+
redirectUri,
|
|
42
43
|
},
|
|
43
44
|
{
|
|
44
45
|
headers: {
|
|
@@ -70,7 +71,7 @@ function startCloudTokenChecking(sid, callback) {
|
|
|
70
71
|
});
|
|
71
72
|
// console.log('CHECK RESP:', resp.data);
|
|
72
73
|
|
|
73
|
-
if (resp.data
|
|
74
|
+
if (resp.data?.email) {
|
|
74
75
|
clearInterval(interval);
|
|
75
76
|
callback(resp.data);
|
|
76
77
|
}
|
|
@@ -80,6 +81,34 @@ function startCloudTokenChecking(sid, callback) {
|
|
|
80
81
|
}, 500);
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
async function readCloudTokenHolder(sid) {
|
|
85
|
+
const resp = await axios.default.get(`${DBGATE_IDENTITY_URL}/api/get-token/${sid}`, {
|
|
86
|
+
headers: {
|
|
87
|
+
...getLicenseHttpHeaders(),
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
if (resp.data?.email) {
|
|
91
|
+
return resp.data;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function readCloudTestTokenHolder(email) {
|
|
97
|
+
const resp = await axios.default.post(
|
|
98
|
+
`${DBGATE_IDENTITY_URL}/api/test-token`,
|
|
99
|
+
{ email },
|
|
100
|
+
{
|
|
101
|
+
headers: {
|
|
102
|
+
...getLicenseHttpHeaders(),
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
if (resp.data?.email) {
|
|
107
|
+
return resp.data;
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
83
112
|
async function loadCloudFiles() {
|
|
84
113
|
try {
|
|
85
114
|
const fileContent = await fs.readFile(path.join(datadir(), 'cloud-files.jsonl'), 'utf-8');
|
|
@@ -396,4 +425,6 @@ module.exports = {
|
|
|
396
425
|
loadCachedCloudConnection,
|
|
397
426
|
putCloudContent,
|
|
398
427
|
removeCloudCachedConnection,
|
|
428
|
+
readCloudTokenHolder,
|
|
429
|
+
readCloudTestTokenHolder,
|
|
399
430
|
};
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
const getChartExport = (title, config, imageFile) => {
|
|
1
|
+
const getChartExport = (title, config, imageFile, plugins) => {
|
|
2
|
+
const PLUGIN_TAGS = {
|
|
3
|
+
zoom: '<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.2.0/chartjs-plugin-zoom.min.js" integrity="sha512-TT0wAMqqtjXVzpc48sI0G84rBP+oTkBZPgeRYIOVRGUdwJsyS3WPipsNh///ay2LJ+onCM23tipnz6EvEy2/UA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>',
|
|
4
|
+
dataLabels:
|
|
5
|
+
'<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.2.0/chartjs-plugin-datalabels.min.js" integrity="sha512-JPcRR8yFa8mmCsfrw4TNte1ZvF1e3+1SdGMslZvmrzDYxS69J7J49vkFL8u6u8PlPJK+H3voElBtUCzaXj+6ig==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>',
|
|
6
|
+
outlabels:
|
|
7
|
+
'<script src="https://cdn.jsdelivr.net/npm/@energiency/chartjs-plugin-piechart-outlabels@1.3.4/dist/chartjs-plugin-piechart-outlabels.min.js"></script>',
|
|
8
|
+
};
|
|
9
|
+
|
|
2
10
|
return `<html>
|
|
3
11
|
<meta charset='utf-8'>
|
|
4
12
|
|
|
@@ -8,7 +16,7 @@ const getChartExport = (title, config, imageFile) => {
|
|
|
8
16
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
9
17
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-adapter-moment/1.0.0/chartjs-adapter-moment.min.js" integrity="sha512-oh5t+CdSBsaVVAvxcZKy3XJdP7ZbYUBSRCXDTVn0ODewMDDNnELsrG9eDm8rVZAQg7RsDD/8K3MjPAFB13o6eA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
10
18
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js" integrity="sha512-UXumZrZNiOwnTcZSHLOfcTs0aos2MzBWHXOHOuB0J/R44QB0dwY5JgfbvljXcklVf65Gc4El6RjZ+lnwd2az2g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
11
|
-
|
|
19
|
+
${plugins.map(plugin => PLUGIN_TAGS[plugin] ?? '')}
|
|
12
20
|
|
|
13
21
|
<style>
|
|
14
22
|
a { text-decoration: none }
|
|
@@ -45,7 +53,7 @@ const getChartExport = (title, config, imageFile) => {
|
|
|
45
53
|
</div>
|
|
46
54
|
|
|
47
55
|
<div class="footer">
|
|
48
|
-
Exported from <a href='https://dbgate.
|
|
56
|
+
Exported from <a href='https://dbgate.io/' target='_blank'>DbGate</a>, powered by <a href='https://www.chartjs.org/' target='_blank'>Chart.js</a>
|
|
49
57
|
</div>
|
|
50
58
|
</body>
|
|
51
59
|
|
|
@@ -18,7 +18,7 @@ const getMapExport = (geoJson) => {
|
|
|
18
18
|
leaflet
|
|
19
19
|
.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
20
20
|
maxZoom: 19,
|
|
21
|
-
attribution: '<a href="https://dbgate.
|
|
21
|
+
attribution: '<a href="https://dbgate.io" title="Exported from DbGate">DbGate</a> | © OpenStreetMap',
|
|
22
22
|
})
|
|
23
23
|
.addTo(map);
|
|
24
24
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// only in DbGate Premium
|
|
2
|
+
|
|
3
|
+
function markUserAsActive(licenseUid) {}
|
|
4
|
+
|
|
5
|
+
async function isLoginLicensed(req, licenseUid) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const LOGIN_LIMIT_ERROR = '';
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
markUserAsActive,
|
|
13
|
+
isLoginLicensed,
|
|
14
|
+
LOGIN_LIMIT_ERROR,
|
|
15
|
+
};
|