adds usage of the export format validation check to export cli commands. Also moves the restore cfg validation check out of the service flags validation checks and into the generic restore runner for better separation of concerns. --- #### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🌻 Feature #### Issue(s) * #3988 #### Test Plan - [x] ⚡ Unit test - [x] 💚 E2E
190 lines
5.6 KiB
Go
190 lines
5.6 KiB
Go
package utils
|
|
|
|
import (
|
|
"github.com/alcionai/clues"
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/alcionai/corso/src/cli/flags"
|
|
"github.com/alcionai/corso/src/pkg/selectors"
|
|
)
|
|
|
|
type ExchangeOpts struct {
|
|
Users []string
|
|
|
|
Contact []string
|
|
ContactFolder []string
|
|
ContactName string
|
|
|
|
Email []string
|
|
EmailFolder []string
|
|
EmailReceivedAfter string
|
|
EmailReceivedBefore string
|
|
EmailSender string
|
|
EmailSubject string
|
|
|
|
Event []string
|
|
EventCalendar []string
|
|
EventOrganizer string
|
|
EventRecurs string
|
|
EventStartsAfter string
|
|
EventStartsBefore string
|
|
EventSubject string
|
|
|
|
RestoreCfg RestoreCfgOpts
|
|
|
|
Populated flags.PopulatedFlags
|
|
}
|
|
|
|
// populates an ExchangeOpts struct with the command's current flags.
|
|
func MakeExchangeOpts(cmd *cobra.Command) ExchangeOpts {
|
|
return ExchangeOpts{
|
|
Users: flags.UserFV,
|
|
|
|
Contact: flags.ContactFV,
|
|
ContactFolder: flags.ContactFolderFV,
|
|
ContactName: flags.ContactNameFV,
|
|
|
|
Email: flags.EmailFV,
|
|
EmailFolder: flags.EmailFolderFV,
|
|
EmailReceivedAfter: flags.EmailReceivedAfterFV,
|
|
EmailReceivedBefore: flags.EmailReceivedBeforeFV,
|
|
EmailSender: flags.EmailSenderFV,
|
|
EmailSubject: flags.EmailSubjectFV,
|
|
|
|
Event: flags.EventFV,
|
|
EventCalendar: flags.EventCalendarFV,
|
|
EventOrganizer: flags.EventOrganizerFV,
|
|
EventRecurs: flags.EventRecursFV,
|
|
EventStartsAfter: flags.EventStartsAfterFV,
|
|
EventStartsBefore: flags.EventStartsBeforeFV,
|
|
EventSubject: flags.EventSubjectFV,
|
|
|
|
RestoreCfg: makeRestoreCfgOpts(cmd),
|
|
|
|
// populated contains the list of flags that appear in the
|
|
// command, according to pflags. Use this to differentiate
|
|
// between an "empty" and a "missing" value.
|
|
Populated: flags.GetPopulatedFlags(cmd),
|
|
}
|
|
}
|
|
|
|
// AddExchangeInclude adds the scope of the provided values to the selector's
|
|
// inclusion set. Any unpopulated slice will be replaced with selectors.Any()
|
|
// to act as a wildcard.
|
|
func AddExchangeInclude(
|
|
sel *selectors.ExchangeRestore,
|
|
folders, items []string,
|
|
eisc selectors.ExchangeItemScopeConstructor,
|
|
) {
|
|
lf, li := len(folders), len(items)
|
|
|
|
// only use the inclusion if either a folder or item of
|
|
// this type is specified.
|
|
if lf+li == 0 {
|
|
return
|
|
}
|
|
|
|
if li == 0 {
|
|
items = selectors.Any()
|
|
}
|
|
|
|
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(folders)
|
|
|
|
if len(containsFolders) > 0 {
|
|
sel.Include(eisc(containsFolders, items))
|
|
}
|
|
|
|
if len(prefixFolders) > 0 {
|
|
sel.Include(eisc(prefixFolders, items, selectors.PrefixMatch()))
|
|
}
|
|
}
|
|
|
|
// AddExchangeInfo adds the scope of the provided values to the selector's
|
|
// filter set
|
|
func AddExchangeInfo(
|
|
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(backupID string, opts ExchangeOpts) error {
|
|
if len(backupID) == 0 {
|
|
return clues.New("a backup ID is required")
|
|
}
|
|
|
|
if _, ok := opts.Populated[flags.EmailReceivedAfterFN]; ok && !IsValidTimeFormat(opts.EmailReceivedAfter) {
|
|
return clues.New("invalid time format for email-received-after")
|
|
}
|
|
|
|
if _, ok := opts.Populated[flags.EmailReceivedBeforeFN]; ok && !IsValidTimeFormat(opts.EmailReceivedBefore) {
|
|
return clues.New("invalid time format for email-received-before")
|
|
}
|
|
|
|
if _, ok := opts.Populated[flags.EventStartsAfterFN]; ok && !IsValidTimeFormat(opts.EventStartsAfter) {
|
|
return clues.New("invalid time format for event-starts-after")
|
|
}
|
|
|
|
if _, ok := opts.Populated[flags.EventStartsBeforeFN]; ok && !IsValidTimeFormat(opts.EventStartsBefore) {
|
|
return clues.New("invalid time format for event-starts-before")
|
|
}
|
|
|
|
if _, ok := opts.Populated[flags.EventRecursFN]; ok && !IsValidBool(opts.EventRecurs) {
|
|
return clues.New("invalid format for event-recurs")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// IncludeExchangeRestoreDataSelectors builds the common data-selector
|
|
// inclusions for exchange commands.
|
|
func IncludeExchangeRestoreDataSelectors(opts ExchangeOpts) *selectors.ExchangeRestore {
|
|
users := opts.Users
|
|
if len(users) == 0 {
|
|
users = selectors.Any()
|
|
}
|
|
|
|
sel := selectors.NewExchangeRestore(users)
|
|
|
|
lc, lcf := len(opts.Contact), len(opts.ContactFolder)
|
|
le, lef := len(opts.Email), len(opts.EmailFolder)
|
|
lev, lec := len(opts.Event), len(opts.EventCalendar)
|
|
// either scope the request to a set of users
|
|
if lc+lcf+le+lef+lev+lec == 0 {
|
|
sel.Include(sel.AllData())
|
|
return sel
|
|
}
|
|
|
|
opts.EmailFolder = trimFolderSlash(opts.EmailFolder)
|
|
|
|
// or add selectors for each type of data
|
|
AddExchangeInclude(sel, opts.ContactFolder, opts.Contact, sel.Contacts)
|
|
AddExchangeInclude(sel, opts.EmailFolder, opts.Email, sel.Mails)
|
|
AddExchangeInclude(sel, opts.EventCalendar, opts.Event, sel.Events)
|
|
|
|
return sel
|
|
}
|
|
|
|
// FilterExchangeRestoreInfoSelectors builds the common info-selector filters.
|
|
func FilterExchangeRestoreInfoSelectors(
|
|
sel *selectors.ExchangeRestore,
|
|
opts ExchangeOpts,
|
|
) {
|
|
AddExchangeInfo(sel, opts.ContactName, sel.ContactName)
|
|
AddExchangeInfo(sel, opts.EmailReceivedAfter, sel.MailReceivedAfter)
|
|
AddExchangeInfo(sel, opts.EmailReceivedBefore, sel.MailReceivedBefore)
|
|
AddExchangeInfo(sel, opts.EmailSender, sel.MailSender)
|
|
AddExchangeInfo(sel, opts.EmailSubject, sel.MailSubject)
|
|
AddExchangeInfo(sel, opts.EventOrganizer, sel.EventOrganizer)
|
|
AddExchangeInfo(sel, opts.EventRecurs, sel.EventRecurs)
|
|
AddExchangeInfo(sel, opts.EventStartsAfter, sel.EventStartsAfter)
|
|
AddExchangeInfo(sel, opts.EventStartsBefore, sel.EventStartsBefore)
|
|
AddExchangeInfo(sel, opts.EventSubject, sel.EventSubject)
|
|
}
|