[enh] Working prototype for certificate management interface

This commit is contained in:
Alexandre Aubin 2016-11-20 20:41:14 -05:00
parent 4f28ba4426
commit 35124f9c74
4 changed files with 301 additions and 7 deletions

View file

@ -81,12 +81,26 @@
// Get existing domain info // Get existing domain info
app.get('#/domains/:domain', function (c) { app.get('#/domains/:domain', function (c) {
c.api('/domains/main', function(dataMain) { c.api('/domains/main', function(dataMain) {
domain = { c.api('/apps?installed', function(data) { // http://api.yunohost.org/#!/app/app_list_get_8
name: c.params['domain'],
main: (c.params['domain'] == dataMain.current_main_domain) ? true : false, enable_cert_management_ = true;
url: "https://"+c.params['domain'] $.each(data['apps'], function(k, v) {
} if (v.id == "letsencrypt")
c.view('domain/domain_info', domain); {
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_
};
console.log(domain);
c.view('domain/domain_info', domain);
});
}, 'PUT'); }, 'PUT');
}); });
@ -101,6 +115,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 // Remove existing domain
app.get('#/domains/:domain/delete', function (c) { app.get('#/domains/:domain/delete', function (c) {
c.confirm( c.confirm(

View file

@ -294,5 +294,30 @@
"warning_first_user": "You probably need to <a href='#/users/create' class='alert-link'>create a user</a> first.", "warning_first_user": "You probably need to <a href='#/users/create' class='alert-link'>create a user</a> first.",
"write": "Write", "write": "Write",
"wrong_password": "Wrong password", "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",
"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"
} }

View file

@ -0,0 +1,84 @@
<div class="btn-breadcrumb">
<a href="#/" ><i class="fa-home"></i><span class="sr-only">{{t 'home'}}</span></a>
<a href="#/domains">{{t 'domains'}}</a>
<a href="#/domains/{{name}}">{{name}}</a>
<a href="#/domains/{{name}}/cert-management">{{t 'certificate'}}</a>
</div>
<div class="separator"></div>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<span class="fa-fw fa-lock"></span> {{t 'certificate_status'}}
</h2>
</div>
<div class="panel-body">
<div class="alert alert-{{status.alert_type}}">
<span class="fa-fw fa-{{status.alert_icon}}"></span> {{status.alert_message}}
</div>
<dl class="dl-horizontal">
<dt>{{t 'certificate_authority'}}</dt>
<dd>{{status.CA_type}} ({{status.CA_name}})</dd>
<dt>{{t 'validity'}}</dt>
<dd>{{status.validity}} days</dd>
</dl>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<span class="fa-fw fa-wrench"></span> {{t 'operations'}}
</h2>
</div>
<div class="panel-body">
{{#if actions_enabled.install_letsencrypt}}
<div class="container">
{{#if status.ACME_eligible}}
<p><span class="fa-fw fa-check"></span>
{{t 'domain_is_eligible_for_ACME'}}</p>
{{else}}
<p><span class="fa-fw fa-meh-o"></span>
{{t 'domain_not_eligible_for_ACME'}}</p>
{{/if}}
<a href="#/domains/{{name}}/cert-install-LE" class="btn btn-success {{#unless status.ACME_eligible}}disabled{{/unless}}">
<span class="fa-star"></span> {{t 'install_letsencrypt_cert'}}
</a>
<hr>
</div>
{{/if}}
{{#if actions_enabled.manual_renew_letsencrpt}}
<div class="container">
<p>{{t 'manually_renew_letsencrypt_message'}}</p>
<a href="#/domains/{{name}}/cert-renew-letsencrypt" class="btn btn-warning">
<span class="fa-refresh"></span> {{t 'manually_renew_letsencrypt'}}
</a>
</div>
<hr>
{{/if}}
{{#if actions_enabled.regen_selfsigned}}
<div class="container">
<p>{{t 'regenerate_selfsigned_cert_message'}}</p>
<a href="#/domains/{{name}}/cert-regen-selfsigned" class="btn btn-warning">
<span class="fa-refresh"></span> {{t 'regenerate_selfsigned_cert'}}
</a>
</div>
<hr>
{{/if}}
{{#if actions_enabled.replace_with_selfsigned}}
<div class="container">
<p>{{t 'revert_to_selfsigned_cert_message'}}</p>
<a href="#/domains/{{name}}/cert-replace-with-selfsigned" class="btn btn-danger">
<span class="fa-exclamation-triangle"></span> {{t 'revert_to_selfsigned_cert'}}
</a>
</div>
{{/if}}
</div>
</div>

View file

@ -56,6 +56,19 @@
</a> </a>
</div> </div>
<hr> <hr>
<div class="container">
<p>Gérer le certificat</p>
{{#unless enable_cert_management}}
<p><span class="fa-fw fa-exclamation-circle"></span> The 'letsencrypt'
app is currently installed and conflicts with this feature. Please
uninstall it first to use the new certificate management
interface.</p>
{{/unless}}
<a href="#/domains/{{name}}/cert-management" class="btn btn-default slide {{#unless enable_cert_management}}disabled{{/unless}}">
Certificat SSL <span class="fa-fw fa-lock"></span>
</a>
</div>
<hr>
<div class="container"> <div class="container">
<p>{{t 'domain_delete_longdesc' name}}</p> <p>{{t 'domain_delete_longdesc' name}}</p>
<a href="#/domains/{{name}}/delete" class="btn btn-danger slide back"> <a href="#/domains/{{name}}/delete" class="btn btn-danger slide back">