mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-06-18 18:16:26 +00:00
Better checking for api sort param to prevent sql injection
And moved filters out and cached object reflection
This commit is contained in:
@ -1,66 +1,22 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"npm/internal/model"
|
||||
"npm/internal/tags"
|
||||
)
|
||||
|
||||
type filterMapValue struct {
|
||||
Type string
|
||||
Field string
|
||||
}
|
||||
|
||||
// GetFilterMap returns the filter map
|
||||
func GetFilterMap(m interface{}, includeBaseEntity bool) map[string]filterMapValue {
|
||||
filterMap := getFilterMapForInterface(m)
|
||||
func GetFilterMap(m interface{}, includeBaseEntity bool) map[string]model.FilterMapValue {
|
||||
filterMap := tags.GetFilterMap(m)
|
||||
if includeBaseEntity {
|
||||
return mergeFilterMaps(getFilterMapForInterface(ModelBase{}), filterMap)
|
||||
return mergeFilterMaps(tags.GetFilterMap(ModelBase{}), filterMap)
|
||||
}
|
||||
|
||||
return filterMap
|
||||
}
|
||||
|
||||
func getFilterMapForInterface(m interface{}) map[string]filterMapValue {
|
||||
var filterMap = make(map[string]filterMapValue)
|
||||
|
||||
// TypeOf returns the reflection Type that represents the dynamic type of variable.
|
||||
// If variable is a nil interface value, TypeOf returns nil.
|
||||
t := reflect.TypeOf(m)
|
||||
|
||||
// Iterate over all available fields and read the tag value
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
// Get the field, returns https://golang.org/pkg/reflect/#StructField
|
||||
field := t.Field(i)
|
||||
|
||||
// Get the field tag value
|
||||
filterTag := field.Tag.Get("filter")
|
||||
dbTag := field.Tag.Get("gorm")
|
||||
if filterTag != "" && dbTag != "" && dbTag != "-" && filterTag != "-" {
|
||||
// db can have many parts, we need to pull out the "column:value" part
|
||||
dbField := field.Name
|
||||
r := regexp.MustCompile(`(?:^|;)column:([^;|$]+)(?:$|;)`)
|
||||
if matches := r.FindStringSubmatch(dbTag); len(matches) > 1 {
|
||||
dbField = matches[1]
|
||||
}
|
||||
// Filter tag can be a 2 part thing: name,type
|
||||
// ie: account_id,integer
|
||||
// So we need to split and use the first part
|
||||
parts := strings.Split(filterTag, ",")
|
||||
if len(parts) > 1 {
|
||||
filterMap[parts[0]] = filterMapValue{
|
||||
Type: parts[1],
|
||||
Field: dbField,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filterMap
|
||||
}
|
||||
|
||||
func mergeFilterMaps(m1 map[string]filterMapValue, m2 map[string]filterMapValue) map[string]filterMapValue {
|
||||
merged := make(map[string]filterMapValue, 0)
|
||||
func mergeFilterMaps(m1 map[string]model.FilterMapValue, m2 map[string]model.FilterMapValue) map[string]model.FilterMapValue {
|
||||
merged := make(map[string]model.FilterMapValue, 0)
|
||||
for k, v := range m1 {
|
||||
merged[k] = v
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ type ListResponse struct {
|
||||
func ListQueryBuilder(
|
||||
pageInfo *model.PageInfo,
|
||||
filters []model.Filter,
|
||||
filterMap map[string]filterMapValue,
|
||||
filterMap map[string]model.FilterMapValue,
|
||||
) *gorm.DB {
|
||||
scopes := make([]func(*gorm.DB) *gorm.DB, 0)
|
||||
scopes = append(scopes, ScopeOffsetLimit(pageInfo))
|
||||
|
@ -36,7 +36,7 @@ func ScopeOrderBy(pageInfo *model.PageInfo, defaultSort model.Sort) func(db *gor
|
||||
}
|
||||
}
|
||||
|
||||
func ScopeFilters(filters []model.Filter, filterMap map[string]filterMapValue) func(db *gorm.DB) *gorm.DB {
|
||||
func ScopeFilters(filters []model.Filter, filterMap map[string]model.FilterMapValue) func(db *gorm.DB) *gorm.DB {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
like := database.GetCaseInsensitiveLike()
|
||||
for _, f := range filters {
|
||||
|
Reference in New Issue
Block a user