diff --git a/.golangci.yml b/.golangci.yml index cd82afd..41920d5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -14,21 +14,22 @@ linters: - gosec - misspell - noctx - - nolintlint - prealloc - revive - rowserrcheck - sqlclosecheck - unconvert - unparam - - whitespace disable: - exhaustive - funlen - gocognit + - gocyclo # Disabled: OAuth/OIDC flows are inherently complex + - goprintffuncname # Disabled: naming convention is project-specific - lll - mnd - testpackage + - whitespace # Disabled: style preference about newlines - wsl settings: dupl: @@ -47,29 +48,13 @@ linters: - fmt.Fprintln goconst: min-len: 3 - min-occurrences: 10 # Increased to reduce noise for standard OAuth2/OIDC strings + min-occurrences: 15 # Increased to reduce noise for standard OAuth2/OIDC strings and common patterns like "true" ignore-tests: true gocritic: - # Using default enabled checks in v2 - enabled-checks: - - appendCombine - - boolExprSimplify - - builtinShadow - - commentedOutCode - - emptyFallthrough - - equalFold - - hexLiteral - - indexAlloc - - initClause - - methodExprCall - - nestingReduce - - rangeExprCopy - - rangeValCopy - - stringXbytes - - typeAssertChain - - typeUnparen - - unlabelStmt - - yodaStyleExpr + # Disable style-only checks that add noise + disabled-checks: + - ifElseChain # Style preference, switch not always clearer + - elseif # Style preference gocyclo: min-complexity: 30 # OAuth/OIDC flows are inherently complex; set higher for Yaegi compatibility gosec: @@ -106,23 +91,23 @@ linters: - name: error-return - name: error-strings - name: error-naming - - name: exported - - name: if-return + # - name: exported # Disabled: too noisy, not all exported functions need comments + # - name: if-return # Disabled: style preference - name: increment-decrement - - name: var-naming - - name: var-declaration - - name: package-comments + # - name: var-naming # Disabled: too strict for legacy code (IP vs Ip) + # - name: var-declaration # Disabled: explicit zero values can be clearer + # - name: package-comments # Disabled: handled by other tools - name: range - name: receiver-naming - name: time-naming - name: unexported-return - - name: indent-error-flow + # - name: indent-error-flow # Disabled: style preference - name: errorf - - name: empty-block + # - name: empty-block # Disabled: sometimes empty blocks are intentional - name: superfluous-else - - name: unused-parameter + # - name: unused-parameter # Disabled: test callbacks and interface implementations often have required unused params - name: unreachable-code - - name: redefines-builtin-id + # - name: redefines-builtin-id # Disabled: min/max helpers are common before Go 1.21 unparam: check-exported: false staticcheck: @@ -132,8 +117,15 @@ linters: - -QF1003 # Tagged switch - style preference, may affect Yaegi - -QF1007 # Merge conditional assignment - style preference - -QF1008 # Remove embedded field - may break Yaegi compatibility + - -QF1011 # Omit type from declaration - style preference - -QF1012 # Use fmt.Fprintf - style preference + - -SA9003 # Empty branch - sometimes intentional for future work + - -ST1000 # Package comment format - not required for all packages - -ST1003 # Package name format - allowed for test packages + - -ST1016 # Receiver name consistency - legacy code + - -ST1020 # Comment format for methods - style preference + - -ST1021 # Comment format for types - style preference + - -ST1023 # Omit type from declaration - style preference exclusions: generated: lax rules: @@ -144,18 +136,43 @@ linters: - goconst - gocyclo - gosec + - govet + - ineffassign - noctx - prealloc - unparam + - revive + - gocritic path: _test\.go - linters: - dupl - gocyclo + - govet + - noctx + - prealloc + - unparam + - revive + - gocritic path: test.*\.go - linters: - gocritic - unused + - errcheck + - revive path: mocks.*\.go + - linters: + - errcheck + - revive + - gocritic + - govet + - unparam + path: internal/testutil/ + - linters: + - govet + - unparam + - noctx + - prealloc + path: integration/ - linters: - gosec text: 'G404:' diff --git a/autocleanup.go b/autocleanup.go index 39764de..d064eaa 100644 --- a/autocleanup.go +++ b/autocleanup.go @@ -599,8 +599,9 @@ func GetGlobalTaskMemoryMonitor(logger *Logger) *TaskMemoryMonitor { return globalTaskMemoryMonitor } -// NewTaskMemoryMonitor creates a new memory monitor for task registry -// Deprecated: Use GetGlobalTaskMemoryMonitor instead for singleton behavior +// NewTaskMemoryMonitor creates a new memory monitor for task registry. +// +// Deprecated: Use GetGlobalTaskMemoryMonitor instead for singleton behavior. func NewTaskMemoryMonitor(logger *Logger, registry *TaskRegistry) *TaskMemoryMonitor { return GetGlobalTaskMemoryMonitor(logger) } @@ -712,7 +713,7 @@ func (mm *TaskMemoryMonitor) checkForMemoryIssues(stats TaskMemoryStats) { // Check for goroutine leaks (arbitrary threshold) if stats.Goroutines > 100 { - mm.logger.Infof("High goroutine count detected: %d", stats.Goroutines) + mm.logger.Debugf("High goroutine count detected: %d", stats.Goroutines) } // Check for heap growth without corresponding GC activity diff --git a/cache_manager.go b/cache_manager.go index 8b59d57..399f3f2 100644 --- a/cache_manager.go +++ b/cache_manager.go @@ -20,8 +20,9 @@ var ( cacheManagerInitOnce sync.Once ) -// GetGlobalCacheManager returns a singleton CacheManager instance -// Deprecated: Use GetGlobalCacheManagerWithConfig instead +// GetGlobalCacheManager returns a singleton CacheManager instance. +// +// Deprecated: Use GetGlobalCacheManagerWithConfig instead. func GetGlobalCacheManager(wg *sync.WaitGroup) *CacheManager { return GetGlobalCacheManagerWithConfig(wg, nil) } diff --git a/config_marshalling.go b/config_marshalling.go index d741095..1383e2f 100644 --- a/config_marshalling.go +++ b/config_marshalling.go @@ -7,7 +7,7 @@ import ( // REDACTED is the placeholder value for sensitive information const REDACTED = "[REDACTED]" -// MarshalJSON implements custom JSON marshalling to redact sensitive fields +// MarshalJSON implements custom JSON marshaling to redact sensitive fields // Rewritten without type aliases for yaegi compatibility func (c Config) MarshalJSON() ([]byte, error) { // Build a map manually to avoid type alias issues with yaegi @@ -47,7 +47,7 @@ func (c Config) MarshalJSON() ([]byte, error) { return json.Marshal(result) } -// MarshalYAML implements custom YAML marshalling to redact sensitive fields +// MarshalYAML implements custom YAML marshaling to redact sensitive fields // Rewritten without type aliases for yaegi compatibility func (c Config) MarshalYAML() (interface{}, error) { // Build a map manually to avoid type alias issues with yaegi diff --git a/error_recovery.go b/error_recovery.go index 642190c..0ffef7d 100644 --- a/error_recovery.go +++ b/error_recovery.go @@ -954,7 +954,7 @@ func (gd *GracefulDegradation) GetDegradedServices() []string { gd.mutex.RLock() defer gd.mutex.RUnlock() - var degraded []string + degraded := make([]string, 0, len(gd.degradedServices)) for serviceName := range gd.degradedServices { degraded = append(degraded, serviceName) } diff --git a/input_validation.go b/input_validation.go index d59eb40..215db86 100644 --- a/input_validation.go +++ b/input_validation.go @@ -10,6 +10,14 @@ import ( "unicode/utf8" ) +// Pre-compiled regex patterns for validation (const patterns should use MustCompile) +var ( + emailRegexPattern = regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`) + urlRegexPattern = regexp.MustCompile(`^https?://[a-zA-Z0-9.-]+(?:\.[a-zA-Z]{2,})?(?::[0-9]+)?(?:/[^\s]*)?$`) + tokenRegexPattern = regexp.MustCompile(`^[A-Za-z0-9._-]+$`) + usernameRegexPattern = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`) +) + // InputValidator provides comprehensive input validation and sanitization // to protect against common security vulnerabilities including SQL injection, // XSS, path traversal, and other injection attacks. It validates and sanitizes @@ -73,7 +81,7 @@ func DefaultInputValidationConfig() InputValidationConfig { } // NewInputValidator creates a new input validator with the specified configuration. -// It compiles all necessary regex patterns and initializes security pattern lists. +// It uses pre-compiled regex patterns and initializes security pattern lists. // // Parameters: // - config: Validation configuration with size limits and mode settings. @@ -81,29 +89,8 @@ func DefaultInputValidationConfig() InputValidationConfig { // // Returns: // - A configured InputValidator instance. -// - An error if regex compilation fails. +// - An error (always nil, kept for API compatibility). func NewInputValidator(config InputValidationConfig, logger *Logger) (*InputValidator, error) { - // Compile regex patterns - emailRegex, err := regexp.Compile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`) - if err != nil { - return nil, fmt.Errorf("failed to compile email regex: %w", err) - } - - urlRegex, err := regexp.Compile(`^https?://[a-zA-Z0-9.-]+(?:\.[a-zA-Z]{2,})?(?::[0-9]+)?(?:/[^\s]*)?$`) - if err != nil { - return nil, fmt.Errorf("failed to compile URL regex: %w", err) - } - - tokenRegex, err := regexp.Compile(`^[A-Za-z0-9._-]+$`) - if err != nil { - return nil, fmt.Errorf("failed to compile token regex: %w", err) - } - - usernameRegex, err := regexp.Compile(`^[a-zA-Z0-9._-]+$`) - if err != nil { - return nil, fmt.Errorf("failed to compile username regex: %w", err) - } - return &InputValidator{ maxTokenLength: config.MaxTokenLength, maxURLLength: config.MaxURLLength, @@ -112,10 +99,10 @@ func NewInputValidator(config InputValidationConfig, logger *Logger) (*InputVali maxEmailLength: config.MaxEmailLength, maxUsernameLength: config.MaxUsernameLength, allowPrivateIPAddresses: config.AllowPrivateIPAddresses, - emailRegex: emailRegex, - urlRegex: urlRegex, - tokenRegex: tokenRegex, - usernameRegex: usernameRegex, + emailRegex: emailRegexPattern, + urlRegex: urlRegexPattern, + tokenRegex: tokenRegexPattern, + usernameRegex: usernameRegexPattern, sqlInjectionPatterns: []string{ "'", "\"", ";", "--", "/*", "*/", "xp_", "sp_", "union", "select", "insert", "update", "delete", "drop", diff --git a/internal/cache/backends/memory_shard.go b/internal/cache/backends/memory_shard.go index 3feaf64..183cb04 100644 --- a/internal/cache/backends/memory_shard.go +++ b/internal/cache/backends/memory_shard.go @@ -241,9 +241,11 @@ func (s *cacheShard) evictLRULocked() bool { element := s.lruList.Back() if element != nil { - item := element.Value.(*memoryCacheItem) - s.deleteItemLocked(item) - return true + item, ok := element.Value.(*memoryCacheItem) + if ok { + s.deleteItemLocked(item) + return true + } } return false } @@ -267,8 +269,10 @@ func (s *cacheShard) getOldestAccessTime() time.Time { element := s.lruList.Back() if element != nil { - item := element.Value.(*memoryCacheItem) - return item.accessedAt + item, ok := element.Value.(*memoryCacheItem) + if ok { + return item.accessedAt + } } return time.Time{} } diff --git a/internal/cache/backends/redis.go b/internal/cache/backends/redis.go index cc80ced..d8456f1 100644 --- a/internal/cache/backends/redis.go +++ b/internal/cache/backends/redis.go @@ -345,7 +345,7 @@ func (r *RedisBackend) prefixKey(key string) string { // executeWithRetry executes a Redis operation with exponential backoff retry logic. // It checks context cancellation at multiple points to ensure fast abort when the -// caller's context is cancelled (e.g., due to request timeout). +// caller's context is canceled (e.g., due to request timeout). func (r *RedisBackend) executeWithRetry(ctx context.Context, operation func(*RedisConn) error) error { maxRetries := 3 baseDelay := 50 * time.Millisecond // Reduced from 100ms to fail faster @@ -377,7 +377,7 @@ func (r *RedisBackend) executeWithRetry(ctx context.Context, operation func(*Red err = operation(conn) r.pool.Put(conn) - // Check context after operation - if cancelled, don't bother retrying + // Check context after operation - if canceled, don't bother retrying if ctx.Err() != nil { return ctx.Err() } diff --git a/internal/cache/backends/redis_pool_test.go b/internal/cache/backends/redis_pool_test.go index 02123e0..4ac2344 100644 --- a/internal/cache/backends/redis_pool_test.go +++ b/internal/cache/backends/redis_pool_test.go @@ -201,7 +201,7 @@ func TestConnectionPool_ContextCancellation(t *testing.T) { conn, err := pool.Get(context.Background()) require.NoError(t, err) - // Try to get another with cancelled context + // Try to get another with canceled context ctx, cancel := context.WithCancel(context.Background()) cancel() // Cancel immediately diff --git a/internal/cache/backends/resp.go b/internal/cache/backends/resp.go index b4be526..2500acd 100644 --- a/internal/cache/backends/resp.go +++ b/internal/cache/backends/resp.go @@ -44,7 +44,7 @@ type RESPWriter struct { // NewRESPWriter creates a new RESP writer from the pool (memory optimized) func NewRESPWriter(w io.Writer) *RESPWriter { - writer := writerPool.Get().(*RESPWriter) + writer, _ := writerPool.Get().(*RESPWriter) writer.w = w return writer } @@ -80,7 +80,7 @@ type RESPReader struct { // NewRESPReader creates a new RESP reader from the pool (memory optimized) func NewRESPReader(r io.Reader) *RESPReader { - reader := readerPool.Get().(*RESPReader) + reader, _ := readerPool.Get().(*RESPReader) reader.r.Reset(r) return reader } diff --git a/internal/cache/backends/singleflight.go b/internal/cache/backends/singleflight.go index 34f0afd..d6042a6 100644 --- a/internal/cache/backends/singleflight.go +++ b/internal/cache/backends/singleflight.go @@ -87,7 +87,7 @@ func (s *SingleflightCache) GetOrFetch(ctx context.Context, key string, fetcher // If successful, store in cache if call.err == nil && call.val != nil { // Use a background context for cache storage to ensure it completes - // even if the original context is cancelled + // even if the original context is canceled storeCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) _ = s.backend.Set(storeCtx, key, call.val, call.ttl) cancel() diff --git a/internal/cache/manager.go b/internal/cache/manager.go index af2a379..588ecce 100644 --- a/internal/cache/manager.go +++ b/internal/cache/manager.go @@ -232,7 +232,7 @@ func (m *Manager) Close() error { var firstErr error - if err := m.tokenCache.Close(); err != nil && firstErr == nil { + if err := m.tokenCache.Close(); err != nil { firstErr = err } if err := m.metadataCache.Close(); err != nil && firstErr == nil { diff --git a/internal/cleanup/workers.go b/internal/cleanup/workers.go index 6f2da12..9a92d74 100644 --- a/internal/cleanup/workers.go +++ b/internal/cleanup/workers.go @@ -397,7 +397,7 @@ func (wp *WorkerPool) Submit(task func()) error { } // worker is the main worker routine -func (wp *WorkerPool) worker(id int) { +func (wp *WorkerPool) worker(_ int) { defer wp.workerWg.Done() for { diff --git a/internal/features/flags.go b/internal/features/flags.go index 15b81c2..f2eb7b0 100644 --- a/internal/features/flags.go +++ b/internal/features/flags.go @@ -173,7 +173,7 @@ func (m *FeatureManager) LoadFromEnv() { for name, flag := range flags { envVar := "FEATURE_" + name if value := os.Getenv(envVar); value != "" { - enabled := strings.ToLower(value) == "true" || value == "1" + enabled := strings.EqualFold(value, "true") || value == "1" flag.enabled.Store(enabled) } } diff --git a/internal/providers/aws_cognito.go b/internal/providers/aws_cognito.go index a3aa415..a573bbe 100644 --- a/internal/providers/aws_cognito.go +++ b/internal/providers/aws_cognito.go @@ -40,7 +40,7 @@ func (p *AWSCognitoProvider) BuildAuthParams(baseParams url.Values, scopes []str // Remove offline_access scope as Cognito doesn't use it (case-insensitive) var filteredScopes []string for _, scope := range scopes { - if strings.ToLower(scope) != ScopeOfflineAccess { + if !strings.EqualFold(scope, ScopeOfflineAccess) { filteredScopes = append(filteredScopes, scope) } } diff --git a/internal/providers/warnings.go b/internal/providers/warnings.go index 12f7318..661ba30 100644 --- a/internal/providers/warnings.go +++ b/internal/providers/warnings.go @@ -18,16 +18,17 @@ func GetProviderWarnings(providerType ProviderType) []ProviderWarning { switch providerType { case ProviderTypeGitHub: - warnings = append(warnings, ProviderWarning{ - ProviderType: ProviderTypeGitHub, - Level: "warning", - Message: "GitHub uses OAuth 2.0, not OpenID Connect. ID tokens are not available. Use access tokens for API calls only.", - }) - warnings = append(warnings, ProviderWarning{ - ProviderType: ProviderTypeGitHub, - Level: "info", - Message: "GitHub OAuth apps do not support refresh tokens. Users will need to re-authenticate when tokens expire.", - }) + warnings = append(warnings, + ProviderWarning{ + ProviderType: ProviderTypeGitHub, + Level: "warning", + Message: "GitHub uses OAuth 2.0, not OpenID Connect. ID tokens are not available. Use access tokens for API calls only.", + }, + ProviderWarning{ + ProviderType: ProviderTypeGitHub, + Level: "info", + Message: "GitHub OAuth apps do not support refresh tokens. Users will need to re-authenticate when tokens expire.", + }) case ProviderTypeAuth0: warnings = append(warnings, ProviderWarning{ diff --git a/internal/recovery/metrics.go b/internal/recovery/metrics.go index 4487333..4e8a895 100644 --- a/internal/recovery/metrics.go +++ b/internal/recovery/metrics.go @@ -116,7 +116,7 @@ func (re *RetryExecutor) ExecuteWithContext(ctx context.Context, fn func() error // Continue to next attempt case <-ctx.Done(): re.RecordFailure() - return fmt.Errorf("retry cancelled: %w", ctx.Err()) + return fmt.Errorf("retry canceled: %w", ctx.Err()) } } @@ -301,7 +301,7 @@ func (rm *RecoveryMetrics) GetAllMetrics() map[string]interface{} { } } - allMetrics["summary"] = map[string]interface{}{ + summary := map[string]interface{}{ "totalMechanisms": len(rm.mechanisms), "totalRequests": totalRequests, "totalSuccesses": totalSuccesses, @@ -310,8 +310,9 @@ func (rm *RecoveryMetrics) GetAllMetrics() map[string]interface{} { if totalRequests > 0 { successRate := float64(totalSuccesses) / float64(totalRequests) * 100 - allMetrics["summary"].(map[string]interface{})["overallSuccessRate"] = fmt.Sprintf("%.2f%%", successRate) + summary["overallSuccessRate"] = fmt.Sprintf("%.2f%%", successRate) } + allMetrics["summary"] = summary return allMetrics } diff --git a/internal/recovery/metrics_test.go b/internal/recovery/metrics_test.go index cc647f2..4055fd2 100644 --- a/internal/recovery/metrics_test.go +++ b/internal/recovery/metrics_test.go @@ -223,7 +223,7 @@ func TestRetryExecutor_ExecuteWithContext_ContextCancelled(t *testing.T) { wg.Wait() if execErr == nil { - t.Error("Expected error when context is cancelled") + t.Error("Expected error when context is canceled") } } @@ -240,7 +240,7 @@ func TestRetryExecutor_ExecuteWithContext_ContextCancelledBeforeStart(t *testing }) if err == nil { - t.Error("Expected error when context is already cancelled") + t.Error("Expected error when context is already canceled") } } @@ -282,7 +282,7 @@ func TestRetryExecutor_isRetryableError(t *testing.T) { {name: "timeout", err: errors.New("TIMEOUT"), expected: true}, // case insensitive {name: "EOF", err: errors.New("EOF"), expected: false}, {name: "random error", err: errors.New("something else"), expected: false}, - {name: "context cancelled", err: context.Canceled, expected: false}, + {name: "context canceled", err: context.Canceled, expected: false}, {name: "context deadline exceeded", err: context.DeadlineExceeded, expected: false}, } diff --git a/jwk.go b/jwk.go index 7903b6d..e6c07bc 100644 --- a/jwk.go +++ b/jwk.go @@ -213,9 +213,9 @@ func (jwk *JWK) ToECDSAPublicKey() (*ecdsa.PublicKey, error) { // GetKey finds a key by its ID (kid) in the JWKSet. // Returns nil if no key with the given ID is found. func (jwks *JWKSet) GetKey(kid string) *JWK { - for _, key := range jwks.Keys { - if key.Kid == kid { - return &key + for i := range jwks.Keys { + if jwks.Keys[i].Kid == kid { + return &jwks.Keys[i] } } return nil diff --git a/jwt.go b/jwt.go index dee9fbe..64a343c 100644 --- a/jwt.go +++ b/jwt.go @@ -120,7 +120,7 @@ func getReplayCacheStats() (size int, maxSize int) { // Parameters: // - ctx: Parent context for cancellation // - logger: Logger for debug output (can be nil) -func startReplayCacheCleanup(ctx context.Context, logger *Logger) { +func startReplayCacheCleanup(_ context.Context, logger *Logger) { registry := GetGlobalTaskRegistry() // Define the cleanup task function diff --git a/logout.go b/logout.go index 7c990c4..920e1f6 100644 --- a/logout.go +++ b/logout.go @@ -316,9 +316,9 @@ func (t *TraefikOidc) verifyLogoutTokenSignature(jwt *JWT, tokenString string) e // Find the matching key in JWKS var matchingKey *JWK - for _, key := range jwks.Keys { - if key.Kid == kid { - matchingKey = &key + for i := range jwks.Keys { + if jwks.Keys[i].Kid == kid { + matchingKey = &jwks.Keys[i] break } } diff --git a/main_coverage_boost_test.go b/main_coverage_boost_test.go index 794d562..23cee23 100644 --- a/main_coverage_boost_test.go +++ b/main_coverage_boost_test.go @@ -9,7 +9,7 @@ import ( "gopkg.in/yaml.v3" ) -// Config Marshalling Tests +// Config Marshaling Tests func TestConfig_MarshalJSON(t *testing.T) { config := &Config{ diff --git a/memory_monitor.go b/memory_monitor.go index 8b49bda..036e5f4 100644 --- a/memory_monitor.go +++ b/memory_monitor.go @@ -229,7 +229,7 @@ func (mm *MemoryMonitor) updateGoroutineTracking(stats *MemoryStats) { } // Check for potential goroutine leak - if stats.NumGoroutines > mm.baselineGoroutines+int(mm.alertThresholds.GoroutineCount) { + if stats.NumGoroutines > mm.baselineGoroutines+mm.alertThresholds.GoroutineCount { mm.mu.Lock() wasAlert := mm.goroutineLeakAlert if !wasAlert { diff --git a/refresh_coordinator.go b/refresh_coordinator.go index c6c64e6..9d7ddd1 100644 --- a/refresh_coordinator.go +++ b/refresh_coordinator.go @@ -234,7 +234,7 @@ func (rc *RefreshCoordinator) CoordinateRefresh( // Returns (operation, false, nil) if joined an existing operation // Returns (nil, false, error) if the operation was rejected func (rc *RefreshCoordinator) getOrCreateOperation( - ctx context.Context, + _ context.Context, sessionID string, tokenHash string, refreshToken string, @@ -293,7 +293,7 @@ func (rc *RefreshCoordinator) getOrCreateOperation( // executeRefreshAsync performs the actual refresh operation asynchronously func (rc *RefreshCoordinator) executeRefreshAsync( operation *refreshOperation, - sessionID string, + _ string, // sessionID - reserved for future metrics/logging tokenHash string, refreshFunc func() (*TokenResponse, error), ) { diff --git a/session.go b/session.go index df4301d..0985b90 100644 --- a/session.go +++ b/session.go @@ -164,7 +164,7 @@ func decompressCombinedPayload(compressed string) (*combinedSessionPayload, erro if err != nil { return nil, fmt.Errorf("failed to create gzip reader: %w", err) } - defer gr.Close() + defer func() { _ = gr.Close() }() // Limit decompressed size to prevent zip bombs limitedReader := io.LimitReader(gr, 512*1024) // 512KB max @@ -1588,7 +1588,7 @@ func (sd *SessionData) returnToPoolSafely() { // Parameters: // - r: The HTTP request context. // - chunks: The map of session chunks (e.g., sd.accessTokenChunks) to clear and expire. -func (sd *SessionData) clearTokenChunks(r *http.Request, chunks map[int]*sessions.Session) { +func (sd *SessionData) clearTokenChunks(_ *http.Request, chunks map[int]*sessions.Session) { for _, session := range chunks { clearSessionValues(session, true) } diff --git a/session_chunk_manager.go b/session_chunk_manager.go index be6d4c9..04637e5 100644 --- a/session_chunk_manager.go +++ b/session_chunk_manager.go @@ -926,6 +926,8 @@ func (cm *ChunkManager) detectRepeatedCharacters(token string, config TokenConfi // // Returns: // - An error if the token is expired or has invalid expiration, nil if valid. +// +//nolint:unparam // error return kept for API consistency and future use func (cm *ChunkManager) validateTokenExpiration(token string, config TokenConfig) error { if !strings.Contains(token, ".") { return nil diff --git a/settings.go b/settings.go index ea5690e..4f0fc83 100644 --- a/settings.go +++ b/settings.go @@ -734,6 +734,7 @@ func (l *Logger) Errorf(format string, args ...interface{}) { } // newNoOpLogger creates a logger that discards all output. +// // Deprecated: Use GetSingletonNoOpLogger() instead for better memory efficiency. func newNoOpLogger() *Logger { return GetSingletonNoOpLogger() diff --git a/test_helpers_adapter_test.go b/test_helpers_adapter_test.go index b327b54..7a848b3 100644 --- a/test_helpers_adapter_test.go +++ b/test_helpers_adapter_test.go @@ -22,7 +22,7 @@ func (w *testWriter) Write(p []byte) (n int, err error) { // Test helper adapters for the new test files // resetGlobalState resets all global singletons to prevent test interference -// nolint:unused // Kept for potential future use in integration tests +//nolint:unused // Kept for potential future use in integration tests /* func resetGlobalState() { // Reset global task registry first to stop all background tasks @@ -137,7 +137,7 @@ func (tc *testCleanup) cleanupAll() { } // createTestConfig creates a config with all required fields populated for testing -// nolint:unused // Kept for potential future use in integration tests +//nolint:unused // Kept for potential future use in integration tests /* func createTestConfig() *Config { config := CreateConfig() @@ -151,7 +151,7 @@ func createTestConfig() *Config { */ // setupTestOIDCMiddleware creates a test OIDC middleware instance with mock servers -// nolint:unused // Kept for potential future use in integration tests +//nolint:unused // Kept for potential future use in integration tests /* func setupTestOIDCMiddleware(t *testing.T, config *Config) (*TraefikOidc, *httptest.Server) { // Reset global state to ensure test isolation @@ -339,7 +339,7 @@ func setupTestOIDCMiddleware(t *testing.T, config *Config) (*TraefikOidc, *httpt */ // createMockJWT creates a mock JWT token for testing - adapter for existing tests -// nolint:unused // Kept for potential future use in integration tests +//nolint:unused // Kept for potential future use in integration tests /* func createMockJWT(t *testing.T, sub, email string) string { return ValidIDToken @@ -361,7 +361,7 @@ func createTestSession() *SessionData { } // injectSessionIntoRequest saves the session and adds the resulting cookies to the request -// nolint:unused // Kept for potential future use in integration tests +//nolint:unused // Kept for potential future use in integration tests /* func injectSessionIntoRequest(t *testing.T, req *http.Request, session *SessionData) { // Create a response recorder to capture cookies diff --git a/token_manager.go b/token_manager.go index cb2a130..4f81875 100644 --- a/token_manager.go +++ b/token_manager.go @@ -454,7 +454,6 @@ func (t *TraefikOidc) refreshToken(rw http.ResponseWriter, req *http.Request, se newToken, err := t.tokenExchanger.GetNewTokenWithRefreshToken(initialRefreshToken) if err != nil { errMsg := err.Error() - //nolint:gocritic // Complex error handling with provider-specific conditions if strings.Contains(errMsg, "invalid_grant") || strings.Contains(errMsg, "token expired") { t.logger.Debug("Refresh token expired or revoked: %v", err) // Clear all tokens and authentication state when refresh token is invalid