Added support for redirection and 404 hosts
This commit is contained in:
parent
61820840e0
commit
64de096565
14
README.md
14
README.md
@ -2,13 +2,13 @@
|
||||
|
||||
# Nginx Proxy Manager
|
||||
|
||||
![Version](https://img.shields.io/badge/version-1.0.0-green.svg)
|
||||
![Version](https://img.shields.io/badge/version-1.0.1-green.svg)
|
||||
![Stars](https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg)
|
||||
![Pulls](https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg)
|
||||
|
||||
![Build Status](http://bamboo.jc21.com/plugins/servlet/wittified/build-status/AB-NPM)
|
||||
|
||||
This NPM comes as a pre-built docker image that enables you to easily forward to your websites
|
||||
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
||||
running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
|
||||
|
||||
|
||||
@ -19,6 +19,10 @@ running at home or otherwise, including free SSL, without having to know too muc
|
||||
- Secure your sites with SSL and optionally force SSL
|
||||
- Secure your sites with Basic HTTP Authentication Access Lists
|
||||
- Advanced Nginx config option for super users
|
||||
- 3 domain uses:
|
||||
- Proxy requests to upstream server
|
||||
- Redirect requests to another domain
|
||||
- Return immediate 404's
|
||||
|
||||
|
||||
## Getting started
|
||||
@ -84,7 +88,7 @@ I won't go in to too much detail here but here are the basics for someone new to
|
||||
1. Your home router will have a Port Forwarding section somewhere. Log in and find it
|
||||
2. Add port forwarding for port 80 and 443 to the server hosting this project
|
||||
3. Configure your domain name details to point to your home, either with a static ip or a service like DuckDNS
|
||||
4. Use the NPM here as your gateway to forward to your other web based services
|
||||
4. Use the Nginx Proxy Manager here as your gateway to forward to your other web based services
|
||||
|
||||
|
||||
## Screenshots
|
||||
@ -98,8 +102,8 @@ I won't go in to too much detail here but here are the basics for someone new to
|
||||
|
||||
- Pass on human readable ssl cert errors to the ui
|
||||
- Allow a host to be a redirection to another domain
|
||||
- Allow a host to return immediate 404's
|
||||
- UI: Allow column sorting on tables
|
||||
- UI: Allow filtering hosts by types
|
||||
- Advanced option to overwrite the default location block (or regex to do it automatically)
|
||||
- Change the renew ssl process to use the letsencrypt renew procedure so as to avoid rate limits
|
||||
- Add nice upstream error pages
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nginx-proxy-manager",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Nginx proxt with built in Web based management",
|
||||
"main": "src/backend/index.js",
|
||||
"dependencies": {
|
||||
|
@ -155,15 +155,14 @@ const internalHost = {
|
||||
*
|
||||
* @param {Object} host
|
||||
* @param {Boolean} [reload_nginx]
|
||||
* @param {Boolean} [force_ssl_renew]
|
||||
* @returns {Promise}
|
||||
*/
|
||||
configure: (host, reload_nginx, force_ssl_renew) => {
|
||||
configure: (host, reload_nginx) => {
|
||||
return new Promise((resolve/*, reject*/) => {
|
||||
resolve(internalNginx.deleteConfig(host));
|
||||
})
|
||||
.then(() => {
|
||||
if (host.ssl && (force_ssl_renew || !internalSsl.hasValidSslCerts(host))) {
|
||||
if (host.ssl && !internalSsl.hasValidSslCerts(host)) {
|
||||
return internalSsl.configureSsl(host);
|
||||
}
|
||||
})
|
||||
@ -248,7 +247,7 @@ const internalHost = {
|
||||
reject(new error.ValidationError('Host does not have SSL enabled'));
|
||||
} else {
|
||||
// 3. Fire the ssl and config generation for this host, forcing ssl
|
||||
internalHost.configure(host, true, true)
|
||||
internalSsl.renewSsl(host)
|
||||
.then((/*result*/) => {
|
||||
resolve(host);
|
||||
})
|
||||
|
@ -45,7 +45,11 @@ const internalNginx = {
|
||||
let filename = internalNginx.getConfigName(host);
|
||||
|
||||
try {
|
||||
template = fs.readFileSync(__dirname + '/../templates/host.conf.ejs', {encoding: 'utf8'});
|
||||
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);
|
||||
|
@ -10,6 +10,10 @@
|
||||
"type": "string",
|
||||
"readonly": true
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"pattern": "^(proxy|redirection|404)$"
|
||||
},
|
||||
"hostname": {
|
||||
"$ref": "../definitions.json#/definitions/hostname"
|
||||
},
|
||||
@ -17,6 +21,9 @@
|
||||
"type": "string",
|
||||
"format": "ipv4"
|
||||
},
|
||||
"forward_host": {
|
||||
"type": "string"
|
||||
},
|
||||
"forward_port": {
|
||||
"type": "integer",
|
||||
"minumum": 1,
|
||||
@ -79,14 +86,19 @@
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"hostname",
|
||||
"forward_server",
|
||||
"forward_port"
|
||||
"type",
|
||||
"hostname"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"$ref": "#/definitions/type"
|
||||
},
|
||||
"hostname": {
|
||||
"$ref": "#/definitions/hostname"
|
||||
},
|
||||
"forward_host": {
|
||||
"$ref": "#/definitions/forward_host"
|
||||
},
|
||||
"forward_server": {
|
||||
"$ref": "#/definitions/forward_server"
|
||||
},
|
||||
@ -137,6 +149,9 @@
|
||||
"hostname": {
|
||||
"$ref": "#/definitions/hostname"
|
||||
},
|
||||
"forward_host": {
|
||||
"$ref": "#/definitions/forward_host"
|
||||
},
|
||||
"forward_server": {
|
||||
"$ref": "#/definitions/forward_server"
|
||||
},
|
||||
@ -188,9 +203,15 @@
|
||||
"_id": {
|
||||
"$ref": "#/definitions/_id"
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/definitions/type"
|
||||
},
|
||||
"hostname": {
|
||||
"$ref": "#/definitions/hostname"
|
||||
},
|
||||
"forward_host": {
|
||||
"$ref": "#/definitions/forward_host"
|
||||
},
|
||||
"forward_server": {
|
||||
"$ref": "#/definitions/forward_server"
|
||||
},
|
||||
|
19
manager/src/backend/templates/404.conf.ejs
Normal file
19
manager/src/backend/templates/404.conf.ejs
Normal file
@ -0,0 +1,19 @@
|
||||
# <%- 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;
|
||||
}
|
22
manager/src/backend/templates/redirection.conf.ejs
Normal file
22
manager/src/backend/templates/redirection.conf.ejs
Normal file
@ -0,0 +1,22 @@
|
||||
# <%- 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;
|
||||
}
|
@ -54,12 +54,34 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Show Host Form
|
||||
* Show Proxy Host Form
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
showHostForm: function (model) {
|
||||
require(['./main', './host/form'], function (App, View) {
|
||||
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}));
|
||||
});
|
||||
},
|
||||
|
@ -1,5 +1,9 @@
|
||||
<td colspan="10" class="text-center">
|
||||
<br><br>
|
||||
<p>It looks like there are no hosts configured.</p>
|
||||
<p><button type="button" class="btn btn-sm btn-success">Create your first Host</button></p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-sm btn-success proxy">Create Proxy Host</button>
|
||||
<button type="button" class="btn btn-sm btn-success redirection">Create Redirection Host</button>
|
||||
<button type="button" class="btn btn-sm btn-success 404">Create 404 Host</button>
|
||||
</p>
|
||||
</td>
|
||||
|
@ -11,13 +11,25 @@ module.exports = Mn.View.extend({
|
||||
tagName: 'tr',
|
||||
|
||||
ui: {
|
||||
create: 'button'
|
||||
proxy: 'button.proxy',
|
||||
redirection: 'button.redirection',
|
||||
'404': 'button.404'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click @ui.create': function (e) {
|
||||
'click @ui.proxy': function (e) {
|
||||
e.preventDefault();
|
||||
Controller.showHostForm(new HostModel.Model);
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,10 +1,21 @@
|
||||
<table class="table table-condensed table-striped">
|
||||
<thead>
|
||||
<th>Hostname</th>
|
||||
<th>Forward</th>
|
||||
<th>Destination</th>
|
||||
<th>SSL</th>
|
||||
<th>Access List</th>
|
||||
<th class="text-right"><button type="button" class="btn btn-xs btn-info">Create Host</button></th>
|
||||
<th class="text-right">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-xs btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Create Host <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#" class="new-proxy">Proxy Host</a></li>
|
||||
<li><a href="#" class="new-redirection">Redirection Host</a></li>
|
||||
<li><a href="#" class="new-404">404 Host</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- items -->
|
||||
|
@ -26,13 +26,25 @@ module.exports = Mn.View.extend({
|
||||
},
|
||||
|
||||
ui: {
|
||||
'create': 'th button'
|
||||
new_proxy: 'th .new-proxy',
|
||||
new_redirection: 'th .new-redirection',
|
||||
new_404: 'th .new-404'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click @ui.create': function (e) {
|
||||
'click @ui.new_proxy': function (e) {
|
||||
e.preventDefault();
|
||||
Controller.showHostForm(new HostModel.Model);
|
||||
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);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1,5 +1,15 @@
|
||||
<td><a href="<%- ssl ? 'https' : 'http' %>://<%- hostname %>" target="_blank"><%- hostname %></a></td>
|
||||
<td><span class="monospace"><%- forward_server %>:<%- forward_port %></span></td>
|
||||
<td>
|
||||
<span class="monospace">
|
||||
<% if (type === 'proxy') { %>
|
||||
<%- forward_server %>:<%- forward_port %>
|
||||
<% } else if (type === 'redirection') { %>
|
||||
<%- forward_host %>
|
||||
<% } else if (type === '404') { %>
|
||||
404
|
||||
<% } %>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<% if (ssl && force_ssl) { %>
|
||||
Forced
|
||||
|
@ -22,7 +22,17 @@ module.exports = Mn.View.extend({
|
||||
events: {
|
||||
'click @ui.edit': function (e) {
|
||||
e.preventDefault();
|
||||
Controller.showHostForm(this.model);
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
'click @ui.delete': function (e) {
|
||||
|
50
manager/src/frontend/js/app/host/404_form.ejs
Normal file
50
manager/src/frontend/js/app/host/404_form.ejs
Normal file
@ -0,0 +1,50 @@
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-header text-left">
|
||||
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> 404 Host</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>A 404 host will simply return a 404 not found page for any hits to any path on the domain.</p>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">Hostname</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" placeholder="myhost.example.com" name="hostname" value="<%- hostname %>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-4 col-sm-8">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="ssl" value="true"<%- ssl ? ' checked' : '' %>> Enable SSL with Letsencrypt
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ssl_options"<%= ssl ? '' : ' style="display: none;"' %>>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">Letsencrypt Email</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="email" class="form-control" placeholder="" name="letsencrypt_email" value="<%- letsencrypt_email %>"<%- ssl ? ' required' : '' %>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-4 col-sm-8">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="accept_tos" value="true"<%- ssl && typeof _id !== 'undefined' ? ' checked' : '' %><%- ssl ? ' required' : '' %>> I accept the <a href="https://letsencrypt.org/repository/" target="_blank">Letsencrypt Terms of Service</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-success save">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
78
manager/src/frontend/js/app/host/404_form.js
Normal file
78
manager/src/frontend/js/app/host/404_form.js
Normal file
@ -0,0 +1,78 @@
|
||||
'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');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
@ -2,7 +2,7 @@
|
||||
<div class="modal-content">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-header text-left">
|
||||
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> Host</h4>
|
||||
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> Proxy Host</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
@ -62,7 +62,7 @@
|
||||
<div class="col-sm-offset-4 col-sm-8">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="accept_tos" value="true"<%- accept_tos ? ' checked' : '' %><%- ssl ? ' required' : '' %>> I accept the <a href="https://letsencrypt.org/repository/" target="_blank">Letsencrypt Terms of Service</a>
|
||||
<input type="checkbox" name="accept_tos" value="true"<%- ssl && typeof _id !== 'undefined' ? ' checked' : '' %><%- ssl ? ' required' : '' %>> I accept the <a href="https://letsencrypt.org/repository/" target="_blank">Letsencrypt Terms of Service</a>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
@ -3,7 +3,7 @@
|
||||
import Mn from 'backbone.marionette';
|
||||
|
||||
const _ = require('lodash');
|
||||
const template = require('./form.ejs');
|
||||
const template = require('./proxy_form.ejs');
|
||||
const Controller = require('../controller');
|
||||
const Api = require('../api');
|
||||
const App = require('../main');
|
||||
@ -46,6 +46,8 @@ module.exports = Mn.View.extend({
|
||||
}
|
||||
});
|
||||
|
||||
data.type = 'proxy';
|
||||
|
||||
// Port is integer
|
||||
data.forward_port = parseInt(data.forward_port, 10);
|
||||
|
62
manager/src/frontend/js/app/host/redirection_form.ejs
Normal file
62
manager/src/frontend/js/app/host/redirection_form.ejs
Normal file
@ -0,0 +1,62 @@
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form class="form-horizontal">
|
||||
<div class="modal-header text-left">
|
||||
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> Redirection Host</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>A redirection host will forward browser requests on this hostname to the new hostname while keeping the same path.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">Hostname</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" placeholder="myhost.example.com" name="hostname" value="<%- hostname %>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">Forwarding Hostname</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" placeholder="mynewhost.example.com" name="forward_host" value="<%- forward_host %>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-4 col-sm-8">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="block_exploits" value="true"<%- block_exploits ? ' checked' : '' %>> Block Common Exploits
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="ssl" value="true"<%- ssl ? ' checked' : '' %>> Enable SSL with Letsencrypt
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ssl_options"<%= ssl ? '' : ' style="display: none;"' %>>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">Letsencrypt Email</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="email" class="form-control" placeholder="" name="letsencrypt_email" value="<%- letsencrypt_email %>"<%- ssl ? ' required' : '' %>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-4 col-sm-8">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="accept_tos" value="true"<%- ssl && typeof _id !== 'undefined' ? ' checked' : '' %><%- ssl ? ' required' : '' %>> I accept the <a href="https://letsencrypt.org/repository/" target="_blank">Letsencrypt Terms of Service</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-success save">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
78
manager/src/frontend/js/app/host/redirection_form.js
Normal file
78
manager/src/frontend/js/app/host/redirection_form.js
Normal file
@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
|
||||
import Mn from 'backbone.marionette';
|
||||
|
||||
const _ = require('lodash');
|
||||
const template = require('./redirection_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;
|
||||
}
|
||||
});
|
||||
|
||||
data.type = 'redirection';
|
||||
|
||||
// accept_tos is not required for backend
|
||||
delete data.accept_tos;
|
||||
|
||||
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');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
@ -7,8 +7,10 @@ const model = Backbone.Model.extend({
|
||||
|
||||
defaults: function () {
|
||||
return {
|
||||
type: 'proxy',
|
||||
hostname: '',
|
||||
forward_server: '',
|
||||
forward_host: '',
|
||||
forward_port: 80,
|
||||
asset_caching: false,
|
||||
block_exploits: true,
|
||||
|
Loading…
Reference in New Issue
Block a user