diff --git a/src/cli/backup/exchange.go b/src/cli/backup/exchange.go index b1da988ba..a283436c3 100644 --- a/src/cli/backup/exchange.go +++ b/src/cli/backup/exchange.go @@ -26,28 +26,7 @@ import ( // exchange bucket info from flags var ( - backupID string 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 - eventOrganizer string - eventRecurs string - eventStartsAfter string - eventStartsBefore string - eventSubject string ) const ( @@ -81,15 +60,15 @@ corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --user a # Explore Alice's emails with subject containing "Hello world" in folder "Inbox" from a specific backup corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ - --user alice@example.com --email-subject "Hello world" --email-folder Inbox + --user alice@example.com --email-subject "Hello world" --email-folder Inbox # Explore Bobs's events occurring after start of 2022 from a specific backup corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ - --user bob@example.com --event-starts-after 2022-01-01T00:00:00 + --user bob@example.com --event-starts-after 2022-01-01T00:00:00 # Explore Alice's contacts with name containing Andy from a specific backup corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ - --user alice@example.com --contact-name Andy` + --user alice@example.com --contact-name Andy` ) // called by backup.go to map subcommands to provider-specific handling. @@ -109,10 +88,8 @@ func addExchangeCommands(cmd *cobra.Command) *cobra.Command { // Flags addition ordering should follow the order we want them to appear in help and docs: // More generic (ex: --user) and more frequently used flags take precedence. - fs.StringSliceVar( - &user, - utils.UserFN, nil, - "Backup Exchange data by a user's email; accepts '"+utils.Wildcard+"' to select all users") + utils.AddUserFlag(c) + fs.StringSliceVar( &exchangeData, utils.DataFN, nil, @@ -121,17 +98,15 @@ func addExchangeCommands(cmd *cobra.Command) *cobra.Command { case listCommand: c, fs = utils.AddCommand(cmd, exchangeListCmd()) + fs.SortFlags = false - fs.StringVar(&backupID, - "backup", "", - "Display a specific backup, including the items that failed or were skipped during processing.") - + utils.AddBackupIDFlag(c, false) addFailedItemsFN(c) addSkippedItemsFN(c) addRecoveredErrorsFN(c) case detailsCommand: - c, fs = utils.AddCommand(cmd, exchangeDetailsCmd()) + c, _ = utils.AddCommand(cmd, exchangeDetailsCmd()) c.Use = c.Use + " " + exchangeServiceCommandDetailsUseSuffix c.Example = exchangeServiceCommandDetailsExamples @@ -140,95 +115,16 @@ func addExchangeCommands(cmd *cobra.Command) *cobra.Command { // Flags addition ordering should follow the order we want them to appear in help and docs: // More generic (ex: --user) and more frequently used flags take precedence. - fs.StringVar(&backupID, - utils.BackupFN, "", - "ID of the backup to explore. (required)") - cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN)) - fs.StringSliceVar( - &user, - utils.UserFN, nil, - "Select backup details by user ID; accepts '"+utils.Wildcard+"' to select all users.") - - // email flags - fs.StringSliceVar( - &email, - utils.EmailFN, nil, - "Select backup details for emails by email ID; accepts '"+utils.Wildcard+"' to select all emails.") - fs.StringSliceVar( - &emailFolder, - utils.EmailFolderFN, nil, - "Select backup details for emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.") - fs.StringVar( - &emailSubject, - utils.EmailSubjectFN, "", - "Select backup details for emails with a subject containing this value.") - fs.StringVar( - &emailSender, - utils.EmailSenderFN, "", - "Select backup details for emails from a specific sender.") - fs.StringVar( - &emailReceivedAfter, - utils.EmailReceivedAfterFN, "", - "Select backup details for emails received after this datetime.") - fs.StringVar( - &emailReceivedBefore, - utils.EmailReceivedBeforeFN, "", - "Select backup details for emails received before this datetime.") - - // event flags - fs.StringSliceVar( - &event, - utils.EventFN, nil, - "Select backup details for events by event ID; accepts '"+utils.Wildcard+"' to select all events.") - fs.StringSliceVar( - &eventCalendar, - utils.EventCalendarFN, nil, - "Select backup details for events under a calendar; accepts '"+utils.Wildcard+"' to select all events.") - fs.StringVar( - &eventSubject, - utils.EventSubjectFN, "", - "Select backup details for events with a subject containing this value.") - fs.StringVar( - &eventOrganizer, - utils.EventOrganizerFN, "", - "Select backup details for events from a specific organizer.") - fs.StringVar( - &eventRecurs, - utils.EventRecursFN, "", - "Select backup details for recurring events. Use `--event-recurs false` to select non-recurring events.") - fs.StringVar( - &eventStartsAfter, - utils.EventStartsAfterFN, "", - "Select backup details for events starting after this datetime.") - fs.StringVar( - &eventStartsBefore, - utils.EventStartsBeforeFN, "", - "Select backup details for events starting before this datetime.") - - // contact flags - fs.StringSliceVar( - &contact, - utils.ContactFN, nil, - "Select backup details for contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.") - fs.StringSliceVar( - &contactFolder, - utils.ContactFolderFN, nil, - "Select backup details for contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.") - fs.StringVar( - &contactName, - utils.ContactNameFN, "", - "Select backup details for contacts whose contact name contains this value.") + utils.AddBackupIDFlag(c, true) + utils.AddExchangeDetailsAndRestoreFlags(c) case deleteCommand: - c, fs = utils.AddCommand(cmd, exchangeDeleteCmd()) + c, _ = utils.AddCommand(cmd, exchangeDeleteCmd()) c.Use = c.Use + " " + exchangeServiceCommandDeleteUseSuffix c.Example = exchangeServiceCommandDeleteExamples - fs.StringVar(&backupID, - utils.BackupFN, "", - "ID of the backup to delete. (required)") - cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN)) + utils.AddBackupIDFlag(c, true) } return c @@ -256,7 +152,7 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error { return nil } - if err := validateExchangeBackupCreateFlags(user, exchangeData); err != nil { + if err := validateExchangeBackupCreateFlags(utils.User, exchangeData); err != nil { return err } @@ -267,7 +163,7 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error { defer utils.CloseRepo(ctx, r) - sel := exchangeBackupCreateSelectors(user, exchangeData) + sel := exchangeBackupCreateSelectors(utils.User, exchangeData) // TODO: log/print recoverable errors errs := fault.New(false) @@ -345,7 +241,7 @@ func exchangeListCmd() *cobra.Command { // lists the history of backup operations func listExchangeCmd(cmd *cobra.Command, args []string) error { - return genericListCommand(cmd, backupID, path.ExchangeService, args) + return genericListCommand(cmd, utils.BackupID, path.ExchangeService, args) } // ------------------------------------------------------------------------------------------------ @@ -371,23 +267,26 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error { ctx := cmd.Context() opts := utils.ExchangeOpts{ - Contact: contact, - ContactFolder: contactFolder, - Email: email, - EmailFolder: emailFolder, - Event: event, - EventCalendar: eventCalendar, - Users: user, - ContactName: contactName, - EmailReceivedAfter: emailReceivedAfter, - EmailReceivedBefore: emailReceivedBefore, - EmailSender: emailSender, - EmailSubject: emailSubject, - EventOrganizer: eventOrganizer, - EventRecurs: eventRecurs, - EventStartsAfter: eventStartsAfter, - EventStartsBefore: eventStartsBefore, - EventSubject: eventSubject, + Users: utils.User, + + Contact: utils.Contact, + ContactFolder: utils.ContactFolder, + ContactName: utils.ContactName, + + Email: utils.Email, + EmailFolder: utils.EmailFolder, + EmailReceivedAfter: utils.EmailReceivedAfter, + EmailReceivedBefore: utils.EmailReceivedBefore, + EmailSender: utils.EmailSender, + EmailSubject: utils.EmailSubject, + EventOrganizer: utils.EventOrganizer, + + Event: utils.Event, + EventCalendar: utils.EventCalendar, + EventRecurs: utils.EventRecurs, + EventStartsAfter: utils.EventStartsAfter, + EventStartsBefore: utils.EventStartsBefore, + EventSubject: utils.EventSubject, Populated: utils.GetPopulatedFlags(cmd), } @@ -401,7 +300,7 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error { ctrlOpts := options.Control() - ds, err := runDetailsExchangeCmd(ctx, r, backupID, opts, ctrlOpts.SkipReduce) + ds, err := runDetailsExchangeCmd(ctx, r, utils.BackupID, opts, ctrlOpts.SkipReduce) if err != nil { return Only(ctx, err) } @@ -467,5 +366,5 @@ func exchangeDeleteCmd() *cobra.Command { // deletes an exchange service backup. func deleteExchangeCmd(cmd *cobra.Command, args []string) error { - return genericDeleteCommand(cmd, backupID, "Exchange", args) + return genericDeleteCommand(cmd, utils.BackupID, "Exchange", args) } diff --git a/src/cli/backup/onedrive.go b/src/cli/backup/onedrive.go index 4a623e22a..fa46d6c26 100644 --- a/src/cli/backup/onedrive.go +++ b/src/cli/backup/onedrive.go @@ -49,11 +49,11 @@ corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd --user a # Explore Alice or Bob's files with name containing "Fiscal 22" in folder "Reports" corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \ - --user alice@example.com,bob@example.com --file-name "Fiscal 22" --folder "Reports" + --user alice@example.com,bob@example.com --file-name "Fiscal 22" --folder "Reports" # Explore Alice's files created before end of 2015 from a specific backup corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \ - --user alice@example.com --file-created-before 2015-01-01T00:00:00` + --user alice@example.com --file-created-before 2015-01-01T00:00:00` ) // called by backup.go to map subcommands to provider-specific handling. @@ -65,83 +65,41 @@ func addOneDriveCommands(cmd *cobra.Command) *cobra.Command { switch cmd.Use { case createCommand: - c, fs = utils.AddCommand(cmd, oneDriveCreateCmd()) + c, _ = utils.AddCommand(cmd, oneDriveCreateCmd()) options.AddFeatureToggle(cmd, options.EnablePermissionsBackup()) c.Use = c.Use + " " + oneDriveServiceCommandCreateUseSuffix c.Example = oneDriveServiceCommandCreateExamples - fs.StringSliceVar(&user, - utils.UserFN, nil, - "Backup OneDrive data by user's email address; accepts '"+utils.Wildcard+"' to select all users. (required)") + utils.AddUserFlag(c) options.AddOperationFlags(c) case listCommand: c, fs = utils.AddCommand(cmd, oneDriveListCmd()) + fs.SortFlags = false - fs.StringVar(&backupID, - "backup", "", - "Display a specific backup, including the items that failed or were skipped during processing.") - + utils.AddBackupIDFlag(c, false) addFailedItemsFN(c) addSkippedItemsFN(c) addRecoveredErrorsFN(c) case detailsCommand: - c, fs = utils.AddCommand(cmd, oneDriveDetailsCmd()) + c, _ = utils.AddCommand(cmd, oneDriveDetailsCmd()) c.Use = c.Use + " " + oneDriveServiceCommandDetailsUseSuffix c.Example = oneDriveServiceCommandDetailsExamples options.AddSkipReduceFlag(c) - - fs.StringVar(&backupID, - utils.BackupFN, "", - "ID of the backup to explore. (required)") - cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN)) - - // onedrive hierarchy flags - - fs.StringSliceVar( - &utils.FolderPaths, - utils.FolderFN, nil, - "Select backup details by OneDrive folder; defaults to root.") - - fs.StringSliceVar( - &utils.FileNames, - utils.FileFN, nil, - "Select backup details by file name.") - - // onedrive info flags - - fs.StringVar( - &utils.FileCreatedAfter, - utils.FileCreatedAfterFN, "", - "Select backup details for files created after this datetime.") - fs.StringVar( - &utils.FileCreatedBefore, - utils.FileCreatedBeforeFN, "", - "Select backup details for files created before this datetime.") - - fs.StringVar( - &utils.FileModifiedAfter, - utils.FileModifiedAfterFN, "", - "Select backup details for files modified after this datetime.") - fs.StringVar( - &utils.FileModifiedBefore, - utils.FileModifiedBeforeFN, "", - "Select backup details for files modified before this datetime.") + utils.AddBackupIDFlag(c, true) + utils.AddOneDriveDetailsAndRestoreFlags(c) case deleteCommand: - c, fs = utils.AddCommand(cmd, oneDriveDeleteCmd()) + c, _ = utils.AddCommand(cmd, oneDriveDeleteCmd()) c.Use = c.Use + " " + oneDriveServiceCommandDeleteUseSuffix c.Example = oneDriveServiceCommandDeleteExamples - fs.StringVar(&backupID, - utils.BackupFN, "", - "ID of the backup to delete. (required)") - cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN)) + utils.AddBackupIDFlag(c, true) } return c @@ -170,7 +128,7 @@ func createOneDriveCmd(cmd *cobra.Command, args []string) error { return nil } - if err := validateOneDriveBackupCreateFlags(user); err != nil { + if err := validateOneDriveBackupCreateFlags(utils.User); err != nil { return err } @@ -181,7 +139,7 @@ func createOneDriveCmd(cmd *cobra.Command, args []string) error { defer utils.CloseRepo(ctx, r) - sel := oneDriveBackupCreateSelectors(user) + sel := oneDriveBackupCreateSelectors(utils.User) // TODO: log/print recoverable errors errs := fault.New(false) @@ -236,7 +194,7 @@ func oneDriveListCmd() *cobra.Command { // lists the history of backup operations func listOneDriveCmd(cmd *cobra.Command, args []string) error { - return genericListCommand(cmd, backupID, path.OneDriveService, args) + return genericListCommand(cmd, utils.BackupID, path.OneDriveService, args) } // ------------------------------------------------------------------------------------------------ @@ -262,7 +220,7 @@ func detailsOneDriveCmd(cmd *cobra.Command, args []string) error { ctx := cmd.Context() opts := utils.OneDriveOpts{ - Users: user, + Users: utils.User, FileNames: utils.FileNames, FolderPaths: utils.FolderPaths, FileCreatedAfter: utils.FileCreatedAfter, @@ -282,7 +240,7 @@ func detailsOneDriveCmd(cmd *cobra.Command, args []string) error { ctrlOpts := options.Control() - ds, err := runDetailsOneDriveCmd(ctx, r, backupID, opts, ctrlOpts.SkipReduce) + ds, err := runDetailsOneDriveCmd(ctx, r, utils.BackupID, opts, ctrlOpts.SkipReduce) if err != nil { return Only(ctx, err) } @@ -345,5 +303,5 @@ func oneDriveDeleteCmd() *cobra.Command { // deletes a oneDrive service backup. func deleteOneDriveCmd(cmd *cobra.Command, args []string) error { - return genericDeleteCommand(cmd, backupID, "OneDrive", args) + return genericDeleteCommand(cmd, utils.BackupID, "OneDrive", args) } diff --git a/src/cli/backup/sharepoint.go b/src/cli/backup/sharepoint.go index e2d468227..4f8c33bca 100644 --- a/src/cli/backup/sharepoint.go +++ b/src/cli/backup/sharepoint.go @@ -26,12 +26,7 @@ import ( // ------------------------------------------------------------------------------------------------ // sharePoint bucket info from flags -var ( - pageFolders []string - page []string - - sharepointData []string -) +var sharepointData []string const ( dataLibraries = "libraries" @@ -105,91 +100,30 @@ func addSharePointCommands(cmd *cobra.Command) *cobra.Command { case listCommand: c, fs = utils.AddCommand(cmd, sharePointListCmd()) + fs.SortFlags = false - fs.StringVar( - &backupID, - utils.BackupFN, "", - "Display a specific backup, including the items that failed or were skipped during processing.") - + utils.AddBackupIDFlag(c, false) addFailedItemsFN(c) addSkippedItemsFN(c) addRecoveredErrorsFN(c) case detailsCommand: - c, fs = utils.AddCommand(cmd, sharePointDetailsCmd()) + c, _ = utils.AddCommand(cmd, sharePointDetailsCmd()) c.Use = c.Use + " " + sharePointServiceCommandDetailsUseSuffix c.Example = sharePointServiceCommandDetailsExamples options.AddSkipReduceFlag(c) - - fs.StringVar( - &backupID, - utils.BackupFN, "", - "ID of the backup to retrieve.") - cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN)) - - // sharepoint hierarchy flags - - fs.StringVar( - &utils.Library, - utils.LibraryFN, "", - "Select backup details within a library. Defaults includes all libraries.") - - fs.StringSliceVar( - &utils.FolderPaths, - utils.FolderFN, nil, - "Select backup details by folder; defaults to root.") - - fs.StringSliceVar( - &utils.FileNames, - utils.FileFN, nil, - "Select backup details by file name.") - - fs.StringSliceVar( - &pageFolders, - utils.PageFolderFN, nil, - "Select backup data by folder name; accepts '"+utils.Wildcard+"' to select all folders.") - cobra.CheckErr(fs.MarkHidden(utils.PageFolderFN)) - - fs.StringSliceVar( - &page, - utils.PagesFN, nil, - "Select backup data by file name; accepts '"+utils.Wildcard+"' to select all pages within the site.") - cobra.CheckErr(fs.MarkHidden(utils.PagesFN)) - - // sharepoint info flags - - fs.StringVar( - &utils.FileCreatedAfter, - utils.FileCreatedAfterFN, "", - "Select backup details created after this datetime.") - - fs.StringVar( - &utils.FileCreatedBefore, - utils.FileCreatedBeforeFN, "", - "Select backup details created before this datetime.") - - fs.StringVar( - &utils.FileModifiedAfter, - utils.FileModifiedAfterFN, "", - "Select backup details modified after this datetime.") - fs.StringVar( - &utils.FileModifiedBefore, - utils.FileModifiedBeforeFN, "", - "Select backup details modified before this datetime.") + utils.AddBackupIDFlag(c, true) + utils.AddSharePointDetailsAndRestoreFlags(c) case deleteCommand: - c, fs = utils.AddCommand(cmd, sharePointDeleteCmd()) + c, _ = utils.AddCommand(cmd, sharePointDeleteCmd()) c.Use = c.Use + " " + sharePointServiceCommandDeleteUseSuffix c.Example = sharePointServiceCommandDeleteExamples - fs.StringVar( - &backupID, - utils.BackupFN, "", - "ID of the backup to delete. (required)") - cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN)) + utils.AddBackupIDFlag(c, true) } return c @@ -354,7 +288,7 @@ func sharePointListCmd() *cobra.Command { // lists the history of backup operations func listSharePointCmd(cmd *cobra.Command, args []string) error { - return genericListCommand(cmd, backupID, path.SharePointService, args) + return genericListCommand(cmd, utils.BackupID, path.SharePointService, args) } // ------------------------------------------------------------------------------------------------ @@ -374,7 +308,7 @@ func sharePointDeleteCmd() *cobra.Command { // deletes a sharePoint service backup. func deleteSharePointCmd(cmd *cobra.Command, args []string) error { - return genericDeleteCommand(cmd, backupID, "SharePoint", args) + return genericDeleteCommand(cmd, utils.BackupID, "SharePoint", args) } // ------------------------------------------------------------------------------------------------ @@ -422,7 +356,7 @@ func detailsSharePointCmd(cmd *cobra.Command, args []string) error { ctrlOpts := options.Control() - ds, err := runDetailsSharePointCmd(ctx, r, backupID, opts, ctrlOpts.SkipReduce) + ds, err := runDetailsSharePointCmd(ctx, r, utils.BackupID, opts, ctrlOpts.SkipReduce) if err != nil { return Only(ctx, err) } diff --git a/src/cli/restore/exchange.go b/src/cli/restore/exchange.go index da295533f..af5e8077f 100644 --- a/src/cli/restore/exchange.go +++ b/src/cli/restore/exchange.go @@ -56,82 +56,10 @@ func addExchangeCommands(cmd *cobra.Command) *cobra.Command { // Flags addition ordering should follow the order we want them to appear in help and docs: // More generic (ex: --user) and more frequently used flags take precedence. // general flags - fs.StringVar(&backupID, - utils.BackupFN, "", - "ID of the backup to restore. (required)") - cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN)) + fs.SortFlags = false - fs.StringSliceVar(&user, - utils.UserFN, nil, - "Restore data by user's email address; accepts '"+utils.Wildcard+"' to select all users.") - - // email flags - fs.StringSliceVar(&email, - utils.EmailFN, nil, - "Restore emails by ID; accepts '"+utils.Wildcard+"' to select all emails.") - fs.StringSliceVar( - &emailFolder, - utils.EmailFolderFN, nil, - "Restore emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.") - fs.StringVar( - &emailSubject, - utils.EmailSubjectFN, "", - "Restore emails with a subject containing this value.") - fs.StringVar( - &emailSender, - utils.EmailSenderFN, "", - "Restore emails from a specific sender.") - fs.StringVar( - &emailReceivedAfter, - utils.EmailReceivedAfterFN, "", - "Restore emails received after this datetime.") - fs.StringVar( - &emailReceivedBefore, - utils.EmailReceivedBeforeFN, "", - "Restore emails received before this datetime.") - - // event flags - fs.StringSliceVar(&event, - utils.EventFN, nil, - "Restore events by event ID; accepts '"+utils.Wildcard+"' to select all events.") - fs.StringSliceVar( - &eventCalendar, - utils.EventCalendarFN, nil, - "Restore events under a calendar; accepts '"+utils.Wildcard+"' to select all event calendars.") - fs.StringVar( - &eventSubject, - utils.EventSubjectFN, "", - "Restore events with a subject containing this value.") - fs.StringVar( - &eventOrganizer, - utils.EventOrganizerFN, "", - "Restore events from a specific organizer.") - fs.StringVar( - &eventRecurs, - utils.EventRecursFN, "", - "Restore recurring events. Use `--event-recurs false` to restore non-recurring events.") - fs.StringVar( - &eventStartsAfter, - utils.EventStartsAfterFN, "", - "Restore events starting after this datetime.") - fs.StringVar( - &eventStartsBefore, - utils.EventStartsBeforeFN, "", - "Restore events starting before this datetime.") - - // contacts flags - fs.StringSliceVar( - &contact, - utils.ContactFN, nil, - "Restore contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.") - fs.StringSliceVar( - &contactFolder, - utils.ContactFolderFN, nil, - "Restore contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.") - fs.StringVar( - &contactName, - utils.ContactNameFN, "", - "Restore contacts whose contact name contains this value.") + utils.AddBackupIDFlag(c, true) + utils.AddExchangeDetailsAndRestoreFlags(c) // others options.AddOperationFlags(c) @@ -149,11 +77,11 @@ corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --email 98765ab # Restore Alice's emails with subject containing "Hello world" in "Inbox" from a specific backup corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ - --user alice@example.com --email-subject "Hello world" --email-folder Inbox + --user alice@example.com --email-subject "Hello world" --email-folder Inbox # Restore Bobs's entire calendar from a specific backup corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ - --user bob@example.com --event-calendar Calendar + --user bob@example.com --event-calendar Calendar # Restore contact with ID abdef0101 from a specific backup corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --contact abdef0101` diff --git a/src/cli/restore/onedrive.go b/src/cli/restore/onedrive.go index 9beeaf3a9..0d4a308eb 100644 --- a/src/cli/restore/onedrive.go +++ b/src/cli/restore/onedrive.go @@ -42,49 +42,8 @@ func addOneDriveCommands(cmd *cobra.Command) *cobra.Command { // More generic (ex: --user) and more frequently used flags take precedence. fs.SortFlags = false - fs.StringVar(&backupID, - utils.BackupFN, "", - "ID of the backup to restore. (required)") - cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN)) - - fs.StringSliceVar(&user, - utils.UserFN, nil, - "Restore data by user's email address; accepts '"+utils.Wildcard+"' to select all users.") - - // onedrive hierarchy (path/name) flags - - fs.StringSliceVar( - &folderPaths, - utils.FolderFN, nil, - "Restore items by OneDrive folder; defaults to root") - - fs.StringSliceVar( - &fileNames, - utils.FileFN, nil, - "Restore items by file name or ID") - - // permissions restore flag - options.AddRestorePermissionsFlag(c) - - // onedrive info flags - - fs.StringVar( - &fileCreatedAfter, - utils.FileCreatedAfterFN, "", - "Restore files created after this datetime") - fs.StringVar( - &fileCreatedBefore, - utils.FileCreatedBeforeFN, "", - "Restore files created before this datetime") - - fs.StringVar( - &fileModifiedAfter, - utils.FileModifiedAfterFN, "", - "Restore files modified after this datetime") - fs.StringVar( - &fileModifiedBefore, - utils.FileModifiedBeforeFN, "", - "Restore files modified before this datetime") + utils.AddBackupIDFlag(c, true) + utils.AddOneDriveDetailsAndRestoreFlags(c) // others options.AddOperationFlags(c) @@ -105,11 +64,11 @@ corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd --file 98765abc # Restore Alice's file named "FY2021 Planning.xlsx in "Documents/Finance Reports" from a specific backup corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \ - --user alice@example.com --file "FY2021 Planning.xlsx" --folder "Documents/Finance Reports" + --user alice@example.com --file "FY2021 Planning.xlsx" --folder "Documents/Finance Reports" # Restore all files from Bob's folder that were created before 2020 when captured in a specific backup corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd - --user bob@example.com --folder "Documents/Finance Reports" --file-created-before 2020-01-01T00:00:00` + --user bob@example.com --folder "Documents/Finance Reports" --file-created-before 2020-01-01T00:00:00` ) // `corso restore onedrive [...]` diff --git a/src/cli/restore/sharepoint.go b/src/cli/restore/sharepoint.go index 6b9267f9f..1057aab0d 100644 --- a/src/cli/restore/sharepoint.go +++ b/src/cli/restore/sharepoint.go @@ -39,73 +39,8 @@ func addSharePointCommands(cmd *cobra.Command) *cobra.Command { // More generic (ex: --site) and more frequently used flags take precedence. fs.SortFlags = false - fs.StringVar( - &backupID, - utils.BackupFN, "", - "ID of the backup to restore. (required)") - cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN)) - - // sharepoint hierarchy (path/name) flags - - fs.StringVar( - &utils.Library, - utils.LibraryFN, "", - "Restore files within a library. Default includes all libraries.") - - fs.StringSliceVar( - &utils.FolderPaths, - utils.FolderFN, nil, - "Restore files by folder; defaults to root.") - - fs.StringSliceVar( - &utils.FileNames, - utils.FileFN, nil, - "Restore files by name.") - - fs.StringSliceVar( - &listPaths, - utils.ListFN, nil, - "Restore list items by SharePoint list ID") - cobra.CheckErr(fs.MarkHidden(utils.ListFN)) - - fs.StringSliceVar( - &listItems, - utils.ListItemFN, nil, - "Restore list items by ID") - cobra.CheckErr(fs.MarkHidden(utils.ListItemFN)) - - fs.StringSliceVar( - &pageFolders, - utils.PageFolderFN, nil, - "Restore Site pages by page folder name") - cobra.CheckErr(fs.MarkHidden(utils.PageFolderFN)) - - fs.StringSliceVar( - &pages, - utils.PagesFN, nil, - "Restore site pages by file name(s)") - cobra.CheckErr(fs.MarkHidden(utils.PagesFN)) - - // sharepoint info flags - - fs.StringVar( - &utils.FileCreatedAfter, - utils.FileCreatedAfterFN, "", - "Restore files created after this datetime.") - - fs.StringVar( - &utils.FileCreatedBefore, - utils.FileCreatedBeforeFN, "", - "Restore files created before this datetime.") - - fs.StringVar( - &utils.FileModifiedAfter, - utils.FileModifiedAfterFN, "", - "Restore files modified after this datetime.") - fs.StringVar( - &utils.FileModifiedBefore, - utils.FileModifiedBeforeFN, "", - "Restore files modified before this datetime.") + utils.AddBackupIDFlag(c, true) + utils.AddSharePointDetailsAndRestoreFlags(c) // others options.AddOperationFlags(c) diff --git a/src/cli/utils/exchange.go b/src/cli/utils/exchange.go index bbc360dfb..62a7d58c8 100644 --- a/src/cli/utils/exchange.go +++ b/src/cli/utils/exchange.go @@ -4,26 +4,51 @@ import ( "errors" "github.com/alcionai/corso/src/pkg/selectors" + "github.com/spf13/cobra" ) // flag names const ( - ContactFN = "contact" - ContactFolderFN = "contact-folder" + ContactFN = "contact" + ContactFolderFN = "contact-folder" + ContactNameFN = "contact-name" + EmailFN = "email" EmailFolderFN = "email-folder" - EventFN = "event" - EventCalendarFN = "event-calendar" - ContactNameFN = "contact-name" EmailReceivedAfterFN = "email-received-after" EmailReceivedBeforeFN = "email-received-before" EmailSenderFN = "email-sender" EmailSubjectFN = "email-subject" - EventOrganizerFN = "event-organizer" - EventRecursFN = "event-recurs" - EventStartsAfterFN = "event-starts-after" - EventStartsBeforeFN = "event-starts-before" - EventSubjectFN = "event-subject" + + EventFN = "event" + EventCalendarFN = "event-calendar" + EventOrganizerFN = "event-organizer" + EventRecursFN = "event-recurs" + EventStartsAfterFN = "event-starts-after" + EventStartsBeforeFN = "event-starts-before" + EventSubjectFN = "event-subject" +) + +// flag population values +var ( + 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 ) type ExchangeOpts struct { @@ -48,6 +73,82 @@ type ExchangeOpts struct { Populated PopulatedFlags } +// AddExchangeDetailsAndRestoreFlags adds flags that are common to both the +// details and restore commands. +func AddExchangeDetailsAndRestoreFlags(cmd *cobra.Command) { + fs := cmd.Flags() + + // email flags + fs.StringSliceVar( + &Email, + EmailFN, nil, + "Select emails by email ID; accepts '"+Wildcard+"' to select all emails.") + fs.StringSliceVar( + &EmailFolder, + EmailFolderFN, nil, + "Select emails within a folder; accepts '"+Wildcard+"' to select all email folders.") + fs.StringVar( + &EmailSubject, + EmailSubjectFN, "", + "Select emails with a subject containing this value.") + fs.StringVar( + &EmailSender, + EmailSenderFN, "", + "Select emails from a specific sender.") + fs.StringVar( + &EmailReceivedAfter, + EmailReceivedAfterFN, "", + "Select emails received after this datetime.") + fs.StringVar( + &EmailReceivedBefore, + EmailReceivedBeforeFN, "", + "Select emails received before this datetime.") + + // event flags + fs.StringSliceVar( + &Event, + EventFN, nil, + "Select events by event ID; accepts '"+Wildcard+"' to select all events.") + fs.StringSliceVar( + &EventCalendar, + EventCalendarFN, nil, + "Select events under a calendar; accepts '"+Wildcard+"' to select all events.") + fs.StringVar( + &EventSubject, + EventSubjectFN, "", + "Select events with a subject containing this value.") + fs.StringVar( + &EventOrganizer, + EventOrganizerFN, "", + "Select events from a specific organizer.") + fs.StringVar( + &EventRecurs, + EventRecursFN, "", + "Select recurring events. Use `--event-recurs false` to select non-recurring events.") + fs.StringVar( + &EventStartsAfter, + EventStartsAfterFN, "", + "Select events starting after this datetime.") + fs.StringVar( + &EventStartsBefore, + EventStartsBeforeFN, "", + "Select events starting before this datetime.") + + // contact flags + fs.StringSliceVar( + &Contact, + ContactFN, nil, + "Select contacts by contact ID; accepts '"+Wildcard+"' to select all contacts.") + fs.StringSliceVar( + &ContactFolder, + ContactFolderFN, nil, + "Select contacts within a folder; accepts '"+Wildcard+"' to select all contact folders.") + fs.StringVar( + &ContactName, + ContactNameFN, "", + "Select contacts whose contact name contains this value.") +} + // 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. diff --git a/src/cli/utils/flags.go b/src/cli/utils/flags.go index 1dbd00968..920ffb333 100644 --- a/src/cli/utils/flags.go +++ b/src/cli/utils/flags.go @@ -12,6 +12,8 @@ import ( // common flag vars var ( + BackupID string + FolderPaths []string FileNames []string @@ -23,6 +25,8 @@ var ( Library string Site []string WebURL []string + + User []string ) // common flag names @@ -43,6 +47,24 @@ const ( FileModifiedBeforeFN = "file-modified-before" ) +// AddBackupIDFlag adds the --backup flag. +func AddBackupIDFlag(cmd *cobra.Command, require bool) { + cmd.Flags().StringVar(&BackupID, BackupFN, "", "ID of the backup to retrieve.") + + if require { + cobra.CheckErr(cmd.MarkFlagRequired(BackupFN)) + } +} + +// AddUserFlag adds the --user flag. +func AddUserFlag(cmd *cobra.Command) { + cmd.Flags().StringSliceVar( + &User, + UserFN, nil, + "Backup a specific user's data; accepts '"+Wildcard+"' to select all users.") + cobra.CheckErr(cmd.MarkFlagRequired(UserFN)) +} + type PopulatedFlags map[string]struct{} func (fs PopulatedFlags) populate(pf *pflag.Flag) { diff --git a/src/cli/utils/onedrive.go b/src/cli/utils/onedrive.go index 04a317ff4..c8b562118 100644 --- a/src/cli/utils/onedrive.go +++ b/src/cli/utils/onedrive.go @@ -4,6 +4,7 @@ import ( "errors" "github.com/alcionai/corso/src/pkg/selectors" + "github.com/spf13/cobra" ) type OneDriveOpts struct { @@ -18,6 +19,41 @@ type OneDriveOpts struct { Populated PopulatedFlags } +// AddOneDriveDetailsAndRestoreFlags adds flags that are common to both the +// details and restore commands. +func AddOneDriveDetailsAndRestoreFlags(cmd *cobra.Command) { + fs := cmd.Flags() + + fs.StringSliceVar( + &FolderPaths, + FolderFN, nil, + "Select files by OneDrive folder; defaults to root.") + + fs.StringSliceVar( + &FileNames, + FileFN, nil, + "Select files by name.") + + fs.StringVar( + &FileCreatedAfter, + FileCreatedAfterFN, "", + "Select files created after this datetime.") + fs.StringVar( + &FileCreatedBefore, + FileCreatedBeforeFN, "", + "Select files created before this datetime.") + + fs.StringVar( + &FileModifiedAfter, + FileModifiedAfterFN, "", + "Select files modified after this datetime.") + + fs.StringVar( + &FileModifiedBefore, + FileModifiedBeforeFN, "", + "Select files modified before this datetime.") +} + // ValidateOneDriveRestoreFlags checks common flags for correctness and interdependencies func ValidateOneDriveRestoreFlags(backupID string, opts OneDriveOpts) error { if len(backupID) == 0 { diff --git a/src/cli/utils/sharepoint.go b/src/cli/utils/sharepoint.go index 35731efdf..e92fb1063 100644 --- a/src/cli/utils/sharepoint.go +++ b/src/cli/utils/sharepoint.go @@ -2,9 +2,9 @@ package utils import ( "errors" - "fmt" "github.com/alcionai/corso/src/pkg/selectors" + "github.com/spf13/cobra" ) const ( @@ -14,6 +14,12 @@ const ( PagesFN = "pages" ) +// flag population variables +var ( + PageFolders []string + Pages []string +) + type SharePointOpts struct { Library string FileNames []string // for libraries, to duplicate onedrive interface @@ -36,6 +42,58 @@ type SharePointOpts struct { Populated PopulatedFlags } +// AddSharePointDetailsAndRestoreFlags adds flags that are common to both the +// details and restore commands. +func AddSharePointDetailsAndRestoreFlags(cmd *cobra.Command) { + fs := cmd.Flags() + + fs.StringVar( + &Library, + LibraryFN, "", + "Select only this library. Default includes all libraries.") + + fs.StringSliceVar( + &FolderPaths, + FolderFN, nil, + "Select by folder; defaults to root.") + + fs.StringSliceVar( + &FileNames, + FileFN, nil, + "Select by file name.") + + fs.StringSliceVar( + &PageFolders, + PageFolderFN, nil, + "Select pages by folder name; accepts '"+Wildcard+"' to select all folders.") + cobra.CheckErr(fs.MarkHidden(PageFolderFN)) + + fs.StringSliceVar( + &Pages, + PagesFN, nil, + "Select pages by item name; accepts '"+Wildcard+"' to select all pages within the site.") + cobra.CheckErr(fs.MarkHidden(PagesFN)) + + fs.StringVar( + &FileCreatedAfter, + FileCreatedAfterFN, "", + "Select files created after this datetime.") + + fs.StringVar( + &FileCreatedBefore, + FileCreatedBeforeFN, "", + "Select files created before this datetime.") + + fs.StringVar( + &FileModifiedAfter, + FileModifiedAfterFN, "", + "Select files modified after this datetime.") + fs.StringVar( + &FileModifiedBefore, + FileModifiedBeforeFN, "", + "Select files modified before this datetime.") +} + // ValidateSharePointRestoreFlags checks common flags for correctness and interdependencies func ValidateSharePointRestoreFlags(backupID string, opts SharePointOpts) error { if len(backupID) == 0 { @@ -43,7 +101,6 @@ func ValidateSharePointRestoreFlags(backupID string, opts SharePointOpts) error } if _, ok := opts.Populated[FileCreatedAfterFN]; ok && !IsValidTimeFormat(opts.FileCreatedAfter) { - fmt.Printf("What was I sent: %v\n", opts.FileCreatedAfter) return errors.New("invalid time format for " + FileCreatedAfterFN) }