From 7fc4116db36c005f244089d42c8072d384731d4a Mon Sep 17 00:00:00 2001 From: holabayor Date: Sat, 23 Sep 2023 12:11:21 +0100 Subject: [PATCH] reset and forgot password --- .eslintrc.json | 3 +- controllers/authController.js | 85 +++++++++++++++++++++++++++++++++ controllers/lunch.controller.js | 15 ------ controllers/userController.js | 54 --------------------- generate-secret-key.js | 4 -- middlewares/auth.js | 2 - middlewares/index.js | 0 models/index.js | 50 ------------------- routes/auth.route.js | 7 +++ routes/users.js | 6 --- tests/userController.test.js | 5 +- 11 files changed, 96 insertions(+), 135 deletions(-) delete mode 100644 controllers/lunch.controller.js delete mode 100644 generate-secret-key.js delete mode 100644 middlewares/index.js delete mode 100644 models/index.js diff --git a/.eslintrc.json b/.eslintrc.json index fd739455..e7e17262 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -15,5 +15,6 @@ "class-methods-use-this": "off", "prefer-destructuring": ["error", { "object": true, "array": false }], "no-unused-vars": ["error", { "argsIgnorePattern": "req|res|next|val" }] - } + }, + "ignorePatterns": ["tests/"] } diff --git a/controllers/authController.js b/controllers/authController.js index 3ff300c1..5d4972de 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -6,6 +6,7 @@ const { createCustomError } = require('../errors/custom-errors'); const Organization = require('../models/organization.model'); const OrgLunchWallet = require('../models/org_lunch_wallet.model'); const { sendEmail } = require('./mailController'); +const transporter = require('../middlewares/emailConfig'); const secretKey = process.env.JWT_SECRET_KEY; @@ -230,10 +231,94 @@ async function createOrgAndUser(req, res, next) { } } +async function forgotPassword(req, res, next) { + const { email } = req.body; + try { + if (!email) { + return res.status(400).json({ + success: false, + message: 'Enter your email address', + }); + } + + const user = await User.findOne({ where: { email } }); + + if (!user) { + throw createCustomError('User not found', 404); + } + + const verificationCode = Math.floor( + 100000 + Math.random() * 900000, + ).toString(); + + // Send an email with the verification code + const mailOptions = { + from: process.env.MAIL_USER, // Your email address + to: email, // User's email address + subject: 'Password Reset', + text: `Your password reset code is: ${verificationCode}`, + }; + + // Send the email + await transporter.sendMail(mailOptions); + await user.update({ refresh_token: verificationCode }); + // Assuming sendUserOtp returns the expected response object + console.log(user); + res.status(202).json({ + success: true, + message: 'Password reset code sent successfully', + data: { + id: user.id, + email: user.email, + }, + }); + } catch (error) { + next(createCustomError('Invalid email', 401)); + } +} + +async function resetPassword(req, res, next) { + const { token, password } = req.body; + + if (!token || !password) { + return res.status(400).json({ + success: false, + message: 'Missing required fields', + data: null, + }); + } + try { + const user = await User.findOne({ where: { refresh_token: token } }); + + if (!user) { + throw createCustomError('User not found', 404); + } + + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, salt); + // Update the user's password + await user.update({ password_hash: hashedPassword }); + + await user.update({ refresh_token: null }); + + await user.save(); + + res.status(200).json({ + success: true, + message: 'Password reset successfully', + data: user, + }); + } catch (error) { + next(createCustomError('Invalid reset code', 400)); + } +} + module.exports = { validateEmail, createUser, loginUser, logoutUser, createOrgAndUser, + forgotPassword, + resetPassword, }; diff --git a/controllers/lunch.controller.js b/controllers/lunch.controller.js deleted file mode 100644 index 0ad7e929..00000000 --- a/controllers/lunch.controller.js +++ /dev/null @@ -1,15 +0,0 @@ -const { Lunch } = require('../models/index'); - -const redeemedLunch = async (req, res) => { - //req.user is equal to the user's id stored in the authentication middleware - await Lunch.update({ redeemed: true }, { where: { sender_id: req.user } }); - return res.status(200).json({ - success: true, - message: 'Lunch has successfully been redeemed', - data: {}, - }); -}; - -module.exports = { - redeemedLunch, -}; diff --git a/controllers/userController.js b/controllers/userController.js index 70347eec..afdcd09a 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -1,7 +1,6 @@ /* eslint-disable camelcase */ const User = require('../models/user.model'); //import user model const { createCustomError } = require('../errors/custom-errors'); -const { sendUserOtp } = require('./mailController'); async function getMe(req, res, next) { try { @@ -147,63 +146,10 @@ async function updateUser(req, res, next) { } } -async function forgotPassword(req, res, next) { - const { email } = req.body; - if (!email) { - return res.status(404).json({ - success: false, - message: 'User not found', - }); - } - - const user = await User.findOne({ where: { email } }); - if (!user) { - throw createCustomError('Invalid credentials', 404); - } - - const response = await sendUserOtp(user.id, email); - - let status = 500; - if (response.status === true) { - status = 202; - } - - res.status(status).json(response); -} - -async function resetPassword(req, res) { - const { email, otp, password } = req.body; - if (!(email && otp && password)) { - return res.status(404).json({ - success: false, - message: 'User not found', - }); - } - - const user = await User.findOne({ where: { email } }); - if (!user) { - throw createCustomError('Invalid credentials', 404); - } - - // const response = await verifyOtp(user.id, otp) - - // update password - user.password = password; - await user.save(); - - res.status(200).json({ - success: true, - message: 'Password reset successfully', - data: null, - }); -} - module.exports = { getMe, getUserById, getAllUsers, updateUser, deleteUser, - forgotPassword, - resetPassword, }; diff --git a/generate-secret-key.js b/generate-secret-key.js deleted file mode 100644 index 79e94fb3..00000000 --- a/generate-secret-key.js +++ /dev/null @@ -1,4 +0,0 @@ -const crypto = require('crypto'); - -const secretKey = crypto.randomBytes(32).toString('hex'); -console.log('Generated Secret Key:', secretKey); diff --git a/middlewares/auth.js b/middlewares/auth.js index a170ea7c..a41fba26 100644 --- a/middlewares/auth.js +++ b/middlewares/auth.js @@ -32,8 +32,6 @@ async function auth(req, res, next) { } } - - /** * checks if the user is an admin user * @requires auth middleware be added first diff --git a/middlewares/index.js b/middlewares/index.js deleted file mode 100644 index e69de29b..00000000 diff --git a/models/index.js b/models/index.js deleted file mode 100644 index 897c1096..00000000 --- a/models/index.js +++ /dev/null @@ -1,50 +0,0 @@ -const Sequelize = require('sequelize'); - -const connection = new Sequelize({ - dialect: 'mysql', -}); - -const Lunch = connection.define('Lunch', { - id: { - type: Sequelize.UUID, - primaryKey: true, - defaultValue: Sequelize.UUIDV4, - }, - org_id: { - type: Sequelize.TEXT, - references: { - model: 'Users', - key: 'org_id', - }, - }, - sender_id: { - type: Sequelize.TEXT, - references: { - model: 'Users', - key: 'id', - }, - }, - receiver_id: { - type: Sequelize.TEXT, - references: { - model: 'Users', - key: 'id', - }, - }, - quantity: { - type: Sequelize.INTEGER, - }, - redeemed: { - type: Sequelize.TINYINT, - }, - created_at: { - type: Sequelize.DATE, - }, - note: { - type: Sequelize.TEXT, - }, -}); - -module.exports = { - Lunch, -}; diff --git a/routes/auth.route.js b/routes/auth.route.js index 305c4768..c73a7320 100644 --- a/routes/auth.route.js +++ b/routes/auth.route.js @@ -4,6 +4,8 @@ const { loginUser, logoutUser, createOrgAndUser, + forgotPassword, + resetPassword, } = require('../controllers/authController'); const { auth } = require('../middlewares/auth'); @@ -12,6 +14,11 @@ const router = express.Router(); router.post('/signup', createUser); router.post('/login', loginUser); router.post('/signup/org-user', createOrgAndUser); + +// forgot password +router.post('/forgot-password', forgotPassword); +router.post('/reset-password', resetPassword); + router.use(auth); router.post('/logout', logoutUser); diff --git a/routes/users.js b/routes/users.js index 79b27048..4b190e8b 100644 --- a/routes/users.js +++ b/routes/users.js @@ -9,16 +9,10 @@ const { getUserById, getAllUsers, updateUser, - forgotPassword, - resetPassword, deleteUser, } = require('../controllers/userController'); const { auth, adminUser } = require('../middlewares/auth'); -// forgot password -router.post('/forgot-password', forgotPassword); -router.post('/reset-password', resetPassword); - router.use(auth); router.get('/me', getMe); diff --git a/tests/userController.test.js b/tests/userController.test.js index 0c8a1210..31f8a4ab 100644 --- a/tests/userController.test.js +++ b/tests/userController.test.js @@ -83,15 +83,14 @@ describe('Users COntroller Endpoints', () => { }); }); - - describe('Users Endpoints', () => { + describe('Users Endpoints', () => { it('should fetch all users', async () => { const res = await request(app).get(`/api/users`); expect(res.status).toEqual(500); }); }); - describe('Users Endpoints', () => { + describe('Users Endpoints', () => { it('should fetch all users', async () => { const res = await request(app).post(`/api/auth/logout`); expect(res.status).toEqual(200);