I have the code below. I'm trying to hash my admin password when they get registered. The password initially is set to default via the mongoose schema. Below are my codes. But it is not hashing.
AdminSchema.pre('save', function(next){
let admin = this; // bind this
if(admin.$isDefault('password')) {
bcrypt.genSalt(12, (err, salt)=> { // generate salt and harsh password
bcrypt.hash(admin.password, salt, (err, hash)=> {
admin.password = hash;
return next();
});
});
}
if(!admin.isModified('password')) {
return next();
}
bcrypt.genSalt(12, (err, salt)=> { // generate salt and harsh password
bcrypt.hash(admin.password, salt, (err, hash)=> {
admin.password = hash;
next();
});
});
});
It's because bcrypt method are execute asynchronously so for the first time this will be always executed
if(!admin.isModified('password')) {
return next();
}
this should work
AdminSchema.pre('save', function(next) {
const admin = this // bind this
if (admin.$isDefault('password') || admin.isModified('password')) {
bcrypt.genSalt(12, (err, salt) => { // generate salt and harsh password
if (err) {
return next(err);
}
bcrypt.hash(admin.password, salt, (err, hash) => {
if (err) {
return next(err);
}
admin.password = hash
return next()
})
})
} else {
return next();
}
})
Related
I've got myself two functions, first is responsible for adding a user model to database and second one for comparing passwords. But.. comparing never works..
module.exports.signup = function (req, res) {
if (req.body == null) {
res.status(400);
return res.end('Bad juju');
} else {
let exists;
User.findOne({ username: req.body.username }),
(err, doc) => {
if (doc) {
exists = true;
return;
}
};
if (exists) {
res.setHeader('user-exists', true);
res.redirect('/signup');
} else {
bcrypt.hash(req.body.password, 10, function (hashE, hash) {
if (hashE) {
throw hashE;
}
new User({
username: req.body.username,
email: req.body.email,
password: hash,
}).save();
});
return res.redirect('/login');
}
}
};
module.exports.login = function (req, res) {
if (req.body.tosignup) {
return res.redirect('/signup');
}
if (req.body == null) {
res.status(400);
return res.end('Bad request');
} else {
User.findOne({ username: req.body.username }, (err, doc) => {
if (err) throw console.log(err);
console.log(doc.password);
console.log(req.body.password);
bcrypt.hash(req.body.password, 10, (err, s) => {
console.log(s);
});
bcrypt.compare(req.body.password, doc.password, (err, succ) => {
if (err) {
throw err;
}
console.log(err);
console.log(succ);
if (succ) {
res.setHeader('username', doc.username);
return res.redirect('/welcome');
} else {
res.setHeader('password-wrong', true);
return res.redirect('/login');
}
});
});
}
};
I've looked for different sources and all of them told that this one method is the correct one, but every time I try using it, it just doesn't work
I had a similar problem using bcrypt in nodejs. To solve the problem i switched from npm bcrypt to npm bcryptjs (https://www.npmjs.com/package/bcryptjs) and used the following:
NPM require:
const bcrypt = require('bcryptjs');
To compare the passwords you can use the following code:
async function compareIt(password, hashedPassword) {
const validPassword = await bcrypt.compare(password, hashedPassword);
return validPassword;
}
compareIt(password, passwordBD).then(v => {
if (v == true) {
console.log("Equal");
} else {
console.log("Not equal");
}
});
To hash the password you can use this function:
async function hashIt(password) {
const salt = await bcrypt.genSalt(6);
const hashed = await bcrypt.hash(password, salt);
return hashed;
}
Postman is returning error whenever i include this pre() function,
it returns an error else its working and everything is getting stored in db using mongodb.
Is there something wrong in ES6 format that i have used or any other?
Below is the code :
// userschema is the name of the schema //
// SALT_I = 10 //
userSchema.pre('save', next => {
if (this.isModified('password')) {
bcrypt.genSalt(SALT_I, (err, salt) => {
if (err)
return next(err)
bcrypt.hash(this.password, salt, (err, hash) => {
if (err)
return next(err)
this.password = hash
next()
})
})
} else
next()
})
here is the postman error:
{
"success": false,
"err": {}
}
and it is as i am making a post request using the function:
app.post('/api/users/register', (req, res) => {
const user = new User(req.body)
user.save((err, data) => {
if (err) return res.json({ success: false, err })
res.status(200).json({
success: true,
userdata: data
})
})
})
You cannot use ES6 spread operator but ES5 syntax works just fine:
userSchema.pre('save', function (next) {
const user = this
if (user.isModified('password')) {
bcrypt.genSalt(SALT_I, function (err, salt) {
if (err) {
console.log("inside gensalt if")
return next(err)
}
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) {
console.log("inside bcrpt hash")
return next(err)
}
user.password = hash
next()
})
})
} else
next()
})
[TypeError: Cannot read property 'rid' of undefined]
Is the error that I get when I try to execute this controller on my post route.
I've tested it out with Postman.
I've tried to console.log(result) but I get undefined.
My query gets executed and my row is inserted into my table. I've checked it. Password is also hashed.
The problem is that I don't get any out binds that should be returned.
Problematic code (IMO) is
...
.then(function(result) {
console.log(result);
cb(null, {
id: result.outBinds.rid[0],
email: result.outBinds.remail[0],
role: result.outBinds.rrole[0]
});
})
...
oracle-NodeDB Wrapper
var oracledb = require('oracledb');
module.exports.OBJECT = oracledb.OBJECT;
function executeSQL(config ,sql, bindParams , options) {
return new Promise(function(resolve, reject) {
oracledb.getConnection(
config,
function(err, connection) {
if (err) {
return reject(err);
}
connection.execute(
sql,
bindParams,
options,
function(err, result) {
if (err) {
doRelease(connection);
return reject(err);
}
resolve(result);
doRelease(connection);
});
});
});
}
function doRelease(connection) {
connection.release(
function(err) {
if (err) {
console.log(err.message);
}
}
);
}
module.exports.executeSQL = executeSQL;
Controller
var database = require('../database/oracledbWrapper');
var dbconfig = require('../database/dbconfig').dbconfig;
var jwt = require('jsonwebtoken');
var bcrypt = require('bcrypt');
exports.createUser = function(req, res, next) {
var user = {
email: req.body.email
};
var unhashedPassword = req.body.password;
bcrypt.genSalt(10, function(err, salt) {
if (err) {
return next(err);
}
bcrypt.hash(unhashedPassword, salt, function(err, hash) {
if (err) {
return next(err);
}
user.hashedPassword = hash;
insertUser(user, function(err, user) {
var payload;
if (err) {
return next(err);
}
payload = {
sub: user.email,
role: user.role
};
res.status(200).json({
user: user,
token: jwt.sign(payload, config.jwtSecretKey, {expiresInMinutes: 60})
});
});
});
});
}
function insertUser(user, cb) {
var bindParams = {
email: user.email.toLowerCase(),
password: user.hashedPassword,
rid: {
type: database.NUMBER,
dir: database.BIND_OUT
},
remail: {
type: database.STRING,
dir: database.BIND_OUT
},
rrole: {
type: database.STRING,
dir: database.BIND_OUT
}
};
database.executeSQL(
dbconfig,
'insert into express_users (email, password, role ) values ( :email, :password, \'BASE\' ) returning id, email, role into :rid , :remail, :rrole',
bindParams,
{}
)
.then(function(result) {
console.log(result);
cb(null, {
id: result.outBinds.rid[0],
email: result.outBinds.remail[0],
role: result.outBinds.rrole[0]
});
})
.catch(function(err) {
console.log(err);
next(err);
});
}
Route
var RESTfulAPICon = require('../controllers/RESTfulAPI');
var indexCon = require('../controllers/index');
var views = require('express').Router();
views.route('/users').post(RESTfulAPICon.createUser);
exports.views = views;
The problem was in my wrapper , mainly here
module.exports.OBJECT = oracledb.OBJECT;
I export only the OBJECT property , but I try to access BIND_OUT properties later on. And they are non existent.
If I do the full export like this
module.exports.OBJECT = oracledb;
Then I can access BIND_OUT properties.
I can use the following to save a new document to my mongodb database.
User.prototype.save = function (fn) {
var user = new userModel({
user: this.user,
pass: this.pass
});
console.log('user: ' +user);
this.hashPassword (user.pass, function (err, salt, hash) {
if (err) return fn (err);
this.pass = hash;
user.salt = salt;
user.pass = hash;
user.save (function (err, product, numberAffected) {
if (err) return fn (err);
return fn(undefined);
});
});
};
Now I'm trying to check if the user already exists before saving it
User.prototype.save = function (fn) {
// See if the username exists
userModel.findOne ({ 'user': this.user }, function (err, user) {
if (err) return fn (err);
if (!user) {
user = new userModel({
user: this.user,
pass: this.pass
});
console.log('user: ' +user);
this.hashPassword (user.pass, function (err, salt, hash) {
if (err) return fn (err);
this.pass = hash;
user.salt = salt;
user.pass = hash;
user.save (function (err, product, numberAffected) {
if (err) return fn (err);
return fn(undefined);
});
});
} else {
// TODO: update all the user fields
console.log ('user already exists');
}
});
}
this.hashPassword is no longer found TypeError: Object #<Promise> has no method 'hashPassword' and the fields of user are now undefined. How can I use this within these callbacks?
EDIT 1:
Taking a closer look I also notice that this.pass = hash; in the first snippet also does nothing to the object I care about.
on line 2
var self = this
then,
self.hashPassword()
In full:
User.prototype.save = function (fn) {
var self = this;
// See if the username exists
userModel.findOne ({ 'user': self.user }, function (err, user) {
if (err) return fn (err);
if (!user) {
user = new userModel({
user: self.user,
pass: self.pass
});
console.log('user: ' +user);
self.hashPassword (user.pass, function (err, salt, hash) {
if (err) return fn (err);
self.pass = hash;
user.salt = salt;
user.pass = hash;
user.save (function (err, product, numberAffected) {
if (err) return fn (err);
return fn(undefined);
});
});
} else {
// TODO: update all the user fields
console.log ('user already exists');
}
});
}
I am have created a node library file called encrypt.js.
Within that are some functions created using bcrypt-nodejs
var bcrypt = require('bcrypt-nodejs');
exports.cryptPassword = function(password, callback) {
bcrypt.genSalt(10, function(err, salt) {
if (err) return callback(err);
else {
bcrypt.hash(password, salt, function(err, hash) {
return callback(err, hash);
});
}
});
};
exports.comparePassword = function(password, userPassword, callback) {
bcrypt.compare(password, userPassword, function(err, isPasswordMatch) {
if (err) return callback(err);
else return callback(null, isPasswordMatch);
});
};
When I now use cryptPassword from my server.js file it shows an error coming from the bcrypt-nodejs library stating 'no callback function was given'
I have added a function within my call as below
var encryptedPassword = encrypt.cryptPassword(req.body.user.password, function (err, salt){
if(err) {throw err};
console.log('hlllll');
});
Can anyone help?
Syntax: bcrypt.hash(data, salt, progress, cb)
You must have two callbacks.
Document here:
https://npmjs.org/package/bcrypt-nodejs
Update:
You can use the package bcrypt instead of bcrypt-nodejs
And your code will work:
bcrypt.hash(password, salt, function(err, hash) {
return callback(err, hash);
});
You can actually use bcyrpt-nodejs if thats what you prefer,but you have to edit the following section in bCrypt.js
if(!callback) {
throw "No callback function was given."
}
and replace it with
if(typeof callback == 'undefined') {
callback = progress;
progress = null;
}
then in your code, just have this;
require('bcrypt').hash(values.password,null,null,function passwordEncrypted(err,password){
use bcyrpt.compareSync instead of bcypt.compare. It doesn't require a callback