<commit_before>var app = require('express')();
var http = require('http').Server(app);
var hash_table = require('hashtable');
var dns = require('dns');
var os = require('os');
var io = require('socket.io')(http);
var client_io = require('socket.io-client');

const global_http_port = 8080;

function p2p_client(initialServerUri) {
  this.otherServerUri = initialServerUri;
  this.http_port = global_http_port;
  this.selfLocalIpAddr = "127.0.0.1";
  this.selfLocalUri = "http://" + this.selfLocalIpAddr + ':' +
    global_http_port;
  this.socketTable = new hash_table();
}

p2p_client.getUriOfSocket = function(socket) {
  // console.log(socket);
  return socket.io.uri;
}

// do everything with client inside callback
// socket_callback takes socket as an argument
p2p_client.prototype.start = function(init_callback, socket_callback) {
  var _this = this;
  this.socket_callback = socket_callback;
  getGlobalSelfIpAddr(function(address) {
    _this.selfGlobalIpAddr = address;
    _this.selfGlobalUri = "http://" + _this.selfGlobalIpAddr + ':' +
      _this.http_port;
    // TODO: determine whether below line is required
    _this.addSocketByUri(_this.selfLocalUri, true);
    _this.addSocketByUri(_this.otherServerUri, true);
    if (typeof init_callback == "function") {
      init_callback();
    }
  });
}

p2p_client.prototype.getNumUsers = function() {
  return this.socketTable.size();
}

p2p_client.prototype.initSocket = function(socket, isAddNew) {
  var _this = this;
  socket.on('connect', function() {
    if (isAddNew) {
      // send global uri to otherServer
      p2p_client.broadcastAddThisUri(socket, _this.selfGlobalUri);
    }
    // connect to given server uri and tell server's client to connect back
    socket.on('add_this_server', function(userGlobalUri) {
      _this.addSocketByUri(userGlobalUri, true).emit(
        'tell_attached_client_to_add_back', _this.selfGlobalUri);
      console.log("---");
      console.log("add_this_server received: " + userGlobalUri);
      console.log("tell_attached_client_to_add_back sent: " +
        _this.selfGlobalUri);
    });
    // just connect to given server uri
    socket.on('just_add_this_server', function(userGlobalUri) {
      _this.addSocketByUri(userGlobalUri, true);
      console.log("---");
      console.log("just_add_this_server received: " + userGlobalUri);
      console.log(userGlobalUri + " socket added")
    });
    socket.on('disconnect', function() {
      _this.removeSocket(socket);
    });
    socket.on('reconnect', function() {
      _this.addSocket(socket, true);
    });
    if (typeof _this.socket_callback == "function") {
      _this.socket_callback(socket);
    }
  });
  return socket;
}

// also serves to rejigger connections for robustness
p2p_client.broadcastAddThisUri = function(socket, selfGlobalUri) {
  socket.emit('tell_your_clients_to_add_me', selfGlobalUri);
  console.log("---");
  console.log("tell_your_clients_to_add_me sent: " + selfGlobalUri);
}

p2p_client.prototype.addSocket = function(socket, isAddNew) {
  this.socketTable.put(p2p_client.getUriOfSocket(socket), socket);
  return this.initSocket(this.socketTable.get(p2p_client.getUriOfSocket(
    socket)), isAddNew);
}

p2p_client.prototype.addSocketByUri = function(Uri, isAddNew) {
  if (Uri == this.selfGlobalUri) {
    var ret = this.socketTable.get(this.selfLocalUri);
    if (ret) {
      return ret;
    } else {
      return this.addSocket(client_io(this.selfLocalUri), isAddNew);
    }
  } else {
    var ret = this.socketTable.get(Uri);
    if (!ret) {
      return this.addSocket(client_io(Uri), isAddNew);
    } else {
      return ret;
    }
  }
}

p2p_client.prototype.removeSocket = function(socket) {
  return this.socketTable.remove(p2p_client.getUriOfSocket(socket));
}

function p2p_server() {
  this.http_port = global_http_port;
  this.selfLocalIpAddr = "127.0.0.1";
  this.selfLocalUri = "http://" + this.selfLocalIpAddr + ':' + this.http_port;
  this.socketTable = new hash_table();
}

p2p_server.prototype.start = function(init_callback, socket_callback) {
  var _this = this;
  http.listen(this.http_port, init_callback);
  io.on('connection', function(socket) {
    _this.socketTable.put(p2p_server.getUriOfSocket(socket), socket);
    console.log("user " + p2p_server.getUriOfSocket(socket) +
      " connected :)");
    if (p2p_server.getUriOfSocket(socket) == _this.selfLocalUri) {
      _this.localClientSocket = socket;
    }
    // send uri of client to all clients
    socket.on('tell_your_clients_to_add_me', function(userGlobalUri) {
      io.emit('add_this_server', userGlobalUri);
      console.log("---");
      console.log("tell_your_clients_to_add_me received: " +
        userGlobalUri);
      console.log("add_this_server sent: " + userGlobalUri);
    });
    socket.on('tell_attached_client_to_add_back',
      function(userGlobalUri) {
        _this.localClientSocket.emit('just_add_this_server',
          userGlobalUri);
        console.log("---");
        console.log(
          "tell_attached_client_to_add_back received: " +
          userGlobalUri);
        console.log("just_add_this_server sent: " + userGlobalUri);
      });
    socket.on('disconnect',
      function() {
        console.log("user " + p2p_server.getUriOfSocket(socket) +
          " disconnected :(");
        _this.socketTable.remove(p2p_server.getUriOfSocket(socket));
      });
    socket.on('reconnect',
      function() {
        console.log("user " + p2p_server.getUriOfSocket(socket) +
          " reconnected :DDD");
        _this.socketTable.put(p2p_server.getUriOfSocket(socket), socket);
      });
    if (typeof socket_callback == "function") {
      socket_callback(socket);
    }
  });
};

// TODO: figure out how to get client socket's http port!
p2p_server.getUriOfSocket = function(socket) {
  return "http://" + socket.handshake.address + ':' + global_http_port;
}

p2p_server.prototype.emit = function(event, data) {
  io.emit(event, data);
};

function p2p_peer(initialServerUri) {
  this.client = new p2p_client(initialServerUri);
  this.server = new p2p_server();
}

p2p_peer.prototype.start = function(client_init_callback,
  client_socket_callback,
  server_init_callback,
  server_socket_callback) {
  this.client.start(client_init_callback, client_socket_callback);
  this.server.start(server_init_callback, server_socket_callback);
}

p2p_peer.prototype.emit = function(event, data) {
  this.server.emit(event, data);
}

p2p_peer.prototype.getNumUsers = function() {
  return this.client.getNumUsers();
}

// helper functions
function getGlobalSelfIpAddr(callback) {
  dns.lookup(os.hostname(), function(error, address, family) {
    callback(address);
  });
}

module.exports = {
  http_port: global_http_port,
  client: p2p_client,
  server: p2p_server,
  peer: p2p_peer
}
<commit_msg>file transfer<commit_after>var app = require('express')();
var http = require('http').Server(app);
var hash_table = require('hashtable');
var dns = require('dns');
var os = require('os');
var io = require('socket.io')(http);
var client_io = require('socket.io-client');

const global_http_port = 8080;

function p2p_client(initialServerUri) {
  this.otherServerUri = initialServerUri;
  this.http_port = global_http_port;
  this.selfLocalIpAddr = "127.0.0.1";
  this.selfLocalUri = "http://" + this.selfLocalIpAddr + ':' +
    global_http_port;
  this.socketTable = new hash_table();
}

p2p_client.getUriOfSocket = function(socket) {
  // console.log(socket);
  return socket.io.uri;
}

// do everything with client inside callback
// socket_callback takes socket as an argument
p2p_client.prototype.start = function(init_callback, socket_callback) {
  var _this = this;
  this.socket_callback = socket_callback;
  getGlobalSelfIpAddr(function(address) {
    _this.selfGlobalIpAddr = address;
    _this.selfGlobalUri = "http://" + _this.selfGlobalIpAddr + ':' +
      _this.http_port;
    // TODO: determine whether below line is required
    _this.addSocketByUri(_this.selfLocalUri, false);
    _this.addSocketByUri(_this.otherServerUri, true);
    if (typeof init_callback == "function") {
      init_callback();
    }
  });
}

p2p_client.prototype.getNumUsers = function() {
  return this.socketTable.size();
}

p2p_client.prototype.initSocket = function(socket, isAddNew) {
  var _this = this;
  socket.on('connect', function() {
    if (isAddNew) {
      // send global uri to otherServer
      p2p_client.broadcastAddThisUri(socket, _this.selfGlobalUri);
    }
    // connect to given server uri and tell server's client to connect back
    socket.on('add_this_server', function(userGlobalUri) {
      _this.addSocketByUri(userGlobalUri, false).emit(
        'tell_attached_client_to_add_back', _this.selfGlobalUri);
      console.log("---");
      console.log("add_this_server received: " + userGlobalUri);
      console.log("tell_attached_client_to_add_back sent: " +
        _this.selfGlobalUri);
    });
    // just connect to given server uri
    socket.on('just_add_this_server', function(userGlobalUri) {
      _this.addSocketByUri(userGlobalUri, false);
      console.log("---");
      console.log("just_add_this_server received: " + userGlobalUri);
      console.log(userGlobalUri + " socket added")
    });
    socket.on('disconnect', function() {
      _this.removeSocket(socket);
    });
    socket.on('reconnect', function() {
      _this.addSocket(socket, false);
    });
    if (typeof _this.socket_callback == "function") {
      _this.socket_callback(socket);
    }
  });
  return socket;
}

// also serves to rejigger connections for robustness
p2p_client.broadcastAddThisUri = function(socket, selfGlobalUri) {
  socket.emit('tell_your_clients_to_add_me', selfGlobalUri);
  console.log("---");
  console.log("tell_your_clients_to_add_me sent: " + selfGlobalUri);
}

p2p_client.prototype.addSocket = function(socket, isAddNew) {
  this.socketTable.put(p2p_client.getUriOfSocket(socket), socket);
  return this.initSocket(this.socketTable.get(p2p_client.getUriOfSocket(
    socket)), isAddNew);
}

p2p_client.prototype.addSocketByUri = function(Uri, isAddNew) {
  if (Uri == this.selfGlobalUri) {
    var ret = this.socketTable.get(this.selfLocalUri);
    if (ret) {
      return ret;
    } else {
      return this.addSocket(client_io(this.selfLocalUri), isAddNew);
    }
  } else {
    var ret = this.socketTable.get(Uri);
    if (!ret) {
      return this.addSocket(client_io(Uri), isAddNew);
    } else {
      return ret;
    }
  }
}

p2p_client.prototype.removeSocket = function(socket) {
  return this.socketTable.remove(p2p_client.getUriOfSocket(socket));
}

