I have a user model like this:
module.exports = {
attributes: {
email: {
type: 'string',
isEmail: true,
unique: true,
required: true
},
password: {
type: 'string',
required: true
}
},
beforeCreate: (value, next) => {
bcrypt.hash(value.password, 10, (err, hash) => {
if (err){
throw new Error(err);
}
value.password = hash;
next();
});
},
};
Now when I want to match the password during login, how do I decrypt the password, if possible I would prefer to perform it in the user model file.
controller/ login.js
module.exports = {
login: async (req, res) => {
try{
const user = await User.findOne({email: req.body.email});
if (!user){
throw new Error('Failed to find User');
}
// here I want to match the password by calling some compare
//function from userModel.js
res.status(201).json({user: user});
}catch(e){
res.status(401).json({message: e.message});
}
},
};
first try to find the user with the given username by user
const find = Users.find(user=>user.username===req.body.username)
if(!find){
res.send('User Not Found')
}
else{
if( await bcrypt.compare(req.body.password,find.password)){
//now your user has been found
}
else{
//Password is Wrong
}
}
You must use bcrypt.compare(a,b)
a = given password by user
b = original password if username exist
hope it solve your problem
I have successfully send a token in my Email upon Registration via Send Grid
router.post(
'/',
[
check('lastname', 'Lastname is required').not().isEmpty(),
check('firstname', 'Firstname is required').not().isEmpty(),
check('email', 'Please include a valid email').isEmail(),
check(
'password',
'Please enter a password with 6 or more characters'
).isLength({ min: 6 }),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { lastname, firstname, email, password } = req.body;
try {
// Identify if users exists
let user = await User.findOne({ email });
if (user) {
return res.status(400).json({
errors: [{ msg: 'User already exists' }],
});
}
// Get users avatar
const avatar = gravatar.url(email, {
// size
s: '200',
// rating
r: 'pg',
// default (mm = default image)
d: 'mm',
});
// create a new instance of a user
user = new User({
lastname,
firstname,
email,
avatar,
password,
});
// // Encrypt password
// // salt to do the hashing
const salt = await bcrypt.genSalt(10);
// // creates a hash and put to the user.password
user.password = await bcrypt.hash(password, salt);
const token = jwt.sign(
{
user,
},
accountActivation,
{
expiresIn: 360000,
}
);
const emailData = {
from: emailFrom,
to: user.email,
subject: 'Account Activation',
html: `
<h1>Please use the following to activate your account</h1>
<p>${PORT}/activeprofile/${token}</p>
<hr />
<p>This email may contain sensetive information</p>
<p>${PORT}</p>
`,
};
sgMail
.send(emailData)
.then(() => {
return res.json({
message: `Email has been sent to ${email}`,
});
})
.catch((err) => {
return res.status(400).json({
msg: 'Unable to send',
});
});
// await user.save()
} catch (err) {
console.error(err.message);
res.status(500).send('Server error');
}
});
and I have successfully get an Email with it's token.
whenever I am trying to verify it in my postman.
router.post('/activeprofile', (req, res) => {
const { token } = req.body;
if (token) {
jwt.verify(token, accountActivation, (err) => {
if (err) {
console.log('Activation error');
return res.status(401).json({
errors: 'Expired link. Signup again',
});
} else {
const { lastname, firstname, email, password } = jwt.decode(
token
);
// create a new instance of a user
const user = new User({
lastname: req.body.lastname,
firstname,
email,
password,
});
user.save((err, user) => {
if (err) {
console.log('Error Saving the User', err.message);
return res.status(401).json({ msg: 'Unable to save' });
} else {
return res.status(200).json({
success: true,
message: user,
message: 'Signup Success',
});
}
});
}
});
} else {
return res.json({
message: 'Error happened, Please try again later',
});
}});
I always get this Error.
I even tried doing
const user = new User({
lastname: req.body.lastname,
firstname: req.body.firstname,
email: req.body.email,
password: req.body.passsword,
});
still I ended up with all the same errors in the picture posted.
Btw. this is my User Schema
const UserSchema = new mongoose.Schema({
lastname: {
type: String,
required: true,
},
firstname: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
avatar: {
type: String,
},
date: {
type: Date,
default: Date.now,
},}); module.exports = Use = mongoose.model('user', UserSchema);
my postman error:
I manage to figure out the problem. It's because I have created a double instance of the user
so I removed the user instance from the registration
router.post(
'/',
[
check('lastname', 'Lastname is required').not().isEmpty(),
check('firstname', 'Firstname is required').not().isEmpty(),
check('email', 'Please include a valid email').isEmail(),
check(
'password',
'Please enter a password with 6 or more characters'
).isLength({ min: 6 }),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { lastname, firstname, email, password } = req.body;
try {
// Identify if users exists
let data = await User.findOne({ email });
if (data) {
return res.status(400).json({
errors: [{ msg: 'User already exists' }],
});
}
const token = jwt.sign(
{
lastname,
firstname,
email,
password,
},
accountActivation,
{
expiresIn: 360000,
}
);
const emailData = {
from: emailFrom,
to: email,
subject: 'Account Activation',
html: `
<h1>Please use the following to activate your account</h1>
<p>${PORT}/activeprofile/${token}</p>
<hr />
<p>This email may contain sensetive information</p>
<p>${PORT}</p>
`,
};
sgMail
.send(emailData)
.then(() => {
return res.json({
message: `Email has been sent to ${email}`,
});
})
.catch((err) => {
return res.status(400).json({
msg: 'Unable to send',
});
});
// await user.save()
} catch (err) {
console.error(err.message);
res.status(500).send('Server error');
}
});
and put it in the account activation together with the gravatar and the hashing of the passwords
router.post('/activeprofile', (req, res) => {
const { token } = req.body;
if (token) {
jwt.verify(token, accountActivation, async (err, decoded) => {
if (err) {
console.log('Activation error');
return res.status(401).json({
errors: 'Expired link. Signup again',
});
}
const { lastname, firstname, email, password } = jwt.decode(token);
// // Get users avatar
const avatar = gravatar.url(email, {
// size
s: '200',
// rating
r: 'pg',
// default (mm = default image)
d: 'mm',
});
// create a new instance of a user
let user = new User({
lastname,
firstname,
email,
avatar,
password,
});
// Encrypt password
// salt to do the hashing
const salt = await bcrypt.genSalt(10);
// creates a hash and put to the user.password
user.password = await bcrypt.hash(password, salt);
user.save((err, user) => {
if (err) {
console.log('Error Saving the User', err.message);
return res.status(401).json({ msg: 'Unable to save' });
} else {
return res.status(200).json({
success: true,
message: user,
message: 'Signup Success',
});
}
});
});
} else {
return res.json({
message: 'Error happened, Please try again later',
});
}});
and it's successful, the user is saved in the database.
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;
}
})
});
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.
When registering a new user, I want to check email for uniqueness. I am using body parser to make sure all fields are not empty, but how am I to check that the input email is not used by anyone else and to immediately output the message for a user?
The technology stack is Node.js, mongoose, body-parser module, mongodb
Here's the route file:
router.post('/register', function(req, res){
let name = req.body.name;
let email = req.body.email;
req.checkBody('name', 'Name field is empty!').notEmpty();
req.checkBody('email', 'Email field is empty!').notEmpty();
req.checkBody('email', 'Invalid email format').isEmail();
var errors = req.validationErrors();
if(errors){
res.render('register', {
errors:errors
});
} else {
let newUser = new User({
name: name,
email: email
});
After looking through similar questions, I found a way to use a pre save in my model file, but I don't know how to sisplay the error to the user as a part of the errors array (see above)
Any help will be highly appreciated!
You can achieve both from the Mongoose model and the Register() method.
The user model should be like this:
var mongoose = require('mongoose');
var UserSchema = new mongoose.Schema({
email: {
type: String,
lowercase: true,
unique: true,
sparse: true
},
password: {
type: String,
required: true
},
},
{
timestamps: true
});
module.exports = mongoose.model('User', UserSchema);
This will ensure that emails are unique. Then at the register method, you do this:
exports.register = function(req, res, next){
let name = req.body.name;
let email = req.body.email;
User.findOne({email: email}, function(err, existingUser){
if(err){
return res.status(500).json(err);
}
if(existingUser){
return res.status(422).json('Email address is already registered.');
}
else {
var user = new User({
username : username,
email: email,
password: password
});
user.save(function(err, user){
if(err){
return next(err);
}
var userInfo = setUserInfo(user);
res.status(201).json({
token: 'JWT ' + generateToken(userInfo),
user: userInfo
})
});
}
});
}
}
}
Hope this helps.