Form design for proxy hosts, audit log base

This commit is contained in:
Jamie Curnow
2018-07-16 17:00:52 +10:00
parent 74d2238010
commit c5450eaa1a
29 changed files with 646 additions and 121 deletions

View File

@ -3,28 +3,115 @@
<h5 class="modal-title"><% if (typeof id !== 'undefined') { %>Edit<% } else { %>New<% } %> Proxy Host</h5>
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal">&nbsp;</button>
</div>
<div class="modal-body">
<div class="modal-body has-tabs">
<form>
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Domain Name <span class="form-required">*</span></label>
<input name="domain_name" type="text" class="form-control" placeholder="example.com" value="<%- domain_name %>" required>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="nav-item"><a href="#details" aria-controls="tab1" role="tab" data-toggle="tab" class="nav-link active"><i class="fe fe-zap"></i> Details</a></li>
<li role="presentation" class="nav-item"><a href="#ssl-options" aria-controls="tab2" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-shield"></i> SSL</a></li>
</ul>
<div class="tab-content">
<!-- Details -->
<div role="tabpanel" class="tab-pane active" id="details">
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Domain Name <span class="form-required">*</span></label>
<input name="domain_name" type="text" class="form-control" placeholder="example.com or *.example.com" value="<%- domain_name %>" pattern="(\*\.)?[a-z0-9\.]+" required title="Please enter a valid domain name. Domain wildcards are allowed: *.yourdomain.com">
</div>
</div>
<div class="col-sm-8 col-md-8">
<div class="form-group">
<label class="form-label">Forward IP <span class="form-required">*</span></label>
<input type="text" name="forward_ip" class="form-control" placeholder="000.000.000.000" autocomplete="off" maxlength="15" required>
</div>
</div>
<div class="col-sm-4 col-md-4">
<div class="form-group">
<label class="form-label">Forward Port <span class="form-required">*</span></label>
<input name="forward_port" type="number" class="form-control" placeholder="80" value="<%- forward_port %>" required>
</div>
</div>
</div>
</div>
<div class="col-sm-8 col-md-8">
<div class="form-group">
<label class="form-label">Forward IP <span class="form-required">*</span></label>
<input type="text" name="forward_ip" class="form-control" placeholder="000.000.000.000" autocomplete="off" maxlength="15" required>
</div>
</div>
<div class="col-sm-4 col-md-4">
<div class="form-group">
<label class="form-label">Forward Port <span class="form-required">*</span></label>
<input name="forward_port" type="number" class="form-control" placeholder="80" value="<%- forward_port %>" required>
<!-- SSL -->
<div role="tabpanel" class="tab-pane" id="ssl-options">
<div class="row">
<div class="col-sm-6 col-md-6">
<div class="form-group">
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="ssl_enabled" value="1"<%- ssl_enabled ? ' checked' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description">Enable SSL</span>
</label>
</div>
</div>
<div class="col-sm-6 col-md-6">
<div class="form-group">
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="ssl_forced" value="1"<%- ssl_forced ? ' checked' : '' %><%- ssl_enabled ? '' : ' disabled' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description">Force SSL</span>
</label>
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Certificate Provider</label>
<div class="selectgroup w-100">
<label class="selectgroup-item">
<input type="radio" name="ssl_provider" value="letsencrypt" class="selectgroup-input"<%- ssl_provider !== 'other' ? ' checked' : '' %>>
<span class="selectgroup-button">Let's Encrypt</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="ssl_provider" value="other" class="selectgroup-input"<%- ssl_provider === 'other' ? ' checked' : '' %>>
<span class="selectgroup-button">Other</span>
</label>
</div>
</div>
</div>
<!-- Lets encrypt -->
<div class="col-sm-12 col-md-12 letsencrypt-ssl">
<div class="form-group">
<label class="form-label">Email Address for Let's Encrypt <span class="form-required">*</span></label>
<input name="meta[letsencrypt_email]" type="email" class="form-control" placeholder="" value="<%- getLetsencryptEmail() %>" required>
</div>
</div>
<div class="col-sm-12 col-md-12 letsencrypt-ssl">
<div class="form-group">
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="meta[letsencrypt_agree]" value="1" required<%- getLetsencryptAgree() ? ' checked' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description">I Agree to the <a href="https://letsencrypt.org/repository/" target="_blank">Let's Encrypt Terms of Service</a> <span class="form-required">*</span></span>
</label>
</div>
</div>
<!-- Other -->
<div class="col-sm-12 col-md-12 other-ssl">
<div class="form-group">
<div class="form-label">Certificate</div>
<div class="custom-file">
<input type="file" class="custom-file-input" name="meta[other_ssl_certificate]">
<label class="custom-file-label">Choose file</label>
</div>
</div>
</div>
<div class="col-sm-12 col-md-12 other-ssl">
<div class="form-group">
<div class="form-label">Certificate Key</div>
<div class="custom-file">
<input type="file" class="custom-file-input" name="meta[other_ssl_certificate_key]">
<label class="custom-file-label">Choose file</label>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">

