Mongoose validate and save code - node.js

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.

Related

findById request, cant find my data in mongodb collection

I am creating URL Shortener Microservice application.I have a mongodb cluster that i save my all url links. I am successfully connect to database.I am making post request to save my posted url. Related code is here
app.post('/api/shorturl', (req, res) => {
const bodyUrl = req.body.url;
const something = dns.lookup(
urlParser.parse(bodyUrl).hostname,
(error, address) => {
if (!address) {
res.json({ error: 'Invalid URL' });
} else {
const url = new Url({ url: bodyUrl });
url.save((err, data) => {
res.json({
original_url: data.url,
short_url: data.id,
});
});
}
}
);
});
So, I can save my new url in database succesfully.Here also related cluster after post request
But my problem is with get request. I dont know why i cant find the url links by id. Here also my get request
app.get('/api/shorturl/:id', (req, res) => {
// const id = req.body.id;
Url.findById({ _id: req.body.id }, (err, data) => {
if (!data) {
res.json({ error: 'Invalid URL' });
} else {
res.redirect(data.url);
}
});
});
You need to either use:
Url.findOne({ _id: req.params.id }, (err, data) => {
if (!data) {
res.json({ error: 'Invalid URL' });
} else {
res.redirect(data.url);
}
});
or:
Url.findById(req.params.id, (err, data) => {
if (!data) {
res.json({ error: 'Invalid URL' });
} else {
res.redirect(data.url);
}
});
findOne takes an object as the argument (like you have).
findById just takes the ID as the argument.
You seem to be combining the two options.
Edit: I found another issue with your code, you are trying to pull the id from req.body.id, but in this case, you need to use req.params.id. The code in my post has been updated.

Deleting the model data through lodash and save() not persisting model in mongodb

