jfromaniello / passport.socketio

access passport.js authenticated user information from socket.io connection
655 stars 81 forks source link

Getting total number of authenticated users #104

Closed arniesaha closed 9 years ago

arniesaha commented 9 years ago

Hello,

I'm relatively new to socket.io and passport, but have been able to successfully integrate and authenticate users via passport.socketio and get the user details in the onAuthorizeSuccess callback.

I would like to understand how can I get total number of authenticated user (in an array with username as values) and render it in the front-end to reflect the logged in usernames in real time?

Thanks, Arnab

Arthur310 commented 9 years ago

Are you using EJS template ? And may i ask what database do you use ?

arniesaha commented 9 years ago

Using a basic node app with passport authentication on remote mongodb based on https://github.com/tutsplus/passport-mongo

And socket.io and passport.socketio module to validate authenticated users via passport

arniesaha commented 9 years ago

This is my onAuthorizeSuccess callback where I pass the username to different function to add the authenticated users in an array

function onAuthorizeSuccess(data, accept){ var username = data.user.username;
increaseCount(username); console.log('successful connection to socket.io '); console.log(data.user.username); accept(); //Let the user through }

function increaseCount(username){

var index = indexOf.call(loggedUser, username);
if(index == -1)
    loggedUser = username;

console.log("Users: "+loggedUser);

}

io.sockets.on('connection', function(socket) { console.log(socket.request.user); });

var indexOf = function(needle) { if(typeof Array.prototype.indexOf === 'function') { indexOf = Array.prototype.indexOf; } else { indexOf = function(needle) { var i = -1, index = -1;

        for(i = 0; i < this.length; i++) {
            if(this[i] === needle) {
                index = i;
                break;
            }
        }

        return index;
    };
}

return indexOf.call(this, needle);

};

But the array retains only the username of the last user. e.g. if user1 logged in, array holds user1 and user2 logs in after, array holds only user2.

Some clarity would be much appreciated.

Thanks, Arnab

Arthur310 commented 9 years ago

ok so you need to have a mongo document (or whatever they call similar to table in SQL) that store the authenticated user once they log in. If they log in, you save information in the 'mongo document' which can be retrieved later even if you close the browser. I don't see anyway for you to save that counting authenticated user in normal variable. Btw, do you have any issue with one user log in override the previous user ? just curious.

arniesaha commented 9 years ago

No. The user sessions are maintained as expected and no overrides occur. I was hoping for a different approach to exist with socket and passport used in conjunction.

I'll look into the mongo document approach. Thanks for the tip!

arniesaha commented 9 years ago

In the callback, I'm storing the username in a mongoose collection, and accordingly on the logout removing the user from the collection. I get a count of the number of users in the model which I need to pass and bind to the view. Jade being the template engine. Below is how my onAuthorizeSuccess callback looks like where I try to pass the count to home.jade.

function onAuthorizeSuccess(data, accept){

var username = data.user.username;

var User = mongoose.model('loggedusers', userSchema);

var user = new User({ username : username });

user.save(function (err, data) { if (err) console.log(err); else {
console.log('Saved : ', data ); }

User.count({}, function(err, c){
    console.log('Count is ' + c);

    app.get('/', function(req, res) {

    res.render('home', {
       count: {countData: c}
    });
});

});

});

console.log('successful connection to socket.io ');

accept(); //Let the user through }

And in the jade view I try to set it using li Logged Users ---> #{countData.c}

But, countData is undefined in the view.

How should I go about rendering a dynamic value from the server to the view in jade?

Any assistance much appreciated.

Thanks, Arnab

arniesaha commented 9 years ago

Figured this out.

Made a function to server content over a socket, that the control helps updating on the front-end

module.exports = function (socket) {

setInterval(function () {

var UserSchema = require('mongoose').model('loggedusers');

UserSchema.count({}, function(err, c){

    console.log('Count is ' + c);
    socket.emit('send:count', {
        count: c
    });

});

}, 1000); };

And the angular controller angular.module('myApp.controllers', []). controller('AppCtrl', function ($scope, socket) { socket.on('send:count', function (data) { $scope.count = data.count; }); });

and in jade {{count}} and add div.container(ng-controller='AppCtrl') should give the updated count on the front-end.

Arnab