From 05f6a55a0b4e16e678e20c3b66588122d4c5669e Mon Sep 17 00:00:00 2001 From: chaptergy <26956711+chaptergy@users.noreply.github.com> Date: Tue, 6 Oct 2020 14:49:02 +0200 Subject: [PATCH] Adds frontend improvements and fixes --- frontend/js/app/api.js | 10 ++--- frontend/js/app/nginx/certificates/form.ejs | 18 +++++++-- frontend/js/app/nginx/certificates/form.js | 40 ++++++++++++++----- .../js/app/nginx/certificates/list/item.ejs | 2 +- frontend/js/app/nginx/dead/form.ejs | 5 +++ frontend/js/app/nginx/dead/form.js | 28 +++++++++++-- frontend/js/app/nginx/proxy/form.ejs | 5 +++ frontend/js/app/nginx/proxy/form.js | 28 +++++++++++-- frontend/js/app/nginx/redirection/form.ejs | 5 +++ frontend/js/app/nginx/redirection/form.js | 31 +++++++++++--- frontend/js/i18n/messages.json | 4 +- utils/certbot-dns-plugins.js | 8 +++- 12 files changed, 147 insertions(+), 37 deletions(-) diff --git a/frontend/js/app/api.js b/frontend/js/app/api.js index 74356f0..1d7b358 100644 --- a/frontend/js/app/api.js +++ b/frontend/js/app/api.js @@ -53,7 +53,7 @@ function fetch(verb, path, data, options) { contentType: options.contentType || 'application/json; charset=UTF-8', processData: options.processData || true, crossDomain: true, - timeout: options.timeout ? options.timeout : 30000, + timeout: options.timeout ? options.timeout : 180000, xhrFields: { withCredentials: true }, @@ -586,8 +586,8 @@ module.exports = { /** * @param {Object} data */ - create: function (data) { - return fetch('post', 'nginx/certificates', data); + create: function (data, timeout = 180000) { + return fetch('post', 'nginx/certificates', data, {timeout}); }, /** @@ -630,8 +630,8 @@ module.exports = { * @param {Number} id * @returns {Promise} */ - renew: function (id) { - return fetch('post', 'nginx/certificates/' + id + '/renew'); + renew: function (id, timeout = 180000) { + return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout}); } } }, diff --git a/frontend/js/app/nginx/certificates/form.ejs b/frontend/js/app/nginx/certificates/form.ejs index a3d6c07..4c7a596 100644 --- a/frontend/js/app/nginx/certificates/form.ejs +++ b/frontend/js/app/nginx/certificates/form.ejs @@ -1,12 +1,20 @@ - - <%- i18n('ssl', provider) %><% if (meta.dns_provider) { %> - <% dns_providers[meta.dns_provider].display_name } %> + <%- i18n('ssl', provider) %><% if (meta.dns_provider) { %> - <%- dns_providers[meta.dns_provider].display_name %><% } %> <%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %> diff --git a/frontend/js/app/nginx/dead/form.ejs b/frontend/js/app/nginx/dead/form.ejs index 1d01e09..253c4b6 100644 --- a/frontend/js/app/nginx/dead/form.ejs +++ b/frontend/js/app/nginx/dead/form.ejs @@ -4,6 +4,7 @@ +
+ + <%= i18n('ssl', 'stored-as-plaintext-info') %> +
diff --git a/frontend/js/app/nginx/dead/form.js b/frontend/js/app/nginx/dead/form.js index 393788d..0df24f7 100644 --- a/frontend/js/app/nginx/dead/form.js +++ b/frontend/js/app/nginx/dead/form.js @@ -20,6 +20,7 @@ module.exports = Mn.View.extend({ buttons: '.modal-footer button', cancel: 'button.cancel', save: 'button.save', + le_error_info: '#le-error-info', certificate_select: 'select[name="certificate_id"]', ssl_forced: 'input[name="ssl_forced"]', hsts_enabled: 'input[name="hsts_enabled"]', @@ -116,6 +117,7 @@ module.exports = Mn.View.extend({ 'click @ui.save': function (e) { e.preventDefault(); + this.ui.le_error_info.hide(); if (!this.ui.form[0].checkValidity()) { $('').hide().appendTo(this.ui.form).click().remove(); @@ -130,7 +132,18 @@ module.exports = Mn.View.extend({ data.hsts_subdomains = !!data.hsts_subdomains; data.http2_support = !!data.http2_support; data.ssl_forced = !!data.ssl_forced; - data.meta.dns_challenge = !!data.meta.dns_challenge; + + if (typeof data.meta === 'undefined') data.meta = {}; + data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1; + data.meta.dns_challenge = data.meta.dns_challenge == 1; + + if(!data.meta.dns_challenge){ + data.meta.dns_provider = undefined; + data.meta.dns_provider_credentials = undefined; + data.meta.propagation_seconds = undefined; + } else { + if(data.meta.propagation_seconds === '') data.meta.propagation_seconds = undefined; + } if (typeof data.domain_names === 'string' && data.domain_names) { data.domain_names = data.domain_names.split(','); @@ -151,8 +164,6 @@ module.exports = Mn.View.extend({ alert(i18n('ssl', 'no-wildcard-without-dns')); return; } - - data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1'; } else { data.certificate_id = parseInt(data.certificate_id, 10); } @@ -181,7 +192,15 @@ module.exports = Mn.View.extend({ }); }) .catch(err => { - alert(err.message); + let more_info = ''; + if(err.code === 500){ + try{ + more_info = JSON.parse(err.debug).debug.stack.join("\n"); + } catch(e) {} + } + this.ui.le_error_info[0].innerHTML = `${err.message}${more_info !== '' ? `
${more_info}
`:''}`; + this.ui.le_error_info.show(); + this.ui.le_error_info[0].scrollIntoView(); this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); this.ui.save.removeClass('btn-loading'); }); @@ -225,6 +244,7 @@ module.exports = Mn.View.extend({ }); // Certificates + this.ui.le_error_info.hide(); this.ui.dns_challenge_content.hide(); this.ui.credentials_file_content.hide(); this.ui.letsencrypt.hide(); diff --git a/frontend/js/app/nginx/proxy/form.ejs b/frontend/js/app/nginx/proxy/form.ejs index 34f319c..1a49830 100644 --- a/frontend/js/app/nginx/proxy/form.ejs +++ b/frontend/js/app/nginx/proxy/form.ejs @@ -4,6 +4,7 @@ +
+ + <%= i18n('ssl', 'stored-as-plaintext-info') %> +
diff --git a/frontend/js/app/nginx/proxy/form.js b/frontend/js/app/nginx/proxy/form.js index 4211050..3c17225 100644 --- a/frontend/js/app/nginx/proxy/form.js +++ b/frontend/js/app/nginx/proxy/form.js @@ -29,6 +29,7 @@ module.exports = Mn.View.extend({ save: 'button.save', add_location_btn: 'button.add_location', locations_container: '.locations_container', + le_error_info: '#le-error-info', certificate_select: 'select[name="certificate_id"]', access_list_select: 'select[name="access_list_id"]', ssl_forced: 'input[name="ssl_forced"]', @@ -137,6 +138,7 @@ module.exports = Mn.View.extend({ 'click @ui.save': function (e) { e.preventDefault(); + this.ui.le_error_info.hide(); if (!this.ui.form[0].checkValidity()) { $('').hide().appendTo(this.ui.form).click().remove(); @@ -165,7 +167,18 @@ module.exports = Mn.View.extend({ data.hsts_enabled = !!data.hsts_enabled; data.hsts_subdomains = !!data.hsts_subdomains; data.ssl_forced = !!data.ssl_forced; - data.meta.dns_challenge = !!data.meta.dns_challenge; + + if (typeof data.meta === 'undefined') data.meta = {}; + data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1; + data.meta.dns_challenge = data.meta.dns_challenge == 1; + + if(!data.meta.dns_challenge){ + data.meta.dns_provider = undefined; + data.meta.dns_provider_credentials = undefined; + data.meta.propagation_seconds = undefined; + } else { + if(data.meta.propagation_seconds === '') data.meta.propagation_seconds = undefined; + } if (typeof data.domain_names === 'string' && data.domain_names) { data.domain_names = data.domain_names.split(','); @@ -186,8 +199,6 @@ module.exports = Mn.View.extend({ alert(i18n('ssl', 'no-wildcard-without-dns')); return; } - - data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1'; } else { data.certificate_id = parseInt(data.certificate_id, 10); } @@ -216,7 +227,15 @@ module.exports = Mn.View.extend({ }); }) .catch(err => { - alert(err.message); + let more_info = ''; + if(err.code === 500){ + try{ + more_info = JSON.parse(err.debug).debug.stack.join("\n"); + } catch(e) {} + } + this.ui.le_error_info[0].innerHTML = `${err.message}${more_info !== '' ? `
${more_info}
`:''}`; + this.ui.le_error_info.show(); + this.ui.le_error_info[0].scrollIntoView(); this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); this.ui.save.removeClass('btn-loading'); }); @@ -293,6 +312,7 @@ module.exports = Mn.View.extend({ }); // Certificates + this.ui.le_error_info.hide(); this.ui.dns_challenge_content.hide(); this.ui.credentials_file_content.hide(); this.ui.letsencrypt.hide(); diff --git a/frontend/js/app/nginx/redirection/form.ejs b/frontend/js/app/nginx/redirection/form.ejs index f4e4375..3247233 100644 --- a/frontend/js/app/nginx/redirection/form.ejs +++ b/frontend/js/app/nginx/redirection/form.ejs @@ -4,6 +4,7 @@ +
+ + <%= i18n('ssl', 'stored-as-plaintext-info') %> +
diff --git a/frontend/js/app/nginx/redirection/form.js b/frontend/js/app/nginx/redirection/form.js index c1c6d9d..5ca3b8d 100644 --- a/frontend/js/app/nginx/redirection/form.js +++ b/frontend/js/app/nginx/redirection/form.js @@ -21,6 +21,7 @@ module.exports = Mn.View.extend({ buttons: '.modal-footer button', cancel: 'button.cancel', save: 'button.save', + le_error_info: '#le-error-info', certificate_select: 'select[name="certificate_id"]', ssl_forced: 'input[name="ssl_forced"]', hsts_enabled: 'input[name="hsts_enabled"]', @@ -116,6 +117,7 @@ module.exports = Mn.View.extend({ 'click @ui.save': function (e) { e.preventDefault(); + this.ui.le_error_info.hide(); if (!this.ui.form[0].checkValidity()) { $('').hide().appendTo(this.ui.form).click().remove(); @@ -132,7 +134,18 @@ module.exports = Mn.View.extend({ data.hsts_enabled = !!data.hsts_enabled; data.hsts_subdomains = !!data.hsts_subdomains; data.ssl_forced = !!data.ssl_forced; - data.meta.dns_challenge = !!data.meta.dns_challenge; + + if (typeof data.meta === 'undefined') data.meta = {}; + data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1; + data.meta.dns_challenge = data.meta.dns_challenge == 1; + + if(!data.meta.dns_challenge){ + data.meta.dns_provider = undefined; + data.meta.dns_provider_credentials = undefined; + data.meta.propagation_seconds = undefined; + } else { + if(data.meta.propagation_seconds === '') data.meta.propagation_seconds = undefined; + } if (typeof data.domain_names === 'string' && data.domain_names) { data.domain_names = data.domain_names.split(','); @@ -152,10 +165,7 @@ module.exports = Mn.View.extend({ if (domain_err) { alert(i18n('ssl', 'no-wildcard-without-dns')); return; - } - - data.meta.cloudflare_use = data.meta.cloudflare_use === '1'; - data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1'; + } } else { data.certificate_id = parseInt(data.certificate_id, 10); } @@ -184,7 +194,15 @@ module.exports = Mn.View.extend({ }); }) .catch(err => { - alert(err.message); + let more_info = ''; + if(err.code === 500){ + try{ + more_info = JSON.parse(err.debug).debug.stack.join("\n"); + } catch(e) {} + } + this.ui.le_error_info[0].innerHTML = `${err.message}${more_info !== '' ? `
${more_info}
`:''}`; + this.ui.le_error_info.show(); + this.ui.le_error_info[0].scrollIntoView(); this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); this.ui.save.removeClass('btn-loading'); }); @@ -228,6 +246,7 @@ module.exports = Mn.View.extend({ }); // Certificates + this.ui.le_error_info.hide(); this.ui.dns_challenge_content.hide(); this.ui.credentials_file_content.hide(); this.ui.letsencrypt.hide(); diff --git a/frontend/js/i18n/messages.json b/frontend/js/i18n/messages.json index 8826afa..af3e8cb 100644 --- a/frontend/js/i18n/messages.json +++ b/frontend/js/i18n/messages.json @@ -109,8 +109,10 @@ "please-choose": "Please Choose...", "credentials-file-content": "Credentials File Content", "credentials-file-content-info": "This plugin requires a configuration file containing an API token or other credentials to your provider", + "stored-as-plaintext-info": "This data will be stored as plaintext in the database!", "propagation-seconds": "Propagation Seconds", - "propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation." + "propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation.", + "obtaining-certificate-info": "Obtaining certificate... This might take a few minutes." }, "proxy-hosts": { "title": "Proxy Hosts", diff --git a/utils/certbot-dns-plugins.js b/utils/certbot-dns-plugins.js index 4af678e..ef533c1 100644 --- a/utils/certbot-dns-plugins.js +++ b/utils/certbot-dns-plugins.js @@ -1,5 +1,7 @@ /** * This file contains info about available Certbot DNS plugins. + * This only works for plugins which use the standard argument structure, so: + * --authenticator ---credentials ---propagation-seconds * * File Structure: * @@ -102,13 +104,15 @@ dns_luadns_token = 0123456789abcdef0123456789abcdef`, display_name: "netcup", package_name: "certbot-dns-netcup", package_version: "1.0.0", - credentials: `certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567`, + credentials: `dns_netcup_customer_id = 123456 +dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567 +dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`, full_plugin_name: "certbot-dns-netcup:dns-netcup", }, //####################################################// njalla: { display_name: "Njalla", - package_name: "certbot-dns-nsone", + package_name: "certbot-dns-njalla", package_version: "0.0.4", credentials: `certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567`, full_plugin_name: "certbot-dns-njalla:dns-njalla",