From 97653b730713379ea248a05ba2fa6363dae2798b Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 9 Aug 2025 16:41:33 +0200 Subject: [PATCH] Preserve masked credentials in admin config updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handle masked sensitive fields (passwords/secrets) in reCAPTCHA and SMTP configuration endpoints. When the frontend sends masked values (bullets), preserve existing credentials instead of overwriting them. This prevents accidental credential loss when updating other configuration fields. - Check for masked placeholder values ('••••••••••••••••') - Preserve existing secretKey/password when masked - Add logging to track credential update actions --- server/api/admin/recaptcha-config.post.ts | 17 +++++++++++++++-- server/api/admin/smtp-config.post.ts | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/server/api/admin/recaptcha-config.post.ts b/server/api/admin/recaptcha-config.post.ts index ca41bb9..e5356bb 100644 --- a/server/api/admin/recaptcha-config.post.ts +++ b/server/api/admin/recaptcha-config.post.ts @@ -45,12 +45,25 @@ export default defineEventHandler(async (event) => { }); } + // Get existing configuration to preserve secretKey if not changed + const { getRecaptchaConfig, saveRecaptchaConfig } = await import('~/server/utils/admin-config'); + const existingConfig = getRecaptchaConfig(); + + // Check if secretKey is the masked value + const isMaskedSecretKey = body.secretKey === '••••••••••••••••'; + // Save reCAPTCHA configuration - const { saveRecaptchaConfig } = await import('~/server/utils/admin-config'); await saveRecaptchaConfig({ siteKey: body.siteKey.trim(), - secretKey: body.secretKey.trim() + // If secretKey is masked bullets, preserve existing secretKey + // Otherwise, use the new secretKey + secretKey: isMaskedSecretKey + ? (existingConfig.secretKey || '') + : body.secretKey.trim() }, session.user.email); + + console.log('[api/admin/recaptcha-config.post] Secret key action:', + isMaskedSecretKey ? 'preserved' : 'updated'); console.log('[api/admin/recaptcha-config.post] ✅ reCAPTCHA configuration saved successfully'); diff --git a/server/api/admin/smtp-config.post.ts b/server/api/admin/smtp-config.post.ts index 76e5112..6ec5272 100644 --- a/server/api/admin/smtp-config.post.ts +++ b/server/api/admin/smtp-config.post.ts @@ -57,20 +57,33 @@ export default defineEventHandler(async (event) => { }); } + // Get existing configuration to preserve password if not changed + const { getSMTPConfig } = await import('~/server/utils/admin-config'); + const existingConfig = getSMTPConfig(); + + // Check if password is the masked value + const isMaskedPassword = body.password === '••••••••••••••••'; + // Prepare configuration object const smtpConfig = { host: body.host.trim(), port: port, secure: Boolean(body.secure), username: body.username?.trim() || '', - password: body.password?.trim() || '', + // If password is masked bullets, preserve existing password + // If password is empty, clear it + // Otherwise, use the new password + password: isMaskedPassword + ? (existingConfig.password || '') + : (body.password?.trim() || ''), fromAddress: body.fromAddress.trim(), fromName: body.fromName.trim() }; console.log('[api/admin/smtp-config.post] Saving SMTP config:', { ...smtpConfig, - password: smtpConfig.password ? '••••••••••••••••' : '' + password: smtpConfig.password ? '••••••••••••••••' : '', + passwordAction: isMaskedPassword ? 'preserved' : (body.password ? 'updated' : 'cleared') }); // Save SMTP configuration