Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
## Changelog

Current [release](https://github.com/flowbi/pgweb/releases) is `0.16.18`.
Current [release](https://github.com/flowbi/pgweb/releases) is `0.16.19`.

## 0.16.19 - 2026-02-27

- `FIX` Remove debug console.log statements that leak parameter/query data to browser console
- `FIX` Remove unused `extractURLParams` backend code (substitution is handled client-side)

## 0.16.18 - 2025-11-23

Expand Down
35 changes: 0 additions & 35 deletions pkg/api/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"mime"
"net/http"
"os"
"path/filepath"
"regexp"
"strconv"
Expand Down Expand Up @@ -189,37 +188,3 @@ func errorResponse(c *gin.Context, status int, err interface{}) {
func badRequest(c *gin.Context, err interface{}) {
errorResponse(c, 400, err)
}

// extractURLParams extracts query parameters that should be used for SQL parameter substitution
// Returns a map of parameters that match configured patterns from PGWEB_CUSTOM_PARAMS
func extractURLParams(c *gin.Context) map[string]string {
params := make(map[string]string)

// Get custom parameter patterns from environment variable
customParams := os.Getenv("PGWEB_CUSTOM_PARAMS")
if customParams == "" {
// No patterns configured - parameter feature disabled
return params
}

// Parse configured patterns (exact matches only)
configuredPatterns := strings.Split(customParams, ",")
for i, pattern := range configuredPatterns {
configuredPatterns[i] = strings.TrimSpace(pattern)
}

// Extract all query parameters
for key, values := range c.Request.URL.Query() {
if len(values) > 0 {
// Check if this parameter matches configured patterns (exact match)
for _, pattern := range configuredPatterns {
if key == pattern {
params[key] = values[0] // Use the first value
break
}
}
}
}

return params
}
89 changes: 0 additions & 89 deletions pkg/api/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"testing"

"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -87,91 +86,3 @@ func Test_serveResult(t *testing.T) {
assert.Equal(t, 200, w.Code)
assert.Equal(t, `null`, w.Body.String())
}

func TestExtractURLParamsEmpty(t *testing.T) {
gin.SetMode(gin.TestMode)

req, _ := http.NewRequest("GET", "/api/query", nil)
c := &gin.Context{Request: req}

params := extractURLParams(c)

assert.Empty(t, params)
}

func TestExtractURLParamsWithConfiguredPatterns(t *testing.T) {
gin.SetMode(gin.TestMode)

// Set environment variable for test
originalEnv := os.Getenv("PGWEB_CUSTOM_PARAMS")
os.Setenv("PGWEB_CUSTOM_PARAMS", "Client,Instance,AccountId")
defer os.Setenv("PGWEB_CUSTOM_PARAMS", originalEnv)

values := url.Values{}
values.Set("Client", "test-client")
values.Set("Instance", "test-instance")
values.Set("AccountId", "123")
values.Set("ignored_param", "should-be-ignored")

req, _ := http.NewRequest("GET", "/api/query?"+values.Encode(), nil)
c := &gin.Context{Request: req}

params := extractURLParams(c)

assert.Len(t, params, 3)
assert.Equal(t, "test-client", params["Client"])
assert.Equal(t, "test-instance", params["Instance"])
assert.Equal(t, "123", params["AccountId"])
assert.NotContains(t, params, "ignored_param")
}

func TestExtractURLParamsNoConfiguration(t *testing.T) {
gin.SetMode(gin.TestMode)

// Clear environment variable for test
originalEnv := os.Getenv("PGWEB_CUSTOM_PARAMS")
os.Setenv("PGWEB_CUSTOM_PARAMS", "")
defer os.Setenv("PGWEB_CUSTOM_PARAMS", originalEnv)

values := url.Values{}
values.Set("Client", "test-client")
values.Set("Instance", "test-instance")
values.Set("any_param", "any-value")

req, _ := http.NewRequest("GET", "/api/query?"+values.Encode(), nil)
c := &gin.Context{Request: req}

params := extractURLParams(c)

// Should be empty when no patterns are configured
assert.Empty(t, params)
}

func TestExtractURLParamsExactMatchOnly(t *testing.T) {
gin.SetMode(gin.TestMode)

// Set environment variable for test
originalEnv := os.Getenv("PGWEB_CUSTOM_PARAMS")
os.Setenv("PGWEB_CUSTOM_PARAMS", "Client,Instance")
defer os.Setenv("PGWEB_CUSTOM_PARAMS", originalEnv)

values := url.Values{}
values.Set("Client", "should-match") // Exact match
values.Set("client", "should-not-match") // Case sensitive - doesn't match
values.Set("ClientId", "should-not-match") // Partial match - doesn't match
values.Set("Instance", "should-match") // Exact match
values.Set("tenant", "should-not-match") // No underscore

req, _ := http.NewRequest("GET", "/api/query?"+values.Encode(), nil)
c := &gin.Context{Request: req}

params := extractURLParams(c)

// Should only match exact parameter names
assert.Len(t, params, 2)
assert.Equal(t, "should-match", params["Client"])
assert.Equal(t, "should-match", params["Instance"])
assert.NotContains(t, params, "client")
assert.NotContains(t, params, "ClientId")
assert.NotContains(t, params, "tenant")
}
9 changes: 0 additions & 9 deletions static/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,6 @@ function loadParameterPatterns(callback) {
});
}

console.log("Loaded parameter patterns:", parameterPatterns.map(function(p) { return p.toString(); }));
if (callback) callback();
});
}
Expand Down Expand Up @@ -382,12 +381,6 @@ function substituteQueryParameters(query) {
result = result.replace(new RegExp('@' + param, 'g'), "'" + escapedValue + "'");
}

console.log('Query parameter substitution:', {
original: query,
substituted: result,
parameters: globalSqlParams
});

return result;
}

Expand Down Expand Up @@ -1499,8 +1492,6 @@ function displayURLParameters() {
globalSqlParamsForOverlay = sqlParams;

if (hasParams) {
console.log('URL parameters available for query substitution:', sqlParams);

// Initialize toggle state and overlay visibility
updateParamToggleState();

Expand Down
Loading