From c02da3011fe792d580eb0a5985a8d30f10278b3d Mon Sep 17 00:00:00 2001 From: pacifiquemboni Date: Sat, 20 Jul 2024 16:43:43 +0200 Subject: [PATCH] [Delivers ##187355054] user-updating-password-after -x-amount-of-time [Delivers ##187355054] user-updating-password-after Fix user updating password after x amount of time Fix user updating password after x amount of time --- .env.example | 1 + src/cronJob/password.cron.job.ts | 14 ++++- src/helps/MailTemplate.ts | 75 +++++++++++++++++++---- src/helps/nodemailer.ts | 2 +- src/middleware/changePasswordIgnored.ts | 63 ++++++++++++++++--- src/server.ts | 5 +- src/utils/sendChangePasswordNofication.ts | 7 ++- 7 files changed, 141 insertions(+), 26 deletions(-) diff --git a/.env.example b/.env.example index 97c819ea..e4785ebb 100644 --- a/.env.example +++ b/.env.example @@ -16,3 +16,4 @@ JWT_SECRET='your jwt secret' CLOUDINARY_NAME="your clouinary_name" CLOUDINARY_API_KEY='your cloudinary_api_key' CLOUDINARY_API_SECRET='your cloudinary_api_secret' +PASSWORD_EXPIRATION_PERIOD_MINUTES='minutes' diff --git a/src/cronJob/password.cron.job.ts b/src/cronJob/password.cron.job.ts index 14677597..be896e9f 100644 --- a/src/cronJob/password.cron.job.ts +++ b/src/cronJob/password.cron.job.ts @@ -1,6 +1,7 @@ import cron from 'node-cron'; import { db } from '../database/models/index'; import sendPasswordUpdateNotification from '../utils/sendChangePasswordNofication'; +import { generateToken } from '../helps/generateToken'; import dotenv from 'dotenv'; dotenv.config(); @@ -8,7 +9,7 @@ dotenv.config(); const startCronJob = (): void => { const cronSchedule = process.env.CRON_SCHEDULE || '* * * * *'; const passwordExpirationPeriodMinutes = parseInt( - process.env.PASSWORD_EXPIRATION_PERIOD_MINUTES || '131527', + process.env.PASSWORD_EXPIRATION_PERIOD_MINUTES || '2', 10, ); @@ -24,7 +25,16 @@ const startCronJob = (): void => { minutesSinceLastChange >= passwordExpirationPeriodMinutes && minutesSinceLastChange < 2 * passwordExpirationPeriodMinutes ) { - sendPasswordUpdateNotification(user); + const token = generateToken( + user.userId, + user.email, + user.firstName, + user.lastName, + user.role, + user.passwordLastChanged, + user.isVerified, + ); + sendPasswordUpdateNotification(user, token); } }); }); diff --git a/src/helps/MailTemplate.ts b/src/helps/MailTemplate.ts index 75bace8a..826a5588 100644 --- a/src/helps/MailTemplate.ts +++ b/src/helps/MailTemplate.ts @@ -1,18 +1,69 @@ const millisecondsToDate = require('./datesConversion'); +import dotenv from 'dotenv'; +dotenv.config(); -export const sendChangePasswordNoficationMail = ` -
+export const sendChangePasswordNotificationMail = (userToken: any) => ` + + + + + + + + + + + + -

We are writing to inform you that it is necessary to update your password for security purposes.

-

Failure to update your password within one day will result in the inability to perform any actions until the update is completed.

-

Please follow the link below to proceed with the password update:

-

- Update Password -

-

Thank you for your prompt attention to this matter.

-

Sincerely,

-

OnesAndZeroes Support Team

-
`; export const sendExpiredEmail = (products: any[]) => { const productRows = products diff --git a/src/helps/nodemailer.ts b/src/helps/nodemailer.ts index fd4b6045..8af9fcd3 100644 --- a/src/helps/nodemailer.ts +++ b/src/helps/nodemailer.ts @@ -33,7 +33,7 @@ async function sendEmail( -

OnesAndZeroes

+

Dear ${firstName},

${html} diff --git a/src/middleware/changePasswordIgnored.ts b/src/middleware/changePasswordIgnored.ts index 7152c8b8..3462279d 100644 --- a/src/middleware/changePasswordIgnored.ts +++ b/src/middleware/changePasswordIgnored.ts @@ -1,3 +1,45 @@ +// import { Request, Response, NextFunction } from 'express'; +// import { verifyToken } from '../helps/verifyToken'; + +// const JWT_SECRET = process.env.JWT_SECRET; + +// export function changePasswordIgnored( +// req: Request, +// res: Response, +// next: NextFunction, +// ) { +// const token = req.headers.authorization; + +// if (token) { +// const decoded = verifyToken(token); +// if (decoded) { +// const lastPasswordChangeDate = new Date( +// decoded.passwordLastChanged * 1000, +// ); +// const minutes = process.env.PASSWORD_EXPIRATION_PERIOD_MINUTES; +// const expirationPeriod = minutes ? parseInt(minutes, 10) : undefined; + +// if (expirationPeriod === undefined) { +// console.error("PASSWORD_EXPIRATION_PERIOD_MINUTES is not defined"); +// return res.status(500).send("Server configuration error"); +// } + +// const currentTime = new Date(); +// const timeInMillis = expirationPeriod * 60 * 1000; + +// if ( +// currentTime.getTime() - lastPasswordChangeDate.getTime() > +// timeInMillis && +// req.path !== `${process.env.CLIENT_URL}/login` +// ) { +// return res.redirect(`${process.env.CLIENT_URL}/reset/new-password?q=${token}`); +// } +// } +// } + +// next(); +// } + import { Request, Response, NextFunction } from 'express'; import { verifyToken } from '../helps/verifyToken'; @@ -13,18 +55,25 @@ export function changePasswordIgnored( if (token) { const decoded = verifyToken(token); if (decoded) { - const lastPasswordChangeDate = new Date( - decoded.passwordLastChanged * 1000, - ); + const lastPasswordChangeDate = new Date(decoded.passwordLastChanged); + + const minutes = process.env.PASSWORD_EXPIRATION_PERIOD_MINUTES; + const expirationPeriod = minutes ? parseInt(minutes, 10) : undefined; + + if (expirationPeriod === undefined) { + console.error('PASSWORD_EXPIRATION_PERIOD_MINUTES is not defined'); + return res.status(500).send('Server configuration error'); + } + const currentTime = new Date(); - const oneDayInMillis = 24 * 60 * 60 * 1000; + const timeInMillis = expirationPeriod * 60 * 1000; // Correct conversion from minutes to milliseconds if ( currentTime.getTime() - lastPasswordChangeDate.getTime() > - oneDayInMillis && - req.path !== '/login' + timeInMillis && + req.path !== `/login` ) { - return res.redirect('https://onesandzeroes/users/update'); + res.redirect(`${process.env.CLIENT_URL}/reset/new-password?q=${token}`); } } } diff --git a/src/server.ts b/src/server.ts index 92bac8a4..50f97ed1 100644 --- a/src/server.ts +++ b/src/server.ts @@ -18,6 +18,7 @@ const { productExpireTask } = require('./cronJob/productsCron'); import chats from './helps/chats'; import { cartExpiryJob } from './cronJob/cartExpiry.job'; +import path from 'path'; dotenv.config(); productExpireTask.start(); @@ -33,6 +34,8 @@ const io = new Server(server, { : ['http://localhost:5173', 'http://localhost:7000/api'], }, }); +// Register your middleware +// app.use(changePasswordIgnored); app.use(cors()); app.use(express.json()); app.use(morgan('dev')); @@ -56,7 +59,7 @@ app.use(passport.initialize()); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(cookieParser()); -app.use('/api', changePasswordIgnored, routes); +app.use('/api', routes); app.use('/docs', swaggerUi.serve, swaggerUi.setup(specs)); app.use('/auth', AuthRouters); diff --git a/src/utils/sendChangePasswordNofication.ts b/src/utils/sendChangePasswordNofication.ts index eb1248f4..8d7640b4 100644 --- a/src/utils/sendChangePasswordNofication.ts +++ b/src/utils/sendChangePasswordNofication.ts @@ -1,10 +1,11 @@ import sendMail from '../helps/nodemailer'; -import { sendChangePasswordNoficationMail } from '../helps/MailTemplate'; -function changePasswordUpdateNotification(user: any): void { +import { sendChangePasswordNotificationMail } from '../helps/MailTemplate'; +function changePasswordUpdateNotification(user: any, token: string): void { const email: string = user.email; const userName: string = user.firstName; + const userToken: string = token; const subject: string = 'You are required to update your password'; - const htmlContent: string = sendChangePasswordNoficationMail; + const htmlContent: string = sendChangePasswordNotificationMail(userToken); sendMail(email, userName, subject, htmlContent); }