hash field with promiss function in nodejs from utilite - javascript

i have a class for hash data in nodejs .
this is my class :
const bycrypt = require("bcrypt");
module.exports = new (class Utilitie {
HashField(field) {
return new Promise((resolve, reject) => {
bycrypt.hash(field, bycrypt.genSaltSync(15), (error, hash) => {
if (error) return reject(error);
resolve(hash);
});
});
}
})();
and this is my controller for use this class for hash data :
async ResetPassword(req, res, next) {
const result = await this.ValidationAction(req, res);
if (result[0]) {
let user = await User.findOne({ userName: req.body.userName }).then(
(user) => {
if (!user) return this.Notfound(res);
user.password = Utilite.HashField(req.body.password).then(
(error, hash) => {
console.log("in controller", hash);
}
);
user.save();
}
);
this.Ok(res);
}
return this.BadRerquest(res, result[1]);
}
but it not hash field and it return the undefined .
whats the problem ? how can i solve this problem ????

The argument that your then callback receives will be the hash value. The return value of the then() call will be another promise. You meant to use await:
async ResetPassword(req, res, next) {
const result = await this.ValidationAction(req, res);
if (result[0]) {
const user = await User.findOne({ userName: req.body.userName });
if (!user) return this.Notfound(res);
user.password = await Utilite.HashField(req.body.password);
// ^^^^^
await user.save();
this.Ok(res);
} else {
this.BadRerquest(res, result[1]);
}
}

Related

Node.js constant is not waiting for response from async function

