Having issue with creating user registration with node - node.js

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.

Related

Getting an error that token is expired when trying to reset password following click on email link. Using Node js, express and mongoose

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.

How to verify if email is already in the MongoDB | Nodejs

I create a loginapp in nodejs but i want to verify if the email(or username) il already in the database.
router.post('/register', function(req, res) {
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
req.checkBody('username', 'Please enter a username').notEmpty();
req.checkBody('email', 'pls enter a email adress').notEmpty().isEmail();
req.checkBody('password', 'pls enter a password').notEmpty();
req.checkBody('password2', 'the password dont match').equals(req.body.password);
var errors = req.validationErrors();
if(errors) {
res.render('register',{
errors:errors,
})
} else {
var newUser = new User({
email:email,
username: username,
password: password
});
User.createUser(newUser, function(err, user){
if(err) throw err;
console.log(user);
});
req.flash('success_msg', 'u create an accoun, u can log');
res.redirect('/users/login');
}
})
How can a do a verify why an error msg if the email is already in the database ?
You can call findOne on the collection with the specified email. It resolves to null if no document matches. You can use that so as to detect whether or not there is already a user with the same email in the database.
You didn't provide the relevant part of the code to guess the architecture of you database, but you're probably going to use something like the following:
const { MongoClient } = require('mongodb');
const email = 'john#doe.com';
// wraps everything in an async function
(async () => {
// connect to database
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const users = client.db('your-db-name').collection('users');
// look for an existing user
let possibleDuplicate = await users.findOne({email});
if (possibleDuplicate===null) {
// email is not taken
// do something...
} else {
// email is taken
// do something...
}
})()

Creating Routes in NodeJs

I am trying to build a user registration forum for a web app.
To refactor my code I created a folder named api and defined some routes in index.js (/api/routes/index.js).
Now I wanted to route my signup form to this route in (/api/routes/index.js) so that the data can go to user_sign_up function which is defined in (api/controllers/users.js)
my app.js looks like:
// some code
var routesApi = require('./api/routes/index');
app.use('/api', routesApi);
// some code
my (/api/routes/index) looks like:
// some code
var ctrlevents = require('../controllers/users');
router.post('/registeruser', ctrlevents.user_sign_up);
// some code
module.exports = router;
In server folder of my app, I have views folder under which all .html files are present.
How do I define routes for action attribute in signup form?
my users.js looks like:
module.exports.user_sign_up = (req, res) => {
// some code
};
I tried:
<form method="POST" action="/registeruser">
got this:
enter image description here
Following is working but getting 500 status.
<form method="POST" action="/api/registeruser">
Adding user_sign_up function:
/* GET signup data */
module.exports.user_sign_up = (req, res) => {
Name: req.body.username;
email: req.body.email;
password: req.body.password;
cpassword: req.body.cpassword;
console.log('ghfhghgh');
console.log(email);
console.log(password);
console.log(cpassword);
req.checkBody('Name', 'Name is required').notEmpty();
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('cpassword', 'Passwords do not match').equals(req.body.password);
let errors = req.validationErrors();
if (err) {
res.render('register', {
errors:errors
});
}
else {
let newUser = new User({
Name:Name,
email:email,
password:password
})
}
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err) {
console.log(err);
}
newUser.password = hash;
newUser.save((err) => {
if(err) {
console.log(err);
return;
}
else {
req.flash('success', 'Welcome to TechPath');
req.redirect('/blog');
}
})
});
})
};
As I understand, you want the action attribute in your sign up form. Since you already created a route registeruser which also has controller user_sign_up, just pass registeruser to your form as action. It should be working.
<form method="POST" action="/registeruser">
</form>
Edit:
I created a similar structure to yours, my code works well. Try to compare your code and my code and keep me updated if your issue is resolved or not.
I think you have to assign value using = sign
Name = req.body.username;
email = req.body.email;
password = req.body.password;
cpassword = req.body.cpassword;

validate user by express-validator

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;
}
})
});

Express-Validator: Validation Error Message not Appearing for custom validator

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.

Resources