dbgate-api 4.7.3 → 4.7.4-alpha.12

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/src/main.js CHANGED
@@ -29,6 +29,8 @@ const queryHistory = require('./controllers/queryHistory');
29
29
  const { rundir } = require('./utility/directories');
30
30
  const platformInfo = require('./utility/platformInfo');
31
31
  const getExpressPath = require('./utility/getExpressPath');
32
+ const { getLogins } = require('./utility/hasPermission');
33
+ const _ = require('lodash');
32
34
 
33
35
  function start() {
34
36
  // console.log('process.argv', process.argv);
@@ -37,12 +39,11 @@ function start() {
37
39
 
38
40
  const server = http.createServer(app);
39
41
 
40
- if (process.env.LOGIN && process.env.PASSWORD) {
42
+ const logins = getLogins();
43
+ if (logins) {
41
44
  app.use(
42
45
  basicAuth({
43
- users: {
44
- [process.env.LOGIN]: process.env.PASSWORD,
45
- },
46
+ users: _.fromPairs(logins.map(x => [x.login, x.password])),
46
47
  challenge: true,
47
48
  realm: 'DbGate Web App',
48
49
  })
@@ -85,15 +86,11 @@ function start() {
85
86
  if (platformInfo.isDocker) {
86
87
  // server static files inside docker container
87
88
  app.use(getExpressPath('/'), express.static('/home/dbgate-docker/public'));
88
- } else {
89
- if (!platformInfo.isNpmDist) {
90
- app.get(getExpressPath('/'), (req, res) => {
91
- res.send('DbGate API');
92
- });
93
- }
94
- }
95
89
 
96
- if (platformInfo.isNpmDist) {
90
+ const port = process.env.PORT || 3000;
91
+ console.log('DbGate API listening on port', port);
92
+ server.listen(port);
93
+ } else if (platformInfo.isNpmDist) {
97
94
  app.use(getExpressPath('/'), express.static(path.join(__dirname, '../../dbgate-web/public')));
98
95
  getPort({
99
96
  port: parseInt(
@@ -105,7 +102,19 @@ function start() {
105
102
  console.log(`DbGate API listening on port ${port}`);
106
103
  });
107
104
  });
105
+ } else if (process.env.DEVWEB) {
106
+ console.log('__dirname', __dirname);
107
+ console.log(path.join(__dirname, '../../web/public/build'));
108
+ app.use(getExpressPath('/'), express.static(path.join(__dirname, '../../web/public')));
109
+
110
+ const port = process.env.PORT || 3000;
111
+ console.log('DbGate API & web listening on port', port);
112
+ server.listen(port);
108
113
  } else {
114
+ app.get(getExpressPath('/'), (req, res) => {
115
+ res.send('DbGate API');
116
+ });
117
+
109
118
  const port = process.env.PORT || 3000;
110
119
  console.log('DbGate API listening on port', port);
111
120
  server.listen(port);
@@ -20,7 +20,7 @@ function start() {
20
20
  if (handleProcessCommunication(connection)) return;
21
21
  try {
22
22
  const driver = requireEngineDriver(connection);
23
- const conn = await connectUtility(driver, connection);
23
+ const conn = await connectUtility(driver, connection, 'app');
24
24
  const res = await driver.getVersion(conn);
25
25
  process.send({ msgtype: 'connected', ...res });
26
26
  } catch (e) {
@@ -7,6 +7,7 @@ const connectUtility = require('../utility/connectUtility');
7
7
  const { handleProcessCommunication } = require('../utility/processComm');
8
8
  const { SqlGenerator } = require('dbgate-tools');
9
9
  const generateDeploySql = require('../shell/generateDeploySql');
10
+ const { dumpSqlSelect } = require('dbgate-sqltree');
10
11
 
11
12
  let systemConnection;
12
13
  let storedConnection;
@@ -107,7 +108,7 @@ async function handleConnect({ connection, structure, globalSettings }) {
107
108
 
108
109
  if (!structure) setStatusName('pending');
109
110
  const driver = requireEngineDriver(storedConnection);
110
- systemConnection = await checkedAsyncCall(connectUtility(driver, storedConnection));
111
+ systemConnection = await checkedAsyncCall(connectUtility(driver, storedConnection, 'app'));
111
112
  await checkedAsyncCall(readVersion());
112
113
  if (structure) {
113
114
  analysedStructure = structure;
@@ -154,6 +155,7 @@ async function handleRunScript({ msgid, sql }) {
154
155
  await waitConnected();
155
156
  const driver = requireEngineDriver(storedConnection);
156
157
  try {
158
+ ensureExecuteCustomScript(driver);
157
159
  await driver.script(systemConnection, sql);
158
160
  process.send({ msgtype: 'response', msgid });
159
161
  } catch (err) {
@@ -165,6 +167,7 @@ async function handleQueryData({ msgid, sql }) {
165
167
  await waitConnected();
166
168
  const driver = requireEngineDriver(storedConnection);
167
169
  try {
170
+ ensureExecuteCustomScript(driver);
168
171
  const res = await driver.query(systemConnection, sql);
169
172
  process.send({ msgtype: 'response', msgid, ...res });
170
173
  } catch (err) {
@@ -172,21 +175,67 @@ async function handleQueryData({ msgid, sql }) {
172
175
  }
173
176
  }
174
177
 
175
- async function handleCollectionData({ msgid, options }) {
178
+ async function handleSqlSelect({ msgid, select }) {
179
+ const driver = requireEngineDriver(storedConnection);
180
+ const dmp = driver.createDumper();
181
+ dumpSqlSelect(dmp, select);
182
+ return handleQueryData({ msgid, sql: dmp.s });
183
+ }
184
+
185
+ async function handleDriverDataCore(msgid, callMethod) {
176
186
  await waitConnected();
177
187
  const driver = requireEngineDriver(storedConnection);
178
188
  try {
179
- const result = await driver.readCollection(systemConnection, options);
189
+ const result = await callMethod(driver);
180
190
  process.send({ msgtype: 'response', msgid, result });
181
191
  } catch (err) {
182
192
  process.send({ msgtype: 'response', msgid, errorMessage: err.message });
183
193
  }
184
194
  }
185
195
 
196
+ async function handleCollectionData({ msgid, options }) {
197
+ return handleDriverDataCore(msgid, driver => driver.readCollection(systemConnection, options));
198
+ }
199
+
200
+ async function handleLoadKeys({ msgid, root }) {
201
+ return handleDriverDataCore(msgid, driver => driver.loadKeys(systemConnection, root));
202
+ }
203
+
204
+ async function handleLoadKeyInfo({ msgid, key }) {
205
+ return handleDriverDataCore(msgid, driver => driver.loadKeyInfo(systemConnection, key));
206
+ }
207
+
208
+ async function handleCallMethod({ msgid, method, args }) {
209
+ return handleDriverDataCore(msgid, driver => {
210
+ ensureExecuteCustomScript(driver);
211
+ return driver.callMethod(systemConnection, method, args);
212
+ });
213
+ }
214
+
215
+ async function handleLoadKeyTableRange({ msgid, key, cursor, count }) {
216
+ return handleDriverDataCore(msgid, driver => driver.loadKeyTableRange(systemConnection, key, cursor, count));
217
+ }
218
+
219
+ async function handleLoadFieldValues({ msgid, schemaName, pureName, field, search }) {
220
+ return handleDriverDataCore(msgid, driver =>
221
+ driver.loadFieldValues(systemConnection, { schemaName, pureName }, field, search)
222
+ );
223
+ }
224
+
225
+ function ensureExecuteCustomScript(driver) {
226
+ if (driver.readOnlySessions) {
227
+ return;
228
+ }
229
+ if (storedConnection.isReadOnly) {
230
+ throw new Error('Connection is read only');
231
+ }
232
+ }
233
+
186
234
  async function handleUpdateCollection({ msgid, changeSet }) {
187
235
  await waitConnected();
188
236
  const driver = requireEngineDriver(storedConnection);
189
237
  try {
238
+ ensureExecuteCustomScript(driver);
190
239
  const result = await driver.updateCollection(systemConnection, changeSet);
191
240
  process.send({ msgtype: 'response', msgid, result });
192
241
  } catch (err) {
@@ -248,10 +297,16 @@ const messageHandlers = {
248
297
  runScript: handleRunScript,
249
298
  updateCollection: handleUpdateCollection,
250
299
  collectionData: handleCollectionData,
300
+ loadKeys: handleLoadKeys,
301
+ loadKeyInfo: handleLoadKeyInfo,
302
+ callMethod: handleCallMethod,
303
+ loadKeyTableRange: handleLoadKeyTableRange,
251
304
  sqlPreview: handleSqlPreview,
252
305
  ping: handlePing,
253
306
  syncModel: handleSyncModel,
254
307
  generateDeploySql: handleGenerateDeploySql,
308
+ loadFieldValues: handleLoadFieldValues,
309
+ sqlSelect: handleSqlSelect,
255
310
  // runCommand: handleRunCommand,
256
311
  };
257
312
 
@@ -58,11 +58,14 @@ async function handleConnect(connection) {
58
58
 
59
59
  const driver = requireEngineDriver(storedConnection);
60
60
  try {
61
- systemConnection = await connectUtility(driver, storedConnection);
61
+ systemConnection = await connectUtility(driver, storedConnection, 'app');
62
62
  readVersion();
63
63
  handleRefresh();
64
64
  if (extractBoolSettingsValue(globalSettings, 'connection.autoRefresh', false)) {
65
- setInterval(handleRefresh, extractIntSettingsValue(globalSettings, 'connection.autoRefreshInterval', 30, 5, 3600) * 1000);
65
+ setInterval(
66
+ handleRefresh,
67
+ extractIntSettingsValue(globalSettings, 'connection.autoRefreshInterval', 30, 5, 3600) * 1000
68
+ );
66
69
  }
67
70
  } catch (err) {
68
71
  setStatus({
@@ -80,7 +83,7 @@ function handlePing() {
80
83
 
81
84
  async function handleCreateDatabase({ name }) {
82
85
  const driver = requireEngineDriver(storedConnection);
83
- systemConnection = await connectUtility(driver, storedConnection);
86
+ systemConnection = await connectUtility(driver, storedConnection, 'app');
84
87
  console.log(`RUNNING SCRIPT: CREATE DATABASE ${driver.dialect.quoteIdentifier(name)}`);
85
88
  if (driver.createDatabase) {
86
89
  await driver.createDatabase(systemConnection, name);
@@ -17,11 +17,15 @@ let afterConnectCallbacks = [];
17
17
  // let currentHandlers = [];
18
18
 
19
19
  class TableWriter {
20
- constructor(structure, resultIndex) {
21
- this.jslid = uuidv1();
22
- this.currentFile = path.join(jsldir(), `${this.jslid}.jsonl`);
20
+ constructor() {
23
21
  this.currentRowCount = 0;
24
22
  this.currentChangeIndex = 1;
23
+ this.initializedFile = false;
24
+ }
25
+
26
+ initializeFromQuery(structure, resultIndex) {
27
+ this.jslid = uuidv1();
28
+ this.currentFile = path.join(jsldir(), `${this.jslid}.jsonl`);
25
29
  fs.writeFileSync(
26
30
  this.currentFile,
27
31
  JSON.stringify({
@@ -32,13 +36,21 @@ class TableWriter {
32
36
  this.currentStream = fs.createWriteStream(this.currentFile, { flags: 'a' });
33
37
  this.writeCurrentStats(false, false);
34
38
  this.resultIndex = resultIndex;
39
+ this.initializedFile = true;
35
40
  process.send({ msgtype: 'recordset', jslid: this.jslid, resultIndex });
36
41
  }
37
42
 
43
+ initializeFromReader(jslid) {
44
+ this.jslid = jslid;
45
+ this.currentFile = path.join(jsldir(), `${this.jslid}.jsonl`);
46
+ this.writeCurrentStats(false, false);
47
+ }
48
+
38
49
  row(row) {
39
50
  // console.log('ACCEPT ROW', row);
40
51
  this.currentStream.write(JSON.stringify(row) + '\n');
41
52
  this.currentRowCount += 1;
53
+
42
54
  if (!this.plannedStats) {
43
55
  this.plannedStats = true;
44
56
  process.nextTick(() => {
@@ -49,6 +61,21 @@ class TableWriter {
49
61
  }
50
62
  }
51
63
 
64
+ rowFromReader(row) {
65
+ if (!this.initializedFile) {
66
+ process.send({ msgtype: 'initializeFile', jslid: this.jslid });
67
+ this.initializedFile = true;
68
+
69
+ fs.writeFileSync(this.currentFile, JSON.stringify(row) + '\n');
70
+ this.currentStream = fs.createWriteStream(this.currentFile, { flags: 'a' });
71
+ this.writeCurrentStats(false, false);
72
+ this.initializedFile = true;
73
+ return;
74
+ }
75
+
76
+ this.row(row);
77
+ }
78
+
52
79
  writeCurrentStats(isFinished = false, emitEvent = false) {
53
80
  const stats = {
54
81
  rowCount: this.currentRowCount,
@@ -63,10 +90,11 @@ class TableWriter {
63
90
  }
64
91
  }
65
92
 
66
- close() {
93
+ close(afterClose) {
67
94
  if (this.currentStream) {
68
95
  this.currentStream.end(() => {
69
96
  this.writeCurrentStats(true, true);
97
+ if (afterClose) afterClose();
70
98
  });
71
99
  }
72
100
  }
@@ -98,7 +126,11 @@ class StreamHandler {
98
126
 
99
127
  recordset(columns) {
100
128
  this.closeCurrentWriter();
101
- this.currentWriter = new TableWriter(Array.isArray(columns) ? { columns } : columns, this.resultIndexHolder.value);
129
+ this.currentWriter = new TableWriter();
130
+ this.currentWriter.initializeFromQuery(
131
+ Array.isArray(columns) ? { columns } : columns,
132
+ this.resultIndexHolder.value
133
+ );
102
134
  this.resultIndexHolder.value += 1;
103
135
 
104
136
  // this.writeCurrentStats();
@@ -110,7 +142,6 @@ class StreamHandler {
110
142
  // }, 500);
111
143
  }
112
144
  row(row) {
113
- // console.log('ACCEPT ROW', row);
114
145
  if (this.currentWriter) this.currentWriter.row(row);
115
146
  else if (row.message) process.send({ msgtype: 'info', info: { message: row.message } });
116
147
  // this.onRow(this.jslid);
@@ -135,11 +166,22 @@ function handleStream(driver, resultIndexHolder, sql) {
135
166
  });
136
167
  }
137
168
 
169
+ function allowExecuteCustomScript(driver) {
170
+ if (driver.readOnlySessions) {
171
+ return true;
172
+ }
173
+ if (storedConnection.isReadOnly) {
174
+ return false;
175
+ // throw new Error('Connection is read only');
176
+ }
177
+ return true;
178
+ }
179
+
138
180
  async function handleConnect(connection) {
139
181
  storedConnection = connection;
140
182
 
141
183
  const driver = requireEngineDriver(storedConnection);
142
- systemConnection = await connectUtility(driver, storedConnection);
184
+ systemConnection = await connectUtility(driver, storedConnection, 'app');
143
185
  for (const [resolve] of afterConnectCallbacks) {
144
186
  resolve();
145
187
  }
@@ -163,6 +205,19 @@ async function handleExecuteQuery({ sql }) {
163
205
  await waitConnected();
164
206
  const driver = requireEngineDriver(storedConnection);
165
207
 
208
+ if (!allowExecuteCustomScript(driver)) {
209
+ process.send({
210
+ msgtype: 'info',
211
+ info: {
212
+ message: 'Connection without read-only sessions is read only',
213
+ severity: 'error',
214
+ },
215
+ });
216
+ process.send({ msgtype: 'done', skipFinishedMessage: true });
217
+ return;
218
+ //process.send({ msgtype: 'error', error: e.message });
219
+ }
220
+
166
221
  const resultIndexHolder = {
167
222
  value: 0,
168
223
  };
@@ -176,9 +231,39 @@ async function handleExecuteQuery({ sql }) {
176
231
  process.send({ msgtype: 'done' });
177
232
  }
178
233
 
234
+ async function handleExecuteReader({ jslid, sql, fileName }) {
235
+ await waitConnected();
236
+
237
+ const driver = requireEngineDriver(storedConnection);
238
+
239
+ if (fileName) {
240
+ sql = fs.readFileSync(fileName, 'utf-8');
241
+ } else {
242
+ if (!allowExecuteCustomScript(driver)) {
243
+ process.send({ msgtype: 'done' });
244
+ return;
245
+ }
246
+ }
247
+
248
+ const writer = new TableWriter();
249
+ writer.initializeFromReader(jslid);
250
+
251
+ const reader = await driver.readQuery(systemConnection, sql);
252
+
253
+ reader.on('data', data => {
254
+ writer.rowFromReader(data);
255
+ });
256
+ reader.on('end', () => {
257
+ writer.close(() => {
258
+ process.send({ msgtype: 'done' });
259
+ });
260
+ });
261
+ }
262
+
179
263
  const messageHandlers = {
180
264
  connect: handleConnect,
181
265
  executeQuery: handleExecuteQuery,
266
+ executeReader: handleExecuteReader,
182
267
  // cancel: handleCancel,
183
268
  };
184
269
 
@@ -5,7 +5,7 @@ async function executeQuery({ connection = undefined, systemConnection = undefin
5
5
  console.log(`Execute query ${sql}`);
6
6
 
7
7
  if (!driver) driver = requireEngineDriver(connection);
8
- const pool = systemConnection || (await connectUtility(driver, connection));
8
+ const pool = systemConnection || (await connectUtility(driver, connection, 'script'));
9
9
  console.log(`Connected.`);
10
10
 
11
11
  await driver.script(pool, sql);
@@ -21,7 +21,7 @@ async function generateDeploySql({
21
21
  }) {
22
22
  if (!driver) driver = requireEngineDriver(connection);
23
23
 
24
- const pool = systemConnection || (await connectUtility(driver, connection));
24
+ const pool = systemConnection || (await connectUtility(driver, connection, 'read'));
25
25
  if (!analysedStructure) {
26
26
  analysedStructure = await driver.analyseFull(pool);
27
27
  }
@@ -1,14 +1,26 @@
1
1
  const requireEngineDriver = require('../utility/requireEngineDriver');
2
- const { decryptConnection } = require('../utility/crypting');
3
2
  const connectUtility = require('../utility/connectUtility');
4
3
 
5
- async function queryReader({ connection, sql }) {
6
- console.log(`Reading query ${sql}`);
4
+ async function queryReader({
5
+ connection,
6
+ query,
7
+ queryType,
8
+ // obsolete; use query instead
9
+ sql,
10
+ }) {
11
+ // if (sql && json) {
12
+ // throw new Error('Only one of sql or json could be set');
13
+ // }
14
+ // if (!sql && !json) {
15
+ // throw new Error('One of sql or json must be set');
16
+ // }
17
+ console.log(`Reading query ${query || sql}`);
18
+ // else console.log(`Reading query ${JSON.stringify(json)}`);
7
19
 
8
20
  const driver = requireEngineDriver(connection);
9
- const pool = await connectUtility(driver, connection);
21
+ const pool = await connectUtility(driver, connection, queryType == 'json' ? 'read' : 'script');
10
22
  console.log(`Connected.`);
11
- return await driver.readQuery(pool, sql);
23
+ return queryType == 'json' ? await driver.readJsonQuery(pool, query) : await driver.readQuery(pool, query || sql);
12
24
  }
13
25
 
14
26
  module.exports = queryReader;
@@ -4,12 +4,12 @@ const connectUtility = require('../utility/connectUtility');
4
4
 
5
5
  async function tableReader({ connection, pureName, schemaName }) {
6
6
  const driver = requireEngineDriver(connection);
7
- const pool = await connectUtility(driver, connection);
7
+ const pool = await connectUtility(driver, connection, 'read');
8
8
  console.log(`Connected.`);
9
9
 
10
10
  const fullName = { pureName, schemaName };
11
11
 
12
- if (driver.dialect.nosql) {
12
+ if (driver.databaseEngineTypes.includes('document')) {
13
13
  // @ts-ignore
14
14
  console.log(`Reading collection ${fullNameToString(fullName)}`);
15
15
  // @ts-ignore
@@ -8,7 +8,7 @@ async function tableWriter({ connection, schemaName, pureName, driver, systemCon
8
8
  if (!driver) {
9
9
  driver = requireEngineDriver(connection);
10
10
  }
11
- const pool = systemConnection || (await connectUtility(driver, connection));
11
+ const pool = systemConnection || (await connectUtility(driver, connection, 'write'));
12
12
 
13
13
  console.log(`Connected.`);
14
14
  return await driver.writeTable(pool, { schemaName, pureName }, options);
@@ -4,11 +4,47 @@ const fs = require('fs-extra');
4
4
  const { decryptConnection } = require('./crypting');
5
5
  const { getSshTunnel } = require('./sshTunnel');
6
6
  const { getSshTunnelProxy } = require('./sshTunnelProxy');
7
+ const platformInfo = require('../utility/platformInfo');
8
+ const connections = require('../controllers/connections');
9
+
10
+ async function loadConnection(driver, storedConnection, connectionMode) {
11
+ const { allowShellConnection } = platformInfo;
12
+
13
+ if (connectionMode == 'app') {
14
+ return storedConnection;
15
+ }
16
+
17
+ if (storedConnection._id || !allowShellConnection) {
18
+ if (!storedConnection._id) {
19
+ throw new Error('Missing connection _id');
20
+ }
21
+
22
+ await connections._init();
23
+ const loaded = await connections.getCore({ conid: storedConnection._id });
24
+ const loadedWithDb = {
25
+ ...loaded,
26
+ database: storedConnection.database,
27
+ };
28
+
29
+ if (loaded.isReadOnly) {
30
+ if (connectionMode == 'read') return loadedWithDb;
31
+ if (connectionMode == 'write') throw new Error('Cannot write readonly connection');
32
+ if (connectionMode == 'script') {
33
+ if (driver.readOnlySessions) return loadedWithDb;
34
+ throw new Error('Cannot write readonly connection');
35
+ }
36
+ }
37
+ return loadedWithDb;
38
+ }
39
+ return storedConnection;
40
+ }
41
+
42
+ async function connectUtility(driver, storedConnection, connectionMode) {
43
+ const connectionLoaded = await loadConnection(driver, storedConnection, connectionMode);
7
44
 
8
- async function connectUtility(driver, storedConnection) {
9
45
  const connection = {
10
- database: storedConnection.defaultDatabase,
11
- ...decryptConnection(storedConnection),
46
+ database: connectionLoaded.defaultDatabase,
47
+ ...decryptConnection(connectionLoaded),
12
48
  };
13
49
 
14
50
  if (!connection.port && driver.defaultPort) connection.port = driver.defaultPort.toString();
@@ -55,7 +55,7 @@ function encryptPasswordField(connection, field) {
55
55
  [field]: 'crypt:' + getEncryptor().encrypt(connection[field]),
56
56
  };
57
57
  }
58
- return connection;
58
+ return connection;
59
59
  }
60
60
 
61
61
  function decryptPasswordField(connection, field) {
@@ -75,6 +75,11 @@ function encryptConnection(connection) {
75
75
  return connection;
76
76
  }
77
77
 
78
+ function maskConnection(connection) {
79
+ if (!connection) return connection;
80
+ return _.omit(connection, ['password', 'sshPassword', 'sshKeyfilePassword']);
81
+ }
82
+
78
83
  function decryptConnection(connection) {
79
84
  connection = decryptPasswordField(connection, 'password');
80
85
  connection = decryptPasswordField(connection, 'sshPassword');
@@ -95,5 +100,6 @@ module.exports = {
95
100
  loadEncryptionKey,
96
101
  encryptConnection,
97
102
  decryptConnection,
103
+ maskConnection,
98
104
  pickSafeConnectionInfo,
99
105
  };
@@ -54,7 +54,7 @@ function packagedPluginsDir() {
54
54
  }
55
55
  if (platformInfo.isNpmDist) {
56
56
  // node_modules
57
- return global['dbgateApiPackagedPluginsPath'];
57
+ return global['PLUGINS_DIR'];
58
58
  }
59
59
  if (platformInfo.isElectronBundle) {
60
60
  return path.resolve(__dirname, '../../plugins');
@@ -1,12 +1,56 @@
1
1
  const { compilePermissions, testPermission } = require('dbgate-tools');
2
+ const _ = require('lodash');
2
3
 
3
- let compiled = undefined;
4
+ const userPermissions = {};
4
5
 
5
- function hasPermission(tested) {
6
- if (compiled === undefined) {
7
- compiled = compilePermissions(process.env.PERMISSIONS);
6
+ function hasPermission(tested, req) {
7
+ const { user } = (req && req.auth) || {};
8
+ const key = user || '';
9
+ const logins = getLogins();
10
+ if (!userPermissions[key] && logins) {
11
+ const login = logins.find(x => x.login == user);
12
+ userPermissions[key] = compilePermissions(login ? login.permissions : null);
8
13
  }
9
- return testPermission(tested, compiled);
14
+ return testPermission(tested, userPermissions[key]);
10
15
  }
11
16
 
12
- module.exports = hasPermission;
17
+ let loginsCache = null;
18
+ let loginsLoaded = false;
19
+
20
+ function getLogins() {
21
+ if (loginsLoaded) {
22
+ return loginsCache;
23
+ }
24
+
25
+ const res = [];
26
+ if (process.env.LOGIN && process.env.PASSWORD) {
27
+ res.push({
28
+ login: process.env.LOGIN,
29
+ password: process.env.PASSWORD,
30
+ permissions: process.env.PERMISSIONS,
31
+ });
32
+ }
33
+ if (process.env.LOGINS) {
34
+ const logins = _.compact(process.env.LOGINS.split(',').map(x => x.trim()));
35
+ for (const login of logins) {
36
+ const password = process.env[`LOGIN_PASSWORD_${login}`];
37
+ const permissions = process.env[`LOGIN_PERMISSIONS_${login}`];
38
+ if (password) {
39
+ res.push({
40
+ login,
41
+ password,
42
+ permissions,
43
+ });
44
+ }
45
+ }
46
+ }
47
+
48
+ loginsCache = res.length > 0 ? res : null;
49
+ loginsLoaded = true;
50
+ return loginsCache;
51
+ }
52
+
53
+ module.exports = {
54
+ hasPermission,
55
+ getLogins,
56
+ };
@@ -10,7 +10,7 @@ const isMac = platform === 'darwin';
10
10
  const isLinux = platform === 'linux';
11
11
  const isDocker = fs.existsSync('/home/dbgate-docker/public');
12
12
  const isDevMode = process.env.DEVMODE == '1';
13
- const isNpmDist = !!global['dbgateApiModulePath'];
13
+ const isNpmDist = !!global['IS_NPM_DIST'];
14
14
  const isForkedApi = processArgs.isForkedApi;
15
15
 
16
16
  // function moduleAvailable(name) {
@@ -39,6 +39,8 @@ const platformInfo = {
39
39
  environment: process.env.NODE_ENV,
40
40
  platform,
41
41
  runningInWebpack: !!process.env.WEBPACK_DEV_SERVER_URL,
42
+ allowShellConnection: !!process.env.SHELL_CONNECTION || !!isElectron(),
43
+ allowShellScripting: !!process.env.SHELL_SCRIPTING || !!isElectron(),
42
44
  defaultKeyfile: path.join(os.homedir(), '.ssh/id_rsa'),
43
45
  };
44
46
 
@@ -62,7 +62,7 @@ module.exports = function useController(app, electron, route, controller) {
62
62
  // controller._init_called = true;
63
63
  // }
64
64
  try {
65
- let params = [{ ...req.body, ...req.query }];
65
+ let params = [{ ...req.body, ...req.query }, req];
66
66
  if (rawParams) params = [req, res];
67
67
  const data = await controller[key](...params);
68
68
  res.json(data);