fix(validation): improve preload column validation logic

* Use related model's validator for filtering preload columns
* Ensure valid columns are checked against the correct validator
This commit is contained in:
Hein
2026-05-21 20:16:53 +02:00
parent c42c6b28e3
commit 1f9b230f7f
+17 -4
View File
@@ -266,11 +266,24 @@ func (v *ColumnValidator) FilterRequestOptions(options RequestOptions) RequestOp
// Filter Preload columns // Filter Preload columns
validPreloads := make([]PreloadOption, 0, len(options.Preload)) validPreloads := make([]PreloadOption, 0, len(options.Preload))
modelType := reflect.TypeOf(v.model)
if modelType != nil && modelType.Kind() == reflect.Ptr {
modelType = modelType.Elem()
}
for idx := range options.Preload { for idx := range options.Preload {
preload := options.Preload[idx] preload := options.Preload[idx]
filteredPreload := preload filteredPreload := preload
filteredPreload.Columns = v.FilterValidColumns(preload.Columns)
filteredPreload.OmitColumns = v.FilterValidColumns(preload.OmitColumns) // Use the related model's validator for preload columns/filters/sorts
preloadValidator := v
if modelType != nil {
if relInfo := GetRelationshipInfo(modelType, preload.Relation); relInfo != nil && relInfo.RelatedModel != nil {
preloadValidator = NewColumnValidator(relInfo.RelatedModel)
}
}
filteredPreload.Columns = preloadValidator.FilterValidColumns(preload.Columns)
filteredPreload.OmitColumns = preloadValidator.FilterValidColumns(preload.OmitColumns)
// Preserve SqlJoins and JoinAliases for preloads with custom joins // Preserve SqlJoins and JoinAliases for preloads with custom joins
filteredPreload.SqlJoins = preload.SqlJoins filteredPreload.SqlJoins = preload.SqlJoins
@@ -279,7 +292,7 @@ func (v *ColumnValidator) FilterRequestOptions(options RequestOptions) RequestOp
// Filter preload filters // Filter preload filters
validPreloadFilters := make([]FilterOption, 0, len(preload.Filters)) validPreloadFilters := make([]FilterOption, 0, len(preload.Filters))
for _, filter := range preload.Filters { for _, filter := range preload.Filters {
if v.IsValidColumn(filter.Column) { if preloadValidator.IsValidColumn(filter.Column) {
validPreloadFilters = append(validPreloadFilters, filter) validPreloadFilters = append(validPreloadFilters, filter)
} else { } else {
// Check if the filter column references a joined table alias // Check if the filter column references a joined table alias
@@ -302,7 +315,7 @@ func (v *ColumnValidator) FilterRequestOptions(options RequestOptions) RequestOp
// Filter preload sort columns // Filter preload sort columns
validPreloadSorts := make([]SortOption, 0, len(preload.Sort)) validPreloadSorts := make([]SortOption, 0, len(preload.Sort))
for _, sort := range preload.Sort { for _, sort := range preload.Sort {
if v.IsValidColumn(sort.Column) { if preloadValidator.IsValidColumn(sort.Column) {
validPreloadSorts = append(validPreloadSorts, sort) validPreloadSorts = append(validPreloadSorts, sort)
} else if strings.HasPrefix(sort.Column, "(") && strings.HasSuffix(sort.Column, ")") { } else if strings.HasPrefix(sort.Column, "(") && strings.HasSuffix(sort.Column, ")") {
// Allow sort by expression/subquery, but validate for security // Allow sort by expression/subquery, but validate for security