Initial commit

Change-Id: Ifc297dd3b5a52bb42d79a08bac4d05c2400ae779
diff --git a/app.js b/app.js
new file mode 100644
index 0000000..5f616cd
--- /dev/null
+++ b/app.js
@@ -0,0 +1,244 @@
+require('dotenv/config');
+
+const express = require('express')
+const app = express();
+const server = require('http').Server(app);
+const session = require('express-session')
+const io = require('socket.io')(server);
+const path = require('path');
+
+//const redis = require('redis')
+const redis = require('redis-url').connect();
+const RedisStore = require('connect-redis')(session)
+/*var passportSocketIo = require('passport.socketio');*/
+//const cookieParser = require('cookie-parser');
+const cookieParser = require('cookie-parser')(process.env.SECRET_KEY_BASE); // <- your secret here
+
+var indexRouter = require('./routes/index');
+//const cors = require('cors')
+
+var parser = require('fast-xml-parser');
+
+const RingDaemon = require('./RingDaemon.js');
+const passport = require('passport')
+    , LocalStrategy = require('passport-local').Strategy;
+
+const sessionStore = new RedisStore({ client: redis });
+
+
+/*
+    Configuation for Passeport Js
+*/
+
+// app.use(express.static('public'));
+// app.use(cookieParser());
+// app.use(bodyParser());
+app.use(session({
+    store: sessionStore,
+    resave: false,
+    saveUninitialized: false,
+    cookie: {
+        secure: process.env.ENVIRONMENT !== 'development' && process.env.ENVIRONMENT !== 'test',
+        maxAge: 2419200000
+    },
+    secret: process.env.SECRET_KEY_BASE
+}));
+
+app.use(passport.initialize());
+app.use(passport.session());
+// app.use(app.router);
+//app.use(cors())
+
+/*
+    Share sessions between Passport.js and Socket.io
+*/
+
+function logSuccess() {
+    console.log("passportSocketIo authorized user with Success 😁");
+}
+
+function logFail() {
+    console.log("passportSocketIo failed to authorized user 👺");
+}
+
+/*
+io.use(passportSocketIo.authorize({
+    key: 'connect.sid',
+    secret: process.env.SECRET_KEY_BASE,
+    store: sessionStore,
+    passport: passport,
+    cookieParser: cookieParser,
+    //success: logSuccess(),
+    // fail: logFail(),
+}));
+*/
+
+/*
+
+    tempAccounts holds users accounts while tempting to authenticate them on Jams.
+    connectedUsers  holds users accounts after they got authenticated by Jams.
+
+    Users should be removed from connectedUsers when receiving a disconnect 
+    web socket call
+
+*/
+const tempAccounts = {};
+const connectedUsers = {};
+
+const callbackMap = {
+    "IncomingAccountMessage": (accountId, from, message) => {
+        console.log("Received message: " + accountId + " " + from + " " + message["text/plain"]);
+
+        if (parser.validate(message["text/plain"]) === true) {
+            console.log(message["text/plain"]);
+        } else {
+
+            user = connectedUsers[accountId];
+            console.log(user.socketId)
+            io.to(user.socketId).emit('receivedMessage', message["text/plain"]);
+            //io.emit('receivedMessage', message["text/plain"]);
+        }
+    },
+    "RegistrationStateChanged": (accountId, state, /*int*/ code, detail) => {
+        console.log("RegistrationStateChanged: " + accountId + " " + state + " " + code + " " + detail);
+        if (state === "REGISTERED") {
+            if (tempAccounts[accountId]) {
+
+                const ctx = tempAccounts[accountId];
+                ctx.newUser.accountId = accountId;
+                ctx.newUser.jamiId = jami.dring.getAccountDetails(accountId).get("Account.username");
+                //connectedUsers[accountId] = ctx.newUser;
+                ctx.done(null, ctx.newUser);
+                delete tempAccounts[accountId];
+            }
+        } else if (state === "ERROR_AUTH") {
+            done(null, false);
+            //remove account
+        }
+    }
+}
+const jami = new RingDaemon(callbackMap);
+
+passport.serializeUser(function (user, done) {
+    console.log(user)
+    connectedUsers[user.accountId] = user;
+    console.log("=============================SerializeUser called " + user.accountId)
+    done(null, user.accountId);
+});
+
+
+const deserializeUser = (id, done) => {
+    console.log("=============================DeserializeUser called on: " + id + " " + connectedUsers[id])
+    done(null, connectedUsers[id]);
+};
+passport.deserializeUser(deserializeUser);
+
+//var tempAccountId = '';
+
+passport.use(new LocalStrategy(
+    (username, password, done) => {
+        const newUser = {};
+        newUser.username = username;
+        //newUser.socketid = 
+
+        const template = jami.dring.getAccountTemplate("RING");
+
+        /*
+            For test purpose we are not checking if a user can SSO using Jams,
+            instead we juste create a new user an get he's or her's newly created accountId
+        */
+        template.set("Account.managerUri", "https://jams.savoirfairelinux.com");
+        template.set("Account.managerUsername", username);
+        template.set("Account.archivePassword", password);
+
+        const accountId = jami.dring.addAccount(template);
+
+        const newProps = jami.getAccountDetails(accountId);
+        console.log(newProps);
+        //Object.entries(newProps).forEach(v => console.log(v[0], v[1]))
+        //tempAccountId = accountId;
+        newUser.accountId = accountId;
+        console.log("AccountId: " + accountId);
+        connectedUsers[accountId] = newUser;
+        tempAccounts[accountId] = { done, newUser };
+
+        //return done(null, newUser);
+
+        /*User.findOne({ username: username }, function (err, user) {
+            if (err) { return done(err); }
+            if (!user) {
+                return done(null, false, { message: 'Incorrect username.' });
+            }
+            if (!user.validPassword(password)) {
+                return done(null, false, { message: 'Incorrect password.' });
+            }
+            return done(null, user);
+        });*/
+    }
+));
+
+app.post('/api/login', passport.authenticate('local'), function (req, res) {
+    res.json({ loggedin: true });
+});
+app.use('/', indexRouter);
+
+/* GET React App */
+
+app.use(express.static(path.join(__dirname, 'public')))
+
+app.use(function (req, res, next) {
+    res.sendFile(path.join(__dirname, 'public', 'index.html'));
+});
+
+server.listen(3000);
+
+io.on('connection', (socket) => {
+    console.log("Client just connected !")
+    socket.on('SendMessage', (data) => {
+        console.log("Message " + data.text + " sent to " + data.destinationId + " by " + socket.session.user.accountId);
+        const msgMap = new jami.dring.StringMap();
+        msgMap.set('text/plain', data.text);
+        jami.dring.sendAccountTextMessage(socket.session.user.accountId, data.destinationId, msgMap);
+    });
+});
+
+
+io.use((socket, next) => {
+    cookieParser(socket.handshake, {}, (err) => {
+        if (err) {
+            console.log("error in parsing cookie");
+            return next(err);
+        }
+        if (!socket.handshake.signedCookies) {
+            console.log("no secureCookies|signedCookies found");
+            return next(new Error("no secureCookies found"));
+        }
+        sessionStore.get(socket.handshake.signedCookies["connect.sid"], (err, session) => {
+            socket.session = session;
+            if (!err && !session) err = new Error('session not found');
+            if (err) {
+                console.log('failed connection to socket.io:', err);
+            } else {
+                console.log(session);
+                console.log('successful connection to socket.io ' + session.passport.user);
+                const userKey = session.passport.user;
+                deserializeUser(userKey, (err, user) => {
+                    console.log("deserializeUser: " + user)
+                    if (err)
+                        return next(err, true);
+                    if (!user)
+                        return next("User not found", false);
+
+                    console.log("User associated socket id: " + socket.id)
+                    user.socketId = socket.id;
+                    socket.session.user = user;
+                    console.log("User added to session --------> " + user.accountId);
+                    /*data[auth.userProperty] = user;
+                    data[auth.userProperty].logged_in = true;*/
+                    //auth.success(data, accept);
+                    next(err, true);
+                });
+            }
+        });
+    });
+});