I am using Mongodb and the findOne feature:
User.findOne({$or: [{email: req.body.email}, {mobile: req.body.mobile}]}
However the issue I am facing is with req.body.email and req.body.mobile - in certain cases can be empty.
I have initially solved this using:
var toSearchSmartString = {$or: [{email: req.body.email}, {mobile: req.body.mobile}]};
if (req.body.email.length == 0) {
toSearchSmartString = {mobile: req.body.mobile};
} else if (req.body.mobile.length == 0) {
toSearchSmartString = {email: req.body.email};
}
then in the findOne, simply using:
User.findOne(toSearchSmartString);
So I want to check is this 'safe' todo? The reason I ask is this safe is because if I don't set the default value for toSearchSmartString and instead set it at the end of the if block (in a else) I get 'undefined' for the string.
I'm concerned that the findOne method may use the default toSearchSmartString before the if else condition has been checked? Am I right to concerned about this?
Alternatively is there some Mongodb function I can use to solve?
UPDATE:
So after comments in answer below - having issues with the code:
I solved it by moving the var declaration above to where its used.
var contWithRegCallback = function(err, user) {
console.log(user);
}
if (req.body.email.length == 0) {
User.findOne({mobile: req.body.mobile}, contWithRegCallback);
} else if (req.body.mobile.length == 0) {
User.findOne({email: req.body.email}, contWithRegCallback);
} else {
User.findOne({$or: [{email: req.body.email}, {mobile: req.body.mobile}]}, contWithRegCallback);
}
Namely the user in the callback function keeps returning undefined. Shouldnt it be the contents fro the fineOne?
Why don't you just use conditional check?
This simple snippet should work as expected, notice, you want to filter by email or mobile.
var callback = function(err, result){
if(err) {
return res.status(400).send({message: 'Server error:' + JSON.stringify(err)});
} else {
res.json(result);
}
}
if (req.body.email){
User.findOne({email: req.body.email}, callback);
} else if (req.body.mobile) {
User.findOne({mobile: req.body.mobile}, callback);
} else {
return res.status(400).send({message: "Email or Mobile required"});
}
Related
I'am setting up a login page for my app. I want to send a file after verifing if the login page is provided with proper username and password.
I have a handler for a post request which checks if the user entered correct username and password.
app.post('/login',function(req,res){
var data="";
var flag_isthere=0,wrongpass=0;
console.log('login-done');
req.setEncoding('UTF-8')
req.on('data',function(chunk){
data+=chunk;
});
req.on('end',function()
{
MongoClient.connect("mongodb://localhost:27017/userdetails",{useNewUrlParser: true ,useUnifiedTopology: true },function(err,db)
{
if(err) throw err;
var q = JSON.parse(data)
const mydb=db.db('userdetails')
var c=mydb.collection('signup').find().toArray(
function(err,res)
{
for(var i=0;i<res.length;i++)
if( (res[i].email==q['email']) ) //check if the account exists
{
flag_isthere=1;
if( (res[i].pass != q['pass'] ) )
wrongpass=1;
break;
}
if(flag_isthere==0)
{
console.log(q['email'], ' is not registered')
}
else
{
console.log('Already exists!!!');
}
if( wrongpass==1)
{
console.log('password entered is wrong')
}
if(flag_isthere==1 && wrongpass==0)
{
console.log('Congratulations,username and password is correct');
res.send( { login:'OK', error:'' } ); //this statement is giving an error in node JS part
}
});//var c
})//mongoclient.connect
})//req.on
res.send({ login:'OK', error:'' }); //this works properly in node JS
console.log(flag_isthere , wrongpass ) //but here the flag_isthere==0 and wrongpass==0 , so it won't get validated
});
It gives the error as
TypeError: res.send is not a function
at E:\ITT_project_shiva\loginserver_new.js:112:25
at result (E:\ITT_project_shiva\node_modules\mongodb\lib\operations\execute_operation.js:75:17)
at executeCallback (E:\ITT_project_shiva\node_modules\mongodb\lib\operations\execute_operation.js:68:9)
at handleCallback (E:\ITT_project_shiva\node_modules\mongodb\lib\utils.js:129:55)
at cursor.close (E:\ITT_project_shiva\node_modules\mongodb\lib\operations\to_array.js:36:13)
at handleCallback (E:\ITT_project_shiva\node_modules\mongodb\lib\utils.js:129:55)
at completeClose (E:\ITT_project_shiva\node_modules\mongodb\lib\cursor.js:859:16)
at Cursor.close (E:\ITT_project_shiva\node_modules\mongodb\lib\cursor.js:878:12)
at cursor._next (E:\ITT_project_shiva\node_modules\mongodb\lib\operations\to_array.js:35:25)
at handleCallback (E:\ITT_project_shiva\node_modules\mongodb\lib\core\cursor.js:32:5)
[nodemon] app crashed - waiting for file changes before starting...
How do I send the response to the user after proper validation?
It's not that you're doing it from the callback that's the problem. There are two different problems:
You're shadowing res by redefining it in the callback's parameter list
(Once you fix that) You're calling res.send twice:
Once at the end of your posthandler
Once within the callback
send implicitly completes the response, so you can only call it once.
In your case, you want to call it from within your callback, once you've determined that none of the records matches.
See *** comments for a rough guideline (but keep reading):
app.post('/login', function(req, res) {
var data = "";
var flag_isthere = 0,
wrongpass = 0;
console.log('login-done');
req.setEncoding('UTF-8')
req.on('data', function(chunk) {
data += chunk;
});
req.on('end', function() {
MongoClient.connect("mongodb://localhost:27017/userdetails", {
useNewUrlParser: true,
useUnifiedTopology: true
}, function(err, db) {
if (err) throw err;
var q = JSON.parse(data)
const mydb = db.db('userdetails')
var c = mydb.collection('signup').find().toArray(
function(err, array) { // *** Renamed `res` to `array
for (var i = 0; i < array.length; i++)
if ((array[i].email == q['email'])) //check if the account exists
{
flag_isthere = 1;
if ((array[i].pass != q['pass']))
wrongpass = 1;
break;
}
if (flag_isthere == 0) {
console.log(q['email'], ' is not registered')
} else {
console.log('Already exists!!!');
}
// *** Handle result here
if (flag_isthere == 1 && wrongpass == 0) {
console.log('Congratulations,username and password is correct');
res.send({ login: 'OK', error: '' }); //this statement is giving an error in node JS part
} else if (wrongpass == 1) {
console.log('password entered is wrong')
// *** res.send(/*...*/)
} else {
// Handle the issue that there was no match
// *** res.send(/*...*/)
}
}
); //var c
}) //mongoclient.connect
}) //req.on
// *** Don't try to send a response here, you don't know the answer yet
});
but, it seems like you should be able to find just the one user (via findOne? I don't do MongoDB), rather than finding all of them and then looping through the resulting array.
See also the answers to these two questions, which may help you with asynchronous code issues:
How do I return the response from an asynchronous call?
Why is my variable unaltered after I modify it inside of a function?
A couple of other notes:
I strongly recommend using booleans for flags, not numbers.
NEVER store actual passwords in your database!! Store a strong hash, and then compare hashes.
You might find async/await syntax more convenient to work with. I think recent MongoDB clients support promises (which you need for async/await).
I am using Google Cloud function to validate my OTP Authentication, and also using Firebase database to save code in the database.
My problem is, even when the If statements condition are satisfied, it always executes else statement. I am comparing code and codeValid from firebase database with the user input. Thus, my user input is satisfied with code and codevalid is also satisfied, but it always moves to else statement. I dont know why.
Here is my code
const admin = require('firebase-admin');
module.exports = function(req, res) {
if(!req.body.phone || !req.body.code) {
return res.status(422).send({error: 'Phone and Code Must be
Provided'});
}
const phone = String(req.body.phone).replace(/[^\d]/g, '');
const code = parseInt(req.body.code);
return admin.auth().getUser(phone)
.then(() => {
const ref = admin.database().ref('users/'+ phone);
return ref.on('value', snapshot => {
ref.off();
const user = snapshot.val();
if (user.code === code && user.codeValid === true) {
ref.update({ codeValid: false });
admin.auth().createCustomToken(phone)
.then(token => res.send({ token: token }))
.catch((err)=> res.status(422).send({ error:err }));
}
else {
return res.status(422).send({ error: 'Code Not Valid' });
}
});
})
.catch((err)=> res.status(422).send({ error:err }) )
}
So, I always get "code not valid" what ever the input i give. I cross checked all the values with firebase database also, everything matches. But couldn't find why its happening.
Add this above your if condition and check whether your statements are really true. I think it's possible that your datatypes are different for example for user.code and code. So you should also test it with == or with parsing your values.
// values and datatypes are equal
if (user.code === code) {
console.log('user.code === code');
}
// values and datatypes are equal
if (user.codeValid === true) {
console.log('user.codeValid === codeValid');
}
// values are equal
if (user.code == code) {
console.log('user.code == code');
}
// values are equal
if (user.codeValid == true) {
console.log('user.codeValid == codeValid');
}
For more information about the difference of == and === look at this answer:
Difference between == and === in JavaScript
I have been on this for a good few hours.
I have the below function which reads from a table in my postgres db. It works as expected if there is stored strings in a column.
I can't get the 'else if' statement to work when there is no string in a field. To test this out I have a completely empty column under brand_code and its still executing the 'else' statement.
Now, I know why. There are 3 rows in the table. When I change the else if to === 3, it works as I'd like.
What code do I need to make the 'else if' statement work if the field is empty? (I plan to expand the SELECT statement later).
readCodes: function(callback) {
var pool = new pg.Pool(config.PG_CONFIG);
pool.connect(function(err, client, done) {
if (err) {
return console.error('Error acquiring client', err.stack);
}
client
.query(
'SELECT brand_code FROM public.voucher_codes',
function(err, result) {
if (err) {
console.log(err);
callback('');
} else if (result.rows.length === 0 ) {
console.log(result);
callback('');
} else {
let codes = [];
for (let i = 0; i < result.rows.length; i++) {
codes.push(result.rows[i]['brand_code']);
}
callback(codes);
};
});
});
}
}
Really struggled with this all day so any help is appreciated.
I am still learning. Prior to last week, I have never coded so apologies if this is amateur hour.
The problem here is that you are checking if it has returned rows or not, what you need instead is to check in each row if the field is empty
I suggest using underscore for iterating over each row:
_.each(result.rows,function(element, index){
if(element['brand_code'].length != 0){
codes.push(element['brand_code'])
}else{
console.log('empty field # results['+index+']')
}
})
CODE :
readCodes: function(callback) {
var pool = new pg.Pool(config.PG_CONFIG);
pool.connect(function(err, client, done) {
if(err){return console.error('Error acquiring client',err.stack);}
client.query(
'SELECT brand_code FROM public.voucher_codes',
function(err, result) {
if (err){console.log('[!] Error:',err); callback('');}
else if(result.rows.length == 0 ){
console.log('[!] Error:','No rows returned!');
callback('');
} else {
let codes = [];
_.each(result.rows,function(element, index){
console.log(element , index)
if(element['brand_code'].length != 0){
codes.push(element['brand_code'])
}else{
console.log('empty field # results['+index+']')
}
})
callback(codes);
}
});
});
}
router.post('/checkuser', function(req, res) {
var db = req.db;
var userEmail = req.body.useremail;
var password = req.body.password;
var collection = db.get('usercollection');
collection.find( { "email": userEmail }, function (err, doc) {
if (err || !doc) {
res.redirect("login");
} else {
res.redirect("userlist");
}
});
});
This code is supposed to check the login credentials in a MongoDB and return false if the values are not matched.
But it always redirects to the userlist.jade file. Can someone please explain why?
Your code always redirects to the userlist.jade file because of the current logic in the callback function: since find() method returns a cursor, the if statement checks whether there is an error OR there is no returned cursor with the matched document, thus the variable doc is a cursor which is always returned whether there is a match or not. Use the findOne() method instead:
collection.findOne({"email": userEmail}, function(err, user) {
if( !err && user && user.password === password ) {
res.redirect("userlist");
}
else { res.redirect("login"); }
});
The code is for handling the POST request within Expressjs and mongodb
router.post('/', function(req, res){
var data = req.body;
Tag.find({name: data.name}).limit(1).exec( function(err, result){
if(err){
} else {
if(result.length > 0){ // Already exist a tag with same name
res.status(400).end('Already exist!');
} else { // Save the new Tag to database
var tag = new Tag();
tag.name = data.name;
tag.lastModifier = req.user?req.user.username:"system";
tag.lastModified = Date.now();
tag.save(function(err){
if(err){
res.status(400).json({
message: "insert tag error"
});
} else {
Tag.findOne(tag, function(err, result){
if(err){
res.status(400).json({
message: "some error.."
});
} else {
//res.status(400).end('same tag name');
res.status(201).json({
_id: result._id
});
}
});
}
});
}
}
});
});
The stairs in the last 9 lines are terrible....please teach me how could I make this mess clearer?
You can use named functions instead of some of the function expressions:
router.post('/', function(req, res){
var data = req.body;
Tag.find({name: data.name}).limit(1).exec( function(err, result){
if(err){
} else {
if(result.length > 0){ // Already exist a tag with same name
res.status(400).end('Already exist!');
} else { // Save the new Tag to database
var tag = new Tag();
tag.name = data.name;
tag.lastModifier = req.user?req.user.username:"system";
tag.lastModified = Date.now();
tag.save(save(err));
}
}
});
});
function save(err){
if(err){
res.status(400).json({
message: "insert tag error"
});
} else {
Tag.findOne(tag, handleResult(err, result));
}
}
function handleResult(err, result){
if(err){
res.status(400).json({
message: "some error.."
});
} else {
//res.status(400).end('same tag name');
res.status(201).json({
_id: result._id
});
}
}
(You can surely name them a little more appropriate for the situation, but it shows the principle.)
router.post('/', function(req, res){
var data = req.body;
Tag.find({name: data.name}).limit(1).exec(cbExec);
});
function cbExec(err, result){
if(err){
} else {
if(result.length > 0){ // Already exist a tag with same name
res.status(400).end('Already exist!');
} else { // Save the new Tag to database
var tag = new Tag();
tag.name = data.name;
tag.lastModifier = req.user?req.user.username:"system";
tag.lastModified = Date.now();
tag.save(cbSave);
}
}
}
function cbSave(err){
if(err){
res.status(400).json({message: "insert tag error"});
} else {
Tag.findOne(tag, cbTag);
}
}
function cbTag(err, result){
if(err){
res.status(400).json({message: "some error.."});
} else {
//res.status(400).end('same tag name');
res.status(201).json({_id: result._id});
}
}
I really recommend you to try promises. There are many implementations available for JavaScript and Node.js.
A promise basically encapsulates an asynchronous operation into a value, which allows you to get rid of these horrible nested callbacks. They also allow you to chain asynchronous operations more easily.
What you're forced to do in your callback-based code is to check errors at every level, which can get rather tedious if your error handling could be at one place. Promises will propagate the error, allowing easy handling in one place.
Here are some references:
http://www.html5rocks.com/en/tutorials/es6/promises/
https://developer.mozilla.org/cs/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://www.promisejs.org/
It might take a little while to adjust to using them, but trust me, it is absolutely worth it.
You can separate the cod a little bi more. Instead of creating lambda functions create normal ones. You can get rid of one pair of braces in 4th line
if(err){
} else {
using if(!err)