reduce filter selector flags to single strings (#393)

* reduce filter selector flags to single strings

Since it doesn't make sense for many of the filter-type
selector flags to receive multiple input values (ex: what
would --received-after date1,date2 result in?), the filter
flags are getting reduced to single-string values.
This commit is contained in:
Keepers 2022-07-26 10:31:34 -06:00 committed by GitHub
parent 350d27dcb4
commit 1929b2307f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 99 deletions

View File

@ -27,10 +27,10 @@ var (
contactFolder []string contactFolder []string
email []string email []string
emailFolder []string emailFolder []string
emailReceivedAfter []string emailReceivedAfter string
emailReceivedBefore []string emailReceivedBefore string
emailSender []string emailSender string
emailSubject []string emailSubject string
event []string event []string
user []string user []string
) )
@ -93,10 +93,10 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
cobra.CheckErr(fs.MarkHidden("event")) cobra.CheckErr(fs.MarkHidden("event"))
// exchange-info flags // exchange-info flags
fs.StringArrayVar(&emailReceivedAfter, "email-received-after", nil, "Select backup details where the email was received after this datetime") fs.StringVar(&emailReceivedAfter, "email-received-after", "", "Select backup details where the email was received after this datetime")
fs.StringArrayVar(&emailReceivedBefore, "email-received-before", nil, "Select backup details where the email was received before this datetime") fs.StringVar(&emailReceivedBefore, "email-received-before", "", "Select backup details where the email was received before this datetime")
fs.StringArrayVar(&emailSender, "email-sender", nil, "Select backup details where the email sender matches this user id") fs.StringVar(&emailSender, "email-sender", "", "Select backup details where the email sender matches this user id")
fs.StringArrayVar(&emailSubject, "email-subject", nil, "Select backup details where the email subject lines contain this value") fs.StringVar(&emailSubject, "email-subject", "", "Select backup details where the email subject lines contain this value")
} }
return c return c
@ -392,7 +392,7 @@ func includeExchangeEvents(sel *selectors.ExchangeRestore, users, events []strin
// builds the info-selector filters for `backup details exchange` // builds the info-selector filters for `backup details exchange`
func filterExchangeBackupDetailInfoSelectors( func filterExchangeBackupDetailInfoSelectors(
sel *selectors.ExchangeRestore, sel *selectors.ExchangeRestore,
emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject []string, emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject string,
) { ) {
filterExchangeInfoMailReceivedAfter(sel, emailReceivedAfter) filterExchangeInfoMailReceivedAfter(sel, emailReceivedAfter)
filterExchangeInfoMailReceivedBefore(sel, emailReceivedBefore) filterExchangeInfoMailReceivedBefore(sel, emailReceivedBefore)
@ -400,32 +400,32 @@ func filterExchangeBackupDetailInfoSelectors(
filterExchangeInfoMailSubject(sel, emailSubject) filterExchangeInfoMailSubject(sel, emailSubject)
} }
func filterExchangeInfoMailReceivedAfter(sel *selectors.ExchangeRestore, receivedAfter []string) { func filterExchangeInfoMailReceivedAfter(sel *selectors.ExchangeRestore, receivedAfter string) {
if len(receivedAfter) == 0 { if len(receivedAfter) == 0 {
return return
} }
sel.Filter(sel.MailReceivedAfter(receivedAfter)) sel.Filter(sel.MailReceivedAfter(receivedAfter))
} }
func filterExchangeInfoMailReceivedBefore(sel *selectors.ExchangeRestore, receivedBefore []string) { func filterExchangeInfoMailReceivedBefore(sel *selectors.ExchangeRestore, receivedBefore string) {
if len(receivedBefore) == 0 { if len(receivedBefore) == 0 {
return return
} }
sel.Filter(sel.MailReceivedBefore(receivedBefore)) sel.Filter(sel.MailReceivedBefore(receivedBefore))
} }
func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender []string) { func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender string) {
if len(sender) == 0 { if len(sender) == 0 {
return return
} }
sel.Filter(sel.MailSender(sender)) sel.Filter(sel.MailSender([]string{sender}))
} }
func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject []string) { func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject string) {
if len(subject) == 0 { if len(subject) == 0 {
return return
} }
sel.Filter(sel.MailSubject(subject)) sel.Filter(sel.MailSubject([]string{subject}))
} }
// checks all flags for correctness and interdependencies // checks all flags for correctness and interdependencies

