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 <noreply@anthropic.com>
This commit is contained in:
shankar0123
2026-03-24 12:17:24 -04:00
parent bd381b3ffd
commit d613d98c72
+21 -3
View File
@@ -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]++
}