From bf039f2103d51c46f6fe75b1740b6cbf578156a8 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Sun, 7 May 2017 21:56:37 +0200 Subject: [PATCH] Rewrote plugins loading (#1) --- server/config.ts | 87 ---------------------------------- server/controllers/routes.js | 38 --------------- server/index.ts | 29 ++++++------ server/router.ts | 5 ++ server/scripts/sethome.ts | 53 --------------------- server/scripts/updateschema.js | 29 ------------ server/utils/handleErrors.ts | 3 ++ server/utils/pluginsLoader.ts | 57 ++++++++++++++++++++++ 8 files changed, 79 insertions(+), 222 deletions(-) delete mode 100644 server/config.ts delete mode 100644 server/controllers/routes.js delete mode 100644 server/scripts/sethome.ts delete mode 100644 server/scripts/updateschema.js create mode 100644 server/utils/pluginsLoader.ts diff --git a/server/config.ts b/server/config.ts deleted file mode 100644 index 007f06d..0000000 --- a/server/config.ts +++ /dev/null @@ -1,87 +0,0 @@ -import * as p from './lib/plugins'; -import * as passport from 'passport'; -import {passportConfig} from './utils/passportConfig' - -var americano = require('americano'), - fs = require('fs'), - path = require('path'); - -var root = path.resolve('./plugins'); - -var config = { - common: { - use: [ - passport.initialize(), - americano.bodyParser.urlencoded({ extended: false }), - americano.bodyParser.json(), - americano.methodOverride(), - americano.static(__dirname + '/../../client/public', { - maxAge: 86400000 - }) - ], - useAfter: [ - americano.errorHandler({ - dumpExceptions: true, - showStack: true - }), - ] - }, - development: [ - americano.logger('dev') - ], - production: [ - americano.logger('short') - ] -}; - -// Configure passport -passportConfig(); - -// Check and update plugins currently stored in the database -p.PluginConnector.update((err) => { - if(err) { - console.error(err); - process.exit(1); - } -}); - -// Retrieve a list of the plugins currently present in the /plugins directory -var plugins = fs.readdirSync(root).filter(file => fs.statSync(path.join(root, file)).isDirectory()); - -// Add plugin's public directories as static routes -for(let plugin of plugins) { - // Get instance of the connector so the plugin gets registered if - // it wasn't before - p.PluginConnector.getInstance(plugin, (err, connector) => { - if(err) return console.error(err); - if(!connector) { - console.error(new Error('Couldn\'t get database connector')); - return process.exit(1); - } - - connector.getState((err, state) => { - if(err) { - console.error(err); - return process.exit(1); - } - // Only create the root if the plugin is enabled - if(state === p.State.enabled) { - // Get the plugin's public path - let pluginPublicPath = path.join(root, plugin, 'public'); - - // Check if the plugin has a public directory - if(fs.existsSync(pluginPublicPath)) { - // Create a static route for the plugin - config.common.use.push([ - '/' + plugin, - americano.static(pluginPublicPath, { - maxAge: 86400000 - }) - ]); - } - } - }); - }); -} - -module.exports = config; \ No newline at end of file diff --git a/server/controllers/routes.js b/server/controllers/routes.js deleted file mode 100644 index 8df41cc..0000000 --- a/server/controllers/routes.js +++ /dev/null @@ -1,38 +0,0 @@ -const data = require('./pluginData'); -const plugin = require('./plugin'); -const admin = require('./admin'); -const user = require('./user'); - -const passport = require('passport'); - -module.exports = { - 'auth': { - post: user.auth - }, - 'auth/:user': { - get: user.get, - post: user.add, - put: user.update, - delete: user.delete - }, - 'api/plugins': { - get: plugin.getList - }, - 'api/home': { - get: plugin.home, - post: admin.home - }, - 'api/:plugin/data': { // Plugins' data - get: data.get, - post: data.add, - put: data.replace, - delete: data.delete - }, - 'api/:plugin/state': { // Plugins' state - get: plugin.state, - put: admin.changeState // Only admin can edit a plugin's state - }, - 'api/:plugin/access': { // Get a user's access level to a plugin - post: admin.setAccessLevel - } -}; \ No newline at end of file diff --git a/server/index.ts b/server/index.ts index 440287f..843847a 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,6 +1,7 @@ import * as Hapi from 'hapi'; import {loadRoutes} from './utils/routesLoader'; +import {loadPlugins} from './utils/pluginsLoader'; const pkg = require('../../package.json'); const log = require('printit')({ @@ -33,17 +34,15 @@ server.connection({ port: port, host: host }); server.register([ require('inert'), + require('vision'), { register: require('hapi-swagger'), - options: { - info: { - 'title': pkg.name, - 'description': pkg.description, - 'version': pkg.version, - }, - } - }, - require('vision') + options: { info: { + 'title': pkg.name, + 'description': pkg.description, + 'version': pkg.version, + }} + } ], (err) => { if(err) { log.error(err); @@ -54,16 +53,16 @@ server.register([ server.route({ method: 'GET', path: '/{file*}', - handler: { - directory: { - path: __dirname + '/../client/', - listing: true - } - } + handler: { directory: { + path: __dirname + '/../client/', + listing: true + }} }); // Load the routes from the main router loadRoutes(server); + // Load the install plugins + loadPlugins(server); }); // Start the server diff --git a/server/router.ts b/server/router.ts index 7c6d6c7..eee428f 100644 --- a/server/router.ts +++ b/server/router.ts @@ -1 +1,6 @@ +import * as admin from './controllers/admin'; +import * as data from './controllers/pluginData'; +import * as plugin from './controllers/plugin'; +import * as user from './controllers/user'; + module.exports = {} \ No newline at end of file diff --git a/server/scripts/sethome.ts b/server/scripts/sethome.ts deleted file mode 100644 index 9a1b20f..0000000 --- a/server/scripts/sethome.ts +++ /dev/null @@ -1,53 +0,0 @@ -import {PluginConnector} from '../lib/plugins'; - -const args = process.argv.slice(2); - -function displayHelp(): void { - console.log('Usage: npm run sethome -- [OPTIONS]\n'); - console.log('Options:'); - console.log(' --plugin PLUGIN\tSets PLUGIN as the new home plugin'); - console.log(' --disable-previous\tDisables the previous home plugin (warning: if not used, the previous home plugin will stay enabled)'); - console.log(' --from-settings\tUses the plugin set in the settings.json file instead of the one provided as command line argument') -} - -if(!args.length) { - displayHelp(); - process.exit(1); -} - -let name = args[0]; -let disableOld = false; - -let fromSettings = false; - -for(var i = 0; i < args.length; i++) { - let arg = args[i]; - switch(arg) { - case '--plugin': - i++; - name = args[i]; - break - case '--disable-previous': - disableOld = true; - break; - case '--from-settings': - name = require('./settings').home; - fromSettings = true; - break; - case '--help': - default: - displayHelp(); - process.exit(0); - } -} - -PluginConnector.getInstance(name, (err, connector) => { - if(!connector) return console.error('Couldn\'t get database connector'); - connector.setHome(false, (err) => { - if(err) { - console.error('Error when setting home plugin to ' + name + ':', err.message); - process.exit(1); - } - console.log('Home set to plugin', name); - }); -}); \ No newline at end of file diff --git a/server/scripts/updateschema.js b/server/scripts/updateschema.js deleted file mode 100644 index 8f5c3b8..0000000 --- a/server/scripts/updateschema.js +++ /dev/null @@ -1,29 +0,0 @@ -import {PluginConnector} from '../lib/plugins'; - -const args = process.argv.slice(2); - -if(!args.length) { - console.error('Please specify at least one plugin name'); - process.exit(1); -} - -// JS script cause tsc messes up promises -let updates = args.map((name) => { - return new Promise((resolve, reject) => { - PluginConnector.updateSchema(name, (err) => { - if(err) { - return reject('Error while updating ' + name + ': ' + err.message); - } else { - return resolve(name); - } - }); - }); -}); - -Promise.all(updates).then((names) => { - for(let name in names) console.log('Schema updated for', names[name]); - process.exit(0); -}).catch((err) => { - console.error(err); - process.exit(1); -}); \ No newline at end of file diff --git a/server/utils/handleErrors.ts b/server/utils/handleErrors.ts index ff366a6..4a57fad 100644 --- a/server/utils/handleErrors.ts +++ b/server/utils/handleErrors.ts @@ -13,6 +13,9 @@ export function handleErr(err: Error, res: e.Response): void { case 'NUMBER_MISSING': code = 400; break; + case 'UNAUTHORISED': + code = 401; + break; case 'NOT_ADMIN': case 'PLUGIN_DISABLED': code = 403; diff --git a/server/utils/pluginsLoader.ts b/server/utils/pluginsLoader.ts new file mode 100644 index 0000000..44f1d18 --- /dev/null +++ b/server/utils/pluginsLoader.ts @@ -0,0 +1,57 @@ +import * as path from 'path'; +import * as fs from 'fs'; + +import * as Hapi from 'hapi'; + +import * as Plugins from '../lib/plugins'; + +const log = require('printit')({ + date: true, + prefix: 'Plugins' +}); + +const root = path.resolve('./plugins'); + +export function loadPlugins(server: Hapi.Server) { + // Check and update plugins currently stored in the database + Plugins.PluginConnector.update().catch(processError); + + // Retrieve a list of the plugins currently present in the /plugins directory + let plugins = fs.readdirSync(root).filter(file => fs.statSync(path.join(root, file)).isDirectory()); + + // Add plugin's public directories as static routes + for(let plugin of plugins) { + // Get instance of the connector so the plugin gets registered if + // it wasn't before + Plugins.PluginConnector.getInstance(plugin) + .then((connector) => { + if(!connector) throw new Error('Couldn\'t get database connector'); + + return connector.getState() + }).then((state) => { + // Only create the root if the plugin is enabled + if(state === Plugins.State.enabled) { + // Get the plugin's public path + let pluginPublicPath = path.join(root, plugin, 'public'); + + // Check if the plugin has a public directory + if(fs.existsSync(pluginPublicPath)) { + // Create a static route for the plugin + server.route({ + method: 'GET', + path: '/' + plugin + '/{file*}', + handler: { directory: { + path: __dirname + pluginPublicPath, + listing: true + }} + }); + } + } + }).catch(processError); + } +} + +function processError(e) { + log.error(e); + process.exit(1); +} \ No newline at end of file