function p2p_server() {
  this.http_port = global_http_port;
  this.selfLocalIpAddr = "127.0.0.1";
  this.selfLocalUri = "http://" + this.selfLocalIpAddr + ':' + this.http_port;
  this.socketTable = new hash_table();
}

p2p_server.prototype.start = function(init_callback, socket_callback) {
  var _this = this;
  http.listen(this.http_port, init_callback);
  io.on('connection', function(socket) {
    _this.socketTable.put(p2p_server.getUriOfSocket(socket), socket);
    console.log("user " + p2p_server.getUriOfSocket(socket) +
      " connected :)");
    if (p2p_server.getUriOfSocket(socket) == _this.selfLocalUri) {
      _this.localClientSocket = socket;
    }
    // send uri of client to all clients
    socket.on('tell_your_clients_to_add_me', function(userGlobalUri) {
      io.emit('add_this_server', userGlobalUri);
      console.log("---");
      console.log("tell_your_clients_to_add_me received: " +
        userGlobalUri);
      console.log("add_this_server sent: " + userGlobalUri);
    });
    socket.on('tell_attached_client_to_add_back',
      function(userGlobalUri) {
        _this.localClientSocket.emit('just_add_this_server',
          userGlobalUri);
        console.log("---");
        console.log(
          "tell_attached_client_to_add_back received: " +
          userGlobalUri);
        console.log("just_add_this_server sent: " + userGlobalUri);
      });
    socket.on('disconnect',
      function() {
        console.log("user " + p2p_server.getUriOfSocket(socket) +
          " disconnected :(");
        _this.socketTable.remove(p2p_server.getUriOfSocket(socket));
      });
    socket.on('reconnect',
      function() {
        console.log("user " + p2p_server.getUriOfSocket(socket) +
          " reconnected :DDD");
        _this.socketTable.put(p2p_server.getUriOfSocket(socket), socket);
      });
    if (typeof socket_callback == "function") {
      socket_callback(socket);
    }
  });
};

// TODO: figure out how to get client socket's http port!
p2p_server.getUriOfSocket = function(socket) {
  return "http://" + socket.handshake.address + ':' + global_http_port;
}

p2p_server.prototype.emit = function(event, data) {
  io.emit(event, data);
};

function p2p_peer(initialServerUri) {
  this.client = new p2p_client(initialServerUri);
  this.server = new p2p_server();
}

p2p_peer.prototype.start = function(client_init_callback,
  client_socket_callback,
  server_init_callback,
  server_socket_callback) {
  this.client.start(client_init_callback, client_socket_callback);
  this.server.start(server_init_callback, server_socket_callback);
}

p2p_peer.prototype.emit = function(event, data) {
  this.server.emit(event, data);
}

p2p_peer.prototype.getNumUsers = function() {
  return this.client.getNumUsers();
}

// helper functions
function getGlobalSelfIpAddr(callback) {
  dns.lookup(os.hostname(), function(error, address, family) {
    callback(address);
  });
}

module.exports = {
  http_port: global_http_port,
  client: p2p_client,
  server: p2p_server,
  peer: p2p_peer
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 * Copyright 2013, 2015 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
var http = require('http');
var https = require('https');
var util = require("util");
var express = require("express");
var routes = require('./routes');
var crypto = require("crypto");
var nopt = require("nopt");
var path = require("path");
var fs = require("fs");
var RED = require("./red/red.js");
var log = require("./red/log");
var passport = require('passport');
var mongoose = require('mongoose');
var config = require('./oauth.js');
var User = require('./user.js');
var auth = require('./authentication.js');

// connect to the database
mongoose.connect('mongodb://127.0.0.1:27017/test');

// serialize and deserialize
passport.serializeUser(function(user, done) {
    console.log('serializeUser: ' + user._id)
    done(null, user._id);
});

passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user){
        if(!err) done(null, user);
        else done(err, null)
    });
});

var server;
var app = express();

app.configure(function(){
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.logger());
    app.use(express.cookieParser());
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.session({ secret: 'cookie monster' }));
    app.use(passport.initialize());
    app.use(passport.session());
    app.use(app.router);
});

// routes
app.get('/', routes.index);

app.get('/', function(req, res){
    res.render('login', { user: req.user });
});

app.get('/auth/facebook', passport.authenticate('facebook'));
app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/' }), function(req, res) {
    res.redirect('/red');
});

app.get('/auth/twitter',  passport.authenticate('twitter'));
app.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/' }), function(req, res) {
    res.redirect('/red');
});

app.get('/auth/github', passport.authenticate('github'));
app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/' }), function(req, res) {
    // Successful authentication, redirect home.
    res.redirect('/red');
});

app.get('/auth/google', passport.authenticate('google',{scope: 'https://www.googleapis.com/auth/plus.me https://www.google.com/m8/feeds https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile'}));

app.get('/auth/google/callback', passport.authenticate('google'), function(req, res) {
        res.redirect('/red');
});

// test authentication
function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) { return next(); }
  res.redirect('/');
}

var settingsFile;
var flowFile;

var knownOpts = {
    "settings":[path],
    "userDir":[path],
    "v": Boolean,
    "help": Boolean
};
var shortHands = {
    "s":["--settings"],
    "u":["--userDir"],
    "?":["--help"]
};
nopt.invalidHandler = function(k,v,t) {
    // TODO: console.log(k,v,t);
}

var parsedArgs = nopt(knownOpts,shortHands,process.argv,2)

if (parsedArgs.help) {
    console.log("Node-RED v"+RED.version());
    console.log("Usage: node-red [-v] [-?] [--settings settings.js] [--userDir DIR] [flows.json]");
    console.log("");
    console.log("Options:");
    console.log("  -s, --settings FILE  use specified settings file");
    console.log("  -u, --userDir  DIR   use specified user directory");
    console.log("  -v                   enable verbose output");
    console.log("  -?, --help           show usage");
    console.log("");
    console.log("Documentation can be found at http://nodered.org");
    process.exit();
}
if (parsedArgs.argv.remain.length > 0) {
    flowFile = parsedArgs.argv.remain[0];
}

if (parsedArgs.settings) {
    // User-specified settings file
    settingsFile = parsedArgs.settings;
} else if (parsedArgs.userDir && fs.existsSync(path.join(parsedArgs.userDir,"settings.js"))) {
    // User-specified userDir that contains a settings.js
    settingsFile = path.join(parsedArgs.userDir,"settings.js");
} else {
    if (fs.existsSync(path.join(process.env.NODE_RED_HOME,".config.json"))) {
        // NODE_RED_HOME contains user data - use its settings.js
        settingsFile = path.join(process.env.NODE_RED_HOME,"settings.js");
    } else {
        var userSettingsFile = path.join(process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE,".node-red","settings.js");
        if (fs.existsSync(userSettingsFile)) {
            // $HOME/.node-red/settings.js exists
            settingsFile = userSettingsFile;
        } else {
            // Use default settings.js
            settingsFile = __dirname+"/settings.js";
        }
    }
}

try {
    var settings = require(settingsFile);
    settings.settingsFile = settingsFile;
} catch(err) {
    if (err.code == 'MODULE_NOT_FOUND') {
        console.log("Unable to load settings file: "+settingsFile);
    } else {
        console.log(err);
    }
    process.exit();
}

if (parsedArgs.v) {
    settings.verbose = true;
}

if (settings.https) {
    server = https.createServer(settings.https,function(req,res){app(req,res);});
} else {
    server = http.createServer(function(req,res){app(req,res);});
}
server.setMaxListeners(0);

function formatRoot(root) {
    if (root[0] != "/") {
        root = "/" + root;
    }
    if (root.slice(-1) != "/") {
        root = root + "/";
    }
    return root;
}

if (settings.httpRoot === false) {
    settings.httpAdminRoot = false;
    settings.httpNodeRoot = false;
} else {
    settings.httpRoot = settings.httpRoot||"/";
    settings.disableEditor = settings.disableEditor||false;
}

if (settings.httpAdminRoot !== false) {
    settings.httpAdminRoot = formatRoot(settings.httpAdminRoot || settings.httpRoot || "/");
    settings.httpAdminAuth = settings.httpAdminAuth || settings.httpAuth;
} else {
    settings.disableEditor = true;
}

if (settings.httpNodeRoot !== false) {
    settings.httpNodeRoot = formatRoot(settings.httpNodeRoot || settings.httpRoot || "/");
    settings.httpNodeAuth = settings.httpNodeAuth || settings.httpAuth;
}

settings.uiPort = settings.uiPort||1880;
settings.uiHost = settings.uiHost||"0.0.0.0";

if (flowFile) {
    settings.flowFile = flowFile;
}
if (parsedArgs.userDir) {
    settings.userDir = parsedArgs.userDir;
}

try {
    RED.init(server,settings);
} catch(err) {
    if (err.code == "not_built") {
        console.log("Node-RED has not been built. See README.md for details");
    } else {
        console.log("Failed to start server:");
        if (err.stack) {
            console.log(err.stack);
        } else {
            console.log(err);
        }
    }
    process.exit(1);
}

if (settings.httpAdminRoot !== false && settings.httpAdminAuth) {
    RED.log.warn(log._("server.httpadminauth-deprecated"));
    app.use(settings.httpAdminRoot,
        express.basicAuth(function(user, pass) {
            return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass;
        })
    );
}

if (settings.httpNodeRoot !== false && settings.httpNodeAuth) {
    app.use(settings.httpNodeRoot,
        express.basicAuth(function(user, pass) {
            return user === settings.httpNodeAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpNodeAuth.pass;
        })
    );
}
if (settings.httpAdminRoot !== false) {
    app.use(settings.httpAdminRoot,RED.httpAdmin);
}
if (settings.httpNodeRoot !== false) {
    app.use(settings.httpNodeRoot,RED.httpNode);
}
if (settings.httpStatic) {
    settings.httpStaticAuth = settings.httpStaticAuth || settings.httpAuth;
    if (settings.httpStaticAuth) {
        app.use("/",
            express.basicAuth(function(user, pass) {
                return user === settings.httpStaticAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpStaticAuth.pass;
            })
        );
    }
    app.use("/",express.static(settings.httpStatic));
}

function getListenPath() {
    var listenPath = 'http'+(settings.https?'s':'')+'://'+
                    (settings.uiHost == '0.0.0.0'?'127.0.0.1':settings.uiHost)+
                    ':'+settings.uiPort;
    if (settings.httpAdminRoot !== false) {
        listenPath += settings.httpAdminRoot;
    } else if (settings.httpStatic) {
        listenPath += "/";
    }
    return listenPath;
}

