const Authentication = require('../modules/authentication');
const Crypto = require('crypto');
const Mongoose = require('mongoose');
const Mailer = require('nodemailer');
const Token = require('../modules/token');
const secret = 'Creepily hooking the gays up since 2008!';
var logger = require('../modules/logger');
function generateHmac (userId, expires) {
var string = String(userId) + '|' + String(expires);
return Crypto.createHmac('sha1', secret).update(string).digest('hex');
}
function sendMail (options, callback) {
// create reusable transporter object using the default SMTP transport
let transporter = Mailer.createTransport({
host: 'mail.fitz.guru',
port: 587,
secure: false, // secure:true for port 465, secure:false for port 587
auth: {
user: 'support@fitz.guru',
pass: 'NotSt@ff3d!'
}
});
callback = typeof callback === 'function' ? callback : (error, info) => {
if (error) {
return logger.error(error);
}
logger.debug('Message %s sent: %s', info.messageId, info.response);
};
// send mail with defined transport object
transporter.sendMail(options, callback);
}
const ResetSchema = new Mongoose.Schema({
user: { type: Mongoose.Schema.Types.ObjectId, required: true },
expires: { type: Date, default: Date.now },
used: { type: Boolean, default: false },
updated_at: { type: Date, default: Date.now }
});
const ResetModel = Mongoose.model('resets', ResetSchema);
module.exports = {
checkReset: (e, id, token, callback) => {
const promise = new Promise((resolve, reject) => {
ResetModel.findOne({ _id: id }, (err, result) => {
if (err) {
reject(err);
}
if (result && (token === generateHmac(result.user, result.expires)) && (Date.now() <= result.expires)) {
resolve({ user: String(result.user), err: null });
} else {
resolve({ user: false, err: 'The reset link has expired. Please request a new reset link from the login page.'});
}
});
});
promise.then((result) => {
if (e) {
e.emit('checkReset', null, result);
} else if (callback) {
callback(null, result.user);
} else {
return true;
}
})
.catch((err) => {
if (e) {
e.emit('checkReset', err, null);
} else if (callback) {
callback(err, null);
} else {
return false;
}
});
},
forceReset: (e, user, callback) => {
const promise = new Promise((forceResetMailResolve, forceResetMailReject) => {
const forceResetTokenPromise = new Promise((forceResetTokenResolve, forceResetTokenReject) => {
var tokenInstance = new ResetModel({ user: user._id, expires: (Date.now() + (72 * 60 * 60 * 1000)) });
tokenInstance.save((err, result) => {
if (err) {
forceResetTokenReject(err);
}
if (result) {
forceResetTokenResolve(result);
}
});
});
forceResetTokenPromise.then((result) => {
let resetLink = 'https://timberland.bizdex.cloud/reset/' + encodeURIComponent(result._id) + '/' + encodeURIComponent(generateHmac(result.user, result.expires));
// setup email data with unicode symbols
let mail = {
from: '"GCS Vendor Database" ' + user.name.first + ', A Timberland GCS Vendor Database Administrator has initiated a password reset on your account.Mandatory Password Reset
If you have any questions, please contact a system administrator.
' }; sendMail(mail, (error, info) => { if (error) { logger.debug('[reset::forceReset] Message Send Error', { error: error }); forceResetMailResolve({ success: false, message: 'There was an error sending the message', error: error }); } if (info) { logger.debug('[reset::forceReset] Message sent', { messageId: info.messageId, response: info.response, resetLink: resetLink }); forceResetMailResolve({ success: true, message: 'Message ' + info.messageId + ' sent: ' + info.response + '.' }); } }); }) .catch((err) => { logger.debug('[reset::forceReset] There was an error creating the reset token.', { err: err }); forceResetMailReject(err); }); }); promise.then((result) => { if (e) { e.emit('forceReset', null, result); } else if (callback) { callback(result); } else { return true; } }) .catch((err) => { if (e) { e.emit('forceReset', err, null); } else if (callback) { callback(err); } else { return false; } }); }, getResets: (e) => { const promise = new Promise((resolve, reject) => { ResetModel.find({}, (err, results) => { if (err) { reject(err); } if (results) { resolve(results); } }); }); promise.then((results) => { e.emit('getResets', null, results); }) .catch((err) => { e.emit('getResets', err, null); }); }, markUsed: (e, id) => { const promise = new Promise((resolve, reject) => { ResetModel.findByIdAndUpdate(id, { $set: { used: true } }, (err, result) => { if (err) { reject(err); } if (result) { resolve(result); } }); }); promise.then((result) => { if (e) { e.emit('markUsed', null, result); } else { logger.debug('[ResetModel::markUsed] Password reset token used', { token: result }); } }) .catch((err) => { if (e) { e.emit('markUsed', err, null); } else { logger.error('[ResetModel::markUsed] Error marking password reset token used', { token: err }); } }); }, sendNewUser: (e, user) => { const promise = new Promise((newUserMailResolve, newUserMailReject) => { const newUserTokenPromise = new Promise((newUserTokenResolve, newUserTokenReject) => { var tokenInstance = new ResetModel({ user: user._id, expires: (Date.now() + (72 * 60 * 60 * 1000)) }); tokenInstance.save((err, result) => { if (err) { newUserTokenReject(err); } if (result) { newUserTokenResolve(result); } }); }); newUserTokenPromise.then((result) => { let setPasswordLink = 'https://timberland.bizdex.cloud/reset/' + encodeURIComponent(result._id) + '/' + encodeURIComponent(generateHmac(result.user, result.expires)); // setup email data with unicode symbols let mail = { from: '"GCS Vendor Database"' + user.name.first + ',
A new user has been created for you on the Timberland GCS Vendor Database.
Your username is: ' + user.userName + '.
To complete the setup you will need to create a password.If you have any questions, please contact a system administrator.
' }; sendMail(mail, (error, info) => { if (error) { logger.error('[reset::sendNewUser] Message Send Error', { error: error }); newUserMailResolve({ success: false, message: 'There was an error sending the message', error: error }); } if (info) { logger.debug('[reset::sendNewUser] Message %s sent: %s', info.messageId, info.response); newUserMailResolve({ success: true, message: 'Message ' + info.messageId + ' sent: ' + info.response + '.' }); } }); }) .catch((err) => { logger.error('[reset::sendNewUser] There was an error creating the reset token.', { err: err }); newUserMailReject(err); }); }); promise.then((result) => { if (e) { e.emit('sendNewUser', null, result); } else { return true; } }) .catch((err) => { if (e) { e.emit('sendNewUser', err, null); } else { return false; } }); }, sendReset: (e, user) => { const resetTokenPromise = new Promise((resetTokenResolve, resetTokenReject) => { var tokenInstance = new ResetModel({ user: user._id, expires: (Date.now() + (30 * 60 * 1000)) }); tokenInstance.save((err, result) => { if (err) { resetTokenReject(err); } if (result) { resetTokenResolve(result); } }); }); resetTokenPromise.then((data) => { var token = generateHmac(data.user, data.expires); var tokenId = data._id; const sendMailPromise = new Promise((sendMailResolve, sendMailReset) => { var resetLink = 'https://timberland.bizdex.cloud/reset/' + encodeURIComponent(tokenId) + '/' + encodeURIComponent(token); // setup email data with unicode symbols var mail = { from: '"GCS Vendor Database"' + user.name.first + ',
A request has been received to reset your password. If you initiated this request, click here to reset your password.
If you did not initiate this request, you can safely ignore this email.
' }; sendMail(mail, (err, info) => { if (err) { var error = { msg: '[reset::sendReset] There was an error sending the reset email.', err: err }; logger.error('[reset::sendReset] Message Send Error', { err: err }); sendMailResolve({ success: false, message: 'There was an error requesting the password reset.', error: error }); } if (info) { var message = 'Message ' + info.messageId + ' sent: ' + info.response + '.'; logger.debug('[reset::sendReset] ' + message); sendMailResolve({ success: true, message: 'The password reset request was successfully completed.', response: message }); } }); }); sendMailPromise.then((result) => { e.emit('sendReset', null, result); }) .catch((err) => { e.emit('sendReset', err, null); }); }) .catch((err) => { var error = { msg: '[reset::sendReset] There was an error creating the reset token.', err: err }; logger.debug(error.msg, { err: err }); e.emit('sendReset', null, { success: false, message: 'There was an error requesting the password reset.', error: error }); }); } };