diff --git a/.gitignore b/.gitignore index 12c624b..1589b76 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -.idea/ node_modules/ -config/ -logs/ \ No newline at end of file +.idea/ +config/express.json +config/mysql.json +config/twitter.json diff --git a/README.md b/README.md index f0476a8..cab58b9 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,49 @@ Clone this repo to your desktop and run `npm install` to install all the depende You might want to look into `app.js` and `public/js/chat.js` to make some adjustments such as changing the socket url to other than localhost, and set up a SSL certificate to work with it. +## Config +Along with version 0.21.0 and up, additional config files are required. + +These allow for furthered environment settings, controlled from within /lib/config/index.js + +The config module loads files from within /config/*, these are detailed below: + +##### config/mysql.json +``` +{ + "username":"", + "password":"", + "database":"", + "host":"" +} +``` +The credentials to connect to your mysql database. + +##### config/express.json +```{ + "key1":"", + "key2":"" +}``` + +These are the keys that encrypt the user cookie session, they should be completely random, and not shared. + +##### config/twitter.json +```{ + "TWITTER_CONSUMER_KEY":"", + "TWITTER_CONSUMER_SECRET":"" +}``` + +##### config/salt.json +```{ + "salt":"random_string" +}``` + +Salt to encrypt the json web token. + + +The keys in order to be able to use the Twitter oauth2 API. +You can get new keys here: https://apps.twitter.com/ + ## Usage After you clone this repo to your desktop, go to its root directory and run `npm install` to install its dependencies. diff --git a/app.js b/app.js index 2dc8e9c..2ce26c0 100644 --- a/app.js +++ b/app.js @@ -1,18 +1,19 @@ // Requires +var session = require('cookie-session'); var favicon = require('serve-favicon'); var s = require("underscore.string"); var readline = require('readline'); +var passport = require("passport"); +var jwt = require("jsonwebtoken"); var express = require('express'); var sockjs = require('sockjs'); var https = require('https'); var chalk = require('chalk'); -var path = require('path'); var fs = require('fs'); //Library Wrappers -var pack = require("./package.json"); +var config = require('./lib/config/'); var logger = require('./lib/logger/'); -var mysql = require('./lib/mysql/'); //Middleware var loginCheck = require('./middleware/loginCheck.js'); @@ -24,13 +25,11 @@ var routes = require('./routes/index.js'); var app = express(); // Variables -var config = { - log: true, - readline: false, //This is breaking on some machines, also to be deprecated with express routes. - ipadr: '127.0.0.1' || 'localhost', - port: 3000, - ssl: false -}; +config.log = true; +config.readline = false; //This is breaking on some machines, also to be deprecated with express routes. +config.ipadr = '127.0.0.1' || 'localhost'; +config.port = 3000; +config.ssl = false; var logInfo = chalk.bold.blue('[Info] '); var logStop = chalk.bold.red.dim('[Stop] '); @@ -71,26 +70,19 @@ if(config.readline) { // Express -//app.use(logger.express); +app.set('trust proxy', 1); +app.use(session({keys: [config.express.key1, config.express.key2]})); +app.use(passport.initialize()); +app.use(logger.express); app.set('view engine', 'ejs'); app.use(favicon(__dirname + '/public/img/favicon.png')); +app.use(express.static(__dirname + '/public')); //Login Check app.use(loginCheck); -/* -Sets up res.locals.user object to be used. -res.locals.user.logged_in contains boolean for logged_in user. -*/ //Routes -app.use('/chat', express.static(__dirname + '/public')); -app.get('/chat', function (req, res) { - res.render('pages/index', {version:pack.version}); -}); - -app.use('/', function(req, res, next){ - res.redirect('/chat'); //Temp redirect pre-login -}); +app.use(routes); // Connections @@ -101,7 +93,10 @@ var server = app.listen(config.port, config.ipadr, function() { consoleLog(logStart, 'Listening at http://' + host + ':' + port); }); +var util = require('util'); + chat.on('connection', function(conn) { + //console.log(util.inspect(conn)); consoleLog(logSocket, chalk.underline(conn.id) +': connected'); rateLimit[conn.id] = 1; lastTime[conn.id] = Date.now(); @@ -167,7 +162,10 @@ chat.on('connection', function(conn) { }); }); -chat.installHandlers(server, {prefix:'/socket',log:function(){}}); +chat.installHandlers(server, { + prefix:'/socket', + log:function(){} +}); // Util diff --git a/config/jwt.json b/config/jwt.json new file mode 100644 index 0000000..bc4a912 --- /dev/null +++ b/config/jwt.json @@ -0,0 +1,3 @@ +{ + "salt":"uhaisbhdsabf" +} \ No newline at end of file diff --git a/lib/config/index.js b/lib/config/index.js new file mode 100644 index 0000000..363455c --- /dev/null +++ b/lib/config/index.js @@ -0,0 +1,11 @@ +var config = {}; +var logger = require('../logger/'); + +config.mysql = require('../../config/mysql.json'); +config.twitter = require('../../config/twitter.json'); +config.express = require('../../config/express.json'); +config.jwt = require('../../config/jwt.json'); + +logger("info", "Config", "Successfully loaded config files!"); + +module.exports = config; diff --git a/lib/mysql/index.js b/lib/mysql/index.js index 3476c36..077041e 100644 --- a/lib/mysql/index.js +++ b/lib/mysql/index.js @@ -1,12 +1,12 @@ var mysql = require('mysql'); var config = require('../../config/mysql.json'); -var logger = require('jethro'); var connection = mysql.createConnection({ host : config.host, user : config.username, password : config.password, - database : config.database + database : config.database, + insecureAuth: true }); connection.connect(); diff --git a/middleware/loginCheck.js b/middleware/loginCheck.js index 070a9ea..0286eb6 100644 --- a/middleware/loginCheck.js +++ b/middleware/loginCheck.js @@ -1,5 +1,12 @@ var cookie = require('cookie'); module.exports = function(req, res, next){ - console.log(req); + //console.log(req.headers.cookie); + if (typeof req.session.user !== "undefined"){ + res.locals.user = req.session.user; + res.locals.user.logged_in = true; + } else { + res.locals.user = {}; + res.locals.user.logged_in = false; + } next(); }; \ No newline at end of file diff --git a/package.json b/package.json index fb0bb64..1aae4ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-chat", - "version": "0.20.31", + "version": "0.21.4", "private": true, "scripts": { "start": "node app.js" @@ -8,8 +8,10 @@ "dependencies": { "bcryptjs": "^2.1.0", "body-parser": "~1.12.0", + "chalk": "~1.0.0", "cookie": "^0.1.2", "cookie-parser": "~1.3.4", + "cookie-session": "^1.1.0", "debug": "~2.1.1", "ejs": "~2.3.1", "express": "~4.12.2", @@ -17,10 +19,11 @@ "jethro": "^1.2.7", "jsonwebtoken": "^4.2.2", "mysql": "^2.6.0", + "passport": "^0.2.1", + "passport-twitter": "^1.0.3", "readline": "0.0.7", "serve-favicon": "~2.2.0", "sockjs": "~0.3.15", - "chalk": "~1.0.0", "underscore.string": "~3.0.3" } -} \ No newline at end of file +} diff --git a/public/css/chat.css b/public/css/chat.css index 0e08970..deee5f9 100644 --- a/public/css/chat.css +++ b/public/css/chat.css @@ -1,7 +1,13 @@ #panel { - height: 300px; + height: 45vh; overflow: auto; - max-height: 300px; + max-height: 45vh; +} + +#users-panel { + height: 55vh; + overflow: auto; + max-height: 55vh; } #emoji, #sound, #desktop, #greentext, #synthesis, #recognition { diff --git a/routes/auth/index.js b/routes/auth/index.js new file mode 100644 index 0000000..68ed1a3 --- /dev/null +++ b/routes/auth/index.js @@ -0,0 +1,13 @@ +var express = require('express'); +var router = express.Router(); + +//Routes +var login = require('./login/'); +var twitter = require('./twitter/'); +var logout = require('./logout'); + +router.use("/login", login); +router.use('/twitter', twitter); +router.use("/logout", logout); + +module.exports = router; \ No newline at end of file diff --git a/routes/auth/login/index.js b/routes/auth/login/index.js new file mode 100644 index 0000000..973af16 --- /dev/null +++ b/routes/auth/login/index.js @@ -0,0 +1,13 @@ +var express = require('express'); +var router = express.Router(); + +router.get('/',function(req, res, next){ + if (res.locals.user.logged_in === true){ + res.redirect("/chat"); + } else { + res.render("pages/login"); + } +}); + + +module.exports = router; \ No newline at end of file diff --git a/routes/auth/logout/index.js b/routes/auth/logout/index.js new file mode 100644 index 0000000..936b26f --- /dev/null +++ b/routes/auth/logout/index.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +router.use("/", function(req, res, next){ + req.session = null; + res.redirect("/auth/login"); +}); + +module.exports = router; \ No newline at end of file diff --git a/routes/auth/twitter/index.js b/routes/auth/twitter/index.js new file mode 100644 index 0000000..5b8559f --- /dev/null +++ b/routes/auth/twitter/index.js @@ -0,0 +1,70 @@ +var express = require('express'); +var router = express.Router(); +var passport = require("passport"); +var TwitterStrategy = require('passport-twitter').Strategy; +var config = require('../../../lib/config/'); +var mysql = require('../../../lib/mysql'); + +passport.use(new TwitterStrategy({ + consumerKey: config.twitter.TWITTER_CONSUMER_KEY, + consumerSecret: config.twitter.TWITTER_CONSUMER_SECRET, + callbackURL: "http://localhost:3000/auth/twitter/callback", + session: false + }, + function(token, tokenSecret, profile, done) { + console.log(profile); + var q = "SELECT * FROM users WHERE token = '" + token + "'"; + console.log(q); + mysql.query(q, function(err, result){ + if (!err){ + if (result.length > 0){ + if (result[0].tokenSecret === tokenSecret){ + done(null, result[0]); + } + } else { + console.log(profile); + var user = { + id: profile.id, + token: token, + tokenSecret: tokenSecret, + name: profile._json.name, + username: profile.username, + location: profile._json.location, + description: profile._json.description + }; + mysql.query("INSERT INTO users SET ?", user, function(err, result){ + if (!err){ + done(null, user); + } else { + throw err; + } + }); + } + } else { + throw err; + } + }); + }) +); + +var jwt = require("jsonwebtoken"); + +router.get('/', passport.authenticate('twitter')); +router.get('/callback', + passport.authenticate('twitter', { + session: false + }), + function(req, res) { + req.session.user = req.user; + var user = req.user; + req.session.token = jwt.sign({ + foo: true, + user: {id: user.id, username: user.username, type:"twitter"}, + date: new Date() + }, config.jwt.salt); + res.cookie('jwt', req.session.token, {httpOnly: true }); + res.redirect("/chat"); + } +); + +module.exports = router; \ No newline at end of file diff --git a/routes/chat/index.js b/routes/chat/index.js new file mode 100644 index 0000000..095e801 --- /dev/null +++ b/routes/chat/index.js @@ -0,0 +1,13 @@ +var express = require('express'); +var router = express.Router(); +var pack = require('../../package.json'); + +router.use('/', function (req, res) { + if (res.locals.user.logged_in === true) { + res.render('pages/index', {version: pack.version}); + } else { + res.redirect("/auth/login"); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index e69de29..0022a23 100644 --- a/routes/index.js +++ b/routes/index.js @@ -0,0 +1,11 @@ +var express = require('express'); +var router = express.Router(); + +//Routes +var auth = require('./auth'); +var chat = require('./chat'); + +router.use("/auth", auth); +router.use("/chat", chat); + +module.exports = router; diff --git a/views/pages/index.ejs b/views/pages/index.ejs index b846ecb..cfa7c91 100644 --- a/views/pages/index.ejs +++ b/views/pages/index.ejs @@ -81,7 +81,12 @@
- + <% var defaultText = user.username + if (typeof user.display_name !== "undefined"){ + defaultText = res.locals.user.display_name; + } + %> + diff --git a/views/pages/login.ejs b/views/pages/login.ejs index e69de29..82026a9 100644 --- a/views/pages/login.ejs +++ b/views/pages/login.ejs @@ -0,0 +1,118 @@ + + + + + + + + + + + + Node.JS Chat- Login + + + + + + + + + + +
+ Fork me on GitHub + +
+

+ +
+ + +
+
+
+

Sign in

+
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+

Created by Igor Antun

+

+ +

+
+
+
+
+
+
+ + + + + + + + + + \ No newline at end of file