Create a Backbone.Model to manage a server connection - backbone.js

So basically, I want building a test app where I need to enter server credentials in order to connect to an ElasticSearch server and I want this connection to be only available for the duration of the session.
I thought this could be managed via Backbone.Model but I'm not too sure how to handle it. Do I need a Collection as well. Do I store this in the Session or locaStorage?
Page 1
Form with protocol, host, post, username, password
Backbone.View.extend
...
events: {
'submit #connection-form' : 'connect'
},
...
connect: function(){
console.log('Connecting...');
protocol = $("#protocol").val();
host = $("#host").val();
port = $("#port").val();
user = $("#username").val();
password = $("#password").val();
App.connection = new Connection({ protocol: protocol, host: host, port: port, user: user, password: password})
self = this
App.connection.connect(function(response){
if (response.status == 200) {
App.connection.set('name', response.name)
App.router.navigate('dashboard', {trigger: true});
} else {
$(self.el).prepend(_.template(noticeTpl, { type: 'danger', message: "Could not connect to the server." }))
}
});
return false;
}
Page 2
List of indexes on my ElasticSearch server
I need to store what have been submitted on page one across all the session in order to be able to query the server at any time.

No reason you'll need a collection since you're only dealing with a single object. I also don't see any reason to use localStorage unless you're storing a lot of data, which you aren't, or want the app to be usable offline, which doesn't make any sense here.
Using sessionStorage is pretty straightforward:
sessionStorage.setItem('user', JSON.stringify(user));
var obj = JSON.parse(sessionStorage.getItem('user'));

Related

Socket.io produces random sockets for one session?

I'm trying to build a private messaging app using socket.io. My assumption was that per session there would only ever be one socket.id. If i keep track of my socket.id and console.log it, it's constantly chnaging and I dont know why.
Here a snippet if how I am saving a new user.
//Listen on the connection for incoming sockets
io.on('connection',function (socket) {
console.log(socket.id)
//Add the users to the socket session
socket.on("add-user", function(username){
oCurrentUser = {
username: username,
id: socket.id
};
console.log("socket.id for this user is", oCurrentUser.id);
aClients.push(oCurrentUser);
console.log(aClients);
socket.emit('login',oCurrentUser);
});
});
Response after I create a users:
listening on *:3000
Vws9v-Wegjx4bvBKAAAA
e611mmTgdYmFvhuMAAAB
IPE95tFpgem0eyvyAAAC
m5YLVR0PE_Qqc-AcAAAD
GXbyRVYAnHgBz4VzAAAE
When I do console.log(socket.id) is get like 5 ID's. I would of assumed it would return just one right?

Send user online/offline status to Laravel with socket.io

I have a chat app as real-time with socket.io. I want to save online/offline status on the database in Laravel back-end. For online status I don't have problem, but for offline status, I don't have any plan. My front-end framework is Angularjs 1.x and use JWT for authentication.
As matter of fact I want to save offline user status in database when user close browser of change route and emit all users from these user's status?
One possible solution would be just reacting to the socket.io server side events like the listening the socket connection and disconnect events.
This would the easiest solution, the problems would occur when your server crashes and you never receive the disconnect event. To avoid such problem, you could create interval check, which after every minute checks the opened sockets and users opened/closed in DB and updates if there changes.
Client side:
var socket = io("http://127.0.0.1:3000/", { query: "id=434354fds43" });
Server side:
var io = require('socket.io')(80);
var users = {};
io.use(function (socket, next) {
console.log('Query: ', socket.handshake.query);
var id = socket.handshake.query.id;
if (id) {
users[socket.id] = id;
return next();
}
// call next() with an Error if you need to reject the connection.
next(new Error('Authentication error'));
});
io.on('connection', function (socket) {
// New connection, get the ID from map
var id = socket.id;
socket.on('disconnect', function () {
// User left
delete users[id];
});
});

Socket.io page refresh disconnects from the room