RED.start().then(function() {
    if (settings.httpAdminRoot !== false || settings.httpNodeRoot !== false || settings.httpStatic) {
        server.on('error', function(err) {
            if (err.errno === "EADDRINUSE") {
                RED.log.error(log._("server.unable-to-listen", {listenpath:getListenPath()}));
                RED.log.error(log._("server.port-in-use"));
            } else {
                RED.log.error(log._("server.uncaught-exception"));
                if (err.stack) {
                    RED.log.error(err.stack);
                } else {
                    RED.log.error(err);
                }
            }
            process.exit(1);
        });
        server.listen(settings.uiPort,settings.uiHost,function() {
            if (settings.httpAdminRoot === false) {
                RED.log.info(log._("server.admin-ui-disabled"));
            }
            process.title = 'node-red';
            RED.log.info(log._("server.now-running", {listenpath:getListenPath()}));
        });
    } else {
        RED.log.info(log._("server.headless-mode"));
    }
}).otherwise(function(err) {
    RED.log.error(log._("server.failed-to-start"));
    if (err.stack) {
        RED.log.error(err.stack);
    } else {
        RED.log.error(err);
    }
});

process.on('uncaughtException',function(err) {
    util.log('[red] Uncaught Exception:');
    if (err.stack) {
        util.log(err.stack);
    } else {
        util.log(err);
    }
    process.exit(1);
});

process.on('SIGINT', function () {
    RED.stop();
    // TODO: need to allow nodes to close asynchronously before terminating the
    // process - ie, promises
    process.exit();
});
<commit_msg>Verifying user<commit_after>#!/usr/bin/env node
/**
 * Copyright 2013, 2015 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
var http = require('http');
var https = require('https');
var util = require("util");
var express = require("express");
var routes = require('./routes');
var crypto = require("crypto");
var nopt = require("nopt");
var path = require("path");
var fs = require("fs");
var RED = require("./red/red.js");
var log = require("./red/log");
var passport = require('passport');
var mongoose = require('mongoose');
var config = require('./oauth.js');
var User = require('./user.js');
var auth = require('./authentication.js');

// connect to the database
mongoose.connect('mongodb://127.0.0.1:27017/test');

// serialize and deserialize
passport.serializeUser(function(user, done) {
    console.log('serializeUser: ' + user._id)
    done(null, user._id);
});

passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user){
        if(!err) done(null, user);
        else done(err, null)
    });
});

var server;
var app = express();

app.configure(function(){
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.logger());
    app.use(express.cookieParser());
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.session({ secret: 'cookie monster' }));
    app.use(passport.initialize());
    app.use(passport.session());
    app.use(app.router);
});

// routes
app.get('/', routes.index);

app.get('/', function(req, res){
    res.render('login', { user: req.user });
});

app.get('/auth/facebook', passport.authenticate('facebook'));
app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/' }), function(req, res) {
    res.redirect('/red');
});

app.get('/auth/twitter',  passport.authenticate('twitter'));
app.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/' }), function(req, res) {
    res.redirect('/red');
});

app.get('/auth/github', passport.authenticate('github'));
app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/' }), function(req, res) {
    // Successful authentication, redirect home.
    res.redirect('/red');
});

app.get('/auth/google', passport.authenticate('google',{scope: 'https://www.googleapis.com/auth/plus.me https://www.google.com/m8/feeds https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile'}));

app.get('/auth/google/callback', passport.authenticate('google'), function(req, res) {
        res.redirect('/red');
});

// test authentication
function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) { return next(); }
  res.redirect('/');
}

var settingsFile;
var flowFile;

var knownOpts = {
    "settings":[path],
    "userDir":[path],
    "v": Boolean,
    "help": Boolean
};
var shortHands = {
    "s":["--settings"],
    "u":["--userDir"],
    "?":["--help"]
};
nopt.invalidHandler = function(k,v,t) {
    // TODO: console.log(k,v,t);
}

var parsedArgs = nopt(knownOpts,shortHands,process.argv,2)

if (parsedArgs.help) {
    console.log("Node-RED v"+RED.version());
    console.log("Usage: node-red [-v] [-?] [--settings settings.js] [--userDir DIR] [flows.json]");
    console.log("");
    console.log("Options:");
    console.log("  -s, --settings FILE  use specified settings file");
    console.log("  -u, --userDir  DIR   use specified user directory");
    console.log("  -v                   enable verbose output");
    console.log("  -?, --help           show usage");
    console.log("");
    console.log("Documentation can be found at http://nodered.org");
    process.exit();
}
if (parsedArgs.argv.remain.length > 0) {
    flowFile = parsedArgs.argv.remain[0];
}

if (parsedArgs.settings) {
    // User-specified settings file
    settingsFile = parsedArgs.settings;
} else if (parsedArgs.userDir && fs.existsSync(path.join(parsedArgs.userDir,"settings.js"))) {
    // User-specified userDir that contains a settings.js
    settingsFile = path.join(parsedArgs.userDir,"settings.js");
} else {
    if (fs.existsSync(path.join(process.env.NODE_RED_HOME,".config.json"))) {
        // NODE_RED_HOME contains user data - use its settings.js
        settingsFile = path.join(process.env.NODE_RED_HOME,"settings.js");
    } else {
        var userSettingsFile = path.join(process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE,".node-red","settings.js");
        if (fs.existsSync(userSettingsFile)) {
            // $HOME/.node-red/settings.js exists
            settingsFile = userSettingsFile;
        } else {
            // Use default settings.js
            settingsFile = __dirname+"/settings.js";
        }
    }
}

try {
    var settings = require(settingsFile);
    settings.settingsFile = settingsFile;
} catch(err) {
    if (err.code == 'MODULE_NOT_FOUND') {
        console.log("Unable to load settings file: "+settingsFile);
    } else {
        console.log(err);
    }
    process.exit();
}

if (parsedArgs.v) {
    settings.verbose = true;
}

if (settings.https) {
    server = https.createServer(settings.https,function(req,res){app(req,res);});
} else {
    server = http.createServer(function(req,res){app(req,res);});
}
server.setMaxListeners(0);

function formatRoot(root) {
    if (root[0] != "/") {
        root = "/" + root;
    }
    if (root.slice(-1) != "/") {
        root = root + "/";
    }
    return root;
}

if (settings.httpRoot === false) {
    settings.httpAdminRoot = false;
    settings.httpNodeRoot = false;
} else {
    settings.httpRoot = settings.httpRoot||"/";
    settings.disableEditor = settings.disableEditor||false;
}

if (settings.httpAdminRoot !== false) {
    settings.httpAdminRoot = formatRoot(settings.httpAdminRoot || settings.httpRoot || "/");
    settings.httpAdminAuth = settings.httpAdminAuth || settings.httpAuth;
} else {
    settings.disableEditor = true;
}

if (settings.httpNodeRoot !== false) {
    settings.httpNodeRoot = formatRoot(settings.httpNodeRoot || settings.httpRoot || "/");
    settings.httpNodeAuth = settings.httpNodeAuth || settings.httpAuth;
}

settings.uiPort = settings.uiPort||1880;
settings.uiHost = settings.uiHost||"0.0.0.0";

if (flowFile) {
    settings.flowFile = flowFile;
}
if (parsedArgs.userDir) {
    settings.userDir = parsedArgs.userDir;
}

try {
    RED.init(server,settings);
} catch(err) {
    if (err.code == "not_built") {
        console.log("Node-RED has not been built. See README.md for details");
    } else {
        console.log("Failed to start server:");
        if (err.stack) {
            console.log(err.stack);
        } else {
            console.log(err);
        }
    }
    process.exit(1);
}

if (settings.httpAdminRoot !== false && settings.httpAdminAuth) {
    RED.log.warn(log._("server.httpadminauth-deprecated"));
    app.use(settings.httpAdminRoot,
        express.basicAuth(function(user, pass) {
            return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass;
        })
    );
}

if (settings.httpNodeRoot !== false && settings.httpNodeAuth) {
    app.use(settings.httpNodeRoot,
        express.basicAuth(function(user, pass) {
            return user === settings.httpNodeAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpNodeAuth.pass;
        })
    );
}

if (settings.httpAdminRoot !== false) {
    app.use(settings.httpAdminRoot, ensureAuthenticated);
    app.use(settings.httpAdminRoot, RED.httpAdmin);
}

if (settings.httpNodeRoot !== false) {
    app.use(settings.httpNodeRoot,RED.httpNode);
}
if (settings.httpStatic) {
    settings.httpStaticAuth = settings.httpStaticAuth || settings.httpAuth;
    if (settings.httpStaticAuth) {
        app.use("/",
            express.basicAuth(function(user, pass) {
                return user === settings.httpStaticAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpStaticAuth.pass;
            })
        );
    }
    app.use("/",express.static(settings.httpStatic));
}

function getListenPath() {
    var listenPath = 'http'+(settings.https?'s':'')+'://'+
                    (settings.uiHost == '0.0.0.0'?'127.0.0.1':settings.uiHost)+
                    ':'+settings.uiPort;
    if (settings.httpAdminRoot !== false) {
        listenPath += settings.httpAdminRoot;
    } else if (settings.httpStatic) {
        listenPath += "/";
    }
    return listenPath;
}

RED.start().then(function() {
    if (settings.httpAdminRoot !== false || settings.httpNodeRoot !== false || settings.httpStatic) {
        server.on('error', function(err) {
            if (err.errno === "EADDRINUSE") {
                RED.log.error(log._("server.unable-to-listen", {listenpath:getListenPath()}));
                RED.log.error(log._("server.port-in-use"));
            } else {
                RED.log.error(log._("server.uncaught-exception"));
                if (err.stack) {
                    RED.log.error(err.stack);
                } else {
                    RED.log.error(err);
                }
            }
            process.exit(1);
        });
        server.listen(settings.uiPort,settings.uiHost,function() {
            if (settings.httpAdminRoot === false) {
                RED.log.info(log._("server.admin-ui-disabled"));
            }
            process.title = 'node-red';
            RED.log.info(log._("server.now-running", {listenpath:getListenPath()}));
        });
    } else {
        RED.log.info(log._("server.headless-mode"));
    }
}).otherwise(function(err) {
    RED.log.error(log._("server.failed-to-start"));
    if (err.stack) {
        RED.log.error(err.stack);
    } else {
        RED.log.error(err);
    }
});

process.on('uncaughtException',function(err) {
    util.log('[red] Uncaught Exception:');
    if (err.stack) {
        util.log(err.stack);
    } else {
        util.log(err);
    }
    process.exit(1);
});

process.on('SIGINT', function () {
    RED.stop();
    // TODO: need to allow nodes to close asynchronously before terminating the
    // process - ie, promises
    process.exit();
});
<|endoftext|>


<commit_before>/**
 * Seedable random number generator functions.
 * @version 1.0.0
 * @license Public Domain
 *
 * @example
 * var rng = new RNG('Example');
 * rng.random(40, 50);  // =>  42
 * rng.uniform();       // =>  0.7972798995050903
 * rng.normal();        // => -0.6698504543216376
 * rng.exponential();   // =>  1.0547367609131555
 * rng.poisson(4);      // =>  2
 * rng.gamma(4);        // =>  2.781724687386858
 */

