diff --git a/src/backend/internal/proxy-host.js b/src/backend/internal/proxy-host.js index 1946427..5eabdeb 100644 --- a/src/backend/internal/proxy-host.js +++ b/src/backend/internal/proxy-host.js @@ -104,7 +104,7 @@ const internalProxyHost = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @return {Promise} */ update: (access, data) => { @@ -192,7 +192,7 @@ const internalProxyHost = { return internalNginx.configure(proxyHostModel, 'proxy_host', row) .then(new_meta => { row.meta = new_meta; - row = internalHost.cleanRowCertificateMeta(row); + row = internalHost.cleanRowCertificateMeta(row); return _.omit(row, omissions()); }); }); @@ -202,7 +202,7 @@ const internalProxyHost = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @param {Array} [data.expand] * @param {Array} [data.omit] * @return {Promise} @@ -249,7 +249,7 @@ const internalProxyHost = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @param {String} [data.reason] * @returns {Promise} */ @@ -291,6 +291,101 @@ const internalProxyHost = { }); }, + /** + * @param {Access} access + * @param {Object} data + * @param {Number} data.id + * @param {String} [data.reason] + * @returns {Promise} + */ + enable: (access, data) => { + return access.can('proxy_hosts:update', data.id) + .then(() => { + return internalProxyHost.get(access, {id: data.id}); + }) + .then(row => { + if (!row) { + throw new error.ItemNotFoundError(data.id); + } else if (row.enabled) { + throw new error.ValidationError('Host is already enabled'); + } + + row.enabled = 1; + + return proxyHostModel + .query() + .where('id', row.id) + .patch({ + enabled: 1 + }) + .then(() => { + // Configure nginx + return internalNginx.configure(proxyHostModel, 'proxy_host', row); + }) + .then(() => { + // Add to audit log + return internalAuditLog.add(access, { + action: 'enabled', + object_type: 'proxy-host', + object_id: row.id, + meta: _.omit(row, omissions()) + }); + }); + }) + .then(() => { + return true; + }); + }, + + /** + * @param {Access} access + * @param {Object} data + * @param {Number} data.id + * @param {String} [data.reason] + * @returns {Promise} + */ + disable: (access, data) => { + return access.can('proxy_hosts:update', data.id) + .then(() => { + return internalProxyHost.get(access, {id: data.id}); + }) + .then(row => { + if (!row) { + throw new error.ItemNotFoundError(data.id); + } else if (!row.enabled) { + throw new error.ValidationError('Host is already disabled'); + } + + row.enabled = 0; + + return proxyHostModel + .query() + .where('id', row.id) + .patch({ + enabled: 0 + }) + .then(() => { + // Delete Nginx Config + return internalNginx.deleteConfig('proxy_host', row) + .then(() => { + return internalNginx.reload(); + }); + }) + .then(() => { + // Add to audit log + return internalAuditLog.add(access, { + action: 'disabled', + object_type: 'proxy-host', + object_id: row.id, + meta: _.omit(row, omissions()) + }); + }); + }) + .then(() => { + return true; + }); + }, + /** * All Hosts * @@ -339,7 +434,7 @@ const internalProxyHost = { /** * Report use * - * @param {Integer} user_id + * @param {Number} user_id * @param {String} visibility * @returns {Promise} */ diff --git a/src/backend/migrations/20190104035154_disabled.js b/src/backend/migrations/20190104035154_disabled.js new file mode 100644 index 0000000..308e219 --- /dev/null +++ b/src/backend/migrations/20190104035154_disabled.js @@ -0,0 +1,57 @@ +'use strict'; + +const migrate_name = 'disabled'; +const logger = require('../logger').migrate; + +/** + * Migrate + * + * @see http://knexjs.org/#Schema + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.up = function (knex/*, Promise*/) { + logger.info('[' + migrate_name + '] Migrating Up...'); + + return knex.schema.table('proxy_host', function (proxy_host) { + proxy_host.integer('enabled').notNull().unsigned().defaultTo(1); + }) + .then(() => { + logger.info('[' + migrate_name + '] proxy_host Table altered'); + + return knex.schema.table('redirection_host', function (redirection_host) { + redirection_host.integer('enabled').notNull().unsigned().defaultTo(1); + }); + }) + .then(() => { + logger.info('[' + migrate_name + '] redirection_host Table altered'); + + return knex.schema.table('dead_host', function (dead_host) { + dead_host.integer('enabled').notNull().unsigned().defaultTo(1); + }); + }) + .then(() => { + logger.info('[' + migrate_name + '] dead_host Table altered'); + + return knex.schema.table('stream', function (stream) { + stream.integer('enabled').notNull().unsigned().defaultTo(1); + }); + }) + .then(() => { + logger.info('[' + migrate_name + '] stream Table altered'); + }); +}; + +/** + * Undo Migrate + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.down = function (knex, Promise) { + logger.warn('[' + migrate_name + '] You can\'t migrate down this one.'); + return Promise.resolve(true); +}; diff --git a/src/backend/routes/api/nginx/proxy_hosts.js b/src/backend/routes/api/nginx/proxy_hosts.js index ad69f00..718f135 100644 --- a/src/backend/routes/api/nginx/proxy_hosts.js +++ b/src/backend/routes/api/nginx/proxy_hosts.js @@ -20,7 +20,7 @@ router .options((req, res) => { res.sendStatus(204); }) - .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes + .all(jwtdecode()) /** * GET /api/nginx/proxy-hosts @@ -79,7 +79,7 @@ router .options((req, res) => { res.sendStatus(204); }) - .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes + .all(jwtdecode()) /** * GET /api/nginx/proxy-hosts/123 @@ -147,4 +147,52 @@ router .catch(next); }); +/** + * Enable proxy-host + * + * /api/nginx/proxy-hosts/123/enable + */ +router + .route('/:host_id/enable') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + + /** + * POST /api/nginx/proxy-hosts/123/enable + */ + .post((req, res, next) => { + internalProxyHost.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)}) + .then(result => { + res.status(200) + .send(result); + }) + .catch(next); + }); + +/** + * Disable proxy-host + * + * /api/nginx/proxy-hosts/123/disable + */ +router + .route('/:host_id/disable') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + + /** + * POST /api/nginx/proxy-hosts/123/disable + */ + .post((req, res, next) => { + internalProxyHost.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)}) + .then(result => { + res.status(200) + .send(result); + }) + .catch(next); + }); + module.exports = router; diff --git a/src/backend/schema/definitions.json b/src/backend/schema/definitions.json index 8320b3d..6654811 100644 --- a/src/backend/schema/definitions.json +++ b/src/backend/schema/definitions.json @@ -172,6 +172,11 @@ "pattern": "^(?:\\*\\.)?(?:[^.*]+\\.?)+[^.]$" } }, + "enabled": { + "description": "Is Enabled", + "example": true, + "type": "boolean" + }, "ssl_enabled": { "description": "Is SSL Enabled", "example": true, diff --git a/src/backend/schema/endpoints/proxy-hosts.json b/src/backend/schema/endpoints/proxy-hosts.json index ae8a1a5..9e033da 100644 --- a/src/backend/schema/endpoints/proxy-hosts.json +++ b/src/backend/schema/endpoints/proxy-hosts.json @@ -58,6 +58,9 @@ "advanced_config": { "type": "string" }, + "enabled": { + "$ref": "../definitions.json#/definitions/enabled" + }, "meta": { "type": "object" } @@ -108,6 +111,9 @@ "advanced_config": { "$ref": "#/definitions/advanced_config" }, + "enabled": { + "$ref": "#/definitions/enabled" + }, "meta": { "$ref": "#/definitions/meta" } @@ -186,6 +192,9 @@ "advanced_config": { "$ref": "#/definitions/advanced_config" }, + "enabled": { + "$ref": "#/definitions/enabled" + }, "meta": { "$ref": "#/definitions/meta" } @@ -247,6 +256,9 @@ "advanced_config": { "$ref": "#/definitions/advanced_config" }, + "enabled": { + "$ref": "#/definitions/enabled" + }, "meta": { "$ref": "#/definitions/meta" } @@ -271,6 +283,34 @@ "targetSchema": { "type": "boolean" } + }, + { + "title": "Enable", + "description": "Enables a existing Proxy Host", + "href": "/nginx/proxy-hosts/{definitions.identity.example}/enable", + "access": "private", + "method": "POST", + "rel": "update", + "http_header": { + "$ref": "../examples.json#/definitions/auth_header" + }, + "targetSchema": { + "type": "boolean" + } + }, + { + "title": "Disable", + "description": "Disables a existing Proxy Host", + "href": "/nginx/proxy-hosts/{definitions.identity.example}/disable", + "access": "private", + "method": "POST", + "rel": "update", + "http_header": { + "$ref": "../examples.json#/definitions/auth_header" + }, + "targetSchema": { + "type": "boolean" + } } ] } diff --git a/src/backend/templates/proxy_host.conf b/src/backend/templates/proxy_host.conf index af89834..3f3b80b 100644 --- a/src/backend/templates/proxy_host.conf +++ b/src/backend/templates/proxy_host.conf @@ -1,5 +1,6 @@ {% include "_header_comment.conf" %} +{% if enabled %} server { set $forward_scheme {{ forward_scheme }}; set $server "{{ forward_host }}"; @@ -33,3 +34,4 @@ server { include conf.d/include/proxy.conf; } } +{% endif %} diff --git a/src/frontend/js/app/api.js b/src/frontend/js/app/api.js index 76ec5c9..2da6414 100644 --- a/src/frontend/js/app/api.js +++ b/src/frontend/js/app/api.js @@ -7,7 +7,7 @@ const Tokens = require('./tokens'); /** * @param {String} message * @param {*} debug - * @param {Integer} code + * @param {Number} code * @constructor */ const ApiError = function (message, debug, code) { @@ -129,7 +129,7 @@ function getAllObjects (path, expand, query) { } /** - * @param {String} path + * @param {String} path * @param {FormData} form_data * @returns {Promise} */ @@ -241,7 +241,7 @@ module.exports = { /** * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @returns {Promise} */ update: function (data) { @@ -251,7 +251,7 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @returns {Promise} */ delete: function (id) { @@ -260,7 +260,7 @@ module.exports = { /** * - * @param {Integer} id + * @param {Number} id * @param {Object} auth * @returns {Promise} */ @@ -269,7 +269,7 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @returns {Promise} */ loginAs: function (id) { @@ -278,7 +278,7 @@ module.exports = { /** * - * @param {Integer} id + * @param {Number} id * @param {Object} perms * @returns {Promise} */ @@ -308,7 +308,7 @@ module.exports = { /** * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @returns {Promise} */ update: function (data) { @@ -318,11 +318,35 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @returns {Promise} */ delete: function (id) { return fetch('delete', 'nginx/proxy-hosts/' + id); + }, + + /** + * @param {Number} id + * @returns {Promise} + */ + get: function (id) { + return fetch('get', 'nginx/proxy-hosts/' + id); + }, + + /** + * @param {Number} id + * @returns {Promise} + */ + enable: function (id) { + return fetch('post', 'nginx/proxy-hosts/' + id + '/enable'); + }, + + /** + * @param {Number} id + * @returns {Promise} + */ + disable: function (id) { + return fetch('post', 'nginx/proxy-hosts/' + id + '/disable'); } }, @@ -345,7 +369,7 @@ module.exports = { /** * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @returns {Promise} */ update: function (data) { @@ -355,7 +379,7 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @returns {Promise} */ delete: function (id) { @@ -363,12 +387,28 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @param {FormData} form_data * @params {Promise} */ setCerts: function (id, form_data) { return FileUpload('nginx/redirection-hosts/' + id + '/certificates', form_data); + }, + + /** + * @param {Number} id + * @returns {Promise} + */ + enable: function (id) { + return fetch('post', 'nginx/redirection-hosts/' + id + '/enable'); + }, + + /** + * @param {Number} id + * @returns {Promise} + */ + disable: function (id) { + return fetch('post', 'nginx/redirection-hosts/' + id + '/disable'); } }, @@ -391,7 +431,7 @@ module.exports = { /** * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @returns {Promise} */ update: function (data) { @@ -401,11 +441,27 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @returns {Promise} */ delete: function (id) { return fetch('delete', 'nginx/streams/' + id); + }, + + /** + * @param {Number} id + * @returns {Promise} + */ + enable: function (id) { + return fetch('post', 'nginx/streams/' + id + '/enable'); + }, + + /** + * @param {Number} id + * @returns {Promise} + */ + disable: function (id) { + return fetch('post', 'nginx/streams/' + id + '/disable'); } }, @@ -428,7 +484,7 @@ module.exports = { /** * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @returns {Promise} */ update: function (data) { @@ -438,7 +494,7 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @returns {Promise} */ delete: function (id) { @@ -446,12 +502,28 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @param {FormData} form_data * @params {Promise} */ setCerts: function (id, form_data) { return FileUpload('nginx/dead-hosts/' + id + '/certificates', form_data); + }, + + /** + * @param {Number} id + * @returns {Promise} + */ + enable: function (id) { + return fetch('post', 'nginx/dead-hosts/' + id + '/enable'); + }, + + /** + * @param {Number} id + * @returns {Promise} + */ + disable: function (id) { + return fetch('post', 'nginx/dead-hosts/' + id + '/disable'); } }, @@ -474,7 +546,7 @@ module.exports = { /** * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @returns {Promise} */ update: function (data) { @@ -484,7 +556,7 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @returns {Promise} */ delete: function (id) { @@ -511,7 +583,7 @@ module.exports = { /** * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @returns {Promise} */ update: function (data) { @@ -521,7 +593,7 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @returns {Promise} */ delete: function (id) { @@ -529,7 +601,7 @@ module.exports = { }, /** - * @param {Integer} id + * @param {Number} id * @param {FormData} form_data * @params {Promise} */ diff --git a/src/frontend/js/app/nginx/proxy/list/item.ejs b/src/frontend/js/app/nginx/proxy/list/item.ejs index d91a598..b1ce044 100644 --- a/src/frontend/js/app/nginx/proxy/list/item.ejs +++ b/src/frontend/js/app/nginx/proxy/list/item.ejs @@ -34,7 +34,9 @@