I have an error in my registration routes - node.js

During the course of testing if my user's registration route is working fine using postman as a testing machine, it throw an error that I don't know what it means.
I have tried using an async function to catch the error, but it didn't work out
const express = require('express');
const router = express.Router();
// Use to help set a default image for users
const gravatar = require('gravatar');
// Use to encrypt our password from bringing plain text
const bcrypt = require('bcryptjs');
// I add the user model from my model
// So i can be able to check create a new registration
// and also check if email exist
const User = require('../../models/User');
// #route GET api/users/register
// #desc Register user
// #access Public
router.post('/register', (req, res) => {
User.findOne({ email: req.body.email }).then(user => {
if (user) {
errors.email = 'Email already exists';
return res.status(400).json(errors);
} else {
const avatar = gravatar.url(req.body.email, {
s: '200', // Size
r: 'pg', // Rating
d: 'mm' // Default
});
const newUser = new User({
name: req.body.name,
email: req.body.email,
avatar,
password: req.body.password
});
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => res.json(user))
.catch(err => console.log(err));
});
});
}
});
});
module.exports = router;
I want the user input on postman should be able to post the form so I can know if the route is actually working fine. And this is the error I got on my console
(node:14164) UnhandledPromiseRejectionWarning: ReferenceError: errors is not defined
at User.findOne.then.user (the working director/name.js:26:7)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:14164) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:14164) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Normally we should handle the error in a kind of this way:
User.findOne({ email: req.body.email }).then(user => {
// ...
}).catch(error => {
console.log('error', error)
res.json({error: error})
})

Related

node.js async multiple await not working for user signup

I am trying to reproduce this code using async/await but I can't figure how to
.then.catch chain/nest
exports.signup = (req, res, next) => {
bcrypt.hash(req.body.password, 10)
.then(hash => {
const user = new User({
email: req.body.email,
password: hash
});
user.save()
.then(() => res.status(201).json({ message: 'Utilisateur créé !' }))
.catch(error => res.status(400).json({ error }));
})
.catch(error => res.status(500).json({ error }));
};
What I came up with trying to use async/await
exports.signup = async (req, res, next) => {
try {
const hash = await bcrypt.hash(req.body.password, 10);
const user = new User({
email: req.body.email,
password: hash
});
console.log(user);
let saveUser = await user.save();
console.log(saveUser);
res.status(201).json({ message: 'Utilisateur créé !'})
} catch (e) {
res.status(500).json({e})
}
};
I am getting the user in my console but the code crashes during user.save() since I don't get anything from console.log(saveUser)
I've been reading that you can stack await functions into one try block, but maybe here it doesn't work since you need
I've tried separating the try/catch, requiring me to initialise hash outside of the try block since i'll be using it in the second try but it's also not working.
After editing according to Nil Alfasir's thoughts:
exports.signup = async (req, res, next) => {
try {
const hash = await bcrypt.hash(req.body.password, 10);
const user = new User({
email: req.body.email,
password: hash
});
console.log(user);
user.save();
return res.status(201).json({ message: 'Utilisateur créé !'})
} catch (e) {
return res.status(500).json({e})
}
};
But I'm getting this in the console
(node:43390) UnhandledPromiseRejectionWarning: MongoError: E11000 duplicate key error collection: myFirstDatabase.users index: username_1 dup key: { username: null }
.
.
.
(node:43390) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:43390) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Correcting Nir Alfasi on save async
save() IS a async function SAVE ASYNC
so it won't return anything.
If there's an error it can be caught be catch.
A few issues:
user.save() doesn't return any value (according to the first snippet) - and you're trying to save a returned value into saveUser
Nit: please add a return before res.status...
UPDATE
The "update" of the question totally changed it, please avoid from doing that and post a new question in the future.
Sounds like you must provide a username when creating a user because username must be unique, and when you try to create multiple users without a username the DB creates a record with username=null so the first one may create but the second one will fail.

"UnhandledPromiseRejectionWarning: Error: Illegal arguments: undefined, string"

