Removed v1 cruft

This commit is contained in:
Jamie Curnow 2018-09-03 09:13:17 +10:00
parent d04f5a619a
commit 5dd723a864
30 changed files with 0 additions and 1874 deletions

View File

@ -1,12 +0,0 @@
{
"presets": [
["env", {
"targets": {
"browsers": ["Chrome >= 65"]
},
"debug": false,
"modules": false,
"useBuiltIns": "usage"
}]
]
}

View File

@ -1,172 +0,0 @@
/*jshint node:true */
'use strict';
const path = require('path');
const gulp = require('gulp');
const gutil = require('gulp-util');
const concat = require('gulp-concat-util');
const runSequence = require('run-sequence');
const webpack = require('webpack');
const webpackStream = require('webpack-stream');
const imagemin = require('gulp-imagemin');
const del = require('del');
const bump = require('gulp-bump');
const sass = require('gulp-sass');
const ejs = require('gulp-ejs');
const PACKAGE = require('./package.json');
const assets = {
views: {
watch: 'src/frontend/views/**/*.ejs',
src: 'src/frontend/views/*.ejs',
dest: 'dist/'
},
fonts: {
watch: 'src/frontend/fonts/**/*.{ttf,woff,woff2,eof,eot,svg,otf}',
dest: 'dist/fonts'
},
images: {
watch: 'src/frontend/images/**/*.{png,jpg,gif}',
dest: 'dist/images'
},
scss: {
watch: 'src/frontend/scss/**/*.scss',
loadPath: 'src/frontend/scss',
src: 'src/frontend/scss/styles.scss',
dest: 'dist/css'
},
js: {
watch: 'src/frontend/js/**/*',
src: 'src/frontend/js/main.js',
dest: 'dist/js/'
}
};
/**
* @param color
* @param label
* @returns {Function}
*/
function logger (color, label) {
return function () {
let args = Array.prototype.slice.call(arguments);
args.unshift(gutil.colors[color].bold(label.toUpperCase() + ':'));
gutil.log.apply(null, args);
};
}
gutil.error = logger('red', 'error');
gutil.warn = logger('yellow', 'warn');
gutil.notice = logger('white', 'notice');
/**
* @param err
*/
function handleError (err) {
gutil.error(err.stack);
}
/*****************************
TASKS
******************************/
/**
* clean
*/
gulp.task('clean', function (cb) {
del(['./dist/*'])
.then(function () {
cb();
})
.catch(handleError);
});
/**
* images
*/
gulp.task('images', function () {
if (process.arch !== 'arm') {
return gulp.src(assets.images.watch)
.pipe(imagemin({
optimizationLevel: 7
}))
.pipe(gulp.dest(assets.images.dest))
.on('error', handleError);
} else {
return gulp.src(assets.images.watch)
.pipe(gulp.dest(assets.images.dest))
.on('error', handleError);
}
});
/**
* fonts
*/
gulp.task('fonts', function () {
return gulp.src(assets.fonts.watch)
.pipe(gulp.dest(assets.fonts.dest))
.on('error', handleError);
});
/**
* scss
*/
gulp.task('scss', function () {
return gulp.src(assets.scss.src)
.pipe(sass().on('error', sass.logError))
.pipe(concat.header('@import url(\'https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300,700\');@import url(\'https://fonts.googleapis.com/css?family=Roboto:100,200,300,400,500,600,700|Roboto+Condensed:300,400,700\');'))
.pipe(gulp.dest(path.resolve(assets.scss.dest)));
});
/**
* js
*/
gulp.task('js', function () {
return gulp.src(assets.js.src)
.pipe(webpackStream(require('./webpack.config.js'), webpack))
.pipe(gulp.dest(assets.js.dest))
.on('error', handleError);
});
/**
* views
*/
gulp.task('views', function () {
return gulp.src(assets.views.src)
.pipe(ejs({
version: PACKAGE.version
}, {}, {
ext: '.html'
}))
.on('error', handleError)
.pipe(gulp.dest(assets.views.dest));
});
/**
* bump
*/
gulp.task('bump', function () {
gulp.src('./package.json')
.pipe(bump({type: 'version'}))
.pipe(gulp.dest('./'));
});
/**
* build
*/
gulp.task('build', function (cb) {
runSequence('clean', ['images', 'fonts', 'scss', 'js', 'views'], cb);
});
/**
* default
*/
gulp.task('default', ['build'], function () {
gulp.watch(assets.scss.watch, ['scss']);
gulp.watch(assets.images.watch, ['images']);
gulp.watch(assets.fonts.watch, ['fonts']);
gulp.watch(assets.js.watch, ['js']);
gulp.watch(assets.views.watch, ['views']);
gulp.watch('./webpack.config.js', ['js']);
});

