dbgate-api-premium 6.6.3 → 6.6.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.
@@ -1,233 +1,99 @@
1
1
  const fs = require('fs-extra');
2
2
  const _ = require('lodash');
3
3
  const path = require('path');
4
- const { appdir } = require('../utility/directories');
4
+ const { appdir, filesdir } = require('../utility/directories');
5
5
  const socket = require('../utility/socket');
6
6
  const connections = require('./connections');
7
+ const {
8
+ loadPermissionsFromRequest,
9
+ loadFilePermissionsFromRequest,
10
+ hasPermission,
11
+ getFilePermissionRole,
12
+ } = require('../utility/hasPermission');
7
13
 
8
14
  module.exports = {
9
- folders_meta: true,
10
- async folders() {
11
- const folders = await fs.readdir(appdir());
12
- return [
13
- ...folders.map(name => ({
14
- name,
15
- })),
16
- ];
17
- },
18
-
19
- createFolder_meta: true,
20
- async createFolder({ folder }) {
21
- const name = await this.getNewAppFolder({ name: folder });
22
- await fs.mkdir(path.join(appdir(), name));
23
- socket.emitChanged('app-folders-changed');
24
- this.emitChangedDbApp(folder);
25
- return name;
26
- },
27
-
28
- files_meta: true,
29
- async files({ folder }) {
30
- if (!folder) return [];
31
- const dir = path.join(appdir(), folder);
15
+ getAllApps_meta: true,
16
+ async getAllApps({}, req) {
17
+ const dir = path.join(filesdir(), 'apps');
32
18
  if (!(await fs.exists(dir))) return [];
33
- const files = await fs.readdir(dir);
34
-
35
- function fileType(ext, type) {
36
- return files
37
- .filter(name => name.endsWith(ext))
38
- .map(name => ({
39
- name: name.slice(0, -ext.length),
40
- label: path.parse(name.slice(0, -ext.length)).base,
41
- type,
42
- }));
43
- }
44
-
45
- return [
46
- ...fileType('.command.sql', 'command.sql'),
47
- ...fileType('.query.sql', 'query.sql'),
48
- ...fileType('.config.json', 'config.json'),
49
- ];
50
- },
51
-
52
- async emitChangedDbApp(folder) {
53
- const used = await this.getUsedAppFolders();
54
- if (used.includes(folder)) {
55
- socket.emitChanged('used-apps-changed');
56
- }
57
- },
58
-
59
- refreshFiles_meta: true,
60
- async refreshFiles({ folder }) {
61
- socket.emitChanged('app-files-changed', { app: folder });
62
- },
63
-
64
- refreshFolders_meta: true,
65
- async refreshFolders() {
66
- socket.emitChanged(`app-folders-changed`);
67
- },
68
-
69
- deleteFile_meta: true,
70
- async deleteFile({ folder, file, fileType }) {
71
- await fs.unlink(path.join(appdir(), folder, `${file}.${fileType}`));
72
- socket.emitChanged('app-files-changed', { app: folder });
73
- this.emitChangedDbApp(folder);
74
- },
75
-
76
- renameFile_meta: true,
77
- async renameFile({ folder, file, newFile, fileType }) {
78
- await fs.rename(
79
- path.join(path.join(appdir(), folder), `${file}.${fileType}`),
80
- path.join(path.join(appdir(), folder), `${newFile}.${fileType}`)
81
- );
82
- socket.emitChanged('app-files-changed', { app: folder });
83
- this.emitChangedDbApp(folder);
84
- },
85
-
86
- renameFolder_meta: true,
87
- async renameFolder({ folder, newFolder }) {
88
- const uniqueName = await this.getNewAppFolder({ name: newFolder });
89
- await fs.rename(path.join(appdir(), folder), path.join(appdir(), uniqueName));
90
- socket.emitChanged(`app-folders-changed`);
91
- },
92
-
93
- deleteFolder_meta: true,
94
- async deleteFolder({ folder }) {
95
- if (!folder) throw new Error('Missing folder parameter');
96
- await fs.rmdir(path.join(appdir(), folder), { recursive: true });
97
- socket.emitChanged(`app-folders-changed`);
98
- socket.emitChanged('app-files-changed', { app: folder });
99
- socket.emitChanged('used-apps-changed');
100
- },
101
-
102
- async getNewAppFolder({ name }) {
103
- if (!(await fs.exists(path.join(appdir(), name)))) return name;
104
- let index = 2;
105
- while (await fs.exists(path.join(appdir(), `${name}${index}`))) {
106
- index += 1;
107
- }
108
- return `${name}${index}`;
109
- },
110
-
111
- getUsedAppFolders_meta: true,
112
- async getUsedAppFolders() {
113
- const list = await connections.list();
114
- const apps = [];
115
-
116
- for (const connection of list) {
117
- for (const db of connection.databases || []) {
118
- for (const key of _.keys(db || {})) {
119
- if (key.startsWith('useApp:') && db[key]) {
120
- apps.push(key.substring('useApp:'.length));
121
- }
122
- }
123
- }
124
- }
125
-
126
- return _.intersection(_.uniq(apps), await fs.readdir(appdir()));
127
- },
128
-
129
- getUsedApps_meta: true,
130
- async getUsedApps() {
131
- const apps = await this.getUsedAppFolders();
132
19
  const res = [];
20
+ const loadedPermissions = await loadPermissionsFromRequest(req);
21
+ const filePermissions = await loadFilePermissionsFromRequest(req);
133
22
 
134
- for (const folder of apps) {
135
- res.push(await this.loadApp({ folder }));
136
- }
137
- return res;
138
- },
139
-
140
- // getAppsForDb_meta: true,
141
- // async getAppsForDb({ conid, database }) {
142
- // const connection = await connections.get({ conid });
143
- // if (!connection) return [];
144
- // const db = (connection.databases || []).find(x => x.name == database);
145
- // const apps = [];
146
- // const res = [];
147
- // if (db) {
148
- // for (const key of _.keys(db || {})) {
149
- // if (key.startsWith('useApp:') && db[key]) {
150
- // apps.push(key.substring('useApp:'.length));
151
- // }
152
- // }
153
- // }
154
- // for (const folder of apps) {
155
- // res.push(await this.loadApp({ folder }));
156
- // }
157
- // return res;
158
- // },
159
-
160
- loadApp_meta: true,
161
- async loadApp({ folder }) {
162
- const res = {
163
- queries: [],
164
- commands: [],
165
- name: folder,
166
- };
167
- const dir = path.join(appdir(), folder);
168
- if (await fs.exists(dir)) {
169
- const files = await fs.readdir(dir);
170
-
171
- async function processType(ext, field) {
172
- for (const file of files) {
173
- if (file.endsWith(ext)) {
174
- res[field].push({
175
- name: file.slice(0, -ext.length),
176
- sql: await fs.readFile(path.join(dir, file), { encoding: 'utf-8' }),
177
- });
178
- }
179
- }
23
+ for (const file of await fs.readdir(dir)) {
24
+ if (!hasPermission(`all-disk-files`, loadedPermissions)) {
25
+ const role = getFilePermissionRole('apps', file, filePermissions);
26
+ if (role == 'deny') continue;
180
27
  }
181
-
182
- await processType('.command.sql', 'commands');
183
- await processType('.query.sql', 'queries');
184
- }
185
-
186
- try {
187
- res.virtualReferences = JSON.parse(
188
- await fs.readFile(path.join(dir, 'virtual-references.config.json'), { encoding: 'utf-8' })
189
- );
190
- } catch (err) {
191
- res.virtualReferences = [];
192
- }
193
- try {
194
- res.dictionaryDescriptions = JSON.parse(
195
- await fs.readFile(path.join(dir, 'dictionary-descriptions.config.json'), { encoding: 'utf-8' })
196
- );
197
- } catch (err) {
198
- res.dictionaryDescriptions = [];
28
+ const content = await fs.readFile(path.join(dir, file), { encoding: 'utf-8' });
29
+ const appJson = JSON.parse(content);
30
+ // const app = {
31
+ // appid: file,
32
+ // name: appJson.applicationName,
33
+ // usageRules: appJson.usageRules || [],
34
+ // icon: appJson.applicationIcon || 'img app',
35
+ // color: appJson.applicationColor,
36
+ // queries: Object.values(appJson.files || {})
37
+ // .filter(x => x.type == 'query')
38
+ // .map(x => ({
39
+ // name: x.label,
40
+ // sql: x.sql,
41
+ // })),
42
+ // commands: Object.values(appJson.files || {})
43
+ // .filter(x => x.type == 'command')
44
+ // .map(x => ({
45
+ // name: x.label,
46
+ // sql: x.sql,
47
+ // })),
48
+ // virtualReferences: appJson.virtualReferences,
49
+ // dictionaryDescriptions: appJson.dictionaryDescriptions,
50
+ // };
51
+ const app = {
52
+ ...appJson,
53
+ appid: file,
54
+ };
55
+
56
+ res.push(app);
199
57
  }
200
-
201
58
  return res;
202
59
  },
203
60
 
204
- async saveConfigFile(appFolder, filename, filterFunc, newItem) {
205
- const file = path.join(appdir(), appFolder, filename);
206
-
207
- let json;
208
- try {
209
- json = JSON.parse(await fs.readFile(file, { encoding: 'utf-8' }));
210
- } catch (err) {
211
- json = [];
61
+ createAppFromDb_meta: true,
62
+ async createAppFromDb({ appName, server, database }, req) {
63
+ const appdir = path.join(filesdir(), 'apps');
64
+ if (!fs.existsSync(appdir)) {
65
+ await fs.mkdir(appdir);
212
66
  }
213
-
214
- if (filterFunc) {
215
- json = json.filter(filterFunc);
67
+ const appId = _.kebabCase(appName);
68
+ let suffix = undefined;
69
+ while (fs.existsSync(path.join(appdir, `${appId}${suffix || ''}`))) {
70
+ if (!suffix) suffix = 2;
71
+ else suffix++;
216
72
  }
73
+ const finalAppId = `${appId}${suffix || ''}`;
74
+
75
+ const appJson = {
76
+ applicationName: appName,
77
+ usageRules: [
78
+ {
79
+ serverHostsList: server,
80
+ databaseNamesList: database,
81
+ },
82
+ ],
83
+ };
217
84
 
218
- json = [...json, newItem];
85
+ await fs.writeFile(path.join(appdir, `${finalAppId}`), JSON.stringify(appJson, undefined, 2));
219
86
 
220
- await fs.writeFile(file, JSON.stringify(json, undefined, 2));
87
+ socket.emitChanged(`files-changed`, { folder: 'apps' });
221
88
 
222
- socket.emitChanged('app-files-changed', { app: appFolder });
223
- socket.emitChanged('used-apps-changed');
89
+ return finalAppId;
224
90
  },
225
91
 
226
92
  saveVirtualReference_meta: true,
227
- async saveVirtualReference({ appFolder, schemaName, pureName, refSchemaName, refTableName, columns }) {
228
- await this.saveConfigFile(
229
- appFolder,
230
- 'virtual-references.config.json',
93
+ async saveVirtualReference({ appid, schemaName, pureName, refSchemaName, refTableName, columns }) {
94
+ await this.saveConfigItem(
95
+ appid,
96
+ 'virtualReferences',
231
97
  columns.length == 1
232
98
  ? x =>
233
99
  !(
@@ -245,14 +111,17 @@ module.exports = {
245
111
  columns,
246
112
  }
247
113
  );
114
+
115
+ socket.emitChanged(`files-changed`, { folder: 'apps' });
116
+
248
117
  return true;
249
118
  },
250
119
 
251
120
  saveDictionaryDescription_meta: true,
252
- async saveDictionaryDescription({ appFolder, pureName, schemaName, expression, columns, delimiter }) {
253
- await this.saveConfigFile(
254
- appFolder,
255
- 'dictionary-descriptions.config.json',
121
+ async saveDictionaryDescription({ appid, pureName, schemaName, expression, columns, delimiter }) {
122
+ await this.saveConfigItem(
123
+ appid,
124
+ 'dictionaryDescriptions',
256
125
  x => !(x.schemaName == schemaName && x.pureName == pureName),
257
126
  {
258
127
  schemaName,
@@ -263,18 +132,271 @@ module.exports = {
263
132
  }
264
133
  );
265
134
 
135
+ socket.emitChanged(`files-changed`, { folder: 'apps' });
136
+
266
137
  return true;
267
138
  },
268
139
 
269
- createConfigFile_meta: true,
270
- async createConfigFile({ appFolder, fileName, content }) {
271
- const file = path.join(appdir(), appFolder, fileName);
272
- if (!(await fs.exists(file))) {
273
- await fs.writeFile(file, JSON.stringify(content, undefined, 2));
274
- socket.emitChanged('app-files-changed', { app: appFolder });
275
- socket.emitChanged('used-apps-changed');
276
- return true;
140
+ async saveConfigItem(appid, fieldName, filterFunc, newItem) {
141
+ const file = path.join(filesdir(), 'apps', appid);
142
+
143
+ const appJson = JSON.parse(await fs.readFile(file, { encoding: 'utf-8' }));
144
+ let json = appJson[fieldName] || [];
145
+
146
+ if (filterFunc) {
147
+ json = json.filter(filterFunc);
277
148
  }
278
- return false;
149
+
150
+ json = [...json, newItem];
151
+
152
+ await fs.writeFile(
153
+ file,
154
+ JSON.stringify(
155
+ {
156
+ ...appJson,
157
+ [fieldName]: json,
158
+ },
159
+ undefined,
160
+ 2
161
+ )
162
+ );
163
+
164
+ socket.emitChanged('files-changed', { folder: 'apps' });
279
165
  },
166
+
167
+ // folders_meta: true,
168
+ // async folders() {
169
+ // const folders = await fs.readdir(appdir());
170
+ // return [
171
+ // ...folders.map(name => ({
172
+ // name,
173
+ // })),
174
+ // ];
175
+ // },
176
+
177
+ // createFolder_meta: true,
178
+ // async createFolder({ folder }) {
179
+ // const name = await this.getNewAppFolder({ name: folder });
180
+ // await fs.mkdir(path.join(appdir(), name));
181
+ // socket.emitChanged('app-folders-changed');
182
+ // this.emitChangedDbApp(folder);
183
+ // return name;
184
+ // },
185
+
186
+ // files_meta: true,
187
+ // async files({ folder }) {
188
+ // if (!folder) return [];
189
+ // const dir = path.join(appdir(), folder);
190
+ // if (!(await fs.exists(dir))) return [];
191
+ // const files = await fs.readdir(dir);
192
+
193
+ // function fileType(ext, type) {
194
+ // return files
195
+ // .filter(name => name.endsWith(ext))
196
+ // .map(name => ({
197
+ // name: name.slice(0, -ext.length),
198
+ // label: path.parse(name.slice(0, -ext.length)).base,
199
+ // type,
200
+ // }));
201
+ // }
202
+
203
+ // return [
204
+ // ...fileType('.command.sql', 'command.sql'),
205
+ // ...fileType('.query.sql', 'query.sql'),
206
+ // ...fileType('.config.json', 'config.json'),
207
+ // ];
208
+ // },
209
+
210
+ // async emitChangedDbApp(folder) {
211
+ // const used = await this.getUsedAppFolders();
212
+ // if (used.includes(folder)) {
213
+ // socket.emitChanged('used-apps-changed');
214
+ // }
215
+ // },
216
+
217
+ // refreshFiles_meta: true,
218
+ // async refreshFiles({ folder }) {
219
+ // socket.emitChanged('app-files-changed', { app: folder });
220
+ // },
221
+
222
+ // refreshFolders_meta: true,
223
+ // async refreshFolders() {
224
+ // socket.emitChanged(`app-folders-changed`);
225
+ // },
226
+
227
+ // deleteFile_meta: true,
228
+ // async deleteFile({ folder, file, fileType }) {
229
+ // await fs.unlink(path.join(appdir(), folder, `${file}.${fileType}`));
230
+ // socket.emitChanged('app-files-changed', { app: folder });
231
+ // this.emitChangedDbApp(folder);
232
+ // },
233
+
234
+ // renameFile_meta: true,
235
+ // async renameFile({ folder, file, newFile, fileType }) {
236
+ // await fs.rename(
237
+ // path.join(path.join(appdir(), folder), `${file}.${fileType}`),
238
+ // path.join(path.join(appdir(), folder), `${newFile}.${fileType}`)
239
+ // );
240
+ // socket.emitChanged('app-files-changed', { app: folder });
241
+ // this.emitChangedDbApp(folder);
242
+ // },
243
+
244
+ // renameFolder_meta: true,
245
+ // async renameFolder({ folder, newFolder }) {
246
+ // const uniqueName = await this.getNewAppFolder({ name: newFolder });
247
+ // await fs.rename(path.join(appdir(), folder), path.join(appdir(), uniqueName));
248
+ // socket.emitChanged(`app-folders-changed`);
249
+ // },
250
+
251
+ // deleteFolder_meta: true,
252
+ // async deleteFolder({ folder }) {
253
+ // if (!folder) throw new Error('Missing folder parameter');
254
+ // await fs.rmdir(path.join(appdir(), folder), { recursive: true });
255
+ // socket.emitChanged(`app-folders-changed`);
256
+ // socket.emitChanged('app-files-changed', { app: folder });
257
+ // socket.emitChanged('used-apps-changed');
258
+ // },
259
+
260
+ // async getNewAppFolder({ name }) {
261
+ // if (!(await fs.exists(path.join(appdir(), name)))) return name;
262
+ // let index = 2;
263
+ // while (await fs.exists(path.join(appdir(), `${name}${index}`))) {
264
+ // index += 1;
265
+ // }
266
+ // return `${name}${index}`;
267
+ // },
268
+
269
+ // getUsedAppFolders_meta: true,
270
+ // async getUsedAppFolders() {
271
+ // const list = await connections.list();
272
+ // const apps = [];
273
+
274
+ // for (const connection of list) {
275
+ // for (const db of connection.databases || []) {
276
+ // for (const key of _.keys(db || {})) {
277
+ // if (key.startsWith('useApp:') && db[key]) {
278
+ // apps.push(key.substring('useApp:'.length));
279
+ // }
280
+ // }
281
+ // }
282
+ // }
283
+
284
+ // return _.intersection(_.uniq(apps), await fs.readdir(appdir()));
285
+ // },
286
+
287
+ // // getAppsForDb_meta: true,
288
+ // // async getAppsForDb({ conid, database }) {
289
+ // // const connection = await connections.get({ conid });
290
+ // // if (!connection) return [];
291
+ // // const db = (connection.databases || []).find(x => x.name == database);
292
+ // // const apps = [];
293
+ // // const res = [];
294
+ // // if (db) {
295
+ // // for (const key of _.keys(db || {})) {
296
+ // // if (key.startsWith('useApp:') && db[key]) {
297
+ // // apps.push(key.substring('useApp:'.length));
298
+ // // }
299
+ // // }
300
+ // // }
301
+ // // for (const folder of apps) {
302
+ // // res.push(await this.loadApp({ folder }));
303
+ // // }
304
+ // // return res;
305
+ // // },
306
+
307
+ // loadApp_meta: true,
308
+ // async loadApp({ folder }) {
309
+ // const res = {
310
+ // queries: [],
311
+ // commands: [],
312
+ // name: folder,
313
+ // };
314
+ // const dir = path.join(appdir(), folder);
315
+ // if (await fs.exists(dir)) {
316
+ // const files = await fs.readdir(dir);
317
+
318
+ // async function processType(ext, field) {
319
+ // for (const file of files) {
320
+ // if (file.endsWith(ext)) {
321
+ // res[field].push({
322
+ // name: file.slice(0, -ext.length),
323
+ // sql: await fs.readFile(path.join(dir, file), { encoding: 'utf-8' }),
324
+ // });
325
+ // }
326
+ // }
327
+ // }
328
+
329
+ // await processType('.command.sql', 'commands');
330
+ // await processType('.query.sql', 'queries');
331
+ // }
332
+
333
+ // try {
334
+ // res.virtualReferences = JSON.parse(
335
+ // await fs.readFile(path.join(dir, 'virtual-references.config.json'), { encoding: 'utf-8' })
336
+ // );
337
+ // } catch (err) {
338
+ // res.virtualReferences = [];
339
+ // }
340
+ // try {
341
+ // res.dictionaryDescriptions = JSON.parse(
342
+ // await fs.readFile(path.join(dir, 'dictionary-descriptions.config.json'), { encoding: 'utf-8' })
343
+ // );
344
+ // } catch (err) {
345
+ // res.dictionaryDescriptions = [];
346
+ // }
347
+
348
+ // return res;
349
+ // },
350
+
351
+ // async saveConfigFile(appFolder, filename, filterFunc, newItem) {
352
+ // const file = path.join(appdir(), appFolder, filename);
353
+
354
+ // let json;
355
+ // try {
356
+ // json = JSON.parse(await fs.readFile(file, { encoding: 'utf-8' }));
357
+ // } catch (err) {
358
+ // json = [];
359
+ // }
360
+
361
+ // if (filterFunc) {
362
+ // json = json.filter(filterFunc);
363
+ // }
364
+
365
+ // json = [...json, newItem];
366
+
367
+ // await fs.writeFile(file, JSON.stringify(json, undefined, 2));
368
+
369
+ // socket.emitChanged('app-files-changed', { app: appFolder });
370
+ // socket.emitChanged('used-apps-changed');
371
+ // },
372
+
373
+ // saveDictionaryDescription_meta: true,
374
+ // async saveDictionaryDescription({ appFolder, pureName, schemaName, expression, columns, delimiter }) {
375
+ // await this.saveConfigFile(
376
+ // appFolder,
377
+ // 'dictionary-descriptions.config.json',
378
+ // x => !(x.schemaName == schemaName && x.pureName == pureName),
379
+ // {
380
+ // schemaName,
381
+ // pureName,
382
+ // expression,
383
+ // columns,
384
+ // delimiter,
385
+ // }
386
+ // );
387
+
388
+ // return true;
389
+ // },
390
+
391
+ // createConfigFile_meta: true,
392
+ // async createConfigFile({ appFolder, fileName, content }) {
393
+ // const file = path.join(appdir(), appFolder, fileName);
394
+ // if (!(await fs.exists(file))) {
395
+ // await fs.writeFile(file, JSON.stringify(content, undefined, 2));
396
+ // socket.emitChanged('app-files-changed', { app: appFolder });
397
+ // socket.emitChanged('used-apps-changed');
398
+ // return true;
399
+ // }
400
+ // return false;
401
+ // },
280
402
  };
@@ -174,7 +174,9 @@ module.exports = {
174
174
  getProviders_meta: true,
175
175
  getProviders() {
176
176
  return {
177
- providers: getAuthProviders().map(x => x.toJson()),
177
+ providers: getAuthProviders()
178
+ .filter(x => !x.skipInList)
179
+ .map(x => x.toJson()),
178
180
  default: getDefaultAuthProvider()?.amoid,
179
181
  };
180
182
  },
@@ -619,7 +619,7 @@ module.exports = {
619
619
  message: `Loaded database structure for ${database}`,
620
620
  });
621
621
 
622
- if (!hasPermission(`all-tables`, loadedPermissions)) {
622
+ if (process.env.STORAGE_DATABASE && !hasPermission(`all-tables`, loadedPermissions)) {
623
623
  // filter databases by permissions
624
624
  const tablePermissions = await loadTablePermissionsFromRequest(req);
625
625
  const databasePermissions = await loadDatabasePermissionsFromRequest(req);
@@ -3,7 +3,12 @@ const path = require('path');
3
3
  const crypto = require('crypto');
4
4
  const { filesdir, archivedir, resolveArchiveFolder, uploadsdir, appdir, jsldir } = require('../utility/directories');
5
5
  const getChartExport = require('../utility/getChartExport');
6
- const { hasPermission, loadPermissionsFromRequest } = require('../utility/hasPermission');
6
+ const {
7
+ hasPermission,
8
+ loadPermissionsFromRequest,
9
+ loadFilePermissionsFromRequest,
10
+ getFilePermissionRole,
11
+ } = require('../utility/hasPermission');
7
12
  const socket = require('../utility/socket');
8
13
  const scheduler = require('./scheduler');
9
14
  const getDiagramExport = require('../utility/getDiagramExport');
@@ -46,7 +46,7 @@ module.exports = {
46
46
  existing.status = status;
47
47
  socket.emitChanged(`server-status-changed`);
48
48
  },
49
- handle_ping() { },
49
+ handle_ping() {},
50
50
  handle_response(conid, { msgid, ...response }) {
51
51
  const [resolve, reject] = this.requests[msgid];
52
52
  resolve(response);
@@ -166,7 +166,7 @@ module.exports = {
166
166
  message: `Loaded databases for connection`,
167
167
  });
168
168
 
169
- if (!hasPermission(`all-databases`, loadedPermissions)) {
169
+ if (process.env.STORAGE_DATABASE && !hasPermission(`all-databases`, loadedPermissions)) {
170
170
  // filter databases by permissions
171
171
  const databasePermissions = await loadDatabasePermissionsFromRequest(req);
172
172
  const res = [];