From 3d4034d6b194a3d2aabdf936af5045cd41e74b69 Mon Sep 17 00:00:00 2001 From: Kobe Date: Fri, 20 Jun 2025 14:09:49 +0200 Subject: [PATCH] copy smtp to new instance --- routes/launch_api.py | 77 +++++++++++++++++++++ static/js/launch_progress.js | 127 +++++++++++++++++++++++++++++++++-- 2 files changed, 200 insertions(+), 4 deletions(-) diff --git a/routes/launch_api.py b/routes/launch_api.py index 0658ceb..bee33d0 100644 --- a/routes/launch_api.py +++ b/routes/launch_api.py @@ -1510,4 +1510,81 @@ Thank you for choosing DocuPulse! except Exception as e: current_app.logger.error(f"Error sending completion email: {str(e)}") + return jsonify({'error': str(e)}), 500 + +@launch_api.route('/copy-smtp-settings', methods=['POST']) +@csrf.exempt +def copy_smtp_settings(): + """Copy SMTP settings from master instance to launched instance""" + try: + if not request.is_json: + return jsonify({'error': 'Request must be JSON'}), 400 + + data = request.get_json() + if 'instance_url' not in data: + return jsonify({'error': 'Missing instance_url parameter'}), 400 + + instance_url = data['instance_url'] + + # Get SMTP settings from master instance + smtp_settings = KeyValueSettings.get_value('smtp_settings') + if not smtp_settings: + return jsonify({'error': 'SMTP settings not configured on master instance'}), 400 + + # Get the instance from database to get the connection token + instance = Instance.query.filter_by(main_url=instance_url).first() + + if not instance: + return jsonify({'error': 'Instance not found in database'}), 404 + + if not instance.connection_token: + return jsonify({'error': 'Instance not authenticated'}), 400 + + # Get JWT token from the launched instance using management API key + jwt_response = requests.post( + f"{instance_url.rstrip('/')}/api/admin/management-token", + headers={ + 'X-API-Key': instance.connection_token, + 'Accept': 'application/json' + }, + timeout=10 + ) + + if jwt_response.status_code != 200: + return jsonify({'error': f'Failed to get JWT token: {jwt_response.text}'}), 400 + + jwt_data = jwt_response.json() + jwt_token = jwt_data.get('token') + + if not jwt_token: + return jsonify({'error': 'No JWT token received'}), 400 + + # Copy SMTP settings to the launched instance + smtp_response = requests.post( + f"{instance_url.rstrip('/')}/api/admin/key-value", + headers={ + 'Authorization': f'Bearer {jwt_token}', + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + json={ + 'key': 'smtp_settings', + 'value': smtp_settings + }, + timeout=10 + ) + + if smtp_response.status_code != 200: + return jsonify({'error': f'Failed to copy SMTP settings: {smtp_response.text}'}), 400 + + # Log the SMTP settings copy + current_app.logger.info(f"SMTP settings copied to instance {instance_url}") + + return jsonify({ + 'message': 'SMTP settings copied successfully', + 'data': smtp_settings + }) + + except Exception as e: + current_app.logger.error(f"Error copying SMTP settings: {str(e)}") return jsonify({'error': str(e)}), 500 \ No newline at end of file diff --git a/static/js/launch_progress.js b/static/js/launch_progress.js index b3159d8..a45a761 100644 --- a/static/js/launch_progress.js +++ b/static/js/launch_progress.js @@ -172,6 +172,18 @@ function initializeSteps() { `; stepsContainer.appendChild(credentialsStep); + // Add Copy SMTP Settings step + const smtpStep = document.createElement('div'); + smtpStep.className = 'step-item'; + smtpStep.innerHTML = ` +
+
+
Copy SMTP Settings
+

Configuring email settings...

+
+ `; + stepsContainer.appendChild(smtpStep); + // Add Send Completion Email step const emailStep = document.createElement('div'); emailStep.className = 'step-item'; @@ -707,8 +719,78 @@ async function startLaunch(data) { `; credentialsStep.querySelector('.step-content').appendChild(credentialsDetails); - // Step 14: Send Completion Email - await updateStep(14, 'Send Completion Email', 'Sending notification to client...'); + // Step 14: Copy SMTP Settings + await updateStep(14, 'Copy SMTP Settings', 'Configuring email settings...'); + const smtpResult = await copySmtpSettings(`https://${data.webAddresses[0]}`); + + if (!smtpResult.success) { + throw new Error(`SMTP settings copy failed: ${smtpResult.error}`); + } + + // Update the SMTP step to show success + const smtpStep = document.querySelectorAll('.step-item')[13]; + smtpStep.classList.remove('active'); + smtpStep.classList.add('completed'); + smtpStep.querySelector('.step-status').textContent = 'Successfully copied SMTP settings'; + + // Add SMTP details + const smtpDetails = document.createElement('div'); + smtpDetails.className = 'mt-3'; + smtpDetails.innerHTML = ` +
+
+
SMTP Settings Copied
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
SMTP Host${smtpResult.data.smtp_host || 'Not set'}
SMTP Port${smtpResult.data.smtp_port || 'Not set'}
Security${smtpResult.data.smtp_security || 'None'}
Username${smtpResult.data.smtp_username || 'Not set'}
From Email${smtpResult.data.smtp_from_email || 'Not set'}
From Name${smtpResult.data.smtp_from_name || 'Not set'}
StatusCopied Successfully
+
+
+ + Email Configuration Complete! The launched instance now has the same SMTP settings as the master instance and can send emails independently. +
+
+
+ `; + smtpStep.querySelector('.step-content').appendChild(smtpDetails); + + // Step 15: Send Completion Email + await updateStep(15, 'Send Completion Email', 'Sending notification to client...'); const emailResult = await sendCompletionEmail(`https://${data.webAddresses[0]}`, data.company, credentialsResult.data); if (!emailResult.success) { @@ -716,7 +798,7 @@ async function startLaunch(data) { } // Update the email step to show success - const emailStep = document.querySelectorAll('.step-item')[13]; + const emailStep = document.querySelectorAll('.step-item')[14]; emailStep.classList.remove('active'); emailStep.classList.add('completed'); emailStep.querySelector('.step-status').textContent = 'Successfully sent completion email'; @@ -901,7 +983,7 @@ Thank you for choosing DocuPulse! } catch (error) { console.error('Launch failed:', error); - await updateStep(14, 'Send Completion Email', `Error: ${error.message}`); + await updateStep(15, 'Send Completion Email', `Error: ${error.message}`); showError(error.message); } } @@ -2028,6 +2110,43 @@ async function updateAdminCredentials(instanceUrl, email) { } } +async function copySmtpSettings(instanceUrl) { + try { + console.log('Copying SMTP settings to:', instanceUrl); + + const response = await fetch('/api/admin/copy-smtp-settings', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content + }, + body: JSON.stringify({ + instance_url: instanceUrl + }) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`Failed to copy SMTP settings: ${errorText}`); + } + + const result = await response.json(); + console.log('SMTP settings copied successfully:', result); + + return { + success: true, + message: result.message, + data: result.data + }; + } catch (error) { + console.error('Error copying SMTP settings:', error); + return { + success: false, + error: error.message + }; + } +} + async function sendCompletionEmail(instanceUrl, company, credentials) { try { console.log('Sending completion email to:', company.email);