mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 19:01:34 +00:00
fix(m-2): thread context through CertificateService cluster
Collapses CertificateService, RevocationSvc, and CAOperationsSvc to ctx-accepting method signatures. Removes context.Background() synthesis at 24 internal call sites across certificate.go, revocation_svc.go, and ca_operations.go. - Primary repo calls inherit request cancellation via the passed ctx. - Audit and notification dispatches use context.WithoutCancel(ctx) so they survive client disconnect. - Collapses TriggerRenewal/TriggerRenewalWithActor, TriggerDeployment/TriggerDeploymentWithActor, and RevokeCertificate/RevokeCertificateWithActor sibling pairs into single canonical ctx-accepting methods (decisions D-1, D-2). Handlers pass r.Context(). Mocks and tests updated to match new signatures. No HTTP surface change, no OpenAPI change. PR 1 of 6 in the M-2 remediation chain. Master green at this commit. Refs: certctl-audit-report.md M-2 (L143, L224)
This commit is contained in:
@@ -27,6 +27,7 @@ package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -120,7 +121,7 @@ func TestGetCertificate_PathInjection(t *testing.T) {
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
// Force a 404 so we can distinguish "service was called" from
|
||||
// "parser accepted the ID"; a 200 with null body is also fine.
|
||||
mock.GetCertificateFn = func(id string) (*domain.ManagedCertificate, error) {
|
||||
mock.GetCertificateFn = func(_ context.Context, id string) (*domain.ManagedCertificate, error) {
|
||||
return nil, ErrMockNotFound
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ func TestUpdateCertificate_PathInjection(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.UpdateCertificateFn = func(id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
mock.UpdateCertificateFn = func(_ context.Context, id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
return nil, ErrMockNotFound
|
||||
}
|
||||
|
||||
@@ -184,7 +185,7 @@ func TestArchiveCertificate_PathInjection(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.ArchiveCertificateFn = func(id string) error { return ErrMockNotFound }
|
||||
mock.ArchiveCertificateFn = func(_ context.Context, id string) error { return ErrMockNotFound }
|
||||
|
||||
req := httptest.NewRequest(http.MethodDelete, "/api/v1/certificates/x", nil)
|
||||
req.URL.Path = "/api/v1/certificates/" + tc.input
|
||||
@@ -227,7 +228,7 @@ func TestGetCertificateVersions_MultiSegment(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.GetCertificateVersionsFn = func(certID string, page, perPage int) ([]domain.CertificateVersion, int64, error) {
|
||||
mock.GetCertificateVersionsFn = func(_ context.Context, certID string, page, perPage int) ([]domain.CertificateVersion, int64, error) {
|
||||
return []domain.CertificateVersion{}, 0, nil
|
||||
}
|
||||
|
||||
@@ -277,7 +278,7 @@ func TestHandleOCSP_MultiSegment(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.GetOCSPResponseFn = func(issuerID, serialHex string) ([]byte, error) {
|
||||
mock.GetOCSPResponseFn = func(_ context.Context, issuerID, serialHex string) ([]byte, error) {
|
||||
return nil, ErrMockNotFound
|
||||
}
|
||||
|
||||
@@ -311,7 +312,7 @@ func TestGetDERCRL_IssuerPathInjection(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.GenerateDERCRLFn = func(issuerID string) ([]byte, error) {
|
||||
mock.GenerateDERCRLFn = func(_ context.Context, issuerID string) ([]byte, error) {
|
||||
return nil, ErrMockNotFound
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -76,7 +77,7 @@ func TestListCertificates_PaginationAbuse(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.ListCertificatesWithFilterFn = func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
mock.ListCertificatesWithFilterFn = func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
// Sanity: page/perPage on the filter must never be negative
|
||||
// and perPage must never exceed 500 after parsing.
|
||||
if filter.Page < 1 {
|
||||
@@ -133,7 +134,7 @@ func TestListCertificates_SortAbuse(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.ListCertificatesWithFilterFn = func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
mock.ListCertificatesWithFilterFn = func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
return []domain.ManagedCertificate{}, 0, nil
|
||||
}
|
||||
|
||||
@@ -175,7 +176,7 @@ func TestListCertificates_FieldsAbuse(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.ListCertificatesWithFilterFn = func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
mock.ListCertificatesWithFilterFn = func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
return []domain.ManagedCertificate{}, 0, nil
|
||||
}
|
||||
|
||||
@@ -219,7 +220,7 @@ func TestListCertificates_TimeRangeAbuse(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.ListCertificatesWithFilterFn = func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
mock.ListCertificatesWithFilterFn = func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
return []domain.ManagedCertificate{}, 0, nil
|
||||
}
|
||||
|
||||
@@ -263,7 +264,7 @@ func TestListCertificates_CursorAbuse(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.ListCertificatesWithFilterFn = func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
mock.ListCertificatesWithFilterFn = func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
return []domain.ManagedCertificate{}, 0, nil
|
||||
}
|
||||
|
||||
@@ -314,7 +315,7 @@ func TestListCertificates_FilterInjection(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.ListCertificatesWithFilterFn = func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
mock.ListCertificatesWithFilterFn = func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
return []domain.ManagedCertificate{}, 0, nil
|
||||
}
|
||||
|
||||
@@ -374,7 +375,7 @@ func TestCreateCertificate_BodyAbuse(t *testing.T) {
|
||||
}()
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.CreateCertificateFn = func(cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
mock.CreateCertificateFn = func(_ context.Context, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
// If we ever reach this, the handler accepted a malformed
|
||||
// body. Return a sentinel that passes but flag it.
|
||||
c := cert
|
||||
@@ -419,7 +420,7 @@ func TestCreateCertificate_HugeBody(t *testing.T) {
|
||||
sb.WriteString(`]}`)
|
||||
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.CreateCertificateFn = func(cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
mock.CreateCertificateFn = func(_ context.Context, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
c := cert
|
||||
c.ID = "mc-huge"
|
||||
return &c, nil
|
||||
@@ -476,7 +477,7 @@ func TestRevokeCertificate_ReasonAbuse(t *testing.T) {
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
// The mock always returns "invalid revocation reason" so we
|
||||
// verify the handler's errMsg→status mapping turns it into a 400.
|
||||
mock.RevokeCertificateFn = func(id string, reason string) error {
|
||||
mock.RevokeCertificateFn = func(_ context.Context, id string, reason string, _ string) error {
|
||||
// The service uses domain.IsValidRevocationReason. If we got
|
||||
// through to here with something bogus, simulate a real
|
||||
// service error.
|
||||
@@ -500,7 +501,7 @@ func TestRevokeCertificate_ReasonAbuse(t *testing.T) {
|
||||
// service error message, which is fragile — this test catches regressions.
|
||||
func TestRevokeCertificate_AlreadyRevoked(t *testing.T) {
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.RevokeCertificateFn = func(id string, reason string) error {
|
||||
mock.RevokeCertificateFn = func(_ context.Context, id string, reason string, _ string) error {
|
||||
return fmt.Errorf("cannot revoke: certificate is already revoked")
|
||||
}
|
||||
|
||||
@@ -520,7 +521,7 @@ func TestRevokeCertificate_AlreadyRevoked(t *testing.T) {
|
||||
// TestRevokeCertificate_NotFound verifies 404 mapping.
|
||||
func TestRevokeCertificate_NotFound(t *testing.T) {
|
||||
handler, mock := newCertHandlerWithMock()
|
||||
mock.RevokeCertificateFn = func(id string, reason string) error {
|
||||
mock.RevokeCertificateFn = func(_ context.Context, id string, reason string, _ string) error {
|
||||
return fmt.Errorf("certificate not found")
|
||||
}
|
||||
|
||||
|
||||
@@ -17,116 +17,116 @@ import (
|
||||
|
||||
// MockCertificateService is a mock implementation of CertificateService interface.
|
||||
type MockCertificateService struct {
|
||||
ListCertificatesFn func(status, environment, ownerID, teamID, issuerID string, page, perPage int) ([]domain.ManagedCertificate, int64, error)
|
||||
ListCertificatesWithFilterFn func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error)
|
||||
GetCertificateFn func(id string) (*domain.ManagedCertificate, error)
|
||||
CreateCertificateFn func(cert domain.ManagedCertificate) (*domain.ManagedCertificate, error)
|
||||
UpdateCertificateFn func(id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error)
|
||||
ArchiveCertificateFn func(id string) error
|
||||
GetCertificateVersionsFn func(certID string, page, perPage int) ([]domain.CertificateVersion, int64, error)
|
||||
TriggerRenewalFn func(certID string) error
|
||||
TriggerDeploymentFn func(certID string, targetID string) error
|
||||
RevokeCertificateFn func(certID string, reason string) error
|
||||
GetRevokedCertificatesFn func() ([]*domain.CertificateRevocation, error)
|
||||
GenerateDERCRLFn func(issuerID string) ([]byte, error)
|
||||
GetOCSPResponseFn func(issuerID string, serialHex string) ([]byte, error)
|
||||
GetCertificateDeploymentsFn func(certID string) ([]domain.DeploymentTarget, error)
|
||||
ListCertificatesFn func(ctx context.Context, status, environment, ownerID, teamID, issuerID string, page, perPage int) ([]domain.ManagedCertificate, int64, error)
|
||||
ListCertificatesWithFilterFn func(ctx context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error)
|
||||
GetCertificateFn func(ctx context.Context, id string) (*domain.ManagedCertificate, error)
|
||||
CreateCertificateFn func(ctx context.Context, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error)
|
||||
UpdateCertificateFn func(ctx context.Context, id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error)
|
||||
ArchiveCertificateFn func(ctx context.Context, id string) error
|
||||
GetCertificateVersionsFn func(ctx context.Context, certID string, page, perPage int) ([]domain.CertificateVersion, int64, error)
|
||||
TriggerRenewalFn func(ctx context.Context, certID string, actor string) error
|
||||
TriggerDeploymentFn func(ctx context.Context, certID string, targetID string, actor string) error
|
||||
RevokeCertificateFn func(ctx context.Context, certID string, reason string, actor string) error
|
||||
GetRevokedCertificatesFn func(ctx context.Context) ([]*domain.CertificateRevocation, error)
|
||||
GenerateDERCRLFn func(ctx context.Context, issuerID string) ([]byte, error)
|
||||
GetOCSPResponseFn func(ctx context.Context, issuerID string, serialHex string) ([]byte, error)
|
||||
GetCertificateDeploymentsFn func(ctx context.Context, certID string) ([]domain.DeploymentTarget, error)
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) ListCertificates(status, environment, ownerID, teamID, issuerID string, page, perPage int) ([]domain.ManagedCertificate, int64, error) {
|
||||
func (m *MockCertificateService) ListCertificates(ctx context.Context, status, environment, ownerID, teamID, issuerID string, page, perPage int) ([]domain.ManagedCertificate, int64, error) {
|
||||
if m.ListCertificatesFn != nil {
|
||||
return m.ListCertificatesFn(status, environment, ownerID, teamID, issuerID, page, perPage)
|
||||
return m.ListCertificatesFn(ctx, status, environment, ownerID, teamID, issuerID, page, perPage)
|
||||
}
|
||||
return nil, 0, nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) GetCertificate(id string) (*domain.ManagedCertificate, error) {
|
||||
func (m *MockCertificateService) GetCertificate(ctx context.Context, id string) (*domain.ManagedCertificate, error) {
|
||||
if m.GetCertificateFn != nil {
|
||||
return m.GetCertificateFn(id)
|
||||
return m.GetCertificateFn(ctx, id)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) CreateCertificate(cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
func (m *MockCertificateService) CreateCertificate(ctx context.Context, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
if m.CreateCertificateFn != nil {
|
||||
return m.CreateCertificateFn(cert)
|
||||
return m.CreateCertificateFn(ctx, cert)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) UpdateCertificate(id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
func (m *MockCertificateService) UpdateCertificate(ctx context.Context, id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
if m.UpdateCertificateFn != nil {
|
||||
return m.UpdateCertificateFn(id, cert)
|
||||
return m.UpdateCertificateFn(ctx, id, cert)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) ArchiveCertificate(id string) error {
|
||||
func (m *MockCertificateService) ArchiveCertificate(ctx context.Context, id string) error {
|
||||
if m.ArchiveCertificateFn != nil {
|
||||
return m.ArchiveCertificateFn(id)
|
||||
return m.ArchiveCertificateFn(ctx, id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) GetCertificateVersions(certID string, page, perPage int) ([]domain.CertificateVersion, int64, error) {
|
||||
func (m *MockCertificateService) GetCertificateVersions(ctx context.Context, certID string, page, perPage int) ([]domain.CertificateVersion, int64, error) {
|
||||
if m.GetCertificateVersionsFn != nil {
|
||||
return m.GetCertificateVersionsFn(certID, page, perPage)
|
||||
return m.GetCertificateVersionsFn(ctx, certID, page, perPage)
|
||||
}
|
||||
return nil, 0, nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) TriggerRenewal(certID string) error {
|
||||
func (m *MockCertificateService) TriggerRenewal(ctx context.Context, certID string, actor string) error {
|
||||
if m.TriggerRenewalFn != nil {
|
||||
return m.TriggerRenewalFn(certID)
|
||||
return m.TriggerRenewalFn(ctx, certID, actor)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) TriggerDeployment(certID string, targetID string) error {
|
||||
func (m *MockCertificateService) TriggerDeployment(ctx context.Context, certID string, targetID string, actor string) error {
|
||||
if m.TriggerDeploymentFn != nil {
|
||||
return m.TriggerDeploymentFn(certID, targetID)
|
||||
return m.TriggerDeploymentFn(ctx, certID, targetID, actor)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) RevokeCertificate(certID string, reason string) error {
|
||||
func (m *MockCertificateService) RevokeCertificate(ctx context.Context, certID string, reason string, actor string) error {
|
||||
if m.RevokeCertificateFn != nil {
|
||||
return m.RevokeCertificateFn(certID, reason)
|
||||
return m.RevokeCertificateFn(ctx, certID, reason, actor)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) GetRevokedCertificates() ([]*domain.CertificateRevocation, error) {
|
||||
func (m *MockCertificateService) GetRevokedCertificates(ctx context.Context) ([]*domain.CertificateRevocation, error) {
|
||||
if m.GetRevokedCertificatesFn != nil {
|
||||
return m.GetRevokedCertificatesFn()
|
||||
return m.GetRevokedCertificatesFn(ctx)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) GenerateDERCRL(issuerID string) ([]byte, error) {
|
||||
func (m *MockCertificateService) GenerateDERCRL(ctx context.Context, issuerID string) ([]byte, error) {
|
||||
if m.GenerateDERCRLFn != nil {
|
||||
return m.GenerateDERCRLFn(issuerID)
|
||||
return m.GenerateDERCRLFn(ctx, issuerID)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) GetOCSPResponse(issuerID string, serialHex string) ([]byte, error) {
|
||||
func (m *MockCertificateService) GetOCSPResponse(ctx context.Context, issuerID string, serialHex string) ([]byte, error) {
|
||||
if m.GetOCSPResponseFn != nil {
|
||||
return m.GetOCSPResponseFn(issuerID, serialHex)
|
||||
return m.GetOCSPResponseFn(ctx, issuerID, serialHex)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) ListCertificatesWithFilter(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
func (m *MockCertificateService) ListCertificatesWithFilter(ctx context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if m.ListCertificatesWithFilterFn != nil {
|
||||
return m.ListCertificatesWithFilterFn(filter)
|
||||
return m.ListCertificatesWithFilterFn(ctx, filter)
|
||||
}
|
||||
return nil, 0, nil
|
||||
}
|
||||
|
||||
func (m *MockCertificateService) GetCertificateDeployments(certID string) ([]domain.DeploymentTarget, error) {
|
||||
func (m *MockCertificateService) GetCertificateDeployments(ctx context.Context, certID string) ([]domain.DeploymentTarget, error) {
|
||||
if m.GetCertificateDeploymentsFn != nil {
|
||||
return m.GetCertificateDeploymentsFn(certID)
|
||||
return m.GetCertificateDeploymentsFn(ctx, certID)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
@@ -158,7 +158,7 @@ func TestListCertificates_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if filter.Page == 1 && filter.PerPage == 50 {
|
||||
return []domain.ManagedCertificate{cert1, cert2}, 2, nil
|
||||
}
|
||||
@@ -197,7 +197,7 @@ func TestListCertificates_Success(t *testing.T) {
|
||||
// Test ListCertificates - with filters
|
||||
func TestListCertificates_WithFilters(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if filter.Status == "Active" && filter.Environment == "prod" {
|
||||
return []domain.ManagedCertificate{}, 0, nil
|
||||
}
|
||||
@@ -236,7 +236,7 @@ func TestListCertificates_MethodNotAllowed(t *testing.T) {
|
||||
// Test ListCertificates - service error
|
||||
func TestListCertificates_ServiceError(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
return nil, 0, ErrMockServiceFailed
|
||||
},
|
||||
}
|
||||
@@ -266,7 +266,7 @@ func TestGetCertificate_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
mock := &MockCertificateService{
|
||||
GetCertificateFn: func(id string) (*domain.ManagedCertificate, error) {
|
||||
GetCertificateFn: func(_ context.Context, id string) (*domain.ManagedCertificate, error) {
|
||||
if id == "mc-prod-001" {
|
||||
return cert, nil
|
||||
}
|
||||
@@ -298,7 +298,7 @@ func TestGetCertificate_Success(t *testing.T) {
|
||||
// Test GetCertificate - not found
|
||||
func TestGetCertificate_NotFound(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GetCertificateFn: func(id string) (*domain.ManagedCertificate, error) {
|
||||
GetCertificateFn: func(_ context.Context, id string) (*domain.ManagedCertificate, error) {
|
||||
return nil, ErrMockNotFound
|
||||
},
|
||||
}
|
||||
@@ -345,7 +345,7 @@ func TestCreateCertificate_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
mock := &MockCertificateService{
|
||||
CreateCertificateFn: func(cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
CreateCertificateFn: func(_ context.Context, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
return created, nil
|
||||
},
|
||||
}
|
||||
@@ -403,7 +403,7 @@ func TestCreateCertificate_InvalidBody(t *testing.T) {
|
||||
// Test CreateCertificate - service error
|
||||
func TestCreateCertificate_ServiceError(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
CreateCertificateFn: func(cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
CreateCertificateFn: func(_ context.Context, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
return nil, ErrMockServiceFailed
|
||||
},
|
||||
}
|
||||
@@ -445,7 +445,7 @@ func TestUpdateCertificate_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
mock := &MockCertificateService{
|
||||
UpdateCertificateFn: func(id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
UpdateCertificateFn: func(_ context.Context, id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error) {
|
||||
if id == "mc-prod-001" {
|
||||
return updated, nil
|
||||
}
|
||||
@@ -501,7 +501,7 @@ func TestUpdateCertificate_InvalidBody(t *testing.T) {
|
||||
// Test ArchiveCertificate - success case
|
||||
func TestArchiveCertificate_Success(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ArchiveCertificateFn: func(id string) error {
|
||||
ArchiveCertificateFn: func(_ context.Context, id string) error {
|
||||
if id == "mc-prod-001" {
|
||||
return nil
|
||||
}
|
||||
@@ -524,7 +524,7 @@ func TestArchiveCertificate_Success(t *testing.T) {
|
||||
// Test ArchiveCertificate - not found
|
||||
func TestArchiveCertificate_NotFound(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ArchiveCertificateFn: func(id string) error {
|
||||
ArchiveCertificateFn: func(_ context.Context, id string) error {
|
||||
return ErrMockNotFound
|
||||
},
|
||||
}
|
||||
@@ -554,7 +554,7 @@ func TestGetCertificateVersions_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
mock := &MockCertificateService{
|
||||
GetCertificateVersionsFn: func(certID string, page, perPage int) ([]domain.CertificateVersion, int64, error) {
|
||||
GetCertificateVersionsFn: func(_ context.Context, certID string, page, perPage int) ([]domain.CertificateVersion, int64, error) {
|
||||
if certID == "mc-prod-001" {
|
||||
return []domain.CertificateVersion{ver1}, 1, nil
|
||||
}
|
||||
@@ -586,7 +586,7 @@ func TestGetCertificateVersions_Success(t *testing.T) {
|
||||
// Test GetCertificateVersions - not found
|
||||
func TestGetCertificateVersions_NotFound(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GetCertificateVersionsFn: func(certID string, page, perPage int) ([]domain.CertificateVersion, int64, error) {
|
||||
GetCertificateVersionsFn: func(_ context.Context, certID string, page, perPage int) ([]domain.CertificateVersion, int64, error) {
|
||||
return nil, 0, ErrMockNotFound
|
||||
},
|
||||
}
|
||||
@@ -606,7 +606,7 @@ func TestGetCertificateVersions_NotFound(t *testing.T) {
|
||||
// Test TriggerRenewal - success case
|
||||
func TestTriggerRenewal_Success(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
TriggerRenewalFn: func(certID string) error {
|
||||
TriggerRenewalFn: func(_ context.Context, certID string, _ string) error {
|
||||
if certID == "mc-prod-001" {
|
||||
return nil
|
||||
}
|
||||
@@ -638,7 +638,7 @@ func TestTriggerRenewal_Success(t *testing.T) {
|
||||
// Test TriggerRenewal - service error
|
||||
func TestTriggerRenewal_ServiceError(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
TriggerRenewalFn: func(certID string) error {
|
||||
TriggerRenewalFn: func(_ context.Context, certID string, _ string) error {
|
||||
return ErrMockServiceFailed
|
||||
},
|
||||
}
|
||||
@@ -658,7 +658,7 @@ func TestTriggerRenewal_ServiceError(t *testing.T) {
|
||||
// Test TriggerDeployment - success case
|
||||
func TestTriggerDeployment_Success(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
TriggerDeploymentFn: func(certID string, targetID string) error {
|
||||
TriggerDeploymentFn: func(_ context.Context, certID string, targetID string, _ string) error {
|
||||
if certID == "mc-prod-001" {
|
||||
return nil
|
||||
}
|
||||
@@ -695,7 +695,7 @@ func TestTriggerDeployment_Success(t *testing.T) {
|
||||
// Test TriggerDeployment - without target ID
|
||||
func TestTriggerDeployment_NoTargetID(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
TriggerDeploymentFn: func(certID string, targetID string) error {
|
||||
TriggerDeploymentFn: func(_ context.Context, certID string, targetID string, _ string) error {
|
||||
// Should accept empty targetID (deploy to all)
|
||||
return nil
|
||||
},
|
||||
@@ -716,7 +716,7 @@ func TestTriggerDeployment_NoTargetID(t *testing.T) {
|
||||
// Test ListCertificates - invalid page parameter
|
||||
func TestListCertificates_InvalidPageParam(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
// Should default to page 1
|
||||
if filter.Page == 1 {
|
||||
return []domain.ManagedCertificate{}, 0, nil
|
||||
@@ -740,7 +740,7 @@ func TestListCertificates_InvalidPageParam(t *testing.T) {
|
||||
// Test ListCertificates - per_page exceeds max
|
||||
func TestListCertificates_PerPageExceedsMax(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
// Should cap perPage at 500
|
||||
if filter.PerPage == 50 { // defaults to 50 if > 500
|
||||
return []domain.ManagedCertificate{}, 0, nil
|
||||
@@ -765,7 +765,7 @@ func TestListCertificates_PerPageExceedsMax(t *testing.T) {
|
||||
|
||||
func TestRevokeCertificate_Handler_Success(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
RevokeCertificateFn: func(certID string, reason string) error {
|
||||
RevokeCertificateFn: func(_ context.Context, certID string, reason string, _ string) error {
|
||||
if certID != "mc-prod-001" {
|
||||
t.Errorf("expected certID mc-prod-001, got %s", certID)
|
||||
}
|
||||
@@ -798,7 +798,7 @@ func TestRevokeCertificate_Handler_Success(t *testing.T) {
|
||||
|
||||
func TestRevokeCertificate_Handler_NoBody(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
RevokeCertificateFn: func(certID string, reason string) error {
|
||||
RevokeCertificateFn: func(_ context.Context, certID string, reason string, _ string) error {
|
||||
// Empty reason is OK — service defaults to "unspecified"
|
||||
return nil
|
||||
},
|
||||
@@ -818,7 +818,7 @@ func TestRevokeCertificate_Handler_NoBody(t *testing.T) {
|
||||
|
||||
func TestRevokeCertificate_Handler_AlreadyRevoked(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
RevokeCertificateFn: func(certID string, reason string) error {
|
||||
RevokeCertificateFn: func(_ context.Context, certID string, reason string, _ string) error {
|
||||
return fmt.Errorf("certificate is already revoked")
|
||||
},
|
||||
}
|
||||
@@ -839,7 +839,7 @@ func TestRevokeCertificate_Handler_AlreadyRevoked(t *testing.T) {
|
||||
|
||||
func TestRevokeCertificate_Handler_NotFound(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
RevokeCertificateFn: func(certID string, reason string) error {
|
||||
RevokeCertificateFn: func(_ context.Context, certID string, reason string, _ string) error {
|
||||
return fmt.Errorf("failed to fetch certificate: not found")
|
||||
},
|
||||
}
|
||||
@@ -858,7 +858,7 @@ func TestRevokeCertificate_Handler_NotFound(t *testing.T) {
|
||||
|
||||
func TestRevokeCertificate_Handler_InvalidReason(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
RevokeCertificateFn: func(certID string, reason string) error {
|
||||
RevokeCertificateFn: func(_ context.Context, certID string, reason string, _ string) error {
|
||||
return fmt.Errorf("invalid revocation reason: badReason")
|
||||
},
|
||||
}
|
||||
@@ -922,7 +922,7 @@ func TestRevokeCertificate_Handler_EmptyID(t *testing.T) {
|
||||
|
||||
func TestRevokeCertificate_Handler_CannotRevokeArchived(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
RevokeCertificateFn: func(certID string, reason string) error {
|
||||
RevokeCertificateFn: func(_ context.Context, certID string, reason string, _ string) error {
|
||||
return fmt.Errorf("cannot revoke archived certificate")
|
||||
},
|
||||
}
|
||||
@@ -941,7 +941,7 @@ func TestRevokeCertificate_Handler_CannotRevokeArchived(t *testing.T) {
|
||||
|
||||
func TestRevokeCertificate_Handler_ServerError(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
RevokeCertificateFn: func(certID string, reason string) error {
|
||||
RevokeCertificateFn: func(_ context.Context, certID string, reason string, _ string) error {
|
||||
return fmt.Errorf("database connection lost")
|
||||
},
|
||||
}
|
||||
@@ -962,7 +962,7 @@ func TestRevokeCertificate_Handler_ServerError(t *testing.T) {
|
||||
|
||||
func TestGetCRL_Success(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GetRevokedCertificatesFn: func() ([]*domain.CertificateRevocation, error) {
|
||||
GetRevokedCertificatesFn: func(_ context.Context) ([]*domain.CertificateRevocation, error) {
|
||||
return []*domain.CertificateRevocation{
|
||||
{
|
||||
ID: "rev-1",
|
||||
@@ -1022,7 +1022,7 @@ func TestGetCRL_Success(t *testing.T) {
|
||||
|
||||
func TestGetCRL_Empty(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GetRevokedCertificatesFn: func() ([]*domain.CertificateRevocation, error) {
|
||||
GetRevokedCertificatesFn: func(_ context.Context) ([]*domain.CertificateRevocation, error) {
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
@@ -1047,7 +1047,7 @@ func TestGetCRL_Empty(t *testing.T) {
|
||||
|
||||
func TestGetCRL_ServiceError(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GetRevokedCertificatesFn: func() ([]*domain.CertificateRevocation, error) {
|
||||
GetRevokedCertificatesFn: func(_ context.Context) ([]*domain.CertificateRevocation, error) {
|
||||
return nil, fmt.Errorf("revocation repository not configured")
|
||||
},
|
||||
}
|
||||
@@ -1083,7 +1083,7 @@ func TestGetCRL_MethodNotAllowed(t *testing.T) {
|
||||
func TestGetDERCRL_Success(t *testing.T) {
|
||||
derCRLData := []byte{0x30, 0x82, 0x01, 0x00} // Mock DER CRL bytes
|
||||
mock := &MockCertificateService{
|
||||
GenerateDERCRLFn: func(issuerID string) ([]byte, error) {
|
||||
GenerateDERCRLFn: func(_ context.Context, issuerID string) ([]byte, error) {
|
||||
if issuerID == "iss-local" {
|
||||
return derCRLData, nil
|
||||
}
|
||||
@@ -1111,7 +1111,7 @@ func TestGetDERCRL_Success(t *testing.T) {
|
||||
|
||||
func TestGetDERCRL_IssuerNotFound(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GenerateDERCRLFn: func(issuerID string) ([]byte, error) {
|
||||
GenerateDERCRLFn: func(_ context.Context, issuerID string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("issuer not found")
|
||||
},
|
||||
}
|
||||
@@ -1130,7 +1130,7 @@ func TestGetDERCRL_IssuerNotFound(t *testing.T) {
|
||||
|
||||
func TestGetDERCRL_NotSupported(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GenerateDERCRLFn: func(issuerID string) ([]byte, error) {
|
||||
GenerateDERCRLFn: func(_ context.Context, issuerID string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("issuer does not support CRL generation")
|
||||
},
|
||||
}
|
||||
@@ -1165,7 +1165,7 @@ func TestGetDERCRL_MethodNotAllowed(t *testing.T) {
|
||||
func TestHandleOCSP_Success(t *testing.T) {
|
||||
ocspResponseBytes := []byte{0x30, 0x82, 0x02, 0x00} // Mock OCSP response
|
||||
mock := &MockCertificateService{
|
||||
GetOCSPResponseFn: func(issuerID string, serialHex string) ([]byte, error) {
|
||||
GetOCSPResponseFn: func(_ context.Context, issuerID string, serialHex string) ([]byte, error) {
|
||||
if issuerID == "iss-local" && serialHex == "12345" {
|
||||
return ocspResponseBytes, nil
|
||||
}
|
||||
@@ -1206,7 +1206,7 @@ func TestHandleOCSP_MissingSerial(t *testing.T) {
|
||||
|
||||
func TestHandleOCSP_IssuerNotFound(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GetOCSPResponseFn: func(issuerID string, serialHex string) ([]byte, error) {
|
||||
GetOCSPResponseFn: func(_ context.Context, issuerID string, serialHex string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("issuer not found")
|
||||
},
|
||||
}
|
||||
@@ -1225,7 +1225,7 @@ func TestHandleOCSP_IssuerNotFound(t *testing.T) {
|
||||
|
||||
func TestHandleOCSP_CertNotFound(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GetOCSPResponseFn: func(issuerID string, serialHex string) ([]byte, error) {
|
||||
GetOCSPResponseFn: func(_ context.Context, issuerID string, serialHex string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("certificate not found")
|
||||
},
|
||||
}
|
||||
@@ -1261,7 +1261,7 @@ func TestHandleOCSP_MethodNotAllowed(t *testing.T) {
|
||||
// TestListCertificates_SortParam tests sort parameter parsing and passing to service.
|
||||
func TestListCertificates_SortParam(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
// Handler strips the '-' prefix and sets SortDesc = true
|
||||
if filter.Sort != "notAfter" || !filter.SortDesc {
|
||||
t.Errorf("expected sort=notAfter desc=true, got sort=%s desc=%v", filter.Sort, filter.SortDesc)
|
||||
@@ -1284,7 +1284,7 @@ func TestListCertificates_SortParam(t *testing.T) {
|
||||
// TestListCertificates_SortParam_Ascending tests sort parameter without '-' prefix (ascending).
|
||||
func TestListCertificates_SortParam_Ascending(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if filter.Sort != "createdAt" || filter.SortDesc {
|
||||
t.Errorf("expected sort=createdAt desc=false, got sort=%s desc=%v", filter.Sort, filter.SortDesc)
|
||||
}
|
||||
@@ -1309,7 +1309,7 @@ func TestListCertificates_TimeRangeFilters(t *testing.T) {
|
||||
after := time.Now().AddDate(0, 0, -90)
|
||||
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if filter.ExpiresBefore == nil {
|
||||
t.Error("expected ExpiresBefore to be set")
|
||||
}
|
||||
@@ -1339,7 +1339,7 @@ func TestListCertificates_CreatedAfterFilter(t *testing.T) {
|
||||
past := time.Now().AddDate(-1, 0, 0)
|
||||
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if filter.CreatedAfter == nil {
|
||||
t.Error("expected CreatedAfter to be set")
|
||||
}
|
||||
@@ -1369,7 +1369,7 @@ func TestListCertificates_CursorPagination(t *testing.T) {
|
||||
}
|
||||
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
return []domain.ManagedCertificate{cert}, 1, nil
|
||||
},
|
||||
}
|
||||
@@ -1409,7 +1409,7 @@ func TestListCertificates_SparseFields(t *testing.T) {
|
||||
}
|
||||
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if len(filter.Fields) != 2 {
|
||||
t.Errorf("expected 2 fields, got %d", len(filter.Fields))
|
||||
}
|
||||
@@ -1456,7 +1456,7 @@ func TestListCertificates_SparseFields(t *testing.T) {
|
||||
// TestListCertificates_ProfileFilter tests profile_id filter.
|
||||
func TestListCertificates_ProfileFilter(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if filter.ProfileID != "prof-standard" {
|
||||
t.Errorf("expected ProfileID=prof-standard, got %s", filter.ProfileID)
|
||||
}
|
||||
@@ -1479,7 +1479,7 @@ func TestListCertificates_ProfileFilter(t *testing.T) {
|
||||
// TestListCertificates_AgentIDFilter tests agent_id filter.
|
||||
func TestListCertificates_AgentIDFilter(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if filter.AgentID != "agent-prod-001" {
|
||||
t.Errorf("expected AgentID=agent-prod-001, got %s", filter.AgentID)
|
||||
}
|
||||
@@ -1502,7 +1502,7 @@ func TestListCertificates_AgentIDFilter(t *testing.T) {
|
||||
// TestListCertificates_CombinedFilters tests multiple filters together.
|
||||
func TestListCertificates_CombinedFilters(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
ListCertificatesWithFilterFn: func(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
ListCertificatesWithFilterFn: func(_ context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error) {
|
||||
if filter.Status != "Active" || filter.Environment != "production" || filter.ProfileID != "prof-standard" {
|
||||
t.Error("expected all filters to be set")
|
||||
}
|
||||
@@ -1540,7 +1540,7 @@ func TestGetCertificateDeployments_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
mock := &MockCertificateService{
|
||||
GetCertificateDeploymentsFn: func(certID string) ([]domain.DeploymentTarget, error) {
|
||||
GetCertificateDeploymentsFn: func(_ context.Context, certID string) ([]domain.DeploymentTarget, error) {
|
||||
if certID != "mc-prod-001" {
|
||||
return nil, ErrMockNotFound
|
||||
}
|
||||
@@ -1576,7 +1576,7 @@ func TestGetCertificateDeployments_Success(t *testing.T) {
|
||||
// TestGetCertificateDeployments_NotFound tests 404 for nonexistent certificate.
|
||||
func TestGetCertificateDeployments_NotFound(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GetCertificateDeploymentsFn: func(certID string) ([]domain.DeploymentTarget, error) {
|
||||
GetCertificateDeploymentsFn: func(_ context.Context, certID string) ([]domain.DeploymentTarget, error) {
|
||||
return nil, fmt.Errorf("certificate not found")
|
||||
},
|
||||
}
|
||||
@@ -1596,7 +1596,7 @@ func TestGetCertificateDeployments_NotFound(t *testing.T) {
|
||||
// TestGetCertificateDeployments_Empty tests successful response with no deployments.
|
||||
func TestGetCertificateDeployments_Empty(t *testing.T) {
|
||||
mock := &MockCertificateService{
|
||||
GetCertificateDeploymentsFn: func(certID string) ([]domain.DeploymentTarget, error) {
|
||||
GetCertificateDeploymentsFn: func(_ context.Context, certID string) ([]domain.DeploymentTarget, error) {
|
||||
if certID == "mc-no-deployments" {
|
||||
return []domain.DeploymentTarget{}, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@@ -15,20 +16,20 @@ import (
|
||||
|
||||
// CertificateService defines the service interface for certificate operations.
|
||||
type CertificateService interface {
|
||||
ListCertificates(status, environment, ownerID, teamID, issuerID string, page, perPage int) ([]domain.ManagedCertificate, int64, error)
|
||||
ListCertificatesWithFilter(filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error)
|
||||
GetCertificate(id string) (*domain.ManagedCertificate, error)
|
||||
CreateCertificate(cert domain.ManagedCertificate) (*domain.ManagedCertificate, error)
|
||||
UpdateCertificate(id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error)
|
||||
ArchiveCertificate(id string) error
|
||||
GetCertificateVersions(certID string, page, perPage int) ([]domain.CertificateVersion, int64, error)
|
||||
TriggerRenewal(certID string) error
|
||||
TriggerDeployment(certID string, targetID string) error
|
||||
RevokeCertificate(certID string, reason string) error
|
||||
GetRevokedCertificates() ([]*domain.CertificateRevocation, error)
|
||||
GenerateDERCRL(issuerID string) ([]byte, error)
|
||||
GetOCSPResponse(issuerID string, serialHex string) ([]byte, error)
|
||||
GetCertificateDeployments(certID string) ([]domain.DeploymentTarget, error)
|
||||
ListCertificates(ctx context.Context, status, environment, ownerID, teamID, issuerID string, page, perPage int) ([]domain.ManagedCertificate, int64, error)
|
||||
ListCertificatesWithFilter(ctx context.Context, filter *repository.CertificateFilter) ([]domain.ManagedCertificate, int, error)
|
||||
GetCertificate(ctx context.Context, id string) (*domain.ManagedCertificate, error)
|
||||
CreateCertificate(ctx context.Context, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error)
|
||||
UpdateCertificate(ctx context.Context, id string, cert domain.ManagedCertificate) (*domain.ManagedCertificate, error)
|
||||
ArchiveCertificate(ctx context.Context, id string) error
|
||||
GetCertificateVersions(ctx context.Context, certID string, page, perPage int) ([]domain.CertificateVersion, int64, error)
|
||||
TriggerRenewal(ctx context.Context, certID string, actor string) error
|
||||
TriggerDeployment(ctx context.Context, certID string, targetID string, actor string) error
|
||||
RevokeCertificate(ctx context.Context, certID string, reason string, actor string) error
|
||||
GetRevokedCertificates(ctx context.Context) ([]*domain.CertificateRevocation, error)
|
||||
GenerateDERCRL(ctx context.Context, issuerID string) ([]byte, error)
|
||||
GetOCSPResponse(ctx context.Context, issuerID string, serialHex string) ([]byte, error)
|
||||
GetCertificateDeployments(ctx context.Context, certID string) ([]domain.DeploymentTarget, error)
|
||||
}
|
||||
|
||||
// CertificateHandler handles HTTP requests for certificate operations.
|
||||
@@ -128,7 +129,7 @@ func (h CertificateHandler) ListCertificates(w http.ResponseWriter, r *http.Requ
|
||||
filter.Fields = strings.Split(fieldsStr, ",")
|
||||
}
|
||||
|
||||
certs, total, err := h.svc.ListCertificatesWithFilter(filter)
|
||||
certs, total, err := h.svc.ListCertificatesWithFilter(r.Context(), filter)
|
||||
if err != nil {
|
||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to list certificates", requestID)
|
||||
return
|
||||
@@ -186,7 +187,7 @@ func (h CertificateHandler) GetCertificate(w http.ResponseWriter, r *http.Reques
|
||||
return
|
||||
}
|
||||
|
||||
cert, err := h.svc.GetCertificate(id)
|
||||
cert, err := h.svc.GetCertificate(r.Context(), id)
|
||||
if err != nil {
|
||||
ErrorWithRequestID(w, http.StatusNotFound, "Certificate not found", requestID)
|
||||
return
|
||||
@@ -241,7 +242,7 @@ func (h CertificateHandler) CreateCertificate(w http.ResponseWriter, r *http.Req
|
||||
return
|
||||
}
|
||||
|
||||
created, err := h.svc.CreateCertificate(cert)
|
||||
created, err := h.svc.CreateCertificate(r.Context(), cert)
|
||||
if err != nil {
|
||||
slog.Error("failed to create certificate", "error", err, "request_id", requestID, "common_name", cert.CommonName, "name", cert.Name)
|
||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to create certificate", requestID)
|
||||
@@ -295,7 +296,7 @@ func (h CertificateHandler) UpdateCertificate(w http.ResponseWriter, r *http.Req
|
||||
}
|
||||
}
|
||||
|
||||
updated, err := h.svc.UpdateCertificate(id, cert)
|
||||
updated, err := h.svc.UpdateCertificate(r.Context(), id, cert)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
ErrorWithRequestID(w, http.StatusNotFound, "Certificate not found", requestID)
|
||||
@@ -325,7 +326,7 @@ func (h CertificateHandler) ArchiveCertificate(w http.ResponseWriter, r *http.Re
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.svc.ArchiveCertificate(id); err != nil {
|
||||
if err := h.svc.ArchiveCertificate(r.Context(), id); err != nil {
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
ErrorWithRequestID(w, http.StatusNotFound, "Certificate not found", requestID)
|
||||
return
|
||||
@@ -370,7 +371,7 @@ func (h CertificateHandler) GetCertificateVersions(w http.ResponseWriter, r *htt
|
||||
}
|
||||
}
|
||||
|
||||
versions, total, err := h.svc.GetCertificateVersions(certID, page, perPage)
|
||||
versions, total, err := h.svc.GetCertificateVersions(r.Context(), certID, page, perPage)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
ErrorWithRequestID(w, http.StatusNotFound, "Certificate not found", requestID)
|
||||
@@ -410,7 +411,7 @@ func (h CertificateHandler) TriggerRenewal(w http.ResponseWriter, r *http.Reques
|
||||
}
|
||||
certID := parts[0]
|
||||
|
||||
if err := h.svc.TriggerRenewal(certID); err != nil {
|
||||
if err := h.svc.TriggerRenewal(r.Context(), certID, "api"); err != nil {
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "not found") {
|
||||
ErrorWithRequestID(w, http.StatusNotFound, "Certificate not found", requestID)
|
||||
@@ -466,7 +467,7 @@ func (h CertificateHandler) TriggerDeployment(w http.ResponseWriter, r *http.Req
|
||||
}
|
||||
}
|
||||
|
||||
if err := h.svc.TriggerDeployment(certID, req.TargetID); err != nil {
|
||||
if err := h.svc.TriggerDeployment(r.Context(), certID, req.TargetID, "api"); err != nil {
|
||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to trigger deployment", requestID)
|
||||
return
|
||||
}
|
||||
@@ -508,7 +509,7 @@ func (h CertificateHandler) RevokeCertificate(w http.ResponseWriter, r *http.Req
|
||||
}
|
||||
}
|
||||
|
||||
if err := h.svc.RevokeCertificate(certID, req.Reason); err != nil {
|
||||
if err := h.svc.RevokeCertificate(r.Context(), certID, req.Reason, "api"); err != nil {
|
||||
// Distinguish between client errors and server errors
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "already revoked") ||
|
||||
@@ -540,7 +541,7 @@ func (h CertificateHandler) GetCRL(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
requestID := middleware.GetRequestID(r.Context())
|
||||
|
||||
revocations, err := h.svc.GetRevokedCertificates()
|
||||
revocations, err := h.svc.GetRevokedCertificates(r.Context())
|
||||
if err != nil {
|
||||
ErrorWithRequestID(w, http.StatusInternalServerError, "Failed to generate CRL", requestID)
|
||||
return
|
||||
@@ -585,7 +586,7 @@ func (h CertificateHandler) GetDERCRL(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
derBytes, err := h.svc.GenerateDERCRL(issuerID)
|
||||
derBytes, err := h.svc.GenerateDERCRL(r.Context(), issuerID)
|
||||
if err != nil {
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "not found") {
|
||||
@@ -627,7 +628,7 @@ func (h CertificateHandler) HandleOCSP(w http.ResponseWriter, r *http.Request) {
|
||||
issuerID := parts[0]
|
||||
serialHex := parts[1]
|
||||
|
||||
derBytes, err := h.svc.GetOCSPResponse(issuerID, serialHex)
|
||||
derBytes, err := h.svc.GetOCSPResponse(r.Context(), issuerID, serialHex)
|
||||
if err != nil {
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "not found") {
|
||||
@@ -667,7 +668,7 @@ func (h CertificateHandler) GetCertificateDeployments(w http.ResponseWriter, r *
|
||||
}
|
||||
certID := parts[0]
|
||||
|
||||
deployments, err := h.svc.GetCertificateDeployments(certID)
|
||||
deployments, err := h.svc.GetCertificateDeployments(r.Context(), certID)
|
||||
if err != nil {
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "not found") {
|
||||
|
||||
Reference in New Issue
Block a user