From 4bbd420ccff3b640612b451244d3d3422e3b470e Mon Sep 17 00:00:00 2001 From: piotrruss Date: Mon, 21 Aug 2023 23:41:26 +0200 Subject: user verification --- .env.example | 3 +++ helpers/createJwt.js | 2 +- helpers/sendMail.js | 25 +++++++++++++++++++++++++ model/User.js | 10 ++++++++-- package-lock.json | 11 ++++++++++- package.json | 3 ++- routes/authRoutes.js | 46 +++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 helpers/sendMail.js diff --git a/.env.example b/.env.example index 6607bc1..24e06c7 100644 --- a/.env.example +++ b/.env.example @@ -2,3 +2,6 @@ PORT= DB_CONNECT= RSA_PASS= TOKEN_EXPIRES_IN= +MAIL_SMTP_SERVER= +MAIL_ADDRESS= +MAIL_PASSWORD= diff --git a/helpers/createJwt.js b/helpers/createJwt.js index 6c6983b..3678790 100644 --- a/helpers/createJwt.js +++ b/helpers/createJwt.js @@ -4,7 +4,7 @@ const cert = fs.readFileSync(`${process.cwd()}/cert/jwt_256_rsa`) const createJwt = (user, sessionId) => jwt.sign({ email: user.email, - verified: !!user.verify, + verified: user.verify === '', role: user.role, sessionId, }, diff --git a/helpers/sendMail.js b/helpers/sendMail.js new file mode 100644 index 0000000..6e3a370 --- /dev/null +++ b/helpers/sendMail.js @@ -0,0 +1,25 @@ +const mailer = require('nodemailer') + +const sendMail = ({to, subject, text, html}) => { + const transporter = mailer.createTransport({ + port: 465, + host: process.env.MAIL_SMTP_SERVER, + auth: { + user: process.env.MAIL_ADDRESS, + pass: process.env.MAIL_PASSWORD + }, + secure: true + }) + + const mailData = { + from: `"Pruss.it" <${process.env.MAIL_ADDRESS}>`, + to, + subject, + text, + html + } + + return transporter.sendMail(mailData) +} + +module.exports = sendMail diff --git a/model/User.js b/model/User.js index 8009980..07ae09f 100644 --- a/model/User.js +++ b/model/User.js @@ -50,8 +50,6 @@ userSchema.statics.checkRefreshToken = async ({ email, sessionId, refreshToken } if (!user) throw new Error('User not found') - console.log(user) - const session = user.sessions.find(s => s._id.toString() === sessionId) if (!session) throw new Error('Session not found') @@ -103,6 +101,14 @@ userSchema.statics.removeSession = async ({ email, sessionId }) => ( ) ) +userSchema.statics.verify = async ({ email, code }) => ( + await User.findOneAndUpdate( + { email, verify: code }, + { verify: '' }, + { new: true } + ) +) + userSchema.statics.getSessions = async ({ email }) => { const user = await User.findOne({ email }) diff --git a/package-lock.json b/package-lock.json index c4b1b8a..39694a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,8 @@ "dotenv-safe": "^8.2.0", "express": "^4.17.3", "jsonwebtoken": "^9.0.1", - "mongoose": "^6.3.1" + "mongoose": "^6.3.1", + "nodemailer": "^6.9.4" } }, "node_modules/@aws-crypto/crc32": { @@ -1846,6 +1847,14 @@ "node": ">= 0.6" } }, + "node_modules/nodemailer": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", + "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", diff --git a/package.json b/package.json index 65234cb..51a4c20 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "dotenv-safe": "^8.2.0", "express": "^4.17.3", "jsonwebtoken": "^9.0.1", - "mongoose": "^6.3.1" + "mongoose": "^6.3.1", + "nodemailer": "^6.9.4" } } diff --git a/routes/authRoutes.js b/routes/authRoutes.js index 110e7f4..ad612ce 100644 --- a/routes/authRoutes.js +++ b/routes/authRoutes.js @@ -1,5 +1,50 @@ const router = require('express').Router() const User = require('../model/User') +const createJwt = require('../helpers/createJwt') +const sendMail = require('../helpers/sendMail') + +// Verify (send verification email) +router.get('/verify', async (req, res) => { + try { + const { email } = req.user + + if (!email) throw new Error() + + const { verify } = await User.findOne({ email }) + + sendMail({ + to: email, + subject: 'Verification Code', + text: `Last step missing - verify your account.\nYour verification code: ${verify}`, + html: `

Last step missing - verify your account.


Your verification code: ${verify}

`, + }) + + res.status(204).send() + } catch (err) { + res.status(401).send({ error: 'Could not verify user' }) + } +}) + +// Verify +router.post('/verify', async (req, res) => { + try { + const { email } = req.user + const code = req.body.code + + if (!email || !code) throw new Error() + + const user = await User.verify({ email, code }) + + if (!user) throw new Error() + + const jwtToken = createJwt(user) + + res.status(200).send({ jwtToken }) + } catch (err) { + res.status(401).send({ error: 'Could not verify user' }) + } +}) + // Logout (pass sessionId or will logout one from jwt) router.post('/logout', async (req, res) => { @@ -12,7 +57,6 @@ router.post('/logout', async (req, res) => { res.status(204).send() } catch (err) { - console.log(err) res.status(401).send({ error: 'Could not logout' }) } }) -- cgit v1.2.3