/**
 * @param {String} seed A string to seed the generator.
 * @constructor
 */
function RC4(seed) {
    this.s = new Array(256);
    this.i = 0;
    this.j = 0;
    for (var i = 0; i < 256; i++) {
        this.s[i] = i;
    }
    if (seed) {
        this.mix(seed);
    }
}

/**
 * Get the underlying bytes of a string.
 * @param {string} string
 * @returns {Array} An array of bytes
 */
RC4.getStringBytes = function(string) {
    var output = [];
    for (var i = 0; i < string.length; i++) {
        var c = string.charCodeAt(i);
        var bytes = [];
        do {
            bytes.push(c & 0xFF);
            c = c >> 8;
        } while (c > 0);
        output = output.concat(bytes.reverse());
    }
    return output;
};

RC4.prototype._swap = function(i, j) {
    var tmp = this.s[i];
    this.s[i] = this.s[j];
    this.s[j] = tmp;
};

/**
 * Mix additional entropy into this generator.
 * @param {String} seed
 */
RC4.prototype.mix = function(seed) {
    var input = RC4.getStringBytes(seed);
    var j = 0;
    for (var i = 0; i < this.s.length; i++) {
        j += this.s[i] + input[i % input.length];
        j %= 256;
        this._swap(i, j);
    }
};

/**
 * @returns {number} The next byte of output from the generator.
 */
RC4.prototype.next = function() {
    this.i = (this.i + 1) % 256;
    this.j = (this.j + this.s[this.i]) % 256;
    this._swap(this.i, this.j);
    return this.s[(this.s[this.i] + this.s[this.j]) % 256];
};

/**
 * Create a new random number generator with optional seed. If the
 * provided seed is a function (i.e. Math.random) it will be used as
 * the uniform number generator.
 * @param seed An arbitrary object used to seed the generator.
 * @constructor
 */
function RNG(seed) {
    if (seed == null) {
        seed = (Math.random() + Date.now()).toString();
    } else if (typeof seed === "function") {
        // Use it as a uniform number generator
        this.uniform = seed;
        this.nextByte = function() {
            return ~~(this.uniform() * 256);
        };
        seed = null;
    } else if (Object.prototype.toString.call(seed) !== "[object String]") {
        seed = JSON.stringify(seed);
    }
    this._normal = null;
    if (seed) {
        this._state = new RC4(seed);
    } else {
        this._state = null;
    }
}

/**
 * @returns {number} Uniform random number between 0 and 255.
 */
RNG.prototype.nextByte = function() {
    return this._state.next();
};

/**
 * @returns {number} Uniform random number between 0 and 1.
 */
RNG.prototype.uniform = function() {
    var BYTES = 7; // 56 bits to make a 53-bit double
    var output = 0;
    for (var i = 0; i < BYTES; i++) {
        output *= 256;
        output += this.nextByte();
    }
    return output / (Math.pow(2, BYTES * 8) - 1);
};

/**
 * Produce a random integer within [n, m).
 * @param {number} [n=0]
 * @param {number} m
 *
 */
RNG.prototype.random = function(n, m) {
    if (n == null) {
        return this.uniform();
    } else if (m == null) {
        m = n;
        n = 0;
    }
    return n + Math.floor(this.uniform() * (m - n));
};

/**
 * Generates numbers using this.uniform() with the Box-Muller transform.
 * @returns {number} Normally-distributed random number of mean 0, variance 1.
 */
RNG.prototype.normal = function() {
    if (this._normal !== null) {
        var n = this._normal;
        this._normal = null;
        return n;
    } else {
        var x = this.uniform() || Math.pow(2, -53); // can't be exactly 0
        var y = this.uniform();
        this._normal = Math.sqrt(-2 * Math.log(x)) * Math.sin(2 * Math.PI * y);
        return Math.sqrt(-2 * Math.log(x)) * Math.cos(2 * Math.PI * y);
    }
};

/**
 * Generates numbers using this.uniform().
 * @returns {number} Number from the exponential distribution, lambda = 1.
 */
RNG.prototype.exponential = function() {
    return -Math.log(this.uniform() || Math.pow(2, -53));
};

/**
 * Generates numbers using this.uniform() and Knuth's method.
 * @param {number} [mean=1]
 * @returns {number} Number from the Poisson distribution.
 */
RNG.prototype.poisson = function(mean) {
    var L = Math.exp(-(mean || 1));
    var k = 0, p = 1;
    do {
        k++;
        p *= this.uniform();
    } while (p > L);
    return k - 1;
};

/**
 * Generates numbers using this.uniform(), this.normal(),
 * this.exponential(), and the Marsaglia-Tsang method.
 * @param {number} a
 * @returns {number} Number from the gamma distribution.
 */
RNG.prototype.gamma = function(a) {
    var d = (a < 1 ? 1 + a : a) - 1 / 3;
    var c = 1 / Math.sqrt(9 * d);
    do {
        do {
            var x = this.normal();
            var v = Math.pow(c * x + 1, 3);
        } while (v <= 0);
        var u = this.uniform();
        var x2 = Math.pow(x, 2);
    } while (u >= 1 - 0.0331 * x2 * x2 &&
             Math.log(u) >= 0.5 * x2 + d * (1 - v + Math.log(v)));
    if (a < 1) {
        return d * v * Math.exp(this.exponential() / -a);
    } else {
        return d * v;
    }
};

/**
 * Accepts a dice rolling notation string and returns a generator
 * function for that distribution. The parser is quite flexible.
 * @param {string} expr A dice-rolling, expression i.e. '2d6+10'.
 * @param {RNG} rng An optional RNG object.
 * @returns {Function}
 */
RNG.roller = function(expr, rng) {
    var parts = expr.split(/(\d+)?d(\d+)([+-]\d+)?/).slice(1);
    var dice = parseFloat(parts[0]) || 1;
    var sides = parseFloat(parts[1]);
    var mod = parseFloat(parts[2]) || 0;
    rng = rng || new RNG();
    return function() {
        var total = dice + mod;
        for (var i = 0; i < dice; i++) {
            total += rng.random(sides);
        }
        return total;
    };
};

