From bcd4d5a830582827e70f102de62fbd75fa07b96d Mon Sep 17 00:00:00 2001 From: Muthu Kumar Date: Thu, 2 Nov 2017 15:08:07 +0530 Subject: [PATCH] Minor Refactoring, added check for IP Addresses --- actions/createProxyServer.js | 18 +++++++------- actions/createStaticServer.js | 24 +++++++++--------- index.js | 51 +++++++++++++++++++------------------- util/isIP.js | 24 ++++++++++++++++++ util/nginxConf.js | 6 +++-- util/nginxPath.js | 13 ++++++---- util/parseToInt.js | 2 ++ util/validate.js | 57 ++++++++++++++++++++++++++----------------- 8 files changed, 119 insertions(+), 76 deletions(-) create mode 100644 util/isIP.js diff --git a/actions/createProxyServer.js b/actions/createProxyServer.js index dfab7e4..2fc5572 100644 --- a/actions/createProxyServer.js +++ b/actions/createProxyServer.js @@ -1,9 +1,9 @@ -var fs = require('fs-extra') -var shell = require('shelljs') -var npath = require('../util/nginxPath') -var conf = require('../util/nginxConf') +var fs = require('fs-extra'); +var shell = require('shelljs'); +var npath = require('../util/nginxPath'); +var conf = require('../util/nginxConf'); -var { EOL } = require('os'); +var { EOL } = require('os'); // \n if used on Linux, \r\n if used on Windows. function createProxyServer(domain, inPort, outPort) { fs.outputFileSync((conf(npath.availableSites(), domain)), @@ -24,8 +24,8 @@ function createProxyServer(domain, inPort, outPort) { " }" + EOL + "}" ) - shell.mkdir('-p', npath.enabledSites()) - shell.ln('-sf', conf(npath.availableSites(), domain), conf(npath.enabledSites(), domain)) -} + shell.mkdir('-p', npath.enabledSites()); // Creates directory if doesn't exist + shell.ln('-sf', conf(npath.availableSites(), domain), conf(npath.enabledSites(), domain)); // Symlink the conf file from sites-available to sites-enabled +}; -module.exports = createProxyServer \ No newline at end of file +module.exports = createProxyServer; \ No newline at end of file diff --git a/actions/createStaticServer.js b/actions/createStaticServer.js index 02fc597..b942476 100644 --- a/actions/createStaticServer.js +++ b/actions/createStaticServer.js @@ -1,16 +1,16 @@ -var fs = require('fs-extra') -var shell = require('shelljs') -var npath = require('../util/nginxPath') -var conf = require('../util/nginxConf') +var fs = require('fs-extra'); +var shell = require('shelljs'); +var npath = require('../util/nginxPath'); +var conf = require('../util/nginxConf'); -var { EOL } = require('os'); +var { EOL } = require('os'); // \n if used on Linux, \r\n if used on Windows. function createStaticServer(domain, outPort = 80) { - fs.outputFileSync((conf(npath.availableSites(), domain)), + fs.outputFileSync((conf(npath.availableSites(), domain)), // Gets nginx's paths from nginxPath.js "server {" + EOL + " listen " + outPort + ";" + EOL + " listen [::]:" + outPort + ";" + EOL + - " root /var/www/" + domain + ";" + EOL + + " root " + npath.webRoot() + + domain + ";" + EOL + " index index.html index.htm;" + EOL + "" + EOL + " server_name " + domain + EOL + @@ -19,9 +19,9 @@ function createStaticServer(domain, outPort = 80) { " }" + EOL + "}" ) - shell.mkdir('-p', npath.enabledSites()) - shell.ln('-sf', conf(npath.availableSites(), domain), conf(npath.enabledSites(), domain)) - shell.ln('-sf', ".", npath.homeDir() + domain) -} + shell.mkdir('-p', npath.enabledSites()) // Creates directory if doesn't exist + shell.ln('-sf', conf(npath.availableSites(), domain), conf(npath.enabledSites(), domain)) // Symlink the conf file from sites-available to sites-enabled + shell.ln('-sf', ".", npath.webRoot() + domain) // Symlink current directory to nginx's web root +}; -module.exports = createStaticServer \ No newline at end of file +module.exports = createStaticServer; \ No newline at end of file diff --git a/index.js b/index.js index 813e3d7..ee93da6 100644 --- a/index.js +++ b/index.js @@ -1,35 +1,33 @@ -#!/usr/bin/env node --harmony +#!/usr/bin/env node // Requiring npm modules -var program = require('commander') -var shell = require('shelljs') -var fs = require('fs-extra') -var chalk = require('chalk') -var validate = require('./util/validate') -//var validator = require('validator') +var program = require('commander'); +var shell = require('shelljs'); +var fs = require('fs-extra'); +var chalk = require('chalk'); -// Requiring Actions -var createProxyServer = require('./actions/createProxyServer') -var createStaticServer = require('./actions/createStaticServer') +// Requiring utils +var validate = require('./util/validate'); -// Using Validator -// var isDomain = validator.isFQDN +// Requiring Actions +var createProxyServer = require('./actions/createProxyServer'); +var createStaticServer = require('./actions/createStaticServer'); /* Uncomment in Production! -//Detect Linux or BSD -var isLin = /^linux|^bsd/.test(process.platform) +// Detect Linux or BSD +var isLin = /^linux|^bsd/.test(process.platform); -//Throw if OS is not Linux or BSD +// Throw if OS is not Linux or BSD. This should be changed to throw if not Debian based distro. Eventually, we can add more exceptions as `up` handles more cases. if(!isLin) { - shell.echo("\nThis is not a Linux or freeBSD distribution. I'm not written for this distro. Please raise an issue at " + chalk.cyan("https://github.com/codefeathers/up-serve") + " if you want `up` to be ported for your distro") - shell.exit(1) + shell.echo("\nThis is not a Linux or freeBSD distribution. I'm not written for this distro. Please raise an issue at " + chalk.cyan("https://github.com/codefeathers/up-serve") + " if you want `up` to be ported for your distro"); + shell.exit(1); } -//Throw if Nginx is not found +// Throw if Nginx is not found if (!shell.which('nginx')) { - shell.echo('I need nginx to work. Install nginx first. https://nginx.org/') - shell.exit(1) + shell.echo('I need nginx to work. Install nginx first. https://nginx.org/'); + shell.exit(1); } */ @@ -40,20 +38,19 @@ program program .command('static [outPort]') .description('Create a static server at this folder.') - .action(function (domain, outPort = 80) { - if (!validate(domain, outPort)) return - //createStaticServer(domain, outPort) + .action(function (domain, outPort = 80) { //If outport is not given, 80 is set as default. Later, change this default to reflect nginx's settings. + if (!validate(domain, outPort)) return //Validates domain and outport, and if invalid, throws and returns. + createStaticServer(domain, outPort) console.log("Done! Your static server has been set up!\nPoint your domain to this server and check " + chalk.cyan(domain) + " to verify!") }) program .command('proxy [outPort]') .description('Create a proxy server, listening at port number.') - .action(function (domain, inPort, outPort = "80") { + .action(function (domain, inPort, outPort = "80") { //Inbound port is necessary, but outbound is set to 80 by default. Again, will change this to reflect nginx's settings. if (!validate(domain, inPort, outPort)) return createProxyServer(domain, inPort, outPort) console.log("Done! Your reverse proxy server has been set up!\nPoint your domain to this server and check " + chalk.cyan(domain) + " to verify!") - //} }) program @@ -71,11 +68,12 @@ program }) program - .command('*') + .command('*') // This should pick invalid commands, but it doesn't, yet. .action(function () { console.log("Invalid command. Type " + chalk.cyan('up --help') + " for help.") }) +// Adds custom help text to the automatically generated help. program.on('--help', function () { console.log(''); console.log(' Usage:'); @@ -88,4 +86,5 @@ program.on('--help', function () { console.log(''); }); +// Parses commands passed to `up` and chooses one of the above commands. program.parse(process.argv); \ No newline at end of file diff --git a/util/isIP.js b/util/isIP.js new file mode 100644 index 0000000..27690f5 --- /dev/null +++ b/util/isIP.js @@ -0,0 +1,24 @@ +// Parses a string, and returns true if it is an IP Address. + +function isIP(str) { + var segments = str + .split('.') + .map(Number); + if (!segments.length === 4) { + return false; + } + for (var segment of segments) { + if (Number.isNaN(segment)) { + return false; + } + if (segment < 1 || segment > 255) { + return false; + } + } + if (segments[3] > 254) { + return false; + } + return true; +} + +module.exports = isIP; \ No newline at end of file diff --git a/util/nginxConf.js b/util/nginxConf.js index d42ca4c..897f198 100644 --- a/util/nginxConf.js +++ b/util/nginxConf.js @@ -1,5 +1,7 @@ +// Simple function that takes a path and domain name, concatenates them with ".conf" and returns it. + function conf(path, domain) { - return (path + domain + ".conf") + return (path + domain + ".conf"); } -module.exports = conf \ No newline at end of file +module.exports = conf; \ No newline at end of file diff --git a/util/nginxPath.js b/util/nginxPath.js index 38634b5..62f787d 100644 --- a/util/nginxPath.js +++ b/util/nginxPath.js @@ -1,17 +1,20 @@ +// These functions just return paths. Later, these should be modified to poll from nginx's config. + function availableSites() { - var availableSites = "/etc/nginx/available-sites/"; + var availableSites = "/etc/nginx/sites-available/"; return availableSites; } function enabledSites() { - var enabledSites = "/etc/nginx/enabled-sites/"; + var enabledSites = "/etc/nginx/sites-enabled/"; return enabledSites; } -function homeDir() { - return "/var/www/"; +function webRoot() { + var webRoot = "/var/www/"; + return webRoot; } module.exports.availableSites = availableSites; module.exports.enabledSites = enabledSites; -module.exports.homeDir = homeDir; \ No newline at end of file +module.exports.webRoot = webRoot; \ No newline at end of file diff --git a/util/parseToInt.js b/util/parseToInt.js index a072aae..891d3f6 100644 --- a/util/parseToInt.js +++ b/util/parseToInt.js @@ -1,3 +1,5 @@ +// Parse an input string and return a number if it is an integer. If it's a float, string, or array, return undefined. + function parseToInt(inputString) { var parsing = /^\d+$/.exec(inputString); return (parsing || [])[0]; diff --git a/util/validate.js b/util/validate.js index 783b90c..cd9996e 100644 --- a/util/validate.js +++ b/util/validate.js @@ -1,48 +1,61 @@ var validator = require('validator'); var parseToInt = require('./parseToInt'); +var isIP = require('./isIP'); // Using Validator -var isDomain = validator.isFQDN +var isDomain = validator.isFQDN; function validate(domain, inPort = undefined, outPort = "80") { - var domainInvalidMsg = "\nDomain is not valid. Please use a valid domain name." - var portInvalidMsg = ["\nPort should be a number.", "\nPort should be a number from 1 and 65535."] - //var validInPort = /^\d+$/.exec(inPort)[0] - //var validOutPort = /^\d+$/.exec(outPort)[0] - //var regex = /^\d+$/.exec(outPort); - //var validInPort = regex ? regex[0] : null; + + // Error messages + var domainInvalidMsg = ["\nPlease use a domain name instead of an IP address.", "\nDomain is not valid. Please use a valid domain name."]; + var portInvalidMsg = ["\nPort should be a number.", "\nPort should be a number from 1 and 65535."]; - var validInPort = parseToInt(inPort) - var validOutPort = parseToInt(outPort) + // ARGV returns a string as input. Port numbers should be parsed to int to validate them. If validation fails, these will return undefined and will fail the subsequent test. + var validInPort = parseToInt(inPort); + var validOutPort = parseToInt(outPort); + + // The value of isInvalid will be returned back. If none of the `if`s are true, the default value `true` is returned `domain`, `inPort` and `outPort` are considered validated. + var isValid = true; + + // Throw if IP is given instead of domain name. + if (isIP(domain)) { + console.log(domainInvalidMsg[0]); + return isValid = false; + } - var isValid = true + // Throw if input is not a Fully Qualified Domain Name (FQDN) if (!isDomain(domain)) { - console.log(domainInvalidMsg) - return isValid = false + console.log(domainInvalidMsg[1]); + return isValid = false; } + + // Enter if `inPort` is not defined. This happens for `up static` where no inbound ports are required. if (typeof inPort == undefined) { if (!validOutPort) { - console.log(portInvalidMsg[0]) - return isValid = false + console.log(portInvalidMsg[0]); // `outPort` is not an integer. + return isValid = false; } if (!(validOutPort > 0 && validOutPort <= 65535)) { - console.log(portInvalidMsg[1]) - return isValid = false + console.log(portInvalidMsg[1]); // `outPort` is not within port range. + return isValid = false; } } + + // Enter if `inPort` is defined. This happens for `up proxy` where inbound port is required. if (typeof inPort !== undefined) { if (!validInPort || !validOutPort) { - console.log(portInvalidMsg[0]) - return isValid = false + console.log(portInvalidMsg[0]); // Either `inPort` or `outPort` is not an integer. + return isValid = false; } if (typeof outPort !== undefined) { if (!((validInPort > 0 && validInPort <= 65535) && (validOutPort > 0 && validOutPort <= 65535))) { - console.log(portInvalidMsg[1]) - return isValid = false + console.log(portInvalidMsg[1]); // Either `inPort` or `outPort` are not within port range. + return isValid = false; } } - return isValid + return isValid; // If any of the `if`s were true, `isInvalid = false`. If not, `isInvalid = true`. } } -module.exports = validate \ No newline at end of file +module.exports = validate; \ No newline at end of file