2016-10-12 23:19:43 +02:00
|
|
|
import crypto from 'crypto';
|
|
|
|
import async from 'async';
|
2017-01-13 16:35:39 +01:00
|
|
|
import nodemailer from 'nodemailer';
|
|
|
|
import mg from 'nodemailer-mailgun-transport';
|
2017-02-22 20:29:35 +01:00
|
|
|
import User from '../models/user';
|
2016-06-09 02:52:59 +02:00
|
|
|
|
|
|
|
export function createUser(req, res, next) {
|
2016-06-24 00:29:55 +02:00
|
|
|
const user = new User({
|
|
|
|
username: req.body.username,
|
2016-06-09 02:52:59 +02:00
|
|
|
email: req.body.email,
|
|
|
|
password: req.body.password
|
|
|
|
});
|
|
|
|
|
2016-06-24 00:29:55 +02:00
|
|
|
User.findOne({ email: req.body.email },
|
2017-02-22 20:29:35 +01:00
|
|
|
(err, existingUser) => {
|
|
|
|
if (err) {
|
|
|
|
res.status(404).send({ error: err });
|
|
|
|
return;
|
|
|
|
}
|
2016-06-09 02:52:59 +02:00
|
|
|
|
2016-06-24 00:29:55 +02:00
|
|
|
if (existingUser) {
|
2017-02-22 20:29:35 +01:00
|
|
|
res.status(422).send({ error: 'Email is in use' });
|
|
|
|
return;
|
2016-06-24 00:29:55 +02:00
|
|
|
}
|
2017-02-22 20:29:35 +01:00
|
|
|
user.save((saveErr) => {
|
|
|
|
if (saveErr) {
|
|
|
|
next(saveErr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
req.logIn(user, (loginErr) => {
|
2016-06-24 00:29:55 +02:00
|
|
|
if (loginErr) {
|
2017-02-22 20:29:35 +01:00
|
|
|
next(loginErr);
|
|
|
|
return;
|
2016-06-24 00:29:55 +02:00
|
|
|
}
|
2017-01-13 16:35:39 +01:00
|
|
|
res.json({
|
|
|
|
email: req.user.email,
|
|
|
|
username: req.user.username,
|
|
|
|
preferences: req.user.preferences,
|
|
|
|
id: req.user._id
|
2016-06-24 00:29:55 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2016-08-05 03:43:13 +02:00
|
|
|
|
2016-09-02 20:51:30 +02:00
|
|
|
export function duplicateUserCheck(req, res) {
|
|
|
|
const checkType = req.query.check_type;
|
|
|
|
const value = req.query[checkType];
|
|
|
|
const query = {};
|
|
|
|
query[checkType] = value;
|
|
|
|
User.findOne(query, (err, user) => {
|
|
|
|
if (user) {
|
|
|
|
return res.json({
|
|
|
|
exists: true,
|
|
|
|
message: `This ${checkType} is already taken.`,
|
|
|
|
type: checkType
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return res.json({
|
|
|
|
exists: false,
|
|
|
|
type: checkType
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-08-05 03:43:13 +02:00
|
|
|
export function updatePreferences(req, res) {
|
2016-08-09 20:20:54 +02:00
|
|
|
User.findById(req.user.id, (err, user) => {
|
|
|
|
if (err) {
|
2017-02-22 20:29:35 +01:00
|
|
|
res.status(500).json({ error: err });
|
|
|
|
return;
|
2016-08-09 20:20:54 +02:00
|
|
|
}
|
2016-11-17 17:15:35 +01:00
|
|
|
if (!user) {
|
2017-02-22 20:29:35 +01:00
|
|
|
res.status(404).json({ error: 'Document not found' });
|
|
|
|
return;
|
2016-08-09 20:20:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const preferences = Object.assign({}, user.preferences, req.body.preferences);
|
|
|
|
user.preferences = preferences;
|
|
|
|
|
2017-02-22 20:29:35 +01:00
|
|
|
user.save((saveErr) => {
|
|
|
|
if (saveErr) {
|
|
|
|
res.status(500).json({ error: saveErr });
|
|
|
|
return;
|
2016-08-09 20:20:54 +02:00
|
|
|
}
|
|
|
|
|
2017-02-22 20:29:35 +01:00
|
|
|
res.json(user.preferences);
|
2016-08-09 20:20:54 +02:00
|
|
|
});
|
2016-11-17 17:15:35 +01:00
|
|
|
});
|
2016-08-05 03:43:13 +02:00
|
|
|
}
|
2016-10-12 20:25:24 +02:00
|
|
|
|
|
|
|
export function resetPasswordInitiate(req, res) {
|
2016-10-12 23:19:43 +02:00
|
|
|
async.waterfall([
|
|
|
|
(done) => {
|
2017-01-11 21:50:36 +01:00
|
|
|
crypto.randomBytes(20, (err, buf) => {
|
|
|
|
const token = buf.toString('hex');
|
2016-10-12 23:19:43 +02:00
|
|
|
done(err, token);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
(token, done) => {
|
2016-11-17 17:15:35 +01:00
|
|
|
User.findOne({ email: req.body.email }, (err, user) => {
|
2016-10-12 23:19:43 +02:00
|
|
|
if (!user) {
|
2017-02-22 20:29:35 +01:00
|
|
|
res.json({ success: true, message: 'If the email is registered with the editor, an email has been sent.' });
|
|
|
|
return;
|
2016-10-12 23:19:43 +02:00
|
|
|
}
|
|
|
|
user.resetPasswordToken = token;
|
|
|
|
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
|
|
|
|
|
2017-02-22 20:29:35 +01:00
|
|
|
user.save((saveErr) => {
|
|
|
|
done(saveErr, token, user);
|
2016-10-12 23:19:43 +02:00
|
|
|
});
|
|
|
|
});
|
2016-10-18 04:56:19 +02:00
|
|
|
},
|
|
|
|
(token, user, done) => {
|
2017-01-13 16:35:39 +01:00
|
|
|
const auth = {
|
|
|
|
auth: {
|
|
|
|
api_key: process.env.MAILGUN_KEY,
|
|
|
|
domain: process.env.MAILGUN_DOMAIN
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const transporter = nodemailer.createTransport(mg(auth));
|
|
|
|
const message = {
|
2016-10-18 04:56:19 +02:00
|
|
|
to: user.email,
|
2017-01-13 16:35:39 +01:00
|
|
|
from: 'p5.js Web Editor <noreply@p5js.org>',
|
2016-10-18 04:56:19 +02:00
|
|
|
subject: 'p5.js Web Editor Password Reset',
|
2017-01-13 16:35:39 +01:00
|
|
|
text: `You are receiving this email because you (or someone else) have requested the reset of the password for your account.
|
|
|
|
\n\nPlease click on the following link, or paste this into your browser to complete the process:
|
|
|
|
\n\nhttp://${req.headers.host}/reset-password/${token}
|
|
|
|
\n\nIf you did not request this, please ignore this email and your password will remain unchanged.
|
|
|
|
\n\nThanks for using the p5.js Web Editor!\n`
|
|
|
|
};
|
|
|
|
transporter.sendMail(message, (error) => {
|
|
|
|
done(error);
|
|
|
|
});
|
2016-10-12 23:19:43 +02:00
|
|
|
}
|
|
|
|
], (err) => {
|
|
|
|
if (err) {
|
|
|
|
console.log(err);
|
2017-02-22 20:29:35 +01:00
|
|
|
res.json({ success: false });
|
|
|
|
return;
|
2016-10-12 20:25:24 +02:00
|
|
|
}
|
2017-02-22 20:29:35 +01:00
|
|
|
res.json({ success: true, message: 'If the email is registered with the editor, an email has been sent.' });
|
2016-10-12 20:25:24 +02:00
|
|
|
});
|
|
|
|
}
|
2016-10-18 22:07:25 +02:00
|
|
|
|
|
|
|
export function validateResetPasswordToken(req, res) {
|
|
|
|
User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, (err, user) => {
|
|
|
|
if (!user) {
|
2017-02-22 20:29:35 +01:00
|
|
|
res.status(401).json({ success: false, message: 'Password reset token is invalid or has expired.' });
|
|
|
|
return;
|
2016-10-18 22:07:25 +02:00
|
|
|
}
|
|
|
|
res.json({ success: true });
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updatePassword(req, res) {
|
2017-02-22 20:29:35 +01:00
|
|
|
User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, (err, user) => {
|
2016-10-18 22:07:25 +02:00
|
|
|
if (!user) {
|
2017-02-22 20:29:35 +01:00
|
|
|
res.status(401).json({ success: false, message: 'Password reset token is invalid or has expired.' });
|
|
|
|
return;
|
2016-10-18 22:07:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
user.password = req.body.password;
|
|
|
|
user.resetPasswordToken = undefined;
|
|
|
|
user.resetPasswordExpires = undefined;
|
|
|
|
|
2017-02-22 20:29:35 +01:00
|
|
|
user.save((saveErr) => {
|
|
|
|
req.logIn(user, loginErr => res.json({
|
|
|
|
email: req.user.email,
|
|
|
|
username: req.user.username,
|
|
|
|
preferences: req.user.preferences,
|
|
|
|
id: req.user._id
|
|
|
|
}));
|
2016-10-18 22:07:25 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-11-17 17:15:35 +01:00
|
|
|
// eventually send email that the password has been reset
|
2016-10-18 22:07:25 +02:00
|
|
|
}
|
2017-01-06 19:08:03 +01:00
|
|
|
|
|
|
|
export function userExists(username, callback) {
|
|
|
|
User.findOne({ username }, (err, user) => (
|
|
|
|
user ? callback(true) : callback(false)
|
|
|
|
));
|
|
|
|
}
|
2017-03-16 23:25:12 +01:00
|
|
|
|
2017-04-06 20:34:14 +02:00
|
|
|
export function saveUser(res, user) {
|
|
|
|
user.save((saveErr) => {
|
|
|
|
if (saveErr) {
|
|
|
|
res.status(500).json({ error: saveErr });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
res.json(user);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-03-16 23:25:12 +01:00
|
|
|
export function updateSettings(req, res) {
|
|
|
|
User.findById(req.user.id, (err, user) => {
|
|
|
|
if (err) {
|
|
|
|
res.status(500).json({ error: err });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!user) {
|
|
|
|
res.status(404).json({ error: 'Document not found' });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
user.email = req.body.email;
|
|
|
|
user.username = req.body.username;
|
|
|
|
|
|
|
|
if (req.body.currentPassword) {
|
2017-04-06 20:34:14 +02:00
|
|
|
user.comparePassword(req.body.currentPassword, (passwordErr, isMatch) => {
|
|
|
|
if (passwordErr) throw passwordErr;
|
2017-03-16 23:25:12 +01:00
|
|
|
if (!isMatch) {
|
|
|
|
res.status(401).json({ error: 'Current password is invalid.' });
|
|
|
|
return;
|
|
|
|
}
|
2017-04-06 20:34:14 +02:00
|
|
|
user.password = req.body.newPassword;
|
|
|
|
saveUser(res, user);
|
2017-03-16 23:25:12 +01:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
saveUser(res, user);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|