/* Provide a pre-made generator instance. */
RNG.$ = new RNG();
<commit_msg>Make better use of provided entropy (fixes #6).<commit_after>/**
 * Seedable random number generator functions.
 * @version 1.0.0
 * @license Public Domain
 *
 * @example
 * var rng = new RNG('Example');
 * rng.random(40, 50);  // =>  42
 * rng.uniform();       // =>  0.7972798995050903
 * rng.normal();        // => -0.6698504543216376
 * rng.exponential();   // =>  1.0547367609131555
 * rng.poisson(4);      // =>  2
 * rng.gamma(4);        // =>  2.781724687386858
 */

/**
 * @param {String} seed A string to seed the generator.
 * @constructor
 */
function RC4(seed) {
    this.s = new Array(256);
    this.i = 0;
    this.j = 0;
    for (var i = 0; i < 256; i++) {
        this.s[i] = i;
    }
    if (seed) {
        this.mix(seed);
    }
}

/**
 * Get the underlying bytes of a string.
 * @param {string} string
 * @returns {Array} An array of bytes
 */
RC4.getStringBytes = function(string) {
    var output = [];
    for (var i = 0; i < string.length; i++) {
        var c = string.charCodeAt(i);
        var bytes = [];
        do {
            bytes.push(c & 0xFF);
            c = c >> 8;
        } while (c > 0);
        output = output.concat(bytes.reverse());
    }
    return output;
};

RC4.prototype._swap = function(i, j) {
    var tmp = this.s[i];
    this.s[i] = this.s[j];
    this.s[j] = tmp;
};

/**
 * Mix additional entropy into this generator.
 * @param {String} seed
 */
RC4.prototype.mix = function(seed) {
    var input = RC4.getStringBytes(seed);
    var j = 0;
    for (var i = 0; i < this.s.length; i++) {
        j += this.s[i] + input[i % input.length];
        j %= 256;
        this._swap(i, j);
    }
};

/**
 * @returns {number} The next byte of output from the generator.
 */
RC4.prototype.next = function() {
    this.i = (this.i + 1) % 256;
    this.j = (this.j + this.s[this.i]) % 256;
    this._swap(this.i, this.j);
    return this.s[(this.s[this.i] + this.s[this.j]) % 256];
};

/**
 * Create a new random number generator with optional seed. If the
 * provided seed is a function (i.e. Math.random) it will be used as
 * the uniform number generator.
 * @param seed An arbitrary object used to seed the generator.
 * @constructor
 */
function RNG(seed) {
    if (seed == null) {
        seed = '' + Math.random() + Date.now();
    } else if (typeof seed === "function") {
        // Use it as a uniform number generator
        this.uniform = seed;
        this.nextByte = function() {
            return ~~(this.uniform() * 256);
        };
        seed = null;
    } else if (Object.prototype.toString.call(seed) !== "[object String]") {
        seed = JSON.stringify(seed);
    }
    this._normal = null;
    if (seed) {
        this._state = new RC4(seed);
    } else {
        this._state = null;
    }
}

/**
 * @returns {number} Uniform random number between 0 and 255.
 */
RNG.prototype.nextByte = function() {
    return this._state.next();
};

/**
 * @returns {number} Uniform random number between 0 and 1.
 */
RNG.prototype.uniform = function() {
    var BYTES = 7; // 56 bits to make a 53-bit double
    var output = 0;
    for (var i = 0; i < BYTES; i++) {
        output *= 256;
        output += this.nextByte();
    }
    return output / (Math.pow(2, BYTES * 8) - 1);
};

/**
 * Produce a random integer within [n, m).
 * @param {number} [n=0]
 * @param {number} m
 *
 */
RNG.prototype.random = function(n, m) {
    if (n == null) {
        return this.uniform();
    } else if (m == null) {
        m = n;
        n = 0;
    }
    return n + Math.floor(this.uniform() * (m - n));
};

/**
 * Generates numbers using this.uniform() with the Box-Muller transform.
 * @returns {number} Normally-distributed random number of mean 0, variance 1.
 */
RNG.prototype.normal = function() {
    if (this._normal !== null) {
        var n = this._normal;
        this._normal = null;
        return n;
    } else {
        var x = this.uniform() || Math.pow(2, -53); // can't be exactly 0
        var y = this.uniform();
        this._normal = Math.sqrt(-2 * Math.log(x)) * Math.sin(2 * Math.PI * y);
        return Math.sqrt(-2 * Math.log(x)) * Math.cos(2 * Math.PI * y);
    }
};

/**
 * Generates numbers using this.uniform().
 * @returns {number} Number from the exponential distribution, lambda = 1.
 */
RNG.prototype.exponential = function() {
    return -Math.log(this.uniform() || Math.pow(2, -53));
};

/**
 * Generates numbers using this.uniform() and Knuth's method.
 * @param {number} [mean=1]
 * @returns {number} Number from the Poisson distribution.
 */
RNG.prototype.poisson = function(mean) {
    var L = Math.exp(-(mean || 1));
    var k = 0, p = 1;
    do {
        k++;
        p *= this.uniform();
    } while (p > L);
    return k - 1;
};

/**
 * Generates numbers using this.uniform(), this.normal(),
 * this.exponential(), and the Marsaglia-Tsang method.
 * @param {number} a
 * @returns {number} Number from the gamma distribution.
 */
RNG.prototype.gamma = function(a) {
    var d = (a < 1 ? 1 + a : a) - 1 / 3;
    var c = 1 / Math.sqrt(9 * d);
    do {
        do {
            var x = this.normal();
            var v = Math.pow(c * x + 1, 3);
        } while (v <= 0);
        var u = this.uniform();
        var x2 = Math.pow(x, 2);
    } while (u >= 1 - 0.0331 * x2 * x2 &&
             Math.log(u) >= 0.5 * x2 + d * (1 - v + Math.log(v)));
    if (a < 1) {
        return d * v * Math.exp(this.exponential() / -a);
    } else {
        return d * v;
    }
};

/**
 * Accepts a dice rolling notation string and returns a generator
 * function for that distribution. The parser is quite flexible.
 * @param {string} expr A dice-rolling, expression i.e. '2d6+10'.
 * @param {RNG} rng An optional RNG object.
 * @returns {Function}
 */
RNG.roller = function(expr, rng) {
    var parts = expr.split(/(\d+)?d(\d+)([+-]\d+)?/).slice(1);
    var dice = parseFloat(parts[0]) || 1;
    var sides = parseFloat(parts[1]);
    var mod = parseFloat(parts[2]) || 0;
    rng = rng || new RNG();
    return function() {
        var total = dice + mod;
        for (var i = 0; i < dice; i++) {
            total += rng.random(sides);
        }
        return total;
    };
};

/* Provide a pre-made generator instance. */
RNG.$ = new RNG();
<|endoftext|>


<commit_before>RssFeed.publish('jobs', function(query) {
  var self = this;
  // We got 3 helpers:
  // 1. self.setValue
  // 2. self.addItem
  // 3. self.cdata

  // query is the parsed querystring as an object
  // eg. foo=latest would be query.foo === 'latest'

  // feed handler helpers
  // this.cdata, this.setValue, this.addItem
  self.setValue('title', self.cdata('Recent Jobs'));
  self.setValue('description', self.cdata('This is a feed of recent jobs posted to We Work Meteor.'));
  self.setValue('link', 'http://wework.meteor.com');
  self.setValue('lastBuildDate', new Date());
  self.setValue('pubDate', new Date());
  self.setValue('ttl', 1);
  // managingEditor, webMaster, language, docs, generator

  Jobs.find({}).forEach(function(job) {
    self.addItem({
      title: job.title,
      description: job.description,
      link: 'http://wework.meteor.com/jobs/'+job._id,
      company: job.company,
      location: job.location,
      companyURL: job.url,
      remote: job.remote,
      found: job.found,
      pubDate: new Date()
      // title, description, link, guid, pubDate
    });
  });
});

RssFeed.publish('experts', function(query) {
  var self = this;
  // We got 3 helpers:
  // 1. self.setValue
  // 2. self.addItem
  // 3. self.cdata

  // query is the parsed querystring as an object
  // eg. foo=latest would be query.foo === 'latest'

  // feed handler helpers
  // this.cdata, this.setValue, this.addItem
  self.setValue('title', self.cdata('Recent Experts'));
  self.setValue('description', self.cdata('This is a feed of recent experts listed on We Work Meteor.'));
  self.setValue('link', 'http://wework.meteor.com');
  self.setValue('lastBuildDate', new Date());
  self.setValue('pubDate', new Date());
  self.setValue('ttl', 1);
  // managingEditor, webMaster, language, docs, generator

  Experts.find({}).forEach(function(expert) {
    self.addItem({
      title: expert.title,
      description: expert.description,
      link: 'http://wework.meteor.com/experts/'+expert._id,
      githubURL: expert.githubUrl,
      linkedinURL: expert.linkedinUrl,
      stackoverflowURL: expert.stackoverflowUrl,
      personalURL: expert.url,
      pubDate: new Date()
      // title, description, link, guid, pubDate
    });
  });
});<commit_msg>Use createdAt for pubDate in RSS<commit_after>RssFeed.publish('jobs', function(query) {
  var self = this;
  // We got 3 helpers:
  // 1. self.setValue
  // 2. self.addItem
  // 3. self.cdata

  // query is the parsed querystring as an object
  // eg. foo=latest would be query.foo === 'latest'

  // feed handler helpers
  // this.cdata, this.setValue, this.addItem
  self.setValue('title', self.cdata('Recent Jobs'));
  self.setValue('description', self.cdata('This is a feed of recent jobs posted to We Work Meteor.'));
  self.setValue('link', 'http://wework.meteor.com');
  self.setValue('lastBuildDate', new Date());
  self.setValue('pubDate', new Date());
  self.setValue('ttl', 1);
  // managingEditor, webMaster, language, docs, generator

  Jobs.find({}).forEach(function(job) {
    self.addItem({
      title: job.title,
      description: job.description,
      link: 'http://wework.meteor.com/jobs/'+job._id,
      company: job.company,
      location: job.location,
      companyURL: job.url,
      remote: job.remote,
      found: job.found,
      pubDate: job.createdAt
      // title, description, link, guid, pubDate
    });
  });
});

RssFeed.publish('experts', function(query) {
  var self = this;
  // We got 3 helpers:
  // 1. self.setValue
  // 2. self.addItem
  // 3. self.cdata

  // query is the parsed querystring as an object
  // eg. foo=latest would be query.foo === 'latest'

  // feed handler helpers
  // this.cdata, this.setValue, this.addItem
  self.setValue('title', self.cdata('Recent Experts'));
  self.setValue('description', self.cdata('This is a feed of recent experts listed on We Work Meteor.'));
  self.setValue('link', 'http://wework.meteor.com');
  self.setValue('lastBuildDate', new Date());
  self.setValue('pubDate', new Date());
  self.setValue('ttl', 1);
  // managingEditor, webMaster, language, docs, generator

  Experts.find({}).forEach(function(expert) {
    self.addItem({
      title: expert.title,
      description: expert.description,
      link: 'http://wework.meteor.com/experts/'+expert._id,
      githubURL: expert.githubUrl,
      linkedinURL: expert.linkedinUrl,
      stackoverflowURL: expert.stackoverflowUrl,
      personalURL: expert.url,
      pubDate: expert.createdAt
      // title, description, link, guid, pubDate
    });
  });
});<|endoftext|>


<commit_before>var fs = require('fs');
var pdf = require('html-pdf');
var request = require('request');
var options = { format: 'Letter' };

request('http://google.com/', function (error, response, body) {
    if (!error && response.statusCode == 200) {
    	pdf.create(html, options).toFile('./businesscard.pdf', function(err, res) {
			if (err) return console.log(err);
		  		console.log(res);
		});
    }
});

<commit_msg>Server<commit_after>var fs = require('fs');
var pdf = require('html-pdf');
var request = require('request');
var options = { format: 'Letter' };

request('http://google.com/', function (error, response, body) {
    if (!error && response.statusCode == 200) {
    	pdf.create(body, options).toFile('./businesscard.pdf', function(err, res) {
			if (err) return console.log(err);
		  		console.log(res);
		});
    }
});

<|endoftext|>


<commit_before>"use strict";

var fs = require("fs"),
    configFilename = process.argv[2] || "config",
    config = JSON.parse(fs.readFileSync(configFilename).toString()),
    enableVerbose = "-verbose" === process.argv[3],
    verbose,
    filters = [],
    extractorPromises = [],
    storageContext,
    storage;

if (enableVerbose) {
    verbose = console.log.bind(console);
} else {
    verbose = function () {};
}

function recordExtracted (uid, record) {
    var idx = 0;
    function loop () {
        filters[idx](record)
            .then (function (newRecord) {
                if (newRecord) {
                    record = newRecord;
                    if (++idx < filters.length) {
                        loop();
                    } else {
                        storage.set(uid, record, false).then(resolve);
                    }
                } else {
                    resolve();
                }

            }, function (reason) {
                console.error(reason);
            });
    }
    if (filters.length) {
        loop();
    }
    // For now, no need to wait
    return Promise.resolve();
}

verbose("Processing filters...");
config.filters.forEach(function (config) {
    var filterModule = require("./filters/" + config.type + ".js");
    filters.push(filterModule.filter.bind({}, config));
});

verbose("Opening storage...");
storageContext = {};
storage = require("./storage/" + config.storage.type + ".js");
storage.open.call(storageContext, config.storage)
    .then(function () {
        verbose("Running extractors...");
        config.extractors.forEach(function (config) {
            var extractorModule = require("./extractors/" + config.type + ".js");
            extractorPromises.push(extractorModule.start.call({}, config, recordExtracted));
        });

        Promise.all(extractorPromises)
            .then(function (statuses) {
                verbose("end.");
                storage.close.call(storageContext);
            });
    });

<commit_msg>Better end synchronization<commit_after>"use strict";

var fs = require("fs"),
    configFilename = process.argv[2] || "config",
    config = JSON.parse(fs.readFileSync(configFilename).toString()),
    enableVerbose = "-verbose" === process.argv[3],
    verbose,
    filters = [],
    extractorPromises = [],
    storageContext,
    storage,
    pendingExtractions = 0,
    extractionPromise,
    extractionDone;

if (enableVerbose) {
    verbose = console.log.bind(console);
} else {
    verbose = function () {};
}

function recordExtracted (record) {
    var idx = 0;
    ++pendingExtractions;

    function done () {
        if (0 === --pendingExtractions && extractionDone) {
            extractionDone();
        }
    }

    function loop () {
        filters[idx](record)
            .then(function (newRecord) {
                if (newRecord) {
                    record = newRecord;
                    if (++idx < filters.length) {
                        loop();
                    } else {
                        storage.add.call(storageContext, config.storage, record, false).then(done);
                    }
                } else {
                    done();
                }

            }, function (reason) {
                console.error(reason);
                done();
            });
    }
    if (filters.length) {
        loop();
    }
    // For now, no need to wait
    return Promise.resolve();
}

verbose("Processing filters...");
config.filters.forEach(function (filterConfig) {
    var filterModule = require("./filters/" + filterConfig.type + ".js");
    filters.push(filterModule.filter.bind({}, filterConfig));
});

verbose("Opening storage...");
storageContext = {};
storage = require("./storage/" + config.storage.type + ".js");
storage.open.call(storageContext, config.storage)
    .then(function () {

        verbose("Running extractors...");
        config.extractors.forEach(function (extractorConfig) {
            var extractorModule = require("./extractors/" + extractorConfig.type + ".js");
            extractorPromises.push(extractorModule.start.call({}, extractorConfig, recordExtracted));
        });

        Promise.all(extractorPromises)
            .then(function (/*statuses*/) {
                verbose("end of extractors, waiting for pending extractions...");
                extractionPromise = new Promise(function (resolve) {
                    extractionDone = resolve;
                });
                return extractionPromise;
            })
            .then(function () {
                verbose("end of extraction, waiting for storage closing...");
                return storage.close.call(storageContext);
            })
            .then(function () {
                verbose("end.");
            });
    });
<|endoftext|>


<commit_before>window.addEventListener('load',function(){
  // safari violates mixed content spec, so no app
  if(!bowser.safari){
    var btn = document.querySelector('[data-client="app"]')
    if(btn) btn.style.display='inline-block'
  }
  // ext only on chrome
  var desktop = (bowser.mac || bowser.linux || bowser.windows || bowser.chromeos)
  if(bowser.chrome && desktop){
    var btn = document.querySelector('[data-client="ext"]')
    if(btn) btn.style.display='inline-block'
  }
})

SecureLogin = function(cb, flow, scope){
  function toQuery(obj){
    return Object.keys(obj).reduce(function(a,k){a.push(encodeURIComponent(k)+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
  }

  var opts = {}

  if(SecureLogin.pubkey) opts.pubkey = SecureLogin.pubkey
  if(scope) opts.scope = toQuery(scope)

  var query = toQuery(opts)
  web_origin = location.host == 'c.dev' ? 'http://securelogin.dev' : 'https://securelogin.pw'
  localStorage.securelogin = flow
  ext_origin = 'chrome-extension://abpigncghjblhknbbannlhmgjpjpbajj'

  if(flow=='app'){
    // we are using a sane browser, let's open direct WS to localhost
    location = 'securelogin://'
    var start_interval = new Date
    sl_interval = setInterval(function(){
      var x=new WebSocket('ws://127.0.0.1:3101')

      x.onmessage=function(e){
        console.log(e.data)
        x.send('{"data":"close"}')
        x.close()
        cb(e.data);
        cb=function(str){ console.log('replay') }
      }

      x.onopen=function(){
        x.send(JSON.stringify({data: query}))
        clearInterval(sl_interval)
      }

      if(new Date - start_interval > 3000){
        //alert("Please make sure SecureLogin app is running")
        clearInterval(sl_interval)

        if(bowser.android) location = "https://play.google.com/store/apps/details?id=pw.securelogin"
        if(bowser.mac) location = "https://securelogin.pw/apps/SecureLogin-1.0.0.dmg"
        if(bowser.windows) location = "https://securelogin.pw/apps/SecureLogin Setup 1.0.0.exe"
      }
    },200)
  }else{
    //ext needs /index.html part
    if(flow=='web'){
      var origin = web_origin
      w = window.open(origin)
    }else{
      var origin = ext_origin
      w = window.open(ext_origin + '/index.html')
      // no extension? go to install page
      var loadext = setTimeout(function(){
        w.location = "https://chrome.google.com/webstore/detail/securelogin/abpigncghjblhknbbannlhmgjpjpbajj"
      },500)
    }

    window.addEventListener('message', function msgListener(e){
      if(e.origin == origin){
        if(e.data == 'ping'){
          if(flow=='ext') clearInterval(loadext)

          e.source.postMessage(query, origin)
        }else{
          cb(e.data)
          window.removeEventListener('message', msgListener)
          w.close()
        }
      }
    })
  }
  return false
}<commit_msg>Cleanup sdk.js<commit_after>/* globals bowser, SecureLogin */

window.addEventListener('load', function () {
  // safari violates mixed content spec, so no app
  if (!bowser.safari) {
    var appBtn = document.querySelector('[data-client="app"]')
    if (appBtn) appBtn.style.display = 'inline-block'
  }
  // ext only on chrome
  var desktop = (bowser.mac || bowser.linux || bowser.windows || bowser.chromeos)
  if (bowser.chrome && desktop) {
    var extBtn = document.querySelector('[data-client="ext"]')
    if (extBtn) extBtn.style.display = 'inline-block'
  }
})

window.SecureLogin = function (cb, flow, scope) {
  function toQuery (obj) {
    return Object.keys(obj).reduce(function (a, k) {
      a.push(encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]))
      return a
    }, []).join('&')
  }

  var opts = {}

  if (SecureLogin.pubkey) opts.pubkey = SecureLogin.pubkey
  if (scope) opts.scope = toQuery(scope)

  var query = toQuery(opts)
  var webOrigin = window.location.host === 'c.dev' ? 'http://securelogin.dev' : 'https://securelogin.pw'
  var extOrigin = 'chrome-extension://abpigncghjblhknbbannlhmgjpjpbajj'

  window.localStorage.securelogin = flow

  if (flow === 'app') {
    // we are using a sane browser, let's open direct WS to localhost
    window.location = 'securelogin://'
    var startInterval = new Date()
    var slInterval = setInterval(function () {
      var x = new window.WebSocket('ws://127.0.0.1:3101')

      x.onmessage = function (e) {
        console.log(e.data)
        x.send('{"data":"close"}')
        x.close()
        cb(e.data)
        cb = function (str) {
          console.log('replay')
        }
      }

      x.onopen = function () {
        x.send(JSON.stringify({
          data: query
        }))
        clearInterval(slInterval)
      }

      if (new Date() - startInterval > 3000) {
        // alert("Please make sure SecureLogin app is running")
        clearInterval(slInterval)

        if (bowser.android) window.location = 'https://play.google.com/store/apps/details?id=pw.securelogin'
        if (bowser.mac) window.location = 'https://securelogin.pw/apps/SecureLogin-1.0.0.dmg'
        if (bowser.windows) window.location = 'https://securelogin.pw/apps/SecureLogin Setup 1.0.0.exe'
      }
    }, 200)
  } else {
    var origin = ''

    // ext needs /index.html part
    if (flow === 'web') {
      origin = webOrigin
      window.w = window.open(webOrigin)
    } else {
      origin = extOrigin
      window.w = window.open(extOrigin + '/index.html')
      // no extension? go to install page
      var loadext = setTimeout(function () {
        window.w.location = 'https://chrome.google.com/webstore/detail/securelogin/abpigncghjblhknbbannlhmgjpjpbajj'
      }, 500)
    }

    window.addEventListener('message', function msgListener (e) {
      if (e.origin === origin) {
        if (e.data === 'ping') {
          if (flow === 'ext') clearInterval(loadext)

          e.source.postMessage(query, origin)
        } else {
          cb(e.data)
          window.removeEventListener('message', msgListener)
          window.w.close()
        }
      }
    })
  }

  return false
}
<|endoftext|>


<commit_before>const { resolve } = require('path');
const { readFileSync } = require('fs');

const pathIsInside = require('path-is-inside');
const findRoot = require('find-root');

const PROPKEY_ESNEXT = 'esnext';
const sourceDirectory = resolve(__dirname, '../src');
const nodeModuleDirectory = resolve(__dirname, '../node_modules');

module.exports = {
  entry: resolve(sourceDirectory, 'index.js'),
  output: {
    path: resolve(__dirname, '../dist'),
    filename: '<%= initialComponentName %>.bundle.js'
  },
  resolve: {
    mainFields: [PROPKEY_ESNEXT, 'browser', 'module', 'main']
  },
  module: {
    rules: [
      {
        test: /\.m?js$/,
        include: (filepath) => {
          return pathIsInside(filepath, sourceDirectory) ||
            (pathIsInside(filepath, nodeModuleDirectory) &&
            hasPkgEsnext(filepath));
        },
        use: {
          loader: 'babel-loader',
          options: {
            babelrc: false,
            presets: [
              ['env', {
                targets: {
                  browsers: [
                    'last 2 versions',
                    'ie 11'
                  ]
                }
              }]
            ],
            plugins: [
              ['transform-react-jsx', {
                pragma: 'h'
              }]
            ]
          }
        }
      },
      {
        test: /\.scss$/,
        use: [
          'raw-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(yml|yaml)$/,
        include: resolve(__dirname, '../translations'),
        use: [
          'json-loader',
          'yaml-loader'
        ]
      }
    ]
  }
};

/**
 * Find package.json for file at `filepath`.
 * Return `true` if it has a property whose key is `PROPKEY_ESNEXT`.
 */
function hasPkgEsnext(filepath) {
  const pkgRoot = findRoot(filepath);
  const packageJsonPath = resolve(pkgRoot, 'package.json');
  const packageJsonText = readFileSync(packageJsonPath, {encoding: 'utf-8'});
  const packageJson = JSON.parse(packageJsonText);

  return {}.hasOwnProperty.call(packageJson, PROPKEY_ESNEXT);
}
<commit_msg>fix "exports is not defined" error<commit_after>const { resolve } = require('path');
const { readFileSync } = require('fs');

const pathIsInside = require('path-is-inside');
const findRoot = require('find-root');

const PROPKEY_ESNEXT = 'esnext';
const sourceDirectory = resolve(__dirname, '../src');
const nodeModuleDirectory = resolve(__dirname, '../node_modules');

module.exports = {
  entry: resolve(sourceDirectory, 'index.js'),
  output: {
    path: resolve(__dirname, '../dist'),
    filename: '<%= initialComponentName %>.bundle.js'
  },
  resolve: {
    mainFields: [PROPKEY_ESNEXT, 'browser', 'module', 'main']
  },
  module: {
    rules: [
      {
        test: /\.m?js$/,
        include: (filepath) => {
          return pathIsInside(filepath, sourceDirectory) ||
            (pathIsInside(filepath, nodeModuleDirectory) &&
            hasPkgEsnext(filepath));
        },
        use: {
          loader: 'babel-loader',
          options: {
            babelrc: false,
            presets: [
              ['env', {
                modules: false,
                targets: {
                  browsers: [
                    'last 2 versions',
                    'ie 11'
                  ]
                }
              }]
            ],
            plugins: [
              ['transform-react-jsx', {
                pragma: 'h'
              }]
            ]
          }
        }
      },
      {
        test: /\.scss$/,
        use: [
          'raw-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(yml|yaml)$/,
        include: resolve(__dirname, '../translations'),
        use: [
          'json-loader',
          'yaml-loader'
        ]
      }
    ]
  }
};

/**
 * Find package.json for file at `filepath`.
 * Return `true` if it has a property whose key is `PROPKEY_ESNEXT`.
 */
function hasPkgEsnext(filepath) {
  const pkgRoot = findRoot(filepath);
  const packageJsonPath = resolve(pkgRoot, 'package.json');
  const packageJsonText = readFileSync(packageJsonPath, {encoding: 'utf-8'});
  const packageJson = JSON.parse(packageJsonText);

  return {}.hasOwnProperty.call(packageJson, PROPKEY_ESNEXT);
}
<|endoftext|>


<commit_before>import { expect } from 'chai';
import { createAction } from 'redux-actions';
import Immutable from 'seamless-immutable';

import {
  cancelReservationEdit,
  changeAdminReservationsFilters,
  clearReservations,
  closeReservationCancelModal,
  selectReservationToCancel,
  selectReservationToEdit,
  selectReservationToShow,
  closeReservationInfoModal,
  toggleTimeSlot,
} from 'actions/uiActions';
import types from 'constants/ActionTypes';
import Reservation from 'fixtures/Reservation';
import reservationsReducer from 'reducers/reservationsReducer';
import { getTimeSlots } from 'utils/TimeUtils';

describe('Reducer: reservationsReducer', () => {
  describe('initial state', () => {
    const initialState = reservationsReducer(undefined, {});

    describe('adminReservationsFilters', () => {
      it('should be an object', () => {
        expect(typeof initialState.adminReservationsFilters).to.equal('object');
      });

      it('state should be "all"', () => {
        expect(initialState.adminReservationsFilters.state).to.equal('all');
      });
    });

    it('selected should be an empty array', () => {
      expect(initialState.selected).to.deep.equal([]);
    });

    it('toCancel should be an empty array', () => {
      expect(initialState.toCancel).to.deep.equal([]);
    });

    it('toEdit should be an empty array', () => {
      expect(initialState.toEdit).to.deep.equal([]);
    });

    it('toShow should be an empty array', () => {
      expect(initialState.toShow).to.deep.equal([]);
    });
  });

  describe('handling actions', () => {
    describe('API.RESERVATION_POST_SUCCESS', () => {
      const postReservationSuccess = createAction(types.API.RESERVATION_POST_SUCCESS);

      it('should clear selected', () => {
        const action = postReservationSuccess();
        const initialState = Immutable({
          selected: ['some-selected'],
          toShow: [],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.selected).to.deep.equal([]);
      });

      it('should clear the toEdit', () => {
        const action = postReservationSuccess();
        const initialState = Immutable({
          toEdit: ['something-to-edit'],
          toShow: [],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.toEdit).to.deep.equal([]);
      });

      it('should add the given reservation to toShow', () => {
        const initialState = Immutable({
          toShow: [],
        });
        const reservation = Reservation.build();
        const action = postReservationSuccess(reservation);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toShow).to.deep.equal(expected);
      });

      it('should not affect other reservations in toShow', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          toShow: [reservations[0]],
        });
        const action = postReservationSuccess(reservations[1]);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[0], reservations[1]]);

        expect(nextState.toShow).to.deep.equal(expected);
      });
    });

    describe('API.RESERVATION_PUT_SUCCESS', () => {
      const putReservationSuccess = createAction(types.API.RESERVATION_PUT_SUCCESS);

      it('should clear selected', () => {
        const action = putReservationSuccess();
        const initialState = Immutable({
          selected: ['some-selected'],
          toShow: [],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.selected).to.deep.equal([]);
      });

      it('should clear the toEdit', () => {
        const action = putReservationSuccess();
        const initialState = Immutable({
          toEdit: ['something-to-edit'],
          toShow: [],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.toEdit).to.deep.equal([]);
      });

      it('should add the given reservation to toShow', () => {
        const initialState = Immutable({
          toShow: [],
        });
        const reservation = Reservation.build();
        const action = putReservationSuccess(reservation);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toShow).to.deep.equal(expected);
      });

      it('should not affect other reservations in toShow', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          toShow: [reservations[0]],
        });
        const action = putReservationSuccess(reservations[1]);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[0], reservations[1]]);

        expect(nextState.toShow).to.deep.equal(expected);
      });
    });

    describe('UI.CANCEL_RESERVATION_EDIT', () => {
      it('should clear toEdit array', () => {
        const initialState = Immutable({
          toEdit: [Reservation.build()],
        });
        const action = cancelReservationEdit();
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.toEdit).to.deep.equal([]);
      });
    });

    describe('UI.CHANGE_ADMIN_RESERVATIONS_FILTERS', () => {
      it('should set the given filters to adminReservationsFilters', () => {
        const adminReservationsFilters = { state: 'some-state' };
        const action = changeAdminReservationsFilters(adminReservationsFilters);
        const initialState = Immutable({
          adminReservationsFilters: {},
        });
        const expected = Immutable(adminReservationsFilters);
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.adminReservationsFilters).to.deep.equal(expected);
      });

      it('should override previous values of same adminReservationsFilters', () => {
        const adminReservationsFilters = { state: 'some-state' };
        const action = changeAdminReservationsFilters(adminReservationsFilters);
        const initialState = Immutable({
          adminReservationsFilters: { state: 'old-value' },
        });
        const expected = Immutable(adminReservationsFilters);
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.adminReservationsFilters).to.deep.equal(expected);
      });

      it('should not override unspecified adminReservationsFilters', () => {
        const adminReservationsFilters = { state: 'some-state' };
        const action = changeAdminReservationsFilters(adminReservationsFilters);
        const initialState = Immutable({
          adminReservationsFilters: { otherFilter: 'other-value' },
        });
        const expected = Immutable({
          otherFilter: 'other-value',
          state: 'some-state',
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.adminReservationsFilters).to.deep.equal(expected);
      });
    });

    describe('UI.CLEAR_RESERVATIONS', () => {
      it('should set the given date to date', () => {
        const resetedState = reservationsReducer(undefined, {});
        const action = clearReservations();
        const initialState = Immutable({
          date: '2015-11-11',
          selected: ['something'],
          toCancel: ['something'],
          toEdit: ['something'],
          toShow: ['something'],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState).to.deep.equal(resetedState);
      });
    });

    describe('UI.CLOSE_MODAL', () => {
      describe('if closed modal is RESERVATION_CANCEL modal', () => {
        it('should clear toCancel array', () => {
          const initialState = Immutable({
            toCancel: [Reservation.build()],
          });
          const action = closeReservationCancelModal();
          const nextState = reservationsReducer(initialState, action);

          expect(nextState.toCancel).to.deep.equal([]);
        });
      });

      describe('if closed modal is SHOW_RESERVATION modal', () => {
        it('should clear toShow array', () => {
          const initialState = Immutable({
            toShow: [Reservation.build()],
          });
          const action = closeReservationInfoModal();
          const nextState = reservationsReducer(initialState, action);

          expect(nextState.toShow).to.deep.equal([]);
        });
      });
    });

    describe('UI.SELECT_RESERVATION_TO_CANCEL', () => {
      it('should add the given reservation to toCancel', () => {
        const initialState = Immutable({
          toCancel: [],
        });
        const reservation = Reservation.build();
        const action = selectReservationToCancel(reservation);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toCancel).to.deep.equal(expected);
      });

      it('should not affect other reservations in toCancel', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          toCancel: [reservations[0]],
        });
        const action = selectReservationToCancel(reservations[1]);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[0], reservations[1]]);

        expect(nextState.toCancel).to.deep.equal(expected);
      });
    });

    describe('UI.SELECT_RESERVATION_TO_EDIT', () => {
      it('should set the given reservation to toEdit', () => {
        const initialState = Immutable({
          selected: [],
          toEdit: [],
        });
        const reservation = Reservation.build();
        const action = selectReservationToEdit({ reservation });
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toEdit).to.deep.equal(expected);
      });

      it('should remove other reservations in toEdit', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          selected: [],
          toEdit: [reservations[0]],
        });
        const action = selectReservationToEdit({ reservation: reservations[1] });
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[1]]);

        expect(nextState.toEdit).to.deep.equal(expected);
      });

      it('should split the given reservation to slots and add to selected', () => {
        const begin = '2015-10-09T08:00:00+03:00';
        const end = '2015-10-09T10:00:00+03:00';
        const minPeriod = '00:30:00';
        const reservation = Reservation.build({ begin, end });
        const initialState = Immutable({
          selected: [],
          toEdit: [],
        });
        const action = selectReservationToEdit({ reservation, minPeriod });
        const nextState = reservationsReducer(initialState, action);
        const slots = getTimeSlots(reservation.begin, reservation.end, minPeriod);
        const expected = slots.map((slot) => slot.asISOString);

        expect(nextState.selected).to.deep.equal(expected);
      });
    });

    describe('UI.SELECT_RESERVATION_TO_SHOW', () => {
      it('should add the given reservation to toShow', () => {
        const initialState = Immutable({
          toShow: [],
        });
        const reservation = Reservation.build();
        const action = selectReservationToShow(reservation);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toShow).to.deep.equal(expected);
      });

      it('should not affect other reservations in toShow', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          toShow: [reservations[0]],
        });
        const action = selectReservationToShow(reservations[1]);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[0], reservations[1]]);

        expect(nextState.toShow).to.deep.equal(expected);
      });
    });

    describe('UI.TOGGLE_TIME_SLOT', () => {
      describe('if slot is not already selected', () => {
        it('should add the given slot to selected', () => {
          const initialState = Immutable({
            selected: [],
          });
          const slot = '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z';
          const action = toggleTimeSlot(slot);
          const nextState = reservationsReducer(initialState, action);
          const expected = Immutable([slot]);

          expect(nextState.selected).to.deep.equal(expected);
        });

        it('should not affect other selected slots ', () => {
          const initialState = Immutable({
            selected: ['2015-12-12T10:00:00Z/2015-12-12T11:00:00Z'],
          });
          const slot = '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z';
          const action = toggleTimeSlot(slot);
          const nextState = reservationsReducer(initialState, action);
          const expected = Immutable([...initialState.selected, slot]);

          expect(nextState.selected).to.deep.equal(expected);
        });
      });

      describe('if slot is already selected', () => {
        it('should remove the given slot from selected', () => {
          const slot = '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z';
          const action = toggleTimeSlot(slot);
          const initialState = Immutable({
            selected: ['2015-10-11T10:00:00Z/2015-10-11T11:00:00Z'],
          });
          const nextState = reservationsReducer(initialState, action);
          const expected = Immutable([]);

          expect(nextState.selected).to.deep.equal(expected);
        });

        it('should not affect other selected slots ', () => {
          const slot = '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z';
          const action = toggleTimeSlot(slot);
          const initialState = Immutable({
            selected: [
              '2015-12-12T10:00:00Z/2015-12-12T11:00:00Z',
              '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z',
            ],
          });
          const nextState = reservationsReducer(initialState, action);
          const expected = Immutable([initialState.selected[0]]);

          expect(nextState.selected).to.deep.equal(expected);
        });
      });
    });
  });
});
<commit_msg>Improve code coverage sligthly<commit_after>import { expect } from 'chai';
import { createAction } from 'redux-actions';
import Immutable from 'seamless-immutable';