View File

@ -481,12 +481,11 @@ func (suite *ExchangeSuite) TestIncludeExchangeBackupDetailDataSelectors() {
} }
func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() { func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
stub := []string{"id-stub"} stub := "id-stub"
twoStubs := []string{"smarfs", "fnords"} any := utils.Wildcard
any := []string{utils.Wildcard}
table := []struct { table := []struct {
name string name string
after, before, sender, subject []string after, before, sender, subject string
expectFilterLen int expectFilterLen int
}{ }{
{ {
@ -503,11 +502,6 @@ func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
after: stub, after: stub,
expectFilterLen: 1, expectFilterLen: 1,
}, },
{
name: "multiple receivedAfter",
after: twoStubs,
expectFilterLen: 1,
},
{ {
name: "any receivedBefore", name: "any receivedBefore",
before: any, before: any,
@ -518,11 +512,6 @@ func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
before: stub, before: stub,
expectFilterLen: 1, expectFilterLen: 1,
}, },
{
name: "multiple receivedBefore",
before: twoStubs,
expectFilterLen: 1,
},
{ {
name: "any sender", name: "any sender",
sender: any, sender: any,
@ -533,11 +522,6 @@ func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
sender: stub, sender: stub,
expectFilterLen: 1, expectFilterLen: 1,
}, },
{
name: "multiple senders",
sender: twoStubs,
expectFilterLen: 1,
},
{ {
name: "any subject", name: "any subject",
subject: any, subject: any,
@ -548,11 +532,6 @@ func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
subject: stub, subject: stub,
expectFilterLen: 1, expectFilterLen: 1,
}, },
{
name: "multiple subjects",
subject: twoStubs,
expectFilterLen: 1,
},
{ {
name: "one of each", name: "one of each",
after: stub, after: stub,

View File

@ -22,10 +22,10 @@ var (
contactFolder []string contactFolder []string
email []string email []string
emailFolder []string emailFolder []string
emailReceivedAfter []string emailReceivedAfter string
emailReceivedBefore []string emailReceivedBefore string
emailSender []string emailSender string
emailSubject []string emailSubject string
event []string event []string
user []string user []string
) )
@ -65,10 +65,10 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
cobra.CheckErr(fs.MarkHidden("event")) cobra.CheckErr(fs.MarkHidden("event"))
// exchange-info flags // exchange-info flags
fs.StringArrayVar(&emailReceivedAfter, "email-received-after", nil, "Restore mail where the email was received after this datetime") fs.StringVar(&emailReceivedAfter, "email-received-after", "", "Restore mail where the email was received after this datetime")
fs.StringArrayVar(&emailReceivedBefore, "email-received-before", nil, "Restore mail where the email was received before this datetime") fs.StringVar(&emailReceivedBefore, "email-received-before", "", "Restore mail where the email was received before this datetime")
fs.StringArrayVar(&emailSender, "email-sender", nil, "Restore mail where the email sender matches this user id") fs.StringVar(&emailSender, "email-sender", "", "Restore mail where the email sender matches this user id")
fs.StringArrayVar(&emailSubject, "email-subject", nil, "Restore mail where the email subject lines contain this value") fs.StringVar(&emailSubject, "email-subject", "", "Restore mail where the email subject lines contain this value")
// others // others
options.AddOperationFlags(c) options.AddOperationFlags(c)
@ -221,7 +221,7 @@ func includeExchangeEvents(sel *selectors.ExchangeRestore, users, events []strin
// builds the info-selector filters for `restore exchange` // builds the info-selector filters for `restore exchange`
func filterExchangeRestoreInfoSelectors( func filterExchangeRestoreInfoSelectors(
sel *selectors.ExchangeRestore, sel *selectors.ExchangeRestore,
emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject []string, emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject string,
) { ) {
filterExchangeInfoMailReceivedAfter(sel, emailReceivedAfter) filterExchangeInfoMailReceivedAfter(sel, emailReceivedAfter)
filterExchangeInfoMailReceivedBefore(sel, emailReceivedBefore) filterExchangeInfoMailReceivedBefore(sel, emailReceivedBefore)
@ -229,32 +229,32 @@ func filterExchangeRestoreInfoSelectors(
filterExchangeInfoMailSubject(sel, emailSubject) filterExchangeInfoMailSubject(sel, emailSubject)
} }
func filterExchangeInfoMailReceivedAfter(sel *selectors.ExchangeRestore, receivedAfter []string) { func filterExchangeInfoMailReceivedAfter(sel *selectors.ExchangeRestore, receivedAfter string) {
if len(receivedAfter) == 0 { if len(receivedAfter) == 0 {
return return
} }
sel.Filter(sel.MailReceivedAfter(receivedAfter)) sel.Filter(sel.MailReceivedAfter(receivedAfter))
} }
func filterExchangeInfoMailReceivedBefore(sel *selectors.ExchangeRestore, receivedBefore []string) { func filterExchangeInfoMailReceivedBefore(sel *selectors.ExchangeRestore, receivedBefore string) {
if len(receivedBefore) == 0 { if len(receivedBefore) == 0 {
return return
} }
sel.Filter(sel.MailReceivedBefore(receivedBefore)) sel.Filter(sel.MailReceivedBefore(receivedBefore))
} }
func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender []string) { func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender string) {
if len(sender) == 0 { if len(sender) == 0 {
return return
} }
sel.Filter(sel.MailSender(sender)) sel.Filter(sel.MailSender([]string{sender}))
} }
func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject []string) { func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject string) {
if len(subject) == 0 { if len(subject) == 0 {
return return
} }
sel.Filter(sel.MailSubject(subject)) sel.Filter(sel.MailSubject([]string{subject}))
} }
// checks all flags for correctness and interdependencies // checks all flags for correctness and interdependencies

View File

@ -317,12 +317,11 @@ func (suite *ExchangeSuite) TestIncludeExchangeRestoreDataSelectors() {
} }
func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() { func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
stub := []string{"id-stub"} stub := "id-stub"
twoStubs := []string{"a-stub", "b-stub"} any := utils.Wildcard
any := []string{utils.Wildcard}
table := []struct { table := []struct {
name string name string
after, before, sender, subject []string after, before, sender, subject string
expectFilterLen int expectFilterLen int
}{ }{
{ {
@ -339,11 +338,6 @@ func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
after: stub, after: stub,
expectFilterLen: 1, expectFilterLen: 1,
}, },
{
name: "multiple receivedAfter",
after: twoStubs,
expectFilterLen: 1,
},
{ {
name: "any receivedBefore", name: "any receivedBefore",
before: any, before: any,
@ -354,11 +348,6 @@ func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
before: stub, before: stub,
expectFilterLen: 1, expectFilterLen: 1,
}, },
{
name: "multiple receivedBefore",
before: twoStubs,
expectFilterLen: 1,
},
{ {
name: "any senders", name: "any senders",
sender: any, sender: any,
@ -369,11 +358,6 @@ func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
sender: stub, sender: stub,
expectFilterLen: 1, expectFilterLen: 1,
}, },
{
name: "multiple senders",
sender: twoStubs,
expectFilterLen: 1,
},
{ {
name: "any subjects", name: "any subjects",
subject: any, subject: any,
@ -384,11 +368,6 @@ func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
subject: stub, subject: stub,
expectFilterLen: 1, expectFilterLen: 1,
}, },
{
name: "multiple subjects",
subject: twoStubs,
expectFilterLen: 1,
},
{ {
name: "one of each", name: "one of each",
after: stub, after: stub,

View File

@ -292,30 +292,28 @@ func makeExchangeFilterScope(cat, filterCat exchangeCategory, vs []string) Excha
} }
} }
// Produces one or more exchange mail received-after filter scopes. // Produces an exchange mail received-after filter scope.
// Matches any mail which was received after the timestring. // Matches any mail which was received after the timestring.
// If any slice contains selectors.Any, that slice is reduced to [selectors.Any] // If the input equals selectors.Any, the scope will match all times.
// If any slice contains selectors.None, that slice is reduced to [selectors.None] // If the input is empty or selectors.None, the scope will always fail comparisons.
// If any slice is empty, it defaults to [selectors.None] func (sr *ExchangeRestore) MailReceivedAfter(timeStrings string) []ExchangeScope {
func (sr *ExchangeRestore) MailReceivedAfter(timeStrings []string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeExchangeFilterScope(ExchangeMail, ExchangeInfoMailReceivedAfter, timeStrings), makeExchangeFilterScope(ExchangeMail, ExchangeInfoMailReceivedAfter, []string{timeStrings}),
} }
} }
// Produces one or more exchange mail received-before filter scopes. // Produces an exchange mail received-before filter scope.
// Matches any mail whose mail subject contains one of the provided strings. // Matches any mail which was received before the timestring.
// If any slice contains selectors.Any, that slice is reduced to [selectors.Any] // If the input equals selectors.Any, the scope will match all times.
// If any slice contains selectors.None, that slice is reduced to [selectors.None] // If the input is empty or selectors.None, the scope will always fail comparisons.
// If any slice is empty, it defaults to [selectors.None] func (sr *ExchangeRestore) MailReceivedBefore(timeStrings string) []ExchangeScope {
func (sr *ExchangeRestore) MailReceivedBefore(timeStrings []string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeExchangeFilterScope(ExchangeMail, ExchangeInfoMailReceivedBefore, timeStrings), makeExchangeFilterScope(ExchangeMail, ExchangeInfoMailReceivedBefore, []string{timeStrings}),
} }
} }
// Produces one or more exchange mail sender filter scopes. // Produces one or more exchange mail sender filter scopes.
// Matches any mail which was received after the timestring. // Matches any mail whose mail sender equals one of the provided strings.
// 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]
@ -326,7 +324,7 @@ func (sr *ExchangeRestore) MailSender(senderIDs []string) []ExchangeScope {
} }
// Produces one or more exchange mail subject line filter scopes. // Produces one or more exchange mail subject line filter scopes.
// Matches any mail which was received before the timestring. // Matches any mail whose mail 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.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]

