Files
NodeBB/app.js

360 lines
10 KiB
JavaScript
Raw Normal View History

2013-07-11 12:14:49 -04:00
/*
2014-07-11 16:26:20 -04:00
NodeBB - A better forum platform for the modern web
https://github.com/NodeBB/NodeBB/
Copyright (C) 2013-2014 NodeBB Inc.
2013-07-11 12:14:49 -04:00
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
2014-02-02 01:38:46 -05:00
"use strict";
2014-04-23 21:20:40 -04:00
/*global require, global, process*/
2014-02-02 01:38:46 -05:00
var nconf = require('nconf');
nconf.argv().env();
var fs = require('fs'),
os = require('os'),
semver = require('semver'),
winston = require('winston'),
path = require('path'),
cluster = require('cluster'),
2014-02-02 01:38:46 -05:00
pkg = require('./package.json'),
utils = require('./public/src/utils.js');
2014-02-02 01:38:46 -05:00
global.env = process.env.NODE_ENV || 'production';
2014-02-02 01:38:46 -05:00
winston.remove(winston.transports.Console);
winston.add(winston.transports.Console, {
2014-10-26 18:46:50 -04:00
colorize: true,
2014-11-13 13:52:46 -05:00
timestamp: function() {
var date = new Date;
return date.getDate() + '/' + (date.getMonth() + 1) + ' ' + date.getHours() + ':' + date.getMinutes() + ' [' + global.process.pid + ']';
},
2014-11-11 13:18:41 -05:00
level: global.env === 'production' ? 'info' : 'verbose'
2014-02-02 01:38:46 -05:00
});
// TODO: remove once https://github.com/flatiron/winston/issues/280 is fixed
winston.err = function (err) {
winston.error(err.stack);
};
if(os.platform() === 'linux') {
2013-12-07 16:51:47 -05:00
require('child_process').exec('/usr/bin/which convert', function(err, stdout, stderr) {
2013-12-07 17:03:07 -05:00
if(err || !stdout) {
2013-12-08 14:49:47 -05:00
winston.warn('Couldn\'t find convert. Did you install imagemagick?');
2013-12-07 16:51:47 -05:00
}
});
2014-02-02 01:38:46 -05:00
}
2013-12-07 16:51:47 -05:00
if (!cluster.isWorker) {
// If run using `node app`, log GNU copyright info along with server info
winston.info('NodeBB v' + pkg.version + ' Copyright (C) 2013-2014 NodeBB Inc.');
winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
winston.info('');
}
2013-09-10 16:26:26 -04:00
2014-02-14 11:49:16 -05:00
// Alternate configuration file support
2014-05-31 16:53:18 -04:00
var configFile = path.join(__dirname, '/config.json'),
2014-02-14 11:49:16 -05:00
configExists;
2014-05-31 16:53:18 -04:00
2014-02-14 11:49:16 -05:00
if (nconf.get('config')) {
2014-03-21 23:04:27 +00:00
configFile = path.resolve(__dirname, nconf.get('config'));
2014-02-14 11:49:16 -05:00
}
configExists = fs.existsSync(configFile);
2013-09-10 16:26:26 -04:00
if (!nconf.get('setup') && !nconf.get('install') && !nconf.get('upgrade') && !nconf.get('reset') && configExists) {
2014-02-02 01:38:46 -05:00
start();
2014-02-14 11:49:16 -05:00
} else if (nconf.get('setup') || nconf.get('install') || !configExists) {
2014-02-02 01:38:46 -05:00
setup();
} else if (nconf.get('upgrade')) {
upgrade();
2014-02-18 17:43:32 -05:00
} else if (nconf.get('reset')) {
2014-04-08 15:29:51 -04:00
reset();
2014-03-02 14:45:57 -05:00
}
2014-02-27 01:32:20 -05:00
function loadConfig() {
2014-02-02 01:38:46 -05:00
nconf.file({
file: configFile
2014-02-02 01:38:46 -05:00
});
nconf.defaults({
2014-04-08 16:52:50 -04:00
base_dir: __dirname,
themes_path: path.join(__dirname, 'node_modules'),
2014-11-13 13:00:36 -05:00
upload_url: nconf.get('relative_path') + '/uploads/',
2014-04-08 16:52:50 -04:00
views_dir: path.join(__dirname, 'public/templates')
});
2014-02-27 01:32:20 -05:00
// Ensure themes_path is a full filepath
nconf.set('themes_path', path.resolve(__dirname, nconf.get('themes_path')));
nconf.set('core_templates_path', path.join(__dirname, 'src/views'));
nconf.set('base_templates_path', path.join(nconf.get('themes_path'), 'nodebb-theme-vanilla/templates'));
2014-02-27 01:32:20 -05:00
}
function start() {
loadConfig();
2014-10-22 13:47:05 -04:00
if (!cluster.isWorker || process.env.cluster_setup === 'true') {
winston.info('Time: ' + new Date());
winston.info('Initializing NodeBB v' + pkg.version);
winston.info('* using configuration stored in: ' + configFile);
}
2014-04-11 01:38:47 -04:00
if (cluster.isWorker && process.env.cluster_setup === 'true') {
var host = nconf.get(nconf.get('database') + ':host'),
storeLocation = host ? 'at ' + host + (host.indexOf('/') === -1 ? ':' + nconf.get(nconf.get('database') + ':port') : '') : '';
2014-01-05 23:57:43 -05:00
winston.info('* using ' + nconf.get('database') +' store ' + storeLocation);
winston.info('* using themes stored in: ' + nconf.get('themes_path'));
2014-02-02 01:38:46 -05:00
}
require('./src/database').init(function(err) {
2014-07-05 00:11:21 -04:00
if (err) {
winston.error(err.stack);
process.exit();
}
2014-07-05 00:19:19 -04:00
var meta = require('./src/meta');
2014-02-02 01:38:46 -05:00
meta.configs.init(function () {
2014-06-25 18:55:22 -04:00
var templates = require('templates.js'),
2014-02-02 01:38:46 -05:00
webserver = require('./src/webserver'),
sockets = require('./src/socket.io'),
plugins = require('./src/plugins'),
2014-07-05 00:19:19 -04:00
upgrade = require('./src/upgrade');
2014-02-02 01:38:46 -05:00
templates.setGlobal('relative_path', nconf.get('relative_path'));
2014-02-02 01:38:46 -05:00
upgrade.check(function(schema_ok) {
if (schema_ok || nconf.get('check-schema') === false) {
sockets.init(webserver.server);
2013-12-31 17:01:51 -05:00
2014-04-08 16:52:50 -04:00
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path'));
2014-02-02 01:38:46 -05:00
plugins.ready(function() {
2014-08-25 11:56:48 -04:00
webserver.init(function() {
webserver.listen(function() {
process.send({
action: 'ready'
});
2014-08-25 11:56:48 -04:00
});
});
2014-02-02 01:38:46 -05:00
});
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);
process.on('SIGHUP', restart);
process.on('message', function(message) {
switch(message.action) {
case 'reload':
meta.reload();
break;
case 'js-propagate':
meta.js.cache = message.cache;
meta.js.map = message.map;
winston.info('[cluster] Client-side javascript and mapping propagated to worker ' + cluster.worker.id);
break;
2014-09-29 19:31:27 -04:00
case 'css-propagate':
meta.css.cache = message.cache;
meta.css.acpCache = message.acpCache;
winston.info('[cluster] Stylesheets propagated to worker ' + cluster.worker.id);
2014-09-29 19:31:27 -04:00
break;
}
2014-09-29 16:58:23 -04:00
});
2014-10-15 16:19:27 -04:00
process.on('uncaughtException', function(err) {
2014-10-15 16:19:27 -04:00
winston.error(err.stack);
console.log(err.stack);
2014-04-17 13:04:46 -04:00
meta.js.killMinifier();
shutdown(1);
2014-07-05 00:11:40 -04:00
});
2014-02-02 01:38:46 -05:00
} else {
winston.warn('Your NodeBB schema is out-of-date. Please run the following command to bring your dataset up to spec:');
winston.warn(' ./nodebb upgrade');
if (cluster.isWorker) {
cluster.worker.kill();
} else {
process.exit();
}
2014-02-02 01:38:46 -05:00
}
});
});
2014-02-02 01:38:46 -05:00
});
}
2014-02-02 01:38:46 -05:00
function setup() {
2014-02-27 01:32:20 -05:00
loadConfig();
2014-02-02 01:38:46 -05:00
if (nconf.get('setup')) {
winston.info('NodeBB Setup Triggered via Command Line');
} else {
winston.warn('Configuration not found, starting NodeBB setup');
}
2014-02-02 01:38:46 -05:00
var install = require('./src/install');
2013-09-10 16:26:26 -04:00
2014-02-02 01:38:46 -05:00
winston.info('Welcome to NodeBB!');
winston.info('This looks like a new installation, so you\'ll have to answer a few questions about your environment before we can proceed.');
winston.info('Press enter to accept the default setting (shown in brackets).');
2013-08-23 13:14:36 -04:00
2014-02-02 01:38:46 -05:00
install.setup(function (err) {
if (err) {
winston.error('There was a problem completing NodeBB setup: ', err.message);
} else {
winston.info('NodeBB Setup Completed. Run \'./nodebb start\' to manually start your NodeBB server.');
}
2014-02-02 01:38:46 -05:00
process.exit();
});
}
2014-02-02 01:38:46 -05:00
function upgrade() {
2014-02-27 01:32:20 -05:00
loadConfig();
2014-02-02 01:38:46 -05:00
require('./src/database').init(function(err) {
2014-07-05 00:11:21 -04:00
if (err) {
winston.error(err.stack);
process.exit();
}
2014-07-05 00:19:19 -04:00
require('./src/meta').configs.init(function () {
2014-02-02 01:38:46 -05:00
require('./src/upgrade').upgrade();
});
2014-02-02 01:38:46 -05:00
});
}
2014-04-08 15:29:51 -04:00
function reset() {
loadConfig();
require('./src/database').init(function(err) {
if (err) {
2014-04-08 16:03:42 -04:00
winston.error(err.message);
2014-04-08 15:29:51 -04:00
process.exit();
}
2014-04-08 16:03:42 -04:00
if (nconf.get('themes')) {
resetThemes();
} else if (nconf.get('plugin')) {
resetPlugin(nconf.get('plugin'));
2014-04-08 16:03:42 -04:00
} else if (nconf.get('plugins')) {
resetPlugins();
} else if (nconf.get('widgets')) {
resetWidgets();
} else if (nconf.get('settings')) {
resetSettings();
} else if (nconf.get('all')) {
require('async').series([resetWidgets, resetThemes, resetPlugins, resetSettings], function(err) {
if (!err) {
winston.info('[reset] Reset complete.');
} else {
winston.error('[reset] Errors were encountered while resetting your forum settings: ' + err.message);
}
2014-04-08 15:29:51 -04:00
process.exit();
2014-04-08 16:03:42 -04:00
});
} else {
winston.warn('[reset] Nothing reset.');
2014-04-08 16:03:42 -04:00
}
});
}
function resetSettings(callback) {
var meta = require('./src/meta');
meta.configs.set('allowLocalLogin', 1, function(err) {
2014-04-08 16:50:23 -04:00
winston.info('[reset] Settings reset to default');
2014-04-08 16:03:42 -04:00
if (typeof callback === 'function') {
callback(err);
} else {
process.exit();
}
2014-04-08 15:29:51 -04:00
});
}
function resetThemes(callback) {
2014-04-08 16:03:42 -04:00
var meta = require('./src/meta');
2014-02-18 17:43:32 -05:00
2014-04-08 16:03:42 -04:00
meta.themes.set({
type: 'local',
id: 'nodebb-theme-vanilla'
}, function(err) {
winston.info('[reset] Theme reset to Vanilla');
if (typeof callback === 'function') {
callback(err);
} else {
process.exit();
}
});
}
function resetPlugin(pluginId) {
var db = require('./src/database');
db.setRemove('plugins:active', pluginId, function(err, result) {
if (err || result !== 1) {
winston.error('[reset] Could not disable plugin: ' + pluginId);
if (err) {
winston.error('[reset] Encountered error: ' + err.message);
} else {
winston.info('[reset] Perhaps it has already been disabled?');
}
} else {
winston.info('[reset] Plugin `' + pluginId + '` disabled');
}
process.exit();
});
}
function resetPlugins(callback) {
var db = require('./src/database');
2014-04-08 16:03:42 -04:00
db.delete('plugins:active', function(err) {
winston.info('[reset] All Plugins De-activated');
if (typeof callback === 'function') {
callback(err);
} else {
process.exit();
}
2014-02-18 17:43:32 -05:00
});
}
2014-04-07 17:52:48 -04:00
function resetWidgets(callback) {
2014-04-08 16:03:42 -04:00
require('./src/widgets').reset(function(err) {
winston.info('[reset] All Widgets moved to Draft Zone');
if (typeof callback === 'function') {
callback(err);
} else {
process.exit();
}
2014-04-07 17:52:48 -04:00
});
}
function shutdown(code) {
winston.info('[app] Shutdown (SIGTERM/SIGINT) Initialised.');
2014-03-02 14:00:28 -05:00
require('./src/database').close();
winston.info('[app] Database connection closed.');
2014-08-25 11:56:48 -04:00
require('./src/webserver').server.close();
winston.info('[app] Web server closed to connections.');
winston.info('[app] Shutdown complete.');
process.exit(code || 0);
}
function restart() {
if (process.send) {
winston.info('[app] Restarting...');
process.send({
action: 'restart'
});
} else {
winston.error('[app] Could not restart server. Shutting down.');
shutdown(1);
}
}