View File

@ -1,60 +0,0 @@
{
"name": "nginx-proxy-manager",
"version": "1.1.2",
"description": "Nginx proxt with built in Web based management",
"main": "src/backend/index.js",
"dependencies": {
"ajv": "^5.5.1",
"batchflow": "^0.4.0",
"body-parser": "^1.18.2",
"compression": "^1.7.1",
"diskdb": "^0.1.17",
"ejs": "^2.5.7",
"express": "^4.16.2",
"express-winston": "^2.4.0",
"json-schema-ref-parser": "^4.0.4",
"lodash": "^4.17.4",
"path": "^0.12.7",
"unix-timestamp": "^0.2.0",
"winston": "^2.4.0"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-minify-webpack-plugin": "^0.3.1",
"babel-preset-env": "^1.7.0",
"backbone": "1.3.3",
"backbone-virtual-collection": "^0.6.15",
"backbone.marionette": "3.4.1",
"backbone.radio": "2.0.0",
"bootstrap": "^3.3.7",
"del": "^3.0.0",
"ejs-loader": "^0.3.0",
"es6-promise": "^4.1.1",
"font-awesome": "^4.7.0",
"form-serializer": "^2.5.0",
"gulp": "^3.9.1",
"gulp-bump": "^2.7.0",
"gulp-concat-util": "^0.5.5",
"gulp-ejs": "^3.0.1",
"gulp-imagemin": "^3.3.0",
"gulp-sass": "^4.0.1",
"gulp-util": "^3.0.8",
"image-size": "^0.6.1",
"jquery": "^3.2.1",
"jquery-serializejson": "^2.8.1",
"normalize-css": "^2.3.1",
"prepack-webpack-plugin": "^1.1.0",
"run-sequence": "^2.2.0",
"underscore": "^1.8.3",
"webpack": "^4.12.0",
"webpack-cli": "^3.0.8",
"webpack-stream": "^4.0.0",
"webpack-visualizer-plugin": "^0.1.11"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jamie Curnow <jc@jc21.com>",
"license": "MIT"
}

View File

@ -1,22 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./empty.ejs');
const AccessModel = require('../../models/access');
const Controller = require('../controller');
module.exports = Mn.View.extend({
template: template,
tagName: 'tr',
ui: {
create: 'button'
},
events: {
'click @ui.create': function (e) {
e.preventDefault();
Controller.showAccessListForm(new AccessModel.Model);
}
}
});

View File

@ -1,61 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const Api = require('../api');
const template = require('./main.ejs');
const Controller = require('../controller');
const RowView = require('./row');
const AccessListModel = require('../../models/access');
const EmptyView = require('./empty');
const TableBody = Mn.CollectionView.extend({
tagName: 'tbody',
childView: RowView
});
module.exports = Mn.View.extend({
template: template,
id: 'access',
regions: {
list_region: {
el: 'tbody',
replaceElement: true
}
},
ui: {
'create': 'th button'
},
events: {
'click @ui.create': function (e) {
e.preventDefault();
Controller.showAccessListForm(new AccessListModel.Model);
}
},
onRender: function () {
let view = this;
Api.Access.getAll()
.then(response => {
if (!view.isDestroyed()) {
if (response && response.length) {
view.showChildView('list_region', new TableBody({
collection: new AccessListModel.Collection(response)
}));
} else {
view.showChildView('list_region', new EmptyView());
}
view.trigger('loaded');
}
})
.catch(err => {
Controller.showError(err, 'Could not fetch Access Lists');
view.trigger('loaded');
});
}
});

View File

@ -1,31 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./row.ejs');
const Controller = require('../controller');
module.exports = Mn.View.extend({
template: template,
tagName: 'tr',
ui: {
edit: 'button.edit',
delete: 'button.delete'
},
events: {
'click @ui.edit': function (e) {
e.preventDefault();
Controller.showAccessListForm(this.model);
},
'click @ui.delete': function (e) {
e.preventDefault();
Controller.showDeleteAccessList(this.model);
}
},
initialize: function () {
this.listenTo(this.model, 'change', this.render);
}
});

View File

@ -1,34 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./delete.ejs');
const Controller = require('../controller');
const Api = require('../api');
const App = require('../main');
module.exports = Mn.View.extend({
template: template,
ui: {
buttons: 'form button',
delete: 'button.delete'
},
events: {
'click @ui.delete': function (e) {
e.preventDefault();
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
Api.Access.delete(this.model.get('_id'))
.then((/*result*/) => {
App.UI.closeModal();
Controller.showAccess();
})
.catch(err => {
alert(err.message);
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
});
}
}
});

View File

@ -1,8 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./item.ejs');
module.exports = Mn.View.extend({
template: template
});

View File

@ -1,160 +0,0 @@
'use strict';
const $ = require('jquery');
/**
* @param {String} message
* @param {*} debug
* @param {Number} code
* @constructor
*/
const ApiError = function (message, debug, code) {
let temp = Error.call(this, message);
temp.name = this.name = 'ApiError';
this.stack = temp.stack;
this.message = temp.message;
this.debug = debug;
this.code = code;
};
ApiError.prototype = Object.create(Error.prototype, {
constructor: {
value: ApiError,
writable: true,
configurable: true
}
});
/**
*
* @param {String} verb
* @param {String} path
* @param {Object} [data]
* @param {Object} [options]
* @returns {Promise}
*/
function fetch (verb, path, data, options) {
options = options || {};
return new Promise(function (resolve, reject) {
let api_url = '/api/';
let url = api_url + path;
$.ajax({
url: url,
data: typeof data === 'object' && data !== null ? JSON.stringify(data) : data,
type: verb,
dataType: 'json',
contentType: 'application/json; charset=UTF-8',
crossDomain: true,
timeout: (options.timeout ? options.timeout : 30000),
xhrFields: {
withCredentials: true
},
success: function (data, textStatus, response) {
resolve(response);
},
error: function (xhr, status, error_thrown) {
let code = 400;
if (typeof xhr.responseJSON !== 'undefined' && typeof xhr.responseJSON.error !== 'undefined' && typeof xhr.responseJSON.error.message !== 'undefined') {
error_thrown = xhr.responseJSON.error.message;
code = xhr.responseJSON.error.code || 500;
}
reject(new ApiError(error_thrown, xhr.responseText, code));
}
});
});
}
module.exports = {
status: function () {
return fetch('get', '');
},
Hosts: {
/**
* @returns {Promise}
*/
getAll: function () {
return fetch('get', 'hosts');
},
/**
* @param {Object} data
* @returns {Promise}
*/
create: function (data) {
return fetch('post', 'hosts', data);
},
/**
* @param {Object} data
* @param {String} data._id
* @returns {Promise}
*/
update: function (data) {
let _id = data._id;
delete data._id;
return fetch('put', 'hosts/' + _id, data);
},
/**
* @param {String} _id
* @returns {Promise}
*/
delete: function (_id) {
return fetch('delete', 'hosts/' + _id);
},
/**
* @param {String} _id
* @returns {Promise}
*/
reconfigure: function (_id) {
return fetch('post', 'hosts/' + _id + '/reconfigure');
}
},
Access: {
/**
* @returns {Promise}
*/
getAll: function () {
return fetch('get', 'access');
},
/**
* @param {Object} data
* @returns {Promise}
*/
create: function (data) {
return fetch('post', 'access', data);
},
/**
* @param {Object} data
* @param {String} data._id
* @returns {Promise}
*/
update: function (data) {
let _id = data._id;
delete data._id;
return fetch('put', 'access/' + _id, data);
},
/**
* @param {String} _id
* @returns {Promise}
*/
delete: function (_id) {
return fetch('delete', 'access/' + _id);
}
}
};

View File

@ -1,171 +0,0 @@
'use strict';
const Backbone = require('backbone');
const Cache = require('./cache');
module.exports = {
/**
* @param {String} route
* @param {Object} [options]
* @returns {Boolean}
*/
navigate: function (route, options) {
options = options || {};
Backbone.history.navigate(route.toString(), options);
return true;
},
/**
* Dashboard
*/
showDashboard: function () {
let controller = this;
require(['./main', './dashboard/main'], (App, View) => {
controller.navigate('/');
App.UI.showMainLoading();
let view = new View();
view.on('loaded', function () {
App.UI.hideMainLoading();
});
App.UI.showChildView('main_region', view);
});
},
/**
* Access
*/
showAccess: function () {
let controller = this;
require(['./main', './access/main'], (App, View) => {
controller.navigate('/access');
App.UI.showMainLoading();
let view = new View();
view.on('loaded', function () {
App.UI.hideMainLoading();
});
App.UI.showChildView('main_region', view);
});
},
/**
* Show Proxy Host Form
*
* @param model
*/
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}));
});
},
/**
* Show Stream Host Form
*
* @param model
*/
showStreamHostForm: function (model) {
require(['./main', './host/stream_form'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
},
/**
* Show Delete Host Confirmation
*
* @param model
*/
showDeleteHost: function (model) {
require(['./main', './host/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
},
/**
* Show Reconfigure Host
*
* @param model
*/
showReconfigureHost: function (model) {
require(['./main', './host/reconfigure'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
},
/**
* Show Advanced Host
*
* @param model
*/
showAdvancedHost: function (model) {
require(['./main', './host/advanced'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
},
/**
* Show Access List Form
*
* @param model
*/
showAccessListForm: function (model) {
require(['./main', './access_list/form'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
},
/**
* Show Delete Access List Confirmation
*
* @param model
*/
showDeleteAccessList: function (model) {
require(['./main', './access_list/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
},
/**
* Error
*
* @param {Error} err
* @param {String} nice_msg
*/
showError: function (err, nice_msg) {
require(['./main', './error/main'], (App, View) => {
App.UI.showChildView('main_region', new View({
err: err,
nice_msg: nice_msg
}));
});
}
};

View File

@ -1,34 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./empty.ejs');
const HostModel = require('../../models/host');
const Controller = require('../controller');
module.exports = Mn.View.extend({
template: template,
tagName: 'tr',
ui: {
proxy: 'button.proxy',
redirection: 'button.redirection',
'404': 'button.404'
},
events: {
'click @ui.proxy': function (e) {
e.preventDefault();
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);
}
}
});

View File

@ -1,80 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const Api = require('../api');
const template = require('./main.ejs');
const Controller = require('../controller');
const RowView = require('./row');
const HostModel = require('../../models/host');
const EmptyView = require('./empty');
const TableBody = Mn.CollectionView.extend({
tagName: 'tbody',
childView: RowView
});
module.exports = Mn.View.extend({
template: template,
id: 'dashboard',
regions: {
list_region: {
el: 'tbody',
replaceElement: true
}
},
ui: {
new_proxy: 'th .new-proxy',
new_redirection: 'th .new-redirection',
new_404: 'th .new-404',
new_stream: 'th .new-stream'
},
events: {
'click @ui.new_proxy': function (e) {
e.preventDefault();
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);
},
'click @ui.new_stream': function (e) {
e.preventDefault();
Controller.showStreamHostForm(new HostModel.Model);
}
},
onRender: function () {
let view = this;
Api.Hosts.getAll()
.then(response => {
if (!view.isDestroyed()) {
if (response && response.length) {
view.showChildView('list_region', new TableBody({
collection: new HostModel.Collection(response)
}));
} else {
view.showChildView('list_region', new EmptyView());
}
view.trigger('loaded');
}
})
.catch(err => {
Controller.showError(err, 'Could not fetch Hosts');
view.trigger('loaded');
});
}
});

View File

@ -1,63 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./row.ejs');
const Controller = require('../controller');
const AccessListModel = require('../../models/access');
module.exports = Mn.View.extend({
template: template,
tagName: 'tr',
ui: {
edit: 'button.edit',
delete: 'button.delete',
access_list: 'a.access_list',
reconfigure: 'button.reconfigure',
advanced: 'button.advanced'
},
events: {
'click @ui.edit': function (e) {
e.preventDefault();
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;
case 'stream':
Controller.showStreamHostForm(this.model);
break;
}
},
'click @ui.delete': function (e) {
e.preventDefault();
Controller.showDeleteHost(this.model);
},
'click @ui.access_list': function (e) {
e.preventDefault();
Controller.showAccessListForm(new AccessListModel.Model(this.model.get('access_list')));
},
'click @ui.reconfigure': function (e) {
e.preventDefault();
Controller.showReconfigureHost(this.model);
},
'click @ui.advanced': function (e) {
e.preventDefault();
Controller.showAdvancedHost(this.model);
}
},
initialize: function () {
this.listenTo(this.model, 'change', this.render);
}
});

View File

@ -1,32 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./main.ejs');
module.exports = Mn.View.extend({
id: 'error',
template: template,
options: {
err: null,
nice_msg: 'Unknown error'
},
templateContext: function () {
let view = this;
return {
getNiceMessage: function () {
return view.options.nice_msg;
},
getErrorMessage: function () {
return view.options.err ? view.options.err.message : '';
}
};
},
initialize: function () {
console.error(this.options.err);
}
});

View File

@ -1,77 +0,0 @@
'use strict';
const Mn = require('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');
});
}
}
});

View File

@ -1,38 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./advanced.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'
},
events: {
'submit @ui.form': function (e) {
e.preventDefault();
let data = this.ui.form.serializeJSON();
data._id = this.model.get('_id');
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
Api.Hosts.update(data)
.then((/*result*/) => {
App.UI.closeModal();
Controller.showDashboard();
})
.catch((err) => {
alert(err.message);
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
});
}
}
});

