add missing any/none target check for paths (#1689)

## Description

the new pathFilterFactory now properly cleans
the inputs and checks for all-pass and all-fail
conditions.

## Type of change

- [x] 🐛 Bugfix

## Issue(s)

* #1616

## Test Plan

- [x]  Unit test
This commit is contained in:
Keepers 2022-12-05 13:57:36 -07:00 committed by GitHub
parent 3e4d6b3573
commit 6165bb55fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 86 additions and 17 deletions

View File

@ -512,23 +512,42 @@ func filterize(sc scopeConfig, s ...string) filters.Filter {
return filters.Contains(join(s...))
}
type filterFunc func(string) filters.Filter
type (
filterFunc func(string) filters.Filter
sliceFilterFunc func([]string) filters.Filter
)
// pathFilterFactory returns the appropriate path filter
// (contains, prefix, or suffix) for the provided options.
// If multiple options are flagged, Prefix takes priority.
// If no options are provided, returns PathContains.
func pathFilterFactory(opts ...option) func([]string) filters.Filter {
func pathFilterFactory(opts ...option) sliceFilterFunc {
sc := &scopeConfig{}
sc.populate(opts...)
var ff sliceFilterFunc
switch true {
case sc.usePrefixFilter:
return filters.PathPrefix
ff = filters.PathPrefix
case sc.useSuffixFilter:
return filters.PathSuffix
ff = filters.PathSuffix
default:
return filters.PathContains
ff = filters.PathContains
}
return wrapSliceFilter(ff)
}
func wrapSliceFilter(ff sliceFilterFunc) sliceFilterFunc {
return func(s []string) filters.Filter {
s = clean(s)
if f, ok := isAnyOrNone(s); ok {
return f
}
return ff(s)
}
}
@ -537,22 +556,37 @@ func pathFilterFactory(opts ...option) func([]string) filters.Filter {
// - normalizes the cleaned input (returns anyFail if empty, allFail if *)
// - joins the string
// - and generates a filter with the joined input.
func wrapFilter(ff filterFunc) func([]string) filters.Filter {
func wrapFilter(ff filterFunc) sliceFilterFunc {
return func(s []string) filters.Filter {
s = clean(s)
if len(s) == 1 {
if s[0] == AnyTgt {
return passAny
}
if s[0] == NoneTgt {
return failAny
}
if f, ok := isAnyOrNone(s); ok {
return f
}
ss := join(s...)
return ff(ss)
return ff(join(s...))
}
}
// returns (<filter>, true) if s is len==1 and s[0] is
// anyTgt or noneTgt, implying that the caller should use
// the returned filter. On (<filter>, false), the caller
// can ignore the returned filter.
// a special case exists for len(s)==0, interpreted as
// "noneTgt"
func isAnyOrNone(s []string) (filters.Filter, bool) {
switch len(s) {
case 0:
return failAny, true
case 1:
switch s[0] {
case AnyTgt:
return passAny, true
case NoneTgt:
return failAny, true
}
}
return failAny, false
}

View File

@ -140,6 +140,41 @@ func (suite *SharePointSelectorSuite) TestSharePointSelector_Include_WebURLs() {
}
}
func (suite *SharePointSelectorSuite) TestSharePointSelector_Include_WebURLs_anyNone() {
table := []struct {
name string
in []string
expect string
}{
{
name: "any",
in: []string{AnyTgt},
expect: AnyTgt,
},
{
name: "none",
in: []string{NoneTgt},
expect: NoneTgt,
},
}
for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) {
sel := NewSharePointRestore()
sel.Include(sel.WebURL(test.in))
scopes := sel.Includes
require.Len(t, scopes, 1)
for _, sc := range scopes {
scopeMustHave(
t,
SharePointScope(sc),
map[categorizer]string{SharePointWebURL: test.expect},
)
}
})
}
}
func (suite *SharePointSelectorSuite) TestSharePointSelector_Exclude_WebURLs() {
t := suite.T()
sel := NewSharePointRestore()