mongolab request returning empty find results - javascript

I have a website that is accessing a local node.js server (that accesses a mongolab database), but when I use a front-end function to request a user JSON object, the mongo database returns nothing. (JSON.parse() finds an unexpected end of data at line 1 col 1)
Here is the front-end function that requests the user data by email and password:
function requestUser(email, password) {
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "http://localhost:8888/getUser/" + email + "/" + password, true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
user = JSON.parse(xmlhttp.responseText);
console.log(user);
}
}
xmlhttp.send();
}
Here is the node.js express server (back-end):
var http = require("http"),
mongojs = require("mongojs"),
express = require('express'),
cors = require('cors'),
fs = require("fs"),
url = require("url");
app = express();
app.use(cors());
var uri = "mongodb://<dbuser>:<dbpassword>#ds036698.mongolab.com:36698/alirodatabase";
var db = mongojs(uri, ["Papers", "Users"]);
app.get('/getUser/:email/:passwd', function(req, res, next) {
var users = db.Users.find({"email": req.params.email,
"password": req.params.passwd});
user = users.toArray[0];
res.json(user);
});
app.listen(8888, function() {
console.log('CORS-enabled web server listening on port 8888');
});
EDIT 1:
app.get('/getUser/:email/:passwd', function(req, res, next) {
var user = db.Users.findOne({
"email": req.params.email,
"password": req.params.passwd
}, function(err, doc) {
if (err) {
res.json({error: 'error retrieving the JSON user' });
}
else {
res.json(doc);
}
});
});
I added async functionality to the nodeserver, but now I am receiving the err: "error retrieving the JSON user". Is this a problem that could be solved by hosting my own database and not using mongolab?

