From f56b9760ad2483c2dc1d6052f073fde031eb08c8 Mon Sep 17 00:00:00 2001
From: "Juan Picado @jotadeveloper" <juanpicado19@gmail.com>
Date: Thu, 30 Nov 2017 08:26:33 +0100
Subject: [PATCH] refactor: better bootstrap structure

---
 src/lib/bootstrap.js   | 132 ++++++++++++++++++++++-------------------
 src/lib/cli.js         |   2 +-
 src/lib/config-path.js |   6 +-
 3 files changed, 77 insertions(+), 63 deletions(-)

diff --git a/src/lib/bootstrap.js b/src/lib/bootstrap.js
index 9af78d311..156864f27 100644
--- a/src/lib/bootstrap.js
+++ b/src/lib/bootstrap.js
@@ -1,16 +1,16 @@
 import isFunction from 'lodash/isFunction';
+import assign from 'lodash/assign';
 import Path from 'path';
 import URL from 'url';
 import fs from 'fs';
 import http from'http';
 import https from 'https';
+import constants from 'constants';
+import chalk from 'chalk';
 
 const server = require('../api/index');
 const Utils = require('./utils');
 const logger = require('./logger');
-const constants = require('constants');
-// const pkgVersion = module.exports.version;
-// const pkgName = module.exports.name;
 
 /**
  * Retrieve all addresses defined in the config file.
@@ -36,7 +36,7 @@ function getListListenAddresses(argListen, configListen) {
     addresses = ['4873'];
   }
   addresses = addresses.map(function(addr) {
-    let parsed_addr = Utils.parse_address(addr);
+    const parsed_addr = Utils.parse_address(addr);
 
     if (!parsed_addr) {
       logger.logger.warn({addr: addr},
@@ -55,13 +55,13 @@ function getListListenAddresses(argListen, configListen) {
  * Trigger the server after configuration has been loaded.
  * @param {Object} config
  * @param {Object} cliArguments
- * @param {String} config_path
+ * @param {String} configPath
  * @param {String} pkgVersion
  * @param {String} pkgName
  */
