I am kind of new to the nodeJs and I am trying to check if user's email already exists in the database, but seems like I am doing something wrong, it always tell me that "Email already exists" I tried a few different ways but none of them work. I hope someone here will be able to help me figure this out. thank you.
router.post('/register', function (req, res) {
var name = req.body.name;
var email = req.body.email;
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('email', 'Email already exists').custom(email => {
return User.getUserByEmail(email, function(user) {
if (user) {
throw new Error('this email is already in use');
}
})
});
// User.getUserByEmail(email, function (err, user) {
//
// if(!isEmpty(user)){
// console.log(user);
// MyEmitter.emit('isUser', true);
// var empty = '';
// req.checkBody('empty', 'Username/Email is already taken').isEmpty();
// }
// });
/** CKECK IF USER EXISTS NEEDS TO BE WORKED ON */
var errors = req.validationErrors();
if (errors) {
res.render('register', {
errors: errors
});
}else {
var newUser = new User({
name: name,
email: email,
username: username,
password: password
});
User.createUser(newUser, function (err, user) {
if (err) throw err;
});
req.flash('success_msg', 'Registration successful, please log in');
res.redirect('/users/login');
}
});
/** get user by email **/
module.exports.getUserByEmail = function(email, callback){
var query = {email: email};
User.findOne(query, callback);
}
Check this one:
req.checkBody('email', 'Email already exists').custom(email => {
User.findOne({email: email}).exec(function(user) {
if (!user) {
return true;
}
else{
return false;
}
})
});
Related
I have created a user registration and login. All working fine. Trying to implement password reset. All is working fine up to the point of filling in the new password and confirming same. Then getting an error that token has expired. No idea why. I'm pretty new to coding (a few month) so sincere apologies if I am not posting this properly. Have used the site a lot but it's my first time posting... Any help would be very much appreciated. Thank you.
p.s
I'm including the main js file. I'm not sure if I need to include any of the other files but as they are quite a number, I'll wait to see if anyone asks to see anything else. Thanks again.
//users.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
const bcrypt = require('bcryptjs');
const async = require('async');
const nodemailer = require('nodemailer');
const crypto = require('crypto');
// User model
const User = require('../models/User');
// Login Page
router.get('/login', function(req, res){
res.render('login');
});
// Register Page
router.get('/register', function(req, res){
res.render('register');
});
// Register Handle
router.post('/register', function (req, res){
const { name, email, password, password2 } = req.body;
let errors = [];
// Check required fields
if(!name || !email || !password || !password2) {
errors.push({ msg: 'Please fill in all fields' });
}
// Check passwords match
if(password !== password2) {
errors.push({ msg: 'Passwords do not match' });
};
// Check password length
if(password.length < 6) {
errors.push({ msg: 'Password should be at least 6 characters' });
};
// If there are errors
if(errors.length > 0){
res.render('register', {
errors,
name,
email,
password,
password2
});
} else {
//Validation passed
User.findOne({ email: email })//This is going to return a promise
.then(function (user){
//If User exists
if(user){
errors.push({ msg: 'Email already registered' });
res.render('register', {
errors,
name,
email,
password,
password2
});
} else {
//If email not registered create a new User
const newUser = new User({
name,// es6 instead of 'name: name' and same for below
email,
password
});
// Hash Password
bcrypt.genSalt(10, function(err, salt){
bcrypt.hash(newUser.password, salt, function(err, hash){
if(err) throw err;
//Set password to hashed
newUser.password = hash;
// Save user
newUser.save()
.then(function(user){
req.flash('success_msg', 'You have been successuflly registered and can now log in');
res.redirect('/users/login');
})
.catch(err, function(){
console.log(err);
});
});
});
}
});
}
});
// Login Handle
router.post('/login', function(req, res, next){
passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
});
// Logout Handle
router.get('/logout', function(req, res){
req.logout();
req.flash('success_msg', 'You have been logged out');
res.redirect('/users/login');
});
// Forgot Password Page
router.get('/forgot', function (req, res){
res.render('forgot');
});
// Forgot Password Handle
router.post('/forgot', function(req, res, next) {
async.waterfall([
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
User.findOne({ email: req.body.email }, function(err, user) {
if (!user) {
req.flash('error', 'No account with that email address exists.');
return res.redirect('/users/forgot');
}
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
user.save(function(err) {
done(err, token, user);
});
});
},
function(token, user, done) {
var smtpTransport = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'nirshihor#gmail.com',
pass: '<password>'
}
});
var mailOptions = {
to: user.email,
from: 'nirshihor#gmail.com',
subject: 'WSS Password Reset',
text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
'http://' + req.headers.host + '/users/reset/' + token + '\n\n' +
'If you did not request this, please ignore this email and your password will remain unchanged.\n'
};
smtpTransport.sendMail(mailOptions, function(err) {
console.log('mail sent');
req.flash('success_mail_sent', 'An e-mail has been sent to ' + user.email + ' with further instructions.');
done(err, 'done');
});
}
], function(err) {
if (err) return next(err);
res.redirect('/users/forgot');
});
});
router.get('/reset/:token', function(req, res) {
User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
if (!user) {
req.flash('error_token', 'Password reset token is invalid or has expired.');
return res.redirect('/users/forgot');
}
res.render('reset', {token: req.params.token});
});
});
router.post('/reset/:token', function(req, res) {
async.waterfall([
function(done) {
User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
if (!user) {
req.flash('error_token', 'Password reset token is invalid or has expired.');
return res.redirect('back');
}
if(req.body.password === req.body.confirm) {
user.setPassword(req.body.password, function(err) {
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
//Update user in database
user.save(function(err) {
req.logIn(user, function(err) {
done(err, user);
});
});
})
} else {
req.flash("error_passwords_match", "Passwords do not match.");
return res.redirect('back');
}
});
},
function(user, done) {
var smtpTransport = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'nirshihor#gmail.com',
pass: 'N1rSh1hor?#'
}
});
var mailOptions = {
to: user.email,
from: 'nirshihor#mail.com',
subject: 'Your password has been changed',
text: 'Hello,\n\n' +
'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n'
};
smtpTransport.sendMail(mailOptions, function(err) {
req.flash('success_password_change', 'Success! Your password has been changed.');
done(err);
});
}
], function(err) {
res.redirect('/home');
});
});
module.exports = router;
Managed to sort it. I put together two different tutorials I followed. One was for registering users and logging in, and the other was for resetting password. I failed to implement the hashing process for the password reset as I did in the first tutorial, which caused the problem. Now resolved. If anyone experiencing the same issue requires code sample - happy to supply.
I am a beginner working with node and I am attempting to allow for user registration on a project. However, anytime I press the register button on my page I receive this error:
ReferenceError: bcrypt is not defined
at model.<anonymous> (/Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/models/User.js:29:5)
at callMiddlewareFunction (/Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/node_modules/kareem/index.js:482:23)
at model.next (/Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/node_modules/kareem/index.js:58:7)
at _next (/Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/node_modules/kareem/index.js:106:10)
at /Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/node_modules/kareem/index.js:507:38
at processTicksAndRejections (internal/process/task_queues.js:79:11)
I don't understand what the issue could be. I gave both downloaded and required the bcryptjs module. Here is my code:
// Modules required to run the application
const express = require('express');
const bcrypt = require('bcryptjs');
// Creates 'mini app'
const router = express.Router();
// User model
const User = require('../models/User');
// Login Page
router.get('/login', function(req, res){
res.render("./home/login");
});
// Registration Page
router.get('/register', function(req, res){
res.render("./home/register");
});
// Registration
router.post('/register', function(req, res){
const { name, email, password, password2 } = req.body;
let errors = [];
// Check requried fields
if(!name || !email || !password || !password2){
errors.push({ msg: 'Please fill in all feilds' });
}
//Check passwords match
if(password !== password2){
errors.push({ msg: "Passwords do not match" });
}
// Check password length
if(password.length < 6){
errors.push({ msg: "Password should be at least six characters long" });
}
// Checks for any errors and prevents registration/redirection
if(errors.length > 0){
res.render('./home/register', {
errors,
name,
email,
password,
password2
});
}
else{
// Validation passed
User.findOne({ email: email })
.then(function(user){
if(user){
// User exists
errors.push({ msg: "Email is already registered" });
res.render('./home/register', {
errors,
name,
email,
password,
password2
});
} else {
const newUser = new User({
name: name,
email: email,
password: password
});
// Hash Password
bcrypt.genSalt(10, function(err, salt){
bcrypt.hash(newUser.password, salt, function(err, hash){
if(err){
throw err;
}
// Sets the password to the hashed password
newUser.password = hash;
newUser.save().then(function(user){
res.send('/users/login');
}).catch(function(err){
console.log(err);
});
});
});
}
});
}
});
module.exports = router;
Thank you for any assistance.
If I try to register a duplicate user Name, it all works, except for the error message saying it has already been registered. All the other error messages work; just not this one.
router.post('/register', function(req, res){
var name = req.body.name;
var email = req.body.email;
// var username = req.body.username;
var username = req.body.name;
var password = req.body.password;
var password2 = req.body.password2;
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('name', 'This name is already registered.')
.custom(function(name, req){
return new Promise((resolve, reject) => {
User.findOne({ name: name }, (err, user) => {
console.log(name);
console.log(user);
if (err) throw err;
if(user == null) {
resolve();
} else {
console.log('rejecting');
reject();
}
});
});
});
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
// req.checkBody('username', 'Username is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('password2', 'Passwords do not match').equals(req.body.password);
var errors = req.validationErrors();
if(errors){
res.render('register',{
errors:errors
});
} else {
var newUser = new User({
name: name,
What am I missing?
I am quite sure the way you chain custom() in your code is for the new API only. You are otherwise using the legacy API. For the legacy API you have to define the custom validators when you apply the middleware (in app.js or something similar). For example:
app.use(expressValidator({
customValidators: {
isUniqueName: function(name) {
return new Promise((resolve, reject) => {
User.findOne({ name: name }, (err, user) => {
console.log(name);
console.log(user);
if (err) throw err;
if (user == null) {
resolve();
} else {
console.log('rejecting');
reject();
}
});
});
},
},
}));
and in the controller:
req.checkBody('name', 'This name is already registered.').isUniqueName();
I would generally recommend changing to the new API. It shouldn't take too much time when you already know what you want to validate. It's written more about that here.
app.get('/changePass', function(req, res) {
password = req.body.password;
password1 = req.body.password1;
xyz = req.body.xyz;
User.find({ email: xyz, password: password }, function(err, data) {
if (err) {
throw err;
}
if (data.length === 0) {
return res.json({ success: false, data: 'please enter valid
Old password' })
} else {
// User.update({ password: password }, {
// $set: {
// password: password1
// }
// });
var usr = new User();
usr.update({ "password":password }, password1, { upsert:true
});
//usr.password = password;
usr.save(function(err, data) {
if (err)
throw err;
return res.json({ success: true, data: 'password changed
successfully' });
})
}
})
how i update password in mongodb i am matching password to password and updating password to password1.this is giving me alert with please enter valid old password.
xyz is cookie that contains email.
You should use findOne on model to return userObject.
Then you can update the object that was found like regular javascript object and save it with .save function.
User.findOne({email: xyz, password: req.body.password1}, function(err, user){
if(err)return handleErr(err);
user.password = req.body.password2;
user.save(function(err){
if(err)return handleErr(err);
//user has been updated
});
});
I'm trying to prevent registration with a previously registered email. I tried to create a custom validation in mongoose schema. but it gave me an error ValidationError: User validation failed
at MongooseError.ValidationError. The code is down bellow. Can some one tell me where is the error or a better way to check if the user email exists in db.
// user schema
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true,
require: true
},
password: {
type: String,
require: true
},
email: {
type: String,
lowercase: true,
trim: true,
index: {
unique: true,
},
validate: {
validator : isEmailExists, msg: 'Email already exists'
}
},
name: {
type: String
},
admin: Boolean,
active: Boolean,
});
// validation
function isEmailExists(email, callback) {
if (email) {
mongoose.models['User'].count({ _id: { '$ne': this._id }, email: email }, function (err, result) {
if (err) {
return callback(err);
}
callback(!result);
})
}
}
// createUser function
module.exports.createUser = function(newUser, callback){
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(newUser.password, salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
}
Router
router.post('/register', function(req, res, next) {
var name = req.body.name;
var email = req.body.email;
var password = req.body.password;
var confirmedPassword = req.body.confirmedPassword;
// Validation
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('confirmedPassword', 'Passwords do not match').equals(req.body.password);
var errors = req.validationErrors();
if (errors) {
res.render('register', {
errors: errors
});
} else {
var newUser = new User({
name: name,
email: email,
password: password,
admin: false,
active: false
});
User.createUser(newUser, function (err, user) {
if (err) {
throw err;
}
});
req.flash('success_msg', 'You are registerd and can now login');
res.redirect('/users/login');
}
The best way to check if the e-mail id already exists in the database or not is by using express-validator.
Since, there upgrade to version 4, the API has changed.
Now, instead of using:-
const expressValidator = require('express-validator');
..in your app.js file, and then calling the middleware. Instead, just do this in your users route file:-
const { check, validationResult } = require('express-validator/check');
Now, to check if the e-mail id already exists in the database, you will have to use Promise. Here's a working code:-
router.post('/register', [
check('name')
.not()
.isEmpty()
.withMessage('Name is required'),
check('email')
.not()
.isEmpty()
.withMessage('Email is required')
.isEmail()
.withMessage('Invalid Email')
.custom((value, {req}) => {
return new Promise((resolve, reject) => {
User.findOne({email:req.body.email}, function(err, user){
if(err) {
reject(new Error('Server Error'))
}
if(Boolean(user)) {
reject(new Error('E-mail already in use'))
}
resolve(true)
});
});
}),
// Check Password
check('password')
.not()
.isEmpty()
.withMessage('Password is required'),
// Check Password Confirmation
check('confirmedPassword', 'Passwords do not match')
.exists()
.custom((value, { req }) => value === req.body.password)
], function(req, res) {
var name = req.body.name;
var email = req.body.email;
var password = req.body.password;
var confirmedPassword = req.body.confirmedPassword;
// Check for Errors
const validationErrors = validationResult(req);
let errors = [];
if(!validationErrors.isEmpty()) {
Object.keys(validationErrors.mapped()).forEach(field => {
errors.push(validationErrors.mapped()[field]['msg']);
});
}
if(errors.length){
res.render('register',{
errors:errors
});
} else {
var newUser = new User({
name: name,
email: email,
password: password,
admin: false,
active: false
});
User.createUser(newUser, function (err, user) {
if (err) {
throw err;
}
});
req.flash('success_msg', 'You are registerd and can now login');
res.redirect('/users/login');
}
You can similarly do this to check for the username also.
Here is the link to the official GitHub page of express-validator
You can use Monsgoose's Model.findOne()=> https://mongoosejs.com/docs/api.html#model_Model.findOne:
router.post('/register',(req,res)=>{
// Object destructuring
const {username,password,email,...rest} =req.body;
// Error's Array
let errors = [];
// Mongoose Model.findOne()
User.findOne({email:email}).then(user=>{
if(user){
errors.push({msg: 'Email already exists'});
res.render('register',{errors})
}
})
})
You can use email-check package for checking whether the user had been previously registered (whether there is a duplicate email address inside email field).
Here is the link for downloading the package
https://www.npmjs.com/package/email-check
By writing unique: true property inside Models will provide mail address to be not repetitive. But you should also include email-chack validation which you can do inside Router
import emailCheck from "email-check";
//other imports
router.post("/register", (req, res) => {
var name = req.body.name;
var email = req.body.email;
var password = req.body.password;
var confirmedPassword = req.body.confirmedPassword;
// your validation for another fields
emailCheck(email)
.then(() => {
User.create(req.body)
.then(() => {
res.send(req.body);
})
.catch((error) =>
res.json({serverErrorDublicateEmail: "The email address is already subscribed. Please try to use another one or simply Log in"});
});
})
.catch(() => {
res.json({serverErrorEmailExistence: "The email address doesn't exist. Please try the valid one"});
});
});
emailCheck returns a Promise. Note: I am using ES6 syntax.
That's all. Your UserSchema can stay without any validation.