Оглавление:
Карта сайта:
Оглавление:
Карта сайта:
emails/reset.js
const config = require('../config/config');//подключаем конфиг /** * Возврощаем функцию * @param email - куда будем отправлять письмо * @param token - токен , по нему определяем какому пользователю меняем пароль * @returns {{to: *, from: string, subject: string, html: string}} */ module.exports = function(email, token){ return { to: email,// - куда будем отправлять письмо from: config.from,//от кого письмо subject:'Восстановление пароля',//тема письма //тело письма html: `<h1>Восстановить пароль</h1> <p>Если вы не делали запрос просто проигнорируйте письмо, иначе пройдите по ссылке <a href="${config.base_url}/auth/password/${token}"> Сбросить пароль</a> </p> <hr> <a href="${config.base_url}"> Перейти в магазин</a> ` } };
routes/auth.js
const {Router} = require('express');//модуль express const bcrypt = require('bcryptjs');//Модуль шифрования const User = require('../models/user');//модель пользователя const nodeMailer = require('nodemailer');//mailer const sendGrid = require('nodemailer-sendgrid-transport');//Транспорт для mailer const config = require('../config/config');//конфигурация const regMail = require('../emails/registration');//конфигурация для почтовой рассылки const resetMail = require('../emails/reset');//конфигурация для почтовой рассылки const crypto = require('crypto');//Встроеннная в node.js криптографическая библиотека const router = Router();//инициируем роутер const transporter = nodeMailer.createTransport(sendGrid({//инициируем коннект с sendGrid, по токену auth: { api_key:config.send_grid_key//токен, его можно получить в самом сервисе // , https://app.sendgrid.com/ -> setting->api_key, выбираем full } })); /** * Восстановить пароль ссылка * первый параметр адрес страницы, в данном случае используется префикс при регистрации ройтера, * второй параметр callback - обработчик запроса req - request , запрос от браузера * res - response, ответ сервера */ router.get('/reset', (req, res) => { res.render('auth/reset',{ //шаблон template/auth/reset.hbs title: 'восстановить пароль', error: req.flash('error')//вывод в шаблон ошибки, выводим по ключу error }); }); /** * Восстановить пароль * первый параметр адрес страницы, в данном случае используется префикс при регистрации ройтера, * второй параметр callback - обработчик запроса req - request , запрос от браузера * res - response, ответ сервера */ router.post('/reset', (req, res) => { /** * 32 - колличество рандомных символов * buffer - Буфер */ crypto.randomBytes(32, async (err, buffer) => { if(err){ req.flash('error', 'Что-то пошло не так');//сообщение об ошибке res.redirect('/auth/reset');//редирект на страницу сброса пароля } const token = buffer.toString('hex');//получаем token в 16-ричном виде const candidate = await User.findOne({//Ищем пользователя с таким email email: req.body.email }); if(candidate){//если пользовател с таким email есть candidate.resetToken = token;//присваиваем токен candidate.resetTokenExp = Date.now() + 3600;//1 час время жизни токен await candidate.save();//сохраняем в таблице user transporter.sendMail(resetMail(candidate.email, token));//Отпровляем сообщение на посту res.redirect('/auth/login');//редирект на страницу Login } else{ req.flash('error', 'Неизвестный email');//Вывод ошибки res.redirect('/auth/reset');//редирект } }); }); module.exports = router;//Экспортирум роутер
template/auth/reset.hbs
<div class="row"> <div id="login" class="col s6 offset-s3"> <br> <div class="card"> <div class="card-content"> <span class="card-title"> войти в магазин </span> {{#if error}} <p class="alert">{{error}}</p> {{/if}} <form action="/auth/reset" method="post"> <div class="row"> <div class="input-field col s12"> <input id="email" type="text" name="email" class="validate" required /> <label for="email">email</label> <span class="helper-text" data-error="введите email" data-success="right"></span> </div> </div> <div class="row"> <div class="input-field col"> <input type="hidden" name="_csrf" value="{{csrf}}"> <input type="submit" class="btn" value="Сбросить пароль"> </div> </div> </form> </div> </div> </div> </div>