dbgate-api-premium 6.6.0 → 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.
Files changed (62) hide show
  1. package/package.json +6 -6
  2. package/src/auth/authProvider.js +14 -2
  3. package/src/auth/storageAuthProvider.js +89 -22
  4. package/src/controllers/archive.js +1 -1
  5. package/src/controllers/auth.js +3 -2
  6. package/src/controllers/cloud.js +1 -1
  7. package/src/controllers/config.js +8 -5
  8. package/src/controllers/connections.js +12 -11
  9. package/src/controllers/databaseConnections.js +148 -83
  10. package/src/controllers/files.js +49 -19
  11. package/src/controllers/plugins.js +7 -4
  12. package/src/controllers/runners.js +10 -6
  13. package/src/controllers/scheduler.js +4 -3
  14. package/src/controllers/serverConnections.js +69 -14
  15. package/src/controllers/sessions.js +8 -5
  16. package/src/controllers/storage.js +81 -51
  17. package/src/controllers/storageDb.js +118 -4
  18. package/src/controllers/uploads.js +2 -2
  19. package/src/currentVersion.js +2 -2
  20. package/src/index.js +36 -5
  21. package/src/main.js +59 -20
  22. package/src/proc/databaseConnectionProcess.js +45 -13
  23. package/src/proc/serverConnectionProcess.js +32 -6
  24. package/src/proc/sessionProcess.js +2 -2
  25. package/src/proc/sshForwardProcess.js +1 -1
  26. package/src/shell/archiveWriter.js +1 -1
  27. package/src/shell/copyStream.js +1 -1
  28. package/src/shell/executeQuery.js +3 -3
  29. package/src/shell/importDatabase.js +3 -3
  30. package/src/shell/jsonLinesReader.js +1 -1
  31. package/src/shell/jsonLinesWriter.js +1 -1
  32. package/src/shell/jsonReader.js +1 -1
  33. package/src/shell/jsonWriter.js +1 -1
  34. package/src/shell/loadDatabase.js +2 -2
  35. package/src/shell/modifyJsonLinesReader.js +1 -1
  36. package/src/shell/queryReader.js +1 -1
  37. package/src/shell/requirePlugin.js +6 -1
  38. package/src/shell/runScript.js +1 -1
  39. package/src/shell/sqlDataWriter.js +1 -1
  40. package/src/shell/tableReader.js +3 -3
  41. package/src/shell/tableWriter.js +1 -1
  42. package/src/shell/unzipDirectory.js +4 -4
  43. package/src/shell/zipDirectory.js +3 -3
  44. package/src/shell/zipJsonLinesData.js +3 -3
  45. package/src/storageModel.js +726 -105
  46. package/src/utility/DatastoreProxy.js +3 -3
  47. package/src/utility/JsonLinesDatastore.js +4 -2
  48. package/src/utility/appLogStore.js +119 -0
  49. package/src/utility/auditlog.js +1 -1
  50. package/src/utility/authProxy.js +4 -4
  51. package/src/utility/checkLicense.js +10 -4
  52. package/src/utility/childProcessChecker.js +1 -1
  53. package/src/utility/cloudIntf.js +5 -5
  54. package/src/utility/cloudUpgrade.js +4 -4
  55. package/src/utility/connectUtility.js +1 -1
  56. package/src/utility/directories.js +2 -2
  57. package/src/utility/extractSingleFileFromZip.js +3 -3
  58. package/src/utility/hasPermission.js +286 -71
  59. package/src/utility/loadModelTransform.js +1 -1
  60. package/src/utility/sshTunnel.js +7 -7
  61. package/src/utility/sshTunnelProxy.js +1 -1
  62. package/src/utility/useController.js +3 -3
@@ -2,23 +2,23 @@ const fs = require('fs-extra');
2
2
  const _ = require('lodash');
3
3
  const path = require('path');
4
4
  const { setAuthProviders, getAuthProviderById } = require('../auth/authProvider');
5
- const { createStorageAuthProvider } = require('../auth/storageAuthProvider');
5
+ const { createStorageAuthProvider, SuperadminAuthProvider } = require('../auth/storageAuthProvider');
6
6
  const {
7
7
  getStorageConnection,
8
8
  getDbConnectionParams,
9
9
  storageSelectFmt,
10
10
  storageReadUserRolePermissions,
11
- loadSuperadminPermissions,
12
11
  storageReadConfig,
13
12
  storageWriteConfig,
14
13
  getStorageConnectionError,
15
14
  storageSaveRelationDiff,
16
15
  selectStorageIdentity,
16
+ storageSaveDetailPermissionsDiff,
17
17
  } = require('./storageDb');
18
- const { hasPermission } = require('../utility/hasPermission');
18
+ const { hasPermission, loadPermissionsFromRequest } = require('../utility/hasPermission');
19
19
  const { changeSetToSql, removeSchemaFromChangeSet } = require('dbgate-datalib');
20
20
  const storageModel = require('../storageModel');
21
- const { dumpSqlCommand, dumpSqlSelect } = require('dbgate-sqltree');
21
+ const { dumpSqlCommand, dumpSqlSelect, createLogCompoudCondition } = require('dbgate-sqltree');
22
22
  const {
23
23
  runCommandOnDriver,
24
24
  getLogger,
@@ -64,6 +64,7 @@ module.exports = {
64
64
  if (defIndex < 0) {
65
65
  defIndex = enabledConfig.findIndex(x => x.type == 'local');
66
66
  }
67
+ providers.push(new SuperadminAuthProvider());
67
68
 
68
69
  setAuthProviders(providers, providers[defIndex]);
69
70
 
@@ -94,14 +95,14 @@ module.exports = {
94
95
  return;
95
96
  }
96
97
  if (resp.status == 'error') {
97
- logger.error(`Error refreshing license: ${resp.message}`);
98
+ logger.error(`DBGM-00146 Error refreshing license: ${resp.message}`);
98
99
  return;
99
100
  }
100
101
  if (resp.status != 'ok') {
101
102
  return;
102
103
  }
103
104
  const { token } = resp;
104
- logger.info('License succesfully refreshed');
105
+ logger.info('DBGM-00022 License succesfully refreshed');
105
106
  if (process.env.STORAGE_DATABASE) {
106
107
  await this.writeConfig({ group: 'license', config: { licenseKey: token } });
107
108
  } else {
@@ -112,6 +113,7 @@ module.exports = {
112
113
 
113
114
  connections_meta: true,
114
115
  async connections(req) {
116
+ const loadedPermissions = await loadPermissionsFromRequest(req);
115
117
  if (!process.env.STORAGE_DATABASE) {
116
118
  return null;
117
119
  }
@@ -121,7 +123,7 @@ module.exports = {
121
123
 
122
124
  let resp = null;
123
125
 
124
- if (hasPermission('all-connections', req)) {
126
+ if (hasPermission('all-connections', loadedPermissions)) {
125
127
  resp = await storageSelectFmt(`select ~connections.* from ~connections`);
126
128
  } else if (userId) {
127
129
  resp = await storageSelectFmt(
@@ -142,9 +144,8 @@ module.exports = {
142
144
  );
143
145
  } else {
144
146
  resp = await storageSelectFmt(
145
- `select distinct ~connections.* from ~connections
146
- inner join ~role_connections on ~connections.~id = ~role_connections.~connection_id
147
- where ~role_connections.~role_id = %v`,
147
+ `select ~connections.* from ~connections
148
+ where exists (select * from ~role_connections where ~role_connections.~connection_id = ~connections.~id and ~role_connections.~role_id = %v)`,
148
149
  roleId ?? -1
149
150
  );
150
151
  }
@@ -153,7 +154,7 @@ module.exports = {
153
154
  return [];
154
155
  }
155
156
  const res = [];
156
- if (hasPermission('internal-storage', req)) {
157
+ if (hasPermission('internal-storage', loadedPermissions)) {
157
158
  res.push(await this.getConnection({ conid: '__storage' }));
158
159
  }
159
160
  if (resp) {
@@ -330,10 +331,6 @@ module.exports = {
330
331
  return storageReadUserRolePermissions(userId);
331
332
  },
332
333
 
333
- async loadSuperadminPermissions() {
334
- return loadSuperadminPermissions();
335
- },
336
-
337
334
  getConnectionsForLoginPage_meta: true,
338
335
  getConnectionsForLoginPage({ amoid }) {
339
336
  return getAuthProviderById(amoid).getLoginPageConnections();
@@ -488,6 +485,10 @@ module.exports = {
488
485
  : (await storageSelectFmt('select ~connection_id from ~user_connections where ~user_id = %v', id)).map(
489
486
  x => x.connection_id
490
487
  );
488
+ const databasePermissions =
489
+ id == 'new' ? [] : await storageSelectFmt('select * from ~user_databases where ~user_id = %v', id);
490
+ const tablePermissions =
491
+ id == 'new' ? [] : await storageSelectFmt('select * from ~user_tables where ~user_id = %v', id);
491
492
 
492
493
  return {
493
494
  ...resp[0],
@@ -497,6 +498,8 @@ module.exports = {
497
498
  usedRoles,
498
499
  allConnections,
499
500
  usedConnections,
501
+ databasePermissions,
502
+ tablePermissions,
500
503
  encryptPassword: !!(resp[0]?.password?.startsWith('crypt:') || id == 'new'),
501
504
  };
502
505
  },
@@ -505,7 +508,8 @@ module.exports = {
505
508
  async saveUserDetail(user) {
506
509
  const [conn, driver] = await getStorageConnection();
507
510
 
508
- const { login, password, email, usedRoles, usedConnections, permissions } = encryptUser(user);
511
+ const { login, password, email, usedRoles, usedConnections, permissions, databasePermissions, tablePermissions } =
512
+ encryptUser(user);
509
513
  let id = user.id;
510
514
 
511
515
  if (id == null) {
@@ -534,6 +538,32 @@ module.exports = {
534
538
  await storageSaveRelationDiff('user_roles', 'user_id', 'role_id', id, usedRoles);
535
539
  await storageSaveRelationDiff('user_connections', 'user_id', 'connection_id', id, usedConnections);
536
540
 
541
+ await storageSaveDetailPermissionsDiff(
542
+ 'user_databases',
543
+ 'user_id',
544
+ id,
545
+ ['connection_id', 'database_names_list', 'database_names_regex', 'database_permission_role_id'],
546
+ databasePermissions
547
+ );
548
+
549
+ await storageSaveDetailPermissionsDiff(
550
+ 'user_tables',
551
+ 'user_id',
552
+ id,
553
+ [
554
+ 'connection_id',
555
+ 'database_names_list',
556
+ 'database_names_regex',
557
+ 'schema_names_list',
558
+ 'schema_names_regex',
559
+ 'table_names_list',
560
+ 'table_names_regex',
561
+ 'table_permission_role_id',
562
+ 'table_permission_scope_id',
563
+ ],
564
+ tablePermissions
565
+ );
566
+
537
567
  return true;
538
568
  },
539
569
 
@@ -678,6 +708,11 @@ module.exports = {
678
708
  : (await storageSelectFmt('select ~connection_id from ~role_connections where ~role_id = %v', id)).map(
679
709
  x => x.connection_id
680
710
  );
711
+ const databasePermissions =
712
+ id == 'new' ? [] : await storageSelectFmt('select * from ~role_databases where ~role_id = %v', id);
713
+ const tablePermissions =
714
+ id == 'new' ? [] : await storageSelectFmt('select * from ~role_tables where ~role_id = %v', id);
715
+
681
716
 
682
717
  return {
683
718
  ...resp[0],
@@ -687,6 +722,8 @@ module.exports = {
687
722
  usedUsers,
688
723
  allConnections,
689
724
  usedConnections,
725
+ databasePermissions,
726
+ tablePermissions,
690
727
  };
691
728
  },
692
729
 
@@ -706,7 +743,7 @@ module.exports = {
706
743
  async saveRoleDetail(role) {
707
744
  const [conn, driver] = await getStorageConnection();
708
745
 
709
- const { name, usedConnections, usedUsers, permissions } = encryptUser(role);
746
+ const { name, usedConnections, usedUsers, permissions, databasePermissions, tablePermissions } = role;
710
747
  let id = role.id;
711
748
 
712
749
  if (id == null) {
@@ -722,42 +759,38 @@ module.exports = {
722
759
  await storageSaveRelationDiff('user_roles', 'role_id', 'user_id', id, usedUsers);
723
760
  await storageSaveRelationDiff('role_connections', 'role_id', 'connection_id', id, usedConnections);
724
761
 
762
+ await storageSaveDetailPermissionsDiff(
763
+ 'role_databases',
764
+ 'role_id',
765
+ id,
766
+ ['connection_id', 'database_names_list', 'database_names_regex', 'database_permission_role_id'],
767
+ databasePermissions
768
+ );
769
+
770
+ await storageSaveDetailPermissionsDiff(
771
+ 'role_tables',
772
+ 'role_id',
773
+ id,
774
+ [
775
+ 'connection_id',
776
+ 'database_names_list',
777
+ 'database_names_regex',
778
+ 'schema_names_list',
779
+ 'schema_names_regex',
780
+ 'table_names_list',
781
+ 'table_names_regex',
782
+ 'table_permission_role_id',
783
+ 'table_permission_scope_id',
784
+ ],
785
+ tablePermissions
786
+ );
787
+
725
788
  return true;
726
789
  },
727
790
 
728
791
  getAuditLog_meta: true,
729
792
  async getAuditLog({ offset = 0, limit = 100, dateFrom = 0, dateTo = new Date().getTime(), filters = {} }) {
730
793
  const [conn, driver] = await getStorageConnection();
731
- const conditions = [
732
- {
733
- conditionType: 'binary',
734
- operator: '>=',
735
- left: { exprType: 'column', columnName: 'created' },
736
- right: { exprType: 'value', value: dateFrom },
737
- },
738
- {
739
- conditionType: 'binary',
740
- operator: '<=',
741
- left: { exprType: 'column', columnName: 'created' },
742
- right: { exprType: 'value', value: dateTo },
743
- },
744
- ];
745
- for (const [key, values] of Object.entries(filters)) {
746
- if (values.length == 1 && values[0] == null) {
747
- // @ts-ignore
748
- conditions.push({
749
- conditionType: 'isNull',
750
- expr: { exprType: 'column', columnName: key },
751
- });
752
- continue;
753
- }
754
- // @ts-ignore
755
- conditions.push({
756
- conditionType: 'in',
757
- expr: { exprType: 'column', columnName: key },
758
- values,
759
- });
760
- }
761
794
  const COLUMNS = [
762
795
  'id',
763
796
  'created',
@@ -780,10 +813,7 @@ module.exports = {
780
813
  exprType: 'column',
781
814
  columnName,
782
815
  })),
783
- where: {
784
- conditionType: 'and',
785
- conditions,
786
- },
816
+ where: createLogCompoudCondition(filters, 'created', dateFrom, dateTo),
787
817
  range: {
788
818
  limit: limit,
789
819
  offset: offset,
@@ -1,4 +1,3 @@
1
- const requireEngineDriver = require('../utility/requireEngineDriver');
2
1
  const storageModel = require('../storageModel');
3
2
  const dbgateApi = require('../shell');
4
3
  const {
@@ -86,6 +85,8 @@ let storageDriver = null;
86
85
  let storageConnectionError = null;
87
86
 
88
87
  async function getStorageConnectionCore() {
88
+ const requireEngineDriver = require('../utility/requireEngineDriver');
89
+
89
90
  if (storageConnection) {
90
91
  return [storageConnection, storageDriver];
91
92
  }
@@ -103,7 +104,9 @@ async function getStorageConnectionCore() {
103
104
  try {
104
105
  newConnection = await storageDriver.connect(dbConnectionParams);
105
106
  const version = await storageDriver.getVersion(newConnection);
106
- logger.info(`Connected to storage database ${dbConnectionParams.engine}, version ${version?.versionText}`);
107
+ logger.info(
108
+ `DBGM-00023 Connected to storage database ${dbConnectionParams.engine}, version ${version?.versionText}`
109
+ );
107
110
  storageConnectionError = null;
108
111
  } catch (err) {
109
112
  storageConnectionError = err;
@@ -113,7 +116,7 @@ async function getStorageConnectionCore() {
113
116
  } catch (err) {}
114
117
  newConnection = null;
115
118
  }
116
- logger.error(extractErrorLogData(err), 'Error connecting to storage database, retrying in 5 seconds');
119
+ logger.error(extractErrorLogData(err), 'DBGM-00024 Error connecting to storage database, retrying in 5 seconds');
117
120
  // sleep 5 seconds
118
121
  await new Promise(resolve => setTimeout(resolve, 5000));
119
122
  }
@@ -149,7 +152,7 @@ function getStorageConnection() {
149
152
  gettingStorageConnectionPromise = null;
150
153
  })
151
154
  .catch(err => {
152
- logger.error(extractErrorLogData(err), 'Error connecting to storage database');
155
+ logger.error(extractErrorLogData(err), 'DBGM-00147 Error connecting to storage database');
153
156
  gettingStorageConnectionPromise = null;
154
157
  });
155
158
 
@@ -216,6 +219,34 @@ async function storageReadRolePermissions(roleId) {
216
219
  return resp.map(x => x.permission);
217
220
  }
218
221
 
222
+ async function readComplexUserRolePermissions(userId, userPermissionsTable, rolePermissionsTable) {
223
+ const rolePermissionsResp = await storageSelectFmt(
224
+ 'select * from %i where %i.~role_id in (select ~role_id from ~user_roles where ~user_roles.~user_id = %v)',
225
+ rolePermissionsTable,
226
+ rolePermissionsTable,
227
+ userId
228
+ );
229
+
230
+ const userPermissionsResp = await storageSelectFmt(
231
+ 'select * from %i where %i.~user_id = %v',
232
+ userPermissionsTable,
233
+ userPermissionsTable,
234
+ userId
235
+ );
236
+
237
+ return [...rolePermissionsResp, ...userPermissionsResp];
238
+ }
239
+
240
+ async function readComplexRolePermissions(roleId, rolePermissionsTable) {
241
+ const rolePermissionsResp = await storageSelectFmt(
242
+ 'select * from %i where %i.~role_id = %v',
243
+ rolePermissionsTable,
244
+ rolePermissionsTable,
245
+ roleId
246
+ );
247
+ return rolePermissionsResp;
248
+ }
249
+
219
250
  async function loadSuperadminPermissions() {
220
251
  const rolePermissions = await storageReadRolePermissions(-3);
221
252
  return [...getPredefinedPermissions('superadmin'), ...rolePermissions];
@@ -283,6 +314,57 @@ async function storageSaveRelationDiff(table, idColumn, valueColumn, idValue, ne
283
314
  }
284
315
  }
285
316
 
317
+ function sanitizePermissionCollectionRow(collectionRow, valueColumns) {
318
+ const res = {};
319
+ let hasValue = false;
320
+ for (const col of valueColumns) {
321
+ if (col.endsWith('_list') || col.endsWith('_regex')) {
322
+ res[col] = collectionRow[col]?.trim() ? collectionRow[col]?.trim() : null;
323
+ } else if (col.endsWith('_id')) {
324
+ res[col] = collectionRow[col] ? parseInt(collectionRow[col]) : null;
325
+ } else {
326
+ res[col] = collectionRow[col] || null;
327
+ }
328
+ if (res[col]) {
329
+ hasValue = true;
330
+ }
331
+ }
332
+ if (!hasValue) {
333
+ return null;
334
+ }
335
+ return res;
336
+ }
337
+
338
+ async function storageSaveDetailPermissionsDiff(table, idColumn, idValue, valueColumns, valuesCollection) {
339
+ const [conn, driver] = await getStorageConnection();
340
+ if (!conn) {
341
+ return null;
342
+ }
343
+
344
+ if (valuesCollection) {
345
+ // Delete existing database permissions for this user
346
+ await runQueryFmt(driver, conn, 'delete from %i where %i = %v', table, idColumn, idValue);
347
+
348
+ // Insert new database permissions
349
+ for (const collectionRow of valuesCollection) {
350
+ const sanitizedRow = sanitizePermissionCollectionRow(collectionRow, valueColumns);
351
+ if (!sanitizedRow) {
352
+ continue;
353
+ }
354
+ await runQueryFmt(
355
+ driver,
356
+ conn,
357
+ 'insert into %i (%i, %,i) values (%v, %,v)',
358
+ table,
359
+ idColumn,
360
+ valueColumns,
361
+ idValue,
362
+ valueColumns.map(col => sanitizedRow[col])
363
+ );
364
+ }
365
+ }
366
+ }
367
+
286
368
  function getStorageConnectionError() {
287
369
  return storageConnectionError;
288
370
  }
@@ -300,6 +382,33 @@ async function selectStorageIdentity(tableName) {
300
382
  return Object.entries(resp.rows[0])[0][1];
301
383
  }
302
384
 
385
+ async function storageCheckRoleConnectionAccess(roleId, conid) {
386
+ const resp = await storageSelectFmt(
387
+ 'select 1 from ~role_connections inner join ~connections on ~role_connections.~connection_id = ~connections.~id where ~role_connections.~role_id = %v and ~connections.~conid = %v',
388
+ roleId,
389
+ conid
390
+ );
391
+ return resp.length > 0;
392
+ }
393
+
394
+ async function storageCheckUserRoleConnectionAccess(userId, conid) {
395
+ const respByUser = await storageSelectFmt(
396
+ 'select 1 from ~user_connections inner join ~connections on ~user_connections.~connection_id = ~connections.~id where ~user_connections.~user_id = %v and ~connections.~conid = %v',
397
+ userId,
398
+ conid
399
+ );
400
+ const respByRole = await storageSelectFmt(
401
+ 'select 1 from ~role_connections inner join ~user_roles on ~role_connections.~role_id = ~user_roles.~role_id inner join ~connections on ~role_connections.~connection_id = ~connections.~id where ~user_roles.~user_id = %v and ~connections.~conid = %v',
402
+ userId,
403
+ conid
404
+ );
405
+ const respByLogged = await storageSelectFmt(
406
+ 'select 1 from ~role_connections inner join ~connections on ~role_connections.~connection_id = ~connections.~id where ~role_connections.~role_id = -2 and ~connections.~conid = %v',
407
+ conid
408
+ );
409
+ return respByUser.length > 0 || respByRole.length > 0 || respByLogged.length > 0;
410
+ }
411
+
303
412
  module.exports = {
304
413
  getStorageConnection,
305
414
  storageSelectFmt,
@@ -314,4 +423,9 @@ module.exports = {
314
423
  storageSqlCommandFmt,
315
424
  storageSaveRelationDiff,
316
425
  selectStorageIdentity,
426
+ storageSaveDetailPermissionsDiff,
427
+ readComplexUserRolePermissions,
428
+ readComplexRolePermissions,
429
+ storageCheckRoleConnectionAccess,
430
+ storageCheckUserRoleConnectionAccess,
317
431
  };
@@ -28,7 +28,7 @@ module.exports = {
28
28
  }
29
29
  const uploadName = crypto.randomUUID();
30
30
  const filePath = path.join(uploadsdir(), uploadName);
31
- logger.info(`Uploading file ${data.name}, size=${data.size}`);
31
+ logger.info(`DBGM-00025 Uploading file ${data.name}, size=${data.size}`);
32
32
 
33
33
  data.mv(filePath, () => {
34
34
  res.json({
@@ -115,7 +115,7 @@ module.exports = {
115
115
 
116
116
  return response.data;
117
117
  } catch (err) {
118
- logger.error(extractErrorLogData(err), 'Error uploading gist');
118
+ logger.error(extractErrorLogData(err), 'DBGM-00148 Error uploading gist');
119
119
 
120
120
  return {
121
121
  apiErrorMessage: err.message,
@@ -1,5 +1,5 @@
1
1
 
2
2
  module.exports = {
3
- version: '6.6.0',
4
- buildTime: '2025-07-25T07:23:41.045Z'
3
+ version: '6.6.2',
4
+ buildTime: '2025-08-29T07:26:38.959Z'
5
5
  };
package/src/index.js CHANGED
@@ -5,11 +5,12 @@ const moment = require('moment');
5
5
  const path = require('path');
6
6
  const { logsdir, setLogsFilePath, getLogsFilePath } = require('./utility/directories');
7
7
  const currentVersion = require('./currentVersion');
8
+ const _ = require('lodash');
8
9
 
9
10
  const logger = getLogger('apiIndex');
10
11
 
11
12
  process.on('uncaughtException', err => {
12
- logger.fatal(extractErrorLogData(err), 'Uncaught exception, exiting process');
13
+ logger.fatal(extractErrorLogData(err), 'DBGM-00259 Uncaught exception, exiting process');
13
14
  process.exit(1);
14
15
  });
15
16
 
@@ -33,6 +34,9 @@ if (processArgs.processDisplayName) {
33
34
  // }
34
35
 
35
36
  function configureLogger() {
37
+ const { initializeRecentLogProvider, pushToRecentLogs } = require('./utility/appLogStore');
38
+ initializeRecentLogProvider();
39
+
36
40
  const logsFilePath = path.join(logsdir(), `${moment().format('YYYY-MM-DD-HH-mm')}-${process.pid}.ndjson`);
37
41
  setLogsFilePath(logsFilePath);
38
42
  setLoggerName('main');
@@ -40,6 +44,8 @@ function configureLogger() {
40
44
  const consoleLogLevel = process.env.CONSOLE_LOG_LEVEL || process.env.LOG_LEVEL || 'info';
41
45
  const fileLogLevel = process.env.FILE_LOG_LEVEL || process.env.LOG_LEVEL || 'debug';
42
46
 
47
+ const streamsByDatePart = {};
48
+
43
49
  const logConfig = {
44
50
  base: { pid: process.pid },
45
51
  targets: [
@@ -49,10 +55,35 @@ function configureLogger() {
49
55
  level: consoleLogLevel,
50
56
  },
51
57
  {
52
- type: 'stream',
58
+ type: 'objstream',
53
59
  // @ts-ignore
54
60
  level: fileLogLevel,
55
- stream: fs.createWriteStream(logsFilePath, { flags: 'a' }),
61
+ objstream: {
62
+ send(msg) {
63
+ const datePart = moment(msg.time).format('YYYY-MM-DD');
64
+ if (!streamsByDatePart[datePart]) {
65
+ streamsByDatePart[datePart] = fs.createWriteStream(
66
+ path.join(logsdir(), `${moment().format('YYYY-MM-DD-HH-mm')}-${process.pid}.ndjson`),
67
+ { flags: 'a' }
68
+ );
69
+ }
70
+ const additionals = {};
71
+ const finalMsg =
72
+ _.isString(msg.msg) && msg.msg.match(/^DBGM-\d\d\d\d\d/)
73
+ ? {
74
+ ...msg,
75
+ msg: msg.msg.substring(10).trimStart(),
76
+ msgcode: msg.msg.substring(0, 10),
77
+ ...additionals,
78
+ }
79
+ : {
80
+ ...msg,
81
+ ...additionals,
82
+ };
83
+ streamsByDatePart[datePart].write(`${JSON.stringify(finalMsg)}\n`);
84
+ pushToRecentLogs(finalMsg);
85
+ },
86
+ },
56
87
  },
57
88
  ],
58
89
  };
@@ -101,10 +132,10 @@ function configureLogger() {
101
132
 
102
133
  if (processArgs.listenApi) {
103
134
  configureLogger();
104
- logger.info(`Starting API process version ${currentVersion.version}`);
135
+ logger.info(`DBGM-00026 Starting API process version ${currentVersion.version}`);
105
136
 
106
137
  if (process.env.DEBUG_PRINT_ENV_VARIABLES) {
107
- logger.info('Debug print environment variables:');
138
+ logger.info('DBGM-00027 Debug print environment variables:');
108
139
  for (const key of Object.keys(process.env)) {
109
140
  logger.info(` ${key}: ${JSON.stringify(process.env[key])}`);
110
141
  }