324 lines
12 KiB
JavaScript
324 lines
12 KiB
JavaScript
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!';
|
|
|
|
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 console.log(error);
|
|
}
|
|
|
|
console.log('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: 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" <system@timberland.bizdex.cloud>',
|
|
to: user.email,
|
|
subject: 'Mandatory Password Reset',
|
|
text: 'Mandatory Password Reset\r\r\r\r' + user.name.first + ',\r\rA Timberland GCS Vendor Database Administrator has initiated a password reset on your account.\r\rTo complete the action you will need to reset you password <<' + resetLink + '>>.\r\rIf you have any questions, please contact a system administrator.',
|
|
html: '<h2>Mandatory Password Reset</h2><p>' + user.name.first + ',</p><p>A Timberland GCS Vendor Database Administrator has initiated a password reset on your account.</p>To complete the action you will need to <a href="' + resetLink + '">reset your password</a>.</p><p><b>If you have any questions, please contact a system administrator.</b></p>'
|
|
};
|
|
|
|
sendMail(mail, (error, info) => {
|
|
if (error) {
|
|
console.log('[reset::forceReset] Message Send Error', { error: error });
|
|
forceResetMailResolve({ success: false, message: 'There was an error sending the message', error: error });
|
|
}
|
|
|
|
if (info) {
|
|
console.log('[reset::forceReset] Message sent', { messageId: info.messageId, response: info.response, resetLink: resetLink });
|
|
forceResetMailResolve({ success: true, message: 'Message ' + info.messageId + ' sent: ' + info.response + '.' });
|
|
}
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
console.log('[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(result);
|
|
} 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 {
|
|
console.log('[ResetModel::markUsed] Password reset token used', { token: result });
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
if (e) {
|
|
e.emit('markUsed', err, null);
|
|
} else {
|
|
console.error('[ResetModel::markUsed] Error marking password reset token used', { token: result });
|
|
}
|
|
});
|
|
},
|
|
|
|
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" <system@timberland.bizdex.cloud>',
|
|
to: user.email,
|
|
subject: 'New User Account Setup',
|
|
text: 'New User Account Setup\r\r\r\r' + user.name.first + ',\r\rA new user has been created for you on the Timberland GCS Vendor Database.\r\rYour username is: <<' + user.userName + '>>.\r\r To complete the setup you will need to create a password <<' + setPasswordLink + '>>.\r\rIf you have any questions, please contact a system administrator.',
|
|
html: '<h2>New User Account Setup</h2><p>' + user.name.first + ',</p><p>A new user has been created for you on the Timberland GCS Vendor Database.</p><p>Your username is: <b>' + user.userName + '</b>.</p>To complete the setup you will need to <a href="' + setPasswordLink + '">create a password</a>.</p><p><b>If you have any questions, please contact a system administrator.</b></p>'
|
|
};
|
|
|
|
sendMail(mail, (error, info) => {
|
|
if (error) {
|
|
console.log('[reset::sendNewUser] Message Send Error', { error: error });
|
|
newUserMailResolve({ success: false, message: 'There was an error sending the message', error: error });
|
|
}
|
|
|
|
if (info) {
|
|
console.log('[reset::sendNewUser] Message %s sent: %s', info.messageId, info.response);
|
|
newUserMailResolve({ success: true, message: 'Message ' + info.messageId + ' sent: ' + info.response + '.' });
|
|
}
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
console.log('[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" <system@timberland.bizdex.cloud>',
|
|
to: user.email,
|
|
subject: 'Password Reset Request',
|
|
text: user.name.first + ',\r\rA request has been received to reset your password. If you initiated please visit <<' + resetLink + '>>.\r\rIf you did not initiate this request, you can safely ignore this email.',
|
|
html: '<h2>Password Reset Request</h2><p>' + user.name.first + ',</p><p>A request has been received to reset your password. If you initiated this request, <a href="' + resetLink + '">click here to reset your password</a>.</p><p><b>If you did not initiate this request, you can safely ignore this email.</b></p>'
|
|
};
|
|
|
|
sendMail(mail, (err, info) => {
|
|
if (err) {
|
|
var error = { msg: '[reset::sendReset] There was an error sending the reset email.', err: err };
|
|
console.log('[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 + '.';
|
|
console.log('[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 };
|
|
console.log(error.msg, { err: err });
|
|
e.emit('sendReset', null, { success: false, message: 'There was an error requesting the password reset.', error: error });
|
|
});
|
|
}
|
|
};
|