deduplicate shared exchange code in cli (#732)
This commit is contained in:
parent
57ddf26007
commit
25ce11b2c6
@ -66,15 +66,14 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
c, fs = utils.AddCommand(parent, exchangeCreateCmd())
|
||||
fs.StringSliceVar(
|
||||
&user,
|
||||
"user",
|
||||
nil,
|
||||
"Backup Exchange data by user ID; accepts "+utils.Wildcard+" to select all users",
|
||||
)
|
||||
fs.BoolVar(&exchangeAll, "all", false, "Backup all Exchange data for all users")
|
||||
"user", nil,
|
||||
"Backup Exchange data by user ID; accepts "+utils.Wildcard+" to select all users")
|
||||
fs.BoolVar(&exchangeAll,
|
||||
"all", false,
|
||||
"Backup all Exchange data for all users")
|
||||
fs.StringSliceVar(
|
||||
&exchangeData,
|
||||
"data",
|
||||
nil,
|
||||
"data", nil,
|
||||
"Select one or more types of data to backup: "+dataEmail+", "+dataContacts+", or "+dataEvents)
|
||||
options.AddOperationFlags(c)
|
||||
|
||||
@ -83,113 +82,82 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
|
||||
case detailsCommand:
|
||||
c, fs = utils.AddCommand(parent, exchangeDetailsCmd())
|
||||
fs.StringVar(&backupID, "backup", "", "ID of the backup containing the details to be shown")
|
||||
fs.StringVar(&backupID,
|
||||
"backup", "",
|
||||
"ID of the backup containing the details to be shown")
|
||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
||||
|
||||
// per-data-type flags
|
||||
fs.StringSliceVar(
|
||||
&contact,
|
||||
"contact",
|
||||
nil,
|
||||
"Select backup details by contact ID; accepts "+utils.Wildcard+" to select all contacts",
|
||||
)
|
||||
"contact", nil,
|
||||
"Select backup details by contact ID; accepts "+utils.Wildcard+" to select all contacts")
|
||||
fs.StringSliceVar(
|
||||
&contactFolder,
|
||||
"contact-folder",
|
||||
nil,
|
||||
"Select backup details by contact folder ID; accepts "+utils.Wildcard+" to select all contact folders",
|
||||
)
|
||||
"contact-folder", nil,
|
||||
"Select backup details by contact folder ID; accepts "+utils.Wildcard+" to select all contact folders")
|
||||
fs.StringSliceVar(
|
||||
&email,
|
||||
"email",
|
||||
nil,
|
||||
"Select backup details by emails ID; accepts "+utils.Wildcard+" to select all emails",
|
||||
)
|
||||
"email", nil,
|
||||
"Select backup details by emails ID; accepts "+utils.Wildcard+" to select all emails")
|
||||
fs.StringSliceVar(
|
||||
&emailFolder,
|
||||
"email-folder",
|
||||
nil,
|
||||
"email-folder", nil,
|
||||
"Select backup details by email folder ID; accepts "+utils.Wildcard+" to select all email folders")
|
||||
fs.StringSliceVar(
|
||||
&event,
|
||||
"event",
|
||||
nil,
|
||||
"Select backup details by event ID; accepts "+utils.Wildcard+" to select all events",
|
||||
)
|
||||
"event", nil,
|
||||
"Select backup details by event ID; accepts "+utils.Wildcard+" to select all events")
|
||||
fs.StringSliceVar(
|
||||
&eventCalendar,
|
||||
"event-calendar",
|
||||
nil,
|
||||
"Select backup details by event calendar ID; accepts "+utils.Wildcard+" to select all events",
|
||||
)
|
||||
"event-calendar", nil,
|
||||
"Select backup details by event calendar ID; accepts "+utils.Wildcard+" to select all events")
|
||||
fs.StringSliceVar(
|
||||
&user,
|
||||
"user",
|
||||
nil,
|
||||
"Select backup details by user ID; accepts "+utils.Wildcard+" to select all users",
|
||||
)
|
||||
"user", nil,
|
||||
"Select backup details by user ID; accepts "+utils.Wildcard+" to select all users")
|
||||
|
||||
// exchange-info flags
|
||||
fs.StringVar(
|
||||
&contactName,
|
||||
"contact-name",
|
||||
"",
|
||||
"Select backup details where the contact name contains this value",
|
||||
)
|
||||
"contact-name", "",
|
||||
"Select backup details where the contact name contains this value")
|
||||
fs.StringVar(
|
||||
&emailReceivedAfter,
|
||||
"email-received-after",
|
||||
"",
|
||||
"Restore mail where the email was received after this datetime",
|
||||
)
|
||||
"email-received-after", "",
|
||||
"Restore mail where the email was received after this datetime")
|
||||
fs.StringVar(
|
||||
&emailReceivedBefore,
|
||||
"email-received-before",
|
||||
"",
|
||||
"Restore mail where the email was received before this datetime",
|
||||
)
|
||||
"email-received-before", "",
|
||||
"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",
|
||||
)
|
||||
"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",
|
||||
)
|
||||
"email-subject", "",
|
||||
"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",
|
||||
)
|
||||
"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.",
|
||||
)
|
||||
"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",
|
||||
)
|
||||
"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",
|
||||
)
|
||||
"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",
|
||||
)
|
||||
"event-subject", "",
|
||||
"Select backup details where the event subject contains this value")
|
||||
|
||||
case deleteCommand:
|
||||
c, fs = utils.AddCommand(parent, exchangeDeleteCmd())
|
||||
@ -368,7 +336,7 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := validateExchangeBackupDetailFlags(
|
||||
if err := utils.ValidateExchangeRestoreFlags(
|
||||
contact,
|
||||
contactFolder,
|
||||
email,
|
||||
@ -399,7 +367,7 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
sel := selectors.NewExchangeRestore()
|
||||
includeExchangeBackupDetailDataSelectors(
|
||||
utils.IncludeExchangeRestoreDataSelectors(
|
||||
sel,
|
||||
contact,
|
||||
contactFolder,
|
||||
@ -408,7 +376,7 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
event,
|
||||
eventCalendar,
|
||||
user)
|
||||
filterExchangeBackupDetailInfoSelectors(
|
||||
utils.FilterExchangeRestoreInfoSelectors(
|
||||
sel,
|
||||
contactName,
|
||||
emailReceivedAfter,
|
||||
@ -436,207 +404,6 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// builds the data-selector inclusions for `backup details exchange`
|
||||
func includeExchangeBackupDetailDataSelectors(
|
||||
sel *selectors.ExchangeRestore,
|
||||
contacts, contactFolders, emails, emailFolders, events, eventCalendars, users []string,
|
||||
) {
|
||||
lc, lcf := len(contacts), len(contactFolders)
|
||||
le, lef := len(emails), len(emailFolders)
|
||||
lev, lec := len(events), len(eventCalendars)
|
||||
|
||||
// either scope the request to a set of users
|
||||
if lc+lcf+le+lef+lev+lec == 0 {
|
||||
if len(users) == 0 {
|
||||
users = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(sel.Users(users))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// or add selectors for each type of data
|
||||
includeExchangeContacts(sel, users, contactFolders, contacts)
|
||||
includeExchangeEmails(sel, users, emailFolders, email)
|
||||
includeExchangeEvents(sel, users, eventCalendars, events)
|
||||
}
|
||||
|
||||
func includeExchangeContacts(sel *selectors.ExchangeRestore, users, contactFolders, contacts []string) {
|
||||
if len(contactFolders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(contacts) == 0 {
|
||||
contacts = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(sel.Contacts(users, contactFolders, contacts))
|
||||
}
|
||||
|
||||
func includeExchangeEmails(sel *selectors.ExchangeRestore, users, emailFolders, emails []string) {
|
||||
if len(emailFolders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(emails) == 0 {
|
||||
emails = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(sel.Mails(users, emailFolders, emails))
|
||||
}
|
||||
|
||||
func includeExchangeEvents(sel *selectors.ExchangeRestore, users, eventCalendars, events []string) {
|
||||
if len(eventCalendars) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(events) == 0 {
|
||||
events = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(sel.Events(users, eventCalendars, events))
|
||||
}
|
||||
|
||||
// builds the info-selector filters for `backup details exchange`
|
||||
func filterExchangeBackupDetailInfoSelectors(
|
||||
sel *selectors.ExchangeRestore,
|
||||
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) {
|
||||
if len(receivedAfter) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
sel.Filter(sel.MailReceivedAfter(receivedAfter))
|
||||
}
|
||||
|
||||
func filterExchangeInfoMailReceivedBefore(sel *selectors.ExchangeRestore, receivedBefore string) {
|
||||
if len(receivedBefore) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
sel.Filter(sel.MailReceivedBefore(receivedBefore))
|
||||
}
|
||||
|
||||
func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender string) {
|
||||
if len(sender) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
sel.Filter(sel.MailSender(sender))
|
||||
}
|
||||
|
||||
func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject string) {
|
||||
if len(subject) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
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,
|
||||
backupID string,
|
||||
) error {
|
||||
if len(backupID) == 0 {
|
||||
return errors.New("a backup ID is required")
|
||||
}
|
||||
|
||||
lu := len(users)
|
||||
lc, lcf := len(contacts), len(contactFolders)
|
||||
le, lef := len(emails), len(emailFolders)
|
||||
lev, lec := len(events), len(eventCalendars)
|
||||
|
||||
if lu+lc+lcf+le+lef+lev+lec == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if lu == 0 {
|
||||
return errors.New("requires one or more --user ids, the wildcard --user *, or the --all flag")
|
||||
}
|
||||
|
||||
if lc > 0 && lcf == 0 {
|
||||
return errors.New(
|
||||
"one or more --contact-folder ids or the wildcard --contact-folder * must be included to specify a --contact")
|
||||
}
|
||||
|
||||
if le > 0 && lef == 0 {
|
||||
return errors.New(
|
||||
"one or more --email-folder ids or the wildcard --email-folder * must be included to specify an --email")
|
||||
}
|
||||
|
||||
if lev > 0 && lec == 0 {
|
||||
return errors.New(
|
||||
"one or more --event-calendar ids or the wildcard --event-calendar * must be included to specify an --event")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// backup delete
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -303,7 +303,7 @@ func (suite *ExchangeSuite) TestValidateBackupDetailFlags() {
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
test.expect(t, validateExchangeBackupDetailFlags(
|
||||
test.expect(t, utils.ValidateExchangeRestoreFlags(
|
||||
test.contacts,
|
||||
test.contactFolders,
|
||||
test.emails,
|
||||
@ -499,7 +499,7 @@ func (suite *ExchangeSuite) TestIncludeExchangeBackupDetailDataSelectors() {
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
sel := selectors.NewExchangeRestore()
|
||||
includeExchangeBackupDetailDataSelectors(
|
||||
utils.IncludeExchangeRestoreDataSelectors(
|
||||
sel,
|
||||
test.contacts,
|
||||
test.contactFolders,
|
||||
@ -600,7 +600,7 @@ func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
sel := selectors.NewExchangeRestore()
|
||||
filterExchangeBackupDetailInfoSelectors(
|
||||
utils.FilterExchangeRestoreInfoSelectors(
|
||||
sel,
|
||||
test.contactName,
|
||||
test.after,
|
||||
|
||||
@ -54,91 +54,71 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
// per-data-type flags
|
||||
fs.StringSliceVar(
|
||||
&contact,
|
||||
"contact",
|
||||
nil,
|
||||
"Restore contacts by ID; accepts "+utils.Wildcard+" to select all contacts",
|
||||
)
|
||||
"contact", nil,
|
||||
"Restore contacts by ID; accepts "+utils.Wildcard+" to select all contacts")
|
||||
fs.StringSliceVar(
|
||||
&contactFolder,
|
||||
"contact-folder",
|
||||
nil,
|
||||
"contact-folder", nil,
|
||||
"Restore all contacts within the folder ID; accepts "+utils.Wildcard+" to select all contact folders")
|
||||
fs.StringSliceVar(&email, "email", nil, "Restore emails by ID; accepts "+utils.Wildcard+" to select all emails")
|
||||
fs.StringSliceVar(&email,
|
||||
"email", nil,
|
||||
"Restore emails by ID; accepts "+utils.Wildcard+" to select all emails")
|
||||
fs.StringSliceVar(
|
||||
&emailFolder,
|
||||
"email-folder",
|
||||
nil,
|
||||
"Restore all emails by folder ID; accepts "+utils.Wildcard+" to select all email folders",
|
||||
)
|
||||
fs.StringSliceVar(&event, "event", nil, "Restore events by ID; accepts "+utils.Wildcard+" to select all events")
|
||||
"email-folder", nil,
|
||||
"Restore all emails by folder ID; accepts "+utils.Wildcard+" to select all email folders")
|
||||
fs.StringSliceVar(&event,
|
||||
"event", nil,
|
||||
"Restore events by ID; accepts "+utils.Wildcard+" to select all events")
|
||||
fs.StringSliceVar(
|
||||
&eventCalendar,
|
||||
"event-calendar",
|
||||
nil,
|
||||
"event-calendar", nil,
|
||||
"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")
|
||||
fs.StringSliceVar(&user,
|
||||
"user", nil,
|
||||
"Restore all data by user ID; accepts "+utils.Wildcard+" to select all users")
|
||||
|
||||
// exchange-info flags
|
||||
fs.StringVar(
|
||||
&contactName,
|
||||
"contact-name",
|
||||
"",
|
||||
"Restore contacts where the contact name contains this value",
|
||||
)
|
||||
"contact-name", "",
|
||||
"Restore contacts where the contact name contains this value")
|
||||
fs.StringVar(
|
||||
&emailReceivedAfter,
|
||||
"email-received-after",
|
||||
"",
|
||||
"Restore mail where the email was received after this datetime",
|
||||
)
|
||||
"email-received-after", "",
|
||||
"Restore mail where the email was received after this datetime")
|
||||
fs.StringVar(
|
||||
&emailReceivedBefore,
|
||||
"email-received-before",
|
||||
"",
|
||||
"Restore mail where the email was received before this datetime",
|
||||
)
|
||||
"email-received-before", "",
|
||||
"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",
|
||||
)
|
||||
"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",
|
||||
)
|
||||
"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",
|
||||
)
|
||||
"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.",
|
||||
)
|
||||
"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",
|
||||
)
|
||||
"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",
|
||||
)
|
||||
"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",
|
||||
)
|
||||
"event-subject", "",
|
||||
"Restore events where the event subject contains this value")
|
||||
|
||||
// others
|
||||
options.AddOperationFlags(c)
|
||||
@ -167,7 +147,7 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := validateExchangeRestoreFlags(
|
||||
if err := utils.ValidateExchangeRestoreFlags(
|
||||
contact,
|
||||
contactFolder,
|
||||
email,
|
||||
@ -193,7 +173,7 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
defer utils.CloseRepo(ctx, r)
|
||||
|
||||
sel := selectors.NewExchangeRestore()
|
||||
includeExchangeRestoreDataSelectors(
|
||||
utils.IncludeExchangeRestoreDataSelectors(
|
||||
sel,
|
||||
contact,
|
||||
contactFolder,
|
||||
@ -202,7 +182,7 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
event,
|
||||
eventCalendar,
|
||||
user)
|
||||
filterExchangeRestoreInfoSelectors(
|
||||
utils.FilterExchangeRestoreInfoSelectors(
|
||||
sel,
|
||||
contactName,
|
||||
emailReceivedAfter,
|
||||
@ -233,205 +213,3 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// builds the data-selector inclusions for `restore exchange`
|
||||
func includeExchangeRestoreDataSelectors(
|
||||
sel *selectors.ExchangeRestore,
|
||||
contacts, contactFolders, emails, emailFolders, events, eventCalendars, users []string,
|
||||
) {
|
||||
lc, lcf := len(contacts), len(contactFolders)
|
||||
le, lef := len(emails), len(emailFolders)
|
||||
lev, lec := len(events), len(eventCalendars)
|
||||
|
||||
// either scope the request to a set of users
|
||||
if lc+lcf+le+lef+lev+lec == 0 {
|
||||
if len(users) == 0 {
|
||||
users = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(sel.Users(users))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// or add selectors for each type of data
|
||||
includeExchangeContacts(sel, users, contactFolders, contacts)
|
||||
includeExchangeEmails(sel, users, emailFolders, email)
|
||||
includeExchangeEvents(sel, users, eventCalendars, events)
|
||||
}
|
||||
|
||||
func includeExchangeContacts(sel *selectors.ExchangeRestore, users, contactFolders, contacts []string) {
|
||||
if len(contactFolders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(contacts) == 0 {
|
||||
contacts = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(sel.Contacts(users, contactFolders, contacts))
|
||||
}
|
||||
|
||||
func includeExchangeEmails(sel *selectors.ExchangeRestore, users, emailFolders, emails []string) {
|
||||
if len(emailFolders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(emails) == 0 {
|
||||
emails = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(sel.Mails(users, emailFolders, emails))
|
||||
}
|
||||
|
||||
func includeExchangeEvents(sel *selectors.ExchangeRestore, users, eventCalendars, events []string) {
|
||||
if len(eventCalendars) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(events) == 0 {
|
||||
events = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(sel.Events(users, eventCalendars, events))
|
||||
}
|
||||
|
||||
// builds the info-selector filters for `restore exchange`
|
||||
func filterExchangeRestoreInfoSelectors(
|
||||
sel *selectors.ExchangeRestore,
|
||||
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) {
|
||||
if len(receivedAfter) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
sel.Filter(sel.MailReceivedAfter(receivedAfter))
|
||||
}
|
||||
|
||||
func filterExchangeInfoMailReceivedBefore(sel *selectors.ExchangeRestore, receivedBefore string) {
|
||||
if len(receivedBefore) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
sel.Filter(sel.MailReceivedBefore(receivedBefore))
|
||||
}
|
||||
|
||||
func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender string) {
|
||||
if len(sender) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
sel.Filter(sel.MailSender(sender))
|
||||
}
|
||||
|
||||
func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject string) {
|
||||
if len(subject) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
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,
|
||||
backupID string,
|
||||
) error {
|
||||
if len(backupID) == 0 {
|
||||
return errors.New("a backup ID is required")
|
||||
}
|
||||
|
||||
lu := len(users)
|
||||
lc, lcf := len(contacts), len(contactFolders)
|
||||
le, lef := len(emails), len(emailFolders)
|
||||
lev, lec := len(events), len(eventCalendars)
|
||||
|
||||
// if only the backupID is populated, that's the same as --all
|
||||
if lu+lc+lcf+le+lef+lev+lec == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if lu == 0 {
|
||||
return errors.New("requires one or more --user ids, the wildcard --user *, or the --all flag")
|
||||
}
|
||||
|
||||
if lc > 0 && lcf == 0 {
|
||||
return errors.New(
|
||||
"one or more --contact-folder ids or the wildcard --contact-folder * must be included to specify a --contact")
|
||||
}
|
||||
|
||||
if le > 0 && lef == 0 {
|
||||
return errors.New(
|
||||
"one or more --email-folder ids or the wildcard --email-folder * must be included to specify an --email")
|
||||
}
|
||||
|
||||
if lev > 0 && lec == 0 {
|
||||
return errors.New(
|
||||
"one or more --event-calendar ids or the wildcard --event-calendar * must be included to specify an --event")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ func (suite *ExchangeSuite) TestValidateExchangeRestoreFlags() {
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
test.expect(t, validateExchangeRestoreFlags(
|
||||
test.expect(t, utils.ValidateExchangeRestoreFlags(
|
||||
test.contacts,
|
||||
test.contactFolders,
|
||||
test.emails,
|
||||
@ -334,7 +334,7 @@ func (suite *ExchangeSuite) TestIncludeExchangeRestoreDataSelectors() {
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
sel := selectors.NewExchangeRestore()
|
||||
includeExchangeRestoreDataSelectors(
|
||||
utils.IncludeExchangeRestoreDataSelectors(
|
||||
sel,
|
||||
test.contacts,
|
||||
test.contactFolders,
|
||||
@ -435,7 +435,7 @@ func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
sel := selectors.NewExchangeRestore()
|
||||
filterExchangeRestoreInfoSelectors(
|
||||
utils.FilterExchangeRestoreInfoSelectors(
|
||||
sel,
|
||||
test.contactName,
|
||||
test.after,
|
||||
|
||||
126
src/cli/utils/exchange.go
Normal file
126
src/cli/utils/exchange.go
Normal file
@ -0,0 +1,126 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/alcionai/corso/src/pkg/selectors"
|
||||
)
|
||||
|
||||
// AddExchangeInclude adds the scope of the provided values to the selector's
|
||||
// inclusion set.
|
||||
func AddExchangeInclude(
|
||||
sel *selectors.ExchangeRestore,
|
||||
resource, folders, items []string,
|
||||
incl func([]string, []string, []string) []selectors.ExchangeScope,
|
||||
) {
|
||||
if len(folders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(items) == 0 {
|
||||
items = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(incl(resource, folders, items))
|
||||
}
|
||||
|
||||
// AddExchangeFilter adds the scope of the provided values to the selector's
|
||||
// filter set
|
||||
func AddExchangeFilter(
|
||||
sel *selectors.ExchangeRestore,
|
||||
v string,
|
||||
f func(string) []selectors.ExchangeScope,
|
||||
) {
|
||||
if len(v) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
sel.Filter(f(v))
|
||||
}
|
||||
|
||||
// ValidateExchangeRestoreFlags checks common flags for correctness and interdependencies
|
||||
func ValidateExchangeRestoreFlags(
|
||||
contacts, contactFolders, emails, emailFolders, events, eventCalendars, users []string,
|
||||
backupID string,
|
||||
) error {
|
||||
if len(backupID) == 0 {
|
||||
return errors.New("a backup ID is required")
|
||||
}
|
||||
|
||||
lu := len(users)
|
||||
lc, lcf := len(contacts), len(contactFolders)
|
||||
le, lef := len(emails), len(emailFolders)
|
||||
lev, lec := len(events), len(eventCalendars)
|
||||
|
||||
// if only the backupID is populated, that's the same as --all
|
||||
if lu+lc+lcf+le+lef+lev+lec == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if lu == 0 {
|
||||
return errors.New("requires one or more --user ids, the wildcard --user *, or the --all flag")
|
||||
}
|
||||
|
||||
if lc > 0 && lcf == 0 {
|
||||
return errors.New(
|
||||
"one or more --contact-folder ids or the wildcard --contact-folder * must be included to specify a --contact")
|
||||
}
|
||||
|
||||
if le > 0 && lef == 0 {
|
||||
return errors.New(
|
||||
"one or more --email-folder ids or the wildcard --email-folder * must be included to specify an --email")
|
||||
}
|
||||
|
||||
if lev > 0 && lec == 0 {
|
||||
return errors.New(
|
||||
"one or more --event-calendar ids or the wildcard --event-calendar * must be included to specify an --event")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IncludeExchangeRestoreDataSelectors builds the common data-selector
|
||||
// inclusions for exchange commands.
|
||||
func IncludeExchangeRestoreDataSelectors(
|
||||
sel *selectors.ExchangeRestore,
|
||||
contacts, contactFolders, emails, emailFolders, events, eventCalendars, users []string,
|
||||
) {
|
||||
lc, lcf := len(contacts), len(contactFolders)
|
||||
le, lef := len(emails), len(emailFolders)
|
||||
lev, lec := len(events), len(eventCalendars)
|
||||
|
||||
// either scope the request to a set of users
|
||||
if lc+lcf+le+lef+lev+lec == 0 {
|
||||
if len(users) == 0 {
|
||||
users = selectors.Any()
|
||||
}
|
||||
|
||||
sel.Include(sel.Users(users))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// or add selectors for each type of data
|
||||
AddExchangeInclude(sel, users, contactFolders, contacts, sel.Contacts)
|
||||
AddExchangeInclude(sel, users, emailFolders, emails, sel.Mails)
|
||||
AddExchangeInclude(sel, users, eventCalendars, events, sel.Events)
|
||||
}
|
||||
|
||||
// FilterExchangeRestoreInfoSelectors builds the common info-selector filters.
|
||||
func FilterExchangeRestoreInfoSelectors(
|
||||
sel *selectors.ExchangeRestore,
|
||||
contactName,
|
||||
emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject,
|
||||
eventOrganizer, eventRecurs, eventStartsAfter, eventStartsBefore, eventSubject string,
|
||||
) {
|
||||
AddExchangeFilter(sel, contactName, sel.ContactName)
|
||||
AddExchangeFilter(sel, emailReceivedAfter, sel.MailReceivedAfter)
|
||||
AddExchangeFilter(sel, emailReceivedBefore, sel.MailReceivedBefore)
|
||||
AddExchangeFilter(sel, emailSender, sel.MailSender)
|
||||
AddExchangeFilter(sel, emailSubject, sel.MailSubject)
|
||||
AddExchangeFilter(sel, eventOrganizer, sel.EventOrganizer)
|
||||
AddExchangeFilter(sel, eventRecurs, sel.EventRecurs)
|
||||
AddExchangeFilter(sel, eventStartsAfter, sel.EventStartsAfter)
|
||||
AddExchangeFilter(sel, eventStartsBefore, sel.EventStartsBefore)
|
||||
AddExchangeFilter(sel, eventSubject, sel.EventSubject)
|
||||
}
|
||||
@ -12,6 +12,7 @@ require (
|
||||
github.com/kopia/kopia v0.11.1
|
||||
github.com/microsoft/kiota-abstractions-go v0.8.2
|
||||
github.com/microsoft/kiota-authentication-azure-go v0.3.0
|
||||
github.com/microsoft/kiota-http-go v0.6.0
|
||||
github.com/microsoft/kiota-serialization-json-go v0.5.5
|
||||
github.com/microsoftgraph/msgraph-sdk-go v0.34.0
|
||||
github.com/microsoftgraph/msgraph-sdk-go-core v0.27.0
|
||||
@ -48,7 +49,6 @@ require (
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/chmduquesne/rollinghash v4.0.0+incompatible // indirect
|
||||
github.com/cjlapao/common-go v0.0.25 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
@ -71,7 +71,6 @@ require (
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/microsoft/kiota-http-go v0.6.0 // indirect
|
||||
github.com/microsoft/kiota-serialization-text-go v0.4.1 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.34 // indirect
|
||||
@ -88,7 +87,6 @@ require (
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rs/xid v1.4.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
|
||||
@ -79,7 +79,6 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@ -335,7 +334,6 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
|
||||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user