case sensitive selection for item IDs (#3397)

Use a strictEquals matcher for item selection when
not matching on item names (no name match assumes
canonical system id match, which is case sensitive).

---

#### Does this PR need a docs update or release note?

- [x]  No

#### Type of change

- [x] 🐛 Bugfix

#### Issue(s)

* #3313

#### Test Plan

- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
Keepers 2023-05-16 12:15:18 -06:00 committed by GitHub
parent 67e055360d
commit 666813865e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 121 additions and 40 deletions

View File

@ -216,9 +216,8 @@ func (s *exchange) Contacts(folders, contacts []string, opts ...option) []Exchan
scopes = append( scopes = append(
scopes, scopes,
makeScope[ExchangeScope](ExchangeContact, contacts). makeScope[ExchangeScope](ExchangeContact, contacts, defaultItemOptions(s.Cfg)...).
set(ExchangeContactFolder, folders, opts...), set(ExchangeContactFolder, folders, opts...))
)
return scopes return scopes
} }
@ -236,8 +235,7 @@ func (s *exchange) ContactFolders(folders []string, opts ...option) []ExchangeSc
scopes = append( scopes = append(
scopes, scopes,
makeScope[ExchangeScope](ExchangeContactFolder, folders, os...), makeScope[ExchangeScope](ExchangeContactFolder, folders, os...))
)
return scopes return scopes
} }
@ -252,9 +250,8 @@ func (s *exchange) Events(calendars, events []string, opts ...option) []Exchange
scopes = append( scopes = append(
scopes, scopes,
makeScope[ExchangeScope](ExchangeEvent, events). makeScope[ExchangeScope](ExchangeEvent, events, defaultItemOptions(s.Cfg)...).
set(ExchangeEventCalendar, calendars, opts...), set(ExchangeEventCalendar, calendars, opts...))
)
return scopes return scopes
} }
@ -273,8 +270,7 @@ func (s *exchange) EventCalendars(events []string, opts ...option) []ExchangeSco
scopes = append( scopes = append(
scopes, scopes,
makeScope[ExchangeScope](ExchangeEventCalendar, events, os...), makeScope[ExchangeScope](ExchangeEventCalendar, events, os...))
)
return scopes return scopes
} }
@ -289,9 +285,8 @@ func (s *exchange) Mails(folders, mails []string, opts ...option) []ExchangeScop
scopes = append( scopes = append(
scopes, scopes,
makeScope[ExchangeScope](ExchangeMail, mails). makeScope[ExchangeScope](ExchangeMail, mails, defaultItemOptions(s.Cfg)...).
set(ExchangeMailFolder, folders, opts...), set(ExchangeMailFolder, folders, opts...))
)
return scopes return scopes
} }
@ -309,8 +304,7 @@ func (s *exchange) MailFolders(folders []string, opts ...option) []ExchangeScope
scopes = append( scopes = append(
scopes, scopes,
makeScope[ExchangeScope](ExchangeMailFolder, folders, os...), makeScope[ExchangeScope](ExchangeMailFolder, folders, os...))
)
return scopes return scopes
} }
@ -326,8 +320,7 @@ func (s *exchange) AllData() []ExchangeScope {
scopes = append(scopes, scopes = append(scopes,
makeScope[ExchangeScope](ExchangeContactFolder, Any()), makeScope[ExchangeScope](ExchangeContactFolder, Any()),
makeScope[ExchangeScope](ExchangeEventCalendar, Any()), makeScope[ExchangeScope](ExchangeEventCalendar, Any()),
makeScope[ExchangeScope](ExchangeMailFolder, Any()), makeScope[ExchangeScope](ExchangeMailFolder, Any()))
)
return scopes return scopes
} }

View File

@ -146,6 +146,14 @@ func stubInfoScope(match string) mockScope {
return sc return sc
} }
func makeStubScope(cfg Config, match []string) mockScope {
return makeScope[mockScope](leafCatStub, match, defaultItemOptions(cfg)...)
}
func (s mockScope) Matches(cat mockCategorizer, target string) bool {
return matches(s, cat, target)
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Stringers and Concealers // Stringers and Concealers
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -223,8 +223,7 @@ func (s *oneDrive) Folders(folders []string, opts ...option) []OneDriveScope {
scopes = append( scopes = append(
scopes, scopes,
makeScope[OneDriveScope](OneDriveFolder, folders, os...), makeScope[OneDriveScope](OneDriveFolder, folders, os...))
)
return scopes return scopes
} }
@ -239,9 +238,8 @@ func (s *oneDrive) Items(folders, items []string, opts ...option) []OneDriveScop
scopes = append( scopes = append(
scopes, scopes,
makeScope[OneDriveScope](OneDriveItem, items). makeScope[OneDriveScope](OneDriveItem, items, defaultItemOptions(s.Cfg)...).
set(OneDriveFolder, folders, opts...), set(OneDriveFolder, folders, opts...))
)
return scopes return scopes
} }

View File

