I'm trying to let the user sign in using either email or username, I'm trying this code in Postman and each time I try it gives me this error:
"success":false,"status":500,"message":"data and hash arguments
required","stack":"Error: data and hash arguments required\n at
Object.compare
Auth.js Configurations:
const emailRegex = "/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/";
router.post("/login", async (req, res, next) => {
const isEmail = String(req.body.emailOrUsername).match(emailRegex);
try {
if (!req.body.password) {
return next(createError(400, "Invalid password"));
}
let user;
if (isEmail) {
user = await User.findOne({ where: { email: req.body.emailOrUsername } });
} else {
user = await User.findOne({ where: { username: req.body.emailOrUsername } });
};
if (!user) return next(createError(404, "User not found!"));
const isPasswordCorrect = await bcrypt.compare(
req.body.password,
user.password
);
if (!isPasswordCorrect) return next(createError(400, "Wrong password!"));
const { password, ...others } = user._doc;
res.status(200).json(others);
} catch (err) {
next(err);
}
});
I'm not sure what I'm missing here!
exports.signupController = async (req, res) => {
const { phone, password } = req.body;
try {
const user = await User.findOne({ phone }).exec()
if (user) {
return res.status(400).json({
errorMessage: 'Phone Number already exists',
});
}
const newUser = new User();
newUser.phone = phone;
const salt = await bcrypt.genSalt(10);
newUser.password = await bcrypt.hash(password, salt);
await newUser.save();
return res.status(200).json({
successMessage: 'Registration success. Please login',
});
} catch (err) {
console.log('signupController error: ', err);
res.status(500).json({
errorMessage: 'Server error',
});
}};
**I upload a node application in shared hosting! **
*But an error was showing in this controller function. All the time the catch block is running on the json. The error is unhandled promise rejection. *
signup(data)
.then((response) => {
console.log('Axios signup success: ', response);
setFormData({
phone: '',
password: '',
password2: '',
loading: false,
successMsg: response.data.successMessage,
});
history.push('/signin');
})
.catch((err) => {
console.log('Axios signup error: ', err);
setFormData({
...formData,
loading: false,
errorMsg: err.response.data.errorMessage,
});
});
this is react front end event handler
import axios from 'axios';
export const signup = async (data) => {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const response = await axios.post('/api/auth/signup', data, config);
return response;
};
the signup api function
Mongoose queries are not promises. They have a .then() function for co and async/await as a convenience. If you need a fully-fledged promise, use the .exec() function. for example:
const query = Band.findOne({name: "Guns N' Roses"});
assert.ok(!(query instanceof Promise));
// A query is not a fully-fledged promise, but it does have a `.then()`.
query.then(function (doc) {
// use doc
});
// `.exec()` gives you a fully-fledged promise
const promise = query.exec();
assert.ok(promise instanceof Promise);
promise.then(function (doc) {
// use doc
});
If you are using exec() on your findOne query you should use:
exports.signupController = async (req, res) => {
const { phone, password } = req.body;
try {
const user = await User.findOne({ phone }).exec();
/// just a pseudo code
user.then('do your things').catch( 'log error')
const newUser = new User();
newUser.phone = phone;
const salt = await bcrypt.genSalt(10);
newUser.password = await bcrypt.hash(password, salt);
await newUser.save();
return res.status(200).json({
successMessage: 'Registration success. Please login',
});
} catch (err) {
console.log('signupController error: ', err);
res.status(500).json({
errorMessage: 'Server error',
});
}};
for more details check this out: https://mongoosejs.com/docs/promises.html#should-you-use-exec-with-await?
This question already has answers here:
Why is it possible to try-catch an async-await call?
(2 answers)
Closed 2 years ago.
I have module that check username is unique or no!
my module is:
// Check for uniqueness username
const UsernameUniqueness = async (_username) => {
const username = await Users.findOne({
username: _username
});
if (username) {
return false;
}
return true;
}
exports.UsernameUniqueness = UsernameUniqueness;
and I have a route that I post username to it.
const FormUniqueness = require('../modules/form-uniqueness');
router.post('/register', redirectDashboard, async (req, res, next) => {
const ( username } = req.body;
try {
console.log(FormUniqueness.UsernameUniqueness(userName));
} catch (error) {
// Internal server error 500
console.log('here');
error.status = 500;
next(error);
}
}
I want when I have an error in "const username = await Users.findOne({
username: _username
}); my error throw in try/catch of my route!"
How can I do this?
Catch the error also in your function
const UsernameUniqueness = async (_username) => {
try {
const username = await Users.findOne({
username: _username
});
if (username) {
return false;
}
return true;
} catch(error) {
throw error;
}
}
exports.UsernameUniqueness = UsernameUniqueness;
Hi so I'm trying to create my first login with sequelize and I'm struggling with hashing and comparing hashes and it always returns false.
I figured I am doing something wrong on the hashes or comparing since I'm learning. I'm using SQL database
Here's my login code, I'm using express session and sequelize:
'processLogin': (req, res) => {
db.User.findOne({
where: {
email: req.body.email
}
})
.then(async user => {
var eSession = req.session.userLogin
let checkPass = await bcrypt.compare(req.body.password, user.password)
console.log(checkPass);
if(checkPass){
eSession = user;
res.send("Success");
}else{
res.render('login', {errors: [{
msg: "Incorrect password"
}]});
}
if(user == undefined){
res.render('login', {errors: [{
msg: "User not found, please Register"
}]});}
})
}
And here is where I actually hashed the passwords on my register:
'save': async (req, res) => {
var a = [req.body.fullname, req.body.email, req.body.number, bcrypt.hashSync(req.body.password, 10), bcrypt.hashSync(req.body.repassword, 10)];
let errors = validationResult(req);
if(errors.isEmpty()){
db.User.create({
full_name: a[0],
email: a[1],
phone_number: a[2],
password: await bcrypt.hash(a[3], 10),
confirm_password: await bcrypt.hash(a[4], 10)
})
.then(users => {
res.send("succes!!");
})
}else{
res.render('register', { errors: errors.errors })
}
}
}
insted of sync why don't you try async and wait unitll it get's hashed or decrypt.
inside async function to hash password.
let hashedPassword = await hash(password, 10);
and inside async function for comparing password
let checkPass = await compare(password, foundUser.password);
I have a route that allows a user to reset their password by sending them an email. Standard procedure for most websites. In this route, I import the async npm module and use the waterfall method so that I can handle the asynchronous nature of multiple functions. I'm still having a bit of trouble understanding promises, but I'm trying to replace waterfall with a promise or promise chain.
How could I refactor this route with a promise? Here are the steps contained in this route that is currently split up into 4 functions with waterfall.
First the route creates a reset token
Search for user based on email
2.5. If user is found, save user, otherwise return 404
Send email to user containing a reset url
Return a status of 200.
app.post('/forgotPassword', function(req, res, next) {
waterfall([
// generate reset token
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
// search for user with the given email
User.findOne({ email: req.body.email }, function(err, user) {
// check to see if the user exists
if (!user) {
// user doesn't exist in database
return res.status(404).send();
}
// user exists, assign token with expiration date
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour from now
// save the user model with the newly added
// token and expiration date
user.save(function(err) {
done(err, token, user);
});
});
},
function(token, user, done) {
var smtpTransport = nodemailer.createTransport('SMTP', {
service: 'SendGrid',
auth: {
user: config.sendgridUser,
pass: config.sendgridPassword
}
});
var mailOptions = {
to: user.email,
from: 'email#school.edu',
subject: 'Password Reset',
text: `Hello etc etc`,
smtpTransport.sendMail(mailOptions, function(err) {
done(err, 'done');
});
}],
function(err) {
// handle error
if (err) return next(err);
res.status(200).send();
});
}); // end POST route '/forgotPassword'
Promise is a very powerful tool. It can be hard to understand it at the beginning, but totally worth the effort! Please let me know if you have any doubts :)
app.post('/forgotPassword', function(req, res, next)
{
new Promise((resolve, reject) =>
{
// generate reset token
crypto.randomBytes(20, (err, buf) =>
{
if(err)
return reject(err);
const token = buf.toString('hex');
resolve(token);
});
})
.then((token) =>
{
return new Promise((resolve, reject) => {
// search for user with the given email
User.findOne({ email: req.body.email }, (err, user) =>
{
if (!user)
return reject(404);
// user exists, assign token with expiration date
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour from now
// save the user model with the newly added
// token and expiration date
user.save(function(err) {
if(err)
return reject(err);
resolve(user);
});
});
});
})
.then((user) =>
{
return new Promise((resolve, reject) =>
{
const smtpTransport = nodemailer.createTransport('SMTP',
{
service: 'SendGrid',
auth: {
user: config.sendgridUser,
pass: config.sendgridPassword
}
});
const mailOptions = {
to: user.email,
from: 'email#school.edu',
subject: 'Password Reset',
text: `Hello etc etc`
};
smtpTransport.sendMail(mailOptions, (err) =>
{
if(err)
return reject(err);
resolve();
});
});
})
.then(() => res.sendStatus(200))
.catch((err) =>
{
//check if the error is the one from the DB where the user was not found
if(err == 404) {
return res.sendStatus(404);
}
return res.status(500).send(err);
});
});
bluebird is one of the most popular promise library.
and it offers promisify function to convert callback hell to promise.
please read this document and play with it.
http://bluebirdjs.com/docs/working-with-callbacks.html
This answer presumes 4 completely sequential steps:
(Function () {
Return Promise (function (resolve, promise) {
// try to do some stuff
if (success) {
Resolve ("pass this value on to next link in the chain");
}
Reject();
})()
.then (function (value) {
// do next step
Return "pass this value on to next link in the chain";
.then (function (value) {
// do next step
Return "pass this value on to next link in the chain";
.catch (function (error) {
// handle any reject or any error in the chain
}
You could in relation to the individual .then also choose to return a Promise. Beware: any errors in the .catch block will be swallowed.
This is just an example with ES6 promise but working code. You can refactor it further to have a clear reusable code. You can replace ES5 functions with ES6 arrow functions.
app.post('/forgotPassword', function(req, res, next) {
var catch = function(err){
return next(err);
}:
var error404 = function(){
return res.status(404).send();
};
var success = function(){
return res.status(200).send();
};
var step1 = new Promise(function(resolve, reject){
crypto.randomBytes(20, function(err, buf) {
if(err){
reject(err);
} else {
var token = buf.toString('hex');
resolve(token);
}
});
});
var step2 = function(token) {
// search for user with the given email
User.findOne({ email: req.body.email }, function(err, user) {
// check to see if the user exists
if (!user) {
// user doesn't exist in database
return {error404: true};
}
// user exists, assign token with expiration date
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour from now
// save the user model with the newly added
// token and expiration date
user.save(function(err) {
return { error: err, token: token, user: user });
});
});
};
var step3 = function(obj) {
if(obj.error){
return catch(obj.error);
} else if(obj.error404) {
return error404();
} else {
var token = obj.token, user = obj.user;
var smtpTransport = nodemailer.createTransport('SMTP', {
service: 'SendGrid',
auth: {
user: config.sendgridUser,
pass: config.sendgridPassword
}
});
var mailOptions = {
to: user.email,
from: 'email#school.edu',
subject: 'Password Reset',
text: `Hello etc etc`,
smtpTransport.sendMail(mailOptions, function(err) {
if(err){
return catch(err);
} else {
return success();
}
});
}
};
step1.then(step2, catch).then(step3);
}); // end POST route '/forgotPassword'
Promises work best when you're dealing with a library where methods already return them, or a library like bluebird that lets you promisify existing callback APIs, otherwise it's a lot of conversions.
If you're still set on refactoring with plain es6, put your promise-wrappers at the lowest possible level, for best effect and cleanest error handling, basically promisify manually:
let convert = (resolve, reject) => (err, res) => err ? reject(err) : resolve(res);
crypto.randomBytesAsync = n=>new Promise((y,n)=>crypto.randomBytes(n,convert(y,n)));
User.findOneAsync = u => new Promise((y, n) => User.findOne(u, convert(y, n)));
User.prototype.saveAsync = () => new Promise((y, n) => this.save(convert(y, n)));
Then use them like this:
app.post('/forgotPassword', function(req, res, next) {
crypto.randomBytesAsync(20).then(buf => {
var token = buf.toString('hex');
// search for user with the given email
return User.findOneAsync({ email: req.body.email }).then(user => {
// check to see if the user exists
if (!user) {
// user doesn't exist in database
res.status(404).send();
throw;
}
// user exists, assign token with expiration date
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour from now
// save the user model with the newly added
// token and expiration date
return user.saveAsync().then(() => {
var smtpTransport = nodemailer.createTransport('SMTP', {
service: 'SendGrid',
auth: { user: config.sendgridUser, pass: config.sendgridPassword }
});
smtpTransport.sendMailAsync =
o => new Promise((y, n) => smtpTransport.sendMail(o, convert(y, n)));
return smtpTransport.sendMailAsync({
to: user.email,
from: 'email#school.edu',
subject: 'Password Reset',
text: `Hello etc etc`,
});
});
})
})
.then(() => res.status(200).send())
.catch(err => next(err));
}); // end POST route '/forgotPassword'