I am trying to remove one object from the User collection like this
router.post('/accept-trades', function (req, res, next) {
const {senderName, receiverName, senderId} = req.body;
const user = req.user;
console.log(senderName, receiverName);
if (senderName) {
User.findOne({ name: senderName })
.then(sender => {
_.remove(user.receivedTradeRequest, {username: senderName});
_.remove(sender.sentTradeRequest, {username: receiverName});
console.log('user.receivedTradeRequest', user.receivedTradeRequest);
console.log('\n\nuser.sentTradeRequest', user.sentTradeRequest);
async.parallel([
function (cb) {
user.save()
.then(isSave => {
cb(null, true);
})
.catch(err => {
cb(err, null);
});
},
function (cb) {
sender.save()
.then(isSave => {
cb(null, true);
})
.catch(err => {
cb(err, null);
});
}
], (err, results) => {
if (err) {
return res.status(500).json({
message: 'Error: Trade is invalid as Card is already traded!',
});
}
res.send('done');
//res.redirect('/trade');
});
})
.catch(err => {
throw err;
});
} else {
return res.status(500).json({
message: 'Only accessible to logged in users!',
});
}
});
Here, user is accessed by req.user (i'm using passport).
When i log the user after removal, user.receivedTradeRequest and sender.sentTradeRequest printing empty array which is the correct behaviour.
But when i see the mongodb the array still present for the username.
Could you please suggest what is wrong with the code ?
PS: I know about the mongodb $pull for removal. I am doing some other computation on the user data so had to do with above approach.
I was able to solve it by re-assigning the array after removing the element. Used _.filter instead of _.remove solves the problem.
One thing i don;t understand is the lodash _.remove update the original array after deletion but that clearly is not the case here.

Node.js - Check if user exists

I'm using NodeJS and passport to let users create an account before they can see results of a quiz they've just taken. My challenge is I need to confirm the username is available before the page refreshes because the user will lose their results if this happens.
Again: I need to verify the username is not taken prior to refreshing.
I think I'm close but it is not working. How would I change my code to handle this challenge?
Currently if the user name is taken it returns an error on trying to create an account and the user ends up on the /failpage as shown below.
app.post('/quiz', usernameToLowerCase, emailToLowerCase, function(req, res) {
User.findOne({
username: req.body.username
}, function(err, user) {
if (err) {
alert(err)
if (user) {
alert('this username is already taken. Please choose another.')
console.log('there was a user');
return false;
}
}
});
var user = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password,
})
user.save(function(err) {
console.log('this is the problem' + ' ' + err)
if (err) {
return res.redirect('/failpage')
}
req.logIn(user, function(err) {
if (err) {
console.log(err);
}
console.log('all looks good')
res.redirect('/results');
});
});
});
Solved it with this if anyone else is trying to do the same thing:
in app.js
app.get('/usercheck', function(req, res) {
User.findOne({username: req.query.username}, function(err, user){
if(err) {
console.log(err);
}
var message;
if(user) {
console.log(user)
message = "user exists";
console.log(message)
} else {
message= "user doesn't exist";
console.log(message)
}
res.json({message: message});
});
});
In js
$('#usercheck').on('change', function() {
$.get('/usercheck?username='+$('#usernameValue').val().toLowerCase(), function(response) {
$('#usernameResponseHidden').text(response.message)
if ($('#usernameResponseHidden').html() === "user exists"){
$('#usernameResponse').text('That username is taken. Please pick another')
}
To solve your problem I think you need to routes. At least a app.get('/quiz') which returns a boolean on if the user exists or not. The section User.findOne can be sent in that route instead. You just need to make a request using ajax when he looses focus of the username field of your form, and display a notification if the name is available or not.

How to mimic mongoose 'save' and 'validate' methods

I have this code
var user = new User({ /** stuff **/ });
user.validate((err) => {
if (err) {
res.json({ success: false, message: 'Invalid input' });
}
else {
// save the sample user
user.save((err) => {
if (err) { throw err; }
res.json({ success: true });
});
}
});
I want to change user to my mock user so code above won't talk to the actual db. How can write custom validate, 'save' methods in such case?
My custom user mock save and validate:
public save(err:any) {
return this;
}
public validate(err:any) {
return this;
}
But the execution just freezes then when I using my custom user. With console.log() I find out that my custom method validate() fired but execution is not continued after probably because missing next() but I have no idea how I can plug it in. Need help.

Find a way to update the user passport with passport-local-mongoose

I'm creating an application with nodejs and passport-local-mongoose,
the problem is that i cannot find a way to update the user password since passport use Salt and Hash, there's some method or some way to update the password by a PUT method?
Assuming you've added the passport-local-mongoose plugin to your user schema, you should be able to call
setPassword(password, cb) on your user schema.
yourSchemaName.findById(id, function(err, user) {
user.setPassword(req.body.password, function(err) {
if (err) //handle error
user.save(function(err) {
if (err) //handle error
else //handle success
});
});
});
If you want to change the password you can use changePassword command.
here is an example
router.post('/changepassword', function(req, res) {
// Search for user in database
User.findOne({ _id: 'your id here' },(err, user) => {
// Check if error connecting
if (err) {
res.json({ success: false, message: err }); // Return error
} else {
// Check if user was found in database
if (!user) {
res.json({ success: false, message: 'User not found' }); // Return error, user was not found in db
} else {
user.changePassword(req.body.oldpassword, req.body.newpassword, function(err) {
if(err) {
if(err.name === 'IncorrectPasswordError'){
res.json({ success: false, message: 'Incorrect password' }); // Return error
}else {
res.json({ success: false, message: 'Something went wrong!! Please try again after sometimes.' });
}
} else {
res.json({ success: true, message: 'Your password has been changed successfully' });
}
})
}
}
});
});
If you want to change the password without using the old password you can use setPassword method. Here is an example
user.setPassword(req.body.password, function(err,user){
if (err) {
res.json({success: false, message: 'Password could not be saved. Please try again!'})
} else {
res.json({success: true, message: 'Your new password has been saved successfully'})
}
});

Resources