add eventOrganizer selector (#720)

## Description
Adds the eventOrganizer exchange filter, wraps
up the addition of eventRecurs filtering, and fixes
a couple improperly designed filter constructors.

## Type of change

Please check the type of change your PR introduces:
- [x] 🌻 Feature

## Issue(s)
#501

## Test Plan

- [x] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
Keepers 2022-09-01 13:56:17 -06:00 committed by GitHub
parent 137123294a
commit a043304e0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 53 deletions

View File

@ -474,7 +474,7 @@ func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender string)
return return
} }
sel.Filter(sel.MailSender([]string{sender})) sel.Filter(sel.MailSender(sender))
} }
func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject string) { func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject string) {
@ -482,7 +482,7 @@ func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject strin
return return
} }
sel.Filter(sel.MailSubject([]string{subject})) sel.Filter(sel.MailSubject(subject))
} }
// checks all flags for correctness and interdependencies // checks all flags for correctness and interdependencies

View File

@ -273,7 +273,7 @@ func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender string)
return return
} }
sel.Filter(sel.MailSender([]string{sender})) sel.Filter(sel.MailSender(sender))
} }
func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject string) { func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject string) {
@ -281,7 +281,7 @@ func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject strin
return return
} }
sel.Filter(sel.MailSubject([]string{subject})) sel.Filter(sel.MailSubject(subject))
} }
// checks all flags for correctness and interdependencies // checks all flags for correctness and interdependencies

View File

