dbgate-api-premium 7.0.4 → 7.1.0

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.
@@ -16,6 +16,7 @@ const {
16
16
  storageSaveDetailPermissionsDiff,
17
17
  saveStorageTeamFilesPermissions,
18
18
  saveStorageTeamFoldersPermissions,
19
+ storageSqlCommandFmt,
19
20
  } = require('./storageDb');
20
21
  const { hasPermission, loadPermissionsFromRequest } = require('../utility/hasPermission');
21
22
  const { changeSetToSql, removeSchemaFromChangeSet } = require('dbgate-datalib');
@@ -28,9 +29,10 @@ const {
28
29
  getPredefinedPermissions,
29
30
  runQueryOnDriver,
30
31
  safeJsonParse,
32
+ extractErrorLogData,
31
33
  } = require('dbgate-tools');
32
34
  const socket = require('../utility/socket');
33
- const { obtainRefreshedLicense } = require('../utility/authProxy');
35
+ const { obtainRefreshedLicense, sendEmailViaApi } = require('../utility/authProxy');
34
36
  const { datadir } = require('../utility/directories');
35
37
  const {
36
38
  loadEncryptionKeyFromExternal,
@@ -43,6 +45,7 @@ const dataReplicator = require('../shell/dataReplicator');
43
45
  const storageReplicatorItems = require('../utility/storageReplicatorItems');
44
46
  const { sendToAuditLog } = require('../utility/auditlog');
45
47
  const { extractImportEntitiesFromEnv, createStorageFromEnvReplicatorItems } = require('../utility/envtools');
48
+ const { format } = require('date-fns');
46
49
 
47
50
  const logger = getLogger('storage');
48
51
 
@@ -1150,4 +1153,133 @@ module.exports = {
1150
1153
  });
1151
1154
  socket.emitChanged('connection-list-changed');
1152
1155
  },
1156
+
1157
+ requestPasswordReset_meta: true,
1158
+ async requestPasswordReset({ email }, req) {
1159
+ // Check if user exists with this email
1160
+ const users = await storageSelectFmt('select * from ~users where ~email = %v', email);
1161
+
1162
+ if (users.length === 0) {
1163
+ // Don't reveal whether user exists or not for security reasons
1164
+ return { success: true };
1165
+ }
1166
+
1167
+ const user = users[0];
1168
+
1169
+ // Generate a secure random token
1170
+ const token = crypto.randomBytes(32).toString('hex');
1171
+ const now = new Date();
1172
+ const expiresAt = new Date(now.getTime() + 60 * 60 * 1000); // 1 hour expiry
1173
+
1174
+ // Store token in database
1175
+ await storageSqlCommandFmt(
1176
+ 'insert into ~user_password_reset_tokens (~user_id, ~token, ~created_at, ~expires_at) values (%v, %v, %v, %v)',
1177
+ user.id,
1178
+ token,
1179
+ format(now, "yyyy-MM-dd'T'HH:mm:ss"),
1180
+ format(expiresAt, "yyyy-MM-dd'T'HH:mm:ss")
1181
+ );
1182
+
1183
+ // Generate reset link
1184
+ const resetUrl = `${req.headers.origin || 'http://localhost:3000'}/reset-password.html?token=${token}`;
1185
+
1186
+ // Send email via api.dbgate.io
1187
+ try {
1188
+ await sendEmailViaApi({
1189
+ receiver: email,
1190
+ subject: 'DbGate Password Reset',
1191
+ body: `
1192
+ Hello,
1193
+
1194
+ You requested a password reset for your DbGate account.
1195
+
1196
+ Click the following link to reset your password:
1197
+ ${resetUrl}
1198
+
1199
+ This link will expire in 1 hour.
1200
+
1201
+ If you did not request this password reset, please ignore this email.
1202
+
1203
+ Best regards,
1204
+ DbGate Team
1205
+ `.trim(),
1206
+ });
1207
+
1208
+ sendToAuditLog(req, {
1209
+ category: 'auth',
1210
+ component: 'StorageController',
1211
+ action: 'requestPasswordReset',
1212
+ event: 'password.resetRequested',
1213
+ severity: 'info',
1214
+ detail: { email },
1215
+ message: 'Password reset requested',
1216
+ });
1217
+ } catch (err) {
1218
+ logger.error(extractErrorLogData(err), 'DBGM-00270 Failed to send password reset email');
1219
+ // Cleanup: delete the password reset token that was inserted before sending the email
1220
+ try {
1221
+ await storageSqlCommandFmt(
1222
+ 'delete from ~user_password_reset_tokens where ~token = %v and ~used_at is null',
1223
+ token
1224
+ );
1225
+ } catch (cleanupErr) {
1226
+ logger.error(
1227
+ extractErrorLogData(cleanupErr),
1228
+ 'DBGM-00274 Failed to clean up password reset token after email failure'
1229
+ );
1230
+ }
1231
+ return { error: 'Failed to send email' };
1232
+ }
1233
+
1234
+ return { success: true };
1235
+ },
1236
+
1237
+ resetPassword_meta: true,
1238
+ async resetPassword({ token, newPassword }, req) {
1239
+ // Find valid token
1240
+ const tokens = await storageSelectFmt(
1241
+ 'select * from ~user_password_reset_tokens where ~token = %v and ~used_at is null and ~expires_at > %v',
1242
+ token,
1243
+ format(new Date(), "yyyy-MM-dd'T'HH:mm:ss")
1244
+ );
1245
+
1246
+ if (tokens.length === 0) {
1247
+ return { error: 'Invalid or expired token' };
1248
+ }
1249
+
1250
+ const resetToken = tokens[0];
1251
+
1252
+ // Get user
1253
+ const users = await storageSelectFmt('select * from ~users where ~id = %v', resetToken.user_id);
1254
+ if (users.length === 0) {
1255
+ return { error: 'User not found' };
1256
+ }
1257
+
1258
+ const user = users[0];
1259
+
1260
+ await storageSqlCommandFmt(
1261
+ 'update ~users set ~password = %v where ~id = %v',
1262
+ encryptPasswordString(newPassword),
1263
+ user.id
1264
+ );
1265
+
1266
+ // Mark token as used
1267
+ await storageSqlCommandFmt(
1268
+ 'update ~user_password_reset_tokens set ~used_at = %v where ~id = %v',
1269
+ format(new Date(), "yyyy-MM-dd'T'HH:mm:ss"),
1270
+ resetToken.id
1271
+ );
1272
+
1273
+ sendToAuditLog(req, {
1274
+ category: 'auth',
1275
+ component: 'StorageController',
1276
+ action: 'resetPassword',
1277
+ event: 'password.resetCompleted',
1278
+ severity: 'info',
1279
+ detail: { userId: user.id, login: user.login },
1280
+ message: 'Password reset completed',
1281
+ });
1282
+
1283
+ return { success: true };
1284
+ },
1153
1285
  };