You need to look at the docs for mongojs (https://github.com/mafintosh/mongojs). You're not using callbacks at all. The functions don't return values because it's Javascript/Node.js where things like to be async. So you have to use callbacks to handle the results. The idea is "find these documents" and then some time later when it actually gets the documents "do something with the documents".
app.get('/getUser/:email/:passwd', function(req, res, next) {
var users = db.Users.find({
"email": req.params.email,
"password": req.params.passwd
}, function(err, docs) {
if (err) {
//handle the error
res.json({error: ':(' });
}
else {
docs.toArray(function(err, users) {
if (err) {
//handle the error
res.json({error: ':(' });
}
else {
res.json(users[0]);
}
});
}
});
});
Lastly, I'd recommend using findOne rather than find. Then you won't need to use toArray to get a single document because it's returned as a single document in the first callback.

Related

ajax callback window.location Request Aborted

I am currently trying to create a client-side reroute for users that are invalid. The server validates if the user has access to the current page and if not it returns {data: 'invalid'} in the success callback of the ajax call I check this value with the following:
if (data.status === 'invalid') {
window.location.href = domain + '/login';
return false;
}
This works sometimes but other times I receive the following browser alert message:
RequestAbortedError: Request aborted
I have attempted to swap out window.location.href with window.location.replace() and top.location.href but neither resolved the issue. I can see that the server is processing the information correctly and returning {data: 'invalid'} but as soon as it tries to run the line window.location.href I receive this error. I have an image below if it helps.
When "OK" is clicked the page does redirect to the appropriate page. The end result is happening as expected but I cannot resolve the error.
UPDATE INCLUDING SERVER SIDE CODE
function authentication (req, res, next) {
console.log('entered');
if (typeof req.rsaConPortal.email !== 'undefined') { // Check if session exists
console.log('passed 1');
User.findOne({ "user.email": req.rsaConPortal.email, "user.status”: req.resConPortal.status}, function (err, user) {
if (!user) {
console.log('failed 2');
req.rsaConPortal.reset();
res.send({status: 'invalid'});
} else {
console.log('passed 2');
req.rsaConPortal.email = user.user.email;
req.rsaConPortal.id = user._id;
req.rsaConPortal.status = user.user.status;
next();
}
});
} else {
console.log('failed 1');
res.send({status: 'invalid'});
}
}
app.get('/api/savedApp/', authentication, function(req, res) {
if (req.rsaConPortal.status !== 'registered') {
res.send({status: 'invalid'});
} else {
User.find({ "_id": req.rsaConPortal.id }, {
profile: 1, documents: 1 }, function(err, user) {
if (err) throw err;
res.send(user);
});
}
});
Is there a better way to authenticate my users? I am using Mozilla's Client-Sessions npm package
The logs on the server are logging "Passed1" and "Passed2". It is sending the client "Invalid" based off the status inside the get call.
Based on reading further about express and a few comments I have received on this question I have decided to re-think my approach and look for a better alternative which I am happy to say I have found in express.Router. I was able to create an authentication function to determine if the user is authorized and handle the business logic of whether to let the user pass or send them back to the login. Then I created a route for each page that I have that takes the business logic a step further based on the users status and either lets them pass or sends them back to login.
Thanks to everyone who looked into this and provided comments.
var router = express.Router();
app.use(router);
var authenticate = function(req, res, next) {
if (req.rsaConPortal !== undefined) {
if (req.rsaConPortal.email !== undefined) { // Check if session exists
// lookup the user in the DB by pulling their email from the session
User.findOne({ "user.email": req.rsaConPortal.email, "user.password": req.rsaConPortal.passport }, function (err, user) {
if (!user) {
// if the user isn't found in the DB, reset the session info and
// redirect the user to the login page
req.rsaConPortal.reset();
req.rsaConPortal.email = '';
req.rsaConPortal.passport = '';
req.rsaConPortal.id = '';
req.rsaConPortal.status = '';
res.redirect('../login');
} else {
req.rsaConPortal.email = user.user.email;
req.rsaConPortal.passport = user.user.password;
req.rsaConPortal.id = user._id + '';
req.rsaConPortal.status = user.user.status;
next();
}
});
} else {
res.redirect('../login');
}
} else {
res.redirect('../login');
}
};
router.get(['/','/create_warranty','/help','/marketing_assets','my_documents','profile'], authenticate, function(req, res, next) {
if (req.rsaConPortal.status !== 'approved') {
res.redirect('../login');
} else {
next();
}
});

express receiving empty request body when receiving from angular 4 app

The body of the request being sent is empty according to req.body in my express route.
My main node file is as follows -
var express = require('express');
var bluebird = require('bluebird')
const bodyParser = require('body-parser');
const cors = require('cors');
/*initializations*/
global.mongoose = require('mongoose');
mongoose.Promise = bluebird
global.app = express();
global.config = require('./config/config');
global.jwt = require('jsonwebtoken');
app.use(bodyParser.json({ type: 'application/json' }))
app.use(bodyParser.urlencoded({ extended: true }));//accept strings, arrays and any other type as values
app.disable('x-powered-by');
require('./routes/auth.routes');
//DB connection
app.listen(config.port, function(){
console.log("Express started on " +config.base_url +' in '+config.env +' environment. Press Ctrl + C to terminate');
mongoose.connect(config.db.uri, config.db.options)
.then(()=> { console.log(`Succesfully Connected to the Mongodb Database at URL : `+config.db.uri)})
.catch((error)=> { console.log(error)})
});
The auth.routes file has the signup route and this is where the req.body is empty but it does not hit the if statement that checks, but when i console.log(re.body), it gives me that - {}
app.post('/signup', function(req,res,next){
if (!req.body||req.body=={}){
return res.status(400).send("Bad Request")
}
var user = new User(req.body);
user.password = bcrypt.hashSync(req.body.password, 10);
User.create(user, function(err,new_user){
if (err) {
console.log('A Big Error');
return res.status(500).send("There was a problem registering the user.")
}
//success code
})
});
And the request from the angular 4 app is
signup(user:User):Observable<boolean>{
return this.http.post(this.signup_url,JSON.stringify(user),
{
headers: new HttpHeaders().set('Accept', "application/json;q=0.9,*/*;q=0.8").set('Content-Type', "x-www-form-encoded")
})
.map((response: Response) => {
if(response){
if(response.json() && response.json().token&&response.json().user&&response.json().expires){
this.setSession(response.json());
return true;
}
else{
return false;
}
}
else{
return false;
}
});
}
I am certain the Angular 4 app is sending the right data to the server and that its not empty - checked chromes network request body.
I have tried the following links but none worked.
Express app empty request body with custom content type headers
Express receiving empty object
Node.js: Receiving empty body when submitting form.
Also tried with postman and the result is the same - which means the problem is from the express server and not the client side.
There is no need to stringify the posted data, the body-parser middleware will be responsible for parsing the data into object:
return this.http.post(this.signup_url, user, { ... }).map( ... );
One other thing, In the post handler, you might want to use .save() method instead of .create() because you already create a model instance, Remember that the .save() method is available on the model instance, while the .create() is called directly from the Model and takes the object as a first parameter
Example with .save() method:
app.post('/signup', function(req,res,next) {
if (!req.body){
return res.status(400).send("Bad Request");
}
var user = new User(req.body);
var salt = bcrypt.genSaltSync(saltRounds);
user.password = bcrypt.hashSync(req.body.password, salt);
user.save(function( err ) {
if (err) {
console.log('A Big Error');
return res.status(500).send("There was a problem registering the user.");
}
//success code
res.json({ success: true });
})
});
Example with .create() method:
router.post('/signup', function(req,res,next){
if (!req.body){
return res.status(400).send("Bad Request")
}
var salt = bcrypt.genSaltSync(saltRounds);
req.body.password = bcrypt.hashSync(req.body.password, salt);
User.create ( req.body, function( err, new_user) {
if (err) {
console.log('A Big Error');
return res.status(500).send("There was a problem registering the user.")
}
//success code
res.json({ success: true });
});
});

My code is deleting the file and removing it from the database records, however, I get an error in the console

I'm trying to add a delete image functionality to my website and even though my code deletes the file from the images folder and removes the image record from my database, I get an error in the console and I don't get redirected to my home page. The error is :
DeprecationWarning: Calling an asynchronous function without callback is deprecated.
And my code:
var express = require('express');
var router = express.Router();
var db = require('../helpers/db');
var fs = require('fs');
router.post('/', function(req, res, next) {
if (req.method == 'POST') {
var id = req.body.id;
var path = req.body.path;
var author = req.body.author;
var completePath = 'public/images/uploads/' + path;
db.query('DELETE FROM image WHERE id = ?', [id], function(error, results, fields) {
if (error) throw error;
if (fs.unlink(completePath)) {
console.log('Successful');
res.redirect('/');
} else {
console.log('Unsuccessful');
}
})
}
});
module.exports = router;
My console logs Unsuccessful and it doesn't redirect me to res.redirect('/');
fs.unlink is an asynchronous function that takes a callback on success. You should use it like this:
db.query('DELETE FROM image WHERE id = ?', [id], function(error, results, fields) {
if (error) throw error;
fs.unlink(completePath,function(err) {
if(err) {
console.log('unsuccessful');
return;
}
console.log('successful');
res.redirect('/');
});
})

Nodejs express4 - undefined session

my problem is that my session is undefined as in new layers as even after "if" where the session value was set.
/*******************************************/
/**/ var express = require('express'),
/**/ cookieParser = require('cookie-parser'),
/**/ session = require('express-session'),
/**/ bodyParser = require('body-parser'),
/**/ ejs = require('ejs'),
/**/ mysql = require('mysql'),
/**/ md5 = require('md5');
/*******************************************/
var app = express();
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'samurai'
});
connection.connect(function(error) {
if(error) {
console.log("There is a problem with connection to the database.");
return;
}
console.log("Connected with a database.");
});
app.use(cookieParser());
app.use(session({
secret: 'test session',
resave: false,
saveUninitialized: true
}));
var sess;
Here my session is undefined (first I go to the '/sign' address):
app.get('/', function(req, res) {
sess = req.session;
console.log("sesja = "+sess.login); <--------------- undefined
if(sess.login) {
res.render('indexo');
} else {
res.render('index');
}
});
app.post('/sign', function(req, res, next) {
sess=req.session;
var query = 'SELECT * FROM ?? where ??=? AND ??=?';
var table = ["users", "name", req.body.login, "password", md5(req.body.password)];
query = mysql.format(query, table);
connection.query(query, function(err, rows) {
if(err) {
console.log(err);
return;
} else if(rows.length > 0) {
console.log("You have been sucessfully logged in.");
sess.login = req.body.login;
console.log(sess.login); <------------ works fine
} else {
console.log("The name or password is incorrect.");
}
});
console.log(sess.login); <---------------- here again undefined
res.end();
});
The problem is only in sessions case because if I create other global variable next to "var sess;" (for example var test;) and set for the variable a value in the "if" in '/sign" layer, then the "test" would be visible in the other layers and after that "if".
The final question: Why the session.login is invisible after the "if" and in other layer? How to set it properly? Have you some tips for me with sessions creating?
Thank you guys for your time and help.
Setting global variables from an http request is an evil thing to do and is fraught with problems. First off, your server can have multiple requests in flight at the same time from different users. Using globals from requests like this means that different requests will "stomp" on each others globals and all sorts of chaos and bugs will ensue.
Stop using globals at all for session information. If you need to communicate session info to other functions, then pass it to them as function arguments.
And, secondly you MUST understand how async operations work in node.js to have any chance of programming successfully in node.js. You are making several mistakes with your asynchronous programming and that's one main reason why variables aren't set where you think they should be.
In this code:
app.post('/sign', function(req, res, next) {
sess=req.session;
var query = 'SELECT * FROM ?? where ??=? AND ??=?';
var table = ["users", "name", req.body.login, "password", md5(req.body.password)];
query = mysql.format(query, table);
connection.query(query, function(err, rows) {
if(err) {
console.log(err);
return;
} else if(rows.length > 0) {
console.log("You have been sucessfully logged in.");
sess.login = req.body.login;
console.log(sess.login); <------------ works fine
} else {
console.log("The name or password is incorrect.");
}
});
// this is executed BEFORE the connection.query() callback is called
console.log(sess.login); <---------------- here again undefined
res.end();
});
connection.query() is asynchronous. T'hat means that it calls its callback sometime in the future. Thus your console.log(sess.login); at the end of your request is happening BEFORE the callback has ever been called.
You aren't specific about exactly what you want to happen in all the cases in your query, but here's an outline for how the code could work:
app.post('/sign', function(req, res, next) {
var query = 'SELECT * FROM ?? where ??=? AND ??=?';
var table = ["users", "name", req.body.login, "password", md5(req.body.password)];
query = mysql.format(query, table);
connection.query(query, function(err, rows) {
if(err) {
console.log(err);
res.end("Query error");
} else if(rows.length > 0) {
res.end("Logged in successfully");
} else {
res.end("The name or password is incorrect.");
}
});
});
You may find this general answer on asynchronous responses useful: How do I return the response from an asynchronous call?

