From ef04bade8ac79c356dd7772787c658bff2360779 Mon Sep 17 00:00:00 2001 From: childish-sambino Date: Mon, 15 Jun 2020 13:42:01 -0500 Subject: [PATCH] feat: add 'plugins:available' command that lists trusted, uninstalled plugins (#193) Fixes #117 --- src/commands/plugins/available.js | 16 +++++++++++ src/hooks/command-not-found.js | 20 +------------- src/hooks/plugin-install.js | 17 ++---------- src/services/plugins.js | 36 +++++++++++++++++++++++++ test/commands/plugins/available.test.js | 24 +++++++++++++++++ 5 files changed, 79 insertions(+), 34 deletions(-) create mode 100644 src/commands/plugins/available.js create mode 100644 src/services/plugins.js create mode 100644 test/commands/plugins/available.test.js diff --git a/src/commands/plugins/available.js b/src/commands/plugins/available.js new file mode 100644 index 000000000..dbf37929b --- /dev/null +++ b/src/commands/plugins/available.js @@ -0,0 +1,16 @@ +const { BaseCommand } = require('@twilio/cli-core').baseCommands; +const { getAvailablePlugins } = require('../../services/plugins'); + +class PluginsAvailable extends BaseCommand { + async run() { + await super.run(); + + getAvailablePlugins(this.config) + .forEach(pluginName => this.logger.info(pluginName)); + } +} + +PluginsAvailable.description = 'list available plugins for installation'; +PluginsAvailable.flags = null; + +module.exports = PluginsAvailable; diff --git a/src/hooks/command-not-found.js b/src/hooks/command-not-found.js index d5c46e010..7f401d13b 100644 --- a/src/hooks/command-not-found.js +++ b/src/hooks/command-not-found.js @@ -1,24 +1,6 @@ const Plugins = require('@oclif/plugin-plugins').default; const { logger } = require('@twilio/cli-core').services.logging; - -const PLUGIN_COMMANDS = { - '@twilio-labs/plugin-flex': ['flex'], - '@twilio-labs/plugin-rtc': ['rtc'], - '@twilio-labs/plugin-serverless': ['serverless'], - '@twilio-labs/plugin-token': ['token'], - '@twilio-labs/plugin-watch': ['watch'], - '@dabblelab/plugin-autopilot': ['autopilot'] -}; - -const getSupportedPlugin = commandId => { - return Object.keys(PLUGIN_COMMANDS).find(plugin => { - return PLUGIN_COMMANDS[plugin].find(command => commandId === command || commandId.startsWith(command + ':')); - }); -}; - -const isPluginInstalled = (config, pluginName) => { - return config.plugins.find(p => p.name === pluginName); -}; +const { getSupportedPlugin, isPluginInstalled } = require('../services/plugins'); const installPlugin = async (config, pluginName) => { const plugins = new Plugins(config); diff --git a/src/hooks/plugin-install.js b/src/hooks/plugin-install.js index b63c88028..9ecd04d12 100644 --- a/src/hooks/plugin-install.js +++ b/src/hooks/plugin-install.js @@ -1,21 +1,8 @@ const { logger } = require('@twilio/cli-core').services.logging; -const ALLOWED_ORGS = [ - '@twilio/', - '@twilio-labs/', - '@dabblelab/plugin-autopilot' -]; - -function isTwilioPlugin(options) { - if (options.plugin.name === undefined) { - return false; - } - return ALLOWED_ORGS.find(function (org) { - return options.plugin.name.startsWith(org); - }); -} +const { isTwilioPlugin } = require('../services/plugins'); module.exports = async function (options) { - if (!isTwilioPlugin(options)) { + if (!isTwilioPlugin(options.plugin.name)) { logger.warn('WARNING!!! You are attempting to install a plugin from an untrusted source.'); logger.warn('It could contain malicious software or in other ways compromise your system.'); diff --git a/src/services/plugins.js b/src/services/plugins.js new file mode 100644 index 000000000..91df40153 --- /dev/null +++ b/src/services/plugins.js @@ -0,0 +1,36 @@ +const ALLOWED_ORGS = [ + '@twilio/', + '@twilio-labs/', + '@dabblelab/plugin-autopilot' +]; + +const PLUGIN_COMMANDS = { + '@twilio-labs/plugin-flex': ['flex'], + '@twilio-labs/plugin-rtc': ['rtc'], + '@twilio-labs/plugin-serverless': ['serverless'], + '@twilio-labs/plugin-token': ['token'], + '@twilio-labs/plugin-watch': ['watch'], + '@dabblelab/plugin-autopilot': ['autopilot'] +}; + +exports.isTwilioPlugin = pluginName => { + if (pluginName === undefined) { + return false; + } + return ALLOWED_ORGS.find(org => pluginName.startsWith(org)); +}; + +exports.isPluginInstalled = (config, pluginName) => { + return config.plugins.find(p => p.name === pluginName); +}; + +exports.getSupportedPlugin = commandId => { + return Object.keys(PLUGIN_COMMANDS).find(plugin => { + return PLUGIN_COMMANDS[plugin].find(command => commandId === command || commandId.startsWith(command + ':')); + }); +}; + +exports.getAvailablePlugins = config => { + return Object.keys(PLUGIN_COMMANDS) + .filter(pluginName => !exports.isPluginInstalled(config, pluginName)); +}; diff --git a/test/commands/plugins/available.test.js b/test/commands/plugins/available.test.js new file mode 100644 index 000000000..f6ea76297 --- /dev/null +++ b/test/commands/plugins/available.test.js @@ -0,0 +1,24 @@ +const { expect, test } = require('@twilio/cli-test'); +const PluginsAvailable = require('../../../src/commands/plugins/available'); + +describe('commands', () => { + describe('plugins', () => { + describe('available', () => { + const testConfig = test + .twilioCliEnv() + .stderr() + .do(ctx => { + ctx.fakeConfig.plugins = [{ name: '@twilio-labs/plugin-watch' }]; + }) + .twilioCommand(PluginsAvailable, []); + + testConfig.it('should print out available plugins', ctx => { + expect(ctx.stderr).to.contain('@twilio-labs/plugin-serverless'); + }); + + testConfig.it('should not print out installed plugins', ctx => { + expect(ctx.stderr).to.not.contain('@twilio-labs/plugin-watch'); + }); + }); + }); +});