expose event info flags in cli (#727)

## Description

Adds the new event filter selectors to the CLI for
backup detail and restore commands.

## 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-02 10:25:58 -06:00 committed by GitHub
parent 568d8e2a0c
commit af9dfe6654
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 353 additions and 74 deletions

View File

@ -21,20 +21,29 @@ import (
// exchange bucket info from flags
var (
backupID string
exchangeAll bool
exchangeData []string
contact []string
contactFolder []string
backupID string
exchangeAll bool
exchangeData []string
user []string
contact []string
contactFolder []string
contactName string
email []string
emailFolder []string
emailReceivedAfter string
emailReceivedBefore string
emailSender string
emailSubject string
event []string
eventCalendar []string
user []string
event []string
eventCalendar []string
eventOrganizer string
eventRecurs string
eventStartsAfter string
eventStartsBefore string
eventSubject string
)
const (
@ -121,24 +130,65 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
)
// exchange-info flags
fs.StringVar(
&contactName,
"contact-name",
"",
"Select backup details where the contact name contains this value",
)
fs.StringVar(
&emailReceivedAfter,
"email-received-after",
"",
"Select backup details where the email was received after this datetime",
"Restore mail where the email was received after this datetime",
)
fs.StringVar(
&emailReceivedBefore,
"email-received-before",
"",
"Select backup details where the email was received before this datetime",
"Restore mail where the email was received before this datetime",
)
fs.StringVar(
&emailSender,
"email-sender",
"",
"Restore mail 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.StringVar(
&emailSubject,
"email-subject",
"",
"Select backup details where the email subject lines contain this value",
"Restore mail where the email subject lines contain this value",
)
fs.StringVar(
&eventOrganizer,
"event-organizer",
"",
"Select backup details where the event organizer user id contains this value",
)
fs.StringVar(
&eventRecurs,
"event-recurs",
"",
"Select backup details if the event recurs. Use --event-recurs false to select where the event does not recur.",
)
fs.StringVar(
&eventStartsAfter,
"event-starts-after",
"",
"Select backup details where the event starts after this datetime",
)
fs.StringVar(
&eventStartsBefore,
"event-starts-before",
"",
"Select backup details where the event starts before this datetime",
)
fs.StringVar(
&eventSubject,
"event-subject",
"",
"Select backup details where the event subject contains this value",
)
case deleteCommand:
@ -360,10 +410,16 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
user)
filterExchangeBackupDetailInfoSelectors(
sel,
contactName,
emailReceivedAfter,
emailReceivedBefore,
emailSender,
emailSubject)
emailSubject,
eventOrganizer,
eventRecurs,
eventStartsAfter,
eventStartsBefore,
eventSubject)
// if no selector flags were specified, get all data in the service.
if len(sel.Scopes()) == 0 {
@ -445,12 +501,28 @@ func includeExchangeEvents(sel *selectors.ExchangeRestore, users, eventCalendars
// builds the info-selector filters for `backup details exchange`
func filterExchangeBackupDetailInfoSelectors(
sel *selectors.ExchangeRestore,
emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject string,
contactName,
emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject,
eventOrganizer, eventRecurs, eventStartsAfter, eventStartsBefore, eventSubject string,
) {
filterExchangeInfoContactName(sel, contactName)
filterExchangeInfoMailReceivedAfter(sel, emailReceivedAfter)
filterExchangeInfoMailReceivedBefore(sel, emailReceivedBefore)
filterExchangeInfoMailSender(sel, emailSender)
filterExchangeInfoMailSubject(sel, emailSubject)
filterExchangeInfoEventOrganizer(sel, eventOrganizer)
filterExchangeInfoEventRecurs(sel, eventRecurs)
filterExchangeInfoEventStartsAfter(sel, eventStartsAfter)
filterExchangeInfoEventStartsBefore(sel, eventStartsBefore)
filterExchangeInfoEventSubject(sel, eventSubject)
}
func filterExchangeInfoContactName(sel *selectors.ExchangeRestore, name string) {
if len(name) == 0 {
return
}
sel.Filter(sel.ContactName(name))
}
func filterExchangeInfoMailReceivedAfter(sel *selectors.ExchangeRestore, receivedAfter string) {
@ -485,6 +557,46 @@ func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject strin
sel.Filter(sel.MailSubject(subject))
}
func filterExchangeInfoEventOrganizer(sel *selectors.ExchangeRestore, organizer string) {
if len(organizer) == 0 {
return
}
sel.Filter(sel.EventOrganizer(organizer))
}
func filterExchangeInfoEventRecurs(sel *selectors.ExchangeRestore, recurs string) {
if len(recurs) == 0 {
return
}
sel.Filter(sel.EventRecurs(recurs))
}
func filterExchangeInfoEventStartsAfter(sel *selectors.ExchangeRestore, startsAfter string) {
if len(startsAfter) == 0 {
return
}
sel.Filter(sel.EventStartsAfter(startsAfter))
}
func filterExchangeInfoEventStartsBefore(sel *selectors.ExchangeRestore, startsBefore string) {
if len(startsBefore) == 0 {
return
}
sel.Filter(sel.EventStartsBefore(startsBefore))
}
func filterExchangeInfoEventSubject(sel *selectors.ExchangeRestore, subject string) {
if len(subject) == 0 {
return
}
sel.Filter(sel.EventSubject(subject))
}
// checks all flags for correctness and interdependencies
func validateExchangeBackupDetailFlags(
contacts, contactFolders, emails, emailFolders, events, eventCalendars, users []string,

View File

@ -515,64 +515,86 @@ func (suite *ExchangeSuite) TestIncludeExchangeBackupDetailDataSelectors() {
func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
stub := "id-stub"
a := utils.Wildcard
table := []struct {
name string
after, before, sender, subject string
expectFilterLen int
name string
contactName string
after, before, sender, subject string
organizer, recurs, startsAfter, startsBefore, eventSubject string
expectFilterLen int
}{
{
name: "no selectors",
expectFilterLen: 0,
},
{
name: "any receivedAfter",
after: a,
name: "contactName",
contactName: stub,
expectFilterLen: 1,
},
{
name: "single receivedAfter",
name: "receivedAfter",
after: stub,
expectFilterLen: 1,
},
{
name: "any receivedBefore",
before: a,
name: "receivedAfter",
after: stub,
expectFilterLen: 1,
},
{
name: "single receivedBefore",
name: "receivedBefore",
before: stub,
expectFilterLen: 1,
},
{
name: "any sender",
sender: a,
expectFilterLen: 1,
},
{
name: "single sender",
name: "sender",
sender: stub,
expectFilterLen: 1,
},
{
name: "any subject",
subject: a,
name: "subject",
subject: stub,
expectFilterLen: 1,
},
{
name: "single subject",
subject: stub,
name: "organizer",
organizer: stub,
expectFilterLen: 1,
},
{
name: "recurs",
recurs: stub,
expectFilterLen: 1,
},
{
name: "startsAfter",
startsAfter: stub,
expectFilterLen: 1,
},
{
name: "startsBefore",
startsBefore: stub,
expectFilterLen: 1,
},
{
name: "eventSubject",
eventSubject: stub,
expectFilterLen: 1,
},
{
name: "one of each",
contactName: stub,
after: stub,
before: stub,
sender: stub,
subject: stub,
expectFilterLen: 4,
organizer: stub,
recurs: stub,
startsAfter: stub,
startsBefore: stub,
eventSubject: stub,
expectFilterLen: 10,
},
}
for _, test := range table {
@ -580,10 +602,16 @@ func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
sel := selectors.NewExchangeRestore()
filterExchangeBackupDetailInfoSelectors(
sel,
test.contactName,
test.after,
test.before,
test.sender,
test.subject)
test.subject,
test.organizer,
test.recurs,
test.startsAfter,
test.startsBefore,
test.eventSubject)
assert.Equal(t, test.expectFilterLen, len(sel.Filters))
})
}

View File

@ -15,18 +15,27 @@ import (
// exchange bucket info from flags
var (
backupID string
contact []string
contactFolder []string
backupID string
user []string
contact []string
contactFolder []string
contactName string
email []string
emailFolder []string
emailReceivedAfter string
emailReceivedBefore string
emailSender string
emailSubject string
event []string
eventCalendar []string
user []string
event []string
eventCalendar []string
eventOrganizer string
eventRecurs string
eventStartsAfter string
eventStartsBefore string
eventSubject string
)
// called by restore.go to map parent subcommands to provider-specific handling.
@ -69,13 +78,13 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
"Restore events by calendar ID; accepts "+utils.Wildcard+" to select all event calendars")
fs.StringSliceVar(&user, "user", nil, "Restore all data by user ID; accepts "+utils.Wildcard+" to select all users")
// TODO: reveal these flags when their production is supported in GC
cobra.CheckErr(fs.MarkHidden("contact"))
cobra.CheckErr(fs.MarkHidden("contact-folder"))
cobra.CheckErr(fs.MarkHidden("event"))
cobra.CheckErr(fs.MarkHidden("event-calendar"))
// exchange-info flags
fs.StringVar(
&contactName,
"contact-name",
"",
"Restore contacts where the contact name contains this value",
)
fs.StringVar(
&emailReceivedAfter,
"email-received-after",
@ -88,8 +97,48 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
"",
"Restore mail where the email was received before this datetime",
)
fs.StringVar(&emailSender, "email-sender", "", "Restore mail where the email sender matches this user id")
fs.StringVar(&emailSubject, "email-subject", "", "Restore mail where the email subject lines contain this value")
fs.StringVar(
&emailSender,
"email-sender",
"",
"Restore mail where the email sender matches this user id",
)
fs.StringVar(
&emailSubject,
"email-subject",
"",
"Restore mail where the email subject lines contain this value",
)
fs.StringVar(
&eventOrganizer,
"event-organizer",
"",
"Restore events where the event organizer user id contains this value",
)
fs.StringVar(
&eventRecurs,
"event-recurs",
"",
"Restore events if the event recurs. Use --event-recurs false to select where the event does not recur.",
)
fs.StringVar(
&eventStartsAfter,
"event-starts-after",
"",
"Restore events where the event starts after this datetime",
)
fs.StringVar(
&eventStartsBefore,
"event-starts-before",
"",
"Restore events where the event starts before this datetime",
)
fs.StringVar(
&eventSubject,
"event-subject",
"",
"Restore events where the event subject contains this value",
)
// others
options.AddOperationFlags(c)
@ -155,10 +204,16 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
user)
filterExchangeRestoreInfoSelectors(
sel,
contactName,
emailReceivedAfter,
emailReceivedBefore,
emailSender,
emailSubject)
emailSubject,
eventOrganizer,
eventRecurs,
eventStartsAfter,
eventStartsBefore,
eventSubject)
// if no selector flags were specified, get all data in the service.
if len(sel.Scopes()) == 0 {
@ -244,12 +299,28 @@ func includeExchangeEvents(sel *selectors.ExchangeRestore, users, eventCalendars
// builds the info-selector filters for `restore exchange`
func filterExchangeRestoreInfoSelectors(
sel *selectors.ExchangeRestore,
emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject string,
contactName,
emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject,
eventOrganizer, eventRecurs, eventStartsAfter, eventStartsBefore, eventSubject string,
) {
filterExchangeInfoContactName(sel, contactName)
filterExchangeInfoMailReceivedAfter(sel, emailReceivedAfter)
filterExchangeInfoMailReceivedBefore(sel, emailReceivedBefore)
filterExchangeInfoMailSender(sel, emailSender)
filterExchangeInfoMailSubject(sel, emailSubject)
filterExchangeInfoEventOrganizer(sel, eventOrganizer)
filterExchangeInfoEventRecurs(sel, eventRecurs)
filterExchangeInfoEventStartsAfter(sel, eventStartsAfter)
filterExchangeInfoEventStartsBefore(sel, eventStartsBefore)
filterExchangeInfoEventSubject(sel, eventSubject)
}
func filterExchangeInfoContactName(sel *selectors.ExchangeRestore, name string) {
if len(name) == 0 {
return
}
sel.Filter(sel.ContactName(name))
}
func filterExchangeInfoMailReceivedAfter(sel *selectors.ExchangeRestore, receivedAfter string) {
@ -284,6 +355,46 @@ func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject strin
sel.Filter(sel.MailSubject(subject))
}
func filterExchangeInfoEventOrganizer(sel *selectors.ExchangeRestore, organizer string) {
if len(organizer) == 0 {
return
}
sel.Filter(sel.EventOrganizer(organizer))
}
func filterExchangeInfoEventRecurs(sel *selectors.ExchangeRestore, recurs string) {
if len(recurs) == 0 {
return
}
sel.Filter(sel.EventRecurs(recurs))
}
func filterExchangeInfoEventStartsAfter(sel *selectors.ExchangeRestore, startsAfter string) {
if len(startsAfter) == 0 {
return
}
sel.Filter(sel.EventStartsAfter(startsAfter))
}
func filterExchangeInfoEventStartsBefore(sel *selectors.ExchangeRestore, startsBefore string) {
if len(startsBefore) == 0 {
return
}
sel.Filter(sel.EventStartsBefore(startsBefore))
}
func filterExchangeInfoEventSubject(sel *selectors.ExchangeRestore, subject string) {
if len(subject) == 0 {
return
}
sel.Filter(sel.EventSubject(subject))
}
// checks all flags for correctness and interdependencies
func validateExchangeRestoreFlags(
contacts, contactFolders, emails, emailFolders, events, eventCalendars, users []string,

View File

@ -350,64 +350,86 @@ func (suite *ExchangeSuite) TestIncludeExchangeRestoreDataSelectors() {
func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
stub := "id-stub"
a := utils.Wildcard
table := []struct {
name string
after, before, sender, subject string
expectFilterLen int
name string
contactName string
after, before, sender, subject string
organizer, recurs, startsAfter, startsBefore, eventSubject string
expectFilterLen int
}{
{
name: "no selectors",
expectFilterLen: 0,
},
{
name: "any receivedAfter",
after: a,
name: "contactName",
contactName: stub,
expectFilterLen: 1,
},
{
name: "single receivedAfter",
name: "receivedAfter",
after: stub,
expectFilterLen: 1,
},
{
name: "any receivedBefore",
before: a,
name: "receivedAfter",
after: stub,
expectFilterLen: 1,
},
{
name: "single receivedBefore",
name: "receivedBefore",
before: stub,
expectFilterLen: 1,
},
{
name: "any senders",
sender: a,
expectFilterLen: 1,
},
{
name: "single sender",
name: "sender",
sender: stub,
expectFilterLen: 1,
},
{
name: "any subjects",
subject: a,
name: "subject",
subject: stub,
expectFilterLen: 1,
},
{
name: "single subject",
subject: stub,
name: "organizer",
organizer: stub,
expectFilterLen: 1,
},
{
name: "recurs",
recurs: stub,
expectFilterLen: 1,
},
{
name: "startsAfter",
startsAfter: stub,
expectFilterLen: 1,
},
{
name: "startsBefore",
startsBefore: stub,
expectFilterLen: 1,
},
{
name: "eventSubject",
eventSubject: stub,
expectFilterLen: 1,
},
{
name: "one of each",
contactName: stub,
after: stub,
before: stub,
sender: stub,
subject: stub,
expectFilterLen: 4,
organizer: stub,
recurs: stub,
startsAfter: stub,
startsBefore: stub,
eventSubject: stub,
expectFilterLen: 10,
},
}
for _, test := range table {
@ -415,10 +437,16 @@ func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
sel := selectors.NewExchangeRestore()
filterExchangeRestoreInfoSelectors(
sel,
test.contactName,
test.after,
test.before,
test.sender,
test.subject)
test.subject,
test.organizer,
test.recurs,
test.startsAfter,
test.startsBefore,
test.eventSubject)
assert.Equal(t, test.expectFilterLen, len(sel.Filters))
})
}