diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index 10fc8cd..71b6fc8 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -47,7 +47,7 @@ func UseMemcache(config *MemcacheConfig) error { // Initializes with in-memory provider if not already initialized. func GetDefaultCache() *Cache { if defaultCache == nil { - UseMemory(&Options{ + _ = UseMemory(&Options{ DefaultTTL: 5 * time.Minute, MaxSize: 10000, }) diff --git a/pkg/cache/example_usage.go b/pkg/cache/example_usage.go index 8aeac41..c6a545b 100644 --- a/pkg/cache/example_usage.go +++ b/pkg/cache/example_usage.go @@ -17,7 +17,6 @@ func ExampleInMemoryCache() { if err != nil { log.Fatal(err) } - defer Close() ctx := context.Background() @@ -33,6 +32,7 @@ func ExampleInMemoryCache() { user := User{ID: 1, Name: "John Doe"} err = cache.Set(ctx, "user:1", user, 10*time.Minute) if err != nil { + _ = Close() log.Fatal(err) } @@ -40,6 +40,7 @@ func ExampleInMemoryCache() { var retrieved User err = cache.Get(ctx, "user:1", &retrieved) if err != nil { + _ = Close() log.Fatal(err) } @@ -52,15 +53,18 @@ func ExampleInMemoryCache() { // Delete a key err = cache.Delete(ctx, "user:1") if err != nil { + _ = Close() log.Fatal(err) } // Get statistics stats, err := cache.Stats(ctx) if err != nil { + _ = Close() log.Fatal(err) } fmt.Printf("Cache stats: %+v\n", stats) + _ = Close() } // ExampleRedisCache demonstrates using the Redis cache provider. @@ -78,7 +82,6 @@ func ExampleRedisCache() { if err != nil { log.Fatal(err) } - defer Close() ctx := context.Background() @@ -89,12 +92,14 @@ func ExampleRedisCache() { data := []byte("Hello, Redis!") err = cache.SetBytes(ctx, "greeting", data, 1*time.Hour) if err != nil { + _ = Close() log.Fatal(err) } // Retrieve raw bytes retrieved, err := cache.GetBytes(ctx, "greeting") if err != nil { + _ = Close() log.Fatal(err) } @@ -103,8 +108,10 @@ func ExampleRedisCache() { // Clear all cache err = cache.Clear(ctx) if err != nil { + _ = Close() log.Fatal(err) } + _ = Close() } // ExampleMemcacheCache demonstrates using the Memcache cache provider. @@ -119,7 +126,6 @@ func ExampleMemcacheCache() { if err != nil { log.Fatal(err) } - defer Close() ctx := context.Background() @@ -136,6 +142,7 @@ func ExampleMemcacheCache() { product := Product{ID: 100, Name: "Widget", Price: 29.99} err = cache.Set(ctx, "product:100", product, 30*time.Minute) if err != nil { + _ = Close() log.Fatal(err) } @@ -143,10 +150,12 @@ func ExampleMemcacheCache() { var retrieved Product err = cache.Get(ctx, "product:100", &retrieved) if err != nil { + _ = Close() log.Fatal(err) } fmt.Printf("Retrieved product: %+v\n", retrieved) + _ = Close() } // ExampleGetOrSet demonstrates the GetOrSet pattern for lazy loading. @@ -158,7 +167,6 @@ func ExampleGetOrSet() { if err != nil { log.Fatal(err) } - defer Close() ctx := context.Background() cache := GetDefaultCache() @@ -175,6 +183,7 @@ func ExampleGetOrSet() { return ExpensiveData{Result: "computed value"}, nil }) if err != nil { + _ = Close() log.Fatal(err) } @@ -186,10 +195,12 @@ func ExampleGetOrSet() { return ExpensiveData{Result: "new value"}, nil }) if err != nil { + _ = Close() log.Fatal(err) } fmt.Printf("Cached data: %+v\n", data) + _ = Close() } // ExampleCustomProvider demonstrates using a custom provider. @@ -202,7 +213,6 @@ func ExampleCustomProvider() { // Initialize with custom provider Initialize(memProvider) - defer Close() ctx := context.Background() cache := GetDefaultCache() @@ -210,6 +220,7 @@ func ExampleCustomProvider() { // Use the cache err := cache.SetBytes(ctx, "key", []byte("value"), 5*time.Minute) if err != nil { + _ = Close() log.Fatal(err) } @@ -218,6 +229,7 @@ func ExampleCustomProvider() { count := mp.CleanExpired(ctx) fmt.Printf("Cleaned %d expired items\n", count) } + _ = Close() } // ExampleDeleteByPattern demonstrates pattern-based deletion (Redis only). @@ -232,21 +244,23 @@ func ExampleDeleteByPattern() { if err != nil { log.Fatal(err) } - defer Close() ctx := context.Background() cache := GetDefaultCache() // Store multiple keys with a pattern - cache.SetBytes(ctx, "user:1:profile", []byte("profile1"), 10*time.Minute) - cache.SetBytes(ctx, "user:2:profile", []byte("profile2"), 10*time.Minute) - cache.SetBytes(ctx, "user:1:settings", []byte("settings1"), 10*time.Minute) + _ = cache.SetBytes(ctx, "user:1:profile", []byte("profile1"), 10*time.Minute) + _ = cache.SetBytes(ctx, "user:2:profile", []byte("profile2"), 10*time.Minute) + _ = cache.SetBytes(ctx, "user:1:settings", []byte("settings1"), 10*time.Minute) // Delete all keys matching pattern (Redis glob pattern) err = cache.DeleteByPattern(ctx, "user:*:profile") if err != nil { - log.Fatal(err) + _ = Close() + log.Print(err) + return } fmt.Println("Deleted all user profile keys") + _ = Close() } diff --git a/pkg/cache/provider.go b/pkg/cache/provider.go index b9ae132..8988d01 100644 --- a/pkg/cache/provider.go +++ b/pkg/cache/provider.go @@ -37,10 +37,10 @@ type Provider interface { // CacheStats contains cache statistics. type CacheStats struct { - Hits int64 `json:"hits"` - Misses int64 `json:"misses"` - Keys int64 `json:"keys"` - ProviderType string `json:"provider_type"` + Hits int64 `json:"hits"` + Misses int64 `json:"misses"` + Keys int64 `json:"keys"` + ProviderType string `json:"provider_type"` ProviderStats map[string]any `json:"provider_stats,omitempty"` } diff --git a/pkg/cache/query_cache.go b/pkg/cache/query_cache.go index 64593a1..071c1f7 100644 --- a/pkg/cache/query_cache.go +++ b/pkg/cache/query_cache.go @@ -13,15 +13,15 @@ import ( // QueryCacheKey represents the components used to build a cache key for query total count type QueryCacheKey struct { - TableName string `json:"table_name"` - Filters []common.FilterOption `json:"filters"` - Sort []common.SortOption `json:"sort"` - CustomSQLWhere string `json:"custom_sql_where,omitempty"` - CustomSQLOr string `json:"custom_sql_or,omitempty"` - Expand []ExpandOptionKey `json:"expand,omitempty"` - Distinct bool `json:"distinct,omitempty"` - CursorForward string `json:"cursor_forward,omitempty"` - CursorBackward string `json:"cursor_backward,omitempty"` + TableName string `json:"table_name"` + Filters []common.FilterOption `json:"filters"` + Sort []common.SortOption `json:"sort"` + CustomSQLWhere string `json:"custom_sql_where,omitempty"` + CustomSQLOr string `json:"custom_sql_or,omitempty"` + Expand []ExpandOptionKey `json:"expand,omitempty"` + Distinct bool `json:"distinct,omitempty"` + CursorForward string `json:"cursor_forward,omitempty"` + CursorBackward string `json:"cursor_backward,omitempty"` } // ExpandOptionKey represents expand options for cache key diff --git a/pkg/funcspec/function_api.go b/pkg/funcspec/function_api.go index ace729e..f28e5b1 100644 --- a/pkg/funcspec/function_api.go +++ b/pkg/funcspec/function_api.go @@ -109,7 +109,7 @@ func (h *Handler) SqlQueryList(sqlquery string, pNoCount, pBlankparms, pAllowFil // Use potentially modified SQL query and variables from hooks sqlquery = hookCtx.SQLQuery variables = hookCtx.Variables - complexAPI = hookCtx.ComplexAPI + // complexAPI = hookCtx.ComplexAPI // Extract input variables from SQL query (placeholders like [variable]) sqlquery = h.extractInputVariables(sqlquery, &inputvars) @@ -299,7 +299,7 @@ func (h *Handler) SqlQueryList(sqlquery string, pNoCount, pBlankparms, pAllowFil } if len(dbobjlist) == 0 { - w.Write([]byte("[]")) + _, _ = w.Write([]byte("[]")) return } @@ -318,7 +318,7 @@ func (h *Handler) SqlQueryList(sqlquery string, pNoCount, pBlankparms, pAllowFil if int64(len(dbobjlist)) < total { w.WriteHeader(http.StatusPartialContent) } - w.Write(data) + _, _ = w.Write(data) } case "detail": @@ -337,7 +337,7 @@ func (h *Handler) SqlQueryList(sqlquery string, pNoCount, pBlankparms, pAllowFil if int64(len(dbobjlist)) < total { w.WriteHeader(http.StatusPartialContent) } - w.Write(data) + _, _ = w.Write(data) } default: @@ -357,7 +357,7 @@ func (h *Handler) SqlQueryList(sqlquery string, pNoCount, pBlankparms, pAllowFil if int64(len(dbobjlist)) < total { w.WriteHeader(http.StatusPartialContent) } - w.Write(data) + _, _ = w.Write(data) } } else { data, err := json.Marshal(dbobjlist) @@ -367,7 +367,7 @@ func (h *Handler) SqlQueryList(sqlquery string, pNoCount, pBlankparms, pAllowFil if int64(len(dbobjlist)) < total { w.WriteHeader(http.StatusPartialContent) } - w.Write(data) + _, _ = w.Write(data) } } } @@ -578,7 +578,7 @@ func (h *Handler) SqlQuery(sqlquery string, pBlankparms bool) HTTPFuncType { if err != nil { sendError(w, http.StatusInternalServerError, "json_error", "Could not marshal response", err) } else { - w.Write(data) + _, _ = w.Write(data) } return } @@ -588,7 +588,7 @@ func (h *Handler) SqlQuery(sqlquery string, pBlankparms bool) HTTPFuncType { if err != nil { sendError(w, http.StatusInternalServerError, "json_error", "Could not marshal response", err) } else { - w.Write(data) + _, _ = w.Write(data) } } } @@ -597,9 +597,9 @@ func (h *Handler) SqlQuery(sqlquery string, pBlankparms bool) HTTPFuncType { // extractInputVariables extracts placeholders like [variable] from the SQL query func (h *Handler) extractInputVariables(sqlquery string, inputvars *[]string) string { - max := strings.Count(sqlquery, "[") * 4 + testsqlquery := sqlquery - for i := 0; i <= max; i++ { + for i := 0; i <= strings.Count(sqlquery, "[")*4; i++ { iStart := strings.Index(testsqlquery, "[") if iStart < 0 { break @@ -722,7 +722,7 @@ func (h *Handler) mergeHeaderParams(r *http.Request, sqlquery string, variables } if strings.Contains(k, "x-simpleapi") { - *complexAPI = !(val == "1" || strings.ToLower(val) == "true") + *complexAPI = !strings.EqualFold(val, "1") && !strings.EqualFold(val, "true") } } return sqlquery @@ -904,5 +904,5 @@ func sendError(w http.ResponseWriter, status int, code, message string, err erro "success": false, "error": errObj, }) - w.Write(data) + _, _ = w.Write(data) } diff --git a/pkg/funcspec/hooks.go b/pkg/funcspec/hooks.go index c59fa35..26d46a3 100644 --- a/pkg/funcspec/hooks.go +++ b/pkg/funcspec/hooks.go @@ -37,11 +37,11 @@ type HookContext struct { Writer http.ResponseWriter // SQL query and variables - SQLQuery string // The SQL query being executed (can be modified by hooks) - Variables map[string]interface{} // Variables extracted from request - InputVars []string // Input variable placeholders found in query - MetaInfo map[string]interface{} // Metadata about the request - PropQry map[string]string // Property query parameters + SQLQuery string // The SQL query being executed (can be modified by hooks) + Variables map[string]interface{} // Variables extracted from request + InputVars []string // Input variable placeholders found in query + MetaInfo map[string]interface{} // Metadata about the request + PropQry map[string]string // Property query parameters // User context UserContext *security.UserContext diff --git a/pkg/funcspec/parameters.go b/pkg/funcspec/parameters.go index 31584f9..af1a4e0 100644 --- a/pkg/funcspec/parameters.go +++ b/pkg/funcspec/parameters.go @@ -18,9 +18,9 @@ type RequestParameters struct { Distinct bool // Filtering - FieldFilters map[string]string // column -> value (exact match) - SearchFilters map[string]string // column -> value (ILIKE) - SearchOps map[string]FilterOperator // column -> {operator, value, logic} + FieldFilters map[string]string // column -> value (exact match) + SearchFilters map[string]string // column -> value (ILIKE) + SearchOps map[string]FilterOperator // column -> {operator, value, logic} CustomSQLWhere string CustomSQLOr string @@ -51,10 +51,10 @@ func (h *Handler) ParseParameters(r *http.Request) *RequestParameters { FieldFilters: make(map[string]string), SearchFilters: make(map[string]string), SearchOps: make(map[string]FilterOperator), - Limit: 20, // Default limit - Offset: 0, // Default offset + Limit: 20, // Default limit + Offset: 0, // Default offset ResponseFormat: "simple", // Default format - ComplexAPI: false, // Default to simple API + ComplexAPI: false, // Default to simple API } // Merge headers and query parameters @@ -155,7 +155,7 @@ func (h *Handler) ParseParameters(r *http.Request) *RequestParameters { // Response Format case strings.HasPrefix(key, "x-simpleapi"): params.ResponseFormat = "simple" - params.ComplexAPI = !(decodedValue == "1" || strings.EqualFold(decodedValue, "true")) + params.ComplexAPI = decodedValue != "1" && !strings.EqualFold(decodedValue, "true") case strings.HasPrefix(key, "x-detailapi"): params.ResponseFormat = "detail" params.ComplexAPI = true diff --git a/pkg/security/composite.go b/pkg/security/composite.go index 8eafcd2..747e211 100644 --- a/pkg/security/composite.go +++ b/pkg/security/composite.go @@ -9,9 +9,9 @@ import ( // CompositeSecurityProvider combines multiple security providers // Allows separating authentication, column security, and row security concerns type CompositeSecurityProvider struct { - auth Authenticator - colSec ColumnSecurityProvider - rowSec RowSecurityProvider + auth Authenticator + colSec ColumnSecurityProvider + rowSec RowSecurityProvider } // NewCompositeSecurityProvider creates a composite provider diff --git a/pkg/security/examples.go b/pkg/security/examples.go index 1260361..c1557b4 100644 --- a/pkg/security/examples.go +++ b/pkg/security/examples.go @@ -377,4 +377,3 @@ func (a *DatabaseAuthenticatorExample) RefreshToken(ctx context.Context, refresh ExpiresIn: int64(24 * time.Hour.Seconds()), }, nil } - diff --git a/pkg/security/providers.go b/pkg/security/providers.go index ce00750..9917520 100644 --- a/pkg/security/providers.go +++ b/pkg/security/providers.go @@ -192,7 +192,7 @@ func (a *DatabaseAuthenticator) updateSessionActivity(ctx context.Context, sessi var updatedUserJSON []byte query := `SELECT p_success, p_error, p_user FROM resolvespec_session_update($1, $2::jsonb)` - a.db.QueryRowContext(ctx, query, sessionToken, userJSON).Scan(&success, &errorMsg, &updatedUserJSON) + _ = a.db.QueryRowContext(ctx, query, sessionToken, userJSON).Scan(&success, &errorMsg, &updatedUserJSON) } // RefreshToken implements Refreshable interface @@ -539,14 +539,14 @@ func generateRandomString(length int) string { return string(b) } -func getClaimString(claims map[string]any, key string) string { - if claims == nil { - return "" - } - if val, ok := claims[key]; ok { - if str, ok := val.(string); ok { - return str - } - } - return "" -} +// func getClaimString(claims map[string]any, key string) string { +// if claims == nil { +// return "" +// } +// if val, ok := claims[key]; ok { +// if str, ok := val.(string); ok { +// return str +// } +// } +// return "" +// }