225d017718
- Fixed frontend API URL configuration to use correct port 3002 - Fixed create event functionality by adding proper endpoint and fixing JSON parsing - Fixed email settings save functionality by importing logActivity correctly - Fixed admin settings save functionality by using api client instead of direct fetch - Implemented password change functionality with modal and backend endpoint - Added updated_at column to admin_users table - Fixed all mock data issues - now using real backend data throughout 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
277 lines
7.8 KiB
JavaScript
277 lines
7.8 KiB
JavaScript
const express = require('express');
|
|
const nodemailer = require('nodemailer');
|
|
const { body, validationResult } = require('express-validator');
|
|
const { db, logActivity } = require('../database/db');
|
|
const { adminAuth } = require('../middleware/auth');
|
|
const router = express.Router();
|
|
|
|
// Get email configuration
|
|
router.get('/config', adminAuth, async (req, res) => {
|
|
try {
|
|
const config = await db('email_configs').first();
|
|
|
|
if (!config) {
|
|
return res.json({
|
|
smtp_host: '',
|
|
smtp_port: 587,
|
|
smtp_secure: false,
|
|
smtp_user: '',
|
|
smtp_pass: '', // Don't send actual password
|
|
from_email: '',
|
|
from_name: ''
|
|
});
|
|
}
|
|
|
|
// Don't send the actual password
|
|
res.json({
|
|
...config,
|
|
smtp_pass: config.smtp_pass ? '********' : ''
|
|
});
|
|
} catch (error) {
|
|
console.error('Email config fetch error:', error);
|
|
res.status(500).json({ error: 'Failed to fetch email configuration' });
|
|
}
|
|
});
|
|
|
|
// Update email configuration
|
|
router.post('/config', [
|
|
adminAuth,
|
|
body('smtp_host').notEmpty().withMessage('SMTP host is required'),
|
|
body('smtp_port').isInt({ min: 1, max: 65535 }).withMessage('Invalid port number'),
|
|
body('from_email').isEmail().withMessage('Invalid from email address')
|
|
], async (req, res) => {
|
|
try {
|
|
const errors = validationResult(req);
|
|
if (!errors.isEmpty()) {
|
|
return res.status(400).json({ errors: errors.array() });
|
|
}
|
|
|
|
const {
|
|
smtp_host,
|
|
smtp_port,
|
|
smtp_secure,
|
|
smtp_user,
|
|
smtp_pass,
|
|
from_email,
|
|
from_name
|
|
} = req.body;
|
|
|
|
// Check if config exists
|
|
const existingConfig = await db('email_configs').first();
|
|
|
|
const configData = {
|
|
smtp_host,
|
|
smtp_port: parseInt(smtp_port),
|
|
smtp_secure: smtp_secure || false,
|
|
smtp_user: smtp_user || '',
|
|
from_email,
|
|
from_name: from_name || 'Photo Sharing',
|
|
updated_at: new Date()
|
|
};
|
|
|
|
// Only update password if provided and not masked
|
|
if (smtp_pass && smtp_pass !== '********') {
|
|
configData.smtp_pass = smtp_pass;
|
|
}
|
|
|
|
if (existingConfig) {
|
|
await db('email_configs')
|
|
.where('id', existingConfig.id)
|
|
.update(configData);
|
|
} else {
|
|
await db('email_configs').insert(configData);
|
|
}
|
|
|
|
// Log activity
|
|
await logActivity('email_config_updated',
|
|
{ smtp_host, from_email },
|
|
null,
|
|
{ type: 'admin', id: req.user.id, name: req.user.username }
|
|
);
|
|
|
|
res.json({ message: 'Email configuration updated successfully' });
|
|
} catch (error) {
|
|
console.error('Email config update error:', error);
|
|
res.status(500).json({ error: 'Failed to update email configuration' });
|
|
}
|
|
});
|
|
|
|
// Test email configuration
|
|
router.post('/test', adminAuth, async (req, res) => {
|
|
try {
|
|
const { test_email } = req.body;
|
|
|
|
if (!test_email) {
|
|
return res.status(400).json({ error: 'Test email address is required' });
|
|
}
|
|
|
|
// Get email config
|
|
const config = await db('email_configs').first();
|
|
|
|
if (!config) {
|
|
return res.status(400).json({ error: 'Email configuration not found. Please configure SMTP settings first.' });
|
|
}
|
|
|
|
// Create transporter
|
|
const transporter = nodemailer.createTransport({
|
|
host: config.smtp_host,
|
|
port: config.smtp_port,
|
|
secure: config.smtp_secure,
|
|
auth: config.smtp_user ? {
|
|
user: config.smtp_user,
|
|
pass: config.smtp_pass
|
|
} : undefined
|
|
});
|
|
|
|
// Send test email
|
|
await transporter.sendMail({
|
|
from: `${config.from_name} <${config.from_email}>`,
|
|
to: test_email,
|
|
subject: 'Test Email - Photo Sharing Platform',
|
|
html: `
|
|
<h2>Test Email Successful!</h2>
|
|
<p>This is a test email from your Photo Sharing platform.</p>
|
|
<p>If you're seeing this, your email configuration is working correctly.</p>
|
|
<hr>
|
|
<p style="color: #666; font-size: 12px;">
|
|
Sent from: ${config.from_email}<br>
|
|
SMTP Host: ${config.smtp_host}<br>
|
|
Time: ${new Date().toISOString()}
|
|
</p>
|
|
`,
|
|
text: 'Test Email Successful! Your email configuration is working correctly.'
|
|
});
|
|
|
|
res.json({ message: 'Test email sent successfully' });
|
|
} catch (error) {
|
|
console.error('Test email error:', error);
|
|
res.status(500).json({
|
|
error: 'Failed to send test email',
|
|
details: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// Get email templates
|
|
router.get('/templates', adminAuth, async (req, res) => {
|
|
try {
|
|
const templates = await db('email_templates')
|
|
.select('*')
|
|
.orderBy('template_key');
|
|
|
|
// Parse variables JSON
|
|
const formattedTemplates = templates.map(template => ({
|
|
...template,
|
|
variables: template.variables ? JSON.parse(template.variables) : []
|
|
}));
|
|
|
|
res.json(formattedTemplates);
|
|
} catch (error) {
|
|
console.error('Email templates fetch error:', error);
|
|
res.status(500).json({ error: 'Failed to fetch email templates' });
|
|
}
|
|
});
|
|
|
|
// Get single template
|
|
router.get('/templates/:key', adminAuth, async (req, res) => {
|
|
try {
|
|
const template = await db('email_templates')
|
|
.where('template_key', req.params.key)
|
|
.first();
|
|
|
|
if (!template) {
|
|
return res.status(404).json({ error: 'Template not found' });
|
|
}
|
|
|
|
res.json({
|
|
...template,
|
|
variables: template.variables ? JSON.parse(template.variables) : []
|
|
});
|
|
} catch (error) {
|
|
console.error('Email template fetch error:', error);
|
|
res.status(500).json({ error: 'Failed to fetch email template' });
|
|
}
|
|
});
|
|
|
|
// Update email template
|
|
router.put('/templates/:key', [
|
|
adminAuth,
|
|
body('subject').notEmpty().withMessage('Subject is required'),
|
|
body('body_html').notEmpty().withMessage('HTML body is required')
|
|
], async (req, res) => {
|
|
try {
|
|
const errors = validationResult(req);
|
|
if (!errors.isEmpty()) {
|
|
return res.status(400).json({ errors: errors.array() });
|
|
}
|
|
|
|
const { subject, body_html, body_text } = req.body;
|
|
|
|
const updated = await db('email_templates')
|
|
.where('template_key', req.params.key)
|
|
.update({
|
|
subject,
|
|
body_html,
|
|
body_text: body_text || '',
|
|
updated_at: new Date()
|
|
});
|
|
|
|
if (!updated) {
|
|
return res.status(404).json({ error: 'Template not found' });
|
|
}
|
|
|
|
// Log activity
|
|
await db('activity_logs').insert({
|
|
activity_type: 'email_template_updated',
|
|
actor_type: 'admin',
|
|
actor_id: req.user.id,
|
|
actor_name: req.user.username,
|
|
metadata: JSON.stringify({ template_key: req.params.key })
|
|
});
|
|
|
|
res.json({ message: 'Email template updated successfully' });
|
|
} catch (error) {
|
|
console.error('Email template update error:', error);
|
|
res.status(500).json({ error: 'Failed to update email template' });
|
|
}
|
|
});
|
|
|
|
// Preview email template
|
|
router.post('/templates/:key/preview', adminAuth, async (req, res) => {
|
|
try {
|
|
const template = await db('email_templates')
|
|
.where('template_key', req.params.key)
|
|
.first();
|
|
|
|
if (!template) {
|
|
return res.status(404).json({ error: 'Template not found' });
|
|
}
|
|
|
|
const { preview_data } = req.body;
|
|
|
|
// Replace variables in template
|
|
let htmlContent = template.body_html;
|
|
let textContent = template.body_text || '';
|
|
let subject = template.subject;
|
|
|
|
if (preview_data) {
|
|
Object.keys(preview_data).forEach(key => {
|
|
const regex = new RegExp(`{{${key}}}`, 'g');
|
|
htmlContent = htmlContent.replace(regex, preview_data[key]);
|
|
textContent = textContent.replace(regex, preview_data[key]);
|
|
subject = subject.replace(regex, preview_data[key]);
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
subject,
|
|
body_html: htmlContent,
|
|
body_text: textContent
|
|
});
|
|
} catch (error) {
|
|
console.error('Email template preview error:', error);
|
|
res.status(500).json({ error: 'Failed to preview email template' });
|
|
}
|
|
});
|
|
|
|
module.exports = router; |