diff --git a/apps/api-server/internal/handlers/api_integration_test.go b/apps/api-server/internal/handlers/api_integration_test.go index d57f8f9..af2c77e 100644 --- a/apps/api-server/internal/handlers/api_integration_test.go +++ b/apps/api-server/internal/handlers/api_integration_test.go @@ -207,7 +207,7 @@ func setupTest(t *testing.T) *TestSetup { } // Helper function to make authenticated requests -func (ts *TestSetup) makeRequest(method, path string, body interface{}, token string) *httptest.ResponseRecorder { +func (ts *TestSetup) makeRequest(method, path string, body any, token string) *httptest.ResponseRecorder { var reqBody *bytes.Buffer if body != nil { jsonBody, _ := json.Marshal(body) @@ -243,7 +243,7 @@ func TestAuthenticationEndpoints(t *testing.T) { w := ts.makeRequest("POST", "/v1/auth/login", loginData, "") assert.Equal(t, http.StatusOK, w.Code) - var response map[string]interface{} + var response map[string]any err := json.Unmarshal(w.Body.Bytes(), &response) require.NoError(t, err) assert.Contains(t, response, "access_token") @@ -293,7 +293,7 @@ func TestRBACPermissions(t *testing.T) { }) t.Run("Viewer cannot write to plugins", func(t *testing.T) { - pluginData := map[string]interface{}{ + pluginData := map[string]any{ "name": "test-plugin", "version": "1.0.0", } @@ -302,7 +302,7 @@ func TestRBACPermissions(t *testing.T) { }) t.Run("Admin can write to plugins", func(t *testing.T) { - pluginData := map[string]interface{}{ + pluginData := map[string]any{ "name": "test-plugin", "version": "1.0.0", } @@ -342,14 +342,14 @@ func TestPluginEndpoints(t *testing.T) { w := ts.makeRequest("GET", "/v1/plugins", nil, ts.AdminToken) assert.Equal(t, http.StatusOK, w.Code) - var response map[string]interface{} + var response map[string]any err := json.Unmarshal(w.Body.Bytes(), &response) require.NoError(t, err) assert.Contains(t, response, "plugins") }) t.Run("Install plugin without permissions", func(t *testing.T) { - pluginData := map[string]interface{}{ + pluginData := map[string]any{ "name": "test-plugin", "version": "1.0.0", } @@ -372,14 +372,14 @@ func TestAutomationEndpoints(t *testing.T) { w := ts.makeRequest("GET", "/v1/automation", nil, ts.AdminToken) assert.Equal(t, http.StatusOK, w.Code) - var response map[string]interface{} + var response map[string]any err := json.Unmarshal(w.Body.Bytes(), &response) require.NoError(t, err) assert.Contains(t, response, "automations") }) t.Run("Create automation without permissions", func(t *testing.T) { - automationData := map[string]interface{}{ + automationData := map[string]any{ "name": "test-automation", "description": "Test automation", "type": "scheduled", @@ -389,7 +389,7 @@ func TestAutomationEndpoints(t *testing.T) { }) t.Run("Create automation with operator permissions", func(t *testing.T) { - automationData := map[string]interface{}{ + automationData := map[string]any{ "name": "test-automation", "description": "Test automation", "type": "scheduled", @@ -410,7 +410,7 @@ func TestConfigurationEndpoints(t *testing.T) { }) t.Run("Update configuration without permissions", func(t *testing.T) { - configData := map[string]interface{}{ + configData := map[string]any{ "section": "test", "key": "test.config", "value": "test-value", @@ -421,7 +421,7 @@ func TestConfigurationEndpoints(t *testing.T) { }) t.Run("Update configuration with admin permissions", func(t *testing.T) { - configData := map[string]interface{}{ + configData := map[string]any{ "section": "test", "key": "test.config", "value": "test-value", @@ -441,7 +441,7 @@ func TestChaosEndpoints(t *testing.T) { w := ts.makeRequest("GET", "/v1/chaos", nil, ts.AdminToken) assert.Equal(t, http.StatusOK, w.Code) - var response map[string]interface{} + var response map[string]any err := json.Unmarshal(w.Body.Bytes(), &response) require.NoError(t, err) assert.Contains(t, response, "active") @@ -449,7 +449,7 @@ func TestChaosEndpoints(t *testing.T) { }) t.Run("Run chaos experiment without permissions", func(t *testing.T) { - chaosData := map[string]interface{}{ + chaosData := map[string]any{ "name": "test-chaos", "type": "pod-delete", "target": "test-pod", @@ -460,7 +460,7 @@ func TestChaosEndpoints(t *testing.T) { }) t.Run("Run chaos experiment with admin permissions", func(t *testing.T) { - chaosData := map[string]interface{}{ + chaosData := map[string]any{ "name": "test-chaos", "type": "pod-delete", "target": "test-pod", @@ -486,7 +486,7 @@ func TestErrorHandling(t *testing.T) { }) t.Run("Missing required fields", func(t *testing.T) { - pluginData := map[string]interface{}{ + pluginData := map[string]any{ "version": "1.0.0", // Missing name field } diff --git a/apps/api-server/internal/logging/logging.go b/apps/api-server/internal/logging/logging.go index 6edcd0d..01f7acb 100644 --- a/apps/api-server/internal/logging/logging.go +++ b/apps/api-server/internal/logging/logging.go @@ -11,9 +11,9 @@ var Logger *logrus.Logger // Config holds logging configuration type Config struct { - Level string - Format string // "json" or "text" - Output string // "stdout" or "stderr" + Level string + Format string // "json" or "text" + Output string // "stdout" or "stderr" } // DefaultConfig returns default logging configuration @@ -76,7 +76,7 @@ func InitWithDefaults() error { } // WithField returns a logger with a single field -func WithField(key string, value interface{}) *logrus.Entry { +func WithField(key string, value any) *logrus.Entry { return Logger.WithField(key, value) } @@ -91,51 +91,51 @@ func WithError(err error) *logrus.Entry { } // Info logs an info message -func Info(args ...interface{}) { +func Info(args ...any) { Logger.Info(args...) } // Infof logs a formatted info message -func Infof(format string, args ...interface{}) { +func Infof(format string, args ...any) { Logger.Infof(format, args...) } // Warn logs a warning message -func Warn(args ...interface{}) { +func Warn(args ...any) { Logger.Warn(args...) } // Warnf logs a formatted warning message -func Warnf(format string, args ...interface{}) { +func Warnf(format string, args ...any) { Logger.Warnf(format, args...) } // Error logs an error message -func Error(args ...interface{}) { +func Error(args ...any) { Logger.Error(args...) } // Errorf logs a formatted error message -func Errorf(format string, args ...interface{}) { +func Errorf(format string, args ...any) { Logger.Errorf(format, args...) } // Fatal logs a fatal message and exits -func Fatal(args ...interface{}) { +func Fatal(args ...any) { Logger.Fatal(args...) } // Fatalf logs a formatted fatal message and exits -func Fatalf(format string, args ...interface{}) { +func Fatalf(format string, args ...any) { Logger.Fatalf(format, args...) } // Debug logs a debug message -func Debug(args ...interface{}) { +func Debug(args ...any) { Logger.Debug(args...) } // Debugf logs a formatted debug message -func Debugf(format string, args ...interface{}) { +func Debugf(format string, args ...any) { Logger.Debugf(format, args...) } diff --git a/apps/api-server/internal/middleware/etag.go b/apps/api-server/internal/middleware/etag.go index 976a6cf..69c3de1 100644 --- a/apps/api-server/internal/middleware/etag.go +++ b/apps/api-server/internal/middleware/etag.go @@ -56,33 +56,33 @@ func NewETagGenerator(secretKey string) *ETagGenerator { func (g *ETagGenerator) GenerateETag(data ETagData) string { // Create a composite hash from multiple factors h := sha256.New() - + // Include path and method h.Write([]byte(data.Path)) h.Write([]byte(data.Method)) - + // Include content if available if len(data.Content) > 0 { h.Write(data.Content) } - + // Include timestamp (rounded to second for consistency) - timestampBytes := []byte(fmt.Sprintf("%d", data.Timestamp.Unix())) + timestampBytes := fmt.Appendf(nil, "%d", data.Timestamp.Unix()) h.Write(timestampBytes) - + // Include user context for personalized responses if data.UserID != "" { h.Write([]byte(data.UserID)) } - + // Include query parameters for cache differentiation if data.Params != "" { h.Write([]byte(data.Params)) } - + // Add secret key for security h.Write(g.secretKey) - + // Generate final ETag hash := h.Sum(nil) return fmt.Sprintf("\"%x\"", hash) @@ -111,7 +111,7 @@ func (g *ETagGenerator) CacheETag(key, etag string) { // InvalidateCache removes ETag entries matching a pattern func (g *ETagGenerator) InvalidateCache(pattern string) { - g.cacheStorage.Range(func(key, value interface{}) bool { + g.cacheStorage.Range(func(key, value any) bool { if keyStr, ok := key.(string); ok { if strings.Contains(keyStr, pattern) { g.cacheStorage.Delete(key) @@ -133,26 +133,26 @@ func generateETag(c *gin.Context) string { Timestamp: time.Now(), Params: c.Request.URL.RawQuery, } - + // Add user context if available if userID, exists := c.Get("user_id"); exists { if idStr, ok := userID.(string); ok { data.UserID = idStr } } - + // Try to get cached ETag first cacheKey := fmt.Sprintf("%s:%s:%s", data.Method, data.Path, data.Params) if cached, exists := etagGenerator.GetCachedETag(cacheKey); exists { return cached } - + // Generate new ETag etag := etagGenerator.GenerateETag(data) - + // Cache the ETag for future use etagGenerator.CacheETag(cacheKey, etag) - + return etag } @@ -165,14 +165,14 @@ func generateContentETag(c *gin.Context, content []byte) string { Timestamp: time.Now(), Params: c.Request.URL.RawQuery, } - + // Add user context if available if userID, exists := c.Get("user_id"); exists { if idStr, ok := userID.(string); ok { data.UserID = idStr } } - + return etagGenerator.GenerateETag(data) } @@ -184,14 +184,14 @@ func generateWeakETag(c *gin.Context) string { Timestamp: time.Now(), Params: c.Request.URL.RawQuery, } - + // Add user context if available if userID, exists := c.Get("user_id"); exists { if idStr, ok := userID.(string); ok { data.UserID = idStr } } - + return etagGenerator.GenerateWeakETag(data) } @@ -203,12 +203,12 @@ func ETagValidationMiddleware() gin.HandlerFunc { c.Next() return } - + // Check If-None-Match header (for GET requests) if noneMatch := c.GetHeader("If-None-Match"); noneMatch != "" { // Generate current ETag currentETag := generateETag(c) - + // Check if any of the ETags match if etagMatches(noneMatch, currentETag) { c.Header("ETag", currentETag) @@ -217,18 +217,18 @@ func ETagValidationMiddleware() gin.HandlerFunc { return } } - + // Check If-Match header (for PUT/PATCH/DELETE requests) if match := c.GetHeader("If-Match"); match != "" { currentETag := generateETag(c) - + if !etagMatches(match, currentETag) { c.Status(http.StatusPreconditionFailed) c.Abort() return } } - + c.Next() } } @@ -242,14 +242,14 @@ func ContentBasedETagMiddleware() gin.HandlerFunc { body: bytes.NewBuffer(nil), } c.Writer = wrapper - + c.Next() - + // Only generate ETags for successful GET requests if c.Request.Method != "GET" || c.Writer.Status() != http.StatusOK { return } - + // Generate ETag based on captured response content responseBody := wrapper.Body() if len(responseBody) > 0 { @@ -268,15 +268,15 @@ func CacheInvalidationMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // Store original request for post-processing c.Next() - + // Invalidate cache for POST, PUT, PATCH, DELETE requests - if c.Request.Method == "POST" || c.Request.Method == "PUT" || - c.Request.Method == "PATCH" || c.Request.Method == "DELETE" { - + if c.Request.Method == "POST" || c.Request.Method == "PUT" || + c.Request.Method == "PATCH" || c.Request.Method == "DELETE" { + // Invalidate ETags for this resource pattern pattern := c.Request.URL.Path etagGenerator.InvalidateCache(pattern) - + // Also invalidate related collection resources if strings.Contains(pattern, "/") { parts := strings.Split(strings.Trim(pattern, "/"), "/") @@ -295,19 +295,19 @@ func etagMatches(headerValue, currentETag string) bool { if headerValue == "*" { return true } - + // Parse the header value (can contain multiple ETags) - etags := strings.Split(headerValue, ",") - for _, etag := range etags { + etags := strings.SplitSeq(headerValue, ",") + for etag := range etags { etag = strings.TrimSpace(etag) // Remove quotes for comparison etag = strings.Trim(etag, "\"") current := strings.Trim(currentETag, "\"W/") - + if etag == current || etag == "W/"+current { return true } } - + return false } diff --git a/apps/api-server/internal/middleware/redis_ratelimit.go b/apps/api-server/internal/middleware/redis_ratelimit.go index a47bb3e..e2fe410 100644 --- a/apps/api-server/internal/middleware/redis_ratelimit.go +++ b/apps/api-server/internal/middleware/redis_ratelimit.go @@ -13,7 +13,7 @@ import ( // RedisClientInterface defines the interface for Redis operations type RedisClientInterface interface { - Eval(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd + Eval(ctx context.Context, script string, keys []string, args ...any) *redis.Cmd Del(ctx context.Context, keys ...string) *redis.IntCmd ZCount(ctx context.Context, key, min, max string) *redis.IntCmd } @@ -90,7 +90,7 @@ func (r *RedisRateLimiter) Allow(ctx context.Context, key string) (*RateLimitRes } // Parse Lua script result - resultSlice, ok := result.([]interface{}) + resultSlice, ok := result.([]any) if !ok || len(resultSlice) < 3 { return nil, fmt.Errorf("invalid redis result format") } @@ -163,7 +163,7 @@ func (r *RedisRateLimiter) AllowTokenBucket(ctx context.Context, key string) (*R return nil, fmt.Errorf("redis token bucket check failed: %w", err) } - resultSlice, ok := result.([]interface{}) + resultSlice, ok := result.([]any) if !ok || len(resultSlice) < 3 { return nil, fmt.Errorf("invalid redis result format") } @@ -207,10 +207,7 @@ func (r *RedisRateLimiter) GetStats(ctx context.Context, key string) (*RateLimit return nil, fmt.Errorf("failed to get rate limit stats: %w", err) } - remaining := r.limit - int64(count) - if remaining < 0 { - remaining = 0 - } + remaining := max(r.limit-int64(count), 0) return &RateLimitResult{ Allowed: remaining > 0, diff --git a/apps/api-server/internal/middleware/redis_ratelimit_test.go b/apps/api-server/internal/middleware/redis_ratelimit_test.go index 9e74883..5c9744e 100644 --- a/apps/api-server/internal/middleware/redis_ratelimit_test.go +++ b/apps/api-server/internal/middleware/redis_ratelimit_test.go @@ -18,8 +18,8 @@ type MockRedisClient struct { mock.Mock } -func (m *MockRedisClient) Eval(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd { - argsList := make([]interface{}, 0, len(keys)+len(args)+1) +func (m *MockRedisClient) Eval(ctx context.Context, script string, keys []string, args ...any) *redis.Cmd { + argsList := make([]any, 0, len(keys)+len(args)+1) argsList = append(argsList, script) for _, key := range keys { argsList = append(argsList, key) @@ -55,11 +55,11 @@ func TestRedisRateLimiter_Allow(t *testing.T) { mockClient := new(MockRedisClient) // Mock Redis response based on test case - var mockResult []interface{} + var mockResult []any if tt.expected { - mockResult = []interface{}{int64(1), int64(tt.limit - 1), int64(time.Now().Unix() + 60)} + mockResult = []any{int64(1), int64(tt.limit - 1), int64(time.Now().Unix() + 60)} } else { - mockResult = []interface{}{int64(0), int64(0), int64(time.Now().Unix() + 60), int64(30)} + mockResult = []any{int64(0), int64(0), int64(time.Now().Unix() + 60), int64(30)} } cmd := redis.NewCmd(context.Background()) @@ -115,7 +115,7 @@ func TestRedisRateLimitMiddleware(t *testing.T) { // Mock successful rate limit check cmd := redis.NewCmd(context.Background()) - cmd.SetVal([]interface{}{int64(1), int64(4), int64(time.Now().Unix() + 60)}) + cmd.SetVal([]any{int64(1), int64(4), int64(time.Now().Unix() + 60)}) mockClient.On("Eval", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("int64"), mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(cmd) // Create rate limiter with mock client @@ -267,10 +267,10 @@ func TestMultiTierRateLimiter(t *testing.T) { // Mock different tier responses freeCmd := redis.NewCmd(context.Background()) - freeCmd.SetVal([]interface{}{int64(1), int64(9), int64(time.Now().Unix() + 60)}) + freeCmd.SetVal([]any{int64(1), int64(9), int64(time.Now().Unix() + 60)}) premiumCmd := redis.NewCmd(context.Background()) - premiumCmd.SetVal([]interface{}{int64(1), int64(99), int64(time.Now().Unix() + 60)}) + premiumCmd.SetVal([]any{int64(1), int64(99), int64(time.Now().Unix() + 60)}) mockClient.On("Eval", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("int64"), mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(freeCmd).Once() mockClient.On("Eval", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("int64"), mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(premiumCmd).Once() diff --git a/apps/api-server/internal/mq/mq.go b/apps/api-server/internal/mq/mq.go index f777b84..fb55c67 100644 --- a/apps/api-server/internal/mq/mq.go +++ b/apps/api-server/internal/mq/mq.go @@ -20,9 +20,9 @@ type MessageQueue struct { // Message represents a message to be sent/received type Message struct { - Type string `json:"type"` - Payload map[string]interface{} `json:"payload"` - Timestamp time.Time `json:"timestamp"` + Type string `json:"type"` + Payload map[string]any `json:"payload"` + Timestamp time.Time `json:"timestamp"` } // NewMessageQueue creates a new message queue connection @@ -162,10 +162,10 @@ func (mq *MessageQueue) PublishToExchange(exchange, routingKey string, msg Messa err = mq.channel.PublishWithContext( ctx, - exchange, // exchange - routingKey, // routing key - false, // mandatory - false, // immediate + exchange, // exchange + routingKey, // routing key + false, // mandatory + false, // immediate amqp.Publishing{ ContentType: "application/json", DeliveryMode: amqp.Persistent, diff --git a/apps/api-server/internal/services/automation_service_test.go b/apps/api-server/internal/services/automation_service_test.go index 315f685..75475e4 100644 --- a/apps/api-server/internal/services/automation_service_test.go +++ b/apps/api-server/internal/services/automation_service_test.go @@ -147,8 +147,8 @@ func TestAutomationService_Create(t *testing.T) { _, service := setupAutomationTest(t) t.Run("Create automation successfully", func(t *testing.T) { - definition := map[string]interface{}{ - "actions": []map[string]interface{}{ + definition := map[string]any{ + "actions": []map[string]any{ { "type": "restart", "target": "service", @@ -313,7 +313,7 @@ func BenchmarkAutomationService_List(b *testing.B) { db, service := setupAutomationTest(&testing.T{}) // Create test automations - for i := 0; i < 100; i++ { + for i := range 100 { automation := models.Automation{ Name: fmt.Sprintf("automation-%d", i), Description: "Test automation", diff --git a/apps/api-server/internal/services/plugin_service_test.go b/apps/api-server/internal/services/plugin_service_test.go index 2e0d6b5..0b7fd52 100644 --- a/apps/api-server/internal/services/plugin_service_test.go +++ b/apps/api-server/internal/services/plugin_service_test.go @@ -110,7 +110,7 @@ func TestPluginService_Install(t *testing.T) { _, service := setupPluginTest(t) t.Run("Install new plugin successfully", func(t *testing.T) { - configJSON, _ := json.Marshal(map[string]interface{}{"key": "value"}) + configJSON, _ := json.Marshal(map[string]any{"key": "value"}) input := InstallPluginInput{ Name: "new-plugin", Version: "1.0.0", @@ -235,7 +235,7 @@ func BenchmarkPluginService_List(b *testing.B) { db, service := setupPluginTest(&testing.T{}) // Create test plugins - for i := 0; i < 100; i++ { + for i := range 100 { plugin := models.Plugin{ Name: fmt.Sprintf("plugin-%d", i), Version: "1.0.0", diff --git a/apps/carrier-connector/internal/handler/handlers.go b/apps/carrier-connector/internal/handler/handlers.go index f2dc52a..ddf6a59 100644 --- a/apps/carrier-connector/internal/handler/handlers.go +++ b/apps/carrier-connector/internal/handler/handlers.go @@ -43,7 +43,7 @@ func CheckConnectivityHandler(client *es2.ES2Client) gin.HandlerFunc { _, err := client.GetProfileStatus(context.Background(), req) connected := err == nil - var errMsg interface{} + var errMsg any if err != nil { errMsg = err.Error() } diff --git a/apps/carrier-connector/internal/handler/profile_handlers.go b/apps/carrier-connector/internal/handler/profile_handlers.go index 7903f8b..7fce503 100644 --- a/apps/carrier-connector/internal/handler/profile_handlers.go +++ b/apps/carrier-connector/internal/handler/profile_handlers.go @@ -71,7 +71,7 @@ func OrderProfileHandlerWithRepo(client *es2.ES2Client, repo repository.ProfileR // Send webhook notification for successful download if webhookClient != nil { - go webhookClient.SendProfileDownloaded(context.Background(), order.ICCID, map[string]interface{}{ + go webhookClient.SendProfileDownloaded(context.Background(), order.ICCID, map[string]any{ "imsi": order.IMSI, "profileType": order.ProfileType, "status": downloadResp.ExecutionStatus, @@ -141,10 +141,7 @@ func GetProfileHandlerWithRepo(client *es2.ES2Client, repo repository.ProfileRep func ListProfilesHandlerWithRepo(repo repository.ProfileRepository) gin.HandlerFunc { return func(c *gin.Context) { page := parsePositiveInt(c.Query("page"), 1) - limit := parsePositiveInt(c.Query("limit"), 20) - if limit > 100 { - limit = 100 - } + limit := min(parsePositiveInt(c.Query("limit"), 20), 100) Logger.Info().Int("page", page).Int("limit", limit).Msg("Listing eSIM profiles") @@ -194,7 +191,7 @@ func DeleteProfileHandlerWithRepo(client *es2.ES2Client, repo repository.Profile // Send webhook notification for profile deletion if webhookClient != nil { - go webhookClient.SendProfileDeleted(context.Background(), profileID, map[string]interface{}{ + go webhookClient.SendProfileDeleted(context.Background(), profileID, map[string]any{ "executionStatus": deleteResp.ExecutionStatus, "statusMessage": deleteResp.StatusMessage, }) diff --git a/apps/carrier-connector/internal/webhook/client.go b/apps/carrier-connector/internal/webhook/client.go index b89b3c2..7918643 100644 --- a/apps/carrier-connector/internal/webhook/client.go +++ b/apps/carrier-connector/internal/webhook/client.go @@ -29,18 +29,18 @@ func NewWebhookClient(webhookURL, apiKey string) *WebhookClient { // WebhookEvent represents a webhook notification event type WebhookEvent struct { - EventType string `json:"event_type"` - Timestamp time.Time `json:"timestamp"` - ProfileICCID string `json:"profile_iccid"` - Data map[string]interface{} `json:"data"` + EventType string `json:"event_type"` + Timestamp time.Time `json:"timestamp"` + ProfileICCID string `json:"profile_iccid"` + Data map[string]any `json:"data"` } // Event types const ( EventProfileDownloaded = "profile.downloaded" - EventProfileActivated = "profile.activated" - EventProfileDeactivated = "profile.deactivated" - EventProfileDeleted = "profile.deleted" + EventProfileActivated = "profile.activated" + EventProfileDeactivated = "profile.deactivated" + EventProfileDeleted = "profile.deleted" EventProfileStatusChange = "profile.status_changed" EventDownloadFailed = "download.failed" ) @@ -80,34 +80,34 @@ func (w *WebhookClient) SendNotification(ctx context.Context, event *WebhookEven } // SendProfileDownloaded sends a notification when a profile is downloaded -func (w *WebhookClient) SendProfileDownloaded(ctx context.Context, iccid string, data map[string]interface{}) error { +func (w *WebhookClient) SendProfileDownloaded(ctx context.Context, iccid string, data map[string]any) error { event := &WebhookEvent{ - EventType: EventProfileDownloaded, - Timestamp: time.Now(), + EventType: EventProfileDownloaded, + Timestamp: time.Now(), ProfileICCID: iccid, - Data: data, + Data: data, } return w.SendNotification(ctx, event) } // SendProfileActivated sends a notification when a profile is activated -func (w *WebhookClient) SendProfileActivated(ctx context.Context, iccid string, data map[string]interface{}) error { +func (w *WebhookClient) SendProfileActivated(ctx context.Context, iccid string, data map[string]any) error { event := &WebhookEvent{ - EventType: EventProfileActivated, - Timestamp: time.Now(), + EventType: EventProfileActivated, + Timestamp: time.Now(), ProfileICCID: iccid, - Data: data, + Data: data, } return w.SendNotification(ctx, event) } // SendProfileDeleted sends a notification when a profile is deleted -func (w *WebhookClient) SendProfileDeleted(ctx context.Context, iccid string, data map[string]interface{}) error { +func (w *WebhookClient) SendProfileDeleted(ctx context.Context, iccid string, data map[string]any) error { event := &WebhookEvent{ - EventType: EventProfileDeleted, - Timestamp: time.Now(), + EventType: EventProfileDeleted, + Timestamp: time.Now(), ProfileICCID: iccid, - Data: data, + Data: data, } return w.SendNotification(ctx, event) } @@ -115,10 +115,10 @@ func (w *WebhookClient) SendProfileDeleted(ctx context.Context, iccid string, da // SendDownloadFailed sends a notification when a profile download fails func (w *WebhookClient) SendDownloadFailed(ctx context.Context, iccid string, errorMessage string) error { event := &WebhookEvent{ - EventType: EventDownloadFailed, - Timestamp: time.Now(), + EventType: EventDownloadFailed, + Timestamp: time.Now(), ProfileICCID: iccid, - Data: map[string]interface{}{ + Data: map[string]any{ "error": errorMessage, }, } diff --git a/apps/cli/internal/types/config.go b/apps/cli/internal/types/config.go index 341feb5..da5e53c 100644 --- a/apps/cli/internal/types/config.go +++ b/apps/cli/internal/types/config.go @@ -1,9 +1,9 @@ package types import ( - "slices" "fmt" "net/url" + "slices" "strings" ) @@ -51,13 +51,7 @@ func (c *CLIConfig) Validate() []error { // Validate theme validThemes := []string{"default", "light", "dark", "high-contrast"} if c.Theme != "" { - valid := false - for _, t := range validThemes { - if c.Theme == t { - valid = true - break - } - } + valid := slices.Contains(validThemes, c.Theme) if !valid { errors = append(errors, fmt.Errorf("invalid theme '%s', must be one of: %v", c.Theme, validThemes)) }