diff --git a/www/caddy/pkg-descr b/www/caddy/pkg-descr
index 4f4a41636..378f12b86 100644
--- a/www/caddy/pkg-descr
+++ b/www/caddy/pkg-descr
@@ -17,6 +17,8 @@ Plugin Changelog
* Add: Layer4 TLS Termination
* Add: h2c protocol to HTTP Handler
+* Cleanup: Caddy Certificate widget hides unused automatic certificates
+* Cleanup: Widgets error handling improved
* Cleanup: Refactor caddy_certs.php to Trust model
1.7.4
diff --git a/www/caddy/src/opnsense/www/js/widgets/CaddyCertificate.js b/www/caddy/src/opnsense/www/js/widgets/CaddyCertificate.js
index ccdf65868..7a3834294 100644
--- a/www/caddy/src/opnsense/www/js/widgets/CaddyCertificate.js
+++ b/www/caddy/src/opnsense/www/js/widgets/CaddyCertificate.js
@@ -38,8 +38,8 @@ export default class CaddyCertificate extends BaseTableWidget {
}
getMarkup() {
- let $container = $('
');
- let $caddyCertificateTable = this.createTable('caddyCertificateTable', {
+ const $container = $('');
+ const $caddyCertificateTable = this.createTable('caddyCertificateTable', {
headerPosition: 'none'
});
@@ -48,49 +48,54 @@ export default class CaddyCertificate extends BaseTableWidget {
}
async onWidgetTick() {
- // Check if Caddy is enabled
- const caddyStatus = await this.ajaxCall('/api/caddy/reverse_proxy/get');
- if (!caddyStatus.caddy.general || caddyStatus.caddy.general.enabled === "0") {
+ const proxyData = await this.ajaxCall('/api/caddy/reverse_proxy/get');
+ if (!proxyData.caddy.general || proxyData.caddy.general.enabled === "0") {
this.displayError(`${this.translations.unconfigured}`);
return;
}
- // Fetch the certificate details
- const response = await this.ajaxCall('/api/caddy/diagnostics/certificate');
- if (response.status !== "success") {
+ const domains = Object.values(proxyData.caddy.reverseproxy?.reverse || [])
+ .map(proxy => proxy.FromDomain)
+ .filter(Boolean);
+
+ const certificates = (await this.ajaxCall('/api/caddy/diagnostics/certificate')).content || [];
+
+ // Display certificate if hostname in config and CN of stored cert on disk match
+ const matchingCertificates = certificates.filter(cert => domains.includes(cert.hostname));
+
+ if (matchingCertificates.length === 0) {
this.displayError(`${this.translations.nocerts}`);
return;
}
- // Process certificates if the response is successful
- this.processCertificates(response.content);
+ this.clearError();
+ this.processCertificates(matchingCertificates);
}
- // Utility function to display errors within the widget
displayError(message) {
const $error = $(``);
$('#caddyCertificateTable').empty().append($error);
}
- processCertificates(certificates) {
- if (!this.dataChanged('certificates', certificates)) {
- return;
- }
+ clearError() {
+ $('#caddyCertificateTable .error-message').remove();
+ }
+ processCertificates(certificates) {
$('.caddy-certificate-tooltip').tooltip('hide');
- let rows = certificates.map(certificate => {
- let colorClass = 'text-success';
- if (certificate.remaining_days === 0) {
- colorClass = 'text-danger';
- } else if (certificate.remaining_days < 14) {
- colorClass = 'text-warning';
- }
+ const rows = certificates.map(certificate => {
+ const colorClass = certificate.remaining_days === 0
+ ? 'text-danger'
+ : certificate.remaining_days < 14
+ ? 'text-warning'
+ : 'text-success';
- let statusText = certificate.remaining_days === 0 ? this.translations.expired :
- this.translations.valid;
+ const statusText = certificate.remaining_days === 0
+ ? this.translations.expired
+ : this.translations.valid;
- let row = `
+ const row = `
@@ -98,19 +103,19 @@ export default class CaddyCertificate extends BaseTableWidget {
${certificate.hostname}
- ${this.translations.expires} ${certificate.remaining_days} ${this.translations.days}, ${new Date(certificate.expiration_date).toLocaleString()}
+
+ ${this.translations.expires} ${certificate.remaining_days} ${this.translations.days},
+ ${new Date(certificate.expiration_date).toLocaleString()}
+
`;
return { html: row, expirationDate: new Date(certificate.expiration_date) };
});
- // Sort rows by expiration date from lowest to highest
rows.sort((a, b) => a.expirationDate - b.expirationDate);
- // Extract sorted HTML rows and update table
- let sortedRows = rows.map(row => [row.html]);
+ const sortedRows = rows.map(row => [row.html]);
super.updateTable('caddyCertificateTable', sortedRows);
- // Initialize tooltips for new elements
- $('.caddy-certificate-tooltip').tooltip({container: 'body'});
+ $('.caddy-certificate-tooltip').tooltip({ container: 'body' });
}
}
diff --git a/www/caddy/src/opnsense/www/js/widgets/CaddyDomain.js b/www/caddy/src/opnsense/www/js/widgets/CaddyDomain.js
index c544cfe6f..ecfbf0f24 100644
--- a/www/caddy/src/opnsense/www/js/widgets/CaddyDomain.js
+++ b/www/caddy/src/opnsense/www/js/widgets/CaddyDomain.js
@@ -37,8 +37,8 @@ export default class CaddyDomain extends BaseTableWidget {
}
getMarkup() {
- let $container = $('');
- let $caddyDomainTable = this.createTable('caddyDomainTable', {
+ const $container = $('');
+ const $caddyDomainTable = this.createTable('caddyDomainTable', {
headerPosition: 'none'
});
@@ -55,7 +55,14 @@ export default class CaddyDomain extends BaseTableWidget {
}
// Process domains if caddy is enabled
- let domains = { ...data.caddy.reverseproxy.reverse, ...data.caddy.reverseproxy.subdomain };
+ const domains = { ...data.caddy.reverseproxy.reverse, ...data.caddy.reverseproxy.subdomain };
+
+ if (Object.keys(domains).length === 0) {
+ this.displayError(`${this.translations.nodomains}`);
+ return;
+ }
+
+ this.clearError();
this.processDomains(domains);
}
@@ -65,6 +72,10 @@ export default class CaddyDomain extends BaseTableWidget {
$('#caddyDomainTable').empty().append($error);
}
+ clearError() {
+ $('#caddyDomainTable .error-message').remove();
+ }
+
processDomains(domains) {
if (!this.dataChanged('domains', domains)) {
return;
@@ -72,19 +83,18 @@ export default class CaddyDomain extends BaseTableWidget {
$('.caddy-domain-tooltip').tooltip('hide');
- let rows = [];
- // Assuming domains is a combination of both reverse and subdomains
+ const rows = [];
for (const key in domains) {
const domain = domains[key];
- let colorClass = domain.enabled === "1" ? 'text-success' : 'text-danger';
- let tooltipText = domain.enabled === "1" ? this.translations.enabled : this.translations.disabled;
+ const colorClass = domain.enabled === "1" ? 'text-success' : 'text-danger';
+ const tooltipText = domain.enabled === "1" ? this.translations.enabled : this.translations.disabled;
let domainPort = domain.FromDomain;
if (domain.FromPort) {
domainPort += `:${domain.FromPort}`;
}
- let row = $(`
+ const row = $(`
[row.html]));
// Initialize tooltips for interactivity
- $('.caddy-domain-tooltip').tooltip({container: 'body'});
+ $('.caddy-domain-tooltip').tooltip({ container: 'body' });
}
}
diff --git a/www/caddy/src/opnsense/www/js/widgets/Metadata/Caddy.xml b/www/caddy/src/opnsense/www/js/widgets/Metadata/Caddy.xml
index ac818fd2a..c423f6163 100644
--- a/www/caddy/src/opnsense/www/js/widgets/Metadata/Caddy.xml
+++ b/www/caddy/src/opnsense/www/js/widgets/Metadata/Caddy.xml
@@ -10,6 +10,7 @@
Enabled
Disabled
Caddy is disabled or not configured.
+ Caddy does not manage any domains.