View File

@ -1,34 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./delete.ejs');
const Controller = require('../controller');
const Api = require('../api');
const App = require('../main');
module.exports = Mn.View.extend({
template: template,
ui: {
buttons: 'form button',
delete: 'button.delete'
},
events: {
'click @ui.delete': function (e) {
e.preventDefault();
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
Api.Hosts.delete(this.model.get('_id'))
.then((/*result*/) => {
App.UI.closeModal();
Controller.showDashboard();
})
.catch(err => {
alert(err.message);
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
});
}
}
});

View File

@ -1,107 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const _ = require('lodash');
const template = require('./proxy_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"]',
access_list_id: 'select[name="access_list_id"]'
},
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 = 'proxy';
// Port is integer
data.forward_port = parseInt(data.forward_port, 10);
// accept_tos is not required for backend
delete data.accept_tos;
delete data.access_list;
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');
});
}
},
onRender: function () {
let view = this;
Api.Access.getAll()
.then(response => {
if (!view.isDestroyed()) {
view.ui.access_list_id.empty().append($('<option>').val('').text('None (Publicly Accessible)'));
if (response && response.length) {
_.map(response, access => {
view.ui.access_list_id.append($('<option>').val(access._id).text(access.name));
});
}
if (this.model.get('access_list_id')) {
view.ui.access_list_id.val(this.model.get('access_list_id'));
}
}
})
.catch(err => {
alert("Error loading Access Lists!\n\n" + err.message);
App.UI.closeModal();
});
}
});