@ -460,6 +460,67 @@ func (suite *SelectorScopesSuite) TestMatchesPathValues() {
} }
} }
func (suite *SelectorScopesSuite) TestDefaultItemOptions() {
table := []struct {
name string
cfg Config
match []string
target string
expect assert.BoolAssertionFunc
}{
{
name: "no config, matches same value",
cfg: Config{},
match: []string{"foo"},
target: "foo",
expect: assert.True,
},
{
name: "no config, does not match different case",
cfg: Config{},
match: []string{"bar"},
target: "BAR",
expect: assert.False,
},
{
name: "no config, does not match substring",
cfg: Config{},
match: []string{"bar"},
target: "ba",
expect: assert.False,
},
{
name: "only names, matches same same value",
cfg: Config{OnlyMatchItemNames: true},
match: []string{"fnords"},
target: "fnords",
expect: assert.True,
},
{
name: "only names, matches different case",
cfg: Config{OnlyMatchItemNames: true},
match: []string{"smarf"},
target: "SMARF",
expect: assert.True,
},
{
name: "only names, does not match substring",
cfg: Config{OnlyMatchItemNames: true},
match: []string{"brunhilda"},
target: "unhild",
expect: assert.False,
},
}
for _, test := range table {
suite.Run(test.name, func() {
t := suite.T()
sc := makeStubScope(test.cfg, test.match)
test.expect(t, sc.Matches(leafCatStub, test.target))
})
}
}
func (suite *SelectorScopesSuite) TestClean() { func (suite *SelectorScopesSuite) TestClean() {
table := []struct { table := []struct {
name string name string

View File

@ -463,11 +463,26 @@ func pathCategoriesIn[T scopeT, C categoryT](ss []scope) []path.CategoryType {
// scope constructors // scope constructors
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// constructs the default item-scope comparator options according
// to the selector configuration.
// - if cfg.OnlyMatchItemNames == false, then comparison assumes item IDs,
// which are case sensitive, resulting in StrictEqualsMatch
func defaultItemOptions(cfg Config) []option {
opts := []option{}
if !cfg.OnlyMatchItemNames {
opts = append(opts, StrictEqualMatch())
}
return opts
}
type scopeConfig struct { type scopeConfig struct {
usePathFilter bool usePathFilter bool
usePrefixFilter bool usePrefixFilter bool
useSuffixFilter bool useSuffixFilter bool
useEqualsFilter bool useEqualsFilter bool
useStrictEqualsFilter bool
} }
type option func(*scopeConfig) type option func(*scopeConfig)
@ -496,9 +511,16 @@ func SuffixMatch() option {
} }
} }
// StrictEqualsMatch ensures the selector uses a StrictEquals comparator, instead
// of contains. Will not override a default Any() or None() comparator.
func StrictEqualMatch() option {
return func(sc *scopeConfig) {
sc.useStrictEqualsFilter = true
}
}
// ExactMatch ensures the selector uses an Equals comparator, instead // ExactMatch ensures the selector uses an Equals comparator, instead
// of contains. Will not override a default Any() or None() // of contains. Will not override a default Any() or None() comparator.
// comparator.
func ExactMatch() option { func ExactMatch() option {
return func(sc *scopeConfig) { return func(sc *scopeConfig) {
sc.useEqualsFilter = true sc.useEqualsFilter = true
@ -599,6 +621,10 @@ func filterize(
return filters.Suffix(targets) return filters.Suffix(targets)
} }
if sc.useStrictEqualsFilter {
return filters.StrictEqual(targets)
}
if defaultFilter != nil { if defaultFilter != nil {
return defaultFilter(targets) return defaultFilter(targets)
} }

View File

@ -245,8 +245,7 @@ func (s *sharePoint) AllData() []SharePointScope {
scopes, scopes,
makeScope[SharePointScope](SharePointLibraryFolder, Any()), makeScope[SharePointScope](SharePointLibraryFolder, Any()),
makeScope[SharePointScope](SharePointList, Any()), makeScope[SharePointScope](SharePointList, Any()),
makeScope[SharePointScope](SharePointPageFolder, Any()), makeScope[SharePointScope](SharePointPageFolder, Any()))
)
return scopes return scopes
} }
@ -276,9 +275,8 @@ func (s *sharePoint) ListItems(lists, items []string, opts ...option) []SharePoi
scopes = append( scopes = append(
scopes, scopes,
makeScope[SharePointScope](SharePointListItem, items). makeScope[SharePointScope](SharePointListItem, items, defaultItemOptions(s.Cfg)...).
set(SharePointList, lists, opts...), set(SharePointList, lists, opts...))
)
return scopes return scopes
} }
@ -312,8 +310,7 @@ func (s *sharePoint) LibraryFolders(libraryFolders []string, opts ...option) []S
scopes = append( scopes = append(
scopes, scopes,
makeScope[SharePointScope](SharePointLibraryFolder, libraryFolders, os...), makeScope[SharePointScope](SharePointLibraryFolder, libraryFolders, os...))
)
return scopes return scopes
} }
@ -328,9 +325,8 @@ func (s *sharePoint) LibraryItems(libraries, items []string, opts ...option) []S
scopes = append( scopes = append(
scopes, scopes,
makeScope[SharePointScope](SharePointLibraryItem, items). makeScope[SharePointScope](SharePointLibraryItem, items, defaultItemOptions(s.Cfg)...).
set(SharePointLibraryFolder, libraries, opts...), set(SharePointLibraryFolder, libraries, opts...))
)
return scopes return scopes
} }
@ -361,8 +357,7 @@ func (s *sharePoint) PageItems(pages, items []string, opts ...option) []SharePoi
scopes = append( scopes = append(
scopes, scopes,
makeScope[SharePointScope](SharePointPage, items). makeScope[SharePointScope](SharePointPage, items).
set(SharePointPageFolder, pages, opts...), set(SharePointPageFolder, pages, opts...))
)
return scopes return scopes
} }