pre() in es6 not running as expected? - javascript

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

Related

findByIdAndUpdate not updating the object Node.js

I have the following code to update Users information by Id:
router.put("/:id", async (req, res) => {
if (req.body.userId === req.params.id || req.body.isAdmin) {
if (req.body.password) {
try {
const salt = await bcrypt.genSalt(10);
req.body.password = await bcrypt.hash(req.body.password, salt);
} catch (err) {
return res.status(500).json(err);
}
}
try {
await User.findByIdAndUpdate(req.params.id, { $set: req.body });
res.status(200).json("Account has been updated");
} catch (err) {
return res.status(500).json(err);
}
} else {
return res.status(403).json("You can update only your account!");
}
});
I pass the new fields and findByIdAndUpdate is returning the catch error, I'm new to node and following a tutorial.

Bcrypt compare issue nodejs

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

How to wrap node.js function to access them in organized way

So I come to this, I want to write into a DB and do other operations to work with my program logic, this is the guide that I'm following Node.js Class Creation:
//## This is my mysql_test.js file
function MySQL(){
var mysql = require('mysql');
var con = mysql.createConnection({
//data omitted
});
function AppendRecordset (req, res){
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
con.query(req, function (err, res) {
if (err) throw err;
console.log("1 record inserted");
});
});
}
function UpdateRecordset (req, res) {
con.connect(function(err) {
if (err) throw err;
con.query(req, function (err, res) {
if (err) throw err;
console.log(result.affectedRows + " record(s) updated");
});
});
}
function DeleteRecordset (req, res){
con.connect(function(err) {
if (err) throw err;
con.query(req, function (err, res) {
if (err) throw err;
console.log("Number of records deleted: " + result.affectedRows);
});
});
}
function GetRecordset (req, res) {
con.connect(function(err) {
if (err) throw err;
con.query(req, function (err, res, fields) {
if (err) throw err;
console.log(result);
});
});
}
}
I then have in a separate file(s) my app logic, and want to use what of the above as an object/class so I wrote this accordingly to that guide:
//##this is inside my main app file
//declare the sql processor
require('./mysql_test.js');
var DB = MySQL();
DB.AppendRecordset(sql_string, res); //sql_string contains a valid SQL statement
But when I try to acces it using `` I get this error message: ReferenceError: MySQL is not defined what am I doing wrong?
I think these functions handle your routes, so I didn't change them. Because I don't know how your router is desined.
Create a file dbHangler.js and write this single function:
const mysql = require('mysql');
let con;
exports.execQuery = (query) => {
return new Promise((resolve, reject) => {
if(!con) {
con = mysql.createConnection({
//data omitted
});
}
con.connect(function(err) {
if(err) {
reject(err);
}
else {
console.log("Connected!");
con.query(query, function (err, res) {
if (err) {
reject(err);
}
else {
resolve(res);
}
});
}
});
});
};
In your dedicated.js file, now you can write:
const dbObject = require('path/to/dbHandler');
function AppendRecordset (req, res){
dbObject.execQuery(req)
.then(result => {
console.log(result.affectedRows + " record(s) updated");
})
.catch(error => {
// handle error
});
}
function AppendRecordset (req, res){
dbObject.execQuery(req)
.then(result => {
console.log("Number of records deleted: " + result.affectedRows);
})
.catch(error => {
// handle error
});
}
function AppendRecordset (req, res){
dbObject.execQuery(req)
.then(result => {
console.log(result);
})
.catch(error => {
// handle error
});
}
UPDATE
I hope this one helps you.
DbHandler.js
const mysql = require('mysql');
class DbHandler {
constructor(config) {
let self = this;
self.dbConfig = config;
self.connection = mysql.createConnection({
//data omitted
});
}
queryExecuter(query) {
let self = this;
return new Promise((resolve, reject) => {
self.connection.connect(function (err) {
if (err) {
reject(err);
}
else {
console.log("Connected!");
self.connection.query(query, function (err, res) {
if (err) {
reject(err);
}
else {
resolve(res);
}
});
}
});
});
}
AppendRecordset(query) {
let self = this;
return self.queryExecuter(query)
.then(result => {
console.log("1 record inserted");
return result;
})
.catch(error => {
// handle error
throw error;
});
}
UpdateRecordset(query) {
let self = this;
return self.queryExecuter(query)
.then(result => {
console.log(result.affectedRows + " record(s) updated");
return result;
})
.catch(error => {
// handle error
throw error;
});
}
// and other functions
}
module.exports = DbHandler;
And use it like below:
let DB = require('/path/to/DbHandler');
let myDb = new DB(/* db config */);
db.UpdateRecordset('your query')
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});

Problem hashing password with bcrypt on node.js

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

Cannot read property "rid" of undefined

[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.

Categories