This commit is contained in:
2025-08-25 21:28:14 -04:00
parent efa2ee5b59
commit 19364fcc76
11 changed files with 1208 additions and 13 deletions

View File

@ -189,6 +189,7 @@ test_application_endpoints() {
"app_link": "https://example.com/test-app",
"type": ["static"],
"callback_url": "https://example.com/callback",
"token_prefix": "TEST",
"token_renewal_duration": 604800000000000,
"max_token_duration": 2592000000000000,
"owner": {

View File

@ -96,8 +96,11 @@ func (suite *IntegrationTestSuite) setupServer() {
// Create a no-op logger for tests
logger := zap.NewNop()
// Initialize repositories
auditRepo := NewMockAuditRepository()
// Initialize services
appService := services.NewApplicationService(appRepo, logger)
appService := services.NewApplicationService(appRepo, auditRepo, logger)
tokenService := services.NewTokenService(tokenRepo, appRepo, permRepo, grantRepo, suite.cfg.GetString("INTERNAL_HMAC_KEY"), suite.cfg, logger)
authService := services.NewAuthenticationService(suite.cfg, logger, permRepo)

View File

@ -7,6 +7,7 @@ import (
"time"
"github.com/google/uuid"
"github.com/kms/api-key-service/internal/audit"
"github.com/kms/api-key-service/internal/domain"
"github.com/kms/api-key-service/internal/repository"
)
@ -612,3 +613,204 @@ func (m *MockGrantedPermissionRepository) HasAnyPermission(ctx context.Context,
return result, nil
}
// MockAuditRepository implements AuditRepository for testing
type MockAuditRepository struct {
mu sync.RWMutex
events []*audit.AuditEvent
}
func NewMockAuditRepository() repository.AuditRepository {
return &MockAuditRepository{
events: make([]*audit.AuditEvent, 0),
}
}
func (m *MockAuditRepository) Create(ctx context.Context, event *audit.AuditEvent) error {
m.mu.Lock()
defer m.mu.Unlock()
if event.ID == uuid.Nil {
event.ID = uuid.New()
}
if event.Timestamp.IsZero() {
event.Timestamp = time.Now().UTC()
}
m.events = append(m.events, event)
return nil
}
func (m *MockAuditRepository) Query(ctx context.Context, filter *audit.AuditFilter) ([]*audit.AuditEvent, error) {
m.mu.RLock()
defer m.mu.RUnlock()
var result []*audit.AuditEvent
for _, event := range m.events {
// Simple filtering logic for testing
if len(filter.EventTypes) > 0 {
found := false
for _, t := range filter.EventTypes {
if event.Type == t {
found = true
break
}
}
if !found {
continue
}
}
if filter.ActorID != "" && event.ActorID != filter.ActorID {
continue
}
if filter.ResourceID != "" && event.ResourceID != filter.ResourceID {
continue
}
if filter.ResourceType != "" && event.ResourceType != filter.ResourceType {
continue
}
result = append(result, event)
}
// Apply pagination
if filter.Offset >= len(result) {
return []*audit.AuditEvent{}, nil
}
end := filter.Offset + filter.Limit
if end > len(result) {
end = len(result)
}
return result[filter.Offset:end], nil
}
func (m *MockAuditRepository) GetStats(ctx context.Context, filter *audit.AuditStatsFilter) (*audit.AuditStats, error) {
m.mu.RLock()
defer m.mu.RUnlock()
stats := &audit.AuditStats{
TotalEvents: len(m.events),
ByType: make(map[audit.EventType]int),
BySeverity: make(map[audit.EventSeverity]int),
ByStatus: make(map[audit.EventStatus]int),
}
for _, event := range m.events {
stats.ByType[event.Type]++
stats.BySeverity[event.Severity]++
stats.ByStatus[event.Status]++
}
return stats, nil
}
func (m *MockAuditRepository) DeleteOldEvents(ctx context.Context, olderThan time.Time) (int, error) {
m.mu.Lock()
defer m.mu.Unlock()
var kept []*audit.AuditEvent
deleted := 0
for _, event := range m.events {
if event.Timestamp.Before(olderThan) {
deleted++
} else {
kept = append(kept, event)
}
}
m.events = kept
return deleted, nil
}
func (m *MockAuditRepository) GetByID(ctx context.Context, eventID uuid.UUID) (*audit.AuditEvent, error) {
m.mu.RLock()
defer m.mu.RUnlock()
for _, event := range m.events {
if event.ID == eventID {
return event, nil
}
}
return nil, fmt.Errorf("audit event with ID '%s' not found", eventID)
}
func (m *MockAuditRepository) GetByRequestID(ctx context.Context, requestID string) ([]*audit.AuditEvent, error) {
m.mu.RLock()
defer m.mu.RUnlock()
var result []*audit.AuditEvent
for _, event := range m.events {
if event.RequestID == requestID {
result = append(result, event)
}
}
return result, nil
}
func (m *MockAuditRepository) GetBySession(ctx context.Context, sessionID string) ([]*audit.AuditEvent, error) {
m.mu.RLock()
defer m.mu.RUnlock()
var result []*audit.AuditEvent
for _, event := range m.events {
if event.SessionID == sessionID {
result = append(result, event)
}
}
return result, nil
}
func (m *MockAuditRepository) GetByActor(ctx context.Context, actorID string, limit, offset int) ([]*audit.AuditEvent, error) {
m.mu.RLock()
defer m.mu.RUnlock()
var matching []*audit.AuditEvent
for _, event := range m.events {
if event.ActorID == actorID {
matching = append(matching, event)
}
}
if offset >= len(matching) {
return []*audit.AuditEvent{}, nil
}
end := offset + limit
if end > len(matching) {
end = len(matching)
}
return matching[offset:end], nil
}
func (m *MockAuditRepository) GetByResource(ctx context.Context, resourceType, resourceID string, limit, offset int) ([]*audit.AuditEvent, error) {
m.mu.RLock()
defer m.mu.RUnlock()
var matching []*audit.AuditEvent
for _, event := range m.events {
if event.ResourceType == resourceType && event.ResourceID == resourceID {
matching = append(matching, event)
}
}
if offset >= len(matching) {
return []*audit.AuditEvent{}, nil
}
end := offset + limit
if end > len(matching) {
end = len(matching)
}
return matching[offset:end], nil
}