I'm implementing user authentication in my Node REST API.
I have defined in the UserController a method to remove a user:
async function remove(req, res) {
try {
User.findOneAndRemove({ _id: req.params.id });
return res.status(200).json({
message: 'user deleted',
});
} catch (err) {
console.log(err);
res.status(500).json({
error: err,
});
}
}
When I hit the route in Postman with an id from a user stored in the database, I get the success message: "user deleted"
However when I look in the database, the user is still there.
What am I doing wrong?
thanks for your help!
dough, forgot to put 'await' before User.findOneAndRemove ...
Related
I build a register page using React as Frontend, and Node Js as backend. However, when I try to check the delicate username. Axios from the Frontend doesn't show any error. I have written the catch in many different ways. But I still cannot find where the problem is. Could anyone help me out? Thanks!
Frontend
const handleSubmit = async (event) => {
event.preventDefault();
if (handleValidation()) {
await axios.post(registerRoute, {
username,
email,
password,
}).then((response) => {
console.log(response);
}).catch((error) => {
if (error.response.status === 11000) {
console.log(error.response.data);
}
})
navigate("/");
}
};
Backend
module.exports.register = async (req, res, next) => {
const { username, email, password } = req.body;
if (!username || typeof username !== 'string') {
return res.json({status: 'error', message: 'Invalid username'})
}
const usernameExit = await Users.findOne({username: username})
if (usernameExit) {
return res.status(11000).json({ message: "Username already exit" });
}
if (!password || typeof password !== 'string') {
return res.json({status: 'error', message: 'Invalid password'})
}
try {
const hashedPassword = await bcrypt.hash(password, 2);
const user = new Users({
username,
email,
password: hashedPassword,
});
user.save();
delete user.password;
return res.json({ status: true, user });
} catch (error) {
if (error.code === 11000) {
return res.status(11000).json({ message: "Username already exit" });
}
}
};
First things first. In your back end endpoint you need to add the word await in before saving the document since you're using async/await for this method.
await user.save();
Second, you won't be able to delete the user's password this way because this is a MongoDB document and not a JavaScript object. You can convert the document to be a JS object which was explained in this question below. After you convert it to a JS object then you do delete user.password, not before.
convert mongodb object to javascript object
Third, you should always follow the industry best practices and use one of the HTTPS codes based on the situation. This way you know that a MongoDB error code is coming from MongoDB and not your endpoint because you setup a different status code like 404 or 400 for any custom error handling that you are doing.
Here's the reference for the HTTPS codes - https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
If you want to catch the status in Axios, you need to set the status like #Yozi mentioned and follow the approach below
return res.status(400).json({message: "Some message here", user});
This way Axios will catch the 400 status and throw an error in the console. If you customize the status like
res.json({status: 'error'});
You need to handle that differently in your front end. You can do something like
console.log(res.data.status === 'error');
return res.json({status: 'error', message: 'Invalid password'})
It returns status 200, which is not an error (axios know nothing about your status: "error" thing.
status 11000 does not sound right to me. Normally it is something below 600. docs. In your case, I would use 422.
So, for all your errors add status(422) and check if it works.
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
I am creating RESTful API on node.js (express.js + mongoose).
I have mongoose model which has _id and title.
When I handle GET request to find specific object by _id, I use findById method and I want to know how to handle if the requested id was wrong. In other words, the question is "how to handle 404 status for findById method".
I have tried something like this, but it didn't work:
Blog.findById(id)
.select("_id title")
.exec()
.then(result => {
if (result) {
res.status(200).json({
article: result
});
} else {
res.status(404).json({
message: 'Article was not found'
});
}
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
Model.findById in mongoose will return null when no object matches the criteria, so you can simply put an if clause inside .then() before all code
.then(result => {
if(!result) return res.status(404).send('No result found');
// rest of your code here
And that will send a 404 to client.
router.delete('/:id', function(req, res){
user.remove({
_id: req.params.id
}, function(err, users) {
if(err) {
res.status(404).send({
message: "Invalid User",
data: []
});
} else {
res.status(200).send({
message: "User deleted",
data: []
});
}
});
});
I tried to implement the DELETE endpoint for my RESTful API.
It successfully deletes an existing data when I test it on postman,
but when I try to delete an invalid data, it still gives me a delete message
with a response status of 200.
What mistake am I making?
That right when you delete an not exist data the code work fine .
But you can check in users values it return nMatched if working in mongodb.
and for all database they contain this type of flag (here flag means 'nMatched' field in users object , you can check by printing users object ). for mongodb they contains values in 0 or 1
Can you something like this.
function(err, users) {
if(err) {
res.status(404).send({
message: "Invalid User",
data: []
});
} else if (users.nMatched === 0) {
res.status(400).send({
message: "User not exist deleted",
data: []
});
} else {
res.status(200).send({
message: "User deleted",
data: []
});
}
});
That is how I validating and saving my user:
var user = new User({ /** from body **/ });
user.validate((err) => {
if (err) {
console.log(err);
res.json({ success: false, message: 'Invalid input' });
}
else {
user.save((err) => {
if (err) { throw err; }
console.log(err);
res.json({ success: true });
});
}
});
Is there a better way of validate and save with mongoose with the less code lines or without if/else?
You can also add your validations inside your schema. I will recommend this way because you'll be able to make custom validations depending of the field.
http://mongoosejs.com/docs/validation.html
Then you'll only need to save your user and check for an error inside the save callback method.