73 lines
3.5 KiB
Plaintext
73 lines
3.5 KiB
Plaintext
@page
|
|
@model Status.Pages.CertificatesModel
|
|
@{
|
|
ViewData["Title"] = "Certificates";
|
|
ViewData["Page"] = "certs";
|
|
}
|
|
|
|
<div class="section-header">
|
|
<span class="section-title">SSL/TLS Certificates</span>
|
|
@if (Model.IsAdmin) { <a href="/admin/certificates" class="btn btn-outline btn-sm">Manage →</a> }
|
|
</div>
|
|
|
|
@if (!Model.Certificates.Any())
|
|
{
|
|
<div class="empty-state">
|
|
<div class="empty-state-icon">◧</div>
|
|
<div class="empty-state-text">No certificates tracked</div>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="stats-grid">
|
|
@{
|
|
var now = DateTime.UtcNow;
|
|
var valid = Model.Certificates.Count(c => c.ExpiresAt.HasValue && (c.ExpiresAt.Value - now).TotalDays > 30);
|
|
var expiringSoon = Model.Certificates.Count(c => c.ExpiresAt.HasValue && (c.ExpiresAt.Value - now).TotalDays is > 0 and <= 30);
|
|
var expired = Model.Certificates.Count(c => c.ExpiresAt.HasValue && c.ExpiresAt.Value <= now);
|
|
}
|
|
<div class="stat-card up"><div class="stat-label">Valid</div><div class="stat-value">@valid</div></div>
|
|
<div class="stat-card warn"><div class="stat-label">Expiring <30d</div><div class="stat-value">@expiringSoon</div></div>
|
|
<div class="stat-card down"><div class="stat-label">Expired</div><div class="stat-value">@expired</div></div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<table class="data-table">
|
|
<thead><tr>
|
|
<th>Name</th>
|
|
<th>Domain</th>
|
|
<th>Issuer</th>
|
|
<th>Valid From</th>
|
|
<th>Expires</th>
|
|
<th>Days Left</th>
|
|
<th>Fingerprint</th>
|
|
<th>Status</th>
|
|
</tr></thead>
|
|
<tbody>
|
|
@foreach (var certificate in Model.Certificates)
|
|
{
|
|
var days = certificate.ExpiresAt.HasValue ? (int)(certificate.ExpiresAt.Value - now).TotalDays : (int?)null;
|
|
var cls = days == null ? "" : days <= 0 ? "cert-expiry-expired" : days <= 7 ? "cert-expiry-critical" : days <= 30 ? "cert-expiry-warn" : "cert-expiry-ok";
|
|
<tr>
|
|
<td style="font-weight:500;color:var(--text-primary)">@certificate.Name</td>
|
|
<td class="mono" style="font-size:11px">@certificate.Domain</td>
|
|
<td style="font-size:11px;color:var(--text-muted);max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">@(certificate.Issuer?.Split(',').FirstOrDefault()?.Replace("CN=","") ?? "—")</td>
|
|
<td class="mono" style="font-size:11px">@(certificate.IssuedAt?.ToString("yyyy-MM-dd") ?? "—")</td>
|
|
<td class="mono @cls" style="font-size:11px">@(certificate.ExpiresAt?.ToString("yyyy-MM-dd") ?? "—")</td>
|
|
<td class="mono @cls" style="font-weight:700">@(days.HasValue ? days + "d" : "—")</td>
|
|
<td class="mono" style="font-size:10px;color:var(--text-muted)">@(certificate.Thumbprint?[..16] ?? "—")…</td>
|
|
<td>
|
|
@if (!string.IsNullOrEmpty(certificate.LastError)) { <span class="badge badge-down" title="@certificate.LastError">ERROR</span> }
|
|
else if (days == null) { <span class="badge badge-unknown">Unchecked</span> }
|
|
else if (days <= 0) { <span class="badge badge-down">EXPIRED</span> }
|
|
else if (days <= 7) { <span class="badge badge-down">CRITICAL</span> }
|
|
else if (days <= 30) { <span class="badge badge-warn">EXPIRING</span> }
|
|
else { <span class="badge badge-up">VALID</span> }
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|