I started the implementation of a RESTful API usin node.js, express, and mongodb. Everything went well until now, I've a route to authenticate an user as follow:
apiRoutes.post('/authenticate', function(req, res) {
User.findOne({
nickname: req.body.nickname
}, function(err, user) {
if (err) throw err;
if (!user) {
res.json({
success: false,
message: 'Authentication failed. User not found.'
});
} else if (user) {
console.log(user);
console.log(user.nickname);
console.log(user.email);
console.log(user.password);
console.log(user.sexe);
if (user.password != req.body.password) {
res.json({
success: false,
message: 'Authentication failed. Wrong password.'
});
} else {
var token = jwt.sign(user, app.get('salt'), {
expiresInMinutes: 1440 // expires in 24 hours
});
res.json({
success: true,
token: token
});
}
}
});
});
The user is retrieved, and loged in the console as follow:
{ sexe: 'H',
email: 'MrPanda#gmail.com',
password: 'bambou',
nickname: 'MrPanda',
_id: 56cb703e7aef3f83c7dac0a7 }
which is perfect, but then, the three following consol.log return the three following lines:
MrPanda
MrPanda#gmail.com
undefined
H
I see absolutely no reason why the password is undefined at this point, I tried to change the attribute name to 'mdp', same issue... Any ideas ? Thanks
If you are using mongoose it does not return a plain JSON object. It is actually a special mongoose object and may not function how you expect.
You have two options:
Convert the mongoose object to a JSON object.
Add {lean: true} to the Users options parameter.
OR JSON.stringify(user)
OR user.toJSON()
Use the proper get() and set() methods (which you should be doing anyways).
user.get('password')
user.get('email')
user.get('name')
Try that and let me know if it doesn't work still.
Related
I have a controller that when i insert data into the database it always inserted. Now i wanna check that if the data i create is null is must report an error.
Here is my code:
// create new car
export async function createCar (req, res) {
const car = new Car({
car_id: id,
name: req.body.name,
color: req.body.color,
brand: req.body.brand,
});
return car
.save()
.then((newCar) => {
return res.status(201).json({
success: true,
message: 'New car created successfully',
Car: newCar,
});
})
.catch((error) => {
console.log(error);
res.status(500).json({
success: false,
message: 'Server error. Please try again.',
error: error.message,
});
});
}
And i check on postman even i let Name is NULL is still inserted. Furthermore, how can i check that COLOR, BRAND if it's null must also report an error. Please help me.
Kato, please follow my boilerplate. I created it with the best practices, and it also provides high-end JOI request validation.
A boilerplate for building production-ready RESTful APIs using Node.js, ExpressJs, Mongoose and Joi (Request Validation)
Node-Express-Mongoose-Joi
For validate before insert
// Validate request
if (!req.body.name)
{
res.status(400).send
({
message: "Name can not be empty!"
});
return;
} else if (!req.body.color)
{
res.status(400).send
({
message: "Color can not be empty!"
});
return;
} else if (!req.body.brand)
{
res.status(400).send({
message: "Brand can not be empty!"
});
return;
}
I'm trying to response from my backend a piece of user id by using lodash, i tryed with id.slice(2, 9) but i get a response without _id. What i'm doing wrong? thanks in advance.
getUserData: (req, res, next) =>{
User.findById(req.params.userId,
(err, user) => {
if (!user)
return res.status(404).json({ status: false, message: 'User record not found.' });
else
return res.status(200).json({ status: true, user: _.pick(user, ['_id'.slice(2, 9), 'domain', 'store', 'settings']) });
}
);
},
getUserData: (req, res, next) =>{
User.findById(req.params.userId,
(err, user) => {
if (!user)
return res.status(404).json({ status: false, message: 'User record not found.' });
else {
let json = { status: true, user: _.pick(user, ['_id', 'domain', 'store', 'settings']) };
json.user._id = json.user._id.slice(2, 9);
return res.status(200).json(json);
}
}
);
},
Pick the parts you want
Slice the _id to replace it with just the part you want
return the object
Edit:
To cut the ObjectId is necessary first to parse to string, so you need something like this:
var newUserId = user._id.toString().substring(3,user._id.toString().length)
But there is a problem (I think, not tested). If you try to store the cut id into a model object, maybe mongoose don't allow you to add an string (and no valid ObjectId) value instead of ObjectId.
Maybe is neccesary create another object instead of the model with the schema.
Old answer (unrelated) but maybe usefull for somebody:
If you want to hide the result just use select() into your query.
You run a query and then select which fields do you want to get or not into the response.
The proper way to code it is as follows:
query.select({ field1: 1, field2: 1 });
//or
query.select('-field1');
//and many other ways
Docs here
So I have this MEAN-stack app where, on the back-end, I have two ways to create a new user: through google authentication and through username.
Now, I am working on the code to create a new user through username, but I can't return the value from another function in my node.js file (in this case createNewUser()). When I look at my database the new user is created, but the value returned from createNewUser() is undefined.
I first thought it was a problem due to asynchronicity, so I tried a setTimeout(). The function however still returns undefined. Does someone see why?
This is the route in my node.js backend: the two console.logs return undefined
router.post('/signup', function(req, res){
var result = createNewUser(req.body);
console.log('result 1', result);
setTimeout(function(){
console.log('result2', result);
if (!result.success){
res.status(500).json({
message: "unable to create User",
obj: result.err
})
} else {
res.status(200).json({
message: "successfully created new user",
obj: result.obj
})
}
}, 6000);
});
This is the createNewUser() function in that same file, the console.log returns the user, so the user is actually created, the function just doesn't return the value.:
function createNewUser(userData, socialRegistry){
var user;
if (socialRegistry){
user = new User({
firstName: userData.firstName,
lastName: userData.lastName,
email: userData.body.email,
googleID: userData.body.provider.ID
});
} else {
user = new User({
firstName: userData.firstName,
lastName: userData.lastName,
username: userData.username,
password: bcrypt.hashSync(userData.password, 10),
email: userData.email,
registerDate: new Date()
});
}
user.save(function(err, user) {
if (err) {
return {
success: false,
err: err
}
}
if (socialRegistry){
return user
} else {
console.log(user);
var test = {
success: true,
obj: user
}
return test
}
});
}
Although I agree that this is a basic Async issue, the link prescribed above answers it in a very general way, and is frankly TLDR for this issue here.
Since your processes, like save, are asynchronous, you can't just return something back. Instead, pass a closure / function to the code, and call that function when things have completed. Most of Node is predicated on this kind of usage, for reasons that are TLDR to list here.
createNewUser(req.body,null,function(result){
if (!result.success){
res.status(500).json({
message: "unable to create User",
obj: result.err
})
} else {
res.status(200).json({
message: "successfully created new user",
obj: result.obj
})
}
});
function createNewUser(userData, socialRegistry, onComplete){
....
user.save(function(err, user) {
if (err) {
onComplete({
success: false,
err: err
})
}
if (socialRegistry){
onComplete(user)
} else {
onComplete({
success: true,
obj: user
})
}
});
}
There are some answers that are great for posterity, this may not be one of them, but there is power in simplicity.
Oh, and to answer one of the questions you post in your post, the reason why 'result' never gets set to anything is that your function has already completed and has an implicit return after the async call to user.save().
I am trying to do a simple login using nodejs and sequelize, i already have a user on the database and i try to send the info as req.body and checking if it exist in the where clausure
Like this:
router.post('/', function (req, res, next) {
console.log("hi");
if (JSON.stringify(req.body) == "{}") {
return res.status(400).json({ Error: "Login request body is empty" });
}
if (!req.body.username || !req.body.password) {
return res.status(400).json({ Error: "Missing fields for login" });
}
User.find({ where: { username: req.body.username,password: req.body.password} })
.then(function (user) {
return res.status(200).json({ message: "loged in!" });
}).catch(function (err) {
return res.status(400).json({ Error: "There is no user with those fields" });
});
});
it enters always on the loged in message, even if i send data that doesn't exist on the database, any info why it is happening?
You need to check if user is actually defined:
User.find({ where: { username: req.body.username,password: req.body.password} })
.then(function (user) {
if (! user) {
return res.status(400).json({ Error: "There is no user with those fields" });
} else {
return res.status(200).json({ message: "loged in!" });
}
})
.catch(...)
You're assuming that a query that doesn't yield any results will throw an error, but it won't (because the query ran successfully).
Also, you can make unique index on db to be completely sure that user is unique.
Btw, this index will speed-up login process.
Sequelize index docs ref
im writing a query in node js, my model of schema has 3 objects( userid, tokenid, mediaid), and i want to find the token id of a certain userid and use it in another function.
my code is as below:
app.get('/registeruser/:userid', function(req, res){
var name = req.params.userid;
user.findOne({userid: name},function(err, users1){
if(!users1){
res.send('Error 404, user not found');
return res.status(404).send();
}
else{
var query = user.find({tokenid: 1});
query.where({userid: name});
query.exec(function(err, result){
if(err){
res.send('erooooooor')
}
else{
res.send('okk')
console.log(result)}
});
user is the name of my model.
i run my code and i expect it to return the tokenid but it returns this: []
with these in my database:
userid: 'hgfj1234',
tokenid: 'juiodkdn12345678',
mediaid: ['med10', 'med11']
when i write userid: 'hgfj1234' it gives me this: [] but i want the real tokenid.
if anyone can help me i really appreciate it.
thanks in advance.
You don't need to do additional request to get record from mongodb.
That's enough to use findOne with complex attributes.
Try this:
app.get('/registeruser/:userid', function(req, res) {
var query = {
userid: req.params.userid,
tokenid: {$exists: true, $not: {$size: 0}}
};
user
.findOne(query)
.exec(function(err, User) {
if(err) { // error happen,
console.error(err); // log error
return res.status(500).send({
success: false,
message: 'System error'
}); // respond with 500 status and send json response with success false and message. return will stop execution to go down
}
if(!User) { // response from database was empty or null
return res.status(404).send({
success: false,
message: 'User not found'
}); // respond with 404 status and send json response with success false and message. return will stop execution to go down
}
res.send({
success: true,
tokenid: User.tokenid
}); // and at last everything is ok, we return json response with success and tokenid in response
});
});
attributes in query variable means to request mongodb to give us document with userid defined in request and that has tokenid that is defined and not is empty string (not size 0).
if You still did not getting desired result so check database for existence of necessary document.
If I understand your query right, you will reduce all find() calls to the tokenid with value 1. You will receive only any result, if the user has the token "1".
I suspect you wanted to code a projection, that is the second parameter on find():
var query = user.find({"userid": name});
query.select({"tokenid": 1})
.exec(function(err, result){
if(err){
res.send('erooooooor')
}
else{
res.send('okk')
console.log(result)}
});