View File

@ -1,5 +1,6 @@
'use strict';
const _ = require('underscore');
const Mn = require('backbone.marionette');
const template = require('./form.ejs');
const Controller = require('../../controller');
@ -16,78 +17,110 @@ module.exports = Mn.View.extend({
className: 'modal-dialog',
ui: {
form: 'form',
forward_ip: 'input[name="forward_ip"]',
buttons: '.modal-footer button',
cancel: 'button.cancel',
save: 'button.save',
error: '.secret-error'
form: 'form',
domain_name: 'input[name="domain_name"]',
forward_ip: 'input[name="forward_ip"]',
buttons: '.modal-footer button',
cancel: 'button.cancel',
save: 'button.save',
ssl_enabled: 'input[name="ssl_enabled"]',
ssl_options: '#ssl-options input',
ssl_provider: 'input[name="ssl_provider"]',
// SSL hiding and showing
all_ssl: '.letsencrypt-ssl, .other-ssl',
letsencrypt_ssl: '.letsencrypt-ssl',
other_ssl: '.other-ssl'
},
events: {
'change @ui.ssl_enabled': function () {
let enabled = this.ui.ssl_enabled.prop('checked');
this.ui.ssl_options.not(this.ui.ssl_enabled).prop('disabled', !enabled).parents('.form-group').css('opacity', enabled ? 1 : 0.5);
this.ui.ssl_provider.trigger('change');
},
'change @ui.ssl_provider': function () {
let enabled = this.ui.ssl_enabled.prop('checked');
let provider = this.ui.ssl_provider.filter(':checked').val();
this.ui.all_ssl.hide().find('input').prop('disabled', true);
this.ui[provider + '_ssl'].show().find('input').prop('disabled', !enabled);
},
'click @ui.save': function (e) {
e.preventDefault();
return;
this.ui.error.hide();
if (!this.ui.form[0].checkValidity()) {
$('<input type="submit">').hide().appendTo(this.ui.form).click().remove();
return;
}
let view = this;
let data = this.ui.form.serializeJSON();
// Manipulate
data.roles = [];
if ((this.model.get('id') === Cache.User.get('id') && this.model.isAdmin()) || (typeof data.is_admin !== 'undefined' && data.is_admin)) {
data.roles.push('admin');
delete data.is_admin;
}
data.forward_port = parseInt(data.forward_port, 10);
_.map(data, function (item, idx) {
if (typeof item === 'string' && item === '1') {
item = true;
} else if (typeof item === 'object' && item !== null) {
_.map(item, function (item2, idx2) {
if (typeof item2 === 'string' && item2 === '1') {
item[idx2] = true;
}
});
}
data[idx] = item;
});
data.is_disabled = typeof data.is_disabled !== 'undefined' ? !!data.is_disabled : false;
// Process
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
let method = Api.Users.create;
let method = Api.Nginx.ProxyHosts.create;
if (this.model.get('id')) {
// edit
method = Api.Users.update;
method = Api.Nginx.ProxyHosts.update;
data.id = this.model.get('id');
}
method(data)
.then(result => {
if (result.id === Cache.User.get('id')) {
Cache.User.set(result);
}
if (view.model.get('id') !== Cache.User.get('id')) {
Controller.showUsers();
}
view.model.set(result);
App.UI.closeModal(function () {
if (method === Api.Users.create) {
// Show permissions dialog immediately
Controller.showUserPermissions(view.model);
if (method === Api.Nginx.ProxyHosts.create) {
Controller.showNginxProxy();
}
});
})
.catch(err => {
this.ui.error.text(err.message).show();
alert(err.message);
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
});
}
},
templateContext: {
getLetsencryptEmail: function () {
return typeof this.meta.letsencrypt_email !== 'undefined' ? this.meta.letsencrypt_email : Cache.User.get('email');
},
getLetsencryptAgree: function () {
return typeof this.meta.letsencrypt_agree !== 'undefined' ? this.meta.letsencrypt_agree : false;
}
},
onRender: function () {
this.ui.forward_ip.mask('099.099.099.099', {
clearIfNotMatch: true,
placeholder: '000.000.000.000'
});
/*
this.ui.forward_ip.mask('099.099.099.099', {
reverse: true,
clearIfNotMatch: true,
placeholder: '000.000.000.000'
});
*/
this.ui.ssl_enabled.trigger('change');
this.ui.ssl_provider.trigger('change');
this.ui.domain_name[0].oninvalid = function () {
this.setCustomValidity('Please enter a valid domain name. Domain wildcards are allowed: *.yourdomain.com');
};
},
initialize: function (options) {