View File

@ -1,32 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./reconfigure.ejs');
const Api = require('../api');
const App = require('../main');
module.exports = Mn.View.extend({
template: template,
ui: {
buttons: 'form button',
reconfigure: 'button.reconfigure'
},
events: {
'click @ui.reconfigure': function (e) {
e.preventDefault();
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
Api.Hosts.reconfigure(this.model.get('_id'))
.then((/*result*/) => {
App.UI.closeModal();
})
.catch(err => {
alert(err.message);
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
});
}
}
});

View File

@ -1,77 +0,0 @@
'use strict';
const Mn = require('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');
});
}
}
});

View File

@ -1,62 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const _ = require('lodash');
const template = require('./stream_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'
},
events: {
'submit @ui.form': function (e) {
e.preventDefault();
let data = _.extend({}, this.ui.form.serializeJSON());
data.type = 'stream';
// Ports are integers
data.incoming_port = parseInt(data.incoming_port, 10);
data.forward_port = parseInt(data.forward_port, 10);
if (typeof data.protocols === 'undefined' || !data.protocols.length) {
alert('You must select one or more Protocols');
return;
}
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');
});
}
},
templateContext: {
hasStreamProtocol: function (protocol) {
return this.protocols.indexOf(protocol) !== -1;
}
}
});