I was trying to follow up this "Build A Node.js API Authentication With JWT Tutorial" on YouTube. For some reason the post request of /register, is giving me this error:
UnhandledPromiseRejectionWarning: Error: Illegal arguments: undefined, string.
Below you can find the code:
const router = require('express').Router();
const User = require('../user');
const {resigerValidate} = require('../validation');
const bcrypt = require('bcryptjs')
router.post('/register', async (req, res)=>{
// doing validation from validation.js
const {error} = resigerValidate(req.body);
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(req.body.password, salt);
if (error) {
return res.status(400).send(error.details[0].message);
}
// checks if the email already exists in the database (partially working)
const emailExists = await User.findOne({email: req.body.email});
if (emailExists){
return res.status(400).send('This email already exists in the database !!!');
}
// user creation
const user = new User({
name: req.body.name,
email: req.body.email,
password: hashedPassword
});
try{
const savedUser = await user.save();
res.send(savedUser);
}catch(err){
res.status(400).send(err);
}
});
module.exports = router;
// Error
(node:15748) UnhandledPromiseRejectionWarning: Error: Illegal arguments: undefined, string
at _async (C:\Users\Admin\JavaScript\jwt\jwt\node_modules\bcryptjs\dist\bcrypt.js:214:46)
at C:\Users\Admin\JavaScript\jwt\jwt\node_modules\bcryptjs\dist\bcrypt.js:223:17
at new Promise (<anonymous>)
at Object.bcrypt.hash (C:\Users\Admin\JavaScript\jwt\jwt\node_modules\bcryptjs\dist\bcrypt.js:222:20)
at C:\Users\Admin\JavaScript\jwt\jwt\routes\auth.js:19:41
(node:15748) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:15748) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate
the Node.js process with a non-zero exit code.
According to your stack info bcrypt.hash(..) is rejected. Looks like you need to move this part of the code a little bit lower. Something like
const {error} = resigerValidate(req.body);
// checks if the email already exists in the database (partially working)
const emailExists = await User.findOne({email: req.body.email});
if (emailExists){
return res.status(400).send('This email already exists in the database !!!');
}
try{
// user creation
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(req.body.password, salt);
if (error) {
return res.status(400).send(error.details[0].message);
}
const user = new User({
name: req.body.name,
email: req.body.email,
password: hashedPassword
});
const savedUser = await user.save();
res.send(savedUser);
}catch(err){
res.status(400).send(err);
}

Node.js: Cannot read property 'password' of undefined in route

