diff --git a/app/controllers/auth.controller.js b/app/controllers/auth.controller.js index 5f94915..c73c53e 100644 --- a/app/controllers/auth.controller.js +++ b/app/controllers/auth.controller.js @@ -100,7 +100,7 @@ exports.resetPasswordEmail = async (req, res, next) => { user = await sequelize.query( ` SELECT id FROM organizations - WHERE email = :email`, + WHERE primary_contact_email = :email`, { type: sequelize.QueryTypes.SELECT, replacements: { email } @@ -109,10 +109,7 @@ exports.resetPasswordEmail = async (req, res, next) => { } user = user[0]; - if (!user) - return res.status(400).json({ - message: 'User not found' - }); + if (!user) return next(errorMaker(400, 'Not a valid user')); const CODE = uuidv4(); const currDate = new Date(); @@ -146,7 +143,8 @@ exports.resetPasswordEmail = async (req, res, next) => { } ); - sendgrid.passwordResetEmail(email, CODE); + await sendgrid.passwordResetEmail(email, CODE); + return res .status(200) .json({ message: 'Successfuly sent password reset email!' }); @@ -154,3 +152,70 @@ exports.resetPasswordEmail = async (req, res, next) => { next(e); } }; + +exports.resetPassword = async (req, res, next) => { + try { + const { password, code } = req.query; + + var passwordResetRow = await sequelize.query( + ` + SELECT * FROM password_reset + WHERE code = :code`, + { + type: sequelize.QueryTypes.SELECT, + replacements: { code } + } + ); + + if (!passwordResetRow.length) + return next(errorMaker(400, 'Forbidden to reset password')); + + passwordResetRow = passwordResetRow[0]; + + //TODO check the timestamp of the code creation + const createdDate = new Date(passwordResetRow.created_at); + const currDate = new Date(); + const diffTime = Math.abs(currDate.getTime() - createdDate.getTime()); + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + + if (diffDays > 3) return next(errorMaker(400, 'Code expired')); + + const hashedPass = bcrypt.hashSync(password); + + if (passwordResetRow.user_type == 'donor') { + await sequelize.query( + ` + UPDATE donors + SET password = :password + WHERE id = :user_id + `, + { + type: sequelize.QueryTypes.UPDATE, + replacements: { + password: hashedPass, + user_id: passwordResetRow.user_id + } + } + ); + } else { + await sequelize.query( + ` + UPDATE organizations + SET password = :password + WHERE id = :user_id + `, + { + type: sequelize.QueryTypes.UPDATE, + replacements: { + password: hashedPass, + user_id: passwordResetRow.user_id + } + } + ); + } + + return res.status(200).json({ message: 'Successfuly reset password!' }); + } catch (e) { + next(e); + } +}; diff --git a/app/controllers/donor.controller.js b/app/controllers/donor.controller.js index 4026f5f..92cd57d 100644 --- a/app/controllers/donor.controller.js +++ b/app/controllers/donor.controller.js @@ -1,91 +1,91 @@ const db = require('../../models'), - bcrypt = require('bcrypt-nodejs'), - errorMaker = require('../helpers/error.maker'), - uuidv4 = require('uuid/v4'); + bcrypt = require('bcrypt-nodejs'), + errorMaker = require('../helpers/error.maker'), + uuidv4 = require('uuid/v4'); const Donor = db.Donor; // Create/post a Donor exports.createDonor = (req, res, next) => { - // see if user already in db - Donor.findAll({ - where: { - email: req.body.email - } - }) - .then(donors => { - if (donors.length >= 1) { - return next(errorMaker(409, `Email Exists: ${req.body.email}`)); - } else { - // hash and store - bcrypt.hash(req.body.password, null, null, function(error, hash) { - // Store hash in your password DB. - if (error) { - return next(error); - } else { - Donor.create({ - id: uuidv4(), - first_name: req.body.first_name, - middle_name: req.body.middle_name, - last_name: req.body.last_name, - email: req.body.email, - password: hash, //hashed password - age: req.body.age, - phone: req.body.phone, - address: req.body.address, - city: req.body.city, - state: req.body.state, - country: req.body.country - }) - .then(donor => { - // Send created donor to client - return res.status(201).json({ - message: 'Donor created', - donor - }); - }) - .catch(error => next(error)); - } - }); - } - }) - .catch(error => next(error)); + // see if user already in db + Donor.findAll({ + where: { + email: req.body.email + } + }) + .then(donors => { + if (donors.length >= 1) { + return next(errorMaker(409, `Email Exists: ${req.body.email}`)); + } else { + // hash and store + bcrypt.hash(req.body.password, null, null, function(error, hash) { + // Store hash in your password DB. + if (error) { + return next(error); + } else { + Donor.create({ + id: uuidv4(), + first_name: req.body.first_name, + middle_name: req.body.middle_name, + last_name: req.body.last_name, + email: req.body.email, + password: hash, //hashed password + age: req.body.age, + phone: req.body.phone, + address: req.body.address, + city: req.body.city, + state: req.body.state, + country: req.body.country + }) + .then(donor => { + // Send created donor to client + return res.status(201).json({ + message: 'Donor created', + donor + }); + }) + .catch(error => next(error)); + } + }); + } + }) + .catch(error => next(error)); }; // FETCH all Donor exports.getAllDonors = (req, res, next) => { - Donor.findAll().then(donors => { - // Send all donors to Client - res.status(200).json({ - donors, - number_donors: donors.length - }); - }); + Donor.findAll().then(donors => { + // Send all donors to Client + res.status(200).json({ + donors, + number_donors: donors.length + }); + }); }; // Find a Donor by Id exports.findDonorById = (req, res) => { - Donor.findById(req.params.donor_id).then(donor => { - res.send(donor); - }); + Donor.findById(req.params.donor_id).then(donor => { + res.send(donor); + }); }; // Delete a Donor by Id exports.deleteDonor = (req, res) => { - const id = req.params.donor_id; - Donor.destroy({ - where: { id: id } - }).then(() => { - res.status(200).send('deleted successfully a donor with id = ' + id); - }); + const id = req.params.donor_id; + Donor.destroy({ + where: { id: id } + }).then(() => { + res.status(200).send('deleted successfully a donor with id = ' + id); + }); }; // GET the quick stats for the dashboard exports.getDashboardData = async (req, res, next) => { - const donor_id = req.user.id; + const donor_id = req.user.id; - const donors = await db.sequelize.query( - ` + const donors = await db.sequelize.query( + ` select d.id, d.first_name, sum(g.amount) as total_contributions @@ -94,25 +94,25 @@ exports.getDashboardData = async (req, res, next) => { group by d.id order by total_contributions DESC `, - { - type: db.sequelize.QueryTypes.SELECT - } - ); + { + type: db.sequelize.QueryTypes.SELECT + } + ); - let number_donors = donors.length; + let number_donors = donors.length; - donors.map((donor, index) => { - if (donor.id == donor_id) { - const donor_contributions = donor.total_contributions; + donors.map((donor, index) => { + if (donor.id == donor_id) { + const donor_contributions = donor.total_contributions; - let percentile = - donor_contributions > 0 ? (number_donors - index) / number_donors : 0; - return res.status(200).json({ - message: 'Successfully got the stats', - percentile - }); - } - }); + let percentile = + donor_contributions > 0 ? (number_donors - index) / number_donors : 0; + return res.status(200).json({ + message: 'Successfully got the stats', + percentile + }); + } + }); }; // // Update a Donor diff --git a/app/controllers/sendgrid.controller.js b/app/controllers/sendgrid.controller.js index 2928353..eefc50d 100644 --- a/app/controllers/sendgrid.controller.js +++ b/app/controllers/sendgrid.controller.js @@ -86,17 +86,19 @@ exports.passwordResetEmail = async (receiver, code) => { const msg = { to: receiver, from: { email: 'no-reply@ucharify.com', name: 'UCharify Security' }, - template_id: 'd-569f804f5e7749cba66bac1994607280', + template_id: 'd-f26ce08089914f3a983f8932913ed262', substitutionWrappers: ['{{', '}}'], dynamic_template_data: { - reset_link: `${process.env.WEB_CLIENT}/resetpassword/form`, + reset_link: `${ + process.env.WEB_CLIENT + }/resetpassword/form?code=${code}`, subject: 'Reset Your Password' } }; const sentRes = await sgMail.send(msg); - resolve(); + resolve(sentRes); } catch (e) { reject(e); } diff --git a/app/routes/auth.route.js b/app/routes/auth.route.js index 7d1fc53..0e8ce97 100644 --- a/app/routes/auth.route.js +++ b/app/routes/auth.route.js @@ -14,6 +14,6 @@ router.post('/org/login', auth.orgLogin); router.get('/resetpassword', auth.resetPasswordEmail); // Reset password for either donor or charity after verifying code -router.post('/resetpassword', auth.resetPasswordEmail); +router.post('/resetpassword', auth.resetPassword); module.exports = router; diff --git a/models/PasswordReset.js b/models/PasswordReset.js index 63ceda5..9b3206e 100644 --- a/models/PasswordReset.js +++ b/models/PasswordReset.js @@ -4,24 +4,24 @@ module.exports = (sequelize, DataTypes) => { 'password_reset', { code: { - type: Sequelize.STRING, + type: DataTypes.STRING, allowNull: false }, user_id: { - type: Sequelize.UUID, + type: DataTypes.UUID, allowNull: false }, user_type: { - type: Sequelize.STRING, + type: DataTypes.STRING, allowNull: false }, created_at: { allowNull: false, - type: Sequelize.DATE + type: DataTypes.DATE }, updated_at: { allowNull: false, - type: Sequelize.DATE + type: DataTypes.DATE } }, {}