nodejs 500 internal server error on production server - node.js

I was testing my app on localhost and everything seemed to work correctly, but then I pushed my website to azure websites and things were working there as well except when I create a user it throws 500 error I don't get what could be the possible reason.
here is my route for creating users
router.post('/create', admin, (req, res, next) => {
bcrypt.hash(req.body.password, 10).then(hash => {
const user = new User({
email: req.body.email,
username: req.body.username,
userType: req.body.userType,
company: req.body.company
});
User.countDocuments({
email: req.body.email
})
.then(count => {
if (!count) {
user.save()
.then(result => {
res.status(201).json({
message: 'User created!',
result: result
});
})
.catch(err => {
res.status(500).json({
error: err
});
});
} else {
res.status(500).json({
message: 'Email already exists!'
});
}
})
.catch(err => {
res.status(500).json({
error: err,
message: 'Email already exists!'
});
});
});
});
so whenever I test the app on angular it shows email already exists! and 500 error

Related

Reactjs: post data to localhost always pending

I am working on ReactJs and NodeJS and I am creating a signup page. I post data to server but it is always pending.
Which part did I do wrong? It would be nice if someone can help.
Front end:
const handleSubmit = (event) => {
// prevent page refresh
event.preventDefault();
const newUserData = {
name: name,
email: email,
password: password,
};
axios
.post("/signup", newUserData)
.then((res) => {
console.log(res.data);
})
.catch((error) => {
console.log(error);
});
setEmail("");
setName("");
setPassword("")
console.log("form submitted ✅");
};
Backend:
router.post("/signup", (req, res) => {
const { name, email, password } = req.body;
if (!email || !password || !name) {
res.status(422).send({ error: "Please add all the fields" });
}
console.log(req.body);
User.findOne({ email: email })
.then((savedUser) => {
if (savedUser) {
res.status(422).send({ error: "Email already been used" });
}
bcrypt.hash(password, 12).then((hashedpassword) => {
const user = new User({
name,
email,
password: hashedpassword,
});
user
.save()
.then((user) => {
res.json({ message: "Sign Up Successfully" });
})
.catch((err) => {
console.log(err);
});
});
})
.catch((err) => {
console.log(err);
});
});
in package.json i set proxy as
"proxy": "http://localhost:5000",
I guess you are using MongoDB as well, in that case keep in your mind that the findOne is async, so you need to use await before. And for to save data you need to use the .create() method from MongoDB, e.g.
router.post("/signup", async (req, res) => {
const { name, email, password } = req.body;
if (!email || !password || !name) {
res.status(422).send({ error: "Please add all the fields" });
}
console.log(req.body);
await User.findOne({ email: email })
.then((savedUser) => {
if (savedUser) {
// you need to add return to stop the code
return res.status(422).send({ error: "Email already been used" });
}
// or you can add else because the code keep running
bcrypt.hash(password, 12).then((hashedpassword) => {
const user = await User.create({
name,
email,
password: hashedpassword,
});
user
.save()
.then((user) => {
res.json({ message: "Sign Up Successfully" });
})
.catch((err) => {
console.log(err);
});
});
})
.catch((err) => {
console.log(err);
});
});
I think it is better to use something like throw new Error('Email already been used') instead of return for your res.status(422).send({ error: "Email already been used" }); because if you have return the server doesn't give back an error, but a normal answer, but of course it is ok if you want that.
I want you to be sure that before you submit, the values name, email, password, are updated. Please try:
const handleSubmit = async (event) => {
// prevent page refresh
event.preventDefault();
console.log(`The value for the name: ${name}`);
console.log(`The value for the email: ${email}`);
console.log(`The value for the password: ${password}`);
try {
const response = await axios.post("http://localhost:5000/signup", {
name,
email,
password,
});
console.log(response.data);
setEmail("");
setName("");
setPassword("");
console.log("form submitted ✅");
} catch (error) {
console.log(error);
}
};

keeps getting "Illegal arguments: undefined, string at Object.bcrypt.hashSync"

