diff --git a/backend/src/config/index.js b/backend/src/config/index.js index e376c51e3..7b254c044 100644 --- a/backend/src/config/index.js +++ b/backend/src/config/index.js @@ -3,13 +3,13 @@ import dotenv from 'dotenv' dotenv.config() const { -MAPBOX_TOKEN, -JWT_SECRET, -PRIVATE_KEY_PASSPHRASE, -SMTP_HOST, -SMTP_PORT, -SMTP_USERNAME, -SMTP_PASSWORD, + MAPBOX_TOKEN, + JWT_SECRET, + PRIVATE_KEY_PASSPHRASE, + SMTP_HOST, + SMTP_PORT, + SMTP_USERNAME, + SMTP_PASSWORD, } = process.env export const requiredConfigs = { MAPBOX_TOKEN, JWT_SECRET, PRIVATE_KEY_PASSPHRASE } diff --git a/backend/src/schema/resolvers/passwordReset.js b/backend/src/schema/resolvers/passwordReset.js index baf6c1339..b80e3d6aa 100644 --- a/backend/src/schema/resolvers/passwordReset.js +++ b/backend/src/schema/resolvers/passwordReset.js @@ -2,6 +2,7 @@ import uuid from 'uuid/v4' import bcrypt from 'bcryptjs' import CONFIG from '../../config' import nodemailer from 'nodemailer' +import { resetPasswordMail, wrongAccountMail } from './passwordReset/emailTemplates' const transporter = () => { const { SMTP_HOST: host, SMTP_PORT: port, SMTP_USERNAME: user, SMTP_PASSWORD: pass } = CONFIG @@ -24,33 +25,28 @@ export async function createPasswordReset(options) { MATCH (u:User) WHERE u.email = $email CREATE(pr:PasswordReset {code: $code, issuedAt: datetime($issuedAt), usedAt: NULL}) MERGE (u)-[:REQUESTED]->(pr) - RETURN pr + RETURN u ` const transactionRes = await session.run(cypher, { issuedAt: issuedAt.toISOString(), code, email, }) - const resets = transactionRes.records.map(record => record.get('pr')) + const users = transactionRes.records.map(record => record.get('u')) session.close() - return resets + return users } export default { Mutation: { requestPasswordReset: async (_, { email }, { driver }) => { const code = uuid().substring(0, 6) - await createPasswordReset({ driver, code, email }) + const [user] = await createPasswordReset({ driver, code, email }) if (CONFIG.SMTP_HOST && CONFIG.SMTP_PORT) { - await transporter().sendMail({ - from: '"Human Connection" ', // sender address - to: email, // list of receivers - subject: 'Password Reset', // Subject line - text: `Code is ${code}`, // plain text body - html: `Code is ${code}`, // plain text body - }) + const name = (user && user.name) || '' + const mailTemplate = user ? resetPasswordMail : wrongAccountMail + await transporter().sendMail(mailTemplate({ email, code, name })) } - return true }, resetPassword: async (_, { email, code, newPassword }, { driver }) => { diff --git a/backend/src/schema/resolvers/passwordReset/emailTemplates.js b/backend/src/schema/resolvers/passwordReset/emailTemplates.js new file mode 100644 index 000000000..10d9c4ed5 --- /dev/null +++ b/backend/src/schema/resolvers/passwordReset/emailTemplates.js @@ -0,0 +1,85 @@ +import CONFIG from '../../../config' + +export const from = '"Human Connection" ' + +export const resetPasswordMail = options => { + const { + name, + email, + code, + subject = 'Use this link to reset your password. The link is only valid for 24 hours.', + supportUrl = 'https://human-connection.org/en/contact/', + } = options + const actionUrl = new URL('/password-reset/change-password', CONFIG.CLIENT_URI) + actionUrl.searchParams.set('code', code) + actionUrl.searchParams.set('email', email) + + return { + to: email, + subject, + text: ` +Hi ${name}! + +You recently requested to reset your password for your Human Connection account. +Use the button below to reset it. This password reset is only valid for the next +24 hours. + +${actionUrl} + +If you did not request a password reset, please ignore this email or contact +support if you have questions: + +${supportUrl} + +Thanks, +The Human Connection Team + +If you’re having trouble with the link above, you can manually copy and +paste the following code into your browser window: + +${code} + +Human Connection gemeinnützige GmbH +Bahnhofstr. 11 +73235 Weilheim / Teck +Deutschland + `, + } +} + +export const wrongAccountMail = options => { + const { + email, + subject = `We received a request to reset your password with this email address (${email})`, + supportUrl = 'https://human-connection.org/en/contact/', + } = options + const actionUrl = new URL('/password-reset/request', CONFIG.CLIENT_URI) + return { + to: email, + subject, + text: ` +We received a request to reset the password to access Human Connection with your +email address, but we were unable to find an account associated with this +address. + +If you use Human Connection and were expecting this email, consider trying to +request a password reset using the email address associated with your account. +Try a different email: + +${actionUrl} + +If you do not use Human Connection or did not request a password reset, please +ignore this email. Feel free to contact support if you have further questions: + +${supportUrl} + +Thanks, +The Human Connection Team + +Human Connection gemeinnützige GmbH +Bahnhofstr. 11 +73235 Weilheim / Teck +Deutschland + `, + } +}