View File

@ -1,119 +0,0 @@
'use strict';
const $ = require('jquery');
const _ = require('underscore');
const Backbone = require('backbone');
const Mn = require('../lib/marionette');
const Cache = require('./cache');
const Controller = require('./controller');
const Router = require('./router');
const UI = require('./ui/main');
const Api = require('./api');
const App = Mn.Application.extend({
region: '#app',
Cache: Cache,
Api: Api,
UI: null,
Controller: Controller,
version: null,
onStart: function (app, options) {
console.log('Welcome to Nginx Proxy Manager');
let myapp = this;
Api.status()
.then(result => {
this.version = [result.version.major, result.version.minor, result.version.revision].join('.');
})
.then(Api.Bootstrap)
.then(() => {
this.bootstrapTimer();
this.UI = new UI();
this.UI.on('render', () => {
// If successful, start the history and routing
new Router(options);
Backbone.history.start({});
// Remove loading class
$('#app').removeClass('loading');
});
this.getRegion().show(this.UI);
})
.catch(function (err) {
console.info('Not logged in: ', err.message);
myapp.trigger('after:start');
myapp.UI = new UI();
myapp.UI.on('render', () => {
// Remove loading class
myapp.UI.reset();
Controller.showLogin();
});
myapp.getRegion().show(myapp.UI);
});
},
History: {
replace: function (data) {
window.history.replaceState(_.extend(window.history.state || {}, data), document.title);
},
get: function (attr) {
return window.history.state ? window.history.state[attr] : undefined;
}
},
Error: function (code, message, debug) {
let temp = Error.call(this, message);
temp.name = this.name = 'AppError';
this.stack = temp.stack;
this.message = temp.message;
this.code = code;
this.debug = debug;
},
showError: function () {
let ErrorView = Mn.View.extend({
tagName: 'section',
id: 'error',
template: _.template('Error loading stuff. Please reload the app.')
});
this.getRegion().show(new ErrorView());
},
/**
* Bootstraps the user from time to time
*/
bootstrapTimer: function () {
setTimeout(() => {
Api.status()
.then(result => {
let version = [result.version.major, result.version.minor, result.version.revision].join('.');
if (version !== this.version) {
document.location.reload();
}
})
.then(Api.Bootstrap)
.then(() => {
this.bootstrapTimer();
})
.catch(err => {
if (err.message !== 'timeout' && err.code && err.code !== 400) {
console.log(err);
console.error(err.message);
document.location.reload();
} else {
this.bootstrapTimer();
}
});
}, 30 * 1000);
}
});
const app = new App();
module.exports = app;