View File

@ -519,12 +519,12 @@ func (suite *ExchangeSourceSuite) TestExchangeScope_MatchesInfo() {
{"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([]string{common.FormatTime(epoch)}), assert.True}, {"mail received after the epoch", es.MailReceivedAfter(common.FormatTime(epoch)), assert.True},
{"mail received after now", es.MailReceivedAfter([]string{common.FormatTime(now)}), assert.False}, {"mail received after now", es.MailReceivedAfter(common.FormatTime(now)), assert.False},
{"mail received after sometime later", es.MailReceivedAfter([]string{common.FormatTime(then)}), assert.False}, {"mail received after sometime later", es.MailReceivedAfter(common.FormatTime(then)), assert.False},
{"mail received before the epoch", es.MailReceivedBefore([]string{common.FormatTime(epoch)}), assert.False}, {"mail received before the epoch", es.MailReceivedBefore(common.FormatTime(epoch)), assert.False},
{"mail received before now", es.MailReceivedBefore([]string{common.FormatTime(now)}), assert.False}, {"mail received before now", es.MailReceivedBefore(common.FormatTime(now)), assert.False},
{"mail received before sometime later", es.MailReceivedBefore([]string{common.FormatTime(then)}), assert.True}, {"mail received before sometime later", es.MailReceivedBefore(common.FormatTime(then)), assert.True},
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {

View File

@ -31,6 +31,8 @@ const (
Filter = "filter" Filter = "filter"
) )
// The granularity exprerssed by the scope. Groups imply non-item granularity,
// such as a directory. Items are individual files or objects.
const ( const (
// AnyTgt is the target value used to select "any data of <type>" // AnyTgt is the target value used to select "any data of <type>"
// Ex: {user: u1, events: AnyTgt) => all events for user u1. // Ex: {user: u1, events: AnyTgt) => all events for user u1.