I've been struggling with Bcrypt on my MERN project I'm trying to create an authentication system I'm trying to run tests on Postman and I'm not sure why do I keep getting the error: "Illegal arguments: undefined, string at Object.bcrypt.hashSync"
this is my postman request:
this is the Controller Code:
const config = require("../config/auth.config");
const db = require("../models");
const User = db.user;
const Role = db.role;
var jwt = require("jsonwebtoken");
var bcrypt = require("bcryptjs");
exports.signup = (req, res) => {
const user = new User({
username: req.body.username,
email: req.body.email,
password: bcrypt.hashSync(req.body.password, 8),
});
user.save((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
if (req.body.roles) {
Role.find(
{
name: { $in: req.body.roles },
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
user.roles = roles.map((role) => role._id);
user.save((err) => {
if (err) {
res.status(500).send({ message: err });
return;
}
res.send({ message: "User was registered successfully!" });
});
}
);
} else {
Role.findOne({ name: "user" }, (err, role) => {
if (err) {
res.status(500).send({ message: err });
return;
}
user.roles = [role._id];
user.save((err) => {
if (err) {
res.status(500).send({ message: err });
return;
}
res.send({ message: "User was registered successfully!" });
});
});
}
});
};
exports.signin = (req, res) => {
User.findOne({
username: req.body.username,
})
.populate("roles", "-__v")
.exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
if (!user) {
return res.status(404).send({ message: "User Not found." });
}
var passwordIsValid = bcrypt.compareSync(
req.body.password,
user.password
);
if (!passwordIsValid) {
return res.status(401).send({ message: "Invalid Password!" });
}
var token = jwt.sign({ id: user.id }, config.secret, {
expiresIn: 86400, // 24 hours
});
var authorities = [];
for (let i = 0; i < user.roles.length; i++) {
authorities.push("ROLE_" + user.roles[i].name.toUpperCase());
}
req.session.token = token;
res.status(200).send({
id: user._id,
username: user.username,
email: user.email,
roles: authorities,
});
});
};
exports.signout = async (req, res) => {
try {
req.session = null;
return res.status(200).send({ message: "You've been signed out!" });
} catch (err) {
this.next(err);
}
};
The error message:
Illegal arguments: undefined, string at Object.bcrypt.hashSync wants to say that you're passing undefined as an argument to the hashSync function. We need to fix this error.
Take a closer look at this line where the error occurs:
password: bcrypt.hashSync(req.body.password, 8),
req.body.password is undefined, you can verify it by console.log(req.body.password). What's wrong is that you are sending data as URL parameters. So req.body is an empty object and req.body.password is undefined.
In Postman, select the Body tab, choose JSON format, then type your data as a JSON object. Then, in your code, use express.json() middleware to parse requests in JSON format. You'll have the desired output.
You can see my example request in Postman below:

Why is the error showing ` catch((err) => {` is not a function?

