mirror of
https://github.com/prymitive/karma
synced 2026-05-05 03:16:51 +00:00
Merge pull request #92 from cloudflare/filters-validation
More strict filter validation
This commit is contained in:
@@ -57,43 +57,49 @@ func NewFilter(expression string) FilterT {
|
||||
invalid := alwaysInvalidFilter{}
|
||||
invalid.init("", nil, expression, false, expression)
|
||||
|
||||
reExp := fmt.Sprintf("^(?P<matched>(%s))(?P<operator>(%s))(?P<value>(.*))", filterRegex, matcherRegex)
|
||||
re := regexp.MustCompile(reExp)
|
||||
match := re.FindStringSubmatch(expression)
|
||||
result := make(map[string]string)
|
||||
for i, name := range re.SubexpNames() {
|
||||
if name != "" && i > 0 && i <= len(match) {
|
||||
result[name] = match[i]
|
||||
}
|
||||
}
|
||||
|
||||
matched, _ := result["matched"]
|
||||
operator, _ := result["operator"]
|
||||
value, _ := result["value"]
|
||||
|
||||
if matched == "" && operator == "" && value == "" {
|
||||
// no "filter=" part, just the value, use fuzzy filter
|
||||
f := newFuzzyFilter()
|
||||
matcher, err := newMatcher(regexpOperator)
|
||||
if err != nil {
|
||||
f.init("", nil, expression, false, expression)
|
||||
} else {
|
||||
f.init("", &matcher, expression, true, expression)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
if value == "" {
|
||||
// there's no value, so it's always invalid
|
||||
return &invalid
|
||||
}
|
||||
|
||||
if operator == "" {
|
||||
// no operator, no valid filter here
|
||||
return &invalid
|
||||
}
|
||||
|
||||
// we have "filter=" part, lookup filter that matches
|
||||
for _, fc := range AllFilters {
|
||||
f := fc.Factory()
|
||||
|
||||
reExp := fmt.Sprintf("^(?P<matched>(%s))(?P<operator>(%s))(?P<value>(.*))", fc.Label, matcherRegex)
|
||||
re := regexp.MustCompile(reExp)
|
||||
match := re.FindStringSubmatch(expression)
|
||||
result := make(map[string]string)
|
||||
for i, name := range re.SubexpNames() {
|
||||
if name != "" && i > 0 && i <= len(match) {
|
||||
result[name] = match[i]
|
||||
}
|
||||
}
|
||||
|
||||
matched, found := result["matched"]
|
||||
if !found && fc.IsSimple {
|
||||
matcher, err := newMatcher(regexpOperator)
|
||||
if err != nil {
|
||||
f.init("", nil, expression, false, expression)
|
||||
} else {
|
||||
f.init("", &matcher, expression, true, expression)
|
||||
}
|
||||
return f
|
||||
}
|
||||
if !found {
|
||||
if !fc.LabelRe.MatchString(matched) {
|
||||
// filter name doesn't match, keep searching
|
||||
continue
|
||||
}
|
||||
if value, ok := result["value"]; !ok || value == "" {
|
||||
// value group not found in the expression
|
||||
// example: 'label=''
|
||||
return &invalid
|
||||
}
|
||||
operator, found := result["operator"]
|
||||
if !found {
|
||||
// used operator is not supported by the filter
|
||||
// example: @limit=~0
|
||||
return &invalid
|
||||
}
|
||||
if !stringInSlice(fc.SupportedOperators, operator) {
|
||||
return &invalid
|
||||
}
|
||||
@@ -101,13 +107,13 @@ func NewFilter(expression string) FilterT {
|
||||
if err != nil {
|
||||
f.init(matched, nil, expression, false, "")
|
||||
} else {
|
||||
if value, found := result["value"]; found {
|
||||
if value != "" {
|
||||
f.init(matched, &matcher, expression, true, value)
|
||||
return f
|
||||
}
|
||||
f.init(matched, &matcher, expression, false, "")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return &invalid
|
||||
}
|
||||
|
||||
@@ -406,6 +406,30 @@ var tests = []filterTest{
|
||||
Expression: "^abb[****].*****",
|
||||
IsValid: false,
|
||||
},
|
||||
filterTest{
|
||||
Expression: "@silenced=true",
|
||||
IsValid: false,
|
||||
},
|
||||
filterTest{
|
||||
Expression: "@silenced!=false",
|
||||
IsValid: false,
|
||||
},
|
||||
filterTest{
|
||||
Expression: "@silenced=~false",
|
||||
IsValid: false,
|
||||
},
|
||||
filterTest{
|
||||
Expression: "@inhibited=true",
|
||||
IsValid: false,
|
||||
},
|
||||
filterTest{
|
||||
Expression: "@inhibited!=false",
|
||||
IsValid: false,
|
||||
},
|
||||
filterTest{
|
||||
Expression: "@inhibited=~false",
|
||||
IsValid: false,
|
||||
},
|
||||
}
|
||||
|
||||
func TestFilters(t *testing.T) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package filters
|
||||
|
||||
import "regexp"
|
||||
|
||||
const (
|
||||
equalOperator string = "="
|
||||
notEqualOperator string = "!="
|
||||
@@ -15,6 +17,9 @@ const (
|
||||
// a===b should yield an error
|
||||
var matcherRegex = "[=!<>~]+"
|
||||
|
||||
// same as matcherRegex but for the filter name part
|
||||
var filterRegex = "^(@)?[a-zA-Z_][a-zA-Z0-9_]*"
|
||||
|
||||
var matcherConfig = map[string]matcherT{
|
||||
equalOperator: &equalMatcher{},
|
||||
notEqualOperator: ¬EqualMatcher{},
|
||||
@@ -25,8 +30,8 @@ var matcherConfig = map[string]matcherT{
|
||||
}
|
||||
|
||||
type filterConfig struct {
|
||||
IsSimple bool
|
||||
Label string
|
||||
LabelRe *regexp.Regexp
|
||||
SupportedOperators []string
|
||||
Factory newFilterFactory
|
||||
Autocomplete autocompleteFactory
|
||||
@@ -37,42 +42,44 @@ type filterConfig struct {
|
||||
var AllFilters = []filterConfig{
|
||||
filterConfig{
|
||||
Label: "@status",
|
||||
LabelRe: regexp.MustCompile("^@status$"),
|
||||
SupportedOperators: []string{equalOperator, notEqualOperator},
|
||||
Factory: newstatusFilter,
|
||||
Autocomplete: statusAutocomplete,
|
||||
},
|
||||
filterConfig{
|
||||
Label: "@age",
|
||||
LabelRe: regexp.MustCompile("^@age$"),
|
||||
SupportedOperators: []string{lessThanOperator, moreThanOperator},
|
||||
Factory: newAgeFilter,
|
||||
Autocomplete: ageAutocomplete,
|
||||
},
|
||||
filterConfig{
|
||||
Label: "@silence_jira",
|
||||
LabelRe: regexp.MustCompile("^@silence_jira$"),
|
||||
SupportedOperators: []string{regexpOperator, negativeRegexOperator, equalOperator, notEqualOperator},
|
||||
Factory: newSilenceJiraFilter,
|
||||
Autocomplete: sinceJiraIDAutocomplete,
|
||||
},
|
||||
filterConfig{
|
||||
Label: "@silence_author",
|
||||
LabelRe: regexp.MustCompile("^@silence_author$"),
|
||||
SupportedOperators: []string{regexpOperator, negativeRegexOperator, equalOperator, notEqualOperator},
|
||||
Factory: newSilenceAuthorFilter,
|
||||
Autocomplete: sinceAuthorAutocomplete,
|
||||
},
|
||||
filterConfig{
|
||||
Label: "@limit",
|
||||
LabelRe: regexp.MustCompile("^@limit$"),
|
||||
SupportedOperators: []string{equalOperator},
|
||||
Factory: newLimitFilter,
|
||||
Autocomplete: limitAutocomplete,
|
||||
},
|
||||
filterConfig{
|
||||
Label: "[a-zA-Z_][a-zA-Z0-9_]*",
|
||||
LabelRe: regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$"),
|
||||
SupportedOperators: []string{regexpOperator, negativeRegexOperator, equalOperator, notEqualOperator, lessThanOperator, moreThanOperator},
|
||||
Factory: newLabelFilter,
|
||||
Autocomplete: labelAutocomplete,
|
||||
},
|
||||
filterConfig{
|
||||
IsSimple: true,
|
||||
Factory: newFuzzyFilter,
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user