I am trying to implement my first user login authentication with jwt. I have a registration endpoint, where I have populated fake data. Now I want to login with the data I have in database. I am testing via Postman, but I have an error which is
[Object: null prototype] {
email: 'fakeEmail#gmail.com\t',
password: '12345678'
}
(node:14781) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'password' of undefined
at /home/me/coding/project/backend/routes/user.js:38:40
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:14781) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:14781) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
POST /user/login - - ms - -
Assuming it might be because of bodyparser, i have tried both way
//app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser());
but same error.
Here is my login endpoint
router.post("/login",(req, res) => {
const {email, password } = req.body;
console.log(req.body)
pool
.query("SELECT * FROM users WHERE email = $1 AND password = $2 LIMIT 1", [email, password ])
.then(res => {
const data = res.rows[0];
if ( email && password === data.password) {
const token = jwt.sign({ email: req.body.email }, "mySecretKey", {
expiresIn: "30 day",
});
res.send(token);
} else {
res.sendStatus(401);
}
});
});```
You have a problem in res object try loging res in then block. res.rows[0] seems undefined
My problem was, that I have registration endpoint, where I am using Bcrypt, and I had to Verify in Login endpoint. Therefore I was getting errors.
So, here is my corrected Login endpoint
router.post("/login", (req, res) => {
const { email, password } = req.body;
pool
.query("SELECT * FROM users WHERE email = $1 LIMIT 1", [email])
.then((result) => {
const data = result.rows[0];
if (result.rows.length > 0 && email) {
bcrypt.compare(password, data.password, function (err, result) {
if (result) {
const token = jwt.sign({ email: req.body.email }, "mySecretKey", {
expiresIn: "30 days",
});
res.send(token);
} else {
res.sendStatus(401);
}
});
} else {
res.sendStatus(401);
}
});
});
I hope, it will help someone having similar issue

`UnhandledPromiseRejectionWarning: Unhandled promise rejection` in my node application

For learning Node.js I follow a course where they use a async/await like this:
exports.signup = async (req, res) => {
const userExists = await userExists.findOne({ email: req.body.email });
if (userExists) {
return res.status(403).json({
error: "Email is taken!"
});
} else {
const user = await new User(req.body);
await user.save();
return res.status(200).json({ user });
}
};
But it gives me a UnhandledPromiseRejectionWarning with crashing the application.
(node:10780) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise
which was not handled with .catch(). (rejection id: 1)
(node:10780) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero
exit code.
It seems I didn't handle the error part but I did it with my else block, isn't it working like this?
Any help will be appreciated.
You need to catch any rejected promise from await statements by surrounding it with try/catch.
exports.signup = async (req, res) => {
try {
const userExists = await User.findOne({ email: req.body.email });
if (userExists) {
return res.status(403).json({
error: "Email is taken!"
});
} else {
const user = new User(req.body);
await user.save();
return res.status(200).json({ user });
}
} catch(e) {
// some sort of internal error (probably database issue)
console.log(e);
res.sendStatus(500);
}
};
This also removes the await in await new User(req.body) as await only does something useful when you await a promise and new User() is not asynchronous and does not return a promise so there's no reason to use await with it.
Note, that to avoid a race condition where two separate requests might both find that the user doesn't exist and both requests may try to create one, you need to make sure that your user email is configured in the database as a unique key so you can never get duplicate users for the same email. This is a subtlety in server programming that is important to understand to avoid race conditions.
As #jfriend00 said You need to catch any rejected promise from await statements by surrounding it with try/catch. You get ReferenceError because of using userExists before it creates. I am pretty sure that it should be User as you named your Schema User const user = new User(req.body); Let me know if you have any issue after change the code:
exports.signup = async (req, res) => {
try {
const userExists = await User.findOne({ email: req.body.email }); //I changed it to the Schema name
if (userExists) {
return res.status(403).json({
error: "Email is taken!"
});
} else {
const user = new User(req.body);
await user.save();
return res.status(200).json({ user });
}
} catch(e) {
// some sort of internal error (probably database issue)
console.log(e);
res.sendStatus(500);
}
};

Node js error "process with a non-zero exit code"

I developing a REST API using node js and express with MongoDB.
I have developed an endpoint to insert the user into DB and works fine. Now I have added the login function with jwt and now when I run my app and try to insert my user I receive this error:
an app is listening on port 3000
(node:3650) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Expected "payload" to be a plain object.
(node:3650) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I'm using a node js version: 8.9.3 on mac
Any help, please?
# this is the code about user add:
var router = require('express').Router();
var bcrypt = require('bcryptjs');
var User = require('../models/user');
var jwt = require('jsonwebtoken');
var constants = require('../config/constants');
router.post('/',(req, res) => {
// add user --> user = { username: 'test', email: 'test#tes.com', pwd: 'Test'}
var user = new User({
username: req.body.user.username,
email : req.body.user.email,
passhash: bcrypt.hashSync(req.body.user.pwd, 10)
});
user.save().then(
(newuser) => {
var sessionToken = jwt.sign(newuser._id, constants.JWT_SECRET, {expiresIn: 60*60*24});
res.json({
user: newuser,
message: 'success',
sessionToken: sessionToken
});
},
(err) => {
res.send(500, err.message);
}
);
});
module.exports = router;
and this is the code about login:
var router = require('express').Router();
var bcrypt = require('bcryptjs');
var jwt = require('jsonwebtoken');
var constants = require('../config/constants');
var User = require('../models/user');
router.post('/', (req, res) => {
User.findOne({ username: req.body.user.username}).then(
(user) => {
if(user){
bcrypt.compare(req.body.pwd, user.passhash, (err, matches) => {
if (matches) {
var sessionToken = jwt.sign(user._id, constants.JWT_SECRET, { expiresIn: 24*60*60 });
res.json({
user:user,
message: 'succesfully authed',
sessionToken: sessionToken
});
}else{
res.json({
user: {},
message: 'failed to auth',
sessionToken: ''
});
}
});
}else{
res.json({
user: {},
message: 'failed to auth',
sessionToken: ''
});
}
},
(err) => {
// could not find users
res.json(err);
}
);
});
module.exports = router;
I have tested the add user with postman and I have seen that when I receive the message posted, the user is inserted into db
If both API methods are declared in the same file, the problem can be because you are declaring twice same path + verb:
router.post('/', (req, res) => {

Resources