portfolio-page/backend/routes/contact.js

96 lines
2.5 KiB
JavaScript

// Currently not in use
import express from 'express'
import rateLimit from 'express-rate-limit'
import { body, validationResult } from 'express-validator'
import { sendContactEmail } from '../services/emailService.js'
const router = express.Router()
// GDPR compliant rate limiting
const contactLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 3, // Limit each IP to 3 requests per windowMs
message: {
error: 'Too many contact requests from this IP, please try again later.',
retryAfter: 15 * 60,
},
standardHeaders: true,
legacyHeaders: false,
})
// GDPR compliant validation
const validateContactForm = [
body('firstName').trim().isLength({ min: 1, max: 50 }).escape(),
body('lastName').trim().isLength({ min: 1, max: 50 }).escape(),
body('email').trim().isEmail().normalizeEmail().isLength({ max: 254 }),
body('subject').trim().isLength({ min: 1, max: 100 }).escape(),
body('message').trim().isLength({ min: 10, max: 2000 }).escape(),
body('gdprConsent').equals('true').withMessage('GDPR consent required'),
body('website').optional().isEmpty(), // Honeypot
]
router.post('/', contactLimiter, validateContactForm, async (req, res) => {
try {
const errors = validationResult(req)
if (!errors.isEmpty()) {
return res.status(400).json({
success: false,
message: 'Invalid form data.',
errors: errors.array(),
})
}
const {
firstName,
lastName,
email,
subject,
message,
gdprConsent,
website,
} = req.body
// Honeypot check
if (website) {
console.warn('🚨 Spam detected:', req.ip)
return res.status(400).json({
success: false,
message: 'Invalid submission detected.',
})
}
// GDPR consent check
if (gdprConsent !== 'true') {
return res.status(400).json({
success: false,
message: 'GDPR consent required.',
})
}
// Send email with minimal logging for GDPR
await sendContactEmail({
firstName,
lastName,
email,
subject,
message,
senderIP: req.ip,
userAgent: req.get('User-Agent'),
})
res.json({
success: true,
message: "Thank you for your message! I'll get back to you soon.",
})
} catch (error) {
console.error('❌ Contact error:', error.message) // No personal data in logs
res.status(500).json({
success: false,
message: 'Failed to send message. Please try again later.',
})
}
})
export { router as contactRouter }