From 3dc76e0b8704c3475f11cfd37969e6792f657aa1 Mon Sep 17 00:00:00 2001 From: Shankar Date: Tue, 24 Mar 2026 12:17:24 -0400 Subject: [PATCH] fix: normalize certificate status case in stats service The stats service compared statuses using exact string match against PascalCase domain constants, but the database may contain legacy lowercase values. This caused the dashboard to show duplicate pie chart segments (green "Active" + gray "active") and incorrect summary counts. Use strings.ToLower() normalization in both GetCertificatesByStatus and GetDashboardSummary to handle any case variant from the database. Co-Authored-By: Claude Opus 4.6 --- internal/service/stats.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/internal/service/stats.go b/internal/service/stats.go index 770b161..65a6dc3 100644 --- a/internal/service/stats.go +++ b/internal/service/stats.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "strings" "time" "github.com/shankar0123/certctl/internal/domain" @@ -61,9 +62,10 @@ func (s *StatsService) GetDashboardSummary(ctx context.Context) (interface{}, er thirtyDaysFromNow := now.AddDate(0, 0, 30) for _, cert := range allCerts { - if cert.Status == domain.CertificateStatusRevoked { + normalizedStatus := strings.ToLower(string(cert.Status)) + if normalizedStatus == "revoked" { summary.RevokedCertificates++ - } else if cert.Status == domain.CertificateStatusExpired || (!cert.ExpiresAt.IsZero() && cert.ExpiresAt.Before(now)) { + } else if normalizedStatus == "expired" || (!cert.ExpiresAt.IsZero() && cert.ExpiresAt.Before(now)) { summary.ExpiredCertificates++ } else if !cert.ExpiresAt.IsZero() && cert.ExpiresAt.Before(thirtyDaysFromNow) && cert.ExpiresAt.After(now) { summary.ExpiringCertificates++ @@ -126,7 +128,9 @@ func (s *StatsService) GetCertificatesByStatus(ctx context.Context) (interface{} for _, cert := range allCerts { status := string(cert.Status) - if status == "" || status == "Active" { + // Normalize status to PascalCase to handle legacy lowercase values in the database + switch strings.ToLower(status) { + case "", "active": if !cert.ExpiresAt.IsZero() { if cert.ExpiresAt.Before(now) { status = "Expired" @@ -138,6 +142,20 @@ func (s *StatsService) GetCertificatesByStatus(ctx context.Context) (interface{} } else { status = "Active" } + case "expiring": + status = "Expiring" + case "expired": + status = "Expired" + case "renewalinprogress", "renewal_in_progress": + status = "RenewalInProgress" + case "failed": + status = "Failed" + case "revoked": + status = "Revoked" + case "archived": + status = "Archived" + case "pending": + status = "Pending" } counts[status]++ }