diff --git a/manager/gulpfile.js b/manager/gulpfile.js deleted file mode 100644 index 41f3d0c..0000000 --- a/manager/gulpfile.js +++ /dev/null @@ -1,171 +0,0 @@ -/*jshint node:true */ - -'use strict'; - -const path = require('path'); -const gulp = require('gulp'); -const gutil = require('gulp-util'); -const concat = require('gulp-concat-util'); -const runSequence = require('run-sequence'); -const webpack = require('webpack-stream'); -const imagemin = require('gulp-imagemin'); -const del = require('del'); -const bump = require('gulp-bump'); -const sass = require('gulp-sass'); -const ejs = require('gulp-ejs'); -const PACKAGE = require('./package.json'); - -const assets = { - views: { - watch: 'src/frontend/views/**/*.ejs', - src: 'src/frontend/views/*.ejs', - dest: 'dist/' - }, - fonts: { - watch: 'src/frontend/fonts/**/*.{ttf,woff,woff2,eof,eot,svg,otf}', - dest: 'dist/fonts' - }, - images: { - watch: 'src/frontend/images/**/*.{png,jpg,gif}', - dest: 'dist/images' - }, - scss: { - watch: 'src/frontend/scss/**/*.scss', - loadPath: 'src/frontend/scss', - src: 'src/frontend/scss/styles.scss', - dest: 'dist/css' - }, - js: { - watch: 'src/frontend/js/**/*', - src: 'src/frontend/js/main.js', - dest: 'dist/js/' - } -}; - -/** - * @param color - * @param label - * @returns {Function} - */ -function logger (color, label) { - return function () { - let args = Array.prototype.slice.call(arguments); - args.unshift(gutil.colors[color].bold(label.toUpperCase() + ':')); - gutil.log.apply(null, args); - }; -} - -gutil.error = logger('red', 'error'); -gutil.warn = logger('yellow', 'warn'); -gutil.notice = logger('white', 'notice'); - -/** - * @param err - */ -function handleError (err) { - gutil.error(err.stack); -} - -/***************************** - TASKS - ******************************/ - -/** - * clean - */ -gulp.task('clean', function (cb) { - del(['./dist/*']) - .then(function () { - cb(); - }) - .catch(handleError); -}); - -/** - * images - */ -gulp.task('images', function () { - if (process.arch !== 'arm') { - return gulp.src(assets.images.watch) - .pipe(imagemin({ - optimizationLevel: 7 - })) - .pipe(gulp.dest(assets.images.dest)) - .on('error', handleError); - } else { - return gulp.src(assets.images.watch) - .pipe(gulp.dest(assets.images.dest)) - .on('error', handleError); - } -}); - -/** - * fonts - */ -gulp.task('fonts', function () { - return gulp.src(assets.fonts.watch) - .pipe(gulp.dest(assets.fonts.dest)) - .on('error', handleError); -}); - -/** - * scss - */ -gulp.task('scss', function () { - return gulp.src(assets.scss.src) - .pipe(sass().on('error', sass.logError)) - .pipe(concat.header('@import url(\'https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300,700\');@import url(\'https://fonts.googleapis.com/css?family=Roboto:100,200,300,400,500,600,700|Roboto+Condensed:300,400,700\');')) - .pipe(gulp.dest(path.resolve(assets.scss.dest))); -}); - -/** - * js - */ -gulp.task('js', function () { - return gulp.src(assets.js.src) - .pipe(webpack(require('./webpack.config.js'))) - .pipe(gulp.dest(assets.js.dest)) - .on('error', handleError); -}); - -/** - * views - */ -gulp.task('views', function () { - return gulp.src(assets.views.src) - .pipe(ejs({ - version: PACKAGE.version - }, {}, { - ext: '.html' - })) - .on('error', handleError) - .pipe(gulp.dest(assets.views.dest)); -}); - -/** - * bump - */ -gulp.task('bump', function () { - gulp.src('./package.json') - .pipe(bump({type: 'version'})) - .pipe(gulp.dest('./')); -}); - -/** - * build - */ -gulp.task('build', function (cb) { - runSequence('clean', ['images', 'fonts', 'scss', 'js', 'views'], cb); -}); - -/** - * default - */ -gulp.task('default', ['build'], function () { - gulp.watch(assets.scss.watch, ['scss']); - gulp.watch(assets.images.watch, ['images']); - gulp.watch(assets.fonts.watch, ['fonts']); - gulp.watch(assets.js.watch, ['js']); - gulp.watch(assets.views.watch, ['views']); - gulp.watch('./webpack.config.js', ['js']); -}); diff --git a/manager/package.json b/manager/package.json deleted file mode 100644 index 9673c85..0000000 --- a/manager/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "nginx-proxy-manager", - "version": "1.1.2", - "description": "Nginx proxt with built in Web based management", - "main": "src/backend/index.js", - "dependencies": { - "ajv": "^5.5.1", - "batchflow": "^0.4.0", - "body-parser": "^1.18.2", - "compression": "^1.7.1", - "diskdb": "^0.1.17", - "ejs": "^2.5.7", - "express": "^4.16.2", - "express-winston": "^2.4.0", - "json-schema-ref-parser": "^4.0.4", - "lodash": "^4.17.4", - "path": "^0.12.7", - "unix-timestamp": "^0.2.0", - "winston": "^2.4.0" - }, - "devDependencies": { - "@babel/core": "^7.0.0-beta.31", - "@babel/preset-env": "^7.0.0-beta.31", - "@babel/preset-es2015": "^7.0.0-beta.32", - "babel-loader": "^8.0.0-beta.0", - "backbone": "1.3.3", - "backbone-virtual-collection": "^0.6.15", - "backbone.marionette": "3.4.1", - "backbone.radio": "2.0.0", - "bootstrap": "^3.3.7", - "del": "^3.0.0", - "ejs-loader": "^0.3.0", - "es6-promise": "^4.1.1", - "font-awesome": "^4.7.0", - "form-serializer": "^2.5.0", - "gulp": "^3.9.1", - "gulp-bump": "^2.7.0", - "gulp-concat-util": "^0.5.5", - "gulp-ejs": "^3.0.1", - "gulp-imagemin": "^3.3.0", - "gulp-sass": "^4.0.1", - "gulp-util": "^3.0.8", - "image-size": "^0.6.1", - "jquery": "^3.2.1", - "jquery-serializejson": "^2.8.1", - "normalize-css": "^2.3.1", - "prepack-webpack-plugin": "^1.1.0", - "run-sequence": "^2.2.0", - "underscore": "^1.8.3", - "webpack": "^3.8.1", - "webpack-stream": "^4.0.0", - "webpack-visualizer-plugin": "^0.1.11" - }, - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Jamie Curnow ", - "license": "MIT" -} diff --git a/manager/src/backend/app.js b/manager/src/backend/app.js deleted file mode 100644 index f538201..0000000 --- a/manager/src/backend/app.js +++ /dev/null @@ -1,77 +0,0 @@ -'use strict'; - -const express = require('express'); -const bodyParser = require('body-parser'); -const compression = require('compression'); -const logger = require('./logger'); - -/** - * App - */ -const app = express(); -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({extended: true})); -app.use(compression()); - -/** - * General Logging, BEFORE routes - */ -app.disable('x-powered-by'); -app.enable('trust proxy', ['loopback', 'linklocal', 'uniquelocal']); -app.enable('strict routing'); - -// pretty print JSON when not live -if (process.env.NODE_ENV !== 'production') { - app.set('json spaces', 2); -} - -// General security/cache related headers + server header -app.use(function (req, res, next) { - res.set({ - 'Strict-Transport-Security': 'includeSubDomains; max-age=631138519; preload', - 'X-XSS-Protection': '0', - 'X-Content-Type-Options': 'nosniff', - 'X-Frame-Options': 'DENY', - 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate', - Pragma: 'no-cache', - Expires: 0 - }); - next(); -}); - -/** - * Routes - */ -app.use('/css', express.static('dist/css')); -app.use('/fonts', express.static('dist/fonts')); -app.use('/images', express.static('dist/images')); -app.use('/js', express.static('dist/js')); -app.use('/api', require('./routes/api/main')); -app.use('/', require('./routes/main')); - -// production error handler -// no stacktraces leaked to user -app.use(function (err, req, res, next) { - let payload = { - error: { - code: err.status, - message: err.public ? err.message : 'Internal Error' - } - }; - - if (process.env.NODE_ENV === 'development') { - payload.debug = { - stack: typeof err.stack !== 'undefined' && err.stack ? err.stack.split('\n') : null, - previous: err.previous - }; - } - - // Not every error is worth logging - but this is good for now until it gets annoying. - if (!err.public && typeof err.stack !== 'undefined' && err.stack) { - logger.warn(err.stack); - } - - res.status(err.status || 500).send(payload); -}); - -module.exports = app; diff --git a/manager/src/backend/db.js b/manager/src/backend/db.js deleted file mode 100644 index 45479f7..0000000 --- a/manager/src/backend/db.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -const db = require('diskdb'); - -module.exports = db.connect('/config', ['hosts', 'access']); diff --git a/manager/src/backend/index.js b/manager/src/backend/index.js deleted file mode 100644 index 2e8b30c..0000000 --- a/manager/src/backend/index.js +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -const app = require('./app'); -const logger = require('./logger'); -const apiValidator = require('./lib/validator/api'); -const internalSsl = require('./internal/ssl'); - -let port = process.env.PORT || 81; - -apiValidator.loadSchemas - .then(() => { - - internalSsl.initTimer(); - - const server = app.listen(port, () => { - logger.info('PID ' + process.pid + ' listening on port ' + port + ' ...'); - - process.on('SIGTERM', () => { - logger.info('PID ' + process.pid + ' received SIGTERM'); - server.close(() => { - logger.info('Stopping.'); - process.exit(0); - }); - }); - }); - }) - .catch((err) => { - logger.error(err); - process.exit(1); - }); diff --git a/manager/src/backend/internal/access.js b/manager/src/backend/internal/access.js deleted file mode 100644 index 4fe8ae5..0000000 --- a/manager/src/backend/internal/access.js +++ /dev/null @@ -1,261 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const fs = require('fs'); -const batchflow = require('batchflow'); -const db = require('../db'); -const logger = require('../logger'); -const internalNginx = require('./nginx'); -const utils = require('../lib/utils'); - -const internalAccess = { - - /** - * All Access Lists - * - * @returns {Promise} - */ - getAll: () => { - return new Promise((resolve/*, reject*/) => { - resolve(db.access.find()); - }) - .then(list => { - _.map(list, (list_item, idx) => { - list[idx] = internalAccess.maskItems(list_item); - list[idx].hosts = db.hosts.find({access_list_id: list_item._id}); - }); - - return list; - }); - }, - - /** - * Specific Access List - * - * @param {String} id - * @returns {Promise} - */ - get: id => { - return new Promise((resolve/*, reject*/) => { - resolve(db.access.findOne({_id: id})); - }) - .then(list => { - if (list) { - return internalAccess.maskItems(list); - } - - list.hosts = db.hosts.find({access_list_id: list._id}); - - return list; - }); - }, - - /** - * Create a Access List - * - * @param {Object} payload - * @returns {Promise} - */ - create: payload => { - return new Promise((resolve/*, reject*/) => { - // Add list to db - resolve(db.access.save(payload)); - }) - .then(list => { - return internalAccess.build(list) - .then(() => { - return internalAccess.maskItems(list); - }); - }); - }, - - /** - * Update a Access List - * - * @param {String} id - * @param {Object} payload - * @returns {Promise} - */ - update: (id, payload) => { - return new Promise((resolve, reject) => { - // get existing list - let list = db.access.findOne({_id: id}); - - if (!list) { - reject(new error.ValidationError('Access List not found')); - } else { - - if (typeof payload.name !== 'undefined') { - list.name = payload.name; - } - - if (typeof payload.items !== 'undefined') { - // go through each of the items in the payload and assess how they apply to the original items - let new_items = []; - _.map(payload.items, (payload_item) => { - if (!payload_item.password) { - // try to find original item and use the password from there, this is essentially keeping existing users - let old = _.find(list.items, {username: payload_item.username}); - if (old) { - new_items.push(old); - } - } else { - new_items.push(payload_item); - } - }); - - list.items = new_items; - } - - db.access.update({_id: id}, list, {multi: false, upsert: false}); - resolve(list); - } - }) - .then(list => { - return internalAccess.build(list) - .then(() => { - return internalAccess.maskItems(list); - }); - }); - }, - - /** - * Deletes a Access List - * - * @param {String} id - * @returns {Promise} - */ - delete: id => { - const internalHost = require('./host'); - let associated_hosts = db.hosts.find({access_list_id: id}); - - return new Promise((resolve/*, reject*/) => { - db.hosts.update({access_list_id: id}, {access_list_id: ''}, {multi: true, upsert: false}); - - if (associated_hosts.length) { - // regenerate config for these hosts - let promises = []; - - _.map(associated_hosts, associated_host => { - promises.push(internalHost.configure(db.hosts.findOne({_id: associated_host._id}))); - }); - - resolve(Promise.all(promises)); - } else { - resolve(); - } - }) - .then(() => { - // restart nginx - if (associated_hosts.length) { - return internalNginx.reload(); - } - }) - .then(() => { - db.access.remove({_id: id}, false); - - // delete access file - try { - fs.unlinkSync(internalAccess.getFilename(id)); - } catch (err) { - // do nothing - } - - return true; - }); - }, - - /** - * @param {Object} list - * @returns {Object} - */ - maskItems: list => { - if (list && typeof list.items !== 'undefined') { - _.map(list.items, (val, idx) => { - list.items[idx].hint = val.password.charAt(0) + ('*').repeat(val.password.length - 1); - list.items[idx].password = ''; - }); - } - - return list; - }, - - /** - * @param {String|Object} list - * @returns {String} - */ - getFilename: (list) => { - return '/config/access/' + (typeof list === 'string' ? list : list._id); - }, - - /** - * @param {Object} list - * @returns {Promise} - */ - build: list => { - logger.info('Building Access file for: ' + list.name); - - return new Promise((resolve, reject) => { - if (typeof list._id !== 'undefined') { - - let htpasswd_file = internalAccess.getFilename(list); - - // 1. remove any existing access file - try { - fs.unlinkSync(htpasswd_file); - } catch (err) { - // do nothing - } - - // 2. create empty access file - try { - fs.writeFileSync(htpasswd_file, '', {encoding: 'utf8'}); - resolve(htpasswd_file); - } catch (err) { - reject(err); - } - } else { - reject(new Error('List does not have an _id')); - } - }) - .then(htpasswd_file => { - // 3. generate password for each user - if (list.items.length) { - return new Promise((resolve, reject) => { - batchflow(list.items).sequential() - .each((i, item, next) => { - if (typeof item.password !== 'undefined' && item.password.length) { - logger.info('Adding: ' + item.username); - - utils.exec('/usr/bin/htpasswd -b "' + htpasswd_file + '" "' + item.username + '" "' + item.password + '"') - .then((/*result*/) => { - next(); - }) - .catch(err => { - logger.error(err); - next(err); - }); - } - }) - .error(err => { - logger.error(err); - reject(err); - }) - .end(results => { - logger.info('Built Access file for: ' + list.name); - resolve(results); - }); - }); - } - }) - .then(() => { - // only reload nginx if any hosts are using this access - let hosts = db.hosts.find({access_list_id: list._id}); - if (hosts && hosts.length) { - return internalNginx.reload(); - } - }); - } -}; - -module.exports = internalAccess; diff --git a/manager/src/backend/internal/host.js b/manager/src/backend/internal/host.js deleted file mode 100644 index 72f55d2..0000000 --- a/manager/src/backend/internal/host.js +++ /dev/null @@ -1,280 +0,0 @@ -'use strict'; - -const _ = require('lodash'); - -const db = require('../db'); -const error = require('../lib/error'); -const internalAccess = require('./access'); -const internalSsl = require('./ssl'); -const internalNginx = require('./nginx'); -const timestamp = require('unix-timestamp'); - -timestamp.round = true; - -const internalHost = { - - /** - * All Hosts - * - * @returns {Promise} - */ - getAll: () => { - return new Promise((resolve/*, reject*/) => { - resolve(db.hosts.find()); - }) - .then(hosts => { - _.map(hosts, (host, idx) => { - if (typeof host.access_list_id !== 'undefined' && host.access_list_id) { - hosts[idx].access_list = internalAccess.maskItems(db.access.findOne({_id: host.access_list_id})); - } else { - hosts[idx].access_list_id = ''; - hosts[idx].access_list = null; - } - }); - - return hosts; - }); - }, - - /** - * Create a Host - * - * @param {Object} payload - * @returns {Promise} - */ - create: payload => { - return new Promise((resolve, reject) => { - let existing_host = false; - - if (payload.type === 'stream') { - // Check that the incoming port doesn't already exist - existing_host = db.hosts.findOne({incoming_port: payload.incoming_port}); - - if (payload.incoming_port === 80 || payload.incoming_port === 81 || payload.incoming_port === 443) { - reject(new error.ConfigurationError('Port ' + payload.incoming_port + ' is reserved')); - return; - } - - } else { - payload.hostname = payload.hostname.toLowerCase(); - - // Check that the hostname doesn't already exist - existing_host = db.hosts.findOne({hostname: payload.hostname}); - } - - if (existing_host) { - reject(new error.ValidationError('Hostname already exists')); - } else { - // Add host to db - let host = db.hosts.save(payload); - - // Fire the config generation for this host - internalHost.configure(host, true) - .then((/*result*/) => { - resolve(host); - }) - .catch(err => { - reject(err); - }); - } - }) - .catch(err => { - // Remove host if the configuration failed - if (err instanceof error.ConfigurationError) { - db.hosts.remove({hostname: payload.hostname}); - internalNginx.deleteConfig(payload); - internalSsl.deleteCerts(payload); - } - - throw err; - }); - }, - - /** - * Update a Host - * - * @param {String} id - * @param {Object} payload - * @returns {Promise} - */ - update: (id, payload) => { - return new Promise((resolve, reject) => { - let original_host = db.hosts.findOne({_id: id}); - - if (!original_host) { - reject(new error.ValidationError('Host not found')); - } else { - // Enforce lowercase hostnames - if (typeof payload.hostname !== 'undefined') { - payload.hostname = payload.hostname.toLowerCase(); - } - - // Check that the hostname doesn't already exist - let other_host = false; - - if (typeof payload.incoming_port !== 'undefined') { - other_host = db.hosts.findOne({incoming_port: payload.incoming_port}); - } else { - other_host = db.hosts.findOne({hostname: payload.hostname}); - } - - if (other_host && other_host._id !== id) { - reject(new error.ValidationError((other_host.type === 'stream' ? 'Source Stream Port' : 'Hostname') + ' already exists')); - } else { - // 2. Update host - db.hosts.update({_id: id}, payload, {multi: false, upsert: false}); - let updated_host = db.hosts.findOne({_id: id}); - - resolve({ - original: original_host, - updated: updated_host - }); - } - } - }) - .then(data => { - if (data.original.hostname !== data.updated.hostname) { - // Hostname has changed, delete the old file - return internalNginx.deleteConfig(data.original) - .then(() => { - return data; - }); - } - - return data; - }) - .then(data => { - if (data.updated.type !== 'stream') { - if ( - (data.original.ssl && !data.updated.ssl) || // ssl was enabled and is now disabled - (data.original.ssl && data.original.hostname !== data.updated.hostname) // hostname was changed for a previously ssl-enabled host - ) { - // SSL was turned off or hostname for ssl has changed so we should remove certs for the original - return internalSsl.deleteCerts(data.original) - .then(() => { - return data; - }); - } - } - - return data; - }) - .then(data => { - // 3. Fire the config generation for this host - return internalHost.configure(data.updated, true) - .then((/*result*/) => { - return data.updated; - }); - }); - }, - - /** - * This will create the nginx config for the host and fire off letsencrypt duties if required - * - * @param {Object} host - * @param {Boolean} [reload_nginx] - * @returns {Promise} - */ - configure: (host, reload_nginx) => { - return new Promise((resolve/*, reject*/) => { - resolve(internalNginx.deleteConfig(host)); - }) - .then(() => { - if (host.ssl && !internalSsl.hasValidSslCerts(host)) { - return internalSsl.configureSsl(host); - } - }) - .then(() => { - return internalNginx.generateConfig(host); - }) - .then(() => { - if (reload_nginx) { - return internalNginx.reload(); - } - }); - }, - - /** - * Deletes a Host - * - * @param {String} id - * @returns {Promise} - */ - delete: id => { - let existing_host = db.hosts.findOne({_id: id}); - return new Promise((resolve, reject) => { - if (existing_host) { - db.hosts.update({_id: id}, {is_deleted: true}, {multi: true, upsert: false}); - resolve(internalNginx.deleteConfig(existing_host)); - } else { - reject(new error.ValidationError('Hostname does not exist')); - } - }) - .then(() => { - if (existing_host.ssl) { - return internalSsl.deleteCerts(existing_host); - } - }) - .then(() => { - db.hosts.remove({_id: id}, false); - return internalNginx.reload(); - }) - .then(() => { - return true; - }); - }, - - /** - * Reconfigure a Host - * - * @param {String} id - * @returns {Promise} - */ - reconfigure: id => { - return new Promise((resolve, reject) => { - let host = db.hosts.findOne({_id: id}); - - if (!host) { - reject(new error.ValidationError('Host does not exist: ' + id)); - } else { - // 3. Fire the config generation for this host - internalHost.configure(host, true) - .then((/*result*/) => { - resolve(host); - }) - .catch(err => { - reject(err); - }); - } - }); - }, - - /** - * Renew SSL for a Host - * - * @param {String} id - * @returns {Promise} - */ - renew: id => { - return new Promise((resolve, reject) => { - let host = db.hosts.findOne({_id: id}); - - if (!host) { - reject(new error.ValidationError('Host does not exist')); - } else if (!host.ssl) { - reject(new error.ValidationError('Host does not have SSL enabled')); - } else { - // 3. Fire the ssl and config generation for this host, forcing ssl - internalSsl.renewSsl(host) - .then((/*result*/) => { - resolve(host); - }) - .catch(err => { - reject(err); - }); - } - }); - } -}; - -module.exports = internalHost; diff --git a/manager/src/backend/internal/nginx.js b/manager/src/backend/internal/nginx.js deleted file mode 100644 index c05d50d..0000000 --- a/manager/src/backend/internal/nginx.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const ejs = require('ejs'); -const logger = require('../logger'); -const utils = require('../lib/utils'); -const error = require('../lib/error'); - -const internalNginx = { - - /** - * @returns {Promise} - */ - test: () => { - logger.info('Testing Nginx configuration'); - return utils.exec('/usr/sbin/nginx -t'); - }, - - /** - * @returns {Promise} - */ - reload: () => { - return internalNginx.test() - .then(() => { - logger.info('Reloading Nginx'); - return utils.exec('/usr/sbin/nginx -s reload'); - }); - }, - - /** - * @param {Object} host - * @returns {String} - */ - getConfigName: host => { - if (host.type === 'stream') { - return '/config/nginx/stream/' + host.incoming_port + '.conf'; - } - - return '/config/nginx/' + host.hostname + '.conf'; - }, - - /** - * @param {Object} host - * @returns {Promise} - */ - generateConfig: host => { - return new Promise((resolve, reject) => { - let template = null; - let filename = internalNginx.getConfigName(host); - - try { - if (typeof host.type === 'undefined' || !host.type) { - host.type = 'proxy'; - } - - template = fs.readFileSync(__dirname + '/../templates/' + host.type + '.conf.ejs', {encoding: 'utf8'}); - let config_text = ejs.render(template, host); - fs.writeFileSync(filename, config_text, {encoding: 'utf8'}); - resolve(true); - } catch (err) { - reject(new error.ConfigurationError(err.message)); - } - }); - }, - - /** - * @param {Object} host - * @param {Boolean} [throw_errors] - * @returns {Promise} - */ - deleteConfig: (host, throw_errors) => { - return new Promise((resolve, reject) => { - try { - fs.unlinkSync(internalNginx.getConfigName(host)); - } catch (err) { - if (throw_errors) { - reject(err); - } - } - - resolve(); - }); - } -}; - -module.exports = internalNginx; diff --git a/manager/src/backend/internal/ssl.js b/manager/src/backend/internal/ssl.js deleted file mode 100644 index f631c27..0000000 --- a/manager/src/backend/internal/ssl.js +++ /dev/null @@ -1,137 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const ejs = require('ejs'); -const timestamp = require('unix-timestamp'); -const internalNginx = require('./nginx'); -const logger = require('../logger'); -const utils = require('../lib/utils'); -const error = require('../lib/error'); - -timestamp.round = true; - -const internalSsl = { - - interval_timeout: 1000 * 60 * 60 * 6, // 6 hours - interval: null, - interval_processing: false, - - initTimer: () => { - internalSsl.interval = setInterval(internalSsl.processExpiringHosts, internalSsl.interval_timeout); - }, - - /** - * Triggered by a timer, this will check for expiring hosts and renew their ssl certs if required - */ - processExpiringHosts: () => { - if (!internalSsl.interval_processing) { - logger.info('Renewing SSL certs close to expiry...'); - return utils.exec('/usr/bin/certbot renew -q') - .then(result => { - logger.info(result); - internalSsl.interval_processing = false; - - return internalNginx.reload() - .then(() => { - logger.info('Renew Complete'); - return result; - }); - }) - .catch(err => { - logger.error(err); - internalSsl.interval_processing = false; - }); - } - }, - - /** - * @param {Object} host - * @returns {Boolean} - */ - hasValidSslCerts: host => { - return fs.existsSync('/etc/letsencrypt/live/' + host.hostname + '/fullchain.pem') && - fs.existsSync('/etc/letsencrypt/live/' + host.hostname + '/privkey.pem'); - }, - - /** - * @param {Object} host - * @returns {Promise} - */ - requestSsl: host => { - logger.info('Requesting SSL certificates for ' + host.hostname); - - return utils.exec('/usr/bin/letsencrypt certonly --agree-tos --email "' + host.letsencrypt_email + '" -n -a webroot -d "' + host.hostname + '"') - .then(result => { - logger.info(result); - return result; - }); - }, - - /** - * @param {Object} host - * @returns {Promise} - */ - renewSsl: host => { - logger.info('Renewing SSL certificates for ' + host.hostname); - - return utils.exec('/usr/bin/certbot renew --force-renewal --disable-hook-validation --cert-name "' + host.hostname + '"') - .then(result => { - logger.info(result); - return result; - }); - }, - - /** - * @param {Object} host - * @returns {Promise} - */ - deleteCerts: host => { - logger.info('Deleting SSL certificates for ' + host.hostname); - - return utils.exec('/usr/bin/certbot delete -n --cert-name "' + host.hostname + '"') - .then(result => { - logger.info(result); - }) - .catch(err => { - logger.error(err); - }); - }, - - /** - * @param {Object} host - * @returns {Promise} - */ - generateSslSetupConfig: host => { - let template = null; - let filename = internalNginx.getConfigName(host); - let template_data = host; - - return new Promise((resolve, reject) => { - try { - template = fs.readFileSync(__dirname + '/../templates/letsencrypt.conf.ejs', {encoding: 'utf8'}); - let config_text = ejs.render(template, template_data); - fs.writeFileSync(filename, config_text, {encoding: 'utf8'}); - - resolve(template_data); - } catch (err) { - reject(new error.ConfigurationError(err.message)); - } - }); - }, - - /** - * @param {Object} host - * @returns {Promise} - */ - configureSsl: host => { - return internalSsl.generateSslSetupConfig(host) - .then(data => { - return internalNginx.reload() - .then(() => { - return internalSsl.requestSsl(data); - }); - }); - } -}; - -module.exports = internalSsl; diff --git a/manager/src/backend/lib/error.js b/manager/src/backend/lib/error.js deleted file mode 100644 index 92ae3e6..0000000 --- a/manager/src/backend/lib/error.js +++ /dev/null @@ -1,56 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const util = require('util'); - -module.exports = { - - ItemNotFoundError: function (id, previous) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - this.previous = previous; - this.message = 'Item Not Found - ' + id; - this.public = true; - this.status = 404; - }, - - InternalError: function (message, previous) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - this.previous = previous; - this.message = message; - this.status = 500; - this.public = false; - }, - - InternalValidationError: function (message, previous) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - this.previous = previous; - this.message = message; - this.status = 400; - this.public = false; - }, - - ConfigurationError: function (message, previous) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - this.previous = previous; - this.message = message; - this.status = 400; - this.public = true; - }, - - ValidationError: function (message, previous) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - this.previous = previous; - this.message = message; - this.public = true; - this.status = 400; - } -}; - -_.forEach(module.exports, function (error) { - util.inherits(error, Error); -}); diff --git a/manager/src/backend/lib/utils.js b/manager/src/backend/lib/utils.js deleted file mode 100644 index 28919b1..0000000 --- a/manager/src/backend/lib/utils.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -const exec = require('child_process').exec; - -module.exports = { - - /** - * @param {String} cmd - * @returns {Promise} - */ - exec: function (cmd) { - return new Promise((resolve, reject) => { - exec(cmd, function (err, stdout, stderr) { - if (err && typeof err === 'object') { - reject(err); - } else { - resolve(stdout.trim()); - } - }); - }); - } -}; diff --git a/manager/src/backend/lib/validator/api.js b/manager/src/backend/lib/validator/api.js deleted file mode 100644 index cc44fd8..0000000 --- a/manager/src/backend/lib/validator/api.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -const error = require('../error'); -const path = require('path'); -const parser = require('json-schema-ref-parser'); - -const ajv = require('ajv')({ - verbose: true, - validateSchema: true, - allErrors: false, - format: 'full', // strict regexes for format checks - coerceTypes: true -}); - -/** - * @param {Object} schema - * @param {Object} payload - * @returns {Promise} - */ -function apiValidator (schema, payload/*, description*/) { - return new Promise(function Promise_apiValidator (resolve, reject) { - if (typeof payload === 'undefined') { - reject(new error.ValidationError('Payload is undefined')); - } - - let validate = ajv.compile(schema); - let valid = validate(payload); - - if (valid && !validate.errors) { - resolve(payload); - } else { - let message = ajv.errorsText(validate.errors); - //console.log(validate.errors); - - let err = new error.ValidationError(message); - err.debug = [validate.errors, payload]; - reject(err); - } - }); -} - -apiValidator.loadSchemas = parser - .dereference(path.resolve('src/backend/schema/index.json')) - .then((schema) => { - ajv.addSchema(schema); - return schema; - }); - -module.exports = apiValidator; diff --git a/manager/src/backend/lib/validator/index.js b/manager/src/backend/lib/validator/index.js deleted file mode 100644 index 00f9393..0000000 --- a/manager/src/backend/lib/validator/index.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const error = require('../error'); -const definitions = require('../../schema/definitions.json'); - -RegExp.prototype.toJSON = RegExp.prototype.toString; - -const ajv = require('ajv')({ - verbose: true, //process.env.NODE_ENV === 'development', - allErrors: true, - format: 'full', // strict regexes for format checks - coerceTypes: true, - schemas: [ - definitions - ] -}); - -/** - * - * @param {Object} schema - * @param {Object} payload - * @returns {Promise} - */ -function validator (schema, payload) { - return new Promise(function (resolve, reject) { - if (!payload) { - reject(new error.InternalValidationError('Payload is falsy')); - } else { - try { - let validate = ajv.compile(schema); - let valid = validate(payload); - if (valid && !validate.errors) { - resolve(_.cloneDeep(payload)); - } else { - //debug('Validation failed:', schema, payload); - let message = ajv.errorsText(validate.errors); - reject(new error.InternalValidationError(message)); - } - } catch (err) { - reject(err); - } - } - }); -} - -module.exports = validator; diff --git a/manager/src/backend/logger.js b/manager/src/backend/logger.js deleted file mode 100644 index 7b37e06..0000000 --- a/manager/src/backend/logger.js +++ /dev/null @@ -1,30 +0,0 @@ -const winston = require('winston'); - -winston.remove(winston.transports.Console); - -winston.add(winston.transports.Console, { - colorize: true, - timestamp: true, - prettyPrint: true, - depth: 3 -}); - -winston.setLevels({ - error: 0, - warn: 1, - info: 2, - success: 2, - verbose: 3, - debug: 4 -}); - -winston.addColors({ - error: 'red', - warn: 'yellow', - info: 'cyan', - success: 'green', - verbose: 'blue', - debug: 'magenta' -}); - -module.exports = winston; diff --git a/manager/src/backend/routes/api/access.js b/manager/src/backend/routes/api/access.js deleted file mode 100644 index 544b5f2..0000000 --- a/manager/src/backend/routes/api/access.js +++ /dev/null @@ -1,121 +0,0 @@ -'use strict'; - -const express = require('express'); -const validator = require('../../lib/validator'); -const apiValidator = require('../../lib/validator/api'); -const internalAccess = require('../../internal/access'); - -let router = express.Router({ - caseSensitive: true, - strict: true, - mergeParams: true -}); - -/** - * /api/access - */ -router - .route('/') - .options((req, res) => { - res.sendStatus(204); - }) - - /** - * GET /api/access - * - * Retrieve all access lists - */ - .get((req, res, next) => { - internalAccess.getAll() - .then(lists => { - res.status(200) - .send(lists); - }) - .catch(next); - }) - - /** - * POST /api/access - * - * Create a new Access List - */ - .post((req, res, next) => { - apiValidator({$ref: 'endpoints/access#/links/1/schema'}, req.body) - .then(payload => { - return internalAccess.create(payload); - }) - .then(result => { - res.status(201) - .send(result); - }) - .catch(next); - }); - -/** - * Specific Access List - * - * /api/access/123 - */ -router - .route('/:list_id') - .options((req, res) => { - res.sendStatus(204); - }) - - /** - * GET /access/123 - * - * Retrieve a specific Access List - */ - .get((req, res, next) => { - validator({ - required: ['list_id'], - additionalProperties: false, - properties: { - list_id: { - $ref: 'definitions#/definitions/id' - } - } - }, req.params) - .then(data => { - return internalAccess.get(data.list_id); - }) - .then(list => { - res.status(200) - .send(list); - }) - .catch(next); - }) - - /** - * PUT /api/access/123 - * - * Update an existing Access List - */ - .put((req, res, next) => { - apiValidator({$ref: 'endpoints/access#/links/2/schema'}, req.body) - .then(payload => { - return internalAccess.update(req.params.list_id, payload); - }) - .then(result => { - res.status(200) - .send(result); - }) - .catch(next); - }) - - /** - * DELETE /api/access/123 - * - * Delete an existing Access List - */ - .delete((req, res, next) => { - internalAccess.delete(req.params.list_id) - .then(result => { - res.status(200) - .send(result); - }) - .catch(next); - }); - -module.exports = router; diff --git a/manager/src/backend/routes/api/hosts.js b/manager/src/backend/routes/api/hosts.js deleted file mode 100644 index 0d300ed..0000000 --- a/manager/src/backend/routes/api/hosts.js +++ /dev/null @@ -1,155 +0,0 @@ -'use strict'; - -const express = require('express'); -const validator = require('../../lib/validator'); -const apiValidator = require('../../lib/validator/api'); -const internalHost = require('../../internal/host'); - -let router = express.Router({ - caseSensitive: true, - strict: true, - mergeParams: true -}); - -/** - * /api/hosts - */ -router - .route('/') - .options((req, res) => { - res.sendStatus(204); - }) - - /** - * GET /api/hosts - * - * Retrieve all hosts - */ - .get((req, res, next) => { - internalHost.getAll() - .then(hosts => { - res.status(200) - .send(hosts); - }) - .catch(next); - }) - - /** - * POST /api/hosts - * - * Create a new Host - */ - .post((req, res, next) => { - apiValidator({$ref: 'endpoints/hosts#/links/1/schema'}, req.body) - .then(payload => { - return internalHost.create(payload); - }) - .then(result => { - res.status(201) - .send(result); - }) - .catch(next); - }); - -/** - * Specific Host - * - * /api/hosts/123 - */ -router - .route('/:host_id') - .options((req, res) => { - res.sendStatus(204); - }) - - /** - * GET /hosts/123 - * - * Retrieve a specific Host - */ - .get((req, res, next) => { - validator({ - required: ['host_id'], - additionalProperties: false, - properties: { - host_id: { - $ref: 'definitions#/definitions/_id' - } - } - }, req.params) - .then(data => { - return internalHost.get(data.host_id); - }) - .then(host => { - res.status(200) - .send(host); - }) - .catch(next); - }) - - /** - * PUT /api/hosts/123 - * - * Update an existing Host - */ - .put((req, res, next) => { - apiValidator({$ref: 'endpoints/hosts#/links/2/schema'}, req.body) - .then(payload => { - return internalHost.update(req.params.host_id, payload); - }) - .then(result => { - res.status(200) - .send(result); - }) - .catch(next); - }) - - /** - * DELETE /api/hosts/123 - * - * Delete an existing Host - */ - .delete((req, res, next) => { - internalHost.delete(req.params.host_id) - .then(result => { - res.status(200) - .send(result); - }) - .catch(next); - }); - -/** - * Reconfigure Host Action - * - * /api/hosts/123/reconfigure - */ -router - .route('/:host_id/reconfigure') - .options((req, res) => { - res.sendStatus(204); - }) - - /** - * POST /api/hosts/123/reconfigure - */ - .post((req, res, next) => { - validator({ - required: ['host_id'], - additionalProperties: false, - properties: { - host_id: { - $ref: 'definitions#/definitions/_id' - } - } - }, req.params) - .then(data => { - return internalHost.reconfigure(data.host_id); - }) - .then(result => { - res.status(200) - .send(result); - }) - .catch(next); - }); - -module.exports = router; diff --git a/manager/src/backend/routes/api/main.js b/manager/src/backend/routes/api/main.js deleted file mode 100644 index 378be3a..0000000 --- a/manager/src/backend/routes/api/main.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -const express = require('express'); -const pjson = require('../../../../package.json'); - -let router = express.Router({ - caseSensitive: true, - strict: true, - mergeParams: true -}); - -/** - * GET /api - */ -router.get('/', (req, res/*, next*/) => { - let version = pjson.version.split('-').shift().split('.'); - - res.status(200).send({ - status: 'Healthy', - version: { - major: parseInt(version.shift(), 10), - minor: parseInt(version.shift(), 10), - revision: parseInt(version.shift(), 10) - } - }); -}); - -router.use('/hosts', require('./hosts')); -router.use('/access', require('./access')); - -module.exports = router; diff --git a/manager/src/backend/routes/main.js b/manager/src/backend/routes/main.js deleted file mode 100644 index 0b0ab4c..0000000 --- a/manager/src/backend/routes/main.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict'; - -const express = require('express'); -const fs = require('fs'); - -const router = express.Router({ - caseSensitive: true, - strict: true, - mergeParams: true -}); - -/** - * Health Check - * GET /health - */ -router.get('/health', (req, res/*, next*/) => { - res.status(200).send({ - status: 'Healthy' - }); -}); - -/** - * GET .* - */ -router.get(/(.*)/, function (req, res, next) { - req.params.page = req.params['0']; - if (req.params.page === '/') { - req.params.page = '/index.html'; - } - - fs.readFile('dist' + req.params.page, 'utf8', function (err, data) { - if (err) { - if (req.params.page !== '/index.html') { - fs.readFile('dist/index.html', 'utf8', function (err2, data) { - if (err2) { - next(err); - } else { - res.contentType('text/html').end(data); - } - }); - } else { - next(err); - } - } else { - res.contentType('text/html').end(data); - } - }); -}); - -module.exports = router; diff --git a/manager/src/backend/schema/definitions.json b/manager/src/backend/schema/definitions.json deleted file mode 100644 index 58822cd..0000000 --- a/manager/src/backend/schema/definitions.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "id": "definitions", - "definitions": { - "id": { - "description": "Unique identifier", - "example": 123456, - "readOnly": true, - "type": "integer", - "minimum": 1 - }, - "_id": { - "description": "Unique identifier", - "example": "dfgbkjwj23asdad23gbweg", - "readOnly": true, - "type": "string", - "minLength": 1 - }, - "hostname": { - "definition": "Fully Qualified Host Name", - "type": "string", - "minLength": 2, - "example": "myhost.example.com" - }, - "expand": { - "anyOf": [ - { - "type": "null" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - ] - }, - "sort": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "required": [ - "field", - "dir" - ], - "additionalProperties": false, - "properties": { - "field": { - "type": "string" - }, - "dir": { - "type": "string", - "pattern": "^(asc|desc)$" - } - } - } - } - } -} diff --git a/manager/src/backend/schema/endpoints/access.json b/manager/src/backend/schema/endpoints/access.json deleted file mode 100644 index b66f888..0000000 --- a/manager/src/backend/schema/endpoints/access.json +++ /dev/null @@ -1,149 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "id": "endpoints/access", - "title": "Access", - "description": "Endpoints relating to Access Lists", - "stability": "stable", - "type": "object", - "definitions": { - "_id": { - "type": "string", - "readonly": true - }, - "name": { - "type": "string", - "minLength": 1, - "maxLength": 50 - }, - "items": { - "type": "array", - "items": { - "type": "object", - "required": [ - "username", - "password" - ], - "properties": { - "username": { - "type": "string", - "minLength": 1, - "maxLength": 50 - }, - "password": { - "type": "string", - "minLength": 0, - "maxLength": 50 - }, - "hint": { - "type": "string", - "minLength": 0, - "maxLength": 50 - } - } - } - }, - "hosts": { - "type": "array", - "items": { - "type": "object" - } - } - }, - "links": [ - { - "title": "List", - "description": "Returns a list of Access Lists", - "href": "/access", - "access": "public", - "method": "GET", - "rel": "self", - "targetSchema": { - "type": "array", - "items": { - "$ref": "#/properties" - } - } - }, - { - "title": "Create", - "description": "Creates a new Access List", - "href": "/access", - "access": "public", - "method": "POST", - "rel": "create", - "schema": { - "type": "object", - "required": [ - "name", - "items" - ], - "properties": { - "name": { - "$ref": "#/definitions/name" - }, - "items": { - "$ref": "#/definitions/items" - } - } - }, - "targetSchema": { - "properties": { - "$ref": "#/properties" - } - } - }, - { - "title": "Update", - "description": "Updates a Access List", - "href": "/hosts/{definitions.identity.example}", - "access": "public", - "method": "PUT", - "rel": "update", - "schema": { - "type": "object", - "required": [ - "name", - "items" - ], - "properties": { - "name": { - "$ref": "#/definitions/name" - }, - "items": { - "$ref": "#/definitions/items" - } - } - }, - "targetSchema": { - "properties": { - "$ref": "#/properties" - } - } - }, - { - "title": "Delete", - "description": "Deletes a existing Access List", - "href": "/hosts/{definitions.identity.example}", - "access": "public", - "method": "DELETE", - "rel": "delete", - "targetSchema": { - "type": "boolean" - } - } - ], - "properties": { - "_id": { - "$ref": "#/definitions/_id" - }, - "name": { - "$ref": "#/definitions/name" - }, - "items": { - "$ref": "#/definitions/items" - }, - "hosts": { - "$ref": "#/definitions/hosts" - } - } -} diff --git a/manager/src/backend/schema/endpoints/hosts.json b/manager/src/backend/schema/endpoints/hosts.json deleted file mode 100644 index c56ed69..0000000 --- a/manager/src/backend/schema/endpoints/hosts.json +++ /dev/null @@ -1,272 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "id": "endpoints/hosts", - "title": "Hosts", - "description": "Endpoints relating to Hosts", - "stability": "stable", - "type": "object", - "definitions": { - "_id": { - "type": "string", - "readonly": true - }, - "type": { - "type": "string", - "pattern": "^(proxy|redirection|404|stream)$" - }, - "hostname": { - "$ref": "../definitions.json#/definitions/hostname" - }, - "forward_server": { - "type": "string", - "format": "ipv4" - }, - "forward_host": { - "type": "string" - }, - "forward_port": { - "type": "integer", - "minumum": 1, - "maxiumum": 65535 - }, - "asset_caching": { - "type": "boolean" - }, - "block_exploits": { - "type": "boolean" - }, - "ssl": { - "type": "boolean" - }, - "letsencrypt_email": { - "type": "string", - "format": "email" - }, - "force_ssl": { - "type": "boolean" - }, - "access_list_id": { - "type": "string" - }, - "advanced": { - "type": "string" - }, - "access_list": { - "type": "object", - "readonly": true - }, - "incoming_port": { - "type": "integer", - "minumum": 1, - "maxiumum": 65535 - }, - "protocols": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "links": [ - { - "title": "List", - "description": "Returns a list of Hosts", - "href": "/hosts", - "access": "public", - "method": "GET", - "rel": "self", - "targetSchema": { - "type": "array", - "items": { - "$ref": "#/properties" - } - } - }, - { - "title": "Create", - "description": "Creates a new Host", - "href": "/hosts", - "access": "public", - "method": "POST", - "rel": "create", - "schema": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "$ref": "#/definitions/type" - }, - "hostname": { - "$ref": "#/definitions/hostname" - }, - "forward_host": { - "$ref": "#/definitions/forward_host" - }, - "forward_server": { - "$ref": "#/definitions/forward_server" - }, - "forward_port": { - "$ref": "#/definitions/forward_port" - }, - "asset_caching": { - "$ref": "#/definitions/asset_caching" - }, - "block_exploits": { - "$ref": "#/definitions/block_exploits" - }, - "ssl": { - "$ref": "#/definitions/ssl" - }, - "letsencrypt_email": { - "$ref": "#/definitions/letsencrypt_email" - }, - "force_ssl": { - "$ref": "#/definitions/force_ssl" - }, - "advanced": { - "$ref": "#/definitions/advanced" - }, - "access_list_id": { - "$ref": "#/definitions/access_list_id" - }, - "incoming_port": { - "$ref": "#/definitions/incoming_port" - }, - "protocols": { - "$ref": "#/definitions/protocols" - } - } - }, - "targetSchema": { - "properties": { - "$ref": "#/properties" - } - } - }, - { - "title": "Update", - "description": "Updates a Host", - "href": "/hosts/{definitions.identity.example}", - "access": "public", - "method": "PUT", - "rel": "update", - "schema": { - "type": "object", - "required": [], - "additionalProperties": false, - "properties": { - "type": { - "$ref": "#/definitions/type" - }, - "hostname": { - "$ref": "#/definitions/hostname" - }, - "forward_host": { - "$ref": "#/definitions/forward_host" - }, - "forward_server": { - "$ref": "#/definitions/forward_server" - }, - "forward_port": { - "$ref": "#/definitions/forward_port" - }, - "asset_caching": { - "$ref": "#/definitions/asset_caching" - }, - "block_exploits": { - "$ref": "#/definitions/block_exploits" - }, - "ssl": { - "$ref": "#/definitions/ssl" - }, - "letsencrypt_email": { - "$ref": "#/definitions/letsencrypt_email" - }, - "force_ssl": { - "$ref": "#/definitions/force_ssl" - }, - "advanced": { - "$ref": "#/definitions/advanced" - }, - "access_list_id": { - "$ref": "#/definitions/access_list_id" - }, - "incoming_port": { - "$ref": "#/definitions/incoming_port" - }, - "protocols": { - "$ref": "#/definitions/protocols" - } - } - }, - "targetSchema": { - "properties": { - "$ref": "#/properties" - } - } - }, - { - "title": "Delete", - "description": "Deletes a existing Host", - "href": "/hosts/{definitions.identity.example}", - "access": "public", - "method": "DELETE", - "rel": "delete", - "targetSchema": { - "type": "boolean" - } - } - ], - "properties": { - "_id": { - "$ref": "#/definitions/_id" - }, - "type": { - "$ref": "#/definitions/type" - }, - "hostname": { - "$ref": "#/definitions/hostname" - }, - "forward_host": { - "$ref": "#/definitions/forward_host" - }, - "forward_server": { - "$ref": "#/definitions/forward_server" - }, - "forward_port": { - "$ref": "#/definitions/forward_port" - }, - "asset_caching": { - "$ref": "#/definitions/asset_caching" - }, - "block_exploits": { - "$ref": "#/definitions/block_exploits" - }, - "ssl": { - "$ref": "#/definitions/ssl" - }, - "letsencrypt_email": { - "$ref": "#/definitions/letsencrypt_email" - }, - "force_ssl": { - "$ref": "#/definitions/force_ssl" - }, - "access_list_id": { - "$ref": "#/definitions/access_list_id" - }, - "access_list": { - "$ref": "#/definitions/access_list" - }, - "advanced": { - "$ref": "#/definitions/advanced" - }, - "incoming_port": { - "$ref": "#/definitions/incoming_port" - }, - "protocols": { - "$ref": "#/definitions/protocols" - } - } -} diff --git a/manager/src/backend/schema/examples.json b/manager/src/backend/schema/examples.json deleted file mode 100644 index 1a95cfa..0000000 --- a/manager/src/backend/schema/examples.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "id": "examples", - "type": "object", - "definitions": {} -} diff --git a/manager/src/backend/schema/index.json b/manager/src/backend/schema/index.json deleted file mode 100644 index ce056d3..0000000 --- a/manager/src/backend/schema/index.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "title": "Nginx Proxy Manager REST API", - "description": "This is the Nginx Proxy Manager REST API", - "id": "root", - "version": "1.0.0", - "links": [ - { - "href": "http://localhost:81/api", - "rel": "self" - } - ], - "properties": { - "hosts": { - "$ref": "endpoints/hosts.json" - }, - "access": { - "$ref": "endpoints/access.json" - } - } -} diff --git a/manager/src/backend/templates/404.conf.ejs b/manager/src/backend/templates/404.conf.ejs deleted file mode 100644 index d136541..0000000 --- a/manager/src/backend/templates/404.conf.ejs +++ /dev/null @@ -1,19 +0,0 @@ -# <%- hostname %> -server { - listen 80; - <%- typeof ssl !== 'undefined' && ssl ? 'listen 443 ssl;' : '' %> - - server_name <%- hostname %>; - - access_log /config/logs/<%- hostname %>.log proxy; - -<% if (typeof ssl !== 'undefined' && ssl) { -%> - include conf.d/include/ssl-ciphers.conf; - ssl_certificate /etc/letsencrypt/live/<%- hostname %>/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/<%- hostname %>/privkey.pem; -<% } -%> - - <%- typeof advanced !== 'undefined' && advanced ? advanced : '' %> - - return 404; -} diff --git a/manager/src/backend/templates/letsencrypt.conf.ejs b/manager/src/backend/templates/letsencrypt.conf.ejs deleted file mode 100644 index f870f2e..0000000 --- a/manager/src/backend/templates/letsencrypt.conf.ejs +++ /dev/null @@ -1,11 +0,0 @@ -# Letsencrypt Verification Temporary Host: <%- hostname %> -server { - listen 80; - server_name <%- hostname %>; - - access_log /config/logs/letsencrypt.log proxy; - - location / { - root /config/letsencrypt-acme-challenge; - } -} diff --git a/manager/src/backend/templates/proxy.conf.ejs b/manager/src/backend/templates/proxy.conf.ejs deleted file mode 100644 index 4f32036..0000000 --- a/manager/src/backend/templates/proxy.conf.ejs +++ /dev/null @@ -1,33 +0,0 @@ -# <%- hostname %> -server { - listen 80; - <%- typeof ssl !== 'undefined' && ssl ? 'listen 443 ssl;' : '' %> - - server_name <%- hostname %>; - - access_log /config/logs/<%- hostname %>.log proxy; - - set $server <%- forward_server %>; - set $port <%- forward_port %>; - - <%- typeof asset_caching !== 'undefined' && asset_caching ? 'include conf.d/include/assets.conf;' : '' %> - <%- typeof block_exploits !== 'undefined' && block_exploits ? 'include conf.d/include/block-exploits.conf;' : '' %> - -<% if (typeof ssl !== 'undefined' && ssl) { -%> - include conf.d/include/letsencrypt-acme-challenge.conf; - include conf.d/include/ssl-ciphers.conf; - ssl_certificate /etc/letsencrypt/live/<%- hostname %>/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/<%- hostname %>/privkey.pem; -<% } -%> - -<%- typeof advanced !== 'undefined' && advanced ? advanced : '' %> - - location / { - <% if (typeof access_list_id !== 'undefined' && access_list_id) { -%> - auth_basic "Authorization required"; - auth_basic_user_file /config/access/<%- access_list_id %>; - <% } -%> - <%- typeof force_ssl !== 'undefined' && force_ssl ? 'include conf.d/include/force-ssl.conf;' : '' %> - include conf.d/include/proxy.conf; - } -} diff --git a/manager/src/backend/templates/redirection.conf.ejs b/manager/src/backend/templates/redirection.conf.ejs deleted file mode 100644 index 1c4f91b..0000000 --- a/manager/src/backend/templates/redirection.conf.ejs +++ /dev/null @@ -1,22 +0,0 @@ -# <%- hostname %> -server { - listen 80; - <%- typeof ssl !== 'undefined' && ssl ? 'listen 443 ssl;' : '' %> - - server_name <%- hostname %>; - - access_log /config/logs/<%- hostname %>.log proxy; - - <%- typeof asset_caching !== 'undefined' && asset_caching ? 'include conf.d/include/assets.conf;' : '' %> - <%- typeof block_exploits !== 'undefined' && block_exploits ? 'include conf.d/include/block-exploits.conf;' : '' %> - -<% if (typeof ssl !== 'undefined' && ssl) { -%> - include conf.d/include/ssl-ciphers.conf; - ssl_certificate /etc/letsencrypt/live/<%- hostname %>/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/<%- hostname %>/privkey.pem; -<% } -%> - - <%- typeof advanced !== 'undefined' && advanced ? advanced : '' %> - - return 301 $scheme://<%- forward_host %>$request_uri; -} diff --git a/manager/src/backend/templates/stream.conf.ejs b/manager/src/backend/templates/stream.conf.ejs deleted file mode 100644 index 49994a2..0000000 --- a/manager/src/backend/templates/stream.conf.ejs +++ /dev/null @@ -1,11 +0,0 @@ -# <%- incoming_port %> - <%- protocols.join(',').toUpperCase() %> -<% -protocols.forEach(function (protocol) { -%> -server { - listen <%- incoming_port %> <%- protocol === 'tcp' ? '' : protocol %>; - proxy_pass <%- forward_server %>:<%- forward_port %>; -} -<% -}); -%> diff --git a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.eot b/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.eot deleted file mode 100755 index b93a495..0000000 Binary files a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.eot and /dev/null differ diff --git a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.svg b/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.svg deleted file mode 100755 index 94fb549..0000000 --- a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.svg +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.ttf b/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.ttf deleted file mode 100755 index 1413fc6..0000000 Binary files a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.ttf and /dev/null differ diff --git a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.woff b/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.woff deleted file mode 100755 index 9e61285..0000000 Binary files a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.woff and /dev/null differ diff --git a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.woff2 b/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.woff2 deleted file mode 100755 index 64539b5..0000000 Binary files a/manager/src/frontend/fonts/bootstrap/glyphicons-halflings-regular.woff2 and /dev/null differ diff --git a/manager/src/frontend/fonts/font-awesome/FontAwesome.otf b/manager/src/frontend/fonts/font-awesome/FontAwesome.otf deleted file mode 100755 index 401ec0f..0000000 Binary files a/manager/src/frontend/fonts/font-awesome/FontAwesome.otf and /dev/null differ diff --git a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.eot b/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.eot deleted file mode 100755 index e9f60ca..0000000 Binary files a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.eot and /dev/null differ diff --git a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.svg b/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.svg deleted file mode 100755 index 855c845..0000000 --- a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.svg +++ /dev/null @@ -1,2671 +0,0 @@ - - - - -Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 - By ,,, -Copyright Dave Gandy 2016. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.ttf b/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.ttf deleted file mode 100755 index 35acda2..0000000 Binary files a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.ttf and /dev/null differ diff --git a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.woff b/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.woff deleted file mode 100755 index 400014a..0000000 Binary files a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.woff and /dev/null differ diff --git a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.woff2 b/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.woff2 deleted file mode 100755 index 4d13fc6..0000000 Binary files a/manager/src/frontend/fonts/font-awesome/fontawesome-webfont.woff2 and /dev/null differ diff --git a/manager/src/frontend/images/favicon/android-chrome-192x192.png b/manager/src/frontend/images/favicon/android-chrome-192x192.png deleted file mode 100644 index 7bf92cc..0000000 Binary files a/manager/src/frontend/images/favicon/android-chrome-192x192.png and /dev/null differ diff --git a/manager/src/frontend/images/favicon/android-chrome-512x512.png b/manager/src/frontend/images/favicon/android-chrome-512x512.png deleted file mode 100644 index 499abf5..0000000 Binary files a/manager/src/frontend/images/favicon/android-chrome-512x512.png and /dev/null differ diff --git a/manager/src/frontend/images/favicon/apple-touch-icon.png b/manager/src/frontend/images/favicon/apple-touch-icon.png deleted file mode 100644 index 31e8c9d..0000000 Binary files a/manager/src/frontend/images/favicon/apple-touch-icon.png and /dev/null differ diff --git a/manager/src/frontend/images/favicon/browserconfig.xml b/manager/src/frontend/images/favicon/browserconfig.xml deleted file mode 100644 index e781b88..0000000 --- a/manager/src/frontend/images/favicon/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - #f0ad00 - - - diff --git a/manager/src/frontend/images/favicon/favicon-16x16.png b/manager/src/frontend/images/favicon/favicon-16x16.png deleted file mode 100644 index 0072a79..0000000 Binary files a/manager/src/frontend/images/favicon/favicon-16x16.png and /dev/null differ diff --git a/manager/src/frontend/images/favicon/favicon-32x32.png b/manager/src/frontend/images/favicon/favicon-32x32.png deleted file mode 100644 index f8762e7..0000000 Binary files a/manager/src/frontend/images/favicon/favicon-32x32.png and /dev/null differ diff --git a/manager/src/frontend/images/favicon/favicon.ico b/manager/src/frontend/images/favicon/favicon.ico deleted file mode 100644 index 6090f0f..0000000 Binary files a/manager/src/frontend/images/favicon/favicon.ico and /dev/null differ diff --git a/manager/src/frontend/images/favicon/manifest.json b/manager/src/frontend/images/favicon/manifest.json deleted file mode 100644 index c0a1e16..0000000 --- a/manager/src/frontend/images/favicon/manifest.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "", - "icons": [ - { - "src": "/images/favicon/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/images/favicon/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#ffffff", - "background_color": "#ffffff", - "display": "standalone" -} \ No newline at end of file diff --git a/manager/src/frontend/images/favicon/mstile-150x150.png b/manager/src/frontend/images/favicon/mstile-150x150.png deleted file mode 100644 index 14687cc..0000000 Binary files a/manager/src/frontend/images/favicon/mstile-150x150.png and /dev/null differ diff --git a/manager/src/frontend/images/favicon/safari-pinned-tab.svg b/manager/src/frontend/images/favicon/safari-pinned-tab.svg deleted file mode 100644 index 8333c04..0000000 --- a/manager/src/frontend/images/favicon/safari-pinned-tab.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - -Created by potrace 1.11, written by Peter Selinger 2001-2013 - - - - - - - diff --git a/manager/src/frontend/js/app/access/empty.ejs b/manager/src/frontend/js/app/access/empty.ejs deleted file mode 100644 index 382b17e..0000000 --- a/manager/src/frontend/js/app/access/empty.ejs +++ /dev/null @@ -1,5 +0,0 @@ - -

