diff --git a/src/js/yunohost/controllers/domains.js b/src/js/yunohost/controllers/domains.js index f9335fe8..e201ef00 100644 --- a/src/js/yunohost/controllers/domains.js +++ b/src/js/yunohost/controllers/domains.js @@ -81,12 +81,29 @@ // Get existing domain info app.get('#/domains/:domain', function (c) { c.api('/domains/main', function(dataMain) { - domain = { - name: c.params['domain'], - main: (c.params['domain'] == dataMain.current_main_domain) ? true : false, - url: "https://"+c.params['domain'] - } - c.view('domain/domain_info', domain); + c.api('/apps?installed', function(data) { // http://api.yunohost.org/#!/app/app_list_get_8 + + // FIXME - This dirty trick (along with the previous API call + // for apps installed) should be removed once letsencrypt_ynh + // is not used by many people anymore. Probably around 07/2017 + // or end of 2017... + enable_cert_management_ = true; + $.each(data['apps'], function(k, v) { + if (v.id == "letsencrypt") + { + enable_cert_management_ = false; + } + }); + + + domain = { + name: c.params['domain'], + main: (c.params['domain'] == dataMain.current_main_domain) ? true : false, + url: "https://"+c.params['domain'], + enable_cert_management: enable_cert_management_ + }; + c.view('domain/domain_info', domain); + }); }, 'PUT'); }); @@ -101,6 +118,164 @@ }); }); + // Domain certificate + app.get('#/domains/:domain/cert-management', function (c) { + c.api('/domains/cert-status/' + c.params['domain'] + '?full', function(data) { + + s = data["certificates"][c.params['domain']] + + status_ = {} + status_.CA_type = s.CA_type.verbose + status_.CA_name = s.CA_name + status_.validity = s.validity + status_.ACME_eligible = s.ACME_eligible + + switch (s.summary.code) + { + case "critical" : + status_.alert_type = "danger"; + status_.alert_icon = "exclamation-circle" ; + status_.alert_message = y18n.t('certificate_alert_not_valid'); + break; + case "warning" : + status_.alert_type = "warning"; + status_.alert_icon = "exclamation-triangle"; + status_.alert_message = y18n.t('certificate_alert_selfsigned'); + break; + case "attention" : + if (status_.CA_type == "lets-encrypt") + { + status_.alert_type = "warning"; + status_.alert_icon = "clock-o"; + status_.alert_message = y18n.t('certificate_alert_letsencrypt_about_to_expire'); + } + else + { + status_.alert_type = "danger"; + status_.alert_icon = "clock-o"; + status_.alert_message = y18n.t('certificate_alert_about_to_expire'); + } + break; + case "good" : + status_.alert_type = "success"; + status_.alert_icon = "check-circle"; + status_.alert_message = y18n.t('certificate_alert_good'); + break; + case "great" : + status_.alert_type = "success"; + status_.alert_icon = "thumbs-up"; + status_.alert_message = y18n.t('certificate_alert_great'); + break; + default : + status_.alert_type = "warning" + status_.alert_icon = "question" + status_.alert_message = y18n.t('certificate_alert_unknown'); + break; + } + + actions_enabled = {}; + actions_enabled.install_letsencrypt = false; + actions_enabled.manual_renew_letsencrpt = false; + actions_enabled.regen_selfsigned = false; + actions_enabled.replace_with_selfsigned = false; + + switch (s.CA_type.code) + { + case "self-signed" : + actions_enabled.install_letsencrypt = true; + actions_enabled.regen_selfsigned = true; + break; + case "lets-encrypt" : + actions_enabled.manual_renew_letsencrpt = true; + actions_enabled.replace_with_selfsigned = true; + break; + default : + actions_enabled.replace_with_selfsigned = true; + break; + } + + data_ = { + name: c.params['domain'], + status: status_, + actions_enabled : actions_enabled + }; + c.view('domain/domain_cert', data_); + }); + }); + + // Install let's encrypt certificate on domain + app.get('#/domains/:domain/cert-install-LE', function (c) { + c.confirm( + y18n.t('certificate'), + y18n.t('confirm_cert_install_LE', [c.params['domain']]), + function(){ + c.api('/domains/cert-install/' + c.params['domain'], function(data) { + store.clear('slide'); + c.redirect('#/domains/'+c.params['domain']+'/cert-management'); + }, 'POST'); + }, + function(){ + store.clear('slide'); + c.redirect('#/domains/'+c.params['domain']+'/cert-management'); + } + ); + }); + + // Regenerate a self-signed certificate + app.get('#/domains/:domain/cert-regen-selfsigned', function (c) { + c.confirm( + y18n.t('certificate'), + y18n.t('confirm_cert_regen_selfsigned', [c.params['domain']]), + function(){ + c.api('/domains/cert-install/' + c.params['domain'] + "?self_signed", function(data) { + store.clear('slide'); + c.redirect('#/domains/'+c.params['domain']+'/cert-management'); + }, 'POST'); + }, + function(){ + store.clear('slide'); + c.redirect('#/domains/'+c.params['domain']+'/cert-management'); + } + ); + }); + + // Manually renew a Let's Encrypt certificate + app.get('#/domains/:domain/cert-renew-letsencrypt', function (c) { + c.confirm( + y18n.t('certificate'), + y18n.t('confirm_cert_manual_renew_LE', [c.params['domain']]), + function(){ + c.api('/domains/cert-renew/' + c.params['domain'] + "?force", function(data) { + store.clear('slide'); + c.redirect('#/domains/'+c.params['domain']+'/cert-management'); + }, 'POST'); + }, + function(){ + store.clear('slide'); + c.redirect('#/domains/'+c.params['domain']+'/cert-management'); + } + ); + }); + + // Replace valid cert with self-signed + app.get('#/domains/:domain/cert-replace-with-selfsigned', function (c) { + c.confirm( + y18n.t('certificate'), + y18n.t('confirm_cert_revert_to_selfsigned', [c.params['domain']]), + function(){ + c.api('/domains/cert-install/' + c.params['domain'] + "?self_signed&force", function(data) { + store.clear('slide'); + c.redirect('#/domains/'+c.params['domain']+'/cert-management'); + }, 'POST'); + }, + function(){ + store.clear('slide'); + c.redirect('#/domains/'+c.params['domain']+'/cert-management'); + } + ); + }); + + // Remove existing domain app.get('#/domains/:domain/delete', function (c) { c.confirm( diff --git a/src/locales/en.json b/src/locales/en.json index 7344d36a..43e2b0fa 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -294,5 +294,33 @@ "warning_first_user": "You probably need to create a user first.", "write": "Write", "wrong_password": "Wrong password", - "yes": "Yes" + "yes": "Yes", + "certificate_alert_not_valid": "CRITICAL : Certificate is not valid ! HTTPS won't work at all !", + "certificate_alert_selfsigned": "WARNING : Current certificate is self-signed. Browsers will display a spooky warning to new visitors !", + "certificate_alert_letsencrypt_about_to_expire": "Attention : Certificate is about to expire. It should soon be renewed automatically.", + "certificate_alert_about_to_expire": "WARNING : Certificate is about to expire ! It will NOT be renewed automatically !", + "certificate_alert_good": "Okay, certificate looks good !", + "certificate_alert_great": "Great ! You're using a valid Let's Encrypt certificate !", + "certificate_alert_unknown": "Unknown status", + "certificate_manage" : "Manage SSL certificate", + "certificate_old_letsencrypt_app_conflict" : "The 'letsencrypt' app is currently installed and conflicts with this feature. Please uninstall it first to use the new certificate management interface.", + "ssl_certificate" : "SSL certificate", + "confirm_cert_install_LE": "Are you sure you want to install a Let's Encrypt certificate for this domain.", + "confirm_cert_regen_selfsigned": "Are you sure you want to regenerate a self-signed certificate for this domain ?", + "confirm_cert_manual_renew_LE": "Are you sure you want to manually renew the Let's Encrypt certificate for this domain now ?", + "confirm_cert_revert_to_selfsigned": "Are you sure you want to revert this domain to a self-signed certificate ?", + "certificate" : "Certificate", + "certificate_status" : "Certificate status", + "certificate_authority" : "Certification authority", + "validity" : "Validity", + "domain_is_eligible_for_ACME" : "This domain seems correctly configured to install a Let's Encrypt certificate !", + "domain_not_eligible_for_ACME" : "This domain doesn't seem ready for a Let's Encrypt certificate. Please check your DNS configuration and HTTP server reachability.", + "install_letsencrypt_cert" : "Install a Let's Encrypt certificate", + "manually_renew_letsencrypt_message" : "Certificate will be automatically renewed during the last 15 days of validity. You can manually renew it if you want to. (Not recommended).", + "manually_renew_letsencrypt" : "Manually renew now", + "regenerate_selfsigned_cert_message" : "If you want, you can regenerate the self-signed certificate.", + "regenerate_selfsigned_cert" : "Regenerate self-signed certificate", + "revert_to_selfsigned_cert_message" : "If you really want to, you can reinstall a self-signed certificate. (Not recommended)", + "revert_to_selfsigned_cert" : "Revert to a self-signed certificate" } + diff --git a/src/views/domain/domain_cert.ms b/src/views/domain/domain_cert.ms new file mode 100644 index 00000000..1ced40de --- /dev/null +++ b/src/views/domain/domain_cert.ms @@ -0,0 +1,84 @@ +
+ {{t 'home'}} + {{t 'domains'}} + {{name}} + {{t 'certificate'}} +
+ +
+ + +
+
+

