Refactor CookieBanner and Contact API for improved functionality and security
- Removed localStorage fallback from CookieBanner, simplifying consent management. - Refactored manual review email handling in the Contact API to utilize HTML templates for better structure and security. - Enhanced email content generation by escaping HTML special characters and using template files for dynamic data insertion.
This commit is contained in:
@@ -311,22 +311,4 @@ export const POST: APIRoute = async ({ request, clientAddress }) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const manualReviewPOST: APIRoute = async ({ request }) => {
|
||||
const { token, email: submittedEmail, justification } = await request.json();
|
||||
try {
|
||||
const payload = jwt.verify(token, MANUAL_REVIEW_SECRET) as { email: string, message: string };
|
||||
if (payload.email !== submittedEmail) {
|
||||
return new Response(JSON.stringify({ error: 'Email does not match original submission.' }), { status: 403 });
|
||||
}
|
||||
// Send to manual review mailbox
|
||||
await sendEmail(
|
||||
MANUAL_REVIEW_EMAIL,
|
||||
'Manual Review Requested: Contact Form Submission',
|
||||
`<p><strong>Email:</strong> ${submittedEmail}</p><p><strong>Message:</strong> ${payload.message}</p><p><strong>Justification:</strong> ${justification || 'None provided'}</p>`,
|
||||
`Email: ${submittedEmail}\nMessage: ${payload.message}\nJustification: ${justification || 'None provided'}`
|
||||
);
|
||||
return new Response(JSON.stringify({ success: true }));
|
||||
} catch (_err) {
|
||||
return new Response(JSON.stringify({ error: 'Invalid or expired token.' }), { status: 400 });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { sendEmail } from '../../../utils/email-handler';
|
||||
import { sendEmail, escapeHtml } from '../../../utils/email-handler';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
const MANUAL_REVIEW_SECRET = process.env.MANUAL_REVIEW_SECRET;
|
||||
const MANUAL_REVIEW_EMAIL = 'manual-review@365devnet.eu';
|
||||
|
||||
// Utility to escape HTML special characters
|
||||
function escapeHtml(str: string): string {
|
||||
return str
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
async function getTemplate(templateName: string, data: Record<string, string>): Promise<string> {
|
||||
const templatePath = path.join(process.cwd(), 'src', 'templates', 'email', `${templateName}.html`);
|
||||
let template = await fs.readFile(templatePath, 'utf-8');
|
||||
for (const key in data) {
|
||||
template = template.replace(new RegExp(`{{${key}}}`, 'g'), data[key]);
|
||||
}
|
||||
return template;
|
||||
}
|
||||
|
||||
export const POST: APIRoute = async ({ request }) => {
|
||||
@@ -23,10 +24,15 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
return new Response(JSON.stringify({ error: 'Email does not match original submission.' }), { status: 403 });
|
||||
}
|
||||
// Send to manual review mailbox
|
||||
const html = await getTemplate('manual-review', {
|
||||
email: escapeHtml(submittedEmail),
|
||||
message: escapeHtml(payload.message),
|
||||
justification: escapeHtml(justification || 'None provided'),
|
||||
});
|
||||
await sendEmail(
|
||||
MANUAL_REVIEW_EMAIL,
|
||||
'Manual Review Requested: Contact Form Submission',
|
||||
`<p><strong>Email:</strong> ${escapeHtml(submittedEmail)}</p><p><strong>Message:</strong> ${escapeHtml(payload.message)}</p><p><strong>Justification:</strong> ${escapeHtml(justification || 'None provided')}</p>`,
|
||||
html,
|
||||
`Email: ${submittedEmail}\nMessage: ${payload.message}\nJustification: ${justification || 'None provided'}`
|
||||
);
|
||||
return new Response(JSON.stringify({ success: true }));
|
||||
@@ -34,4 +40,6 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
return new Response(JSON.stringify({ error: 'Invalid or expired token.' }), { status: 400 });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user