Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Status page certificate expiry #3357

Merged
merged 8 commits into from
Jul 31, 2023
7 changes: 7 additions & 0 deletions db/patch-add-certificate-expiry-status-page.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;

ALTER TABLE status_page
ADD show_certificate_expiry BOOLEAN default 0 NOT NULL;

COMMIT;
1 change: 1 addition & 0 deletions server/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class Database {
"patch-monitor-tls.sql": true,
"patch-maintenance-cron.sql": true,
"patch-add-parent-monitor.sql": true,
"patch-add-certificate-expiry-status-page.sql": true,
};

/**
Expand Down
4 changes: 2 additions & 2 deletions server/model/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ class Group extends BeanModel {
* @param {boolean} [showTags=false] Should the JSON include monitor tags
* @returns {Object}
*/
async toPublicJSON(showTags = false) {
async toPublicJSON(showTags = false, certExpiry = false) {
let monitorBeanList = await this.getMonitorList();
let monitorList = [];

for (let bean of monitorBeanList) {
monitorList.push(await bean.toPublicJSON(showTags));
monitorList.push(await bean.toPublicJSON(showTags, certExpiry));
}

return {
Expand Down
34 changes: 33 additions & 1 deletion server/model/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class Monitor extends BeanModel {
* Only show necessary data to public
* @returns {Object}
*/
async toPublicJSON(showTags = false) {
async toPublicJSON(showTags = false, certExpiry = false) {
let obj = {
id: this.id,
name: this.name,
Expand All @@ -50,6 +50,13 @@ class Monitor extends BeanModel {
if (showTags) {
obj.tags = await this.getTags();
}

if (certExpiry) {
const { certExpiryDaysRemaining, validCert } = await this.getCertExpiry(this.id);
obj.certExpiryDaysRemaining = certExpiryDaysRemaining;
obj.validCert = validCert;
}

return obj;
}

Expand Down Expand Up @@ -174,6 +181,31 @@ class Monitor extends BeanModel {
return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ? ORDER BY tag.name", [ this.id ]);
}

/**
* Gets certificate expiry for this monitor
* @param {number} monitorID ID of monitor to send
* @returns {Promise<LooseObject<any>>}
*/
async getCertExpiry(monitorID) {
let tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [
monitorID,
]);
let tlsInfo;
if (tlsInfoBean) {
tlsInfo = JSON.parse(tlsInfoBean?.info_json);
if (tlsInfo?.valid && tlsInfo?.certInfo?.daysRemaining) {
return {
certExpiryDaysRemaining: tlsInfo.certInfo.daysRemaining,
validCert: true
};
}
}
return {
certExpiryDaysRemaining: "No/Bad Cert",
validCert: false
};
}

/**
* Encode user and password to Base64 encoding
* for HTTP "basic" auth, as per RFC-7617
Expand Down
9 changes: 7 additions & 2 deletions server/model/status_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class StatusPage extends BeanModel {
* @param {StatusPage} statusPage
*/
static async getStatusPageData(statusPage) {

tarun7singh marked this conversation as resolved.
Show resolved Hide resolved
const config = await statusPage.toPublicJSON();

// Incident
let incident = await R.findOne("incident", " pin = 1 AND active = 1 AND status_page_id = ? ", [
statusPage.id,
Expand All @@ -110,13 +113,13 @@ class StatusPage extends BeanModel {
]);

for (let groupBean of list) {
let monitorGroup = await groupBean.toPublicJSON(showTags);
let monitorGroup = await groupBean.toPublicJSON(showTags, config?.showCertificateExpiry);
publicGroupList.push(monitorGroup);
}

// Response
return {
config: await statusPage.toPublicJSON(),
config,
incident,
publicGroupList,
maintenanceList,
Expand Down Expand Up @@ -234,6 +237,7 @@ class StatusPage extends BeanModel {
footerText: this.footer_text,
showPoweredBy: !!this.show_powered_by,
googleAnalyticsId: this.google_analytics_tag_id,
showCertificateExpiry: !!this.show_certificate_expiry,
};
}

Expand All @@ -255,6 +259,7 @@ class StatusPage extends BeanModel {
footerText: this.footer_text,
showPoweredBy: !!this.show_powered_by,
googleAnalyticsId: this.google_analytics_tag_id,
showCertificateExpiry: !!this.show_certificate_expiry,
};
}

Expand Down
1 change: 1 addition & 0 deletions server/socket-handlers/status-page-socket-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ module.exports.statusPageSocketHandler = (socket) => {
statusPage.footer_text = config.footerText;
statusPage.custom_css = config.customCSS;
statusPage.show_powered_by = config.showPoweredBy;
statusPage.show_certificate_expiry = config.showCertificateExpiry;
statusPage.modified_date = R.isoDateTime();
statusPage.google_analytics_tag_id = config.googleAnalyticsId;

Expand Down
18 changes: 18 additions & 0 deletions src/components/PublicGroupList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
@click="$refs.monitorSettingDialog.show(group, monitor)"
/>
</span>
<p v-if="showCertificateExpiry" class="item-name"> Expiry: {{ formatExpiry(monitor) }} </p>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disclaimer: I am not a designer => feel free to overrule
From a design perspective, I don't like how this looks like a regular title (a user would not be able to pick up, that this is an expiry notice).

What do you think: Could we move this to a subtle or tag and still keep the current design?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should i try showing it as pill like the uptime percetage, with colors for showing how soon it will be expiring?
My reason for avoiding that was to not clutter the ui.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a pill is what I meant with tag. This would be one option.

Copy link
Contributor Author

@tarun7singh tarun7singh Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the pill/tags based design i came up with, which one do you prefer?

  1. Expiry inside the pill
    Screenshot 2023-07-06 at 1 36 50 PM

  2. Expiry outside the pill
    Screenshot 2023-07-06 at 1 35 46 PM

I think second option looks much better but name of the monitor is getting confusing.

Color is green for expiry of more than 7 days
Color is red for everything else

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@louislam Do you have any preference out of the above two designs?

tarun7singh marked this conversation as resolved.
Show resolved Hide resolved
</div>
<div v-if="showTags" class="tags">
<Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" />
Expand Down Expand Up @@ -103,6 +104,10 @@ export default {
/** Should tags be shown? */
showTags: {
type: Boolean,
},
/** Should expiry be shown? */
showCertificateExpiry: {
type: Boolean,
}
},
data() {
Expand Down Expand Up @@ -154,6 +159,19 @@ export default {
}
return monitor.element.sendUrl && monitor.element.url && monitor.element.url !== "https://" && !this.editMode;
},

/**
* Returns formatted certificate expiry or Bad cert message
* @param {Object} monitor Monitor to show expiry for
* @returns {string}
*/
formatExpiry(monitor) {
tarun7singh marked this conversation as resolved.
Show resolved Hide resolved
if (monitor?.element?.validCert) {
return monitor.element.certExpiryDaysRemaining + " days";
tarun7singh marked this conversation as resolved.
Show resolved Hide resolved
} else {
return monitor.element.certExpiryDaysRemaining;
tarun7singh marked this conversation as resolved.
Show resolved Hide resolved
}
},
}
};
</script>
Expand Down
8 changes: 7 additions & 1 deletion src/pages/StatusPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@
<label class="form-check-label" for="show-powered-by">{{ $t("Show Powered By") }}</label>
</div>

<!-- Show certificate expiry -->
<div class="my-3 form-check form-switch">
<input id="show-certificate-expiry" v-model="config.showCertificateExpiry" class="form-check-input" type="checkbox">
<label class="form-check-label" for="show-certificate-expiry">{{ $t("Show Certificate Expiry") }}</label>
tarun7singh marked this conversation as resolved.
Show resolved Hide resolved
</div>

<div v-if="false" class="my-3">
<label for="password" class="form-label">{{ $t("Password") }} <sup>{{ $t("Coming Soon") }}</sup></label>
<input id="password" v-model="config.password" disabled type="password" autocomplete="new-password" class="form-control">
Expand Down Expand Up @@ -309,7 +315,7 @@
👀 {{ $t("statusPageNothing") }}
</div>

<PublicGroupList :edit-mode="enableEditMode" :show-tags="config.showTags" />
<PublicGroupList :edit-mode="enableEditMode" :show-tags="config.showTags" :show-certificate-expiry="config.showCertificateExpiry" />
</div>

<footer class="mt-5 mb-4">
Expand Down