Passing a Mongo connection to JQuery code via socket.io? - javascript

I am trying to create a global MongoDB connection in my node.js web app like this:
var MongoClient = require('mongodb').MongoClient;
var mconn = null;
MongoClient.connect('mongodb://myHost:27017/users', function(err, udb) { //open connection to MongoDB db
if (!err){
mconn = udb;
}
else
console.error("Could not connect to sql: ", err);
});
Then, I want to pass this connection via a `socket.emit' event like this:
io.sockets.on('connection', function(socket) {
socket.on('updates', function(PEMSID){
gps_helper.get_gps(PEMSID, conn, function(data){ //make initial query to GPS table for marker coordinates
socket.emit('message', {message: data, mongoConnection: mconn});
});
intervalID = setInterval(function(){
gps_helper.get_gps(PEMSID, conn, function(data){ //query GPS table for marker coordinates on an interval
socket.emit('message', {message: data, mongoConnection: mconn});
});
}, 30000);
});
This doesn't appear to be working, the 'mongoConnection' value is empty on the other side. Is it possible to send it this way?

That's not possible: you can't generally serialize, and therefore transmit, opaque data types like network connections or file handles.
Consider the security risks if it were possible: malicious clients would have complete access to your database.
You're going to have to make some sort of interface where your client code is sending certain messages to the server, the server performs the appropriate database actions and sends back the results (again, make sure you don't make this interface too general so that malicious client code gets to execute random queries against your database).

Related

How do I maintain multi tenant data base connections nodejs

Let's say I have a service app.js. Whenever a new client connects to the service , we will check if a mongodb connection is already establish for this client or not.
If it is not available then we will fetch the server ip, dbname ,collection name from a configuration file, connect to the db,and reply to the user.
Note: we can add a new client and corresponding info to Client Info at any time. (dynamically)
Client Info ClientId: ServerIp : Database Name :Collection Name I have tried to store mongo object in array so I can reuse them object based on database name from user's session data. But I keep running into circular json error. How do I store multi tenant database connections?
async.eachSeries(conf.clientDbs.clientsList, function(clientDetails,callback){
console.log(clientDetails);
mongodb.MongoClient.connect(conf.clientDbs.connection+clientDetails.dbName, function (err, database) {
if (err) {
console.log(err);
process.exit(1);
}
// Save database object from the callback for reuse.
var tempdbobj = {};
tempdbobj["obj"] = database
allDbs[clientDetails.team_id] = tempdbobj;
console.log("Database connection ready for "+clientDetails.team_id);
allDbs[clientDetails.team_id].obj.collection('collection_name').find({"ref_id":"111"}, function(dberr, testDoc){
if (dberr) {
console.log(dberr);
callback();
}
else {
console.log(testDoc);
callback();
}
});
});
});

Socket.io - Cant stop passing all data to all clients

I am having a issue where I am pulling data from a DB via node mysql & Express and passing it via socket.io.... but there's an issue am running into.
All users are updating with the same data rather than unique data per user.
For example:
If user A has just logged in he can see all his account details. But when user B logs in right after he can then see all his details....but it then updates user A details to show user B details as well.
I am trying to ensure user A can can only see his own and same for user B.
I have tried numerous things to stop this happening via JQuery but cant seem to find a resolution.
Below I have trimmed down a the code to a basic example:
HTML
<span id="id-val">User A</span>
<span id="user-val"></span>
Server side
server = http.createServer(app),
io = require('socket.io').listen(server);
function SQLuserData(userval) {
connection.getConnection(function (err, connection) {
connection.query('SELECT val FROM test WHERE name= ?;',
[userval],
function (err, rows) {
var accountval = rows[0]['val'];
if (accountval) {
console.log("Val : " + accountval);
UserVal(accountval);
} else {
console.log("Error | Val: " + err);
}
});
connection.release();
});
}
//Socket.io connection socket
io.sockets.on('connection', function (socket) {
socket.on('sqluser', function (userval) {
SQLuserData(userval);
});
});
//Pass val client side.
function UserVal(accountval) {
io.sockets.emit("valsocket", accountval);
}
Client side
var socket = io.connect();
//Used to grab information for that user from serverside.
$(document).ready(function () {
var userval = $('#id-val').text();
socket.emit('sqluser', userval);
});
//Grabs user value being passed from serverside and updates HTML.
socket.on("valsocket", function (accountval) {
$("#user_val").val(accountval);
});
Does anyone have any advice or potential solutions?
you need to grab and store the socket.id for each connected user
var users = {};
//Socket.io connection socket
io.sockets.on('connection', function (socket) {
socket.on('sqluser', function (userval) {
// 'userval' must be unique for each user
users[userval] = socket.id;
SQLuserData(userval);
});
});
and then use the same id to emit data ti single socket
//Pass val client side.
function UserVal(accountval, userval) {
io.sockets.socket(users[userval]).emit("valsocket", accountval);
}
for socket.io version 1.0 and above
io.to(users[userval]).emit("valsocket", accountval);
I think you want to avoid emitting the account data to all connected users, which is what Socket.IO's emit method does. It might be better have the client send a GET request to the server and respond with the account details to the individual client.
Here are some resources if you choose to use an HTTP request over Socket.IO:
jQuery GET
Express Respond
So basically the problem with your code is that you are not distinguishing between users . Since you are sending data through socket you need to be careful to whom you are sending data.
You can use socketio-auth to create a type of authentication . And then send the data as socket.emit(event, data); Where socket is an individual object per user . You can also use a cookie based session to help you with this .

What is the best way to map websockets connection to users in the database?

I am looking to map websockets connection with users in the database and have something like this at the moment:
function connectToNotifServer(){
var conn = new WebSocket('ws://localhost:8080');
conn.onopen = function(e) {
alert("Connection established!");
conn.send(JSON.stringify({user_id: sessionStorage.getItem("user_id")}));
};
conn.onmessage = function(e) {
alert(e.data);
};
conn.onclose = function(e) {
alert("Connection closed!");
};
return conn;
}
I then have a PHP websockets server, that keeps a mapping of a connection to user_id.
However, I think there is a security flaw, as a user could simply inject any value he want in the user_id and impersonate another user. Is there a better way to keep this mapping, but without sending the user_id or sending it in another way?
Thanks
Anything you send which is 'built in' to your javascript could, at least, be copied and duplicated. The only way to verify a user's credentials to the server side websocket would be for the PCP websocket server to require something like 'username/password' - which it then checks server-side and persists for that websocket only.
i.e. you would have to ask the user to input this info.

Stay Connected to Socket.io while switching pages

I have a phonegap app in which i connect to my node.js socket like so:
var socket = io.connect('http://54.213.92.113:8080');
It works fine but when I go to a different page, the socket gets disconnected.
I could just write the same code in the javascript on the next page but that's messier than I think it needs to be - as it would open up a new connection when it could have just stayed connected in the first place.
Is there any way to stay connected to the socket even if I switch pages?
suppose you have a multi-page application then ,here you can do a trick that when your socket gets connected first time when the page loads then you can assign the session id to that particular connection like this.and then bind that connection to that session.
io.on('connection', function(socket) {
socket.on('start-session', function(data) {
console.log("============start-session event================")
console.log(data)
if (data.sessionId == null) {
var session_id = uuidv4(); //generating the sessions_id and then binding that socket to that sessions
socket.room = session_id;
socket.join(socket.room, function(res) {
console.log("joined successfully ")
socket.emit("set-session-acknowledgement", { sessionId: session_id })
} else {
socket.room = data.sessionId; //this time using the same session
socket.join(socket.room, function(res) {
console.log("joined successfully ")
socket.emit("set-session-acknowledgement", { sessionId: data.sessionId })
})
}
});
Now you had binded the socket connection to a session now you are sending an acknowledgement too at the client side also .There what you can do is that store the session id to the web browsers session storage like this
At client side code
socket.on("set-session-acknowledgement", function(data) {
sessionStorage.setItem('sessionId', data.sessionId);
})
This will store the session id in the browsers session storage.Now when the page is navigated from page1 to page2 and so on. then send that session id to the server so that you will be connected to the same session logically like this
var session_id;
// Get saved data from sessionStorage
let data = sessionStorage.getItem('sessionId');
console.log(data)
if (data == null) {
session_id = null//when we connect first time
socket.emit('start-session', { sessionId: session_id })
} else {
session_id = data//when we connect n times
socket.emit('start-session', { sessionId: session_id })
}
So basically the logic behind is that we can use same session for multiple socket connections by doing this as every time the socket will be joined to that particular room only and emit the events which you can listen on server side and vice a versa.
Only if you build it as a single page application where the actual page doesn't reload load when navigating. However it would probably be better to design your socket.io code and your server side to be resilient to frequent socket connect / disconnect. This is especially true for code written to run on a cell phone.

NodeJS email proxy

I am trying to proxy emails via NodeJS in order to do very custom processing on outgoing emails on our test server.
This is what I have:
var net = require('net');
var server = net.createServer({allowHalfOpen: true}, function(socket) {
console.log('New connection established.');
socket.setEncoding('utf8');
socket.on('data', function(data) {
console.log(data);
});
socket.on('end', function() {
console.log('Connection closing.');
});
socket.resume();
});
server.listen(25);
It does not yet process the emails, because it simply doesn't even work. I get the connection established message in console every time I send an email, but the data event never gets fired. I'm not sure if it's that the data already came before I bound the event listener, or whether I'm supposed to talk to the client first (HELO?).
I'm trying to access the email contents, basically.

Categories

Resources