mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-28 06:08:50 +01:00
Feat email password reset (#730)
* change name of auth.service to AuthService * Add emailEnabled to config api * Setup email * update nodemailer version * add translations * update .env.example * clean up console.log's) * refactor RequestPasswordReset component * chore: rebuild package-lock.json --------- Co-authored-by: Daniel Avila <messagedaniel@protonmail.com>
This commit is contained in:
parent
2faeebfae2
commit
30a49ae611
15 changed files with 221 additions and 171 deletions
|
|
@ -47,7 +47,7 @@
|
|||
"lodash": "^4.17.21",
|
||||
"meilisearch": "^0.33.0",
|
||||
"mongoose": "^7.1.1",
|
||||
"nodemailer": "^6.9.1",
|
||||
"nodemailer": "^6.9.4",
|
||||
"openai": "^3.2.1",
|
||||
"openid-client": "^5.4.2",
|
||||
"passport": "^0.6.0",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
const { registerUser, requestPasswordReset, resetPassword } = require('../services/auth.service');
|
||||
const { registerUser, requestPasswordReset, resetPassword } = require('../services/AuthService');
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
|
|
@ -32,10 +32,10 @@ const getUserController = async (req, res) => {
|
|||
const resetPasswordRequestController = async (req, res) => {
|
||||
try {
|
||||
const resetService = await requestPasswordReset(req.body.email);
|
||||
if (resetService.link) {
|
||||
return res.status(200).json(resetService);
|
||||
} else {
|
||||
if (resetService instanceof Error) {
|
||||
return res.status(400).json(resetService);
|
||||
} else {
|
||||
return res.status(200).json(resetService);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
const { logoutUser } = require('../../services/auth.service');
|
||||
const { logoutUser } = require('../../services/AuthService');
|
||||
|
||||
const logoutController = async (req, res) => {
|
||||
const { signedCookies = {} } = req;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ router.get('/', async function (req, res) {
|
|||
const serverDomain = process.env.DOMAIN_SERVER || 'http://localhost:3080';
|
||||
const registrationEnabled = process.env.ALLOW_REGISTRATION === 'true';
|
||||
const socialLoginEnabled = process.env.ALLOW_SOCIAL_LOGIN === 'true';
|
||||
const emailEnabled =
|
||||
!!process.env.EMAIL_SERVICE &&
|
||||
!!process.env.EMAIL_USERNAME &&
|
||||
!!process.env.EMAIL_PASSWORD &&
|
||||
!!process.env.EMAIL_FROM;
|
||||
|
||||
return res.status(200).send({
|
||||
appTitle,
|
||||
|
|
@ -30,6 +35,7 @@ router.get('/', async function (req, res) {
|
|||
serverDomain,
|
||||
registrationEnabled,
|
||||
socialLoginEnabled,
|
||||
emailEnabled,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
|
|
|||
|
|
@ -125,16 +125,26 @@ const requestPasswordReset = async (email) => {
|
|||
|
||||
const link = `${domains.client}/reset-password?token=${resetToken}&userId=${user._id}`;
|
||||
|
||||
sendEmail(
|
||||
user.email,
|
||||
'Password Reset Request',
|
||||
{
|
||||
name: user.name,
|
||||
link: link,
|
||||
},
|
||||
'./template/requestResetPassword.handlebars',
|
||||
);
|
||||
return { link };
|
||||
const emailEnabled =
|
||||
!!process.env.EMAIL_SERVICE &&
|
||||
!!process.env.EMAIL_USERNAME &&
|
||||
!!process.env.EMAIL_PASSWORD &&
|
||||
!!process.env.EMAIL_FROM;
|
||||
|
||||
if (emailEnabled) {
|
||||
sendEmail(
|
||||
user.email,
|
||||
'Password Reset Request',
|
||||
{
|
||||
name: user.name,
|
||||
link: link,
|
||||
},
|
||||
'requestPasswordReset.handlebars',
|
||||
);
|
||||
return { link: '' };
|
||||
} else {
|
||||
return { link };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -170,7 +180,7 @@ const resetPassword = async (userId, token, password) => {
|
|||
{
|
||||
name: user.name,
|
||||
},
|
||||
'./template/resetPassword.handlebars',
|
||||
'resetPassword.handlebars',
|
||||
);
|
||||
|
||||
await passwordResetToken.deleteOne();
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
/* eslint-disable no-undef */
|
||||
const nodemailer = require('nodemailer');
|
||||
const handlebars = require('handlebars');
|
||||
const fs = require('fs');
|
||||
|
|
@ -7,21 +5,19 @@ const path = require('path');
|
|||
|
||||
const sendEmail = async (email, subject, payload, template) => {
|
||||
try {
|
||||
// create reusable transporter object using the default SMTP transport
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: process.env.EMAIL_HOST,
|
||||
port: 465,
|
||||
service: process.env.EMAIL_SERVICE,
|
||||
auth: {
|
||||
user: process.env.EMAIL_USERNAME,
|
||||
pass: process.env.EMAIL_PASSWORD,
|
||||
},
|
||||
});
|
||||
|
||||
const source = fs.readFileSync(path.join(__dirname, template), 'utf8');
|
||||
const source = fs.readFileSync(path.join(__dirname, 'emails', template), 'utf8');
|
||||
const compiledTemplate = handlebars.compile(source);
|
||||
const options = () => {
|
||||
return {
|
||||
from: process.env.FROM_EMAIL,
|
||||
from: process.env.EMAIL_FROM,
|
||||
to: email,
|
||||
subject: subject,
|
||||
html: compiledTemplate(payload),
|
||||
|
|
@ -31,26 +27,17 @@ const sendEmail = async (email, subject, payload, template) => {
|
|||
// Send email
|
||||
transporter.sendMail(options(), (error, info) => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
return error;
|
||||
} else {
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
});
|
||||
console.log(info);
|
||||
return info;
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Example:
|
||||
sendEmail(
|
||||
"youremail@gmail.com,
|
||||
"Email subject",
|
||||
{ name: "Eze" },
|
||||
"./templates/layouts/main.handlebars"
|
||||
);
|
||||
*/
|
||||
|
||||
module.exports = sendEmail;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue