var fs = require('fs'); var url = require('url'); var mqtt = require('mqtt'); var http = require('http'); var https = require('https'); var flash = require('connect-flash'); var express = require('express'); var session = require('express-session'); var morgan = require('morgan'); var passport = require('passport'); var mongoose = require('mongoose'); var bodyParser = require('body-parser'); var cookieParser = require('cookie-parser'); var LocalStrategy = require('passport-local').Strategy; var PassportOAuthBearer = require('passport-http-bearer'); var oauthServer = require('./oauth'); var port = (process.env.VCAP_APP_PORT || process.env.PORT ||3000); var host = (process.env.VCAP_APP_HOST || '0.0.0.0'); var mongo_url = (process.env.MONGO_URL || 'mongodb://localhost/users'); var mqtt_url = (process.env.MQTT_URL || 'mqtt://localhost:1883'); var mqtt_user = (process.env.MQTT_USER || undefined); var mqtt_password = (process.env.MQTT_PASSWORD || undefined); console.log(mqtt_url); var mqttOptions = { keepAlive: 10, clean: true, clientId: 'webApp_' + Math.random().toString(16).substr(2, 8) }; if (mqtt_user) { mqttOptions.username = mqtt_user; mqttOptions.password = mqtt_password; } var mqttClient = mqtt.connect(mqtt_url, mqttOptions); if (process.env.VCAP_SERVICES) { var services = JSON.parse(process.env.VCAP_SERVICES); for (serviceName in services) { if (serviceName.match('^mongo')) { var creds = services[serviceName][0]['credentials']; mongo_url = creds.url; } else { console.log("no database found"); } } } console.log(mongo_url); mongoose.connect(mongo_url); var Account = require('./models/account'); var oauthModels = require('./models/oauth'); var Devices = require('./models/devices'); var Topics = require('./models/topics'); var app_id = 'https://localhost:' + port; if (process.env.VCAP_APPLICATION) { var application = JSON.parse(process.env.VCAP_APPLICATION); var app_uri = application['application_uris'][0]; app_id = 'https://' + app_uri; } var cookieSecret = 'ihytsrf334'; var app = express(); app.set('view engine', 'ejs'); app.enable('trust proxy'); app.use(morgan("combined")); app.use(cookieParser(cookieSecret)); app.use(flash()); app.use(session({ // genid: function(req) { // return genuuid() // use UUIDs for session IDs // }, secret: cookieSecret, resave: false, saveUninitialized: false, cookie: { secure: true } })); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(passport.initialize()); app.use(passport.session()); function requireHTTPS(req, res, next) { if (req.get('X-Forwarded-Proto') === 'http') { //FYI this should work for local development as well var url = 'https://' + req.get('host'); if (req.get('host') === 'localhost') { url += ':' + port; } url += req.url; return res.redirect(url); } next(); } app.use(requireHTTPS); app.use('/',express.static('static')); passport.use(new LocalStrategy(Account.authenticate())); passport.serializeUser(Account.serializeUser()); passport.deserializeUser(Account.deserializeUser()); var accessTokenStrategy = new PassportOAuthBearer(function(token, done) { oauthModels.AccessToken.findOne({ token: token }).populate('user').populate('grant').exec(function(error, token) { if (token && token.active && token.grant.active && token.user) { done(null, token.user, { scope: token.scope }); } else if (!error) { done(null, false); } else { done(error); } }); }); passport.use(accessTokenStrategy); app.get('/cleanDB', function(req,res){ Account.remove({}); Devices.remove({}); Topics.remove({}); res.send(); }); app.get('/', function(req,res){ res.render('pages/index', {user: req.user}); }); app.get('/docs', function(req,res){ res.render('pages/docs', {user: req.user}); }); app.get('/login', function(req,res){ res.render('pages/login',{user: req.user}); }); app.get('/logout', function(req,res){ req.logout(); res.redirect('/'); }); //app.post('/login',passport.authenticate('local', { failureRedirect: '/login', successRedirect: '/2faCheck', failureFlash: true })); app.post('/login', passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }), function(req,res){ res.redirect('/'); }); function ensureAuthenticated(req,res,next) { if (req.isAuthenticated()) { return next(); } else { res.redirect('/login'); } } app.get('/newuser', function(req,res){ res.render('pages/register',{user: req.user}); }); app.post('/newuser', function(req,res){ Account.register(new Account({ username : req.body.username, email: req.body.email, mqttPass: "foo" }), req.body.password, function(err, account) { if (err) { console.log(err); return res.status(400).send(err.message); } var topics = new Topics({topics: [account.username+'/#']}); topics.save(function(err){ if (!err){ var s = Buffer.from(account.salt, 'hex').toString('base64'); var h = Buffer.from(account.hash, 'hex').toString(('base64')); var mqttPass = "PBKDF2$sha256$901$" + account.salt + "$" + account.hash; Account.update( {username: account.username}, {$set: {mqttPass: mqttPass, topics: topics._id}}, { multi: false }, function(err, count){ if (err) { console.log(err); } } ); } }); passport.authenticate('local')(req, res, function () { console.log("created new user %s", req.body.username); res.status(201).send(); }); }); }); app.get('/auth/start',oauthServer.authorize(function(applicationID, redirectURI,done){ oauthModels.Application.findOne({ oauth_id: applicationID }, function(error, application) { if (application) { var match = false, uri = url.parse(redirectURI || ''); for (var i = 0; i < application.domains.length; i++) { if (uri.host == application.domains[i] || (uri.protocol == application.domains[i] && uri.protocol != 'http' && uri.protocol != 'https')) { match = true; break; } } if (match && redirectURI && redirectURI.length > 0) { done(null, application, redirectURI); } else { done(new Error("You must supply a redirect_uri that is a domain or url scheme owned by your app."), false); } } else if (!error) { done(new Error("There is no app with the client_id you supplied."), false); } else { done(error); } }); }),function(req,res){ var scopeMap = { // ... display strings for all scope variables ... access_devices: 'access you devices', create_devices: 'create new devices' }; res.render('pages/oauth', { transaction_id: req.oauth2.transactionID, currentURL: req.originalUrl, response_type: req.query.response_type, errors: req.flash('error'), scope: req.oauth2.req.scope, application: req.oauth2.client, user: req.user, map: scopeMap }); }); app.post('/auth/finish',function(req,res,next) { if (req.user) { next(); } else { passport.authenticate('local', { session: false }, function(error,user,info){ if (user) { next(); } else if (!error){ req.flash('error', 'Your email or password was incorrect. Try again.'); res.redirect(req.body['auth_url']) } })(req,res,next); } }, oauthServer.decision(function(req,done){ done(null, { scope: req.oauth2.req.scope }); })); app.post('/auth/exchange',function(req,res,next){ var appID = req.body['client_id']; var appSecret = req.body['client_secret']; oauthModels.Application.findOne({ oauth_id: appID, oauth_secret: appSecret }, function(error, application) { if (application) { req.appl = application; next(); } else if (!error) { error = new Error("There was no application with the Application ID and Secret you provided."); next(error); } else { next(error); } }); }, oauthServer.token(), oauthServer.errorHandler()); app.get('/api/v1/discover', passport.authenticate('bearer', { session: false }), function(req,res,next){ var user = req.user.username; Devices.find({username:user}, function(err, data){ if (!err) { console.log(data); res.send(data); } else { res.status(404).send(); } }); } ); app.post('/api/v1/command', passport.authenticate('bearer', { session: false }), function(req,res,next){ console.log(req.user.username); console.log(req.body); var topic = req.user.username + "/" + req.body.payload.appliance.applianceId; var message = JSON.stringify(req.body); try{ mqttClient.publish(topic,message); } catch (err) { } res.status(200).send(); } ); app.get('/devices', ensureAuthenticated, function(req,res){ var user = req.user.username; Devices.find({username:user}, function(err, data){ if (!err) { console.log(data); res.render('pages/devices',{user: req.user ,devices: data}); } }); }); app.put('/devices', ensureAuthenticated, function(req,res){ var user = req.user.username; var device = req.body; device.username = user; device.isReachable = true; var dev = new Devices(device); dev.save(function(err, dev){ if (!err) { res.status(201) res.send(dev); } else { res.status(500); res.send(err); } }); }); app.post('/device/:dev_id', ensureAuthenticated, function(req,res){ var user = req.user.username; var id = req.params.dev_id; var device = req.body; if (user === device.username) { Devices.findOne({_id: device._id, username: device.username}, function(err, data){ if (err) { res.status(500); res.send(err); } else { data.friendlyDescription = device.friendlyDescription; data.actions = device.actions; data.save(function(err, d){ res.status(201); res.send(d); }); } }); } }); app.delete('/device/:dev_id', ensureAuthenticated, function(req,res){ var user = req.user.username; var id = req.params.dev_id; console.log(id); Devices.remove({_id: id, username: user}, function(err) { if (err) { console.log(err); res.status(500); res.send(err); } else { res.status(202); res.send(); } }); }); app.post('/api/v1/devices', passport.authenticate('bearer', { session: false }), function(req,res,next){ var devices = req.body; if (typeof devices == 'object' && Array.isArray(foo)) { for (var i=0; i %s", app_id); });