+ {{t 'certificate_status'}} +

+
+
+ +
+ {{status.alert_message}} +
+ +
+
{{t 'certificate_authority'}}
+
{{status.CA_type}} ({{status.CA_name}})
+
{{t 'validity'}}
+
{{status.validity}} days
+
+
+
+ +
+
+

+ {{t 'operations'}} +

+
+
+ + {{#if actions_enabled.install_letsencrypt}} +
+ {{#if status.ACME_eligible}} +

+ {{t 'domain_is_eligible_for_ACME'}}

+ {{else}} +

+ {{t 'domain_not_eligible_for_ACME'}}

+ {{/if}} + + {{t 'install_letsencrypt_cert'}} + +
+
+ {{/if}} + {{#if actions_enabled.manual_renew_letsencrpt}} +
+

{{t 'manually_renew_letsencrypt_message'}}

+ + {{t 'manually_renew_letsencrypt'}} + +
+
+ {{/if}} + {{#if actions_enabled.regen_selfsigned}} +
+

{{t 'regenerate_selfsigned_cert_message'}}

+ + {{t 'regenerate_selfsigned_cert'}} + +
+
+ {{/if}} + {{#if actions_enabled.replace_with_selfsigned}} +
+

{{t 'revert_to_selfsigned_cert_message'}}

+ + {{t 'revert_to_selfsigned_cert'}} + +
+ {{/if}} +
+
+ + diff --git a/src/views/domain/domain_info.ms b/src/views/domain/domain_info.ms index e49c97fe..e830ea3b 100644 --- a/src/views/domain/domain_info.ms +++ b/src/views/domain/domain_info.ms @@ -56,6 +56,18 @@
+
+

{{t 'certificate_manage'}}

+ {{#unless enable_cert_management}} +

+ {{t 'certificate_old_letsencrypt_app_conflict'}} +

+ {{/unless}} + + {{t 'ssl_certificate'}} + +
+

{{t 'domain_delete_longdesc' name}}