View File

@ -1,36 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./main.ejs');
const Controller = require('../../controller');
module.exports = Mn.View.extend({
template: template,
ui: {
logo: '.navbar-brand',
links: 'a[href^="#"]'
},
events: {
'click @ui.links': function (e) {
e.preventDefault();
let href = e.target.href.replace(/[^#]*#/g, '');
switch (href) {
case 'dashboard':
Controller.showDashboard();
break;
case 'access':
Controller.showAccess();
break;
default:
Controller.showDashboard();
break;
}
}
}
});

View File

@ -1,100 +0,0 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./main.ejs');
const HeaderView = require('./header/main');
const Cache = require('../cache');
require('bootstrap');
module.exports = Mn.View.extend({
template: template,
modal: null,
ui: {
header_region: '#header',
main_region: '#main',
modal_region: '#modal-dialog',
main_loader_region: '#main-loader'
},
regions: {
header_region: '@ui.header_region',
main_region: '@ui.main_region',
modal_region: '@ui.modal_region',
main_loader_region: '@ui.main_loader_region'
},
showMainLoading: function () {
this.ui.main_loader_region.show();
},
hideMainLoading: function () {
this.ui.main_loader_region.hide();
},
/**
*
* @param view
* @param [show_callback]
* @param [shown_callback]
*/
showModalDialog: function (view, show_callback, shown_callback) {
this.showChildView('modal_region', view);
this.modal.modal('show');
let ui = this;
this.modal.on('hidden.bs.modal', function (/*e*/) {
if (show_callback) {
ui.modal.off('show.bs.modal', show_callback);
}
if (shown_callback) {
ui.modal.off('shown.bs.modal', shown_callback);
}
ui.modal.off('hidden.bs.modal');
view.destroy();
});
if (show_callback) {
this.modal.on('show.bs.modal', show_callback);
}
if (shown_callback) {
this.modal.on('shown.bs.modal', shown_callback);
}
},
/**
*
* @param [hidden_callback]
*/
closeModal: function (hidden_callback) {
this.modal.modal('hide');
if (hidden_callback) {
this.modal.on('hidden.bs.modal', hidden_callback);
}
},
onRender: function () {
this.showChildView('header_region', new HeaderView({
model: Cache.User
}));
if (this.modal === null) {
this.modal = $('#modal-dialog');
this.modal.modal({
show: false
});
}
},
reset: function () {
this.getRegion('header_region').reset();
this.getRegion('modal_region').reset();
}
});

View File

@ -1,32 +0,0 @@
'use strict';
const numeral = require('numeral');
const moment = require('moment');
module.exports = {
/**
* @param {Integer} number
* @returns {String}
*/
niceNumber: function (number) {
return numeral(number).format('0,0');
},
/**
* @param {String} date
* @returns {String}
*/
shortTime: function (date) {
let shorttime = '';
if (typeof date === 'number') {
shorttime = moment.unix(date).format('H:mm A');
} else {
shorttime = moment(date).format('H:mm A');
}
return shorttime;
}
};

View File

@ -1,46 +0,0 @@
'use strict';
const _ = require('underscore');
const Mn = require('backbone.marionette');
let render = Mn.Renderer.render;
Mn.Renderer.render = function (template, data, view) {
data = _.clone(data);
/**
* @param {String} string
* @returns {String}
*/
data.escape = function (string) {
let entityMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
'\'': '&#39;',
'/': '&#x2F;'
};
return String(string).replace(/[&<>"'\/]/g, function (s) {
return entityMap[s];
});
};
/**
* @param {String} string
* @param {Integer} length
* @returns {String}
*/
data.trim = function (string, length) {
if (string.length > length) {
let trimmedString = string.substr(0, length);
return trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(' '))) + '...';
}
return string;
};
return render.call(this, template, data, view);
};
module.exports = Mn;