-

It looks like there are no access lists configured.

-

- diff --git a/manager/src/frontend/js/app/access/empty.js b/manager/src/frontend/js/app/access/empty.js deleted file mode 100644 index bf2f06c..0000000 --- a/manager/src/frontend/js/app/access/empty.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const template = require('./empty.ejs'); -const AccessModel = require('../../models/access'); -const Controller = require('../controller'); - -module.exports = Mn.View.extend({ - template: template, - tagName: 'tr', - - ui: { - create: 'button' - }, - - events: { - 'click @ui.create': function (e) { - e.preventDefault(); - Controller.showAccessListForm(new AccessModel.Model); - } - } -}); diff --git a/manager/src/frontend/js/app/access/main.ejs b/manager/src/frontend/js/app/access/main.ejs deleted file mode 100644 index 795e0a9..0000000 --- a/manager/src/frontend/js/app/access/main.ejs +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - -
Access List NameUser CountHost Count
diff --git a/manager/src/frontend/js/app/access/main.js b/manager/src/frontend/js/app/access/main.js deleted file mode 100644 index ac9929a..0000000 --- a/manager/src/frontend/js/app/access/main.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const Api = require('../api'); -const template = require('./main.ejs'); -const Controller = require('../controller'); -const RowView = require('./row'); -const AccessListModel = require('../../models/access'); -const EmptyView = require('./empty'); - -const TableBody = Mn.CollectionView.extend({ - tagName: 'tbody', - childView: RowView -}); - -module.exports = Mn.View.extend({ - template: template, - id: 'access', - - regions: { - list_region: { - el: 'tbody', - replaceElement: true - } - }, - - ui: { - 'create': 'th button' - }, - - events: { - 'click @ui.create': function (e) { - e.preventDefault(); - Controller.showAccessListForm(new AccessListModel.Model); - } - }, - - onRender: function () { - let view = this; - - Api.Access.getAll() - .then(response => { - if (!view.isDestroyed()) { - if (response && response.length) { - view.showChildView('list_region', new TableBody({ - collection: new AccessListModel.Collection(response) - })); - } else { - view.showChildView('list_region', new EmptyView()); - } - - view.trigger('loaded'); - } - }) - .catch(err => { - Controller.showError(err, 'Could not fetch Access Lists'); - view.trigger('loaded'); - }); - } -}); - diff --git a/manager/src/frontend/js/app/access/row.ejs b/manager/src/frontend/js/app/access/row.ejs deleted file mode 100644 index 9aa77bd..0000000 --- a/manager/src/frontend/js/app/access/row.ejs +++ /dev/null @@ -1,7 +0,0 @@ -<%- name %> -<%- items.length %> -<%- hosts.length %> - - - - diff --git a/manager/src/frontend/js/app/access/row.js b/manager/src/frontend/js/app/access/row.js deleted file mode 100644 index 5570db4..0000000 --- a/manager/src/frontend/js/app/access/row.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const template = require('./row.ejs'); -const Controller = require('../controller'); - -module.exports = Mn.View.extend({ - template: template, - tagName: 'tr', - - ui: { - edit: 'button.edit', - delete: 'button.delete' - }, - - events: { - 'click @ui.edit': function (e) { - e.preventDefault(); - Controller.showAccessListForm(this.model); - }, - - 'click @ui.delete': function (e) { - e.preventDefault(); - Controller.showDeleteAccessList(this.model); - } - }, - - initialize: function () { - this.listenTo(this.model, 'change', this.render); - } -}); diff --git a/manager/src/frontend/js/app/access_list/delete.ejs b/manager/src/frontend/js/app/access_list/delete.ejs deleted file mode 100644 index 1bb2cc5..0000000 --- a/manager/src/frontend/js/app/access_list/delete.ejs +++ /dev/null @@ -1,24 +0,0 @@ - diff --git a/manager/src/frontend/js/app/access_list/delete.js b/manager/src/frontend/js/app/access_list/delete.js deleted file mode 100644 index 7062428..0000000 --- a/manager/src/frontend/js/app/access_list/delete.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const template = require('./delete.ejs'); -const Controller = require('../controller'); -const Api = require('../api'); -const App = require('../main'); - -module.exports = Mn.View.extend({ - template: template, - - ui: { - buttons: 'form button', - delete: 'button.delete' - }, - - events: { - 'click @ui.delete': function (e) { - e.preventDefault(); - - this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); - - Api.Access.delete(this.model.get('_id')) - .then((/*result*/) => { - App.UI.closeModal(); - Controller.showAccess(); - }) - .catch(err => { - alert(err.message); - this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); - }); - } - } -}); diff --git a/manager/src/frontend/js/app/access_list/form.ejs b/manager/src/frontend/js/app/access_list/form.ejs deleted file mode 100644 index 3175952..0000000 --- a/manager/src/frontend/js/app/access_list/form.ejs +++ /dev/null @@ -1,30 +0,0 @@ - diff --git a/manager/src/frontend/js/app/access_list/form.js b/manager/src/frontend/js/app/access_list/form.js deleted file mode 100644 index ac636f0..0000000 --- a/manager/src/frontend/js/app/access_list/form.js +++ /dev/null @@ -1,95 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const _ = require('lodash'); -const template = require('./form.ejs'); -const Controller = require('../controller'); -const Api = require('../api'); -const App = require('../main'); -const ItemView = require('./item'); -const AccessItemModel = require('../../models/access_item'); - -require('jquery-serializejson'); - -const ItemsView = Mn.CollectionView.extend({ - childView: ItemView -}); - -module.exports = Mn.View.extend({ - template: template, - id: 'access-list-form', - - ui: { - items_region: '.items', - form: 'form', - buttons: 'form button' - }, - - regions: { - items_region: '@ui.items_region' - }, - - events: { - 'submit @ui.form': function (e) { - e.preventDefault(); - - let form_data = this.ui.form.serializeJSON(); - let items_data = []; - - _.map(form_data.username, (val, idx) => { - if (val.trim().length) { - items_data.push({ - username: val.trim(), - password: form_data.password[idx] - }); - } - }); - - if (!items_data.length) { - alert('You must specify at least 1 Username and Password combination'); - return; - } - - let data = { - name: form_data.name, - items: items_data - }; - - this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); - let method = Api.Access.create; - - if (this.model.get('_id')) { - // edit - method = Api.Access.update; - data._id = this.model.get('_id'); - } - - method(data) - .then((/*result*/) => { - App.UI.closeModal(); - Controller.showAccess(); - }) - .catch((err) => { - alert(err.message); - this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); - }); - } - }, - - onRender: function () { - let items = this.model.get('items'); - - // Add empty items to the end of the list. This is cheating but hey I don't have the time to do it right - let items_to_add = 5 - items.length; - if (items_to_add) { - for (let i = 0; i < items_to_add; i++) { - items.push({}); - } - } - - this.showChildView('items_region', new ItemsView({ - collection: new AccessItemModel.Collection(items) - })); - } -}); diff --git a/manager/src/frontend/js/app/access_list/item.ejs b/manager/src/frontend/js/app/access_list/item.ejs deleted file mode 100644 index 74c6bae..0000000 --- a/manager/src/frontend/js/app/access_list/item.ejs +++ /dev/null @@ -1,8 +0,0 @@ -
-
- -
-
- -
-
diff --git a/manager/src/frontend/js/app/access_list/item.js b/manager/src/frontend/js/app/access_list/item.js deleted file mode 100644 index e707eba..0000000 --- a/manager/src/frontend/js/app/access_list/item.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const template = require('./item.ejs'); - -module.exports = Mn.View.extend({ - template: template -}); diff --git a/manager/src/frontend/js/app/api.js b/manager/src/frontend/js/app/api.js deleted file mode 100644 index 3697a36..0000000 --- a/manager/src/frontend/js/app/api.js +++ /dev/null @@ -1,160 +0,0 @@ -'use strict'; - -import $ from 'jquery'; - -/** - * @param {String} message - * @param {*} debug - * @param {Number} code - * @constructor - */ -const ApiError = function (message, debug, code) { - let temp = Error.call(this, message); - temp.name = this.name = 'ApiError'; - - this.stack = temp.stack; - this.message = temp.message; - this.debug = debug; - this.code = code; -}; - -ApiError.prototype = Object.create(Error.prototype, { - constructor: { - value: ApiError, - writable: true, - configurable: true - } -}); - -/** - * - * @param {String} verb - * @param {String} path - * @param {Object} [data] - * @param {Object} [options] - * @returns {Promise} - */ -function fetch (verb, path, data, options) { - options = options || {}; - - return new Promise(function (resolve, reject) { - let api_url = '/api/'; - let url = api_url + path; - - $.ajax({ - url: url, - data: typeof data === 'object' && data !== null ? JSON.stringify(data) : data, - type: verb, - dataType: 'json', - contentType: 'application/json; charset=UTF-8', - crossDomain: true, - timeout: (options.timeout ? options.timeout : 30000), - xhrFields: { - withCredentials: true - }, - - success: function (data, textStatus, response) { - resolve(response); - }, - - error: function (xhr, status, error_thrown) { - let code = 400; - - if (typeof xhr.responseJSON !== 'undefined' && typeof xhr.responseJSON.error !== 'undefined' && typeof xhr.responseJSON.error.message !== 'undefined') { - error_thrown = xhr.responseJSON.error.message; - code = xhr.responseJSON.error.code || 500; - } - - reject(new ApiError(error_thrown, xhr.responseText, code)); - } - }); - }); -} - -module.exports = { - status: function () { - return fetch('get', ''); - }, - - Hosts: { - - /** - * @returns {Promise} - */ - getAll: function () { - return fetch('get', 'hosts'); - }, - - /** - * @param {Object} data - * @returns {Promise} - */ - create: function (data) { - return fetch('post', 'hosts', data); - }, - - /** - * @param {Object} data - * @param {String} data._id - * @returns {Promise} - */ - update: function (data) { - let _id = data._id; - delete data._id; - return fetch('put', 'hosts/' + _id, data); - }, - - /** - * @param {String} _id - * @returns {Promise} - */ - delete: function (_id) { - return fetch('delete', 'hosts/' + _id); - }, - - /** - * @param {String} _id - * @returns {Promise} - */ - reconfigure: function (_id) { - return fetch('post', 'hosts/' + _id + '/reconfigure'); - } - }, - - Access: { - - /** - * @returns {Promise} - */ - getAll: function () { - return fetch('get', 'access'); - }, - - /** - * @param {Object} data - * @returns {Promise} - */ - create: function (data) { - return fetch('post', 'access', data); - }, - - /** - * @param {Object} data - * @param {String} data._id - * @returns {Promise} - */ - update: function (data) { - let _id = data._id; - delete data._id; - return fetch('put', 'access/' + _id, data); - }, - - /** - * @param {String} _id - * @returns {Promise} - */ - delete: function (_id) { - return fetch('delete', 'access/' + _id); - } - } -}; diff --git a/manager/src/frontend/js/app/cache.js b/manager/src/frontend/js/app/cache.js deleted file mode 100644 index c0c9df5..0000000 --- a/manager/src/frontend/js/app/cache.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -let cache = {}; - -module.exports = cache; diff --git a/manager/src/frontend/js/app/controller.js b/manager/src/frontend/js/app/controller.js deleted file mode 100644 index 2bf685b..0000000 --- a/manager/src/frontend/js/app/controller.js +++ /dev/null @@ -1,170 +0,0 @@ -'use strict'; - -import Backbone from 'backbone'; - -const Cache = require('./cache'); - -module.exports = { - - /** - * @param {String} route - * @param {Object} [options] - * @returns {Boolean} - */ - navigate: function (route, options) { - options = options || {}; - Backbone.history.navigate(route.toString(), options); - return true; - }, - - /** - * Dashboard - */ - showDashboard: function () { - require(['./main', './dashboard/main'], (App, View) => { - this.navigate('/'); - App.UI.showMainLoading(); - - let view = new View(); - - view.on('loaded', function () { - App.UI.hideMainLoading(); - }); - - App.UI.showChildView('main_region', view); - }); - }, - - /** - * Access - */ - showAccess: function () { - require(['./main', './access/main'], (App, View) => { - this.navigate('/access'); - App.UI.showMainLoading(); - - let view = new View(); - - view.on('loaded', function () { - App.UI.hideMainLoading(); - }); - - App.UI.showChildView('main_region', view); - }); - }, - - /** - * Show Proxy Host Form - * - * @param model - */ - showProxyHostForm: function (model) { - require(['./main', './host/proxy_form'], function (App, View) { - App.UI.showModalDialog(new View({model: model})); - }); - }, - - /** - * Show Redirection Host Form - * - * @param model - */ - showRedirectionHostForm: function (model) { - require(['./main', './host/redirection_form'], function (App, View) { - App.UI.showModalDialog(new View({model: model})); - }); - }, - - /** - * Show 404 Host Form - * - * @param model - */ - show404HostForm: function (model) { - require(['./main', './host/404_form'], function (App, View) { - App.UI.showModalDialog(new View({model: model})); - }); - }, - - /** - * Show Stream Host Form - * - * @param model - */ - showStreamHostForm: function (model) { - require(['./main', './host/stream_form'], function (App, View) { - App.UI.showModalDialog(new View({model: model})); - }); - }, - - /** - * Show Delete Host Confirmation - * - * @param model - */ - showDeleteHost: function (model) { - require(['./main', './host/delete'], function (App, View) { - App.UI.showModalDialog(new View({model: model})); - }); - }, - - /** - * Show Reconfigure Host - * - * @param model - */ - showReconfigureHost: function (model) { - require(['./main', './host/reconfigure'], function (App, View) { - App.UI.showModalDialog(new View({model: model})); - }); - }, - - /** - * Show Advanced Host - * - * @param model - */ - showAdvancedHost: function (model) { - require(['./main', './host/advanced'], function (App, View) { - App.UI.showModalDialog(new View({model: model})); - }); - }, - - - /** - * Show Access List Form - * - * @param model - */ - showAccessListForm: function (model) { - require(['./main', './access_list/form'], function (App, View) { - App.UI.showModalDialog(new View({model: model})); - }); - }, - - /** - * Show Delete Access List Confirmation - * - * @param model - */ - showDeleteAccessList: function (model) { - require(['./main', './access_list/delete'], function (App, View) { - App.UI.showModalDialog(new View({model: model})); - }); - }, - - /** - * Error - * - * @param {Error} err - * @param {String} nice_msg - */ - showError: function (err, nice_msg) { - require(['./main', './error/main'], (App, View) => { - App.UI.showChildView('main_region', new View({ - err: err, - nice_msg: nice_msg - })); - }); - } -}; diff --git a/manager/src/frontend/js/app/dashboard/empty.ejs b/manager/src/frontend/js/app/dashboard/empty.ejs deleted file mode 100644 index f45451a..0000000 --- a/manager/src/frontend/js/app/dashboard/empty.ejs +++ /dev/null @@ -1,9 +0,0 @@ - -

-

It looks like there are no hosts configured.

-

- - - -

- diff --git a/manager/src/frontend/js/app/dashboard/empty.js b/manager/src/frontend/js/app/dashboard/empty.js deleted file mode 100644 index 48d6b52..0000000 --- a/manager/src/frontend/js/app/dashboard/empty.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const template = require('./empty.ejs'); -const HostModel = require('../../models/host'); -const Controller = require('../controller'); - -module.exports = Mn.View.extend({ - template: template, - tagName: 'tr', - - ui: { - proxy: 'button.proxy', - redirection: 'button.redirection', - '404': 'button.404' - }, - - events: { - 'click @ui.proxy': function (e) { - e.preventDefault(); - Controller.showProxyHostForm(new HostModel.Model); - }, - - 'click @ui.redirection': function (e) { - e.preventDefault(); - Controller.showRedirectionHostForm(new HostModel.Model); - }, - - 'click @ui.404': function (e) { - e.preventDefault(); - Controller.show404HostForm(new HostModel.Model); - } - } -}); diff --git a/manager/src/frontend/js/app/dashboard/main.ejs b/manager/src/frontend/js/app/dashboard/main.ejs deleted file mode 100644 index 6df4f24..0000000 --- a/manager/src/frontend/js/app/dashboard/main.ejs +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - -
SourceDestinationSSLAccess List -
- - -
-
diff --git a/manager/src/frontend/js/app/dashboard/main.js b/manager/src/frontend/js/app/dashboard/main.js deleted file mode 100644 index 7897a66..0000000 --- a/manager/src/frontend/js/app/dashboard/main.js +++ /dev/null @@ -1,81 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const Api = require('../api'); -const template = require('./main.ejs'); -const Controller = require('../controller'); -const RowView = require('./row'); -const HostModel = require('../../models/host'); -const EmptyView = require('./empty'); - -const TableBody = Mn.CollectionView.extend({ - tagName: 'tbody', - childView: RowView -}); - -module.exports = Mn.View.extend({ - template: template, - id: 'dashboard', - - regions: { - list_region: { - el: 'tbody', - replaceElement: true - } - }, - - ui: { - new_proxy: 'th .new-proxy', - new_redirection: 'th .new-redirection', - new_404: 'th .new-404', - new_stream: 'th .new-stream' - }, - - events: { - 'click @ui.new_proxy': function (e) { - e.preventDefault(); - Controller.showProxyHostForm(new HostModel.Model); - }, - - 'click @ui.new_redirection': function (e) { - e.preventDefault(); - Controller.showRedirectionHostForm(new HostModel.Model); - }, - - 'click @ui.new_404': function (e) { - e.preventDefault(); - Controller.show404HostForm(new HostModel.Model); - }, - - 'click @ui.new_stream': function (e) { - e.preventDefault(); - Controller.showStreamHostForm(new HostModel.Model); - } - }, - - onRender: function () { - let view = this; - - Api.Hosts.getAll() - .then(response => { - if (!view.isDestroyed()) { - if (response && response.length) { - - view.showChildView('list_region', new TableBody({ - collection: new HostModel.Collection(response) - })); - } else { - view.showChildView('list_region', new EmptyView()); - } - - view.trigger('loaded'); - } - }) - .catch(err => { - Controller.showError(err, 'Could not fetch Hosts'); - view.trigger('loaded'); - }); - } -}); - diff --git a/manager/src/frontend/js/app/dashboard/row.ejs b/manager/src/frontend/js/app/dashboard/row.ejs deleted file mode 100644 index 19a3ba4..0000000 --- a/manager/src/frontend/js/app/dashboard/row.ejs +++ /dev/null @@ -1,49 +0,0 @@ - - <% if (type === 'stream') { %> - <%- incoming_port %> - <%- protocols.join(', ').toUpperCase() %> - <% } else { %> - <%- hostname %> - <% } %> - - - - <% if (type === 'proxy' || type === 'stream') { %> - <%- forward_server %>:<%- forward_port %> - <% } else if (type === 'redirection') { %> - <%- forward_host %> - <% } else if (type === '404') { %> - 404 - <% } %> - - - - <% if (type === 'stream') { %> - - - <% } else { %> - <% if (ssl && force_ssl) { %> - Forced - <% } else if (ssl) { %> - Enabled - <% } else { %> - No - <% } %> - <% } %> - - - <% if (type === 'stream') { %> - - - <% } else { %> - <% if (access_list) { %> - <%- access_list.name %> - <% } else { %> - None - <% } %> - <% } %> - - - - - - - diff --git a/manager/src/frontend/js/app/dashboard/row.js b/manager/src/frontend/js/app/dashboard/row.js deleted file mode 100644 index 0cefc94..0000000 --- a/manager/src/frontend/js/app/dashboard/row.js +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const template = require('./row.ejs'); -const Controller = require('../controller'); -const AccessListModel = require('../../models/access'); - -module.exports = Mn.View.extend({ - template: template, - tagName: 'tr', - - ui: { - edit: 'button.edit', - delete: 'button.delete', - access_list: 'a.access_list', - reconfigure: 'button.reconfigure', - advanced: 'button.advanced' - }, - - events: { - 'click @ui.edit': function (e) { - e.preventDefault(); - switch (this.model.get('type')) { - case 'proxy': - Controller.showProxyHostForm(this.model); - break; - case 'redirection': - Controller.showRedirectionHostForm(this.model); - break; - case '404': - Controller.show404HostForm(this.model); - break; - case 'stream': - Controller.showStreamHostForm(this.model); - break; - } - }, - - 'click @ui.delete': function (e) { - e.preventDefault(); - Controller.showDeleteHost(this.model); - }, - - 'click @ui.access_list': function (e) { - e.preventDefault(); - Controller.showAccessListForm(new AccessListModel.Model(this.model.get('access_list'))); - }, - - 'click @ui.reconfigure': function (e) { - e.preventDefault(); - Controller.showReconfigureHost(this.model); - }, - - 'click @ui.advanced': function (e) { - e.preventDefault(); - Controller.showAdvancedHost(this.model); - } - }, - - initialize: function () { - this.listenTo(this.model, 'change', this.render); - } -}); diff --git a/manager/src/frontend/js/app/error/main.ejs b/manager/src/frontend/js/app/error/main.ejs deleted file mode 100644 index 68bafc0..0000000 --- a/manager/src/frontend/js/app/error/main.ejs +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/manager/src/frontend/js/app/error/main.js b/manager/src/frontend/js/app/error/main.js deleted file mode 100644 index 02e8d8b..0000000 --- a/manager/src/frontend/js/app/error/main.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const template = require('./main.ejs'); - -module.exports = Mn.View.extend({ - id: 'error', - template: template, - - options: { - err: null, - nice_msg: 'Unknown error' - }, - - templateContext: function () { - let view = this; - return { - getNiceMessage: function () { - return view.options.nice_msg; - }, - - getErrorMessage: function () { - return view.options.err ? view.options.err.message : ''; - } - }; - }, - - initialize: function () { - console.error(this.options.err); - } -}); - diff --git a/manager/src/frontend/js/app/host/404_form.ejs b/manager/src/frontend/js/app/host/404_form.ejs deleted file mode 100644 index 373a66d..0000000 --- a/manager/src/frontend/js/app/host/404_form.ejs +++ /dev/null @@ -1,50 +0,0 @@ - diff --git a/manager/src/frontend/js/app/host/404_form.js b/manager/src/frontend/js/app/host/404_form.js deleted file mode 100644 index 8a6b3c0..0000000 --- a/manager/src/frontend/js/app/host/404_form.js +++ /dev/null @@ -1,78 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const _ = require('lodash'); -const template = require('./404_form.ejs'); -const Controller = require('../controller'); -const Api = require('../api'); -const App = require('../main'); - -require('jquery-serializejson'); - -module.exports = Mn.View.extend({ - template: template, - - ui: { - form: 'form', - buttons: 'form button', - ssl_options: '.ssl_options', - ssl: 'input[name="ssl"]', - letsencrypt_email: 'input[name="letsencrypt_email"]', - accept_tos: 'input[name="accept_tos"]' - }, - - events: { - 'change @ui.ssl': function (e) { - let inputs = this.ui.letsencrypt_email.add(this.ui.accept_tos); - if (this.ui.ssl.prop('checked')) { - this.ui.ssl_options.show(); - inputs.prop('required', true); - } else { - this.ui.ssl_options.hide(); - inputs.prop('required', false); - } - }, - - 'submit @ui.form': function (e) { - e.preventDefault(); - let data = _.extend({}, this.ui.form.serializeJSON()); - - // Change text true's to bools - _.map(data, function (val, key) { - if (val === 'true') { - data[key] = true; - } - }); - - // This is a 404 host - data.type = '404'; - - // accept_tos is not required for backend - delete data.accept_tos; - - if (!data.ssl) { - delete data.letsencrypt_email; - } - - this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); - let method = Api.Hosts.create; - - if (this.model.get('_id')) { - // edit - method = Api.Hosts.update; - data._id = this.model.get('_id'); - } - - method(data) - .then((/*result*/) => { - App.UI.closeModal(); - Controller.showDashboard(); - }) - .catch(err => { - alert(err.message); - this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); - }); - } - } -}); diff --git a/manager/src/frontend/js/app/host/advanced.ejs b/manager/src/frontend/js/app/host/advanced.ejs deleted file mode 100644 index 378db25..0000000 --- a/manager/src/frontend/js/app/host/advanced.ejs +++ /dev/null @@ -1,23 +0,0 @@ - diff --git a/manager/src/frontend/js/app/host/advanced.js b/manager/src/frontend/js/app/host/advanced.js deleted file mode 100644 index 76d71c5..0000000 --- a/manager/src/frontend/js/app/host/advanced.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const template = require('./advanced.ejs'); -const Controller = require('../controller'); -const Api = require('../api'); -const App = require('../main'); - -require('jquery-serializejson'); - -module.exports = Mn.View.extend({ - template: template, - - ui: { - form: 'form', - buttons: 'form button' - }, - - events: { - 'submit @ui.form': function (e) { - e.preventDefault(); - let data = this.ui.form.serializeJSON(); - data._id = this.model.get('_id'); - - this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); - - Api.Hosts.update(data) - .then((/*result*/) => { - App.UI.closeModal(); - Controller.showDashboard(); - }) - .catch((err) => { - alert(err.message); - this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); - }); - } - } -}); diff --git a/manager/src/frontend/js/app/host/delete.ejs b/manager/src/frontend/js/app/host/delete.ejs deleted file mode 100644 index e891b1a..0000000 --- a/manager/src/frontend/js/app/host/delete.ejs +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/manager/src/frontend/js/app/host/delete.js b/manager/src/frontend/js/app/host/delete.js deleted file mode 100644 index 8a60231..0000000 --- a/manager/src/frontend/js/app/host/delete.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const template = require('./delete.ejs'); -const Controller = require('../controller'); -const Api = require('../api'); -const App = require('../main'); - -module.exports = Mn.View.extend({ - template: template, - - ui: { - buttons: 'form button', - delete: 'button.delete' - }, - - events: { - 'click @ui.delete': function (e) { - e.preventDefault(); - - this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); - - Api.Hosts.delete(this.model.get('_id')) - .then((/*result*/) => { - App.UI.closeModal(); - Controller.showDashboard(); - }) - .catch(err => { - alert(err.message); - this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); - }); - } - } -}); diff --git a/manager/src/frontend/js/app/host/proxy_form.ejs b/manager/src/frontend/js/app/host/proxy_form.ejs deleted file mode 100644 index f977d41..0000000 --- a/manager/src/frontend/js/app/host/proxy_form.ejs +++ /dev/null @@ -1,84 +0,0 @@ - diff --git a/manager/src/frontend/js/app/host/proxy_form.js b/manager/src/frontend/js/app/host/proxy_form.js deleted file mode 100644 index 7804b10..0000000 --- a/manager/src/frontend/js/app/host/proxy_form.js +++ /dev/null @@ -1,108 +0,0 @@ -'use strict'; - -import Mn from 'backbone.marionette'; - -const _ = require('lodash'); -const template = require('./proxy_form.ejs'); -const Controller = require('../controller'); -const Api = require('../api'); -const App = require('../main'); - -require('jquery-serializejson'); - -module.exports = Mn.View.extend({ - template: template, - - ui: { - form: 'form', - buttons: 'form button', - ssl_options: '.ssl_options', - ssl: 'input[name="ssl"]', - letsencrypt_email: 'input[name="letsencrypt_email"]', - accept_tos: 'input[name="accept_tos"]', - access_list_id: 'select[name="access_list_id"]' - }, - - events: { - 'change @ui.ssl': function (e) { - let inputs = this.ui.letsencrypt_email.add(this.ui.accept_tos); - if (this.ui.ssl.prop('checked')) { - this.ui.ssl_options.show(); - inputs.prop('required', true); - } else { - this.ui.ssl_options.hide(); - inputs.prop('required', false); - } - }, - - 'submit @ui.form': function (e) { - e.preventDefault(); - let data = _.extend({}, this.ui.form.serializeJSON()); - - // Change text true's to bools - _.map(data, function (val, key) { - if (val === 'true') { - data[key] = true; - } - }); - - data.type = 'proxy'; - - // Port is integer - data.forward_port = parseInt(data.forward_port, 10); - - // accept_tos is not required for backend - delete data.accept_tos; - delete data.access_list; - - if (!data.ssl) { - delete data.letsencrypt_email; - delete data.force_ssl; - } - - this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); - let method = Api.Hosts.create; - - if (this.model.get('_id')) { - // edit - method = Api.Hosts.update; - data._id = this.model.get('_id'); - } - - method(data) - .then((/*result*/) => { - App.UI.closeModal(); - Controller.showDashboard(); - }) - .catch((err) => { - alert(err.message); - this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); - }); - } - }, - - onRender: function () { - let view = this; - - Api.Access.getAll() - .then(response => { - if (!view.isDestroyed()) { - view.ui.access_list_id.empty().append($('