add event selector info filters (#703)

## Description

Adds filtering support for exchnage events in
the exchange selector.

## Type of change

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

## Issue(s)

#501

## Test Plan

- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
Keepers 2022-08-31 14:44:03 -06:00 committed by GitHub
parent 9fe6ca7f56
commit 6de326a2c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 11 deletions

View File

@ -1,6 +1,8 @@
package selectors package selectors
import ( import (
"strconv"
"github.com/alcionai/corso/internal/common" "github.com/alcionai/corso/internal/common"
"github.com/alcionai/corso/pkg/backup/details" "github.com/alcionai/corso/pkg/backup/details"
"github.com/alcionai/corso/pkg/filters" "github.com/alcionai/corso/pkg/filters"
@ -260,6 +262,64 @@ func (s *exchange) Users(users []string) []ExchangeScope {
// ------------------- // -------------------
// Filter Factories // Filter Factories
// EventRecurs produces one or more exchange event recurrence filter scopes.
// 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.None, that slice is reduced to [selectors.None]
// If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) EventRecurs(recurs bool) []ExchangeScope {
return []ExchangeScope{
makeFilterScope[ExchangeScope](
ExchangeEvent,
ExchangeFilterEventRecurs,
[]string{strconv.FormatBool(recurs)},
wrapFilter(filters.Equal)),
}
}
// EventStartsAfter produces an exchange event starts-after filter scope.
// Matches any event where the start time is after the timestring.
// If the input equals selectors.Any, the scope will match all times.
// If the input is empty or selectors.None, the scope will always fail comparisons.
func (sr *ExchangeRestore) EventStartsAfter(timeStrings string) []ExchangeScope {
return []ExchangeScope{
makeFilterScope[ExchangeScope](
ExchangeMail,
ExchangeFilterMailReceivedAfter,
[]string{timeStrings},
wrapFilter(filters.Less)),
}
}
// EventStartsBefore produces an exchange event starts-before filter scope.
// Matches any event where the start time is before the timestring.
// If the input equals selectors.Any, the scope will match all times.
// If the input is empty or selectors.None, the scope will always fail comparisons.
func (sr *ExchangeRestore) EventStartsBefore(timeStrings string) []ExchangeScope {
return []ExchangeScope{
makeFilterScope[ExchangeScope](
ExchangeMail,
ExchangeFilterMailReceivedBefore,
[]string{timeStrings},
wrapFilter(filters.Greater)),
}
}
// 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) EventSubject(subjectSubstrings []string) []ExchangeScope {
return []ExchangeScope{
makeFilterScope[ExchangeScope](
ExchangeEvent,
ExchangeFilterEventSubject,
subjectSubstrings,
wrapFilter(filters.In)),
}
}
// ContactName produces one or more exchange contact name filter scopes. // ContactName produces one or more exchange contact name filter scopes.
// Matches any contact whose name contains the provided string. // 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.Any, that slice is reduced to [selectors.Any]
@ -399,6 +459,10 @@ const (
ExchangeFilterMailReceivedAfter exchangeCategory = "ExchangeFilterMailReceivedAfter" ExchangeFilterMailReceivedAfter exchangeCategory = "ExchangeFilterMailReceivedAfter"
ExchangeFilterMailReceivedBefore exchangeCategory = "ExchangeFilterMailReceivedBefore" ExchangeFilterMailReceivedBefore exchangeCategory = "ExchangeFilterMailReceivedBefore"
ExchangeFilterContactName exchangeCategory = "ExchangeFilterContactName" ExchangeFilterContactName exchangeCategory = "ExchangeFilterContactName"
ExchangeFilterEventRecurs exchangeCategory = "ExchangeFilterEventRecurs"
ExchangeFilterEventStartsAfter exchangeCategory = "ExchangeFilterEventStartsAfter"
ExchangeFilterEventStartsBefore exchangeCategory = "ExchangeFilterEventStartsBefore"
ExchangeFilterEventSubject exchangeCategory = "ExchangeFilterEventSubject"
// append new filter cats here // append new filter cats here
) )
@ -428,6 +492,9 @@ func (ec exchangeCategory) leafCat() categorizer {
switch ec { switch ec {
case ExchangeContact, ExchangeContactFolder, ExchangeFilterContactName: case ExchangeContact, ExchangeContactFolder, ExchangeFilterContactName:
return ExchangeContact return ExchangeContact
case ExchangeEvent, ExchangeFilterEventRecurs, ExchangeFilterEventStartsAfter,
ExchangeFilterEventStartsBefore, ExchangeFilterEventSubject:
return ExchangeEvent
case ExchangeMail, ExchangeMailFolder, ExchangeFilterMailReceivedAfter, case ExchangeMail, ExchangeMailFolder, ExchangeFilterMailReceivedAfter,
ExchangeFilterMailReceivedBefore, ExchangeFilterMailSender, ExchangeFilterMailSubject: ExchangeFilterMailReceivedBefore, ExchangeFilterMailSender, ExchangeFilterMailSubject:
return ExchangeMail return ExchangeMail
@ -631,10 +698,14 @@ func (s ExchangeScope) matchesInfo(info *details.ExchangeInfo) bool {
i = info.Sender i = info.Sender
case ExchangeFilterMailSubject: case ExchangeFilterMailSubject:
i = info.Subject i = info.Subject
case ExchangeFilterMailReceivedAfter: case ExchangeFilterMailReceivedAfter, ExchangeFilterMailReceivedBefore:
i = common.FormatTime(info.Received)
case 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

@ -654,12 +654,14 @@ func (suite *ExchangeSelectorSuite) TestExchangeScope_MatchesInfo() {
var ( var (
epoch = time.Time{} epoch = time.Time{}
now = time.Now() now = time.Now()
then = now.Add(1 * time.Minute) future = now.Add(1 * time.Minute)
info = &details.ExchangeInfo{ info = &details.ExchangeInfo{
ContactName: name,
EventStart: now,
Sender: sender, Sender: sender,
Subject: subject, Subject: subject,
Received: now, Received: now,
ContactName: name, // TODO: event recurs
} }
) )
@ -673,16 +675,28 @@ func (suite *ExchangeSelectorSuite) TestExchangeScope_MatchesInfo() {
{"mail from a different sender", es.MailSender([]string{"magoo@ma.goo"}), assert.False}, {"mail from a different sender", es.MailSender([]string{"magoo@ma.goo"}), assert.False},
{"mail from the matching sender", es.MailSender([]string{sender}), assert.True}, {"mail from the matching sender", es.MailSender([]string{sender}), assert.True},
{"mail with any subject", es.MailSubject(Any()), assert.True}, {"mail with any subject", es.MailSubject(Any()), assert.True},
{"no mail, regardless of subject", es.MailSubject(None()), assert.False}, {"mail with none subject", es.MailSubject(None()), assert.False},
{"mail with a different subject", es.MailSubject([]string{"fancy"}), assert.False}, {"mail with a different subject", es.MailSubject([]string{"fancy"}), assert.False},
{"mail with the matching subject", es.MailSubject([]string{subject}), assert.True}, {"mail with the matching subject", es.MailSubject([]string{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([]string{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(then)), 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(then)), assert.True}, {"mail received before sometime later", es.MailReceivedBefore(common.FormatTime(future)), assert.True},
// TODO: {"event that recurs", es.EventRecurs(true), assert.True},
// TODO: {"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 now", es.EventStartsAfter(common.FormatTime(now)), 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 now", es.EventStartsBefore(common.FormatTime(now)), assert.False},
{"event starting before sometime later", es.EventStartsBefore(common.FormatTime(future)), assert.True},
{"event with any subject", es.EventSubject(Any()), assert.True},
{"event with none subject", es.EventSubject(None()), assert.False},
{"event with a different subject", es.EventSubject([]string{"fancy"}), assert.False},
{"event with the matching subject", es.EventSubject([]string{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},