p5.js-web-editor/server/controllers/user.controller.js
Yining Shi fe6acc90e4 Adding User Settings View (#325)
* added account page showing username and email

* change username and email

* validate current password and add new  password

* reject promise with error for reduxForm submit-validation for current password

* updated user reducer to handle setting sucess and server side async

* warning if there is current password but no new password

* fixes logout button

* import validate function, fixes logout style
2017-03-16 18:25:12 -04:00

226 lines
6 KiB
JavaScript

import crypto from 'crypto';
import async from 'async';
import nodemailer from 'nodemailer';
import mg from 'nodemailer-mailgun-transport';
import User from '../models/user';
export function createUser(req, res, next) {
const user = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password
});
User.findOne({ email: req.body.email },
(err, existingUser) => {
if (err) {
res.status(404).send({ error: err });
return;
}
if (existingUser) {
res.status(422).send({ error: 'Email is in use' });
return;
}
user.save((saveErr) => {
if (saveErr) {
next(saveErr);
return;
}
req.logIn(user, (loginErr) => {
if (loginErr) {
next(loginErr);
return;
}
res.json({
email: req.user.email,
username: req.user.username,
preferences: req.user.preferences,
id: req.user._id
});
});
});
});
}
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
});
});
}
export function updatePreferences(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;
}
const preferences = Object.assign({}, user.preferences, req.body.preferences);
user.preferences = preferences;
user.save((saveErr) => {
if (saveErr) {
res.status(500).json({ error: saveErr });
return;
}
res.json(user.preferences);
});
});
}
export function resetPasswordInitiate(req, res) {
async.waterfall([
(done) => {
crypto.randomBytes(20, (err, buf) => {
const token = buf.toString('hex');
done(err, token);
});
},
(token, done) => {
User.findOne({ email: req.body.email }, (err, user) => {
if (!user) {
res.json({ success: true, message: 'If the email is registered with the editor, an email has been sent.' });
return;
}
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
user.save((saveErr) => {
done(saveErr, token, user);
});
});
},
(token, user, done) => {
const auth = {
auth: {
api_key: process.env.MAILGUN_KEY,
domain: process.env.MAILGUN_DOMAIN
}
};
const transporter = nodemailer.createTransport(mg(auth));
const message = {
to: user.email,
from: 'p5.js Web Editor <noreply@p5js.org>',
subject: 'p5.js Web Editor Password Reset',
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);
});
}
], (err) => {
if (err) {
console.log(err);
res.json({ success: false });
return;
}
res.json({ success: true, message: 'If the email is registered with the editor, an email has been sent.' });
});
}
export function validateResetPasswordToken(req, res) {
User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, (err, user) => {
if (!user) {
res.status(401).json({ success: false, message: 'Password reset token is invalid or has expired.' });
return;
}
res.json({ success: true });
});
}
export function updatePassword(req, res) {
User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, (err, user) => {
if (!user) {
res.status(401).json({ success: false, message: 'Password reset token is invalid or has expired.' });
return;
}
user.password = req.body.password;
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
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
}));
});
});
// eventually send email that the password has been reset
}
export function userExists(username, callback) {
User.findOne({ username }, (err, user) => (
user ? callback(true) : callback(false)
));
}
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) {
user.comparePassword(req.body.currentPassword, (err, isMatch) => {
if (err) throw err;
if (!isMatch) {
res.status(401).json({ error: 'Current password is invalid.' });
return;
} else {
user.password = req.body.newPassword;
saveUser(res, user);
}
});
} else {
saveUser(res, user);
}
});
}
export function saveUser(res, user) {
user.save((saveErr) => {
if (saveErr) {
res.status(500).json({ error: saveErr });
return;
}
res.json(user);
});
}