I've been reading answers about this problem for some time now but none of the solutions seem to work for my setup.
I have a nodeJS server in conjunction with express. I use Socket.io to send notifications to individual users. (frontend is Angular)
When a user logs in, he joins a room named after his email address (unique).
io.on('connection', function (socket) {
socket.on('join', function(user) {
//list of connected users
connected_users.push({socket_id: socket.id, email: user.email});
socket.join(user.email);
});
...
The join event is broadcasted from angular when a user logs in.
This way I can send notifications like so simply by using email addresses:
io.sockets.in(to).emit('notification', {
message: msg,
source: from,
destination: to,
event: data
});
When a user manually logs out I register the following event listener:
socket.on('leave', function(user) {
//remove the user from the list
var index = findUserConnected(socket.id);
if(index != null) {
connected_users.splice(index, 1);
}
socket.leave(user.email);
});
And finally there's the disconnect handler for whenever a user logs out or refreshes the page:
socket.on('disconnect', function() {
//if the user refreshes the page, he is still in the connected users list
var email = findEmailUserConnected(socket.id);
if(email != null) {
//we make him join back his room
socket.join(email);
}
});
Technically this works. On page refresh, the user joins back his room.
The problem is only on page refresh, notifications sent using io.sockets.in(email).emit('notification', {}); are not received even though the user is in his room.
Apparently a page refresh calls socket.disconnect() which generates a new socket_id. I'm not sure if there's a way to reassign a socket_id to a room or something similar.
Ok first of all receiving a 'disconnect' event on server means that connection on that socket is going to terminate. So, there is no use for making that same socket join back in a room as you are doing right now.
socket.on('disconnect', function() {
var email = findEmailUserConnected(socket.id);
if(email != null) {
socket.join(email); // this would never work because this socket connection is not going to exist anymore.
}
});
My suggestion would be to make sure that the user always joins back into the room(email) every time a new connection is made. It can be easily done by adding sending the join event on every new connection.
In your client side code do
var socket = io();
socket.on('connect', function() { // 'connect' event is received on client on every connection start.
socket.emit('join', user); // where 'user' is your object containing email.
})
This way it ensures that whenever a new connection is established the join event is sent to server and the 'socket.on('join',...)' listener in your server will add the new socket to the room. Hope this helps :)

MEANJS: Security in SocketIO

Situation
I'm using the library SocketIO in my MEAN.JS application.
in NodeJS server controller:
var socketio = req.app.get('socketio');
socketio.sockets.emit('article.created.'+req.user._id, data);
in AngularJS client controller:
//Creating listener
Socket.on('article.created.'+Authentication.user._id, callback);
//Destroy Listener
$scope.$on('$destroy',function(){
Socket.removeListener('article.created.'+Authentication.user._id, callback);
});
Okey. Works well...
Problem
If a person (hacker or another) get the id of the user, he can create in another application a listener in the same channel and he can watch all the data that is sends to the user; for example all the notificacions...
How can I do the same thing but with more security?
Thanks!
Some time ago I stumbled upon the very same issue. Here's my solution (with minor modifications - used in production).
We will use Socket.IO namespaces to create private room for each user. Then we can emit messages (server-side) to specific rooms. In our case - only so specific user can receive them.
But to create private room for each connected user, we have to verify their identify first. We'll use simple piece of authentication middleware for that, supported by Socket.IO since its 1.0 release.
1. Authentication middleware
Since its 1.0 release, Socket.IO supports middleware. We'll use it to:
Verify connecting user identify, using JSON Web Token (see jwt-simple) he sent us as query parameter. (Note that this is just an example, there are many other ways to do this.)
Save his user id (read from the token) within socket.io connection instance, for later usage (in step 2).
Server-side code example:
var io = socketio.listen(server); // initialize the listener
io.use(function(socket, next) {
var handshake = socket.request;
var decoded;
try {
decoded = jwt.decode(handshake.query().accessToken, tokenSecret);
} catch (err) {
console.error(err);
next(new Error('Invalid token!'));
}
if (decoded) {
// everything went fine - save userId as property of given connection instance
socket.userId = decoded.userId; // save user id we just got from the token, to be used later
next();
} else {
// invalid token - terminate the connection
next(new Error('Invalid token!'));
}
});
Here's example on how to provide token when initializing the connection, client-side:
socket = io("http://stackoverflow.com/", {
query: 'accessToken=' + accessToken
});
2. Namespacing
Socket.io namespaces provide us with ability to create private room for each connected user. Then we can emit messages into specific room (so only users within it will receive them, as opposed to every connected client).
In previous step we made sure that:
Only authenticated users can connect to our Socket.IO interface.
For each connected client, we saved user id as property of socket.io connection instance (socket.userId).
All that's left to do is joining proper room upon each connection, with name equal to user id of freshly connected client.
io.on('connection', function(socket){
socket.join(socket.userId); // "userId" saved during authentication
// ...
});
Now, we can emit targeted messages that only this user will receive:
io.in(req.user._id).emit('article.created', data); // we can safely drop req.user._id from event name itself

Node-SQL with node.js and MS integrated Security

I have some sample code that is successfully connecting to SQL Server using Microsoft SQL Server user name and password. But I was wondering if there is a way to use integrated security with this script. Basically which means use the logged in user's credentials without supplying a password in the script.
var sql = require('mssql');
var config = {
server: '127.0.0.1',
database: 'master',
user: 'xx',
password: 'xxx',
options : {
trustedConnection : true
}
}
var connection = new sql.Connection(config, function(err) {
// ... error checks
if(err) {
return console.log("Could not connect to sql: ", err);
}
// Query
var request = new sql.Request(connection);
request.query('select * from dbo.spt_monitor (nolock)', function(err, recordset) {
// ... error checks
console.dir(recordset);
});
// Stored Procedure
});
Wish I could add this as a comment but don't have enough reputation yet... but what happens when you run this without providing a username/password in the config object?
Windows Authentication happens at the login level so there is no need to provide it at the application level.
Just browsed the documentation and looks like you cannot provide a raw connection string to connect, but to connect you want to build something that looks like this:
var connectionString= 'Server=MyServer;Database=MyDb;Trusted_Connection=Yes;'
The source code of the mssql module is here: https://github.com/patriksimek/node-mssql/blob/master/src/msnodesql.coffee... maybe you can fork and do a pull request that would provide an optional flag whether to use Windows Authentication or not, and that flag would remove the Uid={#{user}};Pwd={#{password}} (as it's unneeded for Windows Authentication) from the CONNECTION_STRING_PORT variable in the module's source code.

Resources