function Tomahawk(config) { var $this = this, shutdownHooks = []; this.config = opts.mergeEnvironment(opts.merge(config ? config : {}, baseConfig)); this.meta = this.config.meta ? this.config.meta : (this.config.name + '-Engine'); if (this.config.logger) { this.logger = this.config.logger } else { var winston = require('winston'), meta = { "module": $this.config.name || $this.meta, "pid": process.pid }; $this.logger = new (winston.Logger)({ transports: [ new (winston.transports.Console)({ "level": $this.config.level || "info", "json": false, "colorize": true }) ]}); } if (!this.config.www) this.config.www = process.cwd(); if (this.config.www.charAt(0) !== '/') this.config.www = path.join(process.cwd(), this.config.www); this.headers = _parseHTTPHeaders(this.config.headers, this.logger, this.meta); this.app = express(); this.server = http.Server(this.app); this.io = socketio(this.server); $this.app.use(morgan('combined', { stream : { write : function (message, encoding) { if ($this.logger && $this.logger.log) { $this.logger.log('info', message.replace(/\n/, ''), $this.meta); } } } })); $this.app.use(bodyparser.urlencoded({ extended: true })); var requestBodyParser = $this.config.bodyparser instanceof Array ? $this.config.bodyparser : (typeof($this.config.bodyparser) === 'string' ? [$this.config.bodyparser] : ['./bodyparser']); for (var i = 0 ; i < requestBodyParser.length ; ++i) { $this.logger.log('info', 'requestBodyParser %s', requestBodyParser[i], $this.meta); require(requestBodyParser[i])($this.app, $this.config); } $this.app.use(function(req, res, next) { for (var i = 0 ; i < $this.headers.length ; ++i) { res.setHeader($this.headers[i].name, $this.headers[i].value); } return next(); }); if ($this.config.context) { $this.app.use($this.config.context, express.static($this.config.www)); } if ($this.level === 'error') { $this.app.use(errorhandler()); } else { $this.app.use(errorhandler()); } process.on('exit', function() { shutdownHooks.forEach(function (hook) { hook(); }); $this.logger.log('error', 'EXIT', $this.meta); }); process.on('SIGINT', function() { shutdownHooks.forEach(function (hook) { hook(); }); $this.logger.log('warn', 'SIGINT', $this.meta); process.exit(0); }); //////////////////////////////////////////////////////////////////////// var pluginPath = path.join($this.config.rootPath, ".."); $this.logger.log('debug', 'plugin-path: %s', pluginPath, $this.meta); for (var prop in $this.config.plugins) { if ($this.config.plugins.hasOwnProperty(prop)) { var plugin = $this.config.plugins[prop]; var thisPluginPath = (plugin.implementation.charAt(0) === '/') ? plugin.implementation.charAt(0) : path.join(pluginPath, plugin.implementation); $this.logger.log('debug', 'plugin[%s]:%j', prop, path.join(thisPluginPath, "package.json"), $this.meta); var pluginPkgConfig = JSON.parse(fs.readFileSync(path.join(thisPluginPath, "package.json"))); var pluginImpl = require(path.join(thisPluginPath, pluginPkgConfig.main)); config[prop] = $this.config[prop] = pluginImpl($this.app, $this.config, $this.io, $this); if ($this.config[prop] && $this.config[prop].shutdown) { shutdownHooks.push($this.config[prop].shutdown); } if ($this.config[prop] && $this.config[prop].constructor) { $this.config[prop].constructor(); } } } var routes = $this.config.routes instanceof Array ? $this.config.routes : (typeof($this.config.routes) === 'string' ? [$this.config.routes] : []); for (var i = 0 ; i < routes.length ; ++i) { $this.logger.log('debug', 'loading module: %s', routes[i], $this.meta); var routehooks = require( routes[i].charAt(0) === '/' ? routes[i] : path.join($this.config.rootPath, "lib", routes[i]) )($this.app, $this.config, $this.io, $this); if (routehooks && routehooks.shutdown) { shutdownHooks.push(routehooks.shutdown); } } var cgi = $this.config.cgi instanceof Array ? $this.config.cgi : (typeof($this.config.cgi) === 'string' ? [$this.config.cgi] : []); $this.logger.log('debug', 'cgis: %j', cgi, $this.meta); function createRouteCGI(app, cgi) { var method = cgi.method || "GET"; function handler(req, res) { var command = cgi.command; var args = cgi.args || []; $this.logger.log('debug', 'spawn: %s [args:%j]', command, args, $this.meta); var child = spawn(command, args); if (cgi.encoding) child.stdin.setEncoding(cgi.encoding); child.stderr.on('data', function (data) { $this.logger.log('debug', 'stderr: %s', (''+data), $this.meta); res.write(data); }); child.stdout.on('data', function (data) { $this.logger.log('debug', 'stdout: %s', (''+data), $this.meta); res.write(data); }); child.on('close', function (code) { $this.logger.log('debug', 'close', $this.meta); res.end(); }); req.on('data', function (data) { $this.logger.log('read %s', (''+data), $this.meta); child.stdin.write(data); }); req.on('end', function (data) { $this.logger.log('end %s', (''+data), $this.meta); if (data) child.stdin.end(data); else child.stdin.end(); }); } if (method === 'GET') { app.get(cgi.route, handler); } else if (method === 'POST') { app.post(cgi.route, handler); } else if (method === 'PUT') { app.put(cgi.route, handler); } else if (method === 'DELETE') { app.delete(cgi.route, handler); } } for (i = 0 ; i < cgi.length ; ++i) { createRouteCGI($this.app, cgi[i]); } }
module.exports = function(app) { app.use(errorhandler()); app.use(morgan({format: 'dev'})); }
export default function(app) { var env = app.get('env'); app.set('views', config.root + '/server/views'); app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(compression()); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(methodOverride()); app.use(cookieParser()); // Persist sessions with MongoStore / sequelizeStore // We need to enable sessions for passport-twitter because it's an // oauth 1.0 strategy, and Lusca depends on sessions app.use(session({ secret: config.secrets.session, saveUninitialized: true, resave: false, store: new MongoStore({ mongooseConnection: mongoose.connection, db: 'the-sharks' }) })); /** * Lusca - express server security * https://github.com/krakenjs/lusca */ if ('test' !== env) { app.use(lusca({ csrf: { angular: true }, xframe: 'SAMEORIGIN', hsts: { maxAge: 31536000, //1 year, in seconds includeSubDomains: true, preload: true }, xssProtection: true })); } app.set('appPath', path.join(config.root, 'client')); if ('production' === env) { app.use(favicon(path.join(config.root, 'client', 'favicon.ico'))); app.use(express.static(app.get('appPath'))); app.use(morgan('dev')); } if ('development' === env) { app.use(require('connect-livereload')()); } if ('development' === env || 'test' === env) { app.use(express.static(path.join(config.root, '.tmp'))); app.use(express.static(app.get('appPath'))); app.use(morgan('dev')); app.use(errorHandler()); // Error handler - has to be last } }
module.exports = function(app) { // app.configure(function() { app.use(multer({ dest:'./tmp', rename: function (fieldname, filename) { return (new Date()).getTime()+"-"+filename } })) var logger; app.use('/assets', express.static('assets')); app.use('/uploads', express.static('uploads')); app.set('port', config.run_port); //模板所在路径 app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); //日志支持 log4js.configure({ appenders: [{ type: 'console' }] }); logger = log4js.getLogger('normal'); logger.setLevel('INFO'); app.use(log4js.connectLogger(logger, { level: log4js.levels.INFO })); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(session({ secret: config.session_secret })); app.use(methodOverride()); //rainbow配置 rainbow.route(app, config.rainbow); //404处理 app.all('*', function(req, res, next) { return res.render('404.jade'); }); //所有错误的集中处理,在任何route中调用next(error)即可进入此逻辑 app.use(function(err, req, res, next) { console.trace(err); return res.render('502.jade', { error: err }); }); //给模板引擎设置默认函数,例如时间显示moment app.locals.moment = require('moment'); app.locals.moment.lang('zh-cn'); //静态资源头,本地开发用本地,线上可以用cdn app.locals.assets_head = config.assets_head; app.locals.assets_files = config.assets_files; app.locals.assets_images = config.assets_images; // }); // app.configure('development', function() { // app.use(express.errorHandler()); // app.use(express.logger('dev')); // }); var env = process.env.NODE_ENV || 'development'; if ('development' == env) { app.use(errorhandler()); app.use(morgan('dev')); } }
var path = require('path'); var express = require('express'); var app = express(); var errorHandler = require('errorhandler'); var port = parseInt(process.env.PORT, 10) || 8000; var staticPath = path.join(__dirname, '..' , 'client'); app.get('/', function (req, res) { res.redirect('/index.html'); }); app.use(express.static(staticPath)); app.use(errorHandler({ dumpExceptions: true, showStack: true })); app.listen(port); console.log('Serving %s on port %d', staticPath, port);
function runServer( args: Args, config: ConfigT, // FIXME: this is weird design. The top-level should pass down a custom // reporter rather than passing it up as argument to an event. startedCallback: (reporter: Reporter) => mixed, readyCallback: (reporter: Reporter) => mixed, ) { var wsProxy = null; var ms = null; const terminal = new Terminal(process.stdout); const ReporterImpl = getReporterImpl(args.customLogReporterPath || null); const reporter = new ReporterImpl(terminal); const packagerServer = getPackagerServer(args, config, reporter); startedCallback(reporter); const app = connect() .use(loadRawBodyMiddleware) .use(compression()) .use( '/debugger-ui', serveStatic(path.join(__dirname, 'util', 'debugger-ui')), ) .use( getDevToolsMiddleware(args, () => wsProxy && wsProxy.isChromeConnected()), ) .use(getDevToolsMiddleware(args, () => ms && ms.isChromeConnected())) .use(openStackFrameInEditorMiddleware(args)) .use(copyToClipBoardMiddleware) .use(statusPageMiddleware) .use(systraceProfileMiddleware) .use(indexPageMiddleware) .use(packagerServer.processRequest.bind(packagerServer)); args.projectRoots.forEach(root => app.use(serveStatic(root))); app.use(morgan('combined')).use(errorhandler()); if (args.https && (!args.key || !args.cert)) { throw new Error('Cannot use https without specifying key and cert options'); } const serverInstance = args.https ? https.createServer( { key: fs.readFileSync(args.key), cert: fs.readFileSync(args.cert), }, app, ) : http.createServer(app); serverInstance.listen(args.port, args.host, 511, function() { attachWebsocketServer({ httpServer: serverInstance, path: '/hot', websocketServer: new HmrServer(packagerServer), }); wsProxy = webSocketProxy.attachToServer(serverInstance, '/debugger-proxy'); ms = messageSocket.attachToServer(serverInstance, '/message'); readyCallback(reporter); }); // Disable any kind of automatic timeout behavior for incoming // requests in case it takes the packager more than the default // timeout of 120 seconds to respond to a request. serverInstance.timeout = 0; }
// The application function start() { var app = express(); var port = process.env.PORT || 3000; var server = app.listen(port); require('./routes/redirects')(app); app.use(helmet()); // Extras // Rendering tools app.locals.moment = require('moment'); // Passport Logic var passport = require('passport'); var User = require('./entities/users/model'); var Sponsor = require('./entities/sponsors/model'); // Node mailer var transporter = mailer.createTransport({ host: process.env.MAIL_HOST, port: process.env.MAIL_PORT, secure: true, auth: { user: process.env.MAIL_USER, pass: process.env.MAIL_PASS } }); // all environments app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); app.use(favicon(path.join(__dirname, 'static/assets/img/favicon.png'))); if('development' == app.get('env')) app.use(logger('dev')) else app.use(logger('common', { skip: function (req, res) { return res.statusCode < 400 } })); app.use(cookieParser()); app.use(bodyParser.json({type: 'application/vnd.api+json', limit: '50mb'})); app.use(device.capture()); app.use(bodyParser.urlencoded({extended: true, limit: '50mb', parameterLimit: 3000})); app.use(passport.initialize()); app.use(flash()); app.use(methodOverride('X-HTTP-Method-Override')); app.use(static_dir(path.join(__dirname, 'static'))); var appRoutes = require('./routes/index')(app, process.env); var apiRoutes = require('./routes/api')(app, process.env, transporter); app.get('*', function(req, res){ res.status(404); res.render('error', {'error': 'Page not found'}); }); // Error Handling // Development only if ('development' == app.get('env')) { app.use(errorHandler()); } else { // 404 app.use(function(req, res) { res.sendStatus(404); }); // 500 app.use(function(err, req, res, next) { res.sendStatus(500); }); } http.createServer(app).listen(app.get(port), function(){ console.log('Express server listening on port ' + port + ' on ' + WORKERS + ' worker(s)'); }); }
module.exports = function (app) { var env = app.get('env'); if ('development' === env) { app.use(require('connect-livereload')()); // Disable caching of scripts for easier testing app.use(function noCache(req, res, next) { if (req.url.indexOf('/scripts/') === 0) { res.header('Cache-Control', 'no-cache, no-store, must-revalidate'); res.header('Pragma', 'no-cache'); res.header('Expires', 0); } next(); }); app.use(express.static(path.join(config.root, '.tmp'))); app.use(express.static(path.join(config.root, 'app'))); app.set('views', config.root + '/app/views'); } if ('production' === env) { //http://stackoverflow.com/questions/7185074/heroku-nodejs-http-to-https-ssl-forced-redirect // force everything on SSL when running behind Heroku load balancers... var forceSsl = function (req, res, next) { if (req.headers['x-forwarded-proto'] !== 'https') { return res.redirect(['https://', req.get('Host'), req.url].join('')); } else { next(); } }; app.use(forceSsl); app.use(compression()); app.use(favicon(path.join(config.root, 'public', 'favicon.ico'))); app.use(express.static(path.join(config.root, 'public'))); app.set('views', config.root + '/views'); } app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(morgan('dev')); app.use(bodyParser()); app.use(methodOverride()); app.use(cookieParser()); app.use(logErrors); // Persist sessions with mongo Store app.use(session({ secret: 'ssh-its-classified', store: new mongoStore({ url: config.mongo.uri, collection: 'sessions' }, function () { console.log('db connection is now open'); }) })); // Use passport session app.use(passport.initialize()); app.use(passport.session()); // Error handler - has to be last if ('development' === app.get('env')) { app.use(errorHandler()); } function logErrors(err, req, res, next) { console.error(err.stack); next(err); } };
module.exports = function(app, User) { var env = app.get('env'); if ('development' === env) { app.use(require('connect-livereload')()); // Disable caching of scripts for easier testing app.use(function noCache(req, res, next) { if (req.url.indexOf('/scripts/') === 0) { res.header('Cache-Control', 'no-cache, no-store, must-revalidate'); res.header('Pragma', 'no-cache'); res.header('Expires', 0); } next(); }); app.use(express.static(path.join(config.root, '.tmp'))); app.use(express.static(path.join(config.root, 'app'))); app.set('views', config.root + '/app/views'); } if ('production' === env) { app.use(compression()); app.use(favicon(path.join(config.root, 'public', 'favicon.ico'))); app.use(express.static(path.join(config.root, 'public'))); app.set('views', config.root + '/views'); } app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(morgan('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded()); // app.use(bodyParser()); app.use(methodOverride()); app.use(cookieParser()); app.use(session({ secret: 'keyboard cat' })); passport.serializeUser(function(user, done) { done(null, user.id); }); passport.deserializeUser(function(id, done) { User.findById(id, function(err, user) { done(err, user); }); }); passport.use(new LocalStrategy({ usernameField: 'username', passwordField: 'username' }, function(username, password, done) { User.findOne({ username: username }, function(err, user) { if (err) return done(err); if (!user) return done(null, false); return done(null, user); }); })); app.use(passport.initialize()); app.use(passport.session()); app.use(function(req, res, next) { if (req.user) { res.cookie('user', JSON.stringify(req.user)); } next(); }); app.post('/api/login', passport.authenticate('local'), function(req, res) { res.cookie('user', JSON.stringify(req.user)); res.send(req.user); }); app.get('/api/logout', function(req, res) { req.logout(); res.send(200); }); app.post('/api/signup', function(req, res, next) { var user = new User({ username: req.body.username, }); user.save(function(err) { if (err) return next(err); res.send(200); }); }); // Error handler - has to be last if ('development' === app.get('env')) { app.use(errorHandler()); } };
var app = module.exports = exports.app = express(); app.locals.siteName = "<%= modulename %>"; // Connect to database var db = require('./config/db'); app.use(express.static(__dirname + '/public')); var env = process.env.NODE_ENV || 'development'; var port = process.env.PORT || 3000; if ('development' == env) { app.use(morgan('dev')); app.use(errorhandler({ dumpExceptions: true, showStack: true })); app.set('view options', { pretty: true }); } if ('test' == env) { port = 9997; app.use(morgan('test')); app.set('view options', { pretty: true }); app.use(errorhandler({ dumpExceptions: true, showStack: true
KeyValue.getKeyValues().then(function(data) { cfg.setKeyValue(data); // -------------------------------------------------------- // These next three calls are per the example application at: // https://github.com/jaredhanson/passport-local/blob/master/examples/express3-no-connect-flash/app.js // -------------------------------------------------------- passport.serializeUser(function(user, done) { done(null, user.id); }); passport.deserializeUser(function(id, done) { User.findById(id, function (err, user) { done(err, user); }); }); passport.use(new LocalStrategy( function(username, password, done) { //Find the user by username. If there is no user with the given //username, or the password is not correct, set the user to `false` to //indicate failure and set a flash message. Otherwise, return the //authenticated `user`. User.findByUsername(username, function(err, user) { if (!user) { return done(null, false, { message: 'Unknown user ' + username }); } if (user.get('status') != 1) { return done(null, false, { message: username + ' is not an active account.' }); } user.checkPassword(password, function(err, same) { if (err) return done(err); if (same) { return done(null, user); } else { return done(null, false, {message: 'Invalid password'}); } }); }); } )); // -------------------------------------------------------- // All configurations. // -------------------------------------------------------- app.engine('jade', cons.jade); app.set('view engine', 'jade'); app.set('views', path.join(__dirname,'views')); app.use(favicon(__dirname + '/static/favicon.ico')); app.use(express.static('static')); app.use(bodyParser.json()); app.use(methodOverride()); app.use(cookieParser(cfg.cookie.secret)); console.log('Creating MySQL session pool and session configuration.') cfg.session.pool = MySQL.createPool({ user: cfg.database.dbUser , password: cfg.database.dbPass , host: cfg.database.host , port: cfg.database.port , database: cfg.database.db , schema: { tablename: 'session' , columnNames: { session_id: 'sid' , expires: 'expires' , data: 'session' } } }); sessionCfg = { host: cfg.database.host , port: cfg.database.port , user: cfg.database.dbUser , password: cfg.database.dbPass , database: cfg.database.db }; var sessionStore = new SessionStore(sessionCfg); // -------------------------------------------------------- // sessionMiddleware() allows the same authentication to // be used in Express as in Socket.io. // -------------------------------------------------------- var sessionMiddleware = session({ secret: cfg.session.secret , cookie: {maxAge: cfg.cookie.maxAge, secure: useSecureCookie} , rolling: true // Allows session to remain active as long as it is being used. , resave: false // Usually false since express-mysql-session implements touch(). , saveUninitialized: false , store: sessionStore }); app.use(sessionMiddleware); app.use(bodyParser.urlencoded({extended: false})); app.use(device.capture()); app.use(passport.initialize()); app.use(passport.session()); app.use(flash()); // -------------------------------------------------------- // Insure that our priority numbers are prepped and ready. // -------------------------------------------------------- generateBarcodes(); // -------------------------------------------------------- // Handle a "touch" by an SPA client that maintains the // session on the HTTP side while the client continues to // use exclusively websockets or Socket.io. The session is // automagically touched by the end of handling the request. // This allows the session maintained by the HTTP side, // which can be "abandoned" by the client for long periods // of time while the user is using the SPA client, to remain // valid and ready when the user returns to full page mode. // -------------------------------------------------------- app.put('/touch', function(req, res) { res.statusCode = 204; res.end(); }); // -------------------------------------------------------- // Deliver these JS libraries to the templating system. // -------------------------------------------------------- app.locals.libs = {}; app.locals.libs.mmt = moment; // Moment's global reference is deprecated. app.locals.libs._ = _; // Underscore // -------------------------------------------------------- // Localization. // -------------------------------------------------------- app.use(function(req, res, next) { if (req.session && req.session.user) { var lang = req.session.user.lang || cfg.site.defaultLanguage; req.headers['accept-language'] = lang; } next(); }); app.use(i18n.abide({ supported_languages: cfg.site.languages , default_lang: cfg.site.defaultLanguage , debug_lang: cfg.site.debugLanguage , translation_directory: 'i18n' })); // -------------------------------------------------------- // This is a hack because i18n-abide does not work natively // outside the context of a request. Therefore, we force // it into the context of a request in order to localize // all of the site wide variables for our templates. See // config.js in the site section. // // Note: any additions to cfg.site in config.js need to be // added to this function. // -------------------------------------------------------- var i18nLocals = function(req, res, next) { var title = cfg.getKeyValue('siteShortName'); app.locals.siteTitle = req.gettext(title); next(); }; /* -------------------------------------------------------- * hasSuper() * * Forces the user in the attending role to choose a supervisor * before continuing. Also populates the supervisor variable * for use in the templates. * -------------------------------------------------------- */ var hasSuper = function(req, res, next) { var superName ; if (req.session.roleInfo.roleName === 'attending') { if (req.session.supervisor) { // -------------------------------------------------------- // Store the supervisor in app.locals for the templates. // Not all supervisors have their displayName field // populated so fall back to first and last if necessary. // -------------------------------------------------------- superName = req.session.supervisor.displayName; if (! superName) { superName = req.session.supervisor.firstname + ' ' + req.session.supervisor.lastname; } app.locals.supervisor = superName; next(); } else { res.redirect(cfg.path.setSuper); } } else { next(); } }; /* -------------------------------------------------------- * logDevice() * * Logs the device the client is using to the console. * -------------------------------------------------------- */ var logDevice = function(req, res, next) { //console.dir(req.device); next(); }; /* -------------------------------------------------------- * logRoute() * * Logs a bit about the route being accessed by the user. * This does not imply that the route has been approved yet. * -------------------------------------------------------- */ var logRoute = function(req, res, next) { var msg = '' ; if (req.session && req.session.user && req.session.user.username) { msg += req.session.user.username + ': '; } msg += '[' + req.method + '] ' + req.url; logInfo(msg); next(); }; /* -------------------------------------------------------- * Records in the session the jumpTo URL per the value of * the jumpTo field passed in the request body. The value * of the field corresponds to a lookup in the configuration * to ascertain the proper URL for the key passed. The * pregnancy id is ascertained by checking the session for * the current pregnancy id and replaced if there is a * placeholder for it. * -------------------------------------------------------- */ app.use(function(req, res, next) { var url ; if (req.method === 'POST' && req.body && req.body.jumpTo) { if (_.has(cfg.jumpTo, req.body.jumpTo)) { url = cfg.jumpTo[req.body.jumpTo]; if (req.session.currentPregnancyId && /:id/.test(url)) { url = url.replace(/:id/, req.session.currentPregnancyId); } req.session.jumpTo = url; logInfo(req.session.user.username + ': <JumpTo> ' + url); } } next(); }); /* -------------------------------------------------------- * Make the current path available to the templates so that * it can be used to dynamically create an url for entering * history mode. * -------------------------------------------------------- */ app.use(function(req, res, next) { var currUrl ; if (req.method === 'GET' && req.url.search(/^\/pregnancy\//) !== -1) { app.locals.currUrl = req.url; } next(); }); // -------------------------------------------------------- // Debugging, etc. // -------------------------------------------------------- app.use(function(req, res, next) { if (cfg.site.debug) { console.log('============================'); console.log(req.method + ': ' + req.url); console.log(req.headers); console.log('-----'); console.log(req.body); console.log('============================'); console.log('isAuthenticated(): ' + req.isAuthenticated()); console.log('============================'); } next(); }); // -------------------------------------------------------- // Protect against cross site request forgeries. // -------------------------------------------------------- app.use(csrfProtection); app.use(function(req, res, next) { app.locals.token = req.csrfToken(); next(); }); // -------------------------------------------------------- // Make the application revision available to the templates. // -------------------------------------------------------- if (fs.existsSync('./VERSION')) { tmpRevision = fs.readFileSync('./VERSION', {encoding: 'utf8'}); tmpRevision = tmpRevision.trim(); logInfo('Version: ' + tmpRevision); app.use(function(req, res, next) { app.locals.applicationRevision = tmpRevision? tmpRevision: ''; next(); }); } else { app.locals.applicationRevision = void(0); } // -------------------------------------------------------- // Check for the system mode that we are in per the // SystemMode.dat file in the top-level directory. We do this // when we start as well as periodically thereafter. // -------------------------------------------------------- systemMode = getNewSystemMode(SYSTEM_MODE_FILE); process.send({cmd: SYSTEM_MODE_CHANGE, systemMode: systemMode}); if (systemMode !== 0) logInfo('Starting in SystemMode: ' + systemMode); setInterval(function() { var tmpSystemMode = getNewSystemMode(SYSTEM_MODE_FILE); if (tmpSystemMode !== systemMode) { systemMode = tmpSystemMode; process.send({cmd: SYSTEM_MODE_CHANGE, systemMode: systemMode}); logInfo('New SystemMode: ' + systemMode); } }, checkSystemModeMS); // -------------------------------------------------------- // express-device functionality: render different views // according to device type. // -------------------------------------------------------- device.enableViewRouting(app); // -------------------------------------------------------- // Development configuration // -------------------------------------------------------- if (app.get('env') === 'development') { logInfo('DEVELOPMENT mode'); } // -------------------------------------------------------- // Production configuration // -------------------------------------------------------- if (app.get('env') === 'production') { logInfo('PRODUCTION mode'); } // ======================================================== // ======================================================== // Routes // // Note that the auth method placed before the inRoles() // authentication requirements in many of the routes allows // the request to get redirected to the login page rather // than just being denied if the user is not yet logged in. // ======================================================== // ======================================================== // -------------------------------------------------------- // Group of methods that are commonly needed for // many requests. // common: populates the request with info for protected routes. // spaCommon: same but for API calls. // -------------------------------------------------------- common.push(logRoute, logDevice, setSystemMode, auth, setRoleInfo, i18nLocals); spaCommon.push(logRoute, logDevice, setSystemMode, spaAuth, setRoleInfo, i18nLocals); // -------------------------------------------------------- // Login and logout // -------------------------------------------------------- app.get(cfg.path.login, logRoute, setRoleInfo, setSystemMode, home.login); app.post(cfg.path.login, logRoute, setRoleInfo, setSystemMode, home.loginPost); app.get(cfg.path.logout, logRoute, clearRoleInfo, home.logout); // -------------------------------------------------------- // Catch routes to see if user refreshed page on an SPA route // but don't handle the API calls. // -------------------------------------------------------- app.use(function(req, res, next) { // If url is anything /api, ignore. if (/^\/api\//.test(req.url)) return next(); // If url is for transitioning from SPA to full page load, ignore. if (/^\/toprenatal/.test(req.url)) return next(); // Ignore the birth certificate. if (/^\/printBirthCertificate/.test(req.url)) return next(); if (req.session && req.session.isSpaOnly) return api.doSpa(req, res, next); next(); }); // -------------------------------------------------------- // Home for phase one prenatal (full page load) and the // labor/delivery/postpartum SPA. // -------------------------------------------------------- app.get(cfg.path.home, common, hasSuper, api.doSpa, home.home); // -------------------------------------------------------- // Handle transitions between prenatal full page loads and // labor/delivery/postpartum SPA. // -------------------------------------------------------- app.get(cfg.path.toPrenatal, common, hasSuper, home.handleSPA); app.get(cfg.path.toLabor, common, hasSuper, home.handleSPA); // -------------------------------------------------------- // Search // -------------------------------------------------------- app.get(cfg.path.search, common, hasSuper, inRoles(['clerk', 'supervisor', 'attending', 'guard']), search.view); app.post(cfg.path.search, common, hasSuper, inRoles(['clerk', 'supervisor', 'attending', 'guard']), search.execute); // -------------------------------------------------------- // Users // -------------------------------------------------------- app.get(cfg.path.userList, common, inRoles(['administrator']), api.doSpa, users.list); app.all(cfg.path.userLoad, users.load); // parameter handling app.get(cfg.path.userNewForm, common, inRoles(['administrator']), api.doSpa, users.addForm); app.post(cfg.path.userCreate, common, inRoles(['administrator']), api.doSpa, users.create); app.get(cfg.path.userEditForm, common, inRoles(['administrator']), api.doSpa, users.editForm); app.post(cfg.path.userUpdate, common, inRoles(['administrator']), api.doSpa, users.update); // -------------------------------------------------------- // Roles // -------------------------------------------------------- app.get(cfg.path.roleList, common, inRoles(['administrator']), api.doSpa, roles.list); app.all(cfg.path.roleLoad, roles.load); // parameter handling app.get(cfg.path.roleNewForm, common, inRoles(['administrator']), api.doSpa, roles.addForm); app.post(cfg.path.roleCreate, common, inRoles(['administrator']), api.doSpa, roles.create); app.get(cfg.path.roleEditForm, common, inRoles(['administrator']), api.doSpa, roles.editForm); app.post(cfg.path.roleUpdate, common, inRoles(['administrator']), api.doSpa, roles.update); // -------------------------------------------------------- // Role assignment to users // -------------------------------------------------------- app.all(cfg.path.userLoad2, users.load); // parameter handling // -------------------------------------------------------- // Profile // -------------------------------------------------------- app.get(cfg.path.profile, common, users.editProfile); app.post(cfg.path.profile, common, users.saveProfile); // -------------------------------------------------------- // Set the supervisor if a attending. // -------------------------------------------------------- app.get(cfg.path.setSuper, common, inRoles(['attending']), users.editSupervisor); app.post(cfg.path.setSuper, common, inRoles(['attending']), users.saveSupervisor); // -------------------------------------------------------- // Pregnancy management // -------------------------------------------------------- app.all(cfg.path.pregnancyLoad, pregnancy.load); // parameter handling app.get(cfg.path.pregnancyNewForm, common, hasSuper, inRoles(['clerk','attending','supervisor']), pregnancy.generalAddForm); app.get(cfg.path.pregnancyNewCurrPatForm, common, hasSuper, inRoles(['clerk','attending','supervisor']), pregnancy.generalAddForm); app.post(cfg.path.pregnancyCreate, common, hasSuper, inRoles(['clerk','attending','supervisor']), pregnancy.generalAddSave); app.get(cfg.path.pregnancyEditForm, common, hasSuper, inRoles(['clerk','attending','supervisor']), pregnancy.generalEditForm); app.post(cfg.path.pregnancyUpdate, common, hasSuper, inRoles(['clerk','attending','supervisor']), pregnancy.generalEditSave); app.post(cfg.path.pregnancyDelete, common, hasSuper, inRoles(['supervisor']), pregnancy.pregnancyDelete); // Pregnancy Questionnaire app.get(cfg.path.pregnancyQuesEdit, common, hasSuper, inRoles(['clerk', 'attending','supervisor']), pregnancy.questionaireForm); app.post(cfg.path.pregnancyQuesUpdate, common, hasSuper, inRoles(['clerk', 'attending','supervisor']), pregnancy.questionaireSave); // Pregnancy midwife interview app.get(cfg.path.pregnancyMidwifeEdit, common, hasSuper, inRoles(['attending','supervisor']), pregnancy.midwifeForm); app.post(cfg.path.pregnancyMidwifeUpdate, common, hasSuper, inRoles(['attending','supervisor']), pregnancy.midwifeSave); // Pregnancy History app.get(cfg.path.pregnancyHistoryAdd, common, hasSuper, inRoles(['attending','supervisor']), pregnancyHistory.pregnancyHistoryAddForm); app.post(cfg.path.pregnancyHistoryAdd, common, hasSuper, inRoles(['attending','supervisor']), pregnancyHistory.pregnancyHistorySave); app.get(cfg.path.pregnancyHistoryEdit, common, hasSuper, inRoles(['attending','supervisor']), pregnancyHistory.pregnancyHistoryEditForm); app.post(cfg.path.pregnancyHistoryEdit, common, hasSuper, inRoles(['attending','supervisor']), pregnancyHistory.pregnancyHistorySave); app.post(cfg.path.pregnancyHistoryDelete, common, hasSuper, inRoles(['attending','supervisor']), pregnancyHistory.pregnancyHistoryDelete); // Prenatal app.get(cfg.path.pregnancyPrenatalEdit, common, hasSuper, inRoles(['clerk','attending','supervisor']), pregnancy.prenatalForm); app.post(cfg.path.pregnancyPrenatalUpdate, common, hasSuper, inRoles(['clerk', 'attending','supervisor']), pregnancy.prenatalSave); // Prenatal Exams app.get(cfg.path.pregnancyPrenatalExamAdd, common, hasSuper, inRoles(['clerk','attending','supervisor']), prenatalExam.prenatalExamAddForm); app.post(cfg.path.pregnancyPrenatalExamAdd, common, hasSuper, inRoles(['clerk','attending','supervisor']), prenatalExam.prenatalExamSave); app.get(cfg.path.pregnancyPrenatalExamEdit, common, hasSuper, inRoles(['clerk','attending','supervisor']), prenatalExam.prenatalExamEditForm); app.post(cfg.path.pregnancyPrenatalExamEdit, common, hasSuper, inRoles(['clerk','attending','supervisor']), prenatalExam.prenatalExamSave); app.post(cfg.path.pregnancyPrenatalExamDelete, common, hasSuper, inRoles(['attending','supervisor']), prenatalExam.prenatalExamDelete); app.get(cfg.path.pregnancyPrenatalExamLatest, common, hasSuper, inRoles(['attending','supervisor']), prenatalExam.prenatalExamLatest); // Labs main page app.get(cfg.path.pregnancyLabsEditForm, common, hasSuper, inRoles(['attending','supervisor', 'clerk']), pregnancy.labsForm); // Lab Tests app.post(cfg.path.labTestAddForm, common, hasSuper, inRoles(['attending', 'supervisor', 'clerk']), labs.labTestAddForm); app.post(cfg.path.labTestAdd, common, hasSuper, inRoles(['attending', 'supervisor', 'clerk']), labs.labTestSave); app.get(cfg.path.labTestEdit, common, hasSuper, inRoles(['attending', 'supervisor', 'clerk']), labs.labTestEditForm); app.post(cfg.path.labTestEdit, common, hasSuper, inRoles(['attending', 'supervisor', 'clerk']), labs.labTestSave); app.post(cfg.path.labTestDelete, common, hasSuper, inRoles(['attending', 'supervisor', 'clerk']), labs.labDelete); // Referrals app.get(cfg.path.referralAdd, common, hasSuper, inRoles(['attending', 'supervisor']), referral.referralAddForm); app.post(cfg.path.referralAdd, common, hasSuper, inRoles(['attending', 'supervisor']), referral.referralSave); app.get(cfg.path.referralEdit, common, hasSuper, inRoles(['attending', 'supervisor']), referral.referralEditForm); app.post(cfg.path.referralEdit, common, hasSuper, inRoles(['attending', 'supervisor']), referral.referralSave); app.post(cfg.path.referralDelete, common, hasSuper, inRoles(['attending', 'supervisor']), referral.referralDelete); // Progress Notes app.get(cfg.path.pregnoteAdd, common, hasSuper, inRoles(['attending', 'supervisor']), pregnote.pregnoteAddForm); app.post(cfg.path.pregnoteAdd, common, hasSuper, inRoles(['attending', 'supervisor']), pregnote.pregnoteSave); app.get(cfg.path.pregnoteEdit, common, hasSuper, inRoles(['attending', 'supervisor']), pregnote.pregnoteEditForm); app.post(cfg.path.pregnoteEdit, common, hasSuper, inRoles(['attending', 'supervisor']), pregnote.pregnoteSave); app.post(cfg.path.pregnoteDelete, common, hasSuper, inRoles(['attending', 'supervisor']), pregnote.pregnoteDelete); // Health Teachings app.get(cfg.path.teachingAdd, common, hasSuper, inRoles(['attending', 'clerk', 'supervisor']), teaching.teachingAddForm); app.post(cfg.path.teachingAdd, common, hasSuper, inRoles(['attending', 'clerk', 'supervisor']), teaching.teachingSave); app.get(cfg.path.teachingEdit, common, hasSuper, inRoles(['attending', 'clerk', 'supervisor']), teaching.teachingEditForm); app.post(cfg.path.teachingEdit, common, hasSuper, inRoles(['attending', 'clerk', 'supervisor']), teaching.teachingSave); app.post(cfg.path.teachingDelete, common, hasSuper, inRoles(['attending', 'clerk', 'supervisor']), teaching.teachingDelete); // Doctor and dentist consult dates app.post(cfg.path.docDenConsult, common, hasSuper, inRoles(['attending', 'supervisor']), pregnancy.doctorDentistSave); // Vaccinations app.get(cfg.path.vaccinationAdd, common, hasSuper, inRoles(['attending', 'supervisor']), vaccination.vaccinationAddForm); app.post(cfg.path.vaccinationAdd, common, hasSuper, inRoles(['attending', 'supervisor']), vaccination.vaccinationSave); app.get(cfg.path.vaccinationEdit, common, hasSuper, inRoles(['attending', 'supervisor']), vaccination.vaccinationEditForm); app.post(cfg.path.vaccinationEdit, common, hasSuper, inRoles(['attending', 'supervisor']), vaccination.vaccinationSave); app.post(cfg.path.vaccinationDelete, common, hasSuper, inRoles(['attending', 'supervisor']), vaccination.vaccinationDelete); // Medications and vitamins app.get(cfg.path.medicationAdd, common, hasSuper, inRoles(['attending', 'supervisor']), medication.medicationAddForm); app.post(cfg.path.medicationAdd, common, hasSuper, inRoles(['attending', 'supervisor']), medication.medicationSave); app.get(cfg.path.medicationEdit, common, hasSuper, inRoles(['attending', 'supervisor']), medication.medicationEditForm); app.post(cfg.path.medicationEdit, common, hasSuper, inRoles(['attending', 'supervisor']), medication.medicationSave); app.post(cfg.path.medicationDelete, common, hasSuper, inRoles(['attending', 'supervisor']), medication.medicationDelete); // Checkin and checkout routes for the guard app.get(cfg.path.checkInOut, common, inRoles(['guard']), checkInOut.checkInOut); app.post(cfg.path.checkIn, common, inRoles(['guard']), checkInOut.checkInOutSave); app.post(cfg.path.checkOut, common, inRoles(['guard']), checkInOut.checkInOutSave); app.get(cfg.path.newCheckIn, common, inRoles(['guard']), checkInOut.checkInOut); app.post(cfg.path.newCheckIn, common, inRoles(['guard']), checkInOut.checkInOutSave); app.get(cfg.path.simpleCheckOut, common, inRoles(['guard', 'attending', 'clerk', 'supervisor']), checkInOut.simpleCheckOutForm); app.post(cfg.path.simpleCheckOut, common, inRoles(['guard', 'attending', 'clerk', 'supervisor']), checkInOut.simpleCheckOut); // Priority List app.post(cfg.path.priorityListLoad, priorityList.load); // parameter handling for AJAX save only app.get(cfg.path.priorityList, common, hasSuper, inRoles(['attending', 'clerk', 'supervisor']), priorityList.page); // GET page app.post(cfg.path.priorityList, common, hasSuper, inRoles(['attending', 'clerk', 'supervisor']), priorityList.data); // POST AJAX for data app.post(cfg.path.priorityListSave, common, hasSuper, inRoles(['attending', 'clerk', 'supervisor']), priorityList.save); // POST AJAX for save // AJAX Calls. app.post(cfg.path.requiredTetanus, common, hasSuper, inRoles(['attending', 'supervisor']), vaccination.requiredTetanusSave); // Reports app.get(cfg.path.reportForm, common, hasSuper, inRoles(['supervisor', 'clerk']), report.form); app.post(cfg.path.reportRun, common, hasSuper, inRoles(['supervisor', 'clerk']), report.run); app.get(cfg.path.reportSummary, common, hasSuper, inRoles(['supervisor', 'clerk', 'attending']), report.summary); // Invoice Worksheet app.get(cfg.path.invoiceWorksheet, common, inRoles(['supervisor', 'clerk', 'attending']), invWork.invoiceWorksheet); // Birth Certificate printing app.get(cfg.path.birthCertificatePrinting, common, inRoles(['supervisor', 'clerk', 'attending']), report.birthCertificate); // ======================================================== // ======================================================== // SPA related routes and data calls below. // ======================================================== // ======================================================== // SPA pages: the initial full page load of a SPA portion of the app. app.get(cfg.path.spaLoad, api.params); // parameter handling app.get(cfg.path.spa, common, inRoles(['administrator', 'supervisor', 'clerk', 'attending']), api.spa.main); // History API app.all(cfg.path.apiLoad, api.params); // parameter handling app.get(cfg.path.apiHistory, common, inRoles(['supervisor']), api.history.get); // User/Role Management app.all(cfg.path.apiUser, spaCommon, inRoles(['administrator']), api.userRoles.user); // User Profile app.all(cfg.path.apiProfile, spaCommon, inRoles(['administrator', 'clerk', 'guard', 'supervisor', 'attending']), api.userRoles.profile); app.all(cfg.path.apiProfilePassword, spaCommon, inRoles(['administrator', 'clerk', 'guard', 'supervisor', 'attending']), api.userRoles.profile); // Searches app.get(cfg.path.apiSearch, spaCommon, inRoles(['clerk', 'guard', 'supervisor', 'attending']), apiSearch); // Pregnancy app.get(cfg.path.apiPregnancy, spaCommon, inRoles(['clerk', 'guard', 'supervisor', 'attending']), getPregnancy); // -------------------------------------------------------- // Error handling. // -------------------------------------------------------- app.use(error.notFoundApiError); app.use(error.notFoundError); app.use(error.logException); app.use(error.displayError); app.use(error.exitError); if (app.get('env') === 'development') { app.use(errorHandler()); } // -------------------------------------------------------- // The last resort. // -------------------------------------------------------- process.on('uncaughtException', function(err) { logError('uncaughtException: ', err.message); logError(err.stack); process.exit(1); }); // -------------------------------------------------------- // Start the server. // -------------------------------------------------------- if (process.env.NODE_ENV == 'test') { logInfo('TEST mode'); app.listen(cfg.host.port, cfg.host.name); } else { // -------------------------------------------------------- // Determine which port this instance will listen on. In a // cluster of workers, due to the need to use sticky sessions // for the sake of Socket.io, we have the workers listen on // separate ports if there are more than one worker. See // http://socket.io/docs/using-multiple-nodes/ for details. // // Note that if cfg.cpu.workers is greater than 1, then a // reverse proxy like Nginx must be configured that implements // sticky sessions or else only one worker will be used. // -------------------------------------------------------- if (process.env.WORKER_ID) { if (cfg.tls.key) { workerPort = Number(cfg.host.tlsPort) + Number(process.env.WORKER_ID); } else { workerPort = Number(cfg.host.port) + Number(process.env.WORKER_ID); } } if (cfg.tls.key) { // -------------------------------------------------------- // Listen for HTTPS connections. // -------------------------------------------------------- var tlsCfg = {}; tlsCfg.key = fs.readFileSync(cfg.tls.key); tlsCfg.cert = fs.readFileSync(cfg.tls.cert); server = https.createServer(tlsCfg, app); server.listen(workerPort, cfg.host.name); // -------------------------------------------------------- // Catch all incoming HTTP connections and redirect to HTTPS. // We don't redirect to the workerPort because if we are // running more than one worker in a cluster, the reverse // proxy should be implementing some form of sticky connections // which should choose the correct worker port, if the // remoteAddress has already been assigned to one. // -------------------------------------------------------- http.createServer(function(req, res) { var httpsLoc = url.format({ protocol: 'https', hostname: cfg.host.name, port: cfg.host.tlsPort }) ; res.setHeader('Location', httpsLoc); res.statusCode = 302; res.end('Redirecting to ' + httpsLoc); }).listen(cfg.host.port, cfg.host.name); } else { // -------------------------------------------------------- // HTTP only. This should not be used for production. // -------------------------------------------------------- server = http.createServer(app); server.listen(workerPort, cfg.host.name); } // ======================================================== // ======================================================== // Initialize the communication module for this worker. // ======================================================== // ======================================================== comm.init(SocketIO(server), sessionMiddleware); } if (cfg.tls.key) { logInfo('Server listening for HTTPS on port ' + workerPort + ' and redirecting port ' + cfg.host.port); } else { logInfo('Server listening in INSECURE mode on port ' + workerPort); } })
/** * Creates the mountebank server * @param {object} options - The command line options * @returns {Object} An object with a close method to stop the server */ function create (options) { const Q = require('q'), express = require('express'), cors = require('cors'), errorHandler = require('errorhandler'), path = require('path'), middleware = require('./util/middleware'), thisPackage = require('../package.json'), releases = require('../releases.json'), helpers = require('./util/helpers'), deferred = Q.defer(), app = express(), imposters = options.imposters || {}, hostname = options.host || 'localhost', baseURL = `http://${hostname}:${options.port}`, logger = createLogger(options), isAllowedConnection = createIPVerification(options), protocols = loadProtocols(options, baseURL, logger, isAllowedConnection), homeController = require('./controllers/homeController').create(releases), impostersController = require('./controllers/impostersController').create( protocols, imposters, logger, options.allowInjection), imposterController = require('./controllers/imposterController').create(imposters), logsController = require('./controllers/logsController').create(options.logfile), configController = require('./controllers/configController').create(thisPackage.version, options), feedController = require('./controllers/feedController').create(releases, options), validateImposterExists = middleware.createImposterValidator(imposters); app.use(middleware.useAbsoluteUrls(options.port)); app.use(middleware.logger(logger, ':method :url')); app.use(middleware.globals({ heroku: options.heroku, port: options.port, version: thisPackage.version })); app.use(middleware.defaultIEtoHTML); app.use(middleware.json(logger)); app.use(express.static(path.join(__dirname, 'public'))); app.use(express.static(path.join(__dirname, '../node_modules'))); app.use(errorHandler()); app.use(cors()); app.disable('etag'); app.disable('x-powered-by'); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.set('json spaces', 2); app.get('/', homeController.get); app.get('/imposters', impostersController.get); app.post('/imposters', impostersController.post); app.delete('/imposters', impostersController.del); app.put('/imposters', impostersController.put); app.get('/imposters/:id', validateImposterExists, imposterController.get); app.delete('/imposters/:id', imposterController.del); app.delete('/imposters/:id/savedProxyResponses', imposterController.resetProxies); app.delete('/imposters/:id/requests', imposterController.resetProxies); // deprecated but saved for backwards compatibility // Protocol implementation APIs app.post('/imposters/:id/_requests', imposterController.postRequest); app.post('/imposters/:id/_requests/:proxyResolutionKey', imposterController.postProxyResponse); app.get('/logs', logsController.get); app.get('/config', configController.get); app.get('/feed', feedController.getFeed); app.get('/releases', feedController.getReleases); app.get('/releases/:version', feedController.getRelease); app.get('/sitemap', (request, response) => { response.type('text/plain'); response.render('sitemap', { releases: releases }); }); [ '/support', '/license', '/faqs', '/thoughtworks', '/docs/gettingStarted', '/docs/install', '/docs/mentalModel', '/docs/commandLine', '/docs/clientLibraries', '/docs/security', '/docs/api/overview', '/docs/api/contracts', '/docs/api/mocks', '/docs/api/stubs', '/docs/api/predicates', '/docs/api/xpath', '/docs/api/json', '/docs/api/jsonpath', '/docs/api/proxies', '/docs/api/injection', '/docs/api/behaviors', '/docs/api/errors', '/docs/protocols/http', '/docs/protocols/https', '/docs/protocols/tcp', '/docs/protocols/smtp', '/docs/protocols/custom' ].forEach(endpoint => { app.get(endpoint, (request, response) => { response.render(endpoint.substring(1)); }); }); const connections = {}, server = app.listen(options.port, options.host, () => { logger.info(`mountebank v${thisPackage.version} now taking orders - point your browser to ${baseURL}/ for help`); logger.debug(`config: ${JSON.stringify({ options: options, process: { nodeVersion: process.version, architecture: process.arch, platform: process.platform } })}`); if (options.allowInjection) { logger.warn(`Running with --allowInjection set. See ${baseURL}/docs/security for security info`); } server.on('connection', socket => { const name = helpers.socketName(socket), ipAddress = socket.remoteAddress; connections[name] = socket; socket.on('close', () => { delete connections[name]; }); socket.on('error', error => { logger.error('%s transmission error X=> %s', name, JSON.stringify(error)); }); if (!isAllowedConnection(ipAddress, logger)) { socket.end(); } }); deferred.resolve({ close: callback => { server.close(() => { logger.info('Adios - see you soon?'); callback(); }); // Force kill any open connections to prevent process hanging Object.keys(connections).forEach(socket => { connections[socket].destroy(); }); } }); }); process.once('exit', () => { Object.keys(imposters).forEach(port => { imposters[port].stop(); }); }); return deferred.promise; }
module.exports = function(app) { var env = app.get('env'); app.set('views', config.root + '/server/views'); app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(compression()); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(expressValidator([{ customValidators: { isArray: function(value) { return Array.isArray(value); } }}])); app.use(methodOverride()); app.use(cookieParser()); app.use(passport.initialize()); // Persist sessions with mongoStore // We need to enable sessions for passport twitter because its an oauth 1.0 strategy app.use(session({ secret: config.secrets.session, resave: true, saveUninitialized: true, store: new mongoStore({ mongoose_connection: mongoose.connection }) })); app.use(flash()); // Add headers app.use(function (req, res, next) { // Website you wish to allow to connect res.setHeader('Access-Control-Allow-Origin', 'http://fiddle.jshell.net'); // Request methods you wish to allow res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); // Request headers you wish to allow res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); // Set to true if you need the website to include cookies in the requests sent // to the API (e.g. in case you use sessions) res.setHeader('Access-Control-Allow-Credentials', true); // Pass to next layer of middleware next(); }); if ('production' === env) { app.use(favicon(path.join(config.root, 'public', 'favicon.ico'))); app.use(express.static(path.join(config.root, 'public'))); app.set('appPath', config.root + '/public'); app.use(morgan('dev')); } if ('development' === env || 'test' === env) { app.use(require('connect-livereload')()); app.use(express.static(path.join(config.root, '.tmp'))); app.use(express.static(path.join(config.root, 'client'))); app.set('appPath', 'client'); app.use(morgan('dev')); app.use(errorHandler()); // Error handler - has to be last } };
var setup = function(options) { var app = this; assert(options.cookieSecret, "cookieSecret is required"); assert(options.viewFolder, "viewFolder is required"); assert(options.assetFolder, "assetFolder is required"); // Set default options _.defaults(options, { personaLogin: '******', personaLogout: '/logout', personaUnauthorized: '/unauthorized' }); app.set('views', options.viewFolder); app.set('view engine', 'jade'); app.locals.moment = moment; app.locals.marked = marked; app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.use(methodOverride()); app.use(cookieParser(options.cookieSecret)); app.use(cookieSession({secret: options.cookieSecret})); app.use(passport.initialize()); app.use(passport.session()); app.use(function(req, res, next) { // Expose user to all templates, if logged in res.locals.user = req.user; next(); }); app.use('/assets', express.static(options.assetFolder)); // Warn if no secret was used in production if ('production' == app.get('env')) { var secret = options.cookieSecret; if (secret == "Warn, if no secret is used on production") { console.log("Warning: Customized cookie secret should be used in " + "production"); } } // Middleware for development if (app.get('env') == 'development') { app.use(errorHandler()); } // Passport configuration passport.use(new PassportPersona.Strategy({ audience: options.publicUrl }, function(email, done) { debug("Signed in with:" + email); if (/@mozilla\.com$/.test(email)) { done(null, {email: email}); } else { done(null, null); } })); // Serialize user to signed cookie passport.serializeUser(function(user, done) { done(null, user.email); }); // Deserialize user from signed cookie passport.deserializeUser(function(email, done) { done(null, {email: email}); }); // Facilitate persona login app.post(options.personaLogin, passport.authenticate('persona', { failureRedirect: options.personaUnauthorized }), function(req, res) { res.redirect('/'); }); // Provide end-point to log out the user app.get(options.personaLogout, function(req, res){ req.logout(); res.redirect('/'); }); // Middleware utility for requiring authentication var ensureAuth = function(req, res, next) { if (req.isAuthenticated()) { return next(); } res.redirect(options.personaUnauthorized); }; return ensureAuth; };
function create(env, ctx) { var app = express(); var appInfo = env.name + ' ' + env.version; app.set('title', appInfo); app.enable('trust proxy'); // Allows req.secure test on heroku https connections. var insecureUseHttp = env.insecureUseHttp; var secureHstsHeader = env.secureHstsHeader; console.info('Security settings: INSECURE_USE_HTTP=',insecureUseHttp,', SECURE_HSTS_HEADER=',secureHstsHeader); if (!insecureUseHttp) { app.use((req, res, next) => { if (req.header('x-forwarded-proto') !== 'https') res.redirect(`https://${req.header('host')}${req.url}`); else next() }) if (secureHstsHeader) { // Add HSTS (HTTP Strict Transport Security) header const helmet = require('helmet'); var includeSubDomainsValue = env.secureHstsHeaderIncludeSubdomains; var preloadValue = env.secureHstsHeaderPreload; app.use(helmet({ hsts: { maxAge: 31536000, includeSubDomains: includeSubDomainsValue, preload: preloadValue } })) if (env.secureCsp) { app.use(helmet.contentSecurityPolicy({ //TODO make NS work without 'unsafe-inline' directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", 'https://fonts.googleapis.com/',"'unsafe-inline'"], scriptSrc: ["'self'", "'unsafe-inline'"], fontSrc: [ "'self'", 'https://fonts.gstatic.com/'] } })); } } } app.set('view engine', 'ejs'); // this allows you to render .html files as templates in addition to .ejs app.engine('html', require('ejs').renderFile); app.engine('appcache', require('ejs').renderFile); app.set("views", path.join(__dirname, "views/")); app.locals.cachebuster = fs.readFileSync(process.cwd() + '/tmp/cacheBusterToken').toString().trim(); if (ctx.bootErrors && ctx.bootErrors.length > 0) { app.get('*', require('./lib/server/booterror')(ctx)); return app; } if (env.settings.isEnabled('cors')) { var allowOrigin = _get(env, 'extendedSettings.cors.allowOrigin') || '*'; console.info('Enabled CORS, allow-origin:', allowOrigin); app.use(function allowCrossDomain(req, res, next) { res.header('Access-Control-Allow-Origin', allowOrigin); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With'); // intercept OPTIONS method if ('OPTIONS' === req.method) { res.send(200); } else { next(); } }); } /////////////////////////////////////////////////// // api and json object variables /////////////////////////////////////////////////// var api = require('./lib/api/')(env, ctx); var ddata = require('./lib/data/endpoints')(env, ctx); app.use(compression({ filter: function shouldCompress(req, res) { //TODO: return false here if we find a condition where we don't want to compress // fallback to standard filter function return compression.filter(req, res); } })); app.get("/", (req, res) => { res.render("index.html", { locals: app.locals }); }); var appPages = { "/clock-color.html":"clock-color.html", "/admin":"adminindex.html", "/profile":"profileindex.html", "/food":"foodindex.html", "/bgclock.html":"bgclock.html", "/weatherbg.html":"weatherbg.html", "/report":"reportindex.html", "/translations":"translationsindex.html", "/clock.html":"clock.html" }; Object.keys(appPages).forEach(function(page) { app.get(page, (req, res) => { res.render(appPages[page], { locals: app.locals }); }); }); app.get("/appcache/*", (req, res) => { res.render("nightscout.appcache", { locals: app.locals }); }); app.use('/api/v1', bodyParser({ limit: 1048576 * 50 }), api); app.use('/api/v2/properties', ctx.properties); app.use('/api/v2/authorization', ctx.authorization.endpoints); app.use('/api/v2/ddata', ddata); // pebble data app.get('/pebble', ctx.pebble); // expose swagger.json app.get('/swagger.json', function(req, res) { res.sendFile(__dirname + '/swagger.json'); }); /* if (env.settings.isEnabled('dumps')) { var heapdump = require('heapdump'); app.get('/api/v2/dumps/start', function(req, res) { var path = new Date().toISOString() + '.heapsnapshot'; path = path.replace(/:/g, '-'); console.info('writing dump to', path); heapdump.writeSnapshot(path); res.send('wrote dump to ' + path); }); } */ //app.get('/package.json', software); // Allow static resources to be cached for week var maxAge = 7 * 24 * 60 * 60 * 1000; if (process.env.NODE_ENV === 'development') { maxAge = 10; console.log('Development environment detected, setting static file cache age to 10 seconds'); app.get('/nightscout.appcache', function(req, res) { res.sendStatus(404); }); } //TODO: JC - changed cache to 1 hour from 30d ays to bypass cache hell until we have a real solution var staticFiles = express.static(env.static_files, { maxAge: maxAge }); // serve the static content app.use(staticFiles); const swaggerUiAssetPath = require("swagger-ui-dist").getAbsoluteFSPath(); var swaggerFiles = express.static(swaggerUiAssetPath, { maxAge: maxAge }); // serve the static content app.use('/swagger-ui-dist', swaggerFiles); var tmpFiles = express.static('tmp', { maxAge: maxAge }); // serve the static content app.use(tmpFiles); if (process.env.NODE_ENV !== 'development') { console.log('Production environment detected, enabling Minify'); var minify = require('express-minify'); var myCssmin = require('cssmin'); app.use(minify({ js_match: /\.js/, css_match: /\.css/, sass_match: /scss/, less_match: /less/, stylus_match: /stylus/, coffee_match: /coffeescript/, json_match: /json/, cssmin: myCssmin, cache: __dirname + '/tmp', onerror: undefined, })); } // if this is dev environment, package scripts on the fly // if production, rely on postinstall script to run packaging for us if (process.env.NODE_ENV === 'development') { var webpack = require("webpack"); var webpack_conf = require('./webpack.config'); webpack(webpack_conf, function(err, stats) { var json = stats.toJson() // => webpack --json var options = { noColor: true }; console.log(prettyjson.render(json.errors, options)); console.log(prettyjson.render(json.assets, options)); }); } // Handle errors with express's errorhandler, to display more readable error messages. var errorhandler = require('errorhandler'); //if (process.env.NODE_ENV === 'development') { app.use(errorhandler()); //} return app; }
var fs = require('fs') var logger = require('morgan') var cors = require('cors') var serveStatic = require('serve-static') var errorhandler = require('errorhandler') var arr = [] // Logger arr.push(logger('dev', { skip: function(req, res) { return req.path === '/favicon.ico' } })) // Serve static files if (fs.existsSync(process.cwd() + '/public')) { arr.push(serveStatic(process.cwd() + '/public')); } else { arr.push(serveStatic(__dirname + '/public')); } // CORS arr.push(cors({ origin: true, credentials: true })) if (process.env.NODE_ENV === 'development') { // only use in development arr.push(errorhandler()) } module.exports = arr
var errorHandler = require('errorhandler'); var cookieParser = require('cookie-parser'); var MongoStore = require('connect-mongo')(session); var app = express(); app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/app/server/views'); app.set('view engine', 'jade'); app.use(cookieParser()); app.use(session({ secret: 'faeb4453e5d14fe6f6d04637f78077c76c73d1b4', proxy: true, resave: true, saveUninitialized: true, store: new MongoStore({ host: 'localhost', port: 27017, db: 'node-login'}) }) ); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(require('stylus').middleware({ src: __dirname + '/app/public' })); app.use(express.static(__dirname + '/app/public')); require('./app/server/routes')(app); if (app.get('env') == 'development') app.use(errorHandler()); http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); });
exports.server = http.createServer(exports.app); db.create(); var CLIENT_DIR = path.join(__dirname, '..', '..', 'client'); /** * Configuration */ // all environments exports.app.set('port', process.env.PORT || 3000); exports.app.use(cors()); exports.app.use(compression()); exports.app.use(morgan('dev')); exports.app.use(bodyParser.json({ type: 'text/plain' })); exports.app.use(bodyParser.json()); // development only if ('development' === exports.app.get('env')) { exports.app.use(errorhandler()); /* tslint:disable */ require('longjohn'); } /** * Routes */ exports.app.use(express.static(CLIENT_DIR)); exports.app.use('/auth', auth_1.authRoutes); exports.app.get('/api/helloWorld', expressJwt({ secret: config_1.config.TOKEN_SECRET }), function (req, res) { res.send("~~~ Hello " + req.user.displayName + " ~~~"); }); exports.app.get('*', function (req, res) { res.sendFile(path.join(CLIENT_DIR, 'index.html')); }); /**
export default function(app) { var env = app.get('env'); if (env === 'development' || env === 'test') { app.use(express.static(path.join(config.root, '.tmp'))); } if (env === 'production') { app.use(favicon(path.join(config.root, 'client', 'favicon.ico'))); } app.set('appPath', path.join(config.root, 'client')); app.use(express.static(app.get('appPath'))); app.use(morgan('dev')); app.set('views', config.root + '/server/views'); app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(compression()); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(methodOverride()); app.use(cookieParser()); // Persist sessions with MongoStore / sequelizeStore // We need to enable sessions for passport-twitter because it's an // oauth 1.0 strategy, and Lusca depends on sessions //app.use(session({ // secret: config.secrets.session, // saveUninitialized: true, // resave: false, // store: new MongoStore({ // mongooseConnection: mongoose.connection, // db: 'g-team' // }) //})); /** * Lusca - express server security * https://github.com/krakenjs/lusca */ //if (env !== 'test' && !process.env.SAUCE_USERNAME) { // app.use(lusca({ // csrf: { // angular: true // }, // xframe: 'SAMEORIGIN', // hsts: { // maxAge: 31536000, //1 year, in seconds // includeSubDomains: true, // preload: true // }, // xssProtection: true // })); //} if ('development' === env) { app.use(require('connect-livereload')({ ignore: [ /^\/api\/(.*)/, /\.js(\?.*)?$/, /\.css(\?.*)?$/, /\.svg(\?.*)?$/, /\.ico(\?.*)?$/, /\.woff(\?.*)?$/, /\.png(\?.*)?$/, /\.jpg(\?.*)?$/, /\.jpeg(\?.*)?$/, /\.gif(\?.*)?$/, /\.pdf(\?.*)?$/ ] })); } if ('development' === env || 'test' === env) { app.use(errorHandler()); // Error handler - has to be last } }
function initWebApp(app) { var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var errorhandler = require('errorhandler'); var session = require('express-session'); // view engine setup app.engine('ejs', require('ejs-locals')); // layout partial block app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); if (app.get('env') == 'development') { app.use(logger('dev')); app.use(errorhandler()); } else { app.use(logger('default')); } app.use(favicon()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded()); app.use(cookieParser()); var MongoStore = require('connect-mongo')(session); app.use(session({ secret : config.get('session:secret'), // ABCDE242342342314123421.SHA256 saveUninitialized: true, resave: true, key : config.get('session:key'), cookie : config.get('session:cookie'), store : new MongoStore({ db : config.get('mongodb:db'), host : config.get('mongodb:server:host'), port : config.get('mongodb:server:port') }) })); app.use(express.static(path.join(__dirname, 'public'))); app.use(require('middleware/sendHttpError')); app.use(require('middleware/loadUser')); //var routes = require('./routes/index'); var users = require('./routes/users'); var pages = require('./routes/pages'); var chat = require('./routes/chat'); var frontpage = require('./routes/frontpage'); var login = require('./routes/login'); var logout = require('./routes/logout'); var ngtest = require('./routes/ngtest'); //app.use('/', routes); app.use('/', frontpage); app.use('/chat', chat); app.use('/login', login); app.use('/logout', logout); app.use('/users', users); app.use('/pages', pages); app.use('/ngtest', ngtest); //app.use(function(req, res, next) { //req.session.numberOfVisits = req.session.numberOfVisits + 1 || 1; //res.send("Visits: " + req.session.numberOfVisits); //}); app.use(function(err, req, res, next) { if (typeof err == 'number') { // next(404); err = new HttpError(err); } if (err instanceof HttpError) { log.error(err); // res.sendHttpError(err); } else { if (app.get('env') == 'development') { var handler = errorhandler(); handler(err, req, res, next); } else { log.error(err); err = new HttpError(500); res.sendHttpError(err); } } }); }
function startApp() { console.info("Starting app..."); var app = express(); app.set('port', process.env.PORT || config.PORT); app.set('views', path.join(__dirname, 'src/views')); app.set('view engine', 'jade'); app.use(compress()); app.use(minify({js_match:/js/})); // all environments app.use(morgan('default')); app.use(bodyParser()); app.use(methodOverride()); app.use(cookieParser(config.COOKIE_SECRET)); var sessionStore; var opts = {}; for (var key in config.SESSION_STORE_OPTIONS) { opts[key] = config.SESSION_STORE_OPTIONS[key]; } if (config.SESSION_STORE_TYPE === 'MEMORY') { sessionStore = new session.MemoryStore(); console.log("MEMORY session store type configured"); } else if (config.SESSION_STORE_TYPE === 'REDIS') { var RedisStore = require('connect-redis')(session); var redis = require('redis').createClient(); opts.client = redis; sessionStore = new RedisStore(opts); console.log("REDIS session store type configured"); } app.use(session({store: sessionStore, cookie: {secure:config.SSL_ENABLED}})); app.post('/login', login.login); app.get('/logout', logout.logout); app.get('/:accountSecret?', routes.index); app.get('/roll/:rollId', roll.roll); app.use(serveStatic(path.join(__dirname, 'src/public'))); // development only if ('development' === app.get('env')) { var edt = require('express-debug'); edt(app, {}); app.use(errorhandler()); } var server; if (config.SSL_ENABLED) { server = https.createServer(server_options, app).listen(config.LISTENPORT, function () { console.log("Server listening on port " + config.LISTENPORT); }); sock.io = require('socket.io').listen(server, socketio_options); } else { server = http.createServer(app).listen(config.LISTENPORT, function () { console.log("Server listening on port " + config.LISTENPORT); }); sock.io = require('socket.io').listen(server); } sock.io.set('log level', 1); sock.io.set('browser client minification', true); sock.io.set('browser client etag', true); sock.io.set('browser client gzip', true); sock.io.sockets.on('connection', sock.onconnect); sock.io.set('authorization', function (handshakeData, accept) { if (handshakeData.headers.cookie) { handshakeData.cookie = cookie.parse(handshakeData.headers.cookie); handshakeData.sessionID = connect.utils.parseSignedCookie(handshakeData.cookie['connect.sid'],config.COOKIE_SECRET); sessionStore.get(handshakeData.sessionID, function (err, session) { if (err || !session) { console.error("Error getting handshakeData:",err); } else { handshakeData.session = session; } }); if (handshakeData.cookie['express.sid'] === handshakeData.sessionID) { return accept('Cookie is invalid.', false); } } else { return accept('No cookie transmitted.', false); } accept(null, true); }); // Export the app for grunt's sake module.exports = app; }
app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.use(compression()); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(methodOverride()); app.use(cookieParser()); app.use(morgan('dev')); app.use(express.static(path.join(__dirname, 'public'))); var env = process.env.NODE_ENV || 'development'; // development only if (env === 'development') { app.use(errorHandler()); // Error handler - has to be last } // production only if (env === 'production') { // TODO } /** * Routes */ // serve index and view partials app.get('/', routes.index); app.get('/partials/:name', routes.partials);
exports.start = function (config) { var server, JSONTYPES = { BOARD: 'board', STAGE: 'stage', TICKET: 'ticket', BRANCH: 'branch', AVATAR: 'avatar' }; cbCRUD.connect(config); app = express(); app.use(bodyParser()); app.use(cors()); app.set('showStackError', true); if (process.env.NODE_ENV === 'development') { app.use(morgan('dev')); } // Break each api area up into their own module // Boards app.route('/kanban/boards') .get(function (req, res) { cbCRUD.apiNotSupported(req, res); }) .post(function (req, res) { cbCRUD.createDoc(req, res, JSONTYPES.BOARD); }); app.route('/kanban/boards/:id') .get(function (req, res) { cbCRUD.getDoc(req, res, JSONTYPES.BOARD); }) .put(function (req, res) { cbCRUD.updateDoc(req, res, JSONTYPES.BOARD); }) .delete(function (req, res) { cbCRUD.deleteDoc(req, res, JSONTYPES.BOARD); }); // Stages app.route('/kanban/stages') .get(function (req, res) { cbCRUD.apiNotSupported(req, res); }) .post(function (req, res) { cbCRUD.createDoc(req, res, JSONTYPES.STAGE); }); app.route('/kanban/stages/:id') .get(function (req, res) { cbCRUD.getDoc(req, res, JSONTYPES.STAGE); }) .put(function (req, res) { cbCRUD.updateDoc(req, res, JSONTYPES.STAGE); }) .delete(function (req, res) { cbCRUD.deleteDoc(req, res, JSONTYPES.STAGE); }); // Tickets app.route('/kanban/tickets') .get(function (req, res) { cbCRUD.apiNotSupported(req, res); }) .post(function (req, res) { cbCRUD.createDoc(req, res, JSONTYPES.TICKET); }); app.route('/kanban/tickets/:id') .get(function (req, res) { cbCRUD.getDoc(req, res, JSONTYPES.TICKET); }) .put(function (req, res) { cbCRUD.updateDoc(req, res, JSONTYPES.TICKET); }) .delete(function (req, res) { cbCRUD.deleteDoc(req, res, JSONTYPES.TICKET); }); // Avatars app.route('/kanban/avatars') .get(function (req, res) { cbCRUD.apiNotSupported(req, res); }) .post(function (req, res) { cbCRUD.createDoc(req, res, JSONTYPES.AVATAR); }); app.route('/kanban/avatars/:id') .get(function (req, res) { cbCRUD.getDoc(req, res, JSONTYPES.AVATAR); }) .put(function (req, res) { cbCRUD.updateDoc(req, res, JSONTYPES.AVATAR); }) .delete(function (req, res) { cbCRUD.deleteDoc(req, res, JSONTYPES.AVATAR); }); if (process.env.NODE_ENV === 'development') { app.use(errorHandler()); } server = app.listen(3000, function () { console.log('Listening on port %d', server.address().port); }); };
module.exports.Dashing = function Dashing() { var dashing = {}; dashing.root = path.resolve(__dirname, '../../..'); dashing.NODE_ENV = process.env.NODE_ENV || 'development'; dashing.view_engine = process.env.VIEW_ENGINE || 'jade'; dashing.mincer = {}; dashing.mincer.environment = new Mincer.Environment(); dashing.mincer.assets_prefix = '/assets'; dashing.mincer.environment.appendPath('assets/javascripts'); dashing.mincer.environment.appendPath('assets/stylesheets'); dashing.mincer.environment.appendPath('assets/fonts'); dashing.mincer.environment.appendPath('assets/images'); dashing.mincer.environment.appendPath('widgets'); dashing.mincer.environment.appendPath(path.resolve(__dirname, '../javascripts')); dashing.public_folder = dashing.root + '/public'; dashing.views = dashing.root + '/dashboards'; dashing.settings = dashing.root + '/settings'; dashing.default_dashboard = null; dashing.port = (process.env.PORT || 3030); dashing.force_close_event_socket = false; dashing.protected = function(req, res, next) { next(); }; dashing._protected = function(req, res, next) { dashing.protected(req, res, next); } var expressLoggerOptions = { format: 'dev', stream: { write: function(message, encoding) { logger.info(message); } } }; // setup Express var app = express(); if (app.get('env') == 'development') { Mincer.logger.use(logger); } else { expressLoggerOptions.format = 'short'; // In production we assume that assets are not changed between requests, // so we use cached version of environment. // All file system methods are cached for the instances lifetime. dashing.mincer.environment = dashing.mincer.environment.index; } app.set('views', dashing.views); app.set('view engine', dashing.view_engine); if (dashing.view_engine === 'ejs') { app.use(require('express-ejs-layouts')); } app.use(morgan('dev')); app.use(errorHandler()); app.use(compression()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded()); app.use(methodOverride()); app.use(dashing.mincer.assets_prefix, Mincer.createServer(dashing.mincer.environment)); app.use(serveStatic(dashing.public_folder)); app.set('development', dashing.NODE_ENV === 'development'); app.set('production', dashing.NODE_ENV === 'production'); var connections = {}; app.get('/events', dashing._protected, function(req, res) { // let request last as long as possible req.socket.setTimeout(0); if (!dashing.force_close_event_socket) { // this won't be necessary if we close the connection after each data package var conn = { id: (new Date().getTime().toString() + Math.floor(Math.random() * 1000).toString()), send: function(body) { res.write(body); res.flush(); // need to flush with .compress() } }; connections[conn.id] = conn; } // send headers for event-stream connection res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'X-Accel-Buffering': 'no', // Disable buffering for nginx 'Access-Control-Allow-Origin': '*' //fix XHR issue }); res.write('\n'); res.write(Array(2049).join(' ') + '\n'); // 2kb padding for IE latest_events() .then( function(events) { if(events) { res.write(events); } }).done(function() { res.flush(); // need to flush with .compress() }); if (!dashing.force_close_event_socket) { req.on('close', function() { delete connections[conn.id]; }); } else { res.end(); } }); app.get('/', function(req, res) { if (dashing.default_dashboard) { res.redirect(dashing.default_dashboard); } else { first_dashboard(function(err, dashboard) { if (err) { next(err); } else if (dashboard) { res.redirect(dashboard); } else { next(new Error('There are no dashboards in your dashboard directory.')); } }); } }); app.get('/:dashboard', dashing._protected, function(req, res) { var dashboard = req.params.dashboard; fs.exists([dashing.views, dashboard + '.' + dashing.view_engine].join(path.sep), function(exists) { if (exists) { var templateVars = { dashboard: dashboard, request: req }; var settingsPath = [dashing.settings, dashboard + '.json'].join(path.sep); fs.exists(settingsPath, function(exists) { if (exists) { templateVars.settings = require(settingsPath); } res.render(dashboard, templateVars); }); } else { res.status(404).sendfile(dashing.public_folder + '/404.html'); } }); }); app.get('/views/:widget?.html', dashing._protected, function(req, res) { var widget = req.params.widget; res.sendfile([dashing.root, 'widgets', widget, widget + '.html'].join(path.sep)); }); app.post('/widgets/:id', function(req, res) { var auth_token = req.body.auth_token; if (!dashing.auth_token || dashing.auth_token == auth_token) { send_event(req.params.id, req.body); res.send(204); } else { res.send(401, 'Invalid API key'); } }); // The 404 Route (ALWAYS Keep this as the last route) app.use(function(req, res, next) { res.status(404).sendfile(dashing.public_folder + '/404.html'); }); // Error handler app.use(function(err, req, res, next) { logger.error(err.stack); res.send(500, err); }); function send_event(id, body) { body.id = id; body.updatedAt = Date.now(); var event = format_event(body); dashing.history.record(id, event); for (var k in connections) { connections[k].send(event); } } global.send_event = send_event; function format_event(body) { return 'data: ' + JSON.stringify(body) + '\n\n'; } function latest_events() { return Promise .resolve(dashing.history.getAll()) // assure trusted promise .reduce( function(agg, next) { return agg + next; }); } function first_dashboard(fn) { fs.readdir(dashing.views, function(err, files) { if (err) fn(err); var regex = new RegExp('(\w*)\.' + dashing.view_engine + '$'); for (var i in files) { var file = files[i]; if (file.match(regex) && file !== 'layout.' + dashing.view_engine) { fn(null, file.substring(0, file.length - (dashing.view_engine.length + 1))); return; } } fn(null, null); }); } // Load custom libraries fs.readdir([dashing.root, 'lib'].join(path.sep), function(err, files) { if (err) throw err; for (var i in files) { var file = [dashing.root, 'lib', files[i]].join(path.sep); require(file); } }); function start_jobs() { // Load jobs files var job_path = process.env.JOB_PATH || [dashing.root, 'jobs'].join(path.sep); logger.info('Searching for jobs in', job_path); fs.readdir(job_path, function(err, files) { if (err) throw err; for (var i in files) { var file = [job_path, files[i]].join(path.sep); if (file.match(/(\w*)\.job\.(js|coffee)$/)) { logger.info('Loading job file:', files[i]); try { require(file); } catch (e) { console.error('error while loading job (%s): ', file, e, e.stack); } } } }); } function start_express() { app.listen(dashing.port); logger.info('Listening on http://0.0.0.0:' + dashing.port + (process.env.__daemon === 'false' ? ', CTRL+C to stop' : '')); } dashing.useHistoryStore = function(store) { dashing.history = store; } dashing.start = function() { try { start_jobs(); start_express(); } catch(e) { logger.error("Unable to start dashing"); logger.error(e.toString()); // winston is not catching these? } } dashing.useHistoryStore(new InMemoryHistory()); dashing.app = app; return dashing; };
cookie: { secure: (_config.protocol === 'https' ? true : false) } })); // Templating app.set('view engine', 'ejs'); app.set('views', __dirname + '/views'); // Static folder app.use(serveStatic(__dirname + '/public')); // Compress response data with gzip / deflate app.use(compress()); // Development configuration if (!_PRODUCTION_) { app.use(errorhandler({ dumpExceptions: true, showStack: true })); // throw error on development } // Production configuration if (_PRODUCTION_) { // Redirect all on host app.use(function (req, res, next) { if (req.header('host') !== _config.host || req.protocol !== _config.protocol) return res.redirect(301, _config.protocol + '://' + _config.host + req.url); next(); }); _INFO_ = false; } // Routes require('./routes');
const appMain = () => { const app = express(); { // Settings if (process.env.NODE_ENV === 'development') { const webpackDevServer = require('./webpack-dev-server').default; webpackDevServer(app); // Error handler - https://github.com/expressjs/errorhandler // Development error handler, providing stack traces and error message responses // for requests accepting text, html, or json. app.use(errorhandler()); // a custom "verbose errors" setting which can be used in the templates via settings['verbose errors'] app.enable('verbose errors'); // Enables verbose errors in development app.disable('view cache'); // Disables view template compilation caching in development } else { // a custom "verbose errors" setting which can be used in the templates via settings['verbose errors'] app.disable('verbose errors'); // Disables verbose errors in production app.enable('view cache'); // Enables view template compilation caching in production } app.enable('trust proxy'); // Enables reverse proxy support, disabled by default app.enable('case sensitive routing'); // Enable case sensitivity, disabled by default, treating "/Foo" and "/foo" as the same app.disable('strict routing'); // Enable strict routing, by default "/foo" and "/foo/" are treated the same by the router app.disable('x-powered-by'); // Enables the X-Powered-By: Express HTTP header, enabled by default for (let i = 0; i < settings.view.engines.length; ++i) { const extension = settings.view.engines[i].extension; const template = settings.view.engines[i].template; app.engine(extension, engines[template]); } app.set('view engine', settings.view.defaultExtension); // The default engine extension to use when omitted app.set('views', [ path.resolve(__dirname, '../app'), path.resolve(__dirname, 'views') ]); // The view directory path log.debug('app.settings: %j', app.settings); } // Setup i18n (i18next) i18next .use(i18nextBackend) .use(i18nextLanguageDetector) .init(settings.i18next); app.use(async (req, res, next) => { try { // IP Address Access Control const ipaddr = req.ip || req.connection.remoteAddress; await authorizeIPAddress(ipaddr); } catch (err) { log.warn(err); res.status(ERR_FORBIDDEN).end('Forbidden Access'); return; } next(); }); // Removes the 'X-Powered-By' header in earlier versions of Express app.use((req, res, next) => { res.removeHeader('X-Powered-By'); next(); }); // Middleware // https://github.com/senchalabs/connect try { // https://github.com/valery-barysok/session-file-store const path = settings.middleware.session.path; // Defaults to './cncjs-sessions' rimraf.sync(path); fs.mkdirSync(path); const FileStore = sessionFileStore(session); app.use(session({ // https://github.com/expressjs/session#secret secret: settings.secret, // https://github.com/expressjs/session#resave resave: true, // https://github.com/expressjs/session#saveuninitialized saveUninitialized: true, store: new FileStore({ path: path, logFn: (...args) => { log.debug.apply(log, args); } }) })); } catch (err) { log.error(err); } app.use(favicon(path.join(_get(settings, 'assets.app.path', ''), 'favicon.ico'))); app.use(cookieParser()); // Connect's body parsing middleware. This only handles urlencoded and json bodies. // https://github.com/expressjs/body-parser app.use(bodyParser.json(settings.middleware['body-parser'].json)); app.use(bodyParser.urlencoded(settings.middleware['body-parser'].urlencoded)); // For multipart bodies, please use the following modules: // - [busboy](https://github.com/mscdex/busboy) and [connect-busboy](https://github.com/mscdex/connect-busboy) // - [multiparty](https://github.com/andrewrk/node-multiparty) and [connect-multiparty](https://github.com/andrewrk/connect-multiparty) app.use(multiparty(settings.middleware.multiparty)); // https://github.com/dominictarr/connect-restreamer // connect's bodyParser has a problem when using it with a proxy. // It gobbles up all the body events, so that the proxy doesn't see anything! app.use(connectRestreamer()); // https://github.com/expressjs/method-override app.use(methodOverride()); if (settings.verbosity > 0) { // https://github.com/expressjs/morgan#use-custom-token-formats // Add an ID to all requests and displays it using the :id token morgan.token('id', (req, res) => { return req.session.id; }); app.use(morgan(settings.middleware.morgan.format)); } app.use(compress(settings.middleware.compression)); Object.keys(settings.assets).forEach((name) => { const asset = settings.assets[name]; log.debug('assets: name=%s, asset=%s', name, JSON.stringify(asset)); if (!(asset.path)) { log.error('asset path is not defined'); return; } asset.routes.forEach((assetRoute) => { const route = urljoin(settings.route || '/', assetRoute || ''); log.debug('> route=%s', name, route); app.use(route, serveStatic(asset.path, { maxAge: asset.maxAge })); }); }); app.use(i18nextHandle(i18next, {})); { // Secure API Access app.use(urljoin(settings.route, 'api'), expressJwt({ secret: config.get('secret'), credentialsRequired: true })); app.use(async (err, req, res, next) => { let bypass = !(err && (err.name === 'UnauthorizedError')); // Check whether the app is running in development mode bypass = bypass || (process.env.NODE_ENV === 'development'); // Check whether the request path is not restricted const whitelist = [ // Also see "src/app/api/index.js" urljoin(settings.route, 'api/signin') ]; bypass = bypass || whitelist.some(path => { return req.path.indexOf(path) === 0; }); if (!bypass) { // Check whether the provided credential is correct const token = _get(req, 'query.token') || _get(req, 'body.token'); try { // User Validation const user = jwt.verify(token, settings.secret) || {}; await validateUser(user); bypass = true; } catch (err) { log.warn(err); } } if (!bypass) { const ipaddr = req.ip || req.connection.remoteAddress; log.warn(`Forbidden: ipaddr=${ipaddr}, code="${err.code}", message="${err.message}"`); res.status(ERR_FORBIDDEN).end('Forbidden Access'); return; } next(); }); } { // Register API routes with public access // Also see "src/app/app.js" app.post(urljoin(settings.route, 'api/signin'), api.users.signin); } { // Register API routes with authorized access // Version app.get(urljoin(settings.route, 'api/version/latest'), api.version.getLatestVersion); // State app.get(urljoin(settings.route, 'api/state'), api.state.get); app.post(urljoin(settings.route, 'api/state'), api.state.set); app.delete(urljoin(settings.route, 'api/state'), api.state.unset); // G-code app.get(urljoin(settings.route, 'api/gcode'), api.gcode.fetch); app.post(urljoin(settings.route, 'api/gcode'), api.gcode.upload); app.get(urljoin(settings.route, 'api/gcode/download'), api.gcode.download); app.post(urljoin(settings.route, 'api/gcode/download'), api.gcode.download); // Alias // Controllers app.get(urljoin(settings.route, 'api/controllers'), api.controllers.get); // Commands app.get(urljoin(settings.route, 'api/commands'), api.commands.fetch); app.post(urljoin(settings.route, 'api/commands'), api.commands.create); app.get(urljoin(settings.route, 'api/commands/:id'), api.commands.read); app.put(urljoin(settings.route, 'api/commands/:id'), api.commands.update); app.delete(urljoin(settings.route, 'api/commands/:id'), api.commands.__delete); app.post(urljoin(settings.route, 'api/commands/run/:id'), api.commands.run); // Events app.get(urljoin(settings.route, 'api/events'), api.events.fetch); app.post(urljoin(settings.route, 'api/events/'), api.events.create); app.get(urljoin(settings.route, 'api/events/:id'), api.events.read); app.put(urljoin(settings.route, 'api/events/:id'), api.events.update); app.delete(urljoin(settings.route, 'api/events/:id'), api.events.__delete); // Machines app.get(urljoin(settings.route, 'api/machines'), api.machines.fetch); app.post(urljoin(settings.route, 'api/machines'), api.machines.create); app.get(urljoin(settings.route, 'api/machines/:id'), api.machines.read); app.put(urljoin(settings.route, 'api/machines/:id'), api.machines.update); app.delete(urljoin(settings.route, 'api/machines/:id'), api.machines.__delete); // Macros app.get(urljoin(settings.route, 'api/macros'), api.macros.fetch); app.post(urljoin(settings.route, 'api/macros'), api.macros.create); app.get(urljoin(settings.route, 'api/macros/:id'), api.macros.read); app.put(urljoin(settings.route, 'api/macros/:id'), api.macros.update); app.delete(urljoin(settings.route, 'api/macros/:id'), api.macros.__delete); // MDI app.get(urljoin(settings.route, 'api/mdi'), api.mdi.fetch); app.post(urljoin(settings.route, 'api/mdi'), api.mdi.create); app.put(urljoin(settings.route, 'api/mdi'), api.mdi.bulkUpdate); app.get(urljoin(settings.route, 'api/mdi/:id'), api.mdi.read); app.put(urljoin(settings.route, 'api/mdi/:id'), api.mdi.update); app.delete(urljoin(settings.route, 'api/mdi/:id'), api.mdi.__delete); // Users app.get(urljoin(settings.route, 'api/users'), api.users.fetch); app.post(urljoin(settings.route, 'api/users/'), api.users.create); app.get(urljoin(settings.route, 'api/users/:id'), api.users.read); app.put(urljoin(settings.route, 'api/users/:id'), api.users.update); app.delete(urljoin(settings.route, 'api/users/:id'), api.users.__delete); // Watch app.get(urljoin(settings.route, 'api/watch/files'), api.watch.getFiles); app.post(urljoin(settings.route, 'api/watch/files'), api.watch.getFiles); app.get(urljoin(settings.route, 'api/watch/file'), api.watch.readFile); app.post(urljoin(settings.route, 'api/watch/file'), api.watch.readFile); } // page app.get(urljoin(settings.route, '/'), renderPage('index.hbs', (req, res) => { const webroot = _get(settings, 'assets.app.routes[0]', ''); // with trailing slash const lng = req.language; const t = req.t; return { webroot: webroot, lang: lng, title: `${t('title')} ${settings.version}`, loading: t('loading') }; })); { // Error handling app.use(errlog()); app.use(errclient({ error: 'XHR error' })); app.use(errnotfound({ view: path.join('common', '404.hogan'), error: 'Not found' })); app.use(errserver({ view: path.join('common', '500.hogan'), error: 'Internal server error' })); } return app; };
// new version of line app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(cors()); app.use(function(err, req, res, next) { if (err.name === 'StatusError') { res.send(err.status, err.message); } else { next(err); } }); if (process.env.NODE_ENV === 'development') { app.use(logger('dev')); app.use(errorhandler()); } var jwtCheck = jwt({ secret: config.secret }).unless({ path: ['/api/users/login', '/api/users/r', '/api/users/create'] }); app.use('/api', jwtCheck); // app.use(require('./anonymous-routes')); app.use('/api/homeworks', require('./homeworks')); app.use('/api/users', require('./users')); // app.use(require('./protected-routes')); // app.use(require('./user-routes')); //////////////
Configure(app).then(function() { app.updater = new Updater(app); app.isMacOs = (os.type() == 'Linux') ? false : true; // all environments app.set('host', app.config.host); app.set('port', app.config.port); app.set('views', path.join(paths.core, 'views')); app.set('view engine', 'jade'); passport.use(new LocalStrategy(function(username, password, done) { if(username == app.config.user.username) { bcrypt.compare(password, app.config.user.password, function(err, res) { if(res) { done(null, app.config.user); } else { done(null, false, { message: 'Incorrect username or password.' }); } }); } else { done(null, false, { message: 'Incorrect username or password.' }); } })); passport.serializeUser(function(username, done) { done(null, 1); }); passport.deserializeUser(function(userId, done) { done(null, app.config.user); }); //app.use(app.config.webRoot, favicon()); app.use(bodyParser()); app.use(methodOverride()); app.use(cookieParser()); app.use(session({ secret: app.config.salt, cookie: { maxAge: 24 * 60 * 60 * 1000 } })); app.use(csrf()); app.use(app.config.webRoot, stylus.middleware({src: paths.public, compile: function(str, path) { return stylus(str).set('filename', path) .use(nib()) }})); if(app.config.logHttpRequests) { app.use(morganLogger((app.config.runningMode == 'normal') ? 'default' : 'dev')); } if(app.config.runningMode == 'normal') { app.enable('trust proxy'); function blankLog() { this.log = function() {}; } app.use(app.config.webRoot, expressUglify.middleware({ src: paths.public, logger: new blankLog() })); app.use(app.config.webRoot, serveStatic(paths.public, { maxAge: 31557600000 })); app.use(errorHandler()); } else { app.locals.pretty = true; app.set('json spaces', 2); app.use(responseTime()); app.use(app.config.webRoot, serveStatic(paths.public)); app.use(errorHandler({ dumpExceptions: true, showStack: true })); } app.use(passport.initialize()); app.use(passport.session()); app.use(app.config.webRoot + '/templates', Common.templateFormat); }).then(function() {
app.use(bodyParser.urlencoded({ extended: false })) app.use(bodyParser.json()) app.use(cookieParser()) app.use(session({ secret: settings.cookieSecret, cookie: { maxAge: 1000 * 60 * 60 * 24 * 30 }, resave: false, saveUninitialized: true })) app.use(compression()) app.use(favicon(path.join(__dirname, 'public/imgs/favicon.ico'))) if ('development' === app.get('env')) { app.use(logger('dev')) app.use(errorHandler()) } app.use('/public', express.static(path.join(__dirname, 'public'))) routes(app) app.get('*', function (req, res) { res.sendFile(__dirname + '/public/index.html') }) app.listen(app.get('port'), function () { console.log('Server is running on ' + app.set('port')) })
module.exports = function (app, express, passport) { var allowCrossDomain = function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header('Access-Control-Allow-Credentials', true) res.header("Access-Control-Allow-Headers", "X-Requested-With"); next(); } // settings app .set('env', env) .set('port', app.config.server.port || 3000) .set('views', path.join(__dirname, '../../app/views')) .set('view engine', 'jade') app .enable('trust proxy') app .disable('x-powered-by') // Express use middlewares app .use(favicon(path.join(app.config.root, 'public/favicon.ico'))) .use(express.static(path.join(app.config.root, 'public'))) .use(bodyParser()) .use(multer()) .use(methodOverride()) .use(allowCrossDomain) app.use(cookieParser('notagoodsecretnoreallydontusethisone')) app.use(session({ secret: pkg.name, store: new MongoStore({ url: app.config.database.url, collection : 'sessions', auto_reconnect: true }) })) // use passport session app.use(passport.initialize()) app.use(passport.session({ maxAge: new Date(Date.now() + 3600000) })) app .use(function (req, res, next) { res.locals.pkg = pkg res.locals.NODE_ENV = env next() }) .use(flash()) .use(views_helpers(pkg.name)) /** ROUTES Apps */ app.use(routes.index) app.use(routes.user) app .use(function(err, req, res, next){ // treat as 404 if (err.message && (~err.message.indexOf('not found') || (~err.message.indexOf('Cast to ObjectId failed')))) { return next() } // log it // send emails if you want console.error(err.stack) // error page res.status(500).render('500', { error: err.stack }) }) .use(function(req, res, next){ res.status(404).render('404', { url: req.originalUrl, error: 'Not found' }) }) if(env === 'development') { app .use(logger('dev')) .use(errorHandler()) .use(responseTime()) } else { app .use(logger()) .use(compression({ filter: function (req, res) { return /json|text|javascript|css/.test(res.getHeader('Content-Type')) }, level: 9 })) .use(function logErrors(err, req, res, next){ if (err.status === 404) { return next(err) } if (err.logError === false) { return next(err) } console.error(err.stack) next(err) }) } }