diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 5153feb..464173b 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -23,7 +23,7 @@ export const handle: Handle = async ({ event, resolve }) => { // Force password change if (event.locals.user?.mustChangePassword) { const path = event.url.pathname; - if (path !== '/change-password' && path !== '/logout' && !path.startsWith('/api/')) { + if (path !== '/change-password' && path !== '/logout' && !path.startsWith('/api/worker/')) { throw redirect(302, '/change-password'); } } diff --git a/src/lib/server/email.ts b/src/lib/server/email.ts index ff327a5..18ae0cf 100644 --- a/src/lib/server/email.ts +++ b/src/lib/server/email.ts @@ -1,5 +1,9 @@ import nodemailer from 'nodemailer'; +function escHtml(s: string): string { + return s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); +} + function getTransporter() { if (!process.env.SMTP_USER) return null; @@ -33,8 +37,8 @@ export async function sendApplicationNotification( const subject = `[${orgName}] New ${type} application from ${applicantName}`; const html = `
Applicant: ${applicantName}
- ${petName ? `Pet: ${petName}
` : ''} +Applicant: ${escHtml(applicantName)}
+ ${petName ? `Pet: ${escHtml(petName)}
` : ''}Log in to your admin dashboard to review this application.
`; await sendEmail(staffEmail, subject, html); @@ -51,8 +55,8 @@ export async function sendApplicationStatusUpdate( const subject = `[${orgName}] Your ${type} application has been ${status}`; const html = `Hi ${applicantName},
-Your ${type} application has been ${status}.
+Hi ${escHtml(applicantName)},
+Your ${escHtml(type)} application has been ${escHtml(status)}.
Visit ${siteUrl} for more information.
`; await sendEmail(to, subject, html); @@ -87,9 +91,9 @@ export async function sendRegistrationNotification( const subject = `[${orgName}] New registration request from ${name}`; const html = `Name: ${name}
-Email: ${email}
-Reason: ${reason}
+Name: ${escHtml(name)}
+Email: ${escHtml(email)}
+Reason: ${escHtml(reason)}
Log in to your admin dashboard to approve or deny this request.
`; await sendEmail(staffEmail, subject, html); @@ -104,7 +108,7 @@ export async function sendRegistrationApproved( const subject = `[${orgName}] Your account has been approved!`; const html = `Hi ${name}, your account at ${orgName} has been approved.
+Hi ${escHtml(name)}, your account at ${escHtml(orgName)} has been approved.
Log in at: ${loginUrl}
`; await sendEmail(to, subject, html); @@ -118,7 +122,7 @@ export async function sendRegistrationDenied( const subject = `[${orgName}] Registration update`; const html = `Hi ${name}, unfortunately your registration request at ${orgName} was not approved at this time.
+Hi ${escHtml(name)}, unfortunately your registration request at ${escHtml(orgName)} was not approved at this time.
If you believe this is an error, please contact us.
`; await sendEmail(to, subject, html); @@ -204,9 +208,9 @@ export async function sendContactNotification( const subject = `[${orgName}] Contact form: ${messageSubject || 'New message'}`; const html = `From: ${senderName} (${senderEmail})
-Subject: ${messageSubject || 'N/A'}
-${message}
+From: ${escHtml(senderName)} (${escHtml(senderEmail)})
+Subject: ${escHtml(messageSubject || 'N/A')}
+${escHtml(message)}
`; await sendEmail(staffEmail, subject, html); } diff --git a/src/lib/server/upload.ts b/src/lib/server/upload.ts index ede3387..2190653 100644 --- a/src/lib/server/upload.ts +++ b/src/lib/server/upload.ts @@ -40,7 +40,10 @@ export async function saveUpload( throw new Error('File content does not match declared type'); } - const ext = file.name.split('.').pop()?.toLowerCase() || 'jpg'; + const mimeToExt: Record' + pet.name + '
' + - '' + + '' + esc(pet.name) + '
' + + '' + '