@ -274,17 +274,47 @@ func (s *exchange) Users(users []string) []ExchangeScope {
// ------------------- // -------------------
// Filter Factories // Filter Factories
// ContactName produces one or more exchange contact name filter scopes.
// Matches any contact whose name contains the provided string.
// If any slice contains selectors.Any, that slice is reduced to [selectors.Any]
// If any slice contains selectors.None, that slice is reduced to [selectors.None]
// If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) ContactName(senderID string) []ExchangeScope {
return []ExchangeScope{
makeFilterScope[ExchangeScope](
ExchangeContact,
ExchangeFilterContactName,
[]string{senderID},
wrapFilter(filters.In)),
}
}
// EventSubject produces one or more exchange event subject filter scopes.
// Matches any event where the event subject contains one of the provided strings.
// If any slice contains selectors.Any, that slice is reduced to [selectors.Any]
// If any slice contains selectors.None, that slice is reduced to [selectors.None]
// If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) EventOrganizer(organizer string) []ExchangeScope {
return []ExchangeScope{
makeFilterScope[ExchangeScope](
ExchangeEvent,
ExchangeFilterEventOrganizer,
[]string{organizer},
wrapFilter(filters.In)),
}
}
// EventRecurs produces one or more exchange event recurrence filter scopes. // EventRecurs produces one or more exchange event recurrence filter scopes.
// Matches any event if the comparator flag matches the event recurrence flag. // Matches any event if the comparator flag matches the event recurrence flag.
// If any slice contains selectors.Any, that slice is reduced to [selectors.Any] // If any slice contains selectors.Any, that slice is reduced to [selectors.Any]
// If any slice contains selectors.None, that slice is reduced to [selectors.None] // If any slice contains selectors.None, that slice is reduced to [selectors.None]
// If any slice is empty, it defaults to [selectors.None] // If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) EventRecurs(recurs bool) []ExchangeScope { func (sr *ExchangeRestore) EventRecurs(recurs string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeFilterScope[ExchangeScope]( makeFilterScope[ExchangeScope](
ExchangeEvent, ExchangeEvent,
ExchangeFilterEventRecurs, ExchangeFilterEventRecurs,
[]string{strconv.FormatBool(recurs)}, []string{recurs},
wrapFilter(filters.Equal)), wrapFilter(filters.Equal)),
} }
} }
@ -322,27 +352,12 @@ func (sr *ExchangeRestore) EventStartsBefore(timeStrings string) []ExchangeScope
// If any slice contains selectors.Any, that slice is reduced to [selectors.Any] // If any slice contains selectors.Any, that slice is reduced to [selectors.Any]
// If any slice contains selectors.None, that slice is reduced to [selectors.None] // If any slice contains selectors.None, that slice is reduced to [selectors.None]
// If any slice is empty, it defaults to [selectors.None] // If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) EventSubject(subjectSubstrings []string) []ExchangeScope { func (sr *ExchangeRestore) EventSubject(subject string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeFilterScope[ExchangeScope]( makeFilterScope[ExchangeScope](
ExchangeEvent, ExchangeEvent,
ExchangeFilterEventSubject, ExchangeFilterEventSubject,
subjectSubstrings, []string{subject},
wrapFilter(filters.In)),
}
}
// ContactName produces one or more exchange contact name filter scopes.
// Matches any contact whose name contains the provided string.
// If any slice contains selectors.Any, that slice is reduced to [selectors.Any]
// If any slice contains selectors.None, that slice is reduced to [selectors.None]
// If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) ContactName(senderID string) []ExchangeScope {
return []ExchangeScope{
makeFilterScope[ExchangeScope](
ExchangeContact,
ExchangeFilterContactName,
[]string{senderID},
wrapFilter(filters.In)), wrapFilter(filters.In)),
} }
} }
@ -380,12 +395,12 @@ func (sr *ExchangeRestore) MailReceivedBefore(timeStrings string) []ExchangeScop
// If any slice contains selectors.Any, that slice is reduced to [selectors.Any] // If any slice contains selectors.Any, that slice is reduced to [selectors.Any]
// If any slice contains selectors.None, that slice is reduced to [selectors.None] // If any slice contains selectors.None, that slice is reduced to [selectors.None]
// If any slice is empty, it defaults to [selectors.None] // If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) MailSender(senderIDs []string) []ExchangeScope { func (sr *ExchangeRestore) MailSender(sender string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeFilterScope[ExchangeScope]( makeFilterScope[ExchangeScope](
ExchangeMail, ExchangeMail,
ExchangeFilterMailSender, ExchangeFilterMailSender,
senderIDs, []string{sender},
wrapFilter(filters.In)), wrapFilter(filters.In)),
} }
} }
@ -395,12 +410,12 @@ func (sr *ExchangeRestore) MailSender(senderIDs []string) []ExchangeScope {
// If any slice contains selectors.Any, that slice is reduced to [selectors.Any] // If any slice contains selectors.Any, that slice is reduced to [selectors.Any]
// If any slice contains selectors.None, that slice is reduced to [selectors.None] // If any slice contains selectors.None, that slice is reduced to [selectors.None]
// If any slice is empty, it defaults to [selectors.None] // If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) MailSubject(subjectSubstrings []string) []ExchangeScope { func (sr *ExchangeRestore) MailSubject(subject string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeFilterScope[ExchangeScope]( makeFilterScope[ExchangeScope](
ExchangeMail, ExchangeMail,
ExchangeFilterMailSubject, ExchangeFilterMailSubject,
subjectSubstrings, []string{subject},
wrapFilter(filters.In)), wrapFilter(filters.In)),
} }
} }
@ -472,6 +487,7 @@ const (
ExchangeFilterMailReceivedAfter exchangeCategory = "ExchangeFilterMailReceivedAfter" ExchangeFilterMailReceivedAfter exchangeCategory = "ExchangeFilterMailReceivedAfter"
ExchangeFilterMailReceivedBefore exchangeCategory = "ExchangeFilterMailReceivedBefore" ExchangeFilterMailReceivedBefore exchangeCategory = "ExchangeFilterMailReceivedBefore"
ExchangeFilterContactName exchangeCategory = "ExchangeFilterContactName" ExchangeFilterContactName exchangeCategory = "ExchangeFilterContactName"
ExchangeFilterEventOrganizer exchangeCategory = "ExchangeFilterEventOrganizer"
ExchangeFilterEventRecurs exchangeCategory = "ExchangeFilterEventRecurs" ExchangeFilterEventRecurs exchangeCategory = "ExchangeFilterEventRecurs"
ExchangeFilterEventStartsAfter exchangeCategory = "ExchangeFilterEventStartsAfter" ExchangeFilterEventStartsAfter exchangeCategory = "ExchangeFilterEventStartsAfter"
ExchangeFilterEventStartsBefore exchangeCategory = "ExchangeFilterEventStartsBefore" ExchangeFilterEventStartsBefore exchangeCategory = "ExchangeFilterEventStartsBefore"
@ -506,7 +522,7 @@ func (ec exchangeCategory) leafCat() categorizer {
case ExchangeContact, ExchangeContactFolder, ExchangeFilterContactName: case ExchangeContact, ExchangeContactFolder, ExchangeFilterContactName:
return ExchangeContact return ExchangeContact
case ExchangeEvent, ExchangeEventCalendar, ExchangeFilterEventRecurs, case ExchangeEvent, ExchangeEventCalendar, ExchangeFilterEventOrganizer, ExchangeFilterEventRecurs,
ExchangeFilterEventStartsAfter, ExchangeFilterEventStartsBefore, ExchangeFilterEventSubject: ExchangeFilterEventStartsAfter, ExchangeFilterEventStartsBefore, ExchangeFilterEventSubject:
return ExchangeEvent return ExchangeEvent
@ -696,18 +712,20 @@ func (s ExchangeScope) matchesInfo(info *details.ExchangeInfo) bool {
switch filterCat { switch filterCat {
case ExchangeFilterContactName: case ExchangeFilterContactName:
i = info.ContactName i = info.ContactName
case ExchangeFilterEventOrganizer:
i = info.Organizer
case ExchangeFilterEventRecurs:
i = strconv.FormatBool(info.EventRecurs)
case ExchangeFilterEventStartsAfter, ExchangeFilterEventStartsBefore:
i = common.FormatTime(info.EventStart)
case ExchangeFilterEventSubject:
i = info.Subject
case ExchangeFilterMailSender: case ExchangeFilterMailSender:
i = info.Sender i = info.Sender
case ExchangeFilterMailSubject: case ExchangeFilterMailSubject:
i = info.Subject i = info.Subject
case ExchangeFilterMailReceivedAfter, ExchangeFilterMailReceivedBefore: case ExchangeFilterMailReceivedAfter, ExchangeFilterMailReceivedBefore:
i = common.FormatTime(info.Received) i = common.FormatTime(info.Received)
case ExchangeFilterEventRecurs:
i = "" // TODO: add EventRecurs is added to ExchangeInfo.
case ExchangeFilterEventStartsAfter, ExchangeFilterEventStartsBefore:
i = common.FormatTime(info.EventStart)
case ExchangeFilterEventSubject:
i = info.Subject
} }
return s.Matches(filterCat, i) return s.Matches(filterCat, i)

View File

@ -699,6 +699,7 @@ func (suite *ExchangeSelectorSuite) TestExchangeScope_MatchesInfo() {
const ( const (
name = "smarf mcfnords" name = "smarf mcfnords"
organizer = "cooks@2many.smarf"
sender = "smarf@2many.cooks" sender = "smarf@2many.cooks"
subject = "I have seen the fnords!" subject = "I have seen the fnords!"
) )
@ -709,11 +710,12 @@ func (suite *ExchangeSelectorSuite) TestExchangeScope_MatchesInfo() {
future = now.Add(1 * time.Minute) future = now.Add(1 * time.Minute)
info = &details.ExchangeInfo{ info = &details.ExchangeInfo{
ContactName: name, ContactName: name,
EventRecurs: true,
EventStart: now, EventStart: now,
Organizer: organizer,
Sender: sender, Sender: sender,
Subject: subject, Subject: subject,
Received: now, Received: now,
// TODO: event recurs
} }
) )
@ -722,33 +724,37 @@ func (suite *ExchangeSelectorSuite) TestExchangeScope_MatchesInfo() {
scope []ExchangeScope scope []ExchangeScope
expect assert.BoolAssertionFunc expect assert.BoolAssertionFunc
}{ }{
{"any mail with a sender", es.MailSender(Any()), assert.True}, {"any mail with a sender", es.MailSender(AnyTgt), assert.True},
{"no mail, regardless of sender", es.MailSender(None()), assert.False}, {"no mail, regardless of sender", es.MailSender(NoneTgt), assert.False},
{"mail from a different sender", es.MailSender([]string{"magoo@ma.goo"}), assert.False}, {"mail from a different sender", es.MailSender("magoo@ma.goo"), assert.False},
{"mail from the matching sender", es.MailSender([]string{sender}), assert.True}, {"mail from the matching sender", es.MailSender(sender), assert.True},
{"mail with any subject", es.MailSubject(Any()), assert.True}, {"mail with any subject", es.MailSubject(AnyTgt), assert.True},
{"mail with none subject", es.MailSubject(None()), assert.False}, {"mail with none subject", es.MailSubject(NoneTgt), assert.False},
{"mail with a different subject", es.MailSubject([]string{"fancy"}), assert.False}, {"mail with a different subject", es.MailSubject("fancy"), assert.False},
{"mail with the matching subject", es.MailSubject([]string{subject}), assert.True}, {"mail with the matching subject", es.MailSubject(subject), assert.True},
{"mail with a substring subject match", es.MailSubject([]string{subject[5:9]}), assert.True}, {"mail with a substring subject match", es.MailSubject(subject[5:9]), assert.True},
{"mail received after the epoch", es.MailReceivedAfter(common.FormatTime(epoch)), assert.True}, {"mail received after the epoch", es.MailReceivedAfter(common.FormatTime(epoch)), assert.True},
{"mail received after now", es.MailReceivedAfter(common.FormatTime(now)), assert.False}, {"mail received after now", es.MailReceivedAfter(common.FormatTime(now)), assert.False},
{"mail received after sometime later", es.MailReceivedAfter(common.FormatTime(future)), assert.False}, {"mail received after sometime later", es.MailReceivedAfter(common.FormatTime(future)), assert.False},
{"mail received before the epoch", es.MailReceivedBefore(common.FormatTime(epoch)), assert.False}, {"mail received before the epoch", es.MailReceivedBefore(common.FormatTime(epoch)), assert.False},
{"mail received before now", es.MailReceivedBefore(common.FormatTime(now)), assert.False}, {"mail received before now", es.MailReceivedBefore(common.FormatTime(now)), assert.False},
{"mail received before sometime later", es.MailReceivedBefore(common.FormatTime(future)), assert.True}, {"mail received before sometime later", es.MailReceivedBefore(common.FormatTime(future)), assert.True},
// TODO: {"event that recurs", es.EventRecurs(true), assert.True}, {"event with any organizer", es.EventOrganizer(AnyTgt), assert.True},
// TODO: {"event that does not recur", es.EventRecurs(false), assert.False}, {"event with none organizer", es.EventOrganizer(NoneTgt), assert.False},
{"event with a different organizer", es.EventOrganizer("fancy"), assert.False},
{"event with the matching organizer", es.EventOrganizer(organizer), assert.True},
{"event that recurs", es.EventRecurs("true"), assert.True},
{"event that does not recur", es.EventRecurs("false"), assert.False},
{"event starting after the epoch", es.EventStartsAfter(common.FormatTime(epoch)), assert.True}, {"event starting after the epoch", es.EventStartsAfter(common.FormatTime(epoch)), assert.True},
{"event starting after now", es.EventStartsAfter(common.FormatTime(now)), assert.False}, {"event starting after now", es.EventStartsAfter(common.FormatTime(now)), assert.False},
{"event starting after sometime later", es.EventStartsAfter(common.FormatTime(future)), assert.False}, {"event starting after sometime later", es.EventStartsAfter(common.FormatTime(future)), assert.False},
{"event starting before the epoch", es.EventStartsBefore(common.FormatTime(epoch)), assert.False}, {"event starting before the epoch", es.EventStartsBefore(common.FormatTime(epoch)), assert.False},
{"event starting before now", es.EventStartsBefore(common.FormatTime(now)), assert.False}, {"event starting before now", es.EventStartsBefore(common.FormatTime(now)), assert.False},
{"event starting before sometime later", es.EventStartsBefore(common.FormatTime(future)), assert.True}, {"event starting before sometime later", es.EventStartsBefore(common.FormatTime(future)), assert.True},
{"event with any subject", es.EventSubject(Any()), assert.True}, {"event with any subject", es.EventSubject(AnyTgt), assert.True},
{"event with none subject", es.EventSubject(None()), assert.False}, {"event with none subject", es.EventSubject(NoneTgt), assert.False},
{"event with a different subject", es.EventSubject([]string{"fancy"}), assert.False}, {"event with a different subject", es.EventSubject("fancy"), assert.False},
{"event with the matching subject", es.EventSubject([]string{subject}), assert.True}, {"event with the matching subject", es.EventSubject(subject), assert.True},
{"contact with a different name", es.ContactName("blarps"), assert.False}, {"contact with a different name", es.ContactName("blarps"), assert.False},
{"contact with the same name", es.ContactName(name), assert.True}, {"contact with the same name", es.ContactName(name), assert.True},
{"contact with a subname search", es.ContactName(name[2:5]), assert.True}, {"contact with a subname search", es.ContactName(name[2:5]), assert.True},