const utils = require('../../utils');
const time = require('../../utils/time');
const snippets = require('../../utils/snippets');
const mailgun = require('../../utils/mailgun');
const bcrypt = require('bcrypt');
const query_string = require('query-string');
module.exports = {
post: {
"request-token": function(req, res) {
let token = utils.uuid();
utils.query("INSERT INTO registrations SET ?", {
user_id: req.user.user_id,
reg_id: token,
expires: Date.now() + time.one_day
}).catch(utils.handle_err.sql(res)).then(function() {
res.send(utils.ok({
token: token
}));
}).catch(utils.handle_err.res(res, "Error creating registration token, try again later"));
},
"": [{
auth: false,
captcha: true
},
function(req, res) {
let registered_by;
let confirmation_id;
utils.validate.keys(req.body, [
['token', utils.validate.uuid],
'display_name',
['email', utils.validate.email, "Invalid Email"],
['password', utils.validate.password, "Password not strong enough"]
]).then(function() {
// Look for a registration session matching the reg_id
return utils.query('SELECT * FROM registrations WHERE ?', {
reg_id: req.body.token
}).catch(utils.handle_err.sql(res));
}).then(function([registration_data]) {
if (!registration_data) {
return utils.reject("Registration token invalid");
}
if (registration_data.expires < Date.now()) {
return utils.reject("Registration token expired");
}
registered_by = registration_data.user_id;
// Make sure that the email is not taken
return utils.query("SELECT user_id FROM users WHERE ?", {
email: req.body.email
}).catch(utils.handle_err.sql(res));
}).then(function([user]) {
if (user) {
return utils.reject("Email already taken");
}
// Hash the password and insert a new user with an unconfirmed email
return bcrypt.hash(req.body.password, 10);
}).then(function(hashword) {
return utils.query("INSERT INTO users SET ?", {
user_id: utils.uuid(),
email: req.body.email,
display_name: req.body.display_name,
password: hashword,
registered_by: registered_by,
email_confirmed: 0
}).catch(utils.handle_err.sql(res));
}).then(function() {
// Delete the registration session, the new user is created
return utils.query('DELETE FROM registrations WHERE ?', {
reg_id: req.body.token
}).catch(utils.handle_err.sql(res));
}).then(function() {
// Create a confirmation session and send the confirmation email
confirmation_id = utils.uuid();
return utils.query("INSERT INTO email_confirmations SET ?", {
email: req.body.email,
confirmation_id: confirmation_id,
expires: Date.now() + time.one_day
}).catch(utils.handle_err.sql(res));
}).then(function() {
return mailgun.send_confirmation_email(req.body.email, {
query: query_string.stringify({
token: confirmation_id
})
}).catch(utils.handle_err.mailgun(res));
}).then(function() {
// Finally we are done
res.send(utils.ok({
message: "You must confirm your email to complete registration, please check your inbox"
}));
}).catch(utils.handle_err.res(res, "Error registering your account. Try again or reach out whoever gave you a registration link"));
}
],
"confirm-email": {
"": [{
auth: false
}, function(req, res) {
let email;
utils.validate.keys(req.body, [
['token', utils.validate.uuid]
]).then(function() {
return utils.query('SELECT * FROM email_confirmations WHERE ?', {
confirmation_id: req.body.token
}).catch(utils.handle_err.sql(res));
}).then(function([confirmation]) {
if (!confirmation) {
return utils.reject("Confirmation token invalid");
}
if (confirmation.expires < Date.now()) {
return utils.reject("Confirmation token expired. Please request a new token");
}
email = confirmation.email;
return utils.query("UPDATE users" + utils.set_where({
email_confirmed: 1
}, {
email: email
})).catch(utils.handle_err.sql(res));
}).then(function() {
return utils.query("DELETE FROM email_confirmations WHERE ?", {
confirmation_id: req.body.token
}).catch(utils.handle_err.sql(res));
}).then(function() {
res.send(utils.ok({
message: "Your email is confirmed! You can now log in.",
email: email
}));
}).catch(utils.handle_err.res(res, "Error confirming email, try again later"));
}],
"request": [{
auth: false,
captcha: true
}, function(req, res) {
utils.validate.keys(req.body, [
['token', utils.validate.uuid]
]).then(function() {
return utils.query('SELECT * FROM email_confirmations WHERE ?', {
confirmation_id: req.body.token
}).catch(utils.handle_err.sql(res));
}).then(function([confirmation]) {
if (!confirmation) {
return utils.reject([utils.status.ok, {
message: "You email might already be confirmed, please log in",
show_login: true
}]);
}
if (confirmation.expires > Date.now()) {
return utils.reject("There is already a valid confirmation link, please check your inbox");
}
return snippets.generate_token(
"email_confirmations",
"confirmation_id",
confirmation.email
).catch(utils.handle_err.sql(res)).then(function(token) {
return mailgun.send_confirmation_email(confirmation.email, {
query: query_string.stringify({
token: token
})
}).catch(utils.handle_err.mailgun(res)).catch(function(error) {
// If the confirmation email fails to send, we need to delete the row
// from the email_confirmations table so that it can be sent again.
return utils.query("DELETE FROM email_confirmations WHERE ?", {
confirmation_id: token
}).catch(utils.handle_err.sql(res, true)).finally(function() {
return utils.reject(error);
});
});
}).then(function() {
res.send(utils.ok({
message: "New confirmation email sent, please check your inbox",
show_login: false
}));
});
}).catch(utils.handle_err.res(res, "Error sending email confirmation link, try again later"));
}]
}
}
};