Trying to inject the session into request body within asynchronous function in Nodejs

I am trying to inject a session value into the request so i can use it on different situation on my app. What i am doing is calling a function by giving the id to search for a user into database and return me the name of that specific user. The issue i am facing is when i try to declare the session, it looks like is not working or the callback is not letting this new value out.
Let me show you my code example for an better idea:
The middleware
var express = require('express');
var session = require('express-session');
var router = express.Router();
var userSession = require('../../helpers/user/userSession');
router.use(function(req, res, next){
if (req.method == "GET") {
if (!req.user) {
req.session.username = '';
}else{
var sess = userSession.findUser(req.user, function(err, user){
if (user) {
console.log(user); //It contains the value i need
req.session.username = user; // Supposed to inject the user value to the username session variable.
};
console.log(req.session.username); //it works until here, out of this function not anymore.
});
console.log(req.session.username); //the req.session.username is empty now
};
return next();
}else{
return next();
}
});
Check if user exist
var mongoose = require('mongoose');
var User = mongoose.model('database')
module.exports = {
findUser: function(user, callback){
User.findOne({ 'unq_id' : user }, function(err, user){
if (err) {
console.log('Error: ' +err);
return callback(err, false);
};
if (user) {
//console.log(user);
return callback(null, user.user_collection.firstname);
}else{
return callback(err, false);
};
});
}
}
One idea is to give to that sess variable the value of user, but it appears very difficult since is asynchronous call. I am sure some of might have run into this issue.
How can i get around this? any suggestion will be much appreciated.
How about this?
router.use(function(req, res, next){
if (req.method == "GET") {
if (!req.user) {
req.session.username = '';
next();
} else {
userSession.findUser(req.user, function(err, user){
if (user) {
req.session.username = user;
};
next();
});
}
} else {
next();
}
});
That way it won't go to the next middleware until after the username has been retrieved.

Categories