|
@@ -9,7 +9,7 @@
|
|
|
.disabled.table{
|
|
|
opacity: 0.5;
|
|
|
pointer-events: none;
|
|
|
- user-select: none;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
.expiredDomain{
|
|
@@ -32,9 +32,18 @@
|
|
|
</div>
|
|
|
<div class="ui basic segment">
|
|
|
<div class="ui toggle checkbox">
|
|
|
- <input type="checkbox" id="enableCertAutoRenew" checked>
|
|
|
+ <input type="checkbox" id="enableCertAutoRenew">
|
|
|
<label>Enable Certificate Auto Renew</label>
|
|
|
</div>
|
|
|
+ <br>
|
|
|
+ <h3>ACME Email</h3>
|
|
|
+ <p>Email is generally required for renewing via ACME. Zoraxy do not support no-email renew due to security reasons.</p>
|
|
|
+ <div class="ui fluid action input">
|
|
|
+ <input id="caRegisterEmail" type="text" placeholder="[email protected]">
|
|
|
+ <button class="ui icon basic button">
|
|
|
+ <i class="blue save icon"></i>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div class="ui yellow message">
|
|
|
Certificate Renew only works on the certification authority (CA) supported by Zoraxy. Check Zoraxy wiki for more information on supported list of CAs.
|
|
@@ -50,7 +59,8 @@
|
|
|
<div class="ui toggle checkbox">
|
|
|
<input type="checkbox" id="renewAllSupported" onchange="setAutoRenewIfCASupportMode(this.checked);" checked>
|
|
|
<label>Auto renew if CA is supported</label>
|
|
|
- </div>
|
|
|
+ </div><br>
|
|
|
+ <button class="ui basic right floated button" style="margin-top: -2em;"><i class="yellow refresh icon"></i> Renew Now</button>
|
|
|
<div class="ui horizontal divider"> OR </div>
|
|
|
<p>Select the certificates to automatic renew in the list below</p>
|
|
|
<table id="domainCertFileTable" class="ui very compact unstackable basic disabled table">
|
|
@@ -63,8 +73,9 @@
|
|
|
</thead>
|
|
|
<tbody id="domainTableBody"></tbody>
|
|
|
</table>
|
|
|
+ <small><i class="ui red info circle icon"></i> Domain in red are expired</small><br>
|
|
|
<button class="ui basic right floated button"><i class="blue save icon"></i> Save Changes</button>
|
|
|
- <button class="ui basic right floated button"><i class="yellow refresh icon"></i> Renew All</button>
|
|
|
+ <button class="ui basic right floated button"><i class="yellow refresh icon"></i> Renew Selected</button>
|
|
|
<br><br>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -74,17 +85,21 @@
|
|
|
<p>Pick a certificate below to force renew</p>
|
|
|
<div class="ui form">
|
|
|
<div class="field">
|
|
|
- <label>Domains</label>
|
|
|
- <input id="domainsInput" type="text" placeholder="example.com">
|
|
|
- <small>If you have more than one domain in a single certificate, enter the domains separated by commas (e.g. test.example.com,example.com)</small>
|
|
|
+ <label>Domain(s)</label>
|
|
|
+ <input id="domainsInput" type="text" placeholder="example.com" onkeyup="checkIfInputDomainIsMultiple();">
|
|
|
+ <small>If you have more than one domain in a single certificate, enter the domains separated by commas (e.g. s1.dev.example.com,s2.dev.example.com)</small>
|
|
|
</div>
|
|
|
- <div class="field">
|
|
|
- <label>Filename</label>
|
|
|
- <input id="filenameInput" type="text" placeholder="Enter filename">
|
|
|
+ <div class="field multiDomainOnly" style="display:none;">
|
|
|
+ <label>Matching Rule</label>
|
|
|
+ <input id="filenameInput" type="text" placeholder="Enter filename (no file extension)">
|
|
|
+ <small>Matching rule to let Zoraxy pick which certificate to use (Also be used as filename). Usually is the longest common suffix of the entered addresses. (e.g. dev.example.com)</small>
|
|
|
+ </div>
|
|
|
+ <div class="field multiDomainOnly" style="display:none;">
|
|
|
+ <button class="ui basic fluid button" onclick="autoDetectMatchingRules();">Auto Detect Matching Rule</button>
|
|
|
</div>
|
|
|
<div class="field">
|
|
|
<label>Certificate Authority (CA)</label>
|
|
|
- <div class="ui selection dropdown">
|
|
|
+ <div class="ui selection dropdown" id="ca">
|
|
|
<input type="hidden" name="ca">
|
|
|
<i class="dropdown icon"></i>
|
|
|
<div class="default text">Let's Encrypt</div>
|
|
@@ -92,7 +107,7 @@
|
|
|
<div class="item" data-value="Let's Encrypt">Let's Encrypt</div>
|
|
|
<div class="item" data-value="Buypass">Buypass</div>
|
|
|
<div class="item" data-value="ZeroSSL">ZeroSSL</div>
|
|
|
- <div class="item" data-value="Google">Google</div>
|
|
|
+ <!-- <div class="item" data-value="Google">Google</div> -->
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -193,13 +208,26 @@
|
|
|
function obtainCertificate() {
|
|
|
var domains = $("#domainsInput").val();
|
|
|
var filename = $("#filenameInput").val();
|
|
|
-
|
|
|
+ if (filename.trim() == "" && !domains.includes(",")){
|
|
|
+ //Zoraxy filename are the matching name for domains.
|
|
|
+ //Use the same as domains
|
|
|
+ filename = domains;
|
|
|
+ }else if (filename != "" && !domains.includes(",")){
|
|
|
+ //Invalid settings. Force the filename to be same as domain
|
|
|
+ //if there are only 1 domain
|
|
|
+ filename = domains;
|
|
|
+ }else{
|
|
|
+ parent.msgbox("Filename cannot be empty for certs containing multiple domains.")
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var ca = $("#ca").dropdown("get value");
|
|
|
$.ajax({
|
|
|
url: "/api/acme/obtainCert",
|
|
|
method: "GET",
|
|
|
data: {
|
|
|
domains: domains,
|
|
|
- filename: filename
|
|
|
+ filename: filename,
|
|
|
+ ca: ca,
|
|
|
},
|
|
|
success: function(response) {
|
|
|
if (response.error) {
|
|
@@ -210,6 +238,9 @@
|
|
|
console.log("Certificate renewed successfully");
|
|
|
// Show success message
|
|
|
parent.msgbox("Certificate renewed successfully");
|
|
|
+
|
|
|
+ // Renew the parent certificate list
|
|
|
+ parent.initManagedDomainCertificateList();
|
|
|
}
|
|
|
},
|
|
|
error: function(error) {
|
|
@@ -218,6 +249,69 @@
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ function checkIfInputDomainIsMultiple(){
|
|
|
+ var inputDomains = $("#domainsInput").val();
|
|
|
+ if (inputDomains.includes(",")){
|
|
|
+ $(".multiDomainOnly").show();
|
|
|
+ }else{
|
|
|
+ $(".multiDomainOnly").hide();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function autoDetectMatchingRules(){
|
|
|
+ var domainsString = $("#domainsInput").val();
|
|
|
+ if (!domainsString.includes(",")){
|
|
|
+ return domainsString;
|
|
|
+ }
|
|
|
+
|
|
|
+ let domains = domainsString.split(",");
|
|
|
+
|
|
|
+ //Clean out any spacing between commas
|
|
|
+ for (var i = 0; i < domains.length; i++){
|
|
|
+ domains[i] = domains[i].trim();
|
|
|
+ }
|
|
|
+
|
|
|
+ function getLongestCommonSuffix(strings) {
|
|
|
+ if (strings.length === 0) {
|
|
|
+ return ''; // Return an empty string if the array is empty
|
|
|
+ }
|
|
|
+
|
|
|
+ var sortedStrings = strings.slice().sort(); // Create a sorted copy of the array
|
|
|
+
|
|
|
+ var firstString = sortedStrings[0];
|
|
|
+ var lastString = sortedStrings[sortedStrings.length - 1];
|
|
|
+
|
|
|
+ var suffix = '';
|
|
|
+ var minLength = Math.min(firstString.length, lastString.length);
|
|
|
+
|
|
|
+ for (var i = 0; i < minLength; i++) {
|
|
|
+ if (firstString[firstString.length - 1 - i] !== lastString[lastString.length - 1 - i]) {
|
|
|
+ break; // Stop iterating if characters don't match
|
|
|
+ }
|
|
|
+ suffix = firstString[firstString.length - 1 - i] + suffix;
|
|
|
+ }
|
|
|
+
|
|
|
+ return suffix;
|
|
|
+ }
|
|
|
+
|
|
|
+ let longestSuffix = getLongestCommonSuffix(domains);
|
|
|
+
|
|
|
+ //Check if the suffix is a valid domain
|
|
|
+ if (longestSuffix.substr(0,1) == "."){
|
|
|
+ //Trim off the first dot
|
|
|
+ longestSuffix = longestSuffix.substr(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!longestSuffix.includes(".")){
|
|
|
+ parent.msgbox("Auto Detect failed: Multiple Domains", false, 5000);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $("#filenameInput").val(longestSuffix);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //Clear up the input field when page load
|
|
|
+ $("#filenameInput").val("");
|
|
|
</script>
|
|
|
</body>
|
|
|
</html>
|