diff --git a/.version b/.version index 54f72863f..3800eed08 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.9.15 +2.9.16 diff --git a/README.md b/README.md index 903e243df..ad5dfc2ac 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@



- + @@ -517,6 +517,12 @@ Special thanks to the following contributors:
Troy Kelly + + + +
Ivan Kristianto +
+ diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index 351b9b3de..7c8fddeea 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -388,7 +388,7 @@ const internalCertificate = { zipFiles(source, out) { const archive = archiver('zip', { zlib: { level: 9 } }); const stream = fs.createWriteStream(out); - + return new Promise((resolve, reject) => { source .map((fl) => { @@ -399,7 +399,7 @@ const internalCertificate = { archive .on('error', (err) => reject(err)) .pipe(stream); - + stream.on('close', () => resolve()); archive.finalize(); }); @@ -477,7 +477,7 @@ const internalCertificate = { // Query is used for searching if (typeof search_query === 'string') { query.where(function () { - this.where('name', 'like', '%' + search_query + '%'); + this.where('nice_name', 'like', '%' + search_query + '%'); }); } @@ -1140,7 +1140,7 @@ const internalCertificate = { if (domains.length === 0) { throw new error.InternalValidationError('No domains provided'); } - + // Create a test challenge file const testChallengeDir = '/data/letsencrypt-acme-challenge/.well-known/acme-challenge'; const testChallengeFile = testChallengeDir + '/test-challenge'; @@ -1215,7 +1215,7 @@ const internalCertificate = { // Remove the test challenge file fs.unlinkSync(testChallengeFile); - + return results; } }; diff --git a/docker/Dockerfile b/docker/Dockerfile index a976ade2c..378fffbfc 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -46,6 +46,11 @@ RUN rm -rf /etc/services.d/frontend /etc/nginx/conf.d/dev.conf # Change permission of logrotate config file RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager +# fix for pip installs +# https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1769 +RUN pip uninstall --yes setuptools \ + && pip install "setuptools==58.0.0" + VOLUME [ "/data", "/etc/letsencrypt" ] ENTRYPOINT [ "/init" ] diff --git a/docs/package.json b/docs/package.json index bd78e883a..dc28e5a0b 100644 --- a/docs/package.json +++ b/docs/package.json @@ -357,7 +357,7 @@ "jsbn": "^1.1.0", "jsesc": "^3.0.1", "json-parse-better-errors": "^1.0.2", - "json-schema": "^0.2.5", + "json-schema": "^0.4.0", "json-schema-traverse": "^0.4.1", "json-stringify-safe": "^5.0.1", "json3": "^3.3.3", diff --git a/docs/setup/README.md b/docs/setup/README.md index 8fdad3b1d..b9c422747 100644 --- a/docs/setup/README.md +++ b/docs/setup/README.md @@ -107,7 +107,7 @@ you don't have to worry about doing anything special and you can follow the comm Check out the [dockerhub tags](https://hub.docker.com/r/jc21/nginx-proxy-manager/tags) for a list of supported architectures and if you want one that doesn't exist, -[create a feature request](https://github.com/jc21/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=). +[create a feature request](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=). Also, if you don't know how to already, follow [this guide to install docker and docker-compose](https://manre-universe.net/how-to-run-docker-and-docker-compose-on-raspbian/) on Raspbian. diff --git a/docs/yarn.lock b/docs/yarn.lock index c051c9436..f84c421d4 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -4117,6 +4117,13 @@ fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-xml-parser@^3.19.0: + version "3.21.1" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz#152a1d51d445380f7046b304672dd55d15c9e736" + integrity sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg== + dependencies: + strnum "^1.0.4" + fastq@^1.6.0: version "1.8.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" @@ -4259,9 +4266,9 @@ flush-write-stream@^2.0.0: readable-stream "^3.1.1" follow-redirects@^1.0.0, follow-redirects@^1.12.1: - version "1.14.7" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" - integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== + version "1.14.8" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" + integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== for-in@^1.0.2: version "1.0.2" @@ -5535,11 +5542,11 @@ is-svg@^3.0.0: html-comment-regex "^1.1.0" is-svg@^4.2.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-4.2.2.tgz#a4ea0f3f78dada7085db88f1e85b6f845626cfae" - integrity sha512-JlA7Mc7mfWjdxxTkJ094oUK9amGD7gQaj5xA/NCY0vlVvZ1stmj4VX+bRuwOMN93IHRZ2ctpPH/0FO6DqvQ5Rw== + version "4.3.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-4.3.0.tgz#3e46a45dcdb2780e42a3c8538154d7f7bfc07216" + integrity sha512-Np3TOGLVr0J27VDaS/gVE7bT45ZcSmX4pMmMTsPjqO8JY383fuPIcWmZr3QsHVWhqhZWxSdmW+tkkl3PWOB0Nw== dependencies: - html-comment-regex "^1.1.2" + fast-xml-parser "^3.19.0" is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.3" @@ -5719,10 +5726,10 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= -json-schema@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.5.tgz#97997f50972dd0500214e208c407efa4b5d7063b" - integrity sha512-gWJOWYFrhQ8j7pVm0EM8Slr+EPVq1Phf6lvzvD/WCeqkrx/f2xBI0xOsRRS9xCn3I4vKtP519dvs3TP09r24wQ== +json-schema@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" @@ -9085,6 +9092,11 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strnum@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + stylehacks@^4.0.0, stylehacks@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" diff --git a/frontend/js/app/audit-log/main.ejs b/frontend/js/app/audit-log/main.ejs index acaa8b490..8d182b595 100644 --- a/frontend/js/app/audit-log/main.ejs +++ b/frontend/js/app/audit-log/main.ejs @@ -2,6 +2,16 @@

<%- i18n('audit-log', 'title') %>

+
+ +
diff --git a/frontend/js/app/audit-log/main.js b/frontend/js/app/audit-log/main.js index ec9b53682..0d03c5ca8 100644 --- a/frontend/js/app/audit-log/main.js +++ b/frontend/js/app/audit-log/main.js @@ -12,39 +12,68 @@ module.exports = Mn.View.extend({ ui: { list_region: '.list-region', - dimmer: '.dimmer' + dimmer: '.dimmer', + search: '.search-form', + query: 'input[name="source-query"]' + }, + + fetch: App.Api.AuditLog.getAll, + + showData: function(response) { + this.showChildView('list_region', new ListView({ + collection: new AuditLogModel.Collection(response) + })); + }, + + showError: function(err) { + this.showChildView('list_region', new ErrorView({ + code: err.code, + message: err.message, + retry: function () { + App.Controller.showAuditLog(); + } + })); + + console.error(err); + }, + + showEmpty: function() { + this.showChildView('list_region', new EmptyView({ + title: App.i18n('audit-log', 'empty'), + subtitle: App.i18n('audit-log', 'empty-subtitle') + })); }, regions: { list_region: '@ui.list_region' }, + events: { + 'submit @ui.search': function (e) { + e.preventDefault(); + let query = this.ui.query.val(); + + this.fetch(['user'], query) + .then(response => this.showData(response)) + .catch(err => { + this.showError(err); + }); + } + }, + onRender: function () { let view = this; - App.Api.AuditLog.getAll(['user']) + view.fetch(['user']) .then(response => { if (!view.isDestroyed() && response && response.length) { - view.showChildView('list_region', new ListView({ - collection: new AuditLogModel.Collection(response) - })); + view.showData(response); } else { - view.showChildView('list_region', new EmptyView({ - title: App.i18n('audit-log', 'empty'), - subtitle: App.i18n('audit-log', 'empty-subtitle') - })); + view.showEmpty(); } }) .catch(err => { - view.showChildView('list_region', new ErrorView({ - code: err.code, - message: err.message, - retry: function () { - App.Controller.showAuditLog(); - } - })); - - console.error(err); + view.showError(err); }) .then(() => { view.ui.dimmer.removeClass('active'); diff --git a/frontend/js/app/nginx/access/main.ejs b/frontend/js/app/nginx/access/main.ejs index c245ff4ae..975859364 100644 --- a/frontend/js/app/nginx/access/main.ejs +++ b/frontend/js/app/nginx/access/main.ejs @@ -3,6 +3,14 @@

<%- i18n('access-lists', 'title') %>

+ <% if (showAddButton) { %> <%- i18n('access-lists', 'add') %> diff --git a/frontend/js/app/nginx/access/main.js b/frontend/js/app/nginx/access/main.js index d14a9eb49..513f58659 100644 --- a/frontend/js/app/nginx/access/main.js +++ b/frontend/js/app/nginx/access/main.js @@ -14,7 +14,44 @@ module.exports = Mn.View.extend({ list_region: '.list-region', add: '.add-item', help: '.help', - dimmer: '.dimmer' + dimmer: '.dimmer', + search: '.search-form', + query: 'input[name="source-query"]' + }, + + fetch: App.Api.Nginx.AccessLists.getAll, + + showData: function(response) { + this.showChildView('list_region', new ListView({ + collection: new AccessListModel.Collection(response) + })); + }, + + showError: function(err) { + this.showChildView('list_region', new ErrorView({ + code: err.code, + message: err.message, + retry: function () { + App.Controller.showNginxAccess(); + } + })); + + console.error(err); + }, + + showEmpty: function() { + let manage = App.Cache.User.canManage('access_lists'); + + this.showChildView('list_region', new EmptyView({ + title: App.i18n('access-lists', 'empty'), + subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}), + link: manage ? App.i18n('access-lists', 'add') : null, + btn_color: 'teal', + permission: 'access_lists', + action: function () { + App.Controller.showNginxAccessListForm(); + } + })); }, regions: { @@ -30,6 +67,17 @@ module.exports = Mn.View.extend({ 'click @ui.help': function (e) { e.preventDefault(); App.Controller.showHelp(App.i18n('access-lists', 'help-title'), App.i18n('access-lists', 'help-content')); + }, + + 'submit @ui.search': function (e) { + e.preventDefault(); + let query = this.ui.query.val(); + + this.fetch(['owner', 'items', 'clients'], query) + .then(response => this.showData(response)) + .catch(err => { + this.showError(err); + }); } }, @@ -40,39 +88,18 @@ module.exports = Mn.View.extend({ onRender: function () { let view = this; - App.Api.Nginx.AccessLists.getAll(['owner', 'items', 'clients']) + view.fetch(['owner', 'items', 'clients']) .then(response => { if (!view.isDestroyed()) { if (response && response.length) { - view.showChildView('list_region', new ListView({ - collection: new AccessListModel.Collection(response) - })); + view.showData(response); } else { - let manage = App.Cache.User.canManage('access_lists'); - - view.showChildView('list_region', new EmptyView({ - title: App.i18n('access-lists', 'empty'), - subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}), - link: manage ? App.i18n('access-lists', 'add') : null, - btn_color: 'teal', - permission: 'access_lists', - action: function () { - App.Controller.showNginxAccessListForm(); - } - })); + view.showEmpty(); } } }) .catch(err => { - view.showChildView('list_region', new ErrorView({ - code: err.code, - message: err.message, - retry: function () { - App.Controller.showNginxAccess(); - } - })); - - console.error(err); + view.showError(err); }) .then(() => { view.ui.dimmer.removeClass('active'); diff --git a/frontend/js/app/nginx/certificates/main.ejs b/frontend/js/app/nginx/certificates/main.ejs index cc3624d54..dbd6fa85d 100644 --- a/frontend/js/app/nginx/certificates/main.ejs +++ b/frontend/js/app/nginx/certificates/main.ejs @@ -3,6 +3,14 @@

<%- i18n('certificates', 'title') %>

+ <% if (showAddButton) { %>