import {
  cancelReservationEdit,
  changeAdminReservationsFilters,
  clearReservations,
  closeReservationCancelModal,
  closeReservationInfoModal,
  closeReservationSuccessModal,
  selectReservationToCancel,
  selectReservationToEdit,
  selectReservationToShow,
  toggleTimeSlot,
} from 'actions/uiActions';
import types from 'constants/ActionTypes';
import Reservation from 'fixtures/Reservation';
import reservationsReducer from 'reducers/reservationsReducer';
import { getTimeSlots } from 'utils/TimeUtils';

describe('Reducer: reservationsReducer', () => {
  describe('initial state', () => {
    const initialState = reservationsReducer(undefined, {});

    describe('adminReservationsFilters', () => {
      it('should be an object', () => {
        expect(typeof initialState.adminReservationsFilters).to.equal('object');
      });

      it('state should be "all"', () => {
        expect(initialState.adminReservationsFilters.state).to.equal('all');
      });
    });

    it('selected should be an empty array', () => {
      expect(initialState.selected).to.deep.equal([]);
    });

    it('toCancel should be an empty array', () => {
      expect(initialState.toCancel).to.deep.equal([]);
    });

    it('toEdit should be an empty array', () => {
      expect(initialState.toEdit).to.deep.equal([]);
    });

    it('toShow should be an empty array', () => {
      expect(initialState.toShow).to.deep.equal([]);
    });
  });

  describe('handling actions', () => {
    describe('API.RESERVATION_POST_SUCCESS', () => {
      const postReservationSuccess = createAction(types.API.RESERVATION_POST_SUCCESS);

      it('should clear selected', () => {
        const action = postReservationSuccess();
        const initialState = Immutable({
          selected: ['some-selected'],
          toShow: [],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.selected).to.deep.equal([]);
      });

      it('should clear the toEdit', () => {
        const action = postReservationSuccess();
        const initialState = Immutable({
          toEdit: ['something-to-edit'],
          toShow: [],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.toEdit).to.deep.equal([]);
      });

      it('should add the given reservation to toShow', () => {
        const initialState = Immutable({
          toShow: [],
        });
        const reservation = Reservation.build();
        const action = postReservationSuccess(reservation);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toShow).to.deep.equal(expected);
      });

      it('should not affect other reservations in toShow', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          toShow: [reservations[0]],
        });
        const action = postReservationSuccess(reservations[1]);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[0], reservations[1]]);

        expect(nextState.toShow).to.deep.equal(expected);
      });
    });

    describe('API.RESERVATION_PUT_SUCCESS', () => {
      const putReservationSuccess = createAction(types.API.RESERVATION_PUT_SUCCESS);

      it('should clear selected', () => {
        const action = putReservationSuccess();
        const initialState = Immutable({
          selected: ['some-selected'],
          toShow: [],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.selected).to.deep.equal([]);
      });

      it('should clear the toEdit', () => {
        const action = putReservationSuccess();
        const initialState = Immutable({
          toEdit: ['something-to-edit'],
          toShow: [],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.toEdit).to.deep.equal([]);
      });

      it('should add the given reservation to toShow', () => {
        const initialState = Immutable({
          toShow: [],
        });
        const reservation = Reservation.build();
        const action = putReservationSuccess(reservation);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toShow).to.deep.equal(expected);
      });

      it('should not affect other reservations in toShow', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          toShow: [reservations[0]],
        });
        const action = putReservationSuccess(reservations[1]);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[0], reservations[1]]);

        expect(nextState.toShow).to.deep.equal(expected);
      });
    });

    describe('UI.CANCEL_RESERVATION_EDIT', () => {
      it('should clear toEdit array', () => {
        const initialState = Immutable({
          toEdit: [Reservation.build()],
        });
        const action = cancelReservationEdit();
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.toEdit).to.deep.equal([]);
      });
    });

    describe('UI.CHANGE_ADMIN_RESERVATIONS_FILTERS', () => {
      it('should set the given filters to adminReservationsFilters', () => {
        const adminReservationsFilters = { state: 'some-state' };
        const action = changeAdminReservationsFilters(adminReservationsFilters);
        const initialState = Immutable({
          adminReservationsFilters: {},
        });
        const expected = Immutable(adminReservationsFilters);
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.adminReservationsFilters).to.deep.equal(expected);
      });

      it('should override previous values of same adminReservationsFilters', () => {
        const adminReservationsFilters = { state: 'some-state' };
        const action = changeAdminReservationsFilters(adminReservationsFilters);
        const initialState = Immutable({
          adminReservationsFilters: { state: 'old-value' },
        });
        const expected = Immutable(adminReservationsFilters);
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.adminReservationsFilters).to.deep.equal(expected);
      });

      it('should not override unspecified adminReservationsFilters', () => {
        const adminReservationsFilters = { state: 'some-state' };
        const action = changeAdminReservationsFilters(adminReservationsFilters);
        const initialState = Immutable({
          adminReservationsFilters: { otherFilter: 'other-value' },
        });
        const expected = Immutable({
          otherFilter: 'other-value',
          state: 'some-state',
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState.adminReservationsFilters).to.deep.equal(expected);
      });
    });

    describe('UI.CLEAR_RESERVATIONS', () => {
      it('should set the given date to date', () => {
        const resetedState = reservationsReducer(undefined, {});
        const action = clearReservations();
        const initialState = Immutable({
          date: '2015-11-11',
          selected: ['something'],
          toCancel: ['something'],
          toEdit: ['something'],
          toShow: ['something'],
        });
        const nextState = reservationsReducer(initialState, action);

        expect(nextState).to.deep.equal(resetedState);
      });
    });

    describe('UI.CLOSE_MODAL', () => {
      describe('if closed modal is RESERVATION_CANCEL modal', () => {
        it('should clear toCancel array', () => {
          const initialState = Immutable({
            toCancel: [Reservation.build()],
          });
          const action = closeReservationCancelModal();
          const nextState = reservationsReducer(initialState, action);

          expect(nextState.toCancel).to.deep.equal([]);
        });
      });

      describe('if closed modal is RESERVATION_INFO modal', () => {
        it('should clear toShow array', () => {
          const initialState = Immutable({
            toShow: [Reservation.build()],
          });
          const action = closeReservationInfoModal();
          const nextState = reservationsReducer(initialState, action);

          expect(nextState.toShow).to.deep.equal([]);
        });
      });

      describe('if closed modal is RESERVATION_SUCCESS modal', () => {
        it('should clear toShow array', () => {
          const initialState = Immutable({
            toShow: [Reservation.build()],
          });
          const action = closeReservationSuccessModal();
          const nextState = reservationsReducer(initialState, action);

          expect(nextState.toShow).to.deep.equal([]);
        });
      });
    });

    describe('UI.SELECT_RESERVATION_TO_CANCEL', () => {
      it('should add the given reservation to toCancel', () => {
        const initialState = Immutable({
          toCancel: [],
        });
        const reservation = Reservation.build();
        const action = selectReservationToCancel(reservation);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toCancel).to.deep.equal(expected);
      });

      it('should not affect other reservations in toCancel', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          toCancel: [reservations[0]],
        });
        const action = selectReservationToCancel(reservations[1]);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[0], reservations[1]]);

        expect(nextState.toCancel).to.deep.equal(expected);
      });
    });

    describe('UI.SELECT_RESERVATION_TO_EDIT', () => {
      it('should set the given reservation to toEdit', () => {
        const initialState = Immutable({
          selected: [],
          toEdit: [],
        });
        const reservation = Reservation.build();
        const action = selectReservationToEdit({ reservation });
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toEdit).to.deep.equal(expected);
      });

      it('should remove other reservations in toEdit', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          selected: [],
          toEdit: [reservations[0]],
        });
        const action = selectReservationToEdit({ reservation: reservations[1] });
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[1]]);

        expect(nextState.toEdit).to.deep.equal(expected);
      });

      it('should split the given reservation to slots and add to selected', () => {
        const begin = '2015-10-09T08:00:00+03:00';
        const end = '2015-10-09T10:00:00+03:00';
        const minPeriod = '00:30:00';
        const reservation = Reservation.build({ begin, end });
        const initialState = Immutable({
          selected: [],
          toEdit: [],
        });
        const action = selectReservationToEdit({ reservation, minPeriod });
        const nextState = reservationsReducer(initialState, action);
        const slots = getTimeSlots(reservation.begin, reservation.end, minPeriod);
        const expected = slots.map((slot) => slot.asISOString);

        expect(nextState.selected).to.deep.equal(expected);
      });
    });

    describe('UI.SELECT_RESERVATION_TO_SHOW', () => {
      it('should add the given reservation to toShow', () => {
        const initialState = Immutable({
          toShow: [],
        });
        const reservation = Reservation.build();
        const action = selectReservationToShow(reservation);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservation]);

        expect(nextState.toShow).to.deep.equal(expected);
      });

      it('should not affect other reservations in toShow', () => {
        const reservations = [
          Reservation.build(),
          Reservation.build(),
        ];
        const initialState = Immutable({
          toShow: [reservations[0]],
        });
        const action = selectReservationToShow(reservations[1]);
        const nextState = reservationsReducer(initialState, action);
        const expected = Immutable([reservations[0], reservations[1]]);

        expect(nextState.toShow).to.deep.equal(expected);
      });
    });

    describe('UI.TOGGLE_TIME_SLOT', () => {
      describe('if slot is not already selected', () => {
        it('should add the given slot to selected', () => {
          const initialState = Immutable({
            selected: [],
          });
          const slot = '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z';
          const action = toggleTimeSlot(slot);
          const nextState = reservationsReducer(initialState, action);
          const expected = Immutable([slot]);

          expect(nextState.selected).to.deep.equal(expected);
        });

        it('should not affect other selected slots ', () => {
          const initialState = Immutable({
            selected: ['2015-12-12T10:00:00Z/2015-12-12T11:00:00Z'],
          });
          const slot = '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z';
          const action = toggleTimeSlot(slot);
          const nextState = reservationsReducer(initialState, action);
          const expected = Immutable([...initialState.selected, slot]);

          expect(nextState.selected).to.deep.equal(expected);
        });
      });

      describe('if slot is already selected', () => {
        it('should remove the given slot from selected', () => {
          const slot = '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z';
          const action = toggleTimeSlot(slot);
          const initialState = Immutable({
            selected: ['2015-10-11T10:00:00Z/2015-10-11T11:00:00Z'],
          });
          const nextState = reservationsReducer(initialState, action);
          const expected = Immutable([]);

          expect(nextState.selected).to.deep.equal(expected);
        });

        it('should not affect other selected slots ', () => {
          const slot = '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z';
          const action = toggleTimeSlot(slot);
          const initialState = Immutable({
            selected: [
              '2015-12-12T10:00:00Z/2015-12-12T11:00:00Z',
              '2015-10-11T10:00:00Z/2015-10-11T11:00:00Z',
            ],
          });
          const nextState = reservationsReducer(initialState, action);
          const expected = Immutable([initialState.selected[0]]);

          expect(nextState.selected).to.deep.equal(expected);
        });
      });
    });
  });
});
<|endoftext|>