mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-11-04 01:15:14 +00:00 
			
		
		
		
	v2.1.0 (#293)
* Fix wrapping when too many hosts are shown (#207) * Update npm packages, fixes CVE-2019-10757 * Revert some breaking packages * Major overhaul - Docker buildx support in CI - Cypress API Testing in CI - Restructured folder layout (insert clean face meme) - Added Swagger documentation and validate API against that (to be completed) - Use common base image for all supported archs, which includes updated nginx with ipv6 support - Updated certbot and changes required for it - Large amount of Hosts names will wrap in UI - Updated packages for frontend - Version bump 2.1.0 * Updated documentation * Fix JWT expire time going crazy. Now set to 1day * Backend JS formatting rules * Remove v1 importer, I doubt anyone is using v1 anymore * Added backend formatting rules and enforce them in Jenkins builds * Fix CI, doesn't need a tty * Thanks bcrypt. Why can't you just be normal. * Cleanup after syntax check Co-authored-by: Marcelo Castagna <margaale@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										53
									
								
								frontend/js/app/settings/default-site/main.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								frontend/js/app/settings/default-site/main.ejs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
<div class="modal-content">
 | 
			
		||||
    <div class="modal-header">
 | 
			
		||||
        <h5 class="modal-title"><%- i18n('settings', id) %></h5>
 | 
			
		||||
        <button type="button" class="close cancel" aria-label="Close" data-dismiss="modal"> </button>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="modal-body">
 | 
			
		||||
        <form>
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                <div class="col-sm-12 col-md-12">
 | 
			
		||||
                    <div class="form-group">
 | 
			
		||||
                        <div class="form-label"><%- description %></div>
 | 
			
		||||
                        <div class="custom-controls-stacked">
 | 
			
		||||
                            <label class="custom-control custom-radio">
 | 
			
		||||
                                <input class="custom-control-input" name="value" value="congratulations" type="radio" required <%- value === 'congratulations' ? 'checked' : '' %>>
 | 
			
		||||
                                <div class="custom-control-label"><%- i18n('settings', 'default-site-congratulations') %></div>
 | 
			
		||||
                            </label>
 | 
			
		||||
                            <label class="custom-control custom-radio">
 | 
			
		||||
                                <input class="custom-control-input" name="value" value="404" type="radio" required <%- value === '404' ? 'checked' : '' %>>
 | 
			
		||||
                                <div class="custom-control-label"><%- i18n('settings', 'default-site-404') %></div>
 | 
			
		||||
                            </label>
 | 
			
		||||
                            <label class="custom-control custom-radio">
 | 
			
		||||
                                <input class="custom-control-input" name="value" value="redirect" type="radio" required <%- value === 'redirect' ? 'checked' : '' %>>
 | 
			
		||||
                                <div class="custom-control-label"><%- i18n('settings', 'default-site-redirect') %></div>
 | 
			
		||||
                            </label>
 | 
			
		||||
                            <label class="custom-control custom-radio">
 | 
			
		||||
                                <input class="custom-control-input" name="value" value="html" type="radio" required <%- value === 'html' ? 'checked' : '' %>>
 | 
			
		||||
                                <div class="custom-control-label"><%- i18n('settings', 'default-site-html') %></div>
 | 
			
		||||
                            </label>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div class="col-sm-12 col-md-12 option-item option-redirect">
 | 
			
		||||
                    <div class="form-group">
 | 
			
		||||
                        <div class="form-label">Redirect to</div>
 | 
			
		||||
                        <input class="form-control redirect-input" name="meta[redirect]" placeholder="https://" type="url" value="<%- meta && typeof meta.redirect !== 'undefined' ? meta.redirect : '' %>">
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div class="col-sm-12 col-md-12 option-item option-html">
 | 
			
		||||
                    <div class="form-group">
 | 
			
		||||
                        <div class="form-label">HTML Content</div>
 | 
			
		||||
                        <textarea class="form-control text-monospace html-content" name="meta[html]" rows="6" placeholder="<!-- Enter your HTML here -->"><%- meta && typeof meta.html !== 'undefined' ? meta.html : '' %></textarea>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </form>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="modal-footer">
 | 
			
		||||
        <button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
 | 
			
		||||
        <button type="button" class="btn btn-teal save"><%- i18n('str', 'save') %></button>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										69
									
								
								frontend/js/app/settings/default-site/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								frontend/js/app/settings/default-site/main.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
const Mn       = require('backbone.marionette');
 | 
			
		||||
const App      = require('../../main');
 | 
			
		||||
const template = require('./main.ejs');
 | 
			
		||||
 | 
			
		||||
require('jquery-serializejson');
 | 
			
		||||
require('selectize');
 | 
			
		||||
 | 
			
		||||
module.exports = Mn.View.extend({
 | 
			
		||||
    template:  template,
 | 
			
		||||
    className: 'modal-dialog',
 | 
			
		||||
 | 
			
		||||
    ui: {
 | 
			
		||||
        form:     'form',
 | 
			
		||||
        buttons:  '.modal-footer button',
 | 
			
		||||
        cancel:   'button.cancel',
 | 
			
		||||
        save:     'button.save',
 | 
			
		||||
        options:  '.option-item',
 | 
			
		||||
        value:    'input[name="value"]',
 | 
			
		||||
        redirect: '.redirect-input',
 | 
			
		||||
        html:     '.html-content'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    events: {
 | 
			
		||||
        'change @ui.value': function (e) {
 | 
			
		||||
            let val = this.ui.value.filter(':checked').val();
 | 
			
		||||
            this.ui.options.hide();
 | 
			
		||||
            this.ui.options.filter('.option-' + val).show();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        'click @ui.save': function (e) {
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
 | 
			
		||||
            let val = this.ui.value.filter(':checked').val();
 | 
			
		||||
 | 
			
		||||
            // Clear redirect field before validation
 | 
			
		||||
            if (val !== 'redirect') {
 | 
			
		||||
                this.ui.redirect.val('').attr('required', false);
 | 
			
		||||
            } else {
 | 
			
		||||
                this.ui.redirect.attr('required', true);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.ui.html.attr('required', val === 'html');
 | 
			
		||||
 | 
			
		||||
            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();
 | 
			
		||||
            data.id  = this.model.get('id');
 | 
			
		||||
 | 
			
		||||
            this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
 | 
			
		||||
            App.Api.Settings.update(data)
 | 
			
		||||
                .then(result => {
 | 
			
		||||
                    view.model.set(result);
 | 
			
		||||
                    App.UI.closeModal();
 | 
			
		||||
                })
 | 
			
		||||
                .catch(err => {
 | 
			
		||||
                    alert(err.message);
 | 
			
		||||
                    this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onRender: function () {
 | 
			
		||||
        this.ui.value.trigger('change');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										21
									
								
								frontend/js/app/settings/list/item.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								frontend/js/app/settings/list/item.ejs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
<td>
 | 
			
		||||
    <div><%- name %></div>
 | 
			
		||||
    <div class="small text-muted">
 | 
			
		||||
        <%- description %>
 | 
			
		||||
    </div>
 | 
			
		||||
</td>
 | 
			
		||||
<td>
 | 
			
		||||
    <div>
 | 
			
		||||
        <% if (id === 'default-site') { %>
 | 
			
		||||
            <%- i18n('settings', 'default-site-' + value) %>
 | 
			
		||||
        <% } %>
 | 
			
		||||
    </div>
 | 
			
		||||
</td>
 | 
			
		||||
<td class="text-right">
 | 
			
		||||
    <div class="item-action dropdown">
 | 
			
		||||
        <a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
 | 
			
		||||
        <div class="dropdown-menu dropdown-menu-right">
 | 
			
		||||
            <a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</td>
 | 
			
		||||
							
								
								
									
										23
									
								
								frontend/js/app/settings/list/item.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								frontend/js/app/settings/list/item.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
const Mn       = require('backbone.marionette');
 | 
			
		||||
const App      = require('../../main');
 | 
			
		||||
const template = require('./item.ejs');
 | 
			
		||||
 | 
			
		||||
module.exports = Mn.View.extend({
 | 
			
		||||
    template: template,
 | 
			
		||||
    tagName:  'tr',
 | 
			
		||||
 | 
			
		||||
    ui: {
 | 
			
		||||
        edit: 'a.edit'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    events: {
 | 
			
		||||
        'click @ui.edit': function (e) {
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
            App.Controller.showSettingForm(this.model);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    initialize: function () {
 | 
			
		||||
        this.listenTo(this.model, 'change', this.render);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										8
									
								
								frontend/js/app/settings/list/main.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								frontend/js/app/settings/list/main.ejs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
<thead>
 | 
			
		||||
    <th><%- i18n('str', 'name') %></th>
 | 
			
		||||
    <th><%- i18n('str', 'value') %></th>
 | 
			
		||||
    <th> </th>
 | 
			
		||||
</thead>
 | 
			
		||||
<tbody>
 | 
			
		||||
    <!-- items -->
 | 
			
		||||
</tbody>
 | 
			
		||||
							
								
								
									
										27
									
								
								frontend/js/app/settings/list/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								frontend/js/app/settings/list/main.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
const Mn       = require('backbone.marionette');
 | 
			
		||||
const ItemView = require('./item');
 | 
			
		||||
const template = require('./main.ejs');
 | 
			
		||||
 | 
			
		||||
const TableBody = Mn.CollectionView.extend({
 | 
			
		||||
    tagName:   'tbody',
 | 
			
		||||
    childView: ItemView
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = Mn.View.extend({
 | 
			
		||||
    tagName:   'table',
 | 
			
		||||
    className: 'table table-hover table-outline table-vcenter card-table',
 | 
			
		||||
    template:  template,
 | 
			
		||||
 | 
			
		||||
    regions: {
 | 
			
		||||
        body: {
 | 
			
		||||
            el:             'tbody',
 | 
			
		||||
            replaceElement: true
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onRender: function () {
 | 
			
		||||
        this.showChildView('body', new TableBody({
 | 
			
		||||
            collection: this.collection
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										14
									
								
								frontend/js/app/settings/main.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								frontend/js/app/settings/main.ejs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
<div class="card">
 | 
			
		||||
    <div class="card-status bg-teal"></div>
 | 
			
		||||
    <div class="card-header">
 | 
			
		||||
        <h3 class="card-title"><%- i18n('settings', 'title') %></h3>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="card-body no-padding min-100">
 | 
			
		||||
        <div class="dimmer active">
 | 
			
		||||
            <div class="loader"></div>
 | 
			
		||||
            <div class="dimmer-content list-region">
 | 
			
		||||
                <!-- List Region -->
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										48
									
								
								frontend/js/app/settings/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								frontend/js/app/settings/main.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
const Mn           = require('backbone.marionette');
 | 
			
		||||
const App          = require('../main');
 | 
			
		||||
const SettingModel = require('../../models/setting');
 | 
			
		||||
const ListView     = require('./list/main');
 | 
			
		||||
const ErrorView    = require('../error/main');
 | 
			
		||||
const template     = require('./main.ejs');
 | 
			
		||||
 | 
			
		||||
module.exports = Mn.View.extend({
 | 
			
		||||
    id:       'settings',
 | 
			
		||||
    template: template,
 | 
			
		||||
 | 
			
		||||
    ui: {
 | 
			
		||||
        list_region: '.list-region',
 | 
			
		||||
        add:         '.add-item',
 | 
			
		||||
        dimmer:      '.dimmer'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    regions: {
 | 
			
		||||
        list_region: '@ui.list_region'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onRender: function () {
 | 
			
		||||
        let view = this;
 | 
			
		||||
 | 
			
		||||
        App.Api.Settings.getAll()
 | 
			
		||||
            .then(response => {
 | 
			
		||||
                if (!view.isDestroyed() && response && response.length) {
 | 
			
		||||
                    view.showChildView('list_region', new ListView({
 | 
			
		||||
                        collection: new SettingModel.Collection(response)
 | 
			
		||||
                    }));
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            .catch(err => {
 | 
			
		||||
                view.showChildView('list_region', new ErrorView({
 | 
			
		||||
                    code:    err.code,
 | 
			
		||||
                    message: err.message,
 | 
			
		||||
                    retry:   function () {
 | 
			
		||||
                        App.Controller.showSettings();
 | 
			
		||||
                    }
 | 
			
		||||
                }));
 | 
			
		||||
 | 
			
		||||
                console.error(err);
 | 
			
		||||
            })
 | 
			
		||||
            .then(() => {
 | 
			
		||||
                view.ui.dimmer.removeClass('active');
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
		Reference in New Issue
	
	Block a user