-function startVerdaccio(config, cliListen, config_path, pkgVersion, pkgName, callback) {
+function startVerdaccio(config, cliListen, configPath, pkgVersion, pkgName, callback) {
   if (!config.self_path) {
-    config.self_path = Path.resolve(config_path);
+    config.self_path = Path.resolve(configPath);
   }
   if (!config.https) {
     config.https = {enable: false};
@@ -72,67 +72,18 @@ function startVerdaccio(config, cliListen, config_path, pkgVersion, pkgName, cal
 
   addresses.forEach(function(addr) {
     let webServer;
-    if (addr.proto === 'https') { // https  must either have key cert and ca  or a pfx and (optionally) a passphrase
+    if (addr.proto === 'https') {
+      // https  must either have key cert and ca  or a pfx and (optionally) a passphrase
       if (!config.https || !config.https.key || !config.https.cert || !config.https.ca) {
-        let conf_path = function(file) {
-          if (!file) {
-            return config_path;
-          }
-          return Path.resolve(Path.dirname(config_path), file);
-        };
-
-        logger.logger.fatal([
-          'You need to specify either ',
-          '    "https.key", "https.cert" and "https.ca" or ',
-          '    "https.pfx" and optionally "https.passphrase" ',
-          'to run https server',
-          '',
-          // commands are borrowed from node.js docs
-          'To quickly create self-signed certificate, use:',
-          ' $ openssl genrsa -out ' + conf_path('verdaccio-key.pem') + ' 2048',
-          ' $ openssl req -new -sha256 -key ' + conf_path('verdaccio-key.pem') + ' -out ' + conf_path('verdaccio-csr.pem'),
-          ' $ openssl x509 -req -in ' + conf_path('verdaccio-csr.pem') +
-          ' -signkey ' + conf_path('verdaccio-key.pem') + ' -out ' + conf_path('verdaccio-cert.pem'),
-          '',
-          'And then add to config file (' + conf_path() + '):',
-          '  https:',
-          '    key: verdaccio-key.pem',
-          '    cert: verdaccio-cert.pem',
-          '    ca: verdaccio-cert.pem',
-        ].join('\n'));
-        process.exit(2);
+        displayHTTPSWarning(configPath);
       }
 
-      try {
-        const httpsOptions = {
-          secureProtocol: 'SSLv23_method', // disable insecure SSLv2 and SSLv3
-          secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3,
-        };
-
-        if (config.https.pfx) {
-          Object.assign(httpsOptions, {
-            pfx: fs.readFileSync(config.https.pfx),
-            passphrase: config.https.passphrase || '',
-          });
-        } else {
-          Object.assign(httpsOptions, {
-            key: fs.readFileSync(config.https.key),
-            cert: fs.readFileSync(config.https.cert),
-            ca: fs.readFileSync(config.https.ca),
-          });
-        }
-        webServer = https.createServer(httpsOptions, app);
-      } catch (err) { // catch errors related to certificate loading
-        logger.logger.fatal({err: err}, 'cannot create server: @{err.message}');
-        process.exit(2);
-      }
+      webServer = handleHTTPS(app, configPath);
     } else { // http
       webServer = http.createServer(app);
     }
 
-    if (addr.path && fs.existsSync(addr.path)) {
-      fs.unlinkSync(addr.path);
-    }
+    unlinkAddressPath(addr);
 
     callback(webServer, addr, pkgName, pkgVersion);
   });
@@ -145,6 +96,65 @@ function startVerdaccio(config, cliListen, config_path, pkgVersion, pkgName, cal
   }
 }
 
+function unlinkAddressPath(addr) {
+  if (addr.path && fs.existsSync(addr.path)) {
+    fs.unlinkSync(addr.path);
+  }
+}
+
+function displayHTTPSWarning(configPath) {
+  const resolveConfigPath = function(file) {
+    return Path.resolve(Path.dirname(configPath), file);
+  };
+
+  logger.logger.fatal([
+    'You have enabled HTTPS and need to specify either ',
+    '    "https.key", "https.cert" and "https.ca" or ',
+    '    "https.pfx" and optionally "https.passphrase" ',
+    'to run https server',
+    '',
+    // commands are borrowed from node.js docs
+    'To quickly create self-signed certificate, use:',
+    ' $ openssl genrsa -out ' + resolveConfigPath('verdaccio-key.pem') + ' 2048',
+    ' $ openssl req -new -sha256 -key ' + resolveConfigPath('verdaccio-key.pem') + ' -out ' + resolveConfigPath('verdaccio-csr.pem'),
+    ' $ openssl x509 -req -in ' + resolveConfigPath('verdaccio-csr.pem') +
+    ' -signkey ' + resolveConfigPath('verdaccio-key.pem') + ' -out ' + resolveConfigPath('verdaccio-cert.pem'),
+    '',
+    'And then add to config file (' + configPath + '):',
+    '  https:',
+    '    key: verdaccio-key.pem',
+    '    cert: verdaccio-cert.pem',
+    '    ca: verdaccio-cert.pem',
+  ].join('\n'));
+  process.exit(2);
+}
+
+function handleHTTPS(app, configPath) {
+  try {
+    let httpsOptions = {
+      secureProtocol: 'SSLv23_method', // disable insecure SSLv2 and SSLv3
+      secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3,
+    };
+
+    if (config.https.pfx) {
+      httpsOptions = assign(httpsOptions, {
+        pfx: fs.readFileSync(config.https.pfx),
+        passphrase: config.https.passphrase || '',
+      });
+    } else {
+      httpsOptions = assign(httpsOptions, {
+        key: fs.readFileSync(config.https.key),
+        cert: fs.readFileSync(config.https.cert),
+        ca: fs.readFileSync(config.https.ca),
+      });
+    }
+    return https.createServer(httpsOptions, app);
+  } catch (err) { // catch errors related to certificate loading
+    logger.logger.fatal({err: err}, 'cannot create server: @{err.message}');
+    process.exit(2);
+  }
+}
+
 function listenDefaultCallback(webServer, addr, pkgName, pkgVersion) {
   webServer.listen(addr.port || addr.path, addr.host).on('error', function(err) {
     logger.logger.fatal({err: err}, 'cannot create server: @{err.message}');
diff --git a/src/lib/cli.js b/src/lib/cli.js
index 158c0d40c..d0849e049 100644
--- a/src/lib/cli.js
+++ b/src/lib/cli.js
@@ -47,7 +47,7 @@ let configPathLocation;
 const cliListner = commander.listen;
 
 try {
-  configPathLocation = commander.config ?  path.resolve(commander.config) : findConfigFile();
+  configPathLocation = findConfigFile(commander.config);
   verdaccioConfiguration = Utils.parseConfigFile(configPathLocation);
 
   logger.logger.warn({file: configPathLocation}, 'config file  - @{file}');
diff --git a/src/lib/config-path.js b/src/lib/config-path.js
index 038656fa7..73020da78 100644
--- a/src/lib/config-path.js
+++ b/src/lib/config-path.js
@@ -16,7 +16,11 @@ const pkgJson = require('../../package.json');
  * Find and get the first config file that match.
  * @return {String} the config file path
  */
-function findConfigFile() {
+function findConfigFile(configPath) {
+  if (_.isNil(configPath) === false) {
+    return Path.resolve(configPath);
+  }
+
   const configPaths = getConfigPaths();
 
   if (_.isEmpty(configPaths)) {