View File

@ -1,22 +0,0 @@
'use strict';
const promise = require('es6-promise');
const $ = require('jquery');
global.jQuery = $;
global.$ = $;
const App = require('./app/main');
// es6-promise nukes the Native Promise impl - restore it if this happens.
// See also https://github.com/jakearchibald/es6-promise/issues/140
const NativePromise = window.Promise;
if (NativePromise) {
window.Promise = NativePromise;
} else {
promise.polyfill();
}
$(document).ready(() => {
App.start();
});

View File

@ -1,22 +0,0 @@
'use strict';
const Backbone = require('backbone');
const model = Backbone.Model.extend({
idAttribute: 'username',
defaults: function () {
return {
username: '',
password: '',
hint: ''
};
}
});
module.exports = {
Model: model,
Collection: Backbone.Collection.extend({
model: model
})
};

View File

@ -1,35 +0,0 @@
'use strict';
const Backbone = require('backbone');
const model = Backbone.Model.extend({
idAttribute: '_id',
defaults: function () {
return {
type: 'proxy',
hostname: '',
forward_server: '',
forward_host: '',
forward_port: 80,
asset_caching: false,
block_exploits: true,
ssl: false,
ssl_expires: 0,
force_ssl: false,
letsencrypt_email: '',
accept_tos: false,
access_list_id: '',
advanced: '',
incoming_port: 0,
protocols: []
};
}
});
module.exports = {
Model: model,
Collection: Backbone.Collection.extend({
model: model
})
};

View File

@ -1,95 +0,0 @@
const path = require('path');
const webpack = require('webpack');
const Visualizer = require('webpack-visualizer-plugin');
module.exports = {
entry: {
main: './src/frontend/js/main.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.ejs$/,
loader: 'ejs-loader'
}
]
},
/*
context: __dirname + '/src/frontend/js',
entry: './main.js',
output: {
filename: 'main.js',
path: __dirname + '/dist/js',
publicPath: '/js/',
sourceMapFilename: 'dnBOUAwY76qx3MmZxtHn.map'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader'//,
query: {
presets: ['@babel/es2015']
}
},
{
test: /\.ejs$/,
loader: 'ejs-loader'
}
]
},
*/
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
_: 'underscore'
}),
new Visualizer({
filename: '../webpack_stats.html'
}),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1, // Must be greater than or equal to one
minChunkSize: 999999999
})
]
/*
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
_: 'underscore'
}),
new Visualizer({
filename: '../../webpack_stats.html'
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
unsafe: true,
drop_console: false,
drop_debugger: true,
screw_ie8: true,
warnings: false
}
})
]
*/
};