UNPKG

domotz-remote-pawn

Version:

Domotz Agent

251 lines (210 loc) 8.46 kB
/** This file is part of Domotz Agent. * Copyright (C) 2016 Domotz Ltd * * Domotz Agent is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Domotz Agent is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>. **/ /** * * Created by Iacopo Papalini <ipapalini@domotz.com> on 08/09/15. */ /** * If the agent is not configured, the local web interface must be enabled * If the box registration outcome is 'failure', the local web interface must be enabled * @returns {boolean} True if the web app is enabled, false otherwise. */ function isWebAppEnabled(resourceLocator, myConsole) { if (process.env.BOX_REGISTRATION_OUTCOME === 'failure') { return true; } var isNotConfigured = !resourceLocator.status.isConfigured(); var isPassive = resourceLocator.status.isPassive(); var devMode = process.env.ENABLE_HTTP_TEST_API !== undefined; var webAppEnabledOverride = isNotConfigured || isPassive || devMode; var settingHttpLocalInterface = resourceLocator.lodash.get(resourceLocator, 'configuration.settings.http_local_interface', true); var webAppEnable = webAppEnabledOverride || settingHttpLocalInterface; myConsole.debug('isWebAppEnabled:%s', webAppEnable); return webAppEnable; } // Starts up an HTTP server that enables the hub setup var createApp = function (fs, http, express, event, bodyParser, favicon, path, routes, resourceLocator) { var myConsole = resourceLocator.log.decorateLogs(); var httpLocalInterfaceEnabled = isWebAppEnabled(resourceLocator, myConsole); var app = express(); app.disable('x-powered-by'); /** * Listening port: if not available, it will be increased until a free one is found * @type {number} */ var registrationFailedPort = 80; var boxRegistrationFailed = process.env.BOX_REGISTRATION_OUTCOME === 'failure'; var port = boxRegistrationFailed ? registrationFailedPort : process.env.LISTEN_PORT || '3000'; var portFile = process.env.DOMOTZ_LISTENER_PORT_FILE; if (process.platform === 'win32') { portFile = require('path').join(process.env.TEMP, 'domotz_listener.port'); } /** * The HTTP server * @type {null} */ var server = null; app.use(function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, X-API-Minor-Version, Authorization'); next(); }); if (boxRegistrationFailed) { initializeEmergencyRouting(app, fs, http, express, event, bodyParser, favicon, path, routes); } else if (httpLocalInterfaceEnabled) { initializeStandardRouting(app, fs, http, express, event, bodyParser, favicon, path, routes, myConsole); } else { myConsole.info('Agent local web interface disabled'); initializeRestrictedRouting(app, express, resourceLocator); } app.startServing = function () { app.set('port', port); server = http.createServer(app); app.set('server', server); myConsole.debug('WEBAPP - Try start domotz webapp on port ' + port); server.on('error', onError); server.on('listening', onListening); server.listen(port); }; /** * Event listener for HTTP server "listening" event. */ var onListening = function () { var port = app.get('port'); myConsole.info('WEBAPP - Domotz is listening on port ' + port + '... ' + 'Writing port number on ' + portFile); if (!boxRegistrationFailed) { setTimeout(event.onListeningWebapp, 2000); } myConsole.info('Triggering updatePkgInfo event'); resourceLocator.event.updatePkgInfo(); fs.writeFileSync(portFile, port); }; /** * Error handler: starts from * @param error */ var onError = function onError(error) { if (error.syscall !== 'listen') { myConsole.error('Error on System call ' + error.syscall); throw error; } var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': signalCriticalFailureAndExit(bind + ' requires elevated privileges'); break; case 'EADDRINUSE': port += 1; if (port < 65535) { app.startServing(); } else { signalCriticalFailureAndExit('Cannot find a free port to listen to'); } break; default: throw error; } }; /** * Logs a critical error and waits 30s then exit abnormally. * The wait is a cool down period before a possible restart. * @param message */ function signalCriticalFailureAndExit(message) { myConsole.error('signalCriticalFailureAndExit - ' + message); setTimeout(function () { process.exit(1); }, 30000); } return app; }; function initializeRestrictedRouting(app, express, resourceLocator) { app.get('/', function (req, res) { res.send( 'The Network Collector local Web Interface has been disabled. To re-enable it, please login into the WebApp and enable the "Network Collector Local Web Interface" in the Collector Settings page.' ); }); var router = express.Router(); var handler = require('./request_handlers/api/status')['get'](resourceLocator); var routes = router['get']('/api/v1/status', handler); app.use('/', routes); } function initializeEmergencyRouting(app, fs, http, express, event, bodyParser, favicon, path) { /** * Resource path */ var webappRootPath = path.join(__dirname, '..', '..', 'webapp', 'emergency'); app.use(express.static(webappRootPath)); } function initializeStandardRouting(app, fs, http, express, event, bodyParser, favicon, path, routes, myConsole) { var defaultTenant = 'domotz'; var tenant = process.env.TENANT || defaultTenant; /** * Resource path */ var viewsPath = path.join(__dirname, '..', '..', 'webapp', 'views'); var faviconPath = path.join(__dirname, '..', '..', 'webapp', 'resources', tenant, 'images', 'favicon.ico'); var webappRootPath = path.join(__dirname, '..', '..', 'webapp'); var resourcesPath = '/resources/'; var tenantResourcesPath = path.join(__dirname, '..', '..', 'webapp', 'resources', tenant, '/'); var varCssPath = '/node_modules/domotz-angular-widgets/resources/css/var.css'; var tenantVarCssPath = path.join( __dirname, '..', '..', 'webapp', 'node_modules', 'domotz-angular-widgets', 'resources', 'css', 'var.' + tenant + '.css' ); // view engine setup app.set('views', viewsPath); app.set('view engine', 'ejs'); app.use(favicon(faviconPath)); app.use(bodyParser.json({ limit: '10mb' })); // for parsing application/json app.use( bodyParser.raw({ limit: '100kb', type: '*/*', }) ); app.use(resourcesPath, express.static(tenantResourcesPath)); app.use(varCssPath, express.static(tenantVarCssPath)); app.use(express.static(webappRootPath)); app.use(function (req, res, next) { myConsole.info('API - (%s): %s', req.method, req.url); next(); }); app.use('/', routes); // catch 404 and forward to error handler app.use(function (req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); app.use(function (err, req, res) { res.status(err.status || 500); res.render('error', { message: err.message, error: err, }); }); } module.exports.createApp = createApp;