Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 64de096

Browse files
committedJan 4, 2018
Added support for redirection and 404 hosts
1 parent 6182084 commit 64de096

File tree

22 files changed

+453
-31
lines changed

22 files changed

+453
-31
lines changed
 

‎README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
# Nginx Proxy Manager
44

5-
![Version](https://img.shields.io/badge/version-1.0.0-green.svg)
5+
![Version](https://img.shields.io/badge/version-1.0.1-green.svg)
66
![Stars](https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg)
77
![Pulls](https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg)
88

99
![Build Status](http://bamboo.jc21.com/plugins/servlet/wittified/build-status/AB-NPM)
1010

11-
This NPM comes as a pre-built docker image that enables you to easily forward to your websites
11+
This project comes as a pre-built docker image that enables you to easily forward to your websites
1212
running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
1313

1414

@@ -19,6 +19,10 @@ running at home or otherwise, including free SSL, without having to know too muc
1919
- Secure your sites with SSL and optionally force SSL
2020
- Secure your sites with Basic HTTP Authentication Access Lists
2121
- Advanced Nginx config option for super users
22+
- 3 domain uses:
23+
- Proxy requests to upstream server
24+
- Redirect requests to another domain
25+
- Return immediate 404's
2226

2327

2428
## 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
8488
1. Your home router will have a Port Forwarding section somewhere. Log in and find it
8589
2. Add port forwarding for port 80 and 443 to the server hosting this project
8690
3. Configure your domain name details to point to your home, either with a static ip or a service like DuckDNS
87-
4. Use the NPM here as your gateway to forward to your other web based services
91+
4. Use the Nginx Proxy Manager here as your gateway to forward to your other web based services
8892

8993

9094
## Screenshots
@@ -98,8 +102,8 @@ I won't go in to too much detail here but here are the basics for someone new to
98102

99103
- Pass on human readable ssl cert errors to the ui
100104
- Allow a host to be a redirection to another domain
101-
- Allow a host to return immediate 404's
102105
- UI: Allow column sorting on tables
103106
- UI: Allow filtering hosts by types
104107
- Advanced option to overwrite the default location block (or regex to do it automatically)
105-
- Change the renew ssl process to use the letsencrypt renew procedure so as to avoid rate limits
108+
- Add nice upstream error pages
109+

‎manager/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nginx-proxy-manager",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"description": "Nginx proxt with built in Web based management",
55
"main": "src/backend/index.js",
66
"dependencies": {

‎manager/src/backend/internal/host.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,14 @@ const internalHost = {
155155
*
156156
* @param {Object} host
157157
* @param {Boolean} [reload_nginx]
158-
* @param {Boolean} [force_ssl_renew]
159158
* @returns {Promise}
160159
*/
161-
configure: (host, reload_nginx, force_ssl_renew) => {
160+
configure: (host, reload_nginx) => {
162161
return new Promise((resolve/*, reject*/) => {
163162
resolve(internalNginx.deleteConfig(host));
164163
})
165164
.then(() => {
166-
if (host.ssl && (force_ssl_renew || !internalSsl.hasValidSslCerts(host))) {
165+
if (host.ssl && !internalSsl.hasValidSslCerts(host)) {
167166
return internalSsl.configureSsl(host);
168167
}
169168
})
@@ -248,7 +247,7 @@ const internalHost = {
248247
reject(new error.ValidationError('Host does not have SSL enabled'));
249248
} else {
250249
// 3. Fire the ssl and config generation for this host, forcing ssl
251-
internalHost.configure(host, true, true)
250+
internalSsl.renewSsl(host)
252251
.then((/*result*/) => {
253252
resolve(host);
254253
})

‎manager/src/backend/internal/nginx.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ const internalNginx = {
4545
let filename = internalNginx.getConfigName(host);
4646

4747
try {
48-
template = fs.readFileSync(__dirname + '/../templates/host.conf.ejs', {encoding: 'utf8'});
48+
if (typeof host.type === 'undefined' || !host.type) {
49+
host.type = 'proxy';
50+
}
51+
52+
template = fs.readFileSync(__dirname + '/../templates/' + host.type + '.conf.ejs', {encoding: 'utf8'});
4953
let config_text = ejs.render(template, host);
5054
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
5155
resolve(true);

‎manager/src/backend/schema/endpoints/hosts.json

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@
1010
"type": "string",
1111
"readonly": true
1212
},
13+
"type": {
14+
"type": "string",
15+
"pattern": "^(proxy|redirection|404)$"
16+
},
1317
"hostname": {
1418
"$ref": "../definitions.json#/definitions/hostname"
1519
},
1620
"forward_server": {
1721
"type": "string",
1822
"format": "ipv4"
1923
},
24+
"forward_host": {
25+
"type": "string"
26+
},
2027
"forward_port": {
2128
"type": "integer",
2229
"minumum": 1,
@@ -79,14 +86,19 @@
7986
"schema": {
8087
"type": "object",
8188
"required": [
82-
"hostname",
83-
"forward_server",
84-
"forward_port"
89+
"type",
90+
"hostname"
8591
],
8692
"properties": {
93+
"type": {
94+
"$ref": "#/definitions/type"
95+
},
8796
"hostname": {
8897
"$ref": "#/definitions/hostname"
8998
},
99+
"forward_host": {
100+
"$ref": "#/definitions/forward_host"
101+
},
90102
"forward_server": {
91103
"$ref": "#/definitions/forward_server"
92104
},
@@ -137,6 +149,9 @@
137149
"hostname": {
138150
"$ref": "#/definitions/hostname"
139151
},
152+
"forward_host": {
153+
"$ref": "#/definitions/forward_host"
154+
},
140155
"forward_server": {
141156
"$ref": "#/definitions/forward_server"
142157
},
@@ -188,9 +203,15 @@
188203
"_id": {
189204
"$ref": "#/definitions/_id"
190205
},
206+
"type": {
207+
"$ref": "#/definitions/type"
208+
},
191209
"hostname": {
192210
"$ref": "#/definitions/hostname"
193211
},
212+
"forward_host": {
213+
"$ref": "#/definitions/forward_host"
214+
},
194215
"forward_server": {
195216
"$ref": "#/definitions/forward_server"
196217
},
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# <%- hostname %>
2+
server {
3+
listen 80;
4+
<%- typeof ssl !== 'undefined' && ssl ? 'listen 443 ssl;' : '' %>
5+
6+
server_name <%- hostname %>;
7+
8+
access_log /config/logs/<%- hostname %>.log proxy;
9+
10+
<% if (typeof ssl !== 'undefined' && ssl) { -%>
11+
include conf.d/include/ssl-ciphers.conf;
12+
ssl_certificate /etc/letsencrypt/live/<%- hostname %>/fullchain.pem;
13+
ssl_certificate_key /etc/letsencrypt/live/<%- hostname %>/privkey.pem;
14+
<% } -%>
15+
16+
<%- typeof advanced !== 'undefined' && advanced ? advanced : '' %>
17+
18+
return 404;
19+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# <%- hostname %>
2+
server {
3+
listen 80;
4+
<%- typeof ssl !== 'undefined' && ssl ? 'listen 443 ssl;' : '' %>
5+
6+
server_name <%- hostname %>;
7+
8+
access_log /config/logs/<%- hostname %>.log proxy;
9+
10+
<%- typeof asset_caching !== 'undefined' && asset_caching ? 'include conf.d/include/assets.conf;' : '' %>
11+
<%- typeof block_exploits !== 'undefined' && block_exploits ? 'include conf.d/include/block-exploits.conf;' : '' %>
12+
13+
<% if (typeof ssl !== 'undefined' && ssl) { -%>
14+
include conf.d/include/ssl-ciphers.conf;
15+
ssl_certificate /etc/letsencrypt/live/<%- hostname %>/fullchain.pem;
16+
ssl_certificate_key /etc/letsencrypt/live/<%- hostname %>/privkey.pem;
17+
<% } -%>
18+
19+
<%- typeof advanced !== 'undefined' && advanced ? advanced : '' %>
20+
21+
return 301 $scheme://<%- forward_host %>$request_uri;
22+
}

‎manager/src/frontend/js/app/controller.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,34 @@ module.exports = {
5454
},
5555

5656
/**
57-
* Show Host Form
57+
* Show Proxy Host Form
5858
*
5959
* @param model
6060
*/
61-
showHostForm: function (model) {
62-
require(['./main', './host/form'], function (App, View) {
61+
showProxyHostForm: function (model) {
62+
require(['./main', './host/proxy_form'], function (App, View) {
63+
App.UI.showModalDialog(new View({model: model}));
64+
});
65+
},
66+
67+
/**
68+
* Show Redirection Host Form
69+
*
70+
* @param model
71+
*/
72+
showRedirectionHostForm: function (model) {
73+
require(['./main', './host/redirection_form'], function (App, View) {
74+
App.UI.showModalDialog(new View({model: model}));
75+
});
76+
},
77+
78+
/**
79+
* Show 404 Host Form
80+
*
81+
* @param model
82+
*/
83+
show404HostForm: function (model) {
84+
require(['./main', './host/404_form'], function (App, View) {
6385
App.UI.showModalDialog(new View({model: model}));
6486
});
6587
},
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
<td colspan="10" class="text-center">
22
<br><br>
33
<p>It looks like there are no hosts configured.</p>
4-
<p><button type="button" class="btn btn-sm btn-success">Create your first Host</button></p>
4+
<p>
5+
<button type="button" class="btn btn-sm btn-success proxy">Create Proxy Host</button>
6+
<button type="button" class="btn btn-sm btn-success redirection">Create Redirection Host</button>
7+
<button type="button" class="btn btn-sm btn-success 404">Create 404 Host</button>
8+
</p>
59
</td>

‎manager/src/frontend/js/app/dashboard/empty.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,25 @@ module.exports = Mn.View.extend({
1111
tagName: 'tr',
1212

1313
ui: {
14-
create: 'button'
14+
proxy: 'button.proxy',
15+
redirection: 'button.redirection',
16+
'404': 'button.404'
1517
},
1618

1719
events: {
18-
'click @ui.create': function (e) {
20+
'click @ui.proxy': function (e) {
1921
e.preventDefault();
20-
Controller.showHostForm(new HostModel.Model);
22+
Controller.showProxyHostForm(new HostModel.Model);
23+
},
24+
25+
'click @ui.redirection': function (e) {
26+
e.preventDefault();
27+
Controller.showRedirectionHostForm(new HostModel.Model);
28+
},
29+
30+
'click @ui.404': function (e) {
31+
e.preventDefault();
32+
Controller.show404HostForm(new HostModel.Model);
2133
}
2234
}
2335
});

‎manager/src/frontend/js/app/dashboard/main.ejs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
<table class="table table-condensed table-striped">
22
<thead>
33
<th>Hostname</th>
4-
<th>Forward</th>
4+
<th>Destination</th>
55
<th>SSL</th>
66
<th>Access List</th>
7-
<th class="text-right"><button type="button" class="btn btn-xs btn-info">Create Host</button></th>
7+
<th class="text-right">
8+
<div class="btn-group">
9+
<button type="button" class="btn btn-xs btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
10+
Create Host <span class="caret"></span>
11+
</button>
12+
<ul class="dropdown-menu">
13+
<li><a href="#" class="new-proxy">Proxy Host</a></li>
14+
<li><a href="#" class="new-redirection">Redirection Host</a></li>
15+
<li><a href="#" class="new-404">404 Host</a></li>
16+
</ul>
17+
</div>
18+
</th>
819
</thead>
920
<tbody>
1021
<!-- items -->

‎manager/src/frontend/js/app/dashboard/main.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,25 @@ module.exports = Mn.View.extend({
2626
},
2727

2828
ui: {
29-
'create': 'th button'
29+
new_proxy: 'th .new-proxy',
30+
new_redirection: 'th .new-redirection',
31+
new_404: 'th .new-404'
3032
},
3133

3234
events: {
33-
'click @ui.create': function (e) {
35+
'click @ui.new_proxy': function (e) {
3436
e.preventDefault();
35-
Controller.showHostForm(new HostModel.Model);
37+
Controller.showProxyHostForm(new HostModel.Model);
38+
},
39+
40+
'click @ui.new_redirection': function (e) {
41+
e.preventDefault();
42+
Controller.showRedirectionHostForm(new HostModel.Model);
43+
},
44+
45+
'click @ui.new_404': function (e) {
46+
e.preventDefault();
47+
Controller.show404HostForm(new HostModel.Model);
3648
}
3749
},
3850

‎manager/src/frontend/js/app/dashboard/row.ejs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
<td><a href="<%- ssl ? 'https' : 'http' %>://<%- hostname %>" target="_blank"><%- hostname %></a></td>
2-
<td><span class="monospace"><%- forward_server %>:<%- forward_port %></span></td>
2+
<td>
3+
<span class="monospace">
4+
<% if (type === 'proxy') { %>
5+
<%- forward_server %>:<%- forward_port %>
6+
<% } else if (type === 'redirection') { %>
7+
<%- forward_host %>
8+
<% } else if (type === '404') { %>
9+
404
10+
<% } %>
11+
</span>
12+
</td>
313
<td>
414
<% if (ssl && force_ssl) { %>
515
Forced

‎manager/src/frontend/js/app/dashboard/row.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,17 @@ module.exports = Mn.View.extend({
2222
events: {
2323
'click @ui.edit': function (e) {
2424
e.preventDefault();
25-
Controller.showHostForm(this.model);
25+
switch (this.model.get('type')) {
26+
case 'proxy':
27+
Controller.showProxyHostForm(this.model);
28+
break;
29+
case 'redirection':
30+
Controller.showRedirectionHostForm(this.model);
31+
break;
32+
case '404':
33+
Controller.show404HostForm(this.model);
34+
break;
35+
}
2636
},
2737

2838
'click @ui.delete': function (e) {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<div class="modal-dialog">
2+
<div class="modal-content">
3+
<form class="form-horizontal">
4+
<div class="modal-header text-left">
5+
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> 404 Host</h4>
6+
</div>
7+
<div class="modal-body">
8+
<p>A 404 host will simply return a 404 not found page for any hits to any path on the domain.</p>
9+
<div class="form-group">
10+
<label class="col-sm-4 control-label">Hostname</label>
11+
<div class="col-sm-8">
12+
<input type="text" class="form-control" placeholder="myhost.example.com" name="hostname" value="<%- hostname %>" required>
13+
</div>
14+
</div>
15+
<div class="form-group">
16+
<div class="col-sm-offset-4 col-sm-8">
17+
<div class="checkbox">
18+
<label>
19+
<input type="checkbox" name="ssl" value="true"<%- ssl ? ' checked' : '' %>> Enable SSL with Letsencrypt
20+
</label>
21+
</div>
22+
</div>
23+
</div>
24+
25+
<div class="ssl_options"<%= ssl ? '' : ' style="display: none;"' %>>
26+
<div class="form-group">
27+
<label class="col-sm-4 control-label">Letsencrypt Email</label>
28+
<div class="col-sm-8">
29+
<input type="email" class="form-control" placeholder="" name="letsencrypt_email" value="<%- letsencrypt_email %>"<%- ssl ? ' required' : '' %>>
30+
</div>
31+
</div>
32+
<div class="form-group">
33+
<div class="col-sm-offset-4 col-sm-8">
34+
<div class="checkbox">
35+
<label>
36+
<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>
37+
</label>
38+
</div>
39+
</div>
40+
</div>
41+
</div>
42+
</div>
43+
44+
<div class="modal-footer">
45+
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
46+
<button type="submit" class="btn btn-success save">Save</button>
47+
</div>
48+
</form>
49+
</div>
50+
</div>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
'use strict';
2+
3+
import Mn from 'backbone.marionette';
4+
5+
const _ = require('lodash');
6+
const template = require('./404_form.ejs');
7+
const Controller = require('../controller');
8+
const Api = require('../api');
9+
const App = require('../main');
10+
11+
require('jquery-serializejson');
12+
13+
module.exports = Mn.View.extend({
14+
template: template,
15+
16+
ui: {
17+
form: 'form',
18+
buttons: 'form button',
19+
ssl_options: '.ssl_options',
20+
ssl: 'input[name="ssl"]',
21+
letsencrypt_email: 'input[name="letsencrypt_email"]',
22+
accept_tos: 'input[name="accept_tos"]'
23+
},
24+
25+
events: {
26+
'change @ui.ssl': function (e) {
27+
let inputs = this.ui.letsencrypt_email.add(this.ui.accept_tos);
28+
if (this.ui.ssl.prop('checked')) {
29+
this.ui.ssl_options.show();
30+
inputs.prop('required', true);
31+
} else {
32+
this.ui.ssl_options.hide();
33+
inputs.prop('required', false);
34+
}
35+
},
36+
37+
'submit @ui.form': function (e) {
38+
e.preventDefault();
39+
let data = _.extend({}, this.ui.form.serializeJSON());
40+
41+
// Change text true's to bools
42+
_.map(data, function (val, key) {
43+
if (val === 'true') {
44+
data[key] = true;
45+
}
46+
});
47+
48+
// This is a 404 host
49+
data.type = '404';
50+
51+
// accept_tos is not required for backend
52+
delete data.accept_tos;
53+
54+
if (!data.ssl) {
55+
delete data.letsencrypt_email;
56+
}
57+
58+
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
59+
let method = Api.Hosts.create;
60+
61+
if (this.model.get('_id')) {
62+
// edit
63+
method = Api.Hosts.update;
64+
data._id = this.model.get('_id');
65+
}
66+
67+
method(data)
68+
.then((/*result*/) => {
69+
App.UI.closeModal();
70+
Controller.showDashboard();
71+
})
72+
.catch(err => {
73+
alert(err.message);
74+
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
75+
});
76+
}
77+
}
78+
});

‎manager/src/frontend/js/app/host/form.ejs renamed to ‎manager/src/frontend/js/app/host/proxy_form.ejs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="modal-content">
33
<form class="form-horizontal">
44
<div class="modal-header text-left">
5-
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> Host</h4>
5+
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> Proxy Host</h4>
66
</div>
77
<div class="modal-body">
88
<div class="form-group">
@@ -62,7 +62,7 @@
6262
<div class="col-sm-offset-4 col-sm-8">
6363
<div class="checkbox">
6464
<label>
65-
<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>
65+
<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>
6666
</label>
6767
</div>
6868
<div class="checkbox">

‎manager/src/frontend/js/app/host/form.js renamed to ‎manager/src/frontend/js/app/host/proxy_form.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import Mn from 'backbone.marionette';
44

55
const _ = require('lodash');
6-
const template = require('./form.ejs');
6+
const template = require('./proxy_form.ejs');
77
const Controller = require('../controller');
88
const Api = require('../api');
99
const App = require('../main');
@@ -46,6 +46,8 @@ module.exports = Mn.View.extend({
4646
}
4747
});
4848

49+
data.type = 'proxy';
50+
4951
// Port is integer
5052
data.forward_port = parseInt(data.forward_port, 10);
5153

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<div class="modal-dialog">
2+
<div class="modal-content">
3+
<form class="form-horizontal">
4+
<div class="modal-header text-left">
5+
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> Redirection Host</h4>
6+
</div>
7+
<div class="modal-body">
8+
<p>A redirection host will forward browser requests on this hostname to the new hostname while keeping the same path.</p>
9+
10+
<div class="form-group">
11+
<label class="col-sm-4 control-label">Hostname</label>
12+
<div class="col-sm-8">
13+
<input type="text" class="form-control" placeholder="myhost.example.com" name="hostname" value="<%- hostname %>" required>
14+
</div>
15+
</div>
16+
<div class="form-group">
17+
<label class="col-sm-4 control-label">Forwarding Hostname</label>
18+
<div class="col-sm-8">
19+
<input type="text" class="form-control" placeholder="mynewhost.example.com" name="forward_host" value="<%- forward_host %>" required>
20+
</div>
21+
</div>
22+
<div class="form-group">
23+
<div class="col-sm-offset-4 col-sm-8">
24+
<div class="checkbox">
25+
<label>
26+
<input type="checkbox" name="block_exploits" value="true"<%- block_exploits ? ' checked' : '' %>> Block Common Exploits
27+
</label>
28+
</div>
29+
<div class="checkbox">
30+
<label>
31+
<input type="checkbox" name="ssl" value="true"<%- ssl ? ' checked' : '' %>> Enable SSL with Letsencrypt
32+
</label>
33+
</div>
34+
</div>
35+
</div>
36+
37+
<div class="ssl_options"<%= ssl ? '' : ' style="display: none;"' %>>
38+
<div class="form-group">
39+
<label class="col-sm-4 control-label">Letsencrypt Email</label>
40+
<div class="col-sm-8">
41+
<input type="email" class="form-control" placeholder="" name="letsencrypt_email" value="<%- letsencrypt_email %>"<%- ssl ? ' required' : '' %>>
42+
</div>
43+
</div>
44+
<div class="form-group">
45+
<div class="col-sm-offset-4 col-sm-8">
46+
<div class="checkbox">
47+
<label>
48+
<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>
49+
</label>
50+
</div>
51+
</div>
52+
</div>
53+
</div>
54+
</div>
55+
56+
<div class="modal-footer">
57+
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
58+
<button type="submit" class="btn btn-success save">Save</button>
59+
</div>
60+
</form>
61+
</div>
62+
</div>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
'use strict';
2+
3+
import Mn from 'backbone.marionette';
4+
5+
const _ = require('lodash');
6+
const template = require('./redirection_form.ejs');
7+
const Controller = require('../controller');
8+
const Api = require('../api');
9+
const App = require('../main');
10+
11+
require('jquery-serializejson');
12+
13+
module.exports = Mn.View.extend({
14+
template: template,
15+
16+
ui: {
17+
form: 'form',
18+
buttons: 'form button',
19+
ssl_options: '.ssl_options',
20+
ssl: 'input[name="ssl"]',
21+
letsencrypt_email: 'input[name="letsencrypt_email"]',
22+
accept_tos: 'input[name="accept_tos"]'
23+
},
24+
25+
events: {
26+
'change @ui.ssl': function (e) {
27+
let inputs = this.ui.letsencrypt_email.add(this.ui.accept_tos);
28+
if (this.ui.ssl.prop('checked')) {
29+
this.ui.ssl_options.show();
30+
inputs.prop('required', true);
31+
} else {
32+
this.ui.ssl_options.hide();
33+
inputs.prop('required', false);
34+
}
35+
},
36+
37+
'submit @ui.form': function (e) {
38+
e.preventDefault();
39+
let data = _.extend({}, this.ui.form.serializeJSON());
40+
41+
// Change text true's to bools
42+
_.map(data, function (val, key) {
43+
if (val === 'true') {
44+
data[key] = true;
45+
}
46+
});
47+
48+
data.type = 'redirection';
49+
50+
// accept_tos is not required for backend
51+
delete data.accept_tos;
52+
53+
if (!data.ssl) {
54+
delete data.letsencrypt_email;
55+
delete data.force_ssl;
56+
}
57+
58+
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
59+
let method = Api.Hosts.create;
60+
61+
if (this.model.get('_id')) {
62+
// edit
63+
method = Api.Hosts.update;
64+
data._id = this.model.get('_id');
65+
}
66+
67+
method(data)
68+
.then((/*result*/) => {
69+
App.UI.closeModal();
70+
Controller.showDashboard();
71+
})
72+
.catch((err) => {
73+
alert(err.message);
74+
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
75+
});
76+
}
77+
}
78+
});

‎manager/src/frontend/js/models/host.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ const model = Backbone.Model.extend({
77

88
defaults: function () {
99
return {
10+
type: 'proxy',
1011
hostname: '',
1112
forward_server: '',
13+
forward_host: '',
1214
forward_port: 80,
1315
asset_caching: false,
1416
block_exploits: true,

0 commit comments

Comments
 (0)
Please sign in to comment.