dbgate-api-premium 6.6.1 → 6.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dbgate-api-premium",
3
3
  "main": "src/index.js",
4
- "version": "6.6.1",
4
+ "version": "6.6.2",
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.6.1",
33
+ "dbgate-datalib": "^6.6.2",
34
34
  "dbgate-query-splitter": "^4.11.5",
35
- "dbgate-sqltree": "^6.6.1",
36
- "dbgate-tools": "^6.6.1",
35
+ "dbgate-sqltree": "^6.6.2",
36
+ "dbgate-tools": "^6.6.2",
37
37
  "debug": "^4.3.4",
38
38
  "diff": "^5.0.0",
39
39
  "diff2html": "^3.4.13",
@@ -86,7 +86,7 @@
86
86
  "devDependencies": {
87
87
  "@types/fs-extra": "^9.0.11",
88
88
  "@types/lodash": "^4.14.149",
89
- "dbgate-types": "^6.6.1",
89
+ "dbgate-types": "^6.6.2",
90
90
  "env-cmd": "^10.1.0",
91
91
  "jsdoc-to-markdown": "^9.0.5",
92
92
  "node-loader": "^1.0.2",
@@ -36,12 +36,24 @@ class AuthProviderBase {
36
36
  return !!req?.user || !!req?.auth;
37
37
  }
38
38
 
39
- getCurrentPermissions(req) {
39
+ async getCurrentPermissions(req) {
40
40
  const login = this.getCurrentLogin(req);
41
41
  const permissions = process.env[`LOGIN_PERMISSIONS_${login}`];
42
42
  return permissions || process.env.PERMISSIONS;
43
43
  }
44
44
 
45
+ async checkCurrentConnectionPermission(req, conid) {
46
+ return true;
47
+ }
48
+
49
+ async getCurrentDatabasePermissions(req) {
50
+ return [];
51
+ }
52
+
53
+ async getCurrentTablePermissions(req) {
54
+ return [];
55
+ }
56
+
45
57
  getLoginPageConnections() {
46
58
  return null;
47
59
  }
@@ -11,6 +11,11 @@ const {
11
11
  storageReadUserPermissions,
12
12
  storageReadRolePermissions,
13
13
  storageSqlCommandFmt,
14
+ loadSuperadminPermissions,
15
+ readComplexUserRolePermissions,
16
+ readComplexRolePermissions,
17
+ storageCheckRoleConnectionAccess,
18
+ storageCheckUserRoleConnectionAccess,
14
19
  } = require('../controllers/storageDb');
15
20
  const { getTokenSecret, getTokenLifetime } = require('./authCommon');
16
21
  const { AuthProviderBase } = require('./authProvider');
@@ -31,6 +36,34 @@ async function loadPermissionsForUserId(userId) {
31
36
  return [...getPredefinedPermissions('logged-user'), ...loggedUserPermissions, ...rolePermissions, ...userPermissions];
32
37
  }
33
38
 
39
+ class SuperadminAuthProvider extends AuthProviderBase {
40
+ constructor() {
41
+ super();
42
+ this.amoid = 'superadmin';
43
+ }
44
+
45
+ // @ts-ignore
46
+ async getCurrentPermissions(req) {
47
+ const permissions = await loadSuperadminPermissions();
48
+ return permissions;
49
+ }
50
+
51
+ async getCurrentDatabasePermissions(req) {
52
+ const databasePermissions = await readComplexRolePermissions(-3, 'role_databases');
53
+ return databasePermissions;
54
+ }
55
+
56
+ async getCurrentTablePermissions(req) {
57
+ const tablePermissions = await readComplexRolePermissions(-3, 'role_tables');
58
+ return tablePermissions;
59
+ }
60
+
61
+ async checkCurrentConnectionPermission(req, conid) {
62
+ const res = await storageCheckRoleConnectionAccess(-3, conid);
63
+ return res;
64
+ }
65
+ }
66
+
34
67
  class StorageProviderBase extends AuthProviderBase {
35
68
  constructor(config) {
36
69
  super();
@@ -38,10 +71,6 @@ class StorageProviderBase extends AuthProviderBase {
38
71
  this.amoid = config.amoid;
39
72
  }
40
73
 
41
- getCurrentPermissions(req) {
42
- return req?.user?.permissions || process.env.PERMISSIONS;
43
- }
44
-
45
74
  toJson() {
46
75
  return {
47
76
  ...super.toJson(),
@@ -49,15 +78,38 @@ class StorageProviderBase extends AuthProviderBase {
49
78
  type: this.config.type,
50
79
  };
51
80
  }
81
+
82
+ async getCurrentPermissions(req) {
83
+ const userId = this.getUserIdFromRequest(req);
84
+ const permissions = await loadPermissionsForUserId(userId);
85
+ return permissions;
86
+ }
87
+
88
+ async getCurrentDatabasePermissions(req) {
89
+ const userId = this.getUserIdFromRequest(req);
90
+ const databasePermissions = await readComplexUserRolePermissions(userId, 'user_databases', 'role_databases');
91
+ return databasePermissions;
92
+ }
93
+
94
+ async getCurrentTablePermissions(req) {
95
+ const userId = this.getUserIdFromRequest(req);
96
+ const tablePermissions = await readComplexUserRolePermissions(userId, 'user_tables', 'role_tables');
97
+ return tablePermissions;
98
+ }
99
+
100
+ async checkCurrentConnectionPermission(req, conid) {
101
+ const userId = this.getUserIdFromRequest(req);
102
+ const res = await storageCheckUserRoleConnectionAccess(userId, conid);
103
+ return res;
104
+ }
105
+
106
+ getUserIdFromRequest(req) {
107
+ return req?.user?.userId ?? -1;
108
+ }
52
109
  }
53
110
 
54
111
  class AnonymousProvider extends StorageProviderBase {
55
112
  async login(login, password, options = undefined, req = undefined) {
56
- const permissions = await [
57
- ...getPredefinedPermissions('anonymous-user'),
58
- ...(await storageReadRolePermissions(-1)),
59
- ];
60
-
61
113
  if (!(await isLoginLicensed(req, `anonymous`))) {
62
114
  return { error: LOGIN_LIMIT_ERROR };
63
115
  }
@@ -75,7 +127,6 @@ class AnonymousProvider extends StorageProviderBase {
75
127
  const accessToken = jwt.sign(
76
128
  {
77
129
  amoid: this.amoid,
78
- permissions,
79
130
  licenseUid,
80
131
  },
81
132
  getTokenSecret(),
@@ -87,6 +138,30 @@ class AnonymousProvider extends StorageProviderBase {
87
138
  accessToken,
88
139
  };
89
140
  }
141
+
142
+ // @ts-ignore
143
+ async getCurrentPermissions(req) {
144
+ const permissions = await [
145
+ ...getPredefinedPermissions('anonymous-user'),
146
+ ...(await storageReadRolePermissions(-1)),
147
+ ];
148
+ return permissions;
149
+ }
150
+
151
+ async getCurrentDatabasePermissions(req) {
152
+ const databasePermissions = await readComplexRolePermissions(-1, 'role_databases');
153
+ return databasePermissions;
154
+ }
155
+
156
+ async getCurrentTablePermissions(req) {
157
+ const tablePermissions = await readComplexRolePermissions(-1, 'role_tables');
158
+ return tablePermissions;
159
+ }
160
+
161
+ async checkCurrentConnectionPermission(req, conid) {
162
+ const res = await storageCheckRoleConnectionAccess(-1, conid);
163
+ return res;
164
+ }
90
165
  }
91
166
 
92
167
  class LocalAuthProvider extends StorageProviderBase {
@@ -101,7 +176,6 @@ class LocalAuthProvider extends StorageProviderBase {
101
176
  const row = decryptUser(rows[0]);
102
177
  if (row.password == password) {
103
178
  const userId = row.id;
104
- const permissions = await loadPermissionsForUserId(userId);
105
179
 
106
180
  if (!(await isLoginLicensed(req, `local:${login}`))) {
107
181
  return { error: LOGIN_LIMIT_ERROR };
@@ -122,7 +196,6 @@ class LocalAuthProvider extends StorageProviderBase {
122
196
  {
123
197
  amoid: this.amoid,
124
198
  login,
125
- permissions,
126
199
  userId,
127
200
  licenseUid,
128
201
  },
@@ -198,7 +271,6 @@ class OauthProvider extends StorageProviderBase {
198
271
  : 'oauth';
199
272
 
200
273
  const loginRows = await storageSelectFmt('select * from ~users where ~login = %v', login);
201
- const permissions = await loadPermissionsForUserId(loginRows[0]?.id ?? -1);
202
274
 
203
275
  if (this.config.oauthOnlyDefinedLogins == 1 && loginRows.length == 0) {
204
276
  sendToAuditLog(req, {
@@ -264,7 +336,6 @@ class OauthProvider extends StorageProviderBase {
264
336
  {
265
337
  amoid: this.amoid,
266
338
  login,
267
- permissions,
268
339
  userId: loginRows[0]?.id,
269
340
  licenseUid,
270
341
  },
@@ -328,7 +399,6 @@ class ADProvider extends StorageProviderBase {
328
399
  }
329
400
 
330
401
  const loginRows = await storageSelectFmt('select * from ~users where ~login = %v', login);
331
- const permissions = await loadPermissionsForUserId(loginRows[0]?.id ?? -1);
332
402
 
333
403
  if (this.config.adOnlyDefinedLogins == 1) {
334
404
  if (loginRows.length == 0) {
@@ -355,8 +425,8 @@ class ADProvider extends StorageProviderBase {
355
425
  {
356
426
  amoid: this.amoid,
357
427
  login,
358
- permissions,
359
428
  licenseUid,
429
+ userId: loginRows[0]?.id ?? -1,
360
430
  },
361
431
  getTokenSecret(),
362
432
  { expiresIn: getTokenLifetime() }
@@ -421,7 +491,6 @@ class DatabaseProvider extends StorageProviderBase {
421
491
  return { error: 'Login not allowed', login };
422
492
  }
423
493
  const userId = rows[0]?.id;
424
- const permissions = await loadPermissionsForUserId(userId ?? -1);
425
494
 
426
495
  if (!(await isLoginLicensed(req, `db:${login}`))) {
427
496
  return { error: LOGIN_LIMIT_ERROR };
@@ -442,7 +511,6 @@ class DatabaseProvider extends StorageProviderBase {
442
511
  {
443
512
  amoid: this.amoid,
444
513
  login,
445
- permissions,
446
514
  userId,
447
515
  conid,
448
516
  licenseUid,
@@ -490,7 +558,6 @@ class MsEntraProvider extends StorageProviderBase {
490
558
  const { email } = payload;
491
559
 
492
560
  const loginRows = await storageSelectFmt('select * from ~users where ~email = %v', email);
493
- const permissions = await loadPermissionsForUserId(loginRows[0]?.id ?? -1);
494
561
 
495
562
  if (this.config.msentraOnlyDefinedLogins == 1) {
496
563
  if (loginRows.length == 0) {
@@ -527,7 +594,6 @@ class MsEntraProvider extends StorageProviderBase {
527
594
  const accessToken = jwt.sign(
528
595
  {
529
596
  amoid: this.amoid,
530
- permissions,
531
597
  msentraToken: token,
532
598
  userId: loginRows[0]?.id,
533
599
  login: payload.unique_name,
@@ -593,4 +659,5 @@ function createStorageAuthProvider(config) {
593
659
 
594
660
  module.exports = {
595
661
  createStorageAuthProvider,
662
+ SuperadminAuthProvider,
596
663
  };
@@ -51,6 +51,7 @@ function authMiddleware(req, res, next) {
51
51
  '/auth/oauth-token',
52
52
  '/auth/login',
53
53
  '/auth/redirect',
54
+ '/redirect',
54
55
  '/stream',
55
56
  '/storage/get-connections-for-login-page',
56
57
  '/storage/set-admin-password',
@@ -139,9 +140,9 @@ module.exports = {
139
140
  const accessToken = jwt.sign(
140
141
  {
141
142
  login: 'superadmin',
142
- permissions: await storage.loadSuperadminPermissions(),
143
143
  roleId: -3,
144
144
  licenseUid,
145
+ amoid: 'superadmin',
145
146
  },
146
147
  getTokenSecret(),
147
148
  {
@@ -3,7 +3,7 @@ const os = require('os');
3
3
  const path = require('path');
4
4
  const axios = require('axios');
5
5
  const { datadir, getLogsFilePath } = require('../utility/directories');
6
- const { hasPermission } = require('../utility/hasPermission');
6
+ const { hasPermission, loadPermissionsFromRequest } = require('../utility/hasPermission');
7
7
  const socket = require('../utility/socket');
8
8
  const _ = require('lodash');
9
9
  const AsyncLock = require('async-lock');
@@ -46,7 +46,7 @@ module.exports = {
46
46
  async get(_params, req) {
47
47
  const authProvider = getAuthProviderFromReq(req);
48
48
  const login = authProvider.getCurrentLogin(req);
49
- const permissions = authProvider.getCurrentPermissions(req);
49
+ const permissions = await authProvider.getCurrentPermissions(req);
50
50
  const isUserLoggedIn = authProvider.isUserLoggedIn(req);
51
51
 
52
52
  const singleConid = authProvider.getSingleConnectionId(req);
@@ -280,7 +280,8 @@ module.exports = {
280
280
 
281
281
  updateSettings_meta: true,
282
282
  async updateSettings(values, req) {
283
- if (!hasPermission(`settings/change`, req)) return false;
283
+ const loadedPermissions = await loadPermissionsFromRequest(req);
284
+ if (!hasPermission(`settings/change`, loadedPermissions)) return false;
284
285
  cachedSettingsValue = null;
285
286
 
286
287
  const res = await lock.acquire('settings', async () => {
@@ -392,7 +393,8 @@ module.exports = {
392
393
 
393
394
  exportConnectionsAndSettings_meta: true,
394
395
  async exportConnectionsAndSettings(_params, req) {
395
- if (!hasPermission(`admin/config`, req)) {
396
+ const loadedPermissions = await loadPermissionsFromRequest(req);
397
+ if (!hasPermission(`admin/config`, loadedPermissions)) {
396
398
  throw new Error('Permission denied: admin/config');
397
399
  }
398
400
 
@@ -416,7 +418,8 @@ module.exports = {
416
418
 
417
419
  importConnectionsAndSettings_meta: true,
418
420
  async importConnectionsAndSettings({ db }, req) {
419
- if (!hasPermission(`admin/config`, req)) {
421
+ const loadedPermissions = await loadPermissionsFromRequest(req);
422
+ if (!hasPermission(`admin/config`, loadedPermissions)) {
420
423
  throw new Error('Permission denied: admin/config');
421
424
  }
422
425
 
@@ -14,7 +14,7 @@ const JsonLinesDatabase = require('../utility/JsonLinesDatabase');
14
14
  const processArgs = require('../utility/processArgs');
15
15
  const { safeJsonParse, getLogger, extractErrorLogData } = require('dbgate-tools');
16
16
  const platformInfo = require('../utility/platformInfo');
17
- const { connectionHasPermission, testConnectionPermission } = require('../utility/hasPermission');
17
+ const { connectionHasPermission, testConnectionPermission, loadPermissionsFromRequest } = require('../utility/hasPermission');
18
18
  const pipeForkLogs = require('../utility/pipeForkLogs');
19
19
  const requireEngineDriver = require('../utility/requireEngineDriver');
20
20
  const { getAuthProviderById } = require('../auth/authProvider');
@@ -227,6 +227,7 @@ module.exports = {
227
227
  list_meta: true,
228
228
  async list(_params, req) {
229
229
  const storage = require('./storage');
230
+ const loadedPermissions = await loadPermissionsFromRequest(req);
230
231
 
231
232
  const storageConnections = await storage.connections(req);
232
233
  if (storageConnections) {
@@ -234,9 +235,9 @@ module.exports = {
234
235
  }
235
236
  if (portalConnections) {
236
237
  if (platformInfo.allowShellConnection) return portalConnections;
237
- return portalConnections.map(maskConnection).filter(x => connectionHasPermission(x, req));
238
+ return portalConnections.map(maskConnection).filter(x => connectionHasPermission(x, loadedPermissions));
238
239
  }
239
- return (await this.datastore.find()).filter(x => connectionHasPermission(x, req));
240
+ return (await this.datastore.find()).filter(x => connectionHasPermission(x, loadedPermissions));
240
241
  },
241
242
 
242
243
  async getUsedEngines() {
@@ -375,7 +376,7 @@ module.exports = {
375
376
  update_meta: true,
376
377
  async update({ _id, values }, req) {
377
378
  if (portalConnections) return;
378
- testConnectionPermission(_id, req);
379
+ await testConnectionPermission(_id, req);
379
380
  const res = await this.datastore.patch(_id, values);
380
381
  socket.emitChanged('connection-list-changed');
381
382
  return res;
@@ -392,7 +393,7 @@ module.exports = {
392
393
  updateDatabase_meta: true,
393
394
  async updateDatabase({ conid, database, values }, req) {
394
395
  if (portalConnections) return;
395
- testConnectionPermission(conid, req);
396
+ await testConnectionPermission(conid, req);
396
397
  const conn = await this.datastore.get(conid);
397
398
  let databases = (conn && conn.databases) || [];
398
399
  if (databases.find(x => x.name == database)) {
@@ -410,7 +411,7 @@ module.exports = {
410
411
  delete_meta: true,
411
412
  async delete(connection, req) {
412
413
  if (portalConnections) return;
413
- testConnectionPermission(connection, req);
414
+ await testConnectionPermission(connection, req);
414
415
  const res = await this.datastore.remove(connection._id);
415
416
  socket.emitChanged('connection-list-changed');
416
417
  return res;
@@ -452,7 +453,7 @@ module.exports = {
452
453
  _id: '__model',
453
454
  };
454
455
  }
455
- testConnectionPermission(conid, req);
456
+ await testConnectionPermission(conid, req);
456
457
  return this.getCore({ conid, mask: true });
457
458
  },
458
459