Saturday, February 24, 2018

Passport.SocketIo - How to get a list of online users with NodeJS, Express and Passport

1 comment

i am finish sessionStore with MongoStore every login is being performed correctly and sessions are being written to the database without errors. I am using this package github.com/jfromaniello/passport.socketio to align the passport with socket io but I have already looked for several places about how after login make the treatment of the sessionStorageso it lists which users with names are online and offline, Could show me a light on this?

app.js

var express = require('express'); var mongoose = require('mongoose'); var path = require('path'); var bodyParser = require('body-parser'); var cookieParser = require('cookie-parser'); var session = require('express-session'); const MongoStore = require('connect-mongo')(session); var flash = require('connect-flash'); var logger = require('morgan'); var passport = require('passport');  var passportSetup = require('./passport-setup');  // import routes var routes = require('./routes');  // setup express app var app = express(); app.use(logger());  // setup connection with mongodb mongoose.connect( process.env.MONGODB_URI || "mongodb://smachs:***@d***.mlab.com:****/****-messenger",     (err, db)=> {         if (err) return new Error(err);         console.log('🔐  Conexão estabelecida com banco de dados!');     }); // setup passport from different class         passportSetup();   // set view engine and connection of application app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.use(bodyParser.urlencoded({extended:false})); app.use(cookieParser());  // session storage based in mongodb var sessionStore = new MongoStore({     url: 'mongodb://smachs:***@d***.mlab.com:****/****-messenger',     ttl: 1 * 24 * 60 * 60, // = 1 days. Default     autoReconnect: true })  // setup session based in express-session app.use(session({     secret:"58585858585858",     key: "connect.sid",     resave: false,     saveUninitialized: false,     store: sessionStore }));  app.use(flash());  // public directory app.use(express.static(__dirname + '/public'));  // passport staff app.use(passport.initialize()); app.use(passport.session());  // start routes app.use(routes);  // start server var port = process.env.PORT || 3000; var server = app.listen(port, () => { console.log('🌐  Servidor iniciado em localhost:', port); });;  // setup socket.io and passport.socketio packages var io = require('socket.io').listen(server); var passportSocketIo = require("passport.socketio");  // setup session found in express-session io.use(passportSocketIo.authorize({     cookieParser: cookieParser,       // the same middleware you registrer in express     key: 'connect.sid',       // the name of the cookie where express/connect stores its session_id     secret: '58585858585858',    // the session_secret to parse the cookie     store: sessionStore, // we NEED to use a sessionstore. no memorystore please     success: onAuthorizeSuccess,  // *optional* callback on success - read more below     fail: onAuthorizeFail,     // *optional* callback on fail/error - read more below }));  // setup route just for clients authenticate function ensureAutheticated(req, res, next) {     if (req.isAuthenticated()) next();     else {         req.flash("info", "Você precisa estar logado para visualizar essa página!");         res.redirect('/login');     } }  // setup current online clients var User = require('./models/user'); app.use((req, res, next) => {     res.locals.currentUser = req.user;     res.locals.errors = req.flash('error');     res.locals.infos = req.flash('info');     next(); });  // callback from passport.socketio function onAuthorizeSuccess(data, accept) {     console.log('🗲 Passport-Socket.IO conectado com sucesso');      io.on('connection', function (socket) {         console.log("🗲 Socket.IO-Native conectado com sucesso");     });      // get current user online after authentication     io.on('connection', function (socket) {          // get user details of documents in database         app.get('/user-online', ensureAutheticated, (req, res) => {             User.find()                 .sort({ createdAd: 'descending' })                 .exec((err, users) => {                     if (err) return next(err);                     // render response                     res.send({                         users: users                     })                 });         });     });      accept(); }  function onAuthorizeFail(data, message, error, accept) {     console.log('failed connection to socket.io:', data, message);     if (error)         accept(new Error(message)); } 

user.js

var mongoose = require('mongoose'); var bcrypt = require('bcrypt-nodejs'); const SALT_FACTOR = 10;  var userSchema = mongoose.Schema({     username: { type: String, required: true, unique: true },     password: { type: String, required: true },     createdAt: { type: Date, default: Date.now },     displayName: String,     bio: String });  userSchema.methods.name = function() { return this.displayName || this.username;}  function noop() { };  userSchema.pre('save', function(done) {     var user = this;     console.log('USER: ' + JSON.stringify( user));      if (!( user.isModified('password'))) return done();     bcrypt.genSalt(SALT_FACTOR, function(err, salt) {         if (err) return done(err);         bcrypt.hash(user.password, salt, noop,            function (err, hashedPassword)  {                 if (err) return done(err);                 user.password = hashedPassword;                 done();             });     }); });  userSchema.methods.checkPassword = function(guess, done){     bcrypt.compare(guess, this.password, function(err, isMatch){         done(err,isMatch);     }); };  var User = mongoose.model('User', userSchema);  module.exports = User; 

I was trying after login to make an query in a collection to list the users I logged but it is limited to only 1 user and gives me no option to treat this result better, thank you very much for the help they give me!

1 Answers

Answers 1

You can track connection, disconnect, login and logout events to create a list of online users. You can manage online users in RAM or you can use redis for that. Following code snippet may help you achieve your goal -

// Store userIds here let onlineUsers = [];  io.on('connection', function (socket) {      socket.on('login', (userTokenOrId) => {         // store this to onlineUsers or redis         // Other stuff     });     socket.on('logout', (userTokenOrId) => {         // remove this from onlineUsers or redis         // Other stuff     });     socket.on('disconnect', (userTokenOrId) => {         // remove this from onlineUsers or redis         // Other stuff     }); }); 

For better use, You can manage one array of objects to store userId and list of socketIds for same and one object to map socketId to userId. This way you can track is one user is online on different browsers/system.

If You Enjoyed This, Take 5 Seconds To Share It

1 comment: