diff --git a/src/backend/internal/dead-host.js b/src/backend/internal/dead-host.js index 9c2b8d3f..9ad5b1ff 100644 --- a/src/backend/internal/dead-host.js +++ b/src/backend/internal/dead-host.js @@ -103,7 +103,7 @@ const internalDeadHost = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @return {Promise} */ update: (access, data) => { @@ -201,7 +201,7 @@ const internalDeadHost = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @param {Array} [data.expand] * @param {Array} [data.omit] * @return {Promise} @@ -248,7 +248,7 @@ const internalDeadHost = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @param {String} [data.reason] * @returns {Promise} */ @@ -290,6 +290,104 @@ const internalDeadHost = { }); }, + /** + * @param {Access} access + * @param {Object} data + * @param {Number} data.id + * @param {String} [data.reason] + * @returns {Promise} + */ + enable: (access, data) => { + return access.can('dead_hosts:update', data.id) + .then(() => { + return internalDeadHost.get(access, { + id: data.id, + expand: ['certificate', 'owner'] + }); + }) + .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 deadHostModel + .query() + .where('id', row.id) + .patch({ + enabled: 1 + }) + .then(() => { + // Configure nginx + return internalNginx.configure(deadHostModel, 'dead_host', row); + }) + .then(() => { + // Add to audit log + return internalAuditLog.add(access, { + action: 'enabled', + object_type: 'dead-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('dead_hosts:update', data.id) + .then(() => { + return internalDeadHost.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 deadHostModel + .query() + .where('id', row.id) + .patch({ + enabled: 0 + }) + .then(() => { + // Delete Nginx Config + return internalNginx.deleteConfig('dead_host', row) + .then(() => { + return internalNginx.reload(); + }); + }) + .then(() => { + // Add to audit log + return internalAuditLog.add(access, { + action: 'disabled', + object_type: 'dead-host', + object_id: row.id, + meta: _.omit(row, omissions()) + }); + }); + }) + .then(() => { + return true; + }); + }, + /** * All Hosts * @@ -338,7 +436,7 @@ const internalDeadHost = { /** * Report use * - * @param {Integer} user_id + * @param {Number} user_id * @param {String} visibility * @returns {Promise} */ diff --git a/src/backend/internal/redirection-host.js b/src/backend/internal/redirection-host.js index 57bb9d18..9850426a 100644 --- a/src/backend/internal/redirection-host.js +++ b/src/backend/internal/redirection-host.js @@ -103,7 +103,7 @@ const internalRedirectionHost = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @return {Promise} */ update: (access, data) => { @@ -201,7 +201,7 @@ const internalRedirectionHost = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @param {Array} [data.expand] * @param {Array} [data.omit] * @return {Promise} @@ -248,7 +248,7 @@ const internalRedirectionHost = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @param {String} [data.reason] * @returns {Promise} */ @@ -290,6 +290,104 @@ const internalRedirectionHost = { }); }, + /** + * @param {Access} access + * @param {Object} data + * @param {Number} data.id + * @param {String} [data.reason] + * @returns {Promise} + */ + enable: (access, data) => { + return access.can('redirection_hosts:update', data.id) + .then(() => { + return internalRedirectionHost.get(access, { + id: data.id, + expand: ['certificate', 'owner'] + }); + }) + .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 redirectionHostModel + .query() + .where('id', row.id) + .patch({ + enabled: 1 + }) + .then(() => { + // Configure nginx + return internalNginx.configure(redirectionHostModel, 'redirection_host', row); + }) + .then(() => { + // Add to audit log + return internalAuditLog.add(access, { + action: 'enabled', + object_type: 'redirection-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('redirection_hosts:update', data.id) + .then(() => { + return internalRedirectionHost.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 redirectionHostModel + .query() + .where('id', row.id) + .patch({ + enabled: 0 + }) + .then(() => { + // Delete Nginx Config + return internalNginx.deleteConfig('redirection_host', row) + .then(() => { + return internalNginx.reload(); + }); + }) + .then(() => { + // Add to audit log + return internalAuditLog.add(access, { + action: 'disabled', + object_type: 'redirection-host', + object_id: row.id, + meta: _.omit(row, omissions()) + }); + }); + }) + .then(() => { + return true; + }); + }, + /** * All Hosts * @@ -338,7 +436,7 @@ const internalRedirectionHost = { /** * Report use * - * @param {Integer} user_id + * @param {Number} user_id * @param {String} visibility * @returns {Promise} */ diff --git a/src/backend/internal/stream.js b/src/backend/internal/stream.js index b47b9fa6..bb90bd87 100644 --- a/src/backend/internal/stream.js +++ b/src/backend/internal/stream.js @@ -56,7 +56,7 @@ const internalStream = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @return {Promise} */ update: (access, data) => { @@ -75,6 +75,12 @@ const internalStream = { .query() .omit(omissions()) .patchAndFetchById(row.id, data) + .then(saved_row => { + return internalNginx.configure(streamModel, 'stream', saved_row) + .then(() => { + return internalStream.get(access, {id: row.id, expand: ['owner']}); + }); + }) .then(saved_row => { // Add to audit log return internalAuditLog.add(access, { @@ -93,7 +99,7 @@ const internalStream = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @param {Array} [data.expand] * @param {Array} [data.omit] * @return {Promise} @@ -139,7 +145,7 @@ const internalStream = { /** * @param {Access} access * @param {Object} data - * @param {Integer} data.id + * @param {Number} data.id * @param {String} [data.reason] * @returns {Promise} */ @@ -181,6 +187,104 @@ const internalStream = { }); }, + /** + * @param {Access} access + * @param {Object} data + * @param {Number} data.id + * @param {String} [data.reason] + * @returns {Promise} + */ + enable: (access, data) => { + return access.can('streams:update', data.id) + .then(() => { + return internalStream.get(access, { + id: data.id, + expand: ['owner'] + }); + }) + .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 streamModel + .query() + .where('id', row.id) + .patch({ + enabled: 1 + }) + .then(() => { + // Configure nginx + return internalNginx.configure(streamModel, 'stream', row); + }) + .then(() => { + // Add to audit log + return internalAuditLog.add(access, { + action: 'enabled', + object_type: 'stream', + 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('streams:update', data.id) + .then(() => { + return internalStream.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 streamModel + .query() + .where('id', row.id) + .patch({ + enabled: 0 + }) + .then(() => { + // Delete Nginx Config + return internalNginx.deleteConfig('stream', row) + .then(() => { + return internalNginx.reload(); + }); + }) + .then(() => { + // Add to audit log + return internalAuditLog.add(access, { + action: 'disabled', + object_type: 'stream-host', + object_id: row.id, + meta: _.omit(row, omissions()) + }); + }); + }) + .then(() => { + return true; + }); + }, + /** * All Streams * @@ -222,7 +326,7 @@ const internalStream = { /** * Report use * - * @param {Integer} user_id + * @param {Number} user_id * @param {String} visibility * @returns {Promise} */ diff --git a/src/backend/routes/api/nginx/access_lists.js b/src/backend/routes/api/nginx/access_lists.js index 79bce0ef..46883887 100644 --- a/src/backend/routes/api/nginx/access_lists.js +++ b/src/backend/routes/api/nginx/access_lists.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/access-lists @@ -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/access-lists/123 diff --git a/src/backend/routes/api/nginx/certificates.js b/src/backend/routes/api/nginx/certificates.js index 73241b85..04fafdf7 100644 --- a/src/backend/routes/api/nginx/certificates.js +++ b/src/backend/routes/api/nginx/certificates.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/certificates @@ -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/certificates/123 @@ -157,7 +157,7 @@ router .options((req, res) => { res.sendStatus(204); }) - .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes + .all(jwtdecode()) /** * POST /api/nginx/certificates/123/upload @@ -191,7 +191,7 @@ router .options((req, res) => { res.sendStatus(204); }) - .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes + .all(jwtdecode()) /** * POST /api/nginx/certificates/validate diff --git a/src/backend/routes/api/nginx/dead_hosts.js b/src/backend/routes/api/nginx/dead_hosts.js index 01015302..5e7a367e 100644 --- a/src/backend/routes/api/nginx/dead_hosts.js +++ b/src/backend/routes/api/nginx/dead_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/dead-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/dead-hosts/123 @@ -147,4 +147,52 @@ router .catch(next); }); +/** + * Enable dead-host + * + * /api/nginx/dead-hosts/123/enable + */ +router + .route('/:host_id/enable') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + + /** + * POST /api/nginx/dead-hosts/123/enable + */ + .post((req, res, next) => { + internalDeadHost.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)}) + .then(result => { + res.status(200) + .send(result); + }) + .catch(next); + }); + +/** + * Disable dead-host + * + * /api/nginx/dead-hosts/123/disable + */ +router + .route('/:host_id/disable') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + + /** + * POST /api/nginx/dead-hosts/123/disable + */ + .post((req, res, next) => { + internalDeadHost.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/routes/api/nginx/redirection_hosts.js b/src/backend/routes/api/nginx/redirection_hosts.js index acd5a67e..501d5601 100644 --- a/src/backend/routes/api/nginx/redirection_hosts.js +++ b/src/backend/routes/api/nginx/redirection_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/redirection-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/redirection-hosts/123 @@ -147,4 +147,52 @@ router .catch(next); }); +/** + * Enable redirection-host + * + * /api/nginx/redirection-hosts/123/enable + */ +router + .route('/:host_id/enable') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + + /** + * POST /api/nginx/redirection-hosts/123/enable + */ + .post((req, res, next) => { + internalRedirectionHost.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)}) + .then(result => { + res.status(200) + .send(result); + }) + .catch(next); + }); + +/** + * Disable redirection-host + * + * /api/nginx/redirection-hosts/123/disable + */ +router + .route('/:host_id/disable') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + + /** + * POST /api/nginx/redirection-hosts/123/disable + */ + .post((req, res, next) => { + internalRedirectionHost.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/routes/api/nginx/streams.js b/src/backend/routes/api/nginx/streams.js index 80f4c9fd..857f325c 100644 --- a/src/backend/routes/api/nginx/streams.js +++ b/src/backend/routes/api/nginx/streams.js @@ -147,4 +147,52 @@ router .catch(next); }); +/** + * Enable stream + * + * /api/nginx/streams/123/enable + */ +router + .route('/:host_id/enable') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + + /** + * POST /api/nginx/streams/123/enable + */ + .post((req, res, next) => { + internalStream.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)}) + .then(result => { + res.status(200) + .send(result); + }) + .catch(next); + }); + +/** + * Disable stream + * + * /api/nginx/streams/123/disable + */ +router + .route('/:host_id/disable') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + + /** + * POST /api/nginx/streams/123/disable + */ + .post((req, res, next) => { + internalStream.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/routes/api/users.js b/src/backend/routes/api/users.js index b7ab5e62..f4495512 100644 --- a/src/backend/routes/api/users.js +++ b/src/backend/routes/api/users.js @@ -21,7 +21,7 @@ router .options((req, res) => { res.sendStatus(204); }) - .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes + .all(jwtdecode()) /** * GET /api/users @@ -80,7 +80,7 @@ router .options((req, res) => { res.sendStatus(204); }) - .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes + .all(jwtdecode()) .all(userIdFromMe) /** @@ -160,7 +160,7 @@ router .options((req, res) => { res.sendStatus(204); }) - .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes + .all(jwtdecode()) .all(userIdFromMe) /** @@ -191,7 +191,7 @@ router .options((req, res) => { res.sendStatus(204); }) - .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes + .all(jwtdecode()) .all(userIdFromMe) /** @@ -222,7 +222,7 @@ router .options((req, res) => { res.sendStatus(204); }) - .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes + .all(jwtdecode()) /** * POST /api/users/123/login diff --git a/src/backend/schema/endpoints/dead-hosts.json b/src/backend/schema/endpoints/dead-hosts.json index 641c0063..0fb4d17c 100644 --- a/src/backend/schema/endpoints/dead-hosts.json +++ b/src/backend/schema/endpoints/dead-hosts.json @@ -30,6 +30,9 @@ "advanced_config": { "type": "string" }, + "enabled": { + "$ref": "../definitions.json#/definitions/enabled" + }, "meta": { "type": "object" } @@ -59,6 +62,9 @@ "advanced_config": { "$ref": "#/definitions/advanced_config" }, + "enabled": { + "$ref": "#/definitions/enabled" + }, "meta": { "$ref": "#/definitions/meta" } @@ -177,6 +183,34 @@ "targetSchema": { "type": "boolean" } + }, + { + "title": "Enable", + "description": "Enables a existing 404 Host", + "href": "/nginx/dead-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 404 Host", + "href": "/nginx/dead-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/schema/endpoints/redirection-hosts.json b/src/backend/schema/endpoints/redirection-hosts.json index 724deaec..804ab9dc 100644 --- a/src/backend/schema/endpoints/redirection-hosts.json +++ b/src/backend/schema/endpoints/redirection-hosts.json @@ -41,6 +41,9 @@ "advanced_config": { "type": "string" }, + "enabled": { + "$ref": "../definitions.json#/definitions/enabled" + }, "meta": { "type": "object" } @@ -79,6 +82,9 @@ "advanced_config": { "$ref": "#/definitions/advanced_config" }, + "enabled": { + "$ref": "#/definitions/enabled" + }, "meta": { "$ref": "#/definitions/meta" } @@ -216,6 +222,34 @@ "targetSchema": { "type": "boolean" } + }, + { + "title": "Enable", + "description": "Enables a existing Redirection Host", + "href": "/nginx/redirection-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 Redirection Host", + "href": "/nginx/redirection-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/schema/endpoints/streams.json b/src/backend/schema/endpoints/streams.json index e8535a31..e93e1ff3 100644 --- a/src/backend/schema/endpoints/streams.json +++ b/src/backend/schema/endpoints/streams.json @@ -35,6 +35,9 @@ "udp_forwarding": { "type": "boolean" }, + "enabled": { + "$ref": "../definitions.json#/definitions/enabled" + }, "meta": { "type": "object" } @@ -64,6 +67,9 @@ "udp_forwarding": { "$ref": "#/definitions/udp_forwarding" }, + "enabled": { + "$ref": "#/definitions/enabled" + }, "meta": { "$ref": "#/definitions/meta" } @@ -184,6 +190,34 @@ "targetSchema": { "type": "boolean" } + }, + { + "title": "Enable", + "description": "Enables a existing Stream", + "href": "/nginx/streams/{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 Stream", + "href": "/nginx/streams/{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/dead_host.conf b/src/backend/templates/dead_host.conf index 8b807958..d80536d3 100644 --- a/src/backend/templates/dead_host.conf +++ b/src/backend/templates/dead_host.conf @@ -1,5 +1,6 @@ {% include "_header_comment.conf" %} +{% if enabled %} server { {% include "_listen.conf" %} {% include "_certificates.conf" %} @@ -10,3 +11,4 @@ server { return 404; } +{% endif %} diff --git a/src/backend/templates/redirection_host.conf b/src/backend/templates/redirection_host.conf index 9d51a920..f405a099 100644 --- a/src/backend/templates/redirection_host.conf +++ b/src/backend/templates/redirection_host.conf @@ -1,5 +1,6 @@ {% include "_header_comment.conf" %} +{% if enabled %} server { {% include "_listen.conf" %} {% include "_certificates.conf" %} @@ -22,3 +23,4 @@ server { {% endif %} } } +{% endif %} diff --git a/src/backend/templates/stream.conf b/src/backend/templates/stream.conf index 9bcd76de..53356cfd 100644 --- a/src/backend/templates/stream.conf +++ b/src/backend/templates/stream.conf @@ -2,6 +2,7 @@ # {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }} # ------------------------------------------------------------ +{% if enabled %} {% if tcp_forwarding == 1 or tcp_forwarding == true -%} server { listen {{ incoming_port }}; @@ -14,3 +15,4 @@ server { proxy_pass {{ forward_ip }}:{{ forwarding_port }}; } {% endif %} +{% endif %} \ No newline at end of file diff --git a/src/frontend/js/app/api.js b/src/frontend/js/app/api.js index 2da64149..cc3b5ce6 100644 --- a/src/frontend/js/app/api.js +++ b/src/frontend/js/app/api.js @@ -386,6 +386,14 @@ module.exports = { return fetch('delete', 'nginx/redirection-hosts/' + id); }, + /** + * @param {Number} id + * @returns {Promise} + */ + get: function (id) { + return fetch('get', 'nginx/redirection-hosts/' + id); + }, + /** * @param {Number} id * @param {FormData} form_data @@ -448,6 +456,14 @@ module.exports = { return fetch('delete', 'nginx/streams/' + id); }, + /** + * @param {Number} id + * @returns {Promise} + */ + get: function (id) { + return fetch('get', 'nginx/streams/' + id); + }, + /** * @param {Number} id * @returns {Promise} @@ -501,6 +517,14 @@ module.exports = { return fetch('delete', 'nginx/dead-hosts/' + id); }, + /** + * @param {Number} id + * @returns {Promise} + */ + get: function (id) { + return fetch('get', 'nginx/dead-hosts/' + id); + }, + /** * @param {Number} id * @param {FormData} form_data diff --git a/src/frontend/js/app/nginx/dead/list/item.ejs b/src/frontend/js/app/nginx/dead/list/item.ejs index f411aacb..f975da58 100644 --- a/src/frontend/js/app/nginx/dead/list/item.ejs +++ b/src/frontend/js/app/nginx/dead/list/item.ejs @@ -28,7 +28,9 @@