I am new to async/await and I'm trying to set a 'user'-constant as the return value of a MySQL query in Node.js. However, the constant does not wait for the return value of the function. How do I use async and await to set 'user' to the return value of the SQL query?
// Should return a user object
const getUserByUsername = async (username, db) => {
const QUERY = `SELECT * FROM ${table_name} WHERE username = '${username}'`;
const user = await db.query(QUERY,
async (err, result) => {
if (!err) {
console.log("name in SQL function: " + result[0].username);
return await result[0];
} else {
console.log(err);
}
}
);
return user;
};
// Does stuff with the user object
const authenticateUser = async (username, password, done) => {
const user = await getUserByUsername(username, db);
console.log("name in main function: " + user.username);
// Trying to do stuff with the user object...
}
What I get in the terminal:
name in main function: undefined
UnhandledPromiseRejectionWarning: Error: data and hash arguments required
at Object.compare
at /app/node_modules/bcrypt/promises.js:29:12
at new Promise (<anonymous>)
at Object.module.exports.promise
etc.....
name in SQL function: john
When you use db.query with a callback, it does not return a promise
Try the following code instead
const getUserByUsername = async (username, db) => {
const QUERY = `SELECT * FROM ${table_name} WHERE username = '${username}'`;
const result = await db.query(QUERY);
console.log("name in SQL function: " + result[0].username);
return result[0];
};
Please try the below code.
const getUserByUsername = async (username, db) => {
try {
const QUERY = `SELECT * FROM ${table_name} WHERE username = '${username}'`;
const user = await db.query(QUERY, async (err, result) => {
if (err) {
throw err;
}
if (result && result.length) {
return result[0];
}
throw new Error(`User with username ${username} not found`);
});
console.log(`name in SQL function: ${user.username}`);
return user;
} catch (error) {
console.log(error);
throw error;
}
};
After jfriend00's comment, I decided to make my function a callback function. I found this answer explaining how to do it: https://stackoverflow.com/a/31875808/6817961. This worked!
My code now:
// Function returns a user object
const getUserByUsername = (username, callback) => {
const QUERY = `SELECT * FROM ${db_name} WHERE username = '${username}'`;
db.query(QUERY, (err, result) => {
if (!err) {
if (result.length > 0) {
return callback(null, result[0]);
} else {
err = "No user with that username";
return callback(err, null);
}
} else {
return callback(err, null);
}
});
};
// Then this function does stuff with the callback
const authenticateUser = (username, password, done) => {
getUserByUsername(username, async (err, result) => {
if (err) {
console.log(err);
return done(null, false, { message: err });
} else {
const user = result;
// result will now return the user object!

Can't return data out of the bcrypt.compare() function in nodejs with promises

I'm currently buildung an application with nodejs (10.15.2) but I'm running into some problems with the login function.
Snippet from my "dbconnector.js" file:
login(email, password) {
return userModel.findOne({
email: email
}).lean().then(function(user) {
// return user;
return bcrypt.compare(password, user.password, function(err, res) {
if (res) {
console.log(user); //prints the userinfo - works fine
return user;
}
});
});
};
Snippet from my serve.js file:
app.post('/login', async (req, res) => {
var { email, password } = req.body;
var user = await dbconnector.login(email,password);
console.log(user) //returns undefined
if (user != false) {
console.log("loggedin");
const accessToken = jwt.sign({ email: user.email, id: user.id }, key.tokenKey);
res.json({
accessToken
});
} else {
res.send('Username or password incorrect');
}
});
My problem is that the login()-function returns undefined. However, when I change it to the following, it works perfect (just without checking the password...):
login(email, password) {
return userModel.findOne({
email: email
}).lean().then(function(user) {
return user;
});
};
So I know something's wrong with the bcrypt / promise part but I couldn't find a solution.
My Fellow brother, the problem lives in the fact that a promise will only return you another promise and the compare callback that you have there as its name says callback is not apromise. Lets make it a promise
login(email, password) {
return userModel.findOne({
email: email
}).lean().then(function(user) {
// return user;
return new Promise((resolve, reject) => {
return bcrypt.compare(password, user.password, (err, res) => {
if (err) {
return reject(err);
}
return resolve(res);
})
};
BUT!!! if by any means the bcrypt package u are using is this one
https://www.npmjs.com/package/bcrypt
then you dont event have to promisify the method, it has it as promise already
login(email, password) {
return userModel.findOne({
email: email
}).lean().then(function(user) {
return bcrypt.compare(password, user.password);
}).then(isEquals => {
if (isEquals) {
return true
}
return false
}).catch(error => {
throw error;
})
};

async function not returns value but showing after calling undefined typescript

Below is my function returning login token when I debug my function it waits until return but when call function returns undefined and errors are also undefined don't know why it's happening
import userModel from '../Models/user.model';
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken')
let token = null;
process.env.SECRET_KEY = 'secret';
export default class loginController{
static async login(user:any): Promise<any>{
try{
await userModel.findOne({
Email: user.Email
})
.then(async (res:any) => {
if (user) {
if (await bcrypt.compareSync(user.Password, res.Password)) {
const payload = {
Firstname: res.Firstname,
Lastname: res.Lastname,
email: res.Email,
}
token = await jwt.sign(payload, process.env.SECRET_KEY, {
expiresIn: 1400
})
let decoded = jwt.verify(token, process.env.SECRET_KEY)
return token;
}
else {
return "Password is Wrong";
}
}
else {
return 'Please Check Username';
}
})
.catch(err => {
return('error : ' + err)
})
}
catch(err)
{
return err
}
}
}
And my calling function is
const router : Router = Router();
router.post('/login', async (req, res, next) => {
try {
const user = await loginController.login(req.body);
res.json(user)
} catch (error) {
res.json(error)
}
})
I tried call errors it's also debugger waiting until returns value to error but showing undefined
Thanks for the help!
login function doesn't return token because of function scoping. If you have multiple callbacks you can wrap it with a new Promise and use resolve function for returning values.
export default class loginController {
static async login(user: any): Promise<any> {
try {
return new Promise(async (resolve, reject) => {
await userModel
.findOne({
Email: user.Email
})
.then(async res => {
if (user) {
if (await bcrypt.compareSync(user.Password, res.Password)) {
const payload = {
Firstname: res.Firstname,
Lastname: res.Lastname,
email: res.Email
};
const token = await jwt.sign(payload, process.env.SECRET_KEY, {
expiresIn: 1400
});
let decoded = jwt.verify(token, process.env.SECRET_KEY);
resolve(token);
} else {
resolve('Password is Wrong');
}
} else {
resolve('Please Check Username');
}
})
.catch(err => {
resolve('error : ' + err);
});
});
} catch (error) {
return error;
}
}
}

I am not getting the mongoose queried user as the returned value

This is my apollo resolver and I want to return the user but it does not return anything and if I return the query itself then I cannot do the password checking
my code:
login: (parent, { email, password }, context, info) => {
User.findOne({ email }, function(err, user) {
if (user.length) {
bcrypt.compare(password, user[0].password, function(err, res) {
if (res) {
console.log(user[0]); // this has the user
return user[0]; // but this does not return anything
} else {
throw new ApolloError("failed");
}
});
} else {
throw new ApolloError("failed");
}
});
}
I have done this solution and it is working perfectly
login: async (parent, { email, password }, context, info) => {
const user = await attemptSignIn(email, password);
return user;
}
const attemptSignIn = async (email, password) => {
const message = "Incorrect email or password. Please try again.";
const user = await User.findOne({ email });
if (!user || !(await matchesPassword(user, password))) {
throw new AuthenticationError(message);
}
return user;
};
matchesPassword = (user, password) => {
return compare(password, user.password);
};

How to wait on sequelize executing a findOne

I've got a route using Sequelize.js
app.get('/api/users/:username', (req, res) => {
const foundUser = getUserByUsername(req.params.username);
console.log(`foundUser = ${foundUser}`);
return res.send(foundUser);
});
the getUserByUsername function is as follows
const getUserByUsername = username => {
Viewer.findOne({
where: {username}
}).then(response => {
console.log(response.dataValues);//the object with the data I need
return response.dataValues;
});
};
I hoped on getting the object in my const foundUser in my route, but it seems I need to wait until the findOne has been executed, because in my console I can see that the log of foundUser (which is undefined then) is executed before the function getUserByUsername
foundUser = undefined
Executing (default): SELECT `id`, `username`, `instakluiten`, `role`, `createdAt`, `updatedAt` FROM `viewers` AS `viewer` WHERE `viewer`.`username` = 'instak' LIMIT 1;
{ id: 19,
username: 'instak',
instakluiten: 18550,
role: 'moderators',
createdAt: 2016-10-02T16:27:44.000Z,
updatedAt: 2016-10-09T10:17:40.000Z }
How can I make sure that my foundUser will be updated with the data áfter the user has been found?
You have to return the promise that Sequelize creates and then wait for it to resolve. So the getUserByUsername becomes:
const getUserByUsername = username => {
return Viewer.findOne({
where: {username}
}).then(response => {
console.log(response.dataValues);//the object with the data I need
return response.dataValues;
});
};
and in the route:
app.get('/api/users/:username', (req, res) => {
getUserByUsername(req.params.username).then(foundUser => {
res.send(foundUser);
});
});
This is because you need to keep the chain of promises. If you forget to return it, the function returns undefined end even if the promise is finallly resolved, the value it resolves to never gets up back in the chain.
app.get('/api/users/:username', (req, res) => {
getUserByUsername(req.params.username, function(err, result){
const foundUser = result;
console.log(`foundUser = ${foundUser}`);
res.send(foundUser);
});
});
const getUserByUsername = function(username, callback) {
Viewer.findOne({
where: {username}
}).then(response => {
console.log(response.dataValues);//the object with the data I need
return callback(null, response.dataValues);
});
};
You can avoid it with promise or with callback
app.get('/api/users/:username', (req, res) => {
getUserByUsername(req.params.username, function(err, foundUser) {
if (!err) {
console.log(`foundUser = ${foundUser}`);
return res.send(foundUser);
} else {
res.send(err)
}
});
});
const getUserByUsername = (username, callback) => {
Viewer.findOne({
where: {
username
}
}).then(response => {
console.log(response.dataValues); //the object with the data I need
return callback(null, response.dataValues);
});
};

Categories

Resources