feat(validation): Clear JoinAliases in FilterRequestOptions
Some checks failed
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in -27m20s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in -26m49s
Build , Vet Test, and Lint / Build (push) Successful in -26m53s
Build , Vet Test, and Lint / Lint Code (push) Successful in -26m22s
Tests / Integration Tests (push) Failing after -27m37s
Tests / Unit Tests (push) Successful in -27m25s

* Implemented logic to clear JoinAliases after filtering.
* Added unit test to verify JoinAliases is nil post-filtering.
* Ensured other fields are correctly filtered.
This commit is contained in:
Hein
2026-01-15 14:43:11 +02:00
parent 24a7ef7284
commit c12c045db1
2 changed files with 48 additions and 8 deletions

View File

@@ -237,15 +237,29 @@ func (v *ColumnValidator) FilterRequestOptions(options RequestOptions) RequestOp
for _, sort := range options.Sort {
if v.IsValidColumn(sort.Column) {
validSorts = append(validSorts, sort)
} else if strings.HasPrefix(sort.Column, "(") && strings.HasSuffix(sort.Column, ")") {
// Allow sort by expression/subquery, but validate for security
if IsSafeSortExpression(sort.Column) {
validSorts = append(validSorts, sort)
} else {
logger.Warn("Unsafe sort expression '%s' removed", sort.Column)
}
} else {
logger.Warn("Invalid column in sort '%s' removed", sort.Column)
foundJoin := false
for _, j := range options.JoinAliases {
if strings.Contains(sort.Column, j) {
foundJoin = true
break
}
}
if foundJoin {
validSorts = append(validSorts, sort)
continue
}
if strings.HasPrefix(sort.Column, "(") && strings.HasSuffix(sort.Column, ")") {
// Allow sort by expression/subquery, but validate for security
if IsSafeSortExpression(sort.Column) {
validSorts = append(validSorts, sort)
} else {
logger.Warn("Unsafe sort expression '%s' removed", sort.Column)
}
} else {
logger.Warn("Invalid column in sort '%s' removed", sort.Column)
}
}
}
filtered.Sort = validSorts
@@ -291,6 +305,9 @@ func (v *ColumnValidator) FilterRequestOptions(options RequestOptions) RequestOp
}
filtered.Preload = validPreloads
// Clear JoinAliases - this is an internal validation field and should not be persisted
filtered.JoinAliases = nil
return filtered
}

View File

@@ -362,6 +362,29 @@ func TestFilterRequestOptions(t *testing.T) {
}
}
func TestFilterRequestOptions_ClearsJoinAliases(t *testing.T) {
model := TestModel{}
validator := NewColumnValidator(model)
options := RequestOptions{
Columns: []string{"id", "name"},
// Set JoinAliases - this should be cleared by FilterRequestOptions
JoinAliases: []string{"d", "u", "r"},
}
filtered := validator.FilterRequestOptions(options)
// Verify that JoinAliases was cleared (internal field should not persist)
if filtered.JoinAliases != nil {
t.Errorf("Expected JoinAliases to be nil after filtering, got %v", filtered.JoinAliases)
}
// Verify that other fields are still properly filtered
if len(filtered.Columns) != 2 {
t.Errorf("Expected 2 columns, got %d", len(filtered.Columns))
}
}
func TestIsSafeSortExpression(t *testing.T) {
tests := []struct {
name string