I'm trying to authenticate users when registering on my app using Nodejs, express and mongoDB.
The user gets registered successfully and added to my database but then I get this error in the console that .catch is not a function. Which is after my user has been successfully registered and password hashed successfully as well.
what is the cause of the error that makes my server to crash?
console error:
.catch((err) => {
TypeError: res.status(...).send(...).catch is not a function
My code:
bcrypt.hash(req.body.password, 10)
.then((hashedPassword) => {
const user = new User({
email: req.body.email,
password: hashedPassword,
});
user.save().then((result) => {
res.status(201)
.send({
message: "User created successfully",
result,
}).catch((err) => {
// error is pointing at this line of code
res.status(500).send({
message: "Error creating User",
err,
});
});
});
}).catch((err) => {
res.status(500).send({
message: "Password was not hashed successfully",
err,
});
});
});
You placed/copied the catch to the wrong place, it should be catching the error when creating the user not when you send.
So change:
user.save().then((result) => {
res.status(201).send({
message: "User created successfully",
result,
}).catch((err) => {
// error is pointing at this line of code
res.status(500).send({
message: "Error creating User",
err,
});
});
});
to
user.save().then((result) => {
res.status(201).send({
message: "User created successfully",
result,
})
}).catch((err) => {
res.status(500).send({
message: "Error creating User",
err,
});
});
A few aolutions
1.Check your catch() function
You can try to make the code become clearer such as using a try catch function as the code maybe have some problems.
2. If problem #1 didn't work
Re-install express(if the problem didn't solve)
npm install express

How can I create secure CRUD operation using MERN stack

I'm new to MERN stack and I did CRUD operation. I want to hash the password upon creation of new user, since I'm getting an error after creating a new user and trying to login "Invalid credentials" since the new user has been created with the password plain text and my registration compares the password with the hashed one
My create new user code:
exports.create = (req, res) => {
if(!req.body.name || !req.body.email || !req.body.password) {
return res.status(400).send({
message: "Name, Email and Password can not be empty"
});
}
const user = new User({
name: req.body.name.trim(),
email: req.body.email.trim(),
password: req.body.password.trim()
});
user.save()
.then(data => {
const user = usersSerializer(data)
res.send(user);
}).catch(err => {
res.status(500).send({
message: err.message || "Some error occurred while creating the User."
});
});
};
You must hash the user's password before storing it in the database. Do something like this.
router.post(
'/register',
[
check('email', 'Uncorrectly e-mail').isEmail(),
check('password', 'Uncorrectly password').isLength({ min: 6 })
],
async (req, res) => {
try {
const errors = validationResult(req)
if (!errors.isEmpty()) {
return res.status(400).json ({
errors: errors.array(),
message: 'Incorrect registration data'
})
}
console.log(req.body)
const { email, password, firstName, lastName } = req.body
const candidate = await User.findOne({ email })
if (candidate) {
return res.status(400).json({ message: 'User already exist' })
}
const hashedPassword = await bcrypt.hash(password,12)
const user = new User ({email, password: hashedPassword, firstName, lastName})
await user.save()
res.status(201).json({ message: 'New user created' })
} catch (error) {
res.status(500).json ({ message: 'ERROR' })
}
})

Create USER with bcrypt and authenticate

This is my user.js file, where i handle two requestes.
First the POST /signup, where the user enters an email, and a password so that i can store it in mongodb.
var express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
var bcrypt = require("bcrypt");
var jwt = require("jsonwebtoken");
var User = require("../models/user");
router.post("/signup", (req, res, next) => {
User.find({ email: req.body.email })
.exec()
.then(user => {
if (user.length >= 1) {
return res.status(409).json({
message: "Mail exists"
});
} else {
bcrypt.hash(req.body.password, 10, (err, hash) => {
if (err) {
return res.status(500).json({
error: err
});
} else {
const user = new User({
_id: new mongoose.Types.ObjectId(),
email: req.body.email,
password: hash
});
user
.save()
.then(result => {
console.log(result);
res.status(201).json({
message: "User created"
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
}
});
}
});
});
Second the POST /login, where the user enters an email, and the password and with bcrypt i compare if the password matches the one in the db.
router.post("/login", (req, res, next) => {
User.find({ email: req.body.email })
.exec()
.then(user => {
if (user.length < 1) {
return res.status(401).json({
message: "Auth failed"
});
}
bcrypt.compare(req.body.password, user[0].password, (err, result) => {
if (err) {
return res.status(401).json({
message: "Auth failed"
});
}
if (result) {
const token = jwt.sign(
{
email: user[0].email,
userId: user[0]._id
},
process.env.JWT_KEY,
{
expiresIn: "1h"
}
);
return res.status(200).json({
message: "Auth successful",
token: token
});
}
res.status(401).json({
message: "Auth failed"
});
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
The problem is the following: Whenever i try to create a user /signup using postman the request stays in "loading" and the server shuts down.
POSTMAN body: {
'emial': 'teste#gmail.com',
'password': '12345'
}
Error in the server:
UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [node-rest-shop-shard-00-01-pbcph.azure.mongodb.net:27017] on first connect [MongoNetworkError: connection 4 to node-rest-shop-shard-00-01-pbcph.azure.mongodb.net:27017 timed out]
(node:1496) 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:1496) [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.
The User.find promise is being rejected because Node fails to connect to your MongoDB instance. This rejected promise tries to execute the first error handler that it comes across. In your case, it fails to find any catch() to handle this error. You can avoid this by adding a catch() to the promise chain at the end.
You should also look into why your Node instance cannot make a successful connection to your MongoDB instance.
router.post("/signup", (req, res, next) => {
User.find({ email: req.body.email })
.exec()
.then(user => {
if (user.length >= 1) {
return res.status(409).json({
message: "Mail exists"
});
} else {
bcrypt.hash(req.body.password, 10, (err, hash) => {
if (err) {
return res.status(500).json({
error: err
});
} else {
const user = new User({
_id: new mongoose.Types.ObjectId(),
email: req.body.email,
password: hash
});
user
.save()
.then(result => {
console.log(result);
res.status(201).json({
message: "User created"
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
}
});
}
}).catch(err => { //Handle the error here.
console.log(err);
res.status(500).json({
error: err
});
});
});
You should do the same for your login call.

Resources