javanode.jspassport.jseasyrtc

Node.JS + Passport + MySQL + EasyRTC authentication


As mentioned in the title i'm working with Node.js + Passport.JS and MySQL.js. All are installed and are working properly for the most part but i'm running into a few problems that I can't figure out.

  1. My profile.ejs page has access to the user.x variables but i'm not able to access these variables in most of my scripts. i'd like to set my easyrtcid to the email address of the logged in user.

  2. at the moment passport-session doesn't seem to be working. logging in from two different browsers is possible with the same userID and pass.

profile.ejs

    <!doctype html>
<html>
    <head>
        <title>Node Authentication</title>
        <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
        <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
        <link rel="stylesheet" type="text/css" href="/easyrtc/easyrtc.css" />
        <script src="http://localhost:8080/socket.io/socket.io.js"></script>
        <script type="text/javascript" src="http://localhost:8080/easyrtc/easyrtc.js"></script>
        <script type="text/javascript" src="E:/PortableApps/nodejs/app/config/demo_audio_video_simple.js"></script>
        <script type="text/javascript" src="E:/PortableApps/nodejs/app/config/jquery-2.1.1.min.js"></script>

        <style>
            /* Header styles */

            .row {
                float:left;
                position:relative;
                width:250px;
                text-align:center;
               }
            .well,
            .hidden {
                float:left;
                position:relative;
                padding:0 0 1em 0;
                overflow:hidden;
                }

            #otherClients {
                height:200px;
                overflow-y:scroll;
               }

            #selfVideo {
                height:225px;
                width:300px;
                float:left;
                border:1px solid gray;
                margin-left:10px;
            }
            #callerVideo {
                height:225px;
                width:300px;
                border:1px solid gray;
                margin-left:10px;
            }

            #well {
                position:relative;
            }
            #connectControls {
                float:left;
                width:250px;
                text-align:center;
            }
           /*#acceptCallBox {
                display:none;
                z-index:2;
                position:absolute;
                top:100px;
                left:400px;
                border:red solid 2px;
                background-color:pink;
                padding:15px; 
           }
        </style>
        <script>
            //var socket = io.connect('http://localhost');
            var selfEasyrtcid = "";
            var haveSelfVideo = false;
            //console.log(user);

            // easyrtc.enableDebug(true);

            // display globals in console
            //for(var b in window) { 
            //if(window.hasOwnProperty(b)) console.log(b); 
            // }


            function disable(domId) {
                console.log("about to try disabling "  + domId);
                document.getElementById(domId).disabled = "disabled";
            }


            function enable(domId) {
                console.log("about to try enabling "  + domId);
                document.getElementById(domId).disabled = "";
            }


            function connect() {
                console.log("Initializing connection");
                easyrtc.enableAudio(document.getElementById('shareAudio').checked);
                easyrtc.enableVideo(document.getElementById('shareVideo').checked);
                easyrtc.setRoomOccupantListener(convertListToButtons);
                easyrtc.connect("easyrtc.audioVideo", loginSuccess, loginFailure);
                console.log("connection complete");

            }

            function hangup() {
                easyrtc.hangupAll();
                disable('hangupButton');
                console.log("hangup");
            }


            function clearConnectList() {
                var otherClientDiv = document.getElementById('otherClients');
                while (otherClientDiv.hasChildNodes()) {
                    otherClientDiv.removeChild(otherClientDiv.lastChild);
                }
            }

            function convertListToButtons (roomName, data, isPrimary) {
                console.log("convert list to buttons");
                console.log(JSON.stringify(data));
                console.dir(data);
                clearConnectList();
                var otherClientDiv = document.getElementById('otherClients');
                for(var easyrtcid in data) {
                    var button = document.createElement('button');
                    button.onclick = function(easyrtcid) {
                        return function() {
                            performCall(easyrtcid);
                        };
                    }(easyrtcid);

                    var label = document.createTextNode(easyrtc.idToName(easyrtcid));
                    button.appendChild(label);
                    otherClientDiv.appendChild(button);
                }
            }

            function setUpMirror() {
                if( !haveSelfVideo) {
                    var selfVideo = document.getElementById("selfVideo");
                    easyrtc.setVideoObjectSrc(selfVideo, easyrtc.getLocalStream());
                    selfVideo.muted = true;
                    haveSelfVideo = true;
                }
            }

            function performCall(otherEasyrtcid) {
                easyrtc.hangupAll();
                console.log("calling" + otherEasyrtcid);
                var acceptedCB = function(accepted, easyrtcid) {
                    if( !accepted ) {
                        easyrtc.showError("CALL-REJECTED", "Sorry, your call to " + easyrtc.idToName(easyrtcid) + " was rejected");
                        enable('otherClients');
                    }
                };

                var successCB = function(easyrtcid) {
                    setUpMirror();
                    console.log("call accepted by " + easyrtc.idToName(easyrtcid));
                    enable('hangupButton');
                };
                var failureCB = function(otherEasyrtcid) {
                    console.log("call to  " + easyrtc.idToName(otherEasyrtcid) + " failed:" + errMessage);
                    enable('otherClients');
                };
                easyrtc.call(otherEasyrtcid, successCB, failureCB, acceptedCB);
                enable('hangupButton');
            }

            function loginSuccess(easyrtcid) {
                console.log(easyrtcid);
                selfEasyrtcid = easyrtcid;
                disable("connectButton");
              //  enable("disconnectButton");
                enable('otherClients');
              //  console.log(data);
                document.getElementById("iam").innerHTML = "I am " + easyrtc.cleanId(easyrtcid);
            }


            function loginFailure(errorCode, message) {
                easyrtc.showError(errorCode, message);
            }

            function disconnect() {
                console.log("disconnect");
                document.getElementById("iam").innerHTML = "logged out";
                easyrtc.disconnect();
                enable("connectButton");
            //    disable("disconnectButton");
                clearConnectList();
                easyrtc.setVideoObjectSrc(document.getElementById('selfVideo'), "");
            }

            easyrtc.setStreamAcceptor( function(easyrtcid, stream) {
                setUpMirror();
                var video = document.getElementById('callerVideo');
                easyrtc.setVideoObjectSrc(video,stream);
                console.log("saw video from " + easyrtcid);
                enable("hangupButton");
            });



            easyrtc.setOnStreamClosed( function (easyrtcid) {
                easyrtc.setVideoObjectSrc(document.getElementById('callerVideo'), "");
                disable("hangupButton");
            });


            var callerPending = null;

            easyrtc.setCallCancelled( function(easyrtcid){
                if( easyrtcid === callerPending) {
                    document.getElementById('acceptCallBox').style.display = "none";
                    callerPending = false;
                }
            });


            easyrtc.setAcceptChecker(function(easyrtcid, callback) {
                document.getElementById('acceptCallBox').style.display = "block";
                callerPending = easyrtcid;
                if( easyrtc.getConnectionCount() > 0 ) {
                    console.log(easyrtcid + "has" + easyrtc.getConnectionCount() + " peer connections");
                    document.getElementById('acceptCallLabel').innerHTML = "Drop current call and accept new from " + easyrtc.idToName(easyrtcid) + " ?";
                }
                else {
                    document.getElementById('acceptCallLabel').innerHTML = "Accept incoming call from " + easyrtc.idToName(easyrtcid) + " ?";
                }
                var acceptTheCall = function(wasAccepted) {
                    document.getElementById('acceptCallBox').style.display = "none";
                    if( wasAccepted && easyrtc.getConnectionCount() > 0 ) {
                        easyrtc.hangupAll();
                    }
                    callback(wasAccepted);
                    callerPending = null;
                };
                document.getElementById("callAcceptButton").onclick = function() {
                    acceptTheCall(true);
                };
                document.getElementById("callRejectButton").onclick =function() {
                    acceptTheCall(false);
                };
            } );

        </script>

    </head>
    <body>

    <div class="container">

        <div class="page-header text-center">
            <h1><span class="fa fa-anchor"> </span> Profile Page</h1>
            <a href="/logout" class="btn btn-default btn-sm">Logout</a>
        </div>
        <div class="row">

            <!-- LOCAL INFORMATION -->
                <div class="well">
                    <h3><span class="fa fa-user"> </span> Local</h3>

                    <div id="connectControls">
                        <input type="checkbox" checked="checked" id="shareAudio" />Share audio
                        <input type="checkbox" checked="checked" id="shareVideo" />Share video <br />
                        <button id="connectButton" onclick="connect()">Connect</button>
                        <button id="hangupButton" disabled="disabled" onclick="hangup()">Hangup</button>
                        <div id="iam">Not yet connected...</div>
                        <strong>id</strong>: <%= user.id %><br>
                        <strong>email</strong>: <%= user.email%><br>
                        <strong>password</strong>: <%= user.password %>
                        <br />
                        <strong>Connected users:</strong>
                        <div id="otherClients"> </div>
                    </div>

                    <div id="videos">
                        <video autoplay="autoplay" id="selfVideo"  class="easyrtcMirror" muted="muted" volume="0"> </video>
                        <video autoplay="autoplay" id="callerVideo"> </video>
                        <div id="acceptCallBox"> <!-- Should be initially hidden using CSS -->
                            <div id="acceptCallLabel"> </div>
                            <button id="callAcceptButton" >Accept</button> <button id="callRejectButton">Reject</button>
                        </div>
                    </div>
                    <div id="hidden"> </div>
                <!--hide-->
                <br style="clear:both;" />
                <hr />
                </div>
        </div>

    </div>
    </body>
</html>

passport.js

    // config/passport.js

// load all the things we need
var LocalStrategy   = require('passport-local').Strategy;
// load up the user model
var User            = require('../models/user');
var mysql = require('mysql');
//Database connection details
var connection = mysql.createConnection({
                  host     : '127.0.0.1',
                  user     : 'root',
                  password : ''
                });

connection.query('USE nodejsmysql');    
// expose this function to our app using module.exports
module.exports = function(passport) {

    // =========================================================================
    // passport session setup ==================================================
    // =========================================================================
    // required for persistent login sessions
    // passport needs ability to serialize and unserialize users out of session
    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        console.log("serialize");
        done(null, user.id);
    });

    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        console.log("deserialize");        
        connection.query("select * from users where id = "+id,function(err,rows){
            done(err, rows[0]);

        });
    });

    // =========================================================================
    // LOCAL SIGNUP ============================================================
    // =========================================================================
    // we are using named strategies since we have one for login and one for signup
    // by default, if there was no name, it would just be called 'local'

    passport.use('local-signup', new LocalStrategy({
        // by default, local strategy uses username and password, we will override with email
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true // allows us to pass back the entire request to the callback
    },
    function(req, email, password, done) {

        // find a user whose email is the same as the forms email
        // we are checking to see if the user trying to login already exists
        connection.query("select * from users where email = '"+email+"'",function(err,rows){
          //  console.log(rows);

            if (err) // error connecting to database
                return done(err);
             if (rows.length) { // user exists
                return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
            } else {

                // if there is no user with that email
                // create the user
                var newUserMysql = new Object();

                newUserMysql.email    = email;
                newUserMysql.password = password; // use the generateHash function in our user model

                var insertQuery = "INSERT INTO users ( email, password ) values ('" + email +"','"+ password +"')";

                connection.query(insertQuery,function(err,rows){
                newUserMysql.id = rows.insertId;

                return done(null, newUserMysql);
                }); 
            }   
        });
    }));

    // =========================================================================
    // LOCAL LOGIN =============================================================
    // =========================================================================
    // we are using named strategies since we have one for login and one for signup
    // by default, if there was no name, it would just be called 'local'

    passport.use('local-login', new LocalStrategy({
        // by default, local strategy uses username and password, we will override with email
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true // allows us to pass back the entire request to the callback
    },
    function(req, email, password, done) { // callback with email and password from our form

         connection.query("select * from users where email = '"+email+"'",function(err,rows){


            if (err)
                return done(err);
             if (!rows.length) {
                return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash
            } 

            // if the user is found but the password is wrong
            if (!( rows[0].password == password))
                return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata

            // all is well, return successful user

            return done(null, rows[0]);         

        });
    }));
};

Solution

  • I was able to resolve the first part of my problem. on profile.ejs i just grabbed the value of the element and set it to the easyrtcid.username

    element = document.getElementById('email');
                    var searchThis = element.textContent || element.innerText;
                     easyrtc.setUsername(searchThis);
    

    so now when the user logs in rather than seeing the random easyrtcID they'll see their own username and each other user will be sending their username so convertlisttobuttons() will now also show the email address of the logged in user.

    i'm still having the second issue though with no ideas on how to proceed. once a user is logged in their session should be locked and no one else should be able to login with that email/pw combo. I could still use help on that.