Mongo query always returns the value exists in database, when it does not - mongodb

I am trying to query for a name field in mongodb and with the following code I always get the response that the value is a duplicate.
var checkUserName = function (userName, email, res){
User.findOne({ name : userName }, function () {
if(userName && typeof userName !== 'undefined'){
res.send("duplicate");
}else{
checkEmail(email);
}
});
}

you are currently ignoring the answer from the database completely and are just checking your input again. This cannot work. Mongoose returns the answer of the query as the second parameter of the callback function (the first is always there to signal errors) - try something like this:
var checkUserName = function (userName, email, res){
User.findOne({ name : userName }, function (err, userFromDb) {
if (err) {
console.log("there was an error: " + err;
return res.send("err: " + err.message);
}
if(userFromDb) {
res.send("duplicate");
} else {
checkEmail(email);
}
});
}

Related

.find() returning nothing even when data exists

I've a mongo database with 3 collections for 3 different kind of users as User,Partner,Admin. Whenever a new user of any type signup I'm searching all three collections to check if username and email exist already. I'm trying to achieve this by calling a function as:
function checkAttribute(attr,val,callback){
User.find({attr: val},function(err,user){
if(err){
console.log(err);
}else{
if(user.length === 0){
Partner.find({attr: val},function(err,partner){
if(err){
console.log(err);
}else{
if(partner.length === 0){
Admin.find({attr: val},function(err,admin){
if(err){
console.log(err);
}else{
if(admin.length === 0){
return callback(null,true);
}else{
return callback(null,false);
}
}
});
}else{
return callback(null,false);
}
}
});
}else{
return callback(null,false);
}
}
});
};
Calling function line:
checkAttribute("username",newUser.username,function(error,response){
.......
});
But this is not working as it returns true always even when users with passed username/email exists already. I am unable to find the problem. Any one knows why this is happening?
Thanks in advance.
Since you are passing in the attribute as a variable in the function parameters, the query document
{ attr: val } is an object with the key "attr", not the dynamic attribute you pass in.
To fix this, you need to use computed property names in your query object as
{ [attr]: val }
Also, the function can use async/await pattern to be more readable and for the purpose of finding if a document exist findOne does the job so
well as it returns a document if it exists and null otherwise.
So your function can be refactored as
async function checkAttribute(attr, val, callback) {
try {
const query = { [attr]: val }
const user = await User.findOne(query).exec()
const partner = await Partner.findOne(query).exec()
const admin = await Admin.findOne(query).exec()
const found = (user || partner || admin) ? true: false
return callback(null, found)
} catch (err) {
console.error(err)
return callback(err, null)
}
};
attr: in your queries will search for a db field called attr. If you want to use the function parameter attr, use [attr]: as the key.
Example:
attr = 'username'
User.find({ [attr]: val }, function (err, user) {
if (err) {
console.log(err);
}
})
This is a feature available since ES6 so should work fine. See the docs here for more info

auth0 Custom Database Action Script - How to access user_id?

I'm using auth0, I'm making a script on create under Action Scripts to save user to my mongoDB database. I only need to save the email and user_id, but I can't find the user_id?
Code is below, but the user only returns: {"tenant":"tenant-name","connection":"MongoDB-MainDB","email":"xxx","password":"xxx","debug":true}
Here is my code (This is basically the sample code provided by auth0):
function create (user, callback) {
mongo('mongodb://xxx', function (db) {
var users = db.collection('users');
users.findOne({ email: user.email }, function (err, withSameMail) {
if (err) return callback(err);
if (withSameMail) return callback(new Error('the user already exists'));
else {
users.insert({ "_id" : user.user_id, "email" : user.email}, function (err) {
if (err) return callback(err);
callback(new Error(JSON.stringify(user)))
});
}
});
});
}
auth0 tutorial for reference: https://auth0.com/docs/connections/database/custom-db

Sails js,find user using either email or username

I am trying to login user using either username or email i.e user can enter either email or password and should be able to log in. However, so far I am able to use one of them.
Here is the code tried so far.
authenticate: function (req, res) {
var username = req.body.username;
var email = req.body.email;
users.findOne({
or: [
{username: username},
{email: email}
]
}).exec(function(err, user) {
console.log(user);
if (err) {
return res.json({err});
} else if (!user) {
var err = new Error('User not found.');
err.status = 401;
return res.json({err});
} else {
require('bcrypt').compare(req.body.password, user.password, function(err, result) {
if(result === true) {
return res.json({user});
} else {
return res.json({err});
}
});
}
});
}
Though sails waterline is not as powerful as direct access to any one db, it can do what you want here and much more. The docs give some good examples of what's possible.
I don't know exactly how you are passing in the username or email to your request object, but something like this should work:
authenticate: function(req, res) {
var username = req.param('username'); // or however you get this
var email = req.param('email'); // or however you get this
Users.findOne({
or: [{username: username}, {email: email}]
}).exec(function(err, user) {
// handle the error, or make use of found user...
});
}
You can also handle the case where user hands you an input that could be either a username or email...
var identifier = req.param('identifier'); // could be a username or an email
And then modify your or array to:
or: [{username: identifer}, {email: identifier}]
if you use the action 2 style, you can do
```
var identifier = inputs.identifier;
var userRecord = await User.findOne({
or : [{username: identifier}, {email: identifier}]
});

How do I send a Mongo Document back to the front end?

//router
app.get('/retrieve_report', function(req, res) {
var retrieved = retrieve_report(req, res);
res.render('retrieve_report.ejs', {
'report' : retrieved
});
});
//Load up the report model
var Report = require('../models/report');
console.log('Report ' + Report.schema);
//expose this function to our app using module.exports
//query
module.exports = function(req, res) {
//console.log('param ' + res.send);
var query = Report.findById(req.param('id'), function(err, doc) {
if(err) {
throw err;
}
else {
console.log('doc ' + JSON.stringify(doc));
res.send(doc);
}
});
}
//app.js
var retrieve_report = require('./config/retrieve_report');//which is the above code
I want to return the document to the router so that I can put its information into my view. I tried "res.json(doc), but that gave me the error, "throw new Error('Can\'t set headers after they are sent.');" Everyone says to use a callback function, but aren't I using a callback function here?
As your error says:
but that gave me the error, "throw new Error('Can\'t set headers after they are sent.');"
Means you are trying to send data the twice.
Sample code:
app.get('/retrieve_report', function(req, res) {
var query = Report.findById(req.param('id'), function(err, doc) {
if(err) {
throw err;
}
else {
console.log('doc ' + JSON.stringify(doc));
res.send(doc);
}
});
This should work..

Node Express Trouble returning object to view from query

I'm trying to:
Pass user's ID to a model query, that should return the user record from mongo.
Render this user object to my view so I can use its fields.
I'm not quite sure what's going wrong - the query function finds the correct user and I can console.dir to see all the fields. When I try to return it to my view with res.render I get nothing:
Here's my route:
app.get('/account', function(req, res) {
res.render('account', {title: 'Your Account', username: req.user.name, user:account.check(req.user.id) });
});
And my query function:
exports.check = function(userId) {
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
if(err) throw err;
var collection = db.collection('test');
collection.findOne({userId : userId}, function(err, user) {
if (err) throw err;
console.log("account.check logging found user to console: ");
console.dir(user);
return user;
});
});
}
Again, this shows the proper entry
Finally my view:
<h1>Account Page</h1>
<hr>
<p>Why, Hello, there <b> {{username}} </b> </p><br/>
<p>You came from {{user.provider}}</p>
<p>{{user.lastConnected}}</p>
Go Home ~ Log Out
Any held would be most appreciated!
The MongoDB findOne function is asynchronous (it takes a callback as an argument). This means that your check function also needs to be asynchronous and take a callback as an argument (or return a promise).
Then you should call res.render() inside the callback you pass to query on success.
app.get('/account', function(req, res) {
account.check(req.user.id, function(error, user) {
if (error) {
// do something smart like res.status(500).end()
return;
}
res.render('account', {title: 'Your Account', username: req.user.name, user:user });
}
});
And the check function should be something like:
exports.check = function(userId, callback) {
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
if(err) {
callback(err);
}
var collection = db.collection('test');
collection.findOne({userId : userId}, function(err, user) {
if(err) {
callback(err);
}
console.log("account.check logging found user to console: ");
console.dir(user);
callback(null, user);
});
});
}
Of course if you don't need to do any additional processing, you can just pass your the callback argument as the callback to collection.findOne(). I just kept it this way because it was closer to what you were doing initially.