@@ -1,5 +1,5 @@
1
1
 
2
2
  module.exports = {
3
- version: '7.0.4',
4
- buildTime: '2026-02-09T14:41:54.930Z'
3
+ version: '7.1.0',
4
+ buildTime: '2026-02-24T14:21:05.674Z'
5
5
  };
package/src/main.js CHANGED
@@ -14,6 +14,7 @@ const socket = require('./utility/socket');
14
14
  const connections = require('./controllers/connections');
15
15
  const serverConnections = require('./controllers/serverConnections');
16
16
  const databaseConnections = require('./controllers/databaseConnections');
17
+ const restConnections = require('./controllers/restConnections');
17
18
  const metadata = require('./controllers/metadata');
18
19
  const sessions = require('./controllers/sessions');
19
20
  const runners = require('./controllers/runners');
@@ -267,6 +268,7 @@ function useAllControllers(app, electron) {
267
268
  useController(app, electron, '/auth', auth);
268
269
  useController(app, electron, '/cloud', cloud);
269
270
  useController(app, electron, '/team-files', teamFiles);
271
+ useController(app, electron, '/rest-connections', restConnections);
270
272
  }
271
273
 
272
274
  function setElectronSender(electronSender) {
@@ -1,6 +1,6 @@
1
1
  const childProcessChecker = require('../utility/childProcessChecker');
2
2
  const requireEngineDriver = require('../utility/requireEngineDriver');
3
- const { connectUtility } = require('../utility/connectUtility');
3
+ const { connectUtility, getRestAuthFromConnection } = require('../utility/connectUtility');
4
4
  const { handleProcessCommunication } = require('../utility/processComm');
5
5
  const { pickSafeConnectionInfo } = require('../utility/crypting');
6
6
  const _ = require('lodash');
@@ -29,6 +29,9 @@ function start() {
29
29
  try {
30
30
  const driver = requireEngineDriver(connection);
31
31
  const connectionChanged = driver?.beforeConnectionSave ? driver.beforeConnectionSave(connection) : connection;
32
+ if (driver?.databaseEngineTypes?.includes('rest')) {
33
+ connectionChanged.restAuth = getRestAuthFromConnection(connection);
34
+ }
32
35
 
33
36
  if (!connection.isVolatileResolved) {
34
37
  if (connectionChanged.useRedirectDbLogin) {
package/src/proc/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const connectProcess = require('./connectProcess');
2
2
  const databaseConnectionProcess = require('./databaseConnectionProcess');
3
3
  const serverConnectionProcess = require('./serverConnectionProcess');
4
+ const restConnectionProcess = require('./restConnectionProcess');
4
5
  const sessionProcess = require('./sessionProcess');
5
6
  const jslDatastoreProcess = require('./jslDatastoreProcess');
6
7
  const sshForwardProcess = require('./sshForwardProcess');
@@ -9,6 +10,7 @@ module.exports = {
9
10
  connectProcess,
10
11
  databaseConnectionProcess,
11
12
  serverConnectionProcess,
13
+ restConnectionProcess,
12
14
  sessionProcess,
13
15
  jslDatastoreProcess,
14
16
  sshForwardProcess,