From 780e1221ec028c35964fc6508c5ea75665f38b20 Mon Sep 17 00:00:00 2001 From: amgrobelny-box Date: Tue, 31 Oct 2017 22:12:11 -0500 Subject: [PATCH] Added shared link commands, fixed UTF-8 issue with saving CSV reports, added autopaging for events and fixed faulty event get command. Added date options w for weeks and now. Bumped to v1.0.2 --- BoxCLI/BoxCLIInfo.cs | 2 +- .../Utilities/BoxCollectionsIterators.cs | 88 +++++++---- .../Utilities/IBoxCollectionsIterators.cs | 2 + BoxCLI/CommandUtilities/GeneralUtilities.cs | 15 +- BoxCLI/Commands/BoxBaseCommand.cs | 18 +-- .../EventSubCommands/EventGetCommand.cs | 32 +++- BoxCLI/Commands/SharedLinkCommand.cs | 15 +- .../FilesSharedLinkSubCommandFactory.cs | 14 +- .../FoldersSharedLinkSubCommandFactory.cs | 4 + .../SharedLinkCreateCommand.cs | 86 +++++------ .../SharedLinkDeleteCommand.cs | 143 ++++++++++++++++++ .../SharedLinkSubCommandBase.cs | 4 + .../SharedLinkSubCommandFactory.cs | 18 ++- .../SharedLinkUpdateCommand.cs | 24 ++- BoxCLIInstaller/Product.wxs | 2 +- CHANGELOG.md | 6 + README.md | 2 +- 17 files changed, 351 insertions(+), 124 deletions(-) create mode 100644 BoxCLI/Commands/SharedLinkSubCommands/SharedLinkDeleteCommand.cs diff --git a/BoxCLI/BoxCLIInfo.cs b/BoxCLI/BoxCLIInfo.cs index 7c3c697d..5f9cb680 100644 --- a/BoxCLI/BoxCLIInfo.cs +++ b/BoxCLI/BoxCLIInfo.cs @@ -4,6 +4,6 @@ public class BoxCLIInfo { public const string ProductTitle = "Box CLI"; - public const string Version = "1.0.1"; + public const string Version = "1.0.2"; } } \ No newline at end of file diff --git a/BoxCLI/BoxPlatform/Utilities/BoxCollectionsIterators.cs b/BoxCLI/BoxPlatform/Utilities/BoxCollectionsIterators.cs index e32275dd..72882ca8 100644 --- a/BoxCLI/BoxPlatform/Utilities/BoxCollectionsIterators.cs +++ b/BoxCLI/BoxPlatform/Utilities/BoxCollectionsIterators.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Box.V2; using Box.V2.Models; @@ -23,13 +24,13 @@ public class BoxCollectionsIterators : IBoxCollectionsIterators Reporter.WriteInformation("Show next? Enter q to quit. "); return System.Console.ReadLine().Trim().ToLower(); } - public string PageInConsole(Action print, BoxEventCollection collection) - { - print(collection.Entries[0]); - collection.Entries.RemoveAt(0); - Reporter.WriteInformation("Show next? Enter q to quit. "); - return System.Console.ReadLine().Trim().ToLower(); - } + public string PageInConsole(Action print, BoxEventCollection collection) + { + print(collection.Entries[0]); + collection.Entries.RemoveAt(0); + Reporter.WriteInformation("Show next? Enter q to quit. "); + return System.Console.ReadLine().Trim().ToLower(); + } public async Task ListOffsetCollectionToConsole(Func>> callBox, Action print, int limit = -1) where T : BoxEntity, new() { @@ -42,7 +43,7 @@ public string PageInConsole(Action print, BoxEventCollection { if (collection.Entries.Count > 0) { - if(limit == 0) + if (limit == 0) { break; } @@ -83,29 +84,52 @@ public string PageInConsole(Action print, BoxEventCollection } while (keepGoing && showNext != "q"); } - public async Task ListEventCollectionToConsole(Func>> callBox, Action print) - { - var keepGoing = false; - var showNext = ""; - do - { - string streamPosition = ""; - var collection = await callBox(streamPosition); - if (collection.Entries.Count > 0) - { - while (collection.Entries.Count > 0 && showNext != "q") - { - showNext = PageInConsole(print, collection); - } - } - else - { - streamPosition = collection.NextStreamPosition; - collection = await callBox(streamPosition); - } - keepGoing = !string.IsNullOrEmpty(collection.NextStreamPosition); - } - while (keepGoing && showNext != "q"); - } + public async Task ListEventCollectionToConsole(Func>> callBox, Action print) + { + var keepGoing = false; + var showNext = ""; + do + { + string streamPosition = ""; + var collection = await callBox(streamPosition); + if (collection.Entries.Count > 0) + { + while (collection.Entries.Count > 0 && showNext != "q") + { + showNext = PageInConsole(print, collection); + } + } + else + { + streamPosition = collection.NextStreamPosition; + collection = await callBox(streamPosition); + } + keepGoing = !string.IsNullOrEmpty(collection.NextStreamPosition); + } + while (keepGoing && showNext != "q"); + } + + public async Task> ReturnAllEvents(Func>> callBox) + { + var keepGoing = true; + var fullCollection = new BoxEventCollection(); + fullCollection.Entries = new List(); + string streamPosition = ""; + do + { + var collection = await callBox(streamPosition); + if (collection.Entries.Count > 0) + { + fullCollection.Entries.AddRange(collection.Entries); + } + if (collection != null && !string.IsNullOrEmpty(collection.NextStreamPosition)) + { + streamPosition = collection.NextStreamPosition; + } + keepGoing = collection.Entries.Count != 0; + } + while (keepGoing); + return fullCollection; + } } } \ No newline at end of file diff --git a/BoxCLI/BoxPlatform/Utilities/IBoxCollectionsIterators.cs b/BoxCLI/BoxPlatform/Utilities/IBoxCollectionsIterators.cs index fb4dec20..1db77687 100644 --- a/BoxCLI/BoxPlatform/Utilities/IBoxCollectionsIterators.cs +++ b/BoxCLI/BoxPlatform/Utilities/IBoxCollectionsIterators.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Box.V2; using Box.V2.Models; namespace BoxCLI.BoxPlatform.Utilities @@ -9,6 +10,7 @@ public interface IBoxCollectionsIterators Task ListOffsetCollectionToConsole(Func>> callBox, Action print, int limit = -1) where T : BoxEntity, new(); Task ListMarkerCollectionToConsole(Func>> callBox, Action print) where T : BoxEntity, new(); Task ListEventCollectionToConsole(Func>> callBox, Action print); + Task> ReturnAllEvents(Func>> callBox); string PageInConsole(Action print, BoxCollection collection) where T : class, new(); } } \ No newline at end of file diff --git a/BoxCLI/CommandUtilities/GeneralUtilities.cs b/BoxCLI/CommandUtilities/GeneralUtilities.cs index 79d082e3..a268d89a 100644 --- a/BoxCLI/CommandUtilities/GeneralUtilities.cs +++ b/BoxCLI/CommandUtilities/GeneralUtilities.cs @@ -23,8 +23,12 @@ public static DateTime ResolveTimeUnit(double span, char unit) return DateTime.Now.AddHours(span); case 'd': return DateTime.Now.AddDays(span); + case 'w': + return DateTime.Now.AddDays(span * 7); case 'M': return DateTime.Now.AddMonths(Convert.ToInt32(span)); + case 'n': + return DateTime.Now; default: throw new Exception("Time format unrecognized."); } @@ -32,8 +36,9 @@ public static DateTime ResolveTimeUnit(double span, char unit) public static DateTime GetDateTimeFromString(string t, bool allowNegativeTime = false) { t = t.Trim(); - var pattern = @"^[0-6][0-9]{1}[s,m,h,d,M]$"; - var negativePattern = @"^-[0-6][0-9]{1}[s,m,h,d,M]$"; + var now = "now"; + var pattern = @"^[0-6][0-9]{1}[s,m,h,d,w,M]$"; + var negativePattern = @"^-[0-6][0-9]{1}[s,m,h,d,w,M]$"; var regex = new Regex(pattern); var negativeRegex = new Regex(negativePattern); if (regex.Match(t).Success) @@ -50,6 +55,10 @@ public static DateTime GetDateTimeFromString(string t, bool allowNegativeTime = double.TryParse(t.Substring(0, 3), out span); return ResolveTimeUnit(span, unit); } + else if (now == t) + { + return ResolveTimeUnit(0, 'n'); + } else { throw new Exception("Time format unrecognized."); @@ -86,7 +95,7 @@ private static string ResolveContainerPath(string containerPath) public static string ResolveItemName(string path) { - if(path.Last() == Path.DirectorySeparatorChar) + if (path.Last() == Path.DirectorySeparatorChar) { path = path.Substring(0, path.Length - 1); } diff --git a/BoxCLI/Commands/BoxBaseCommand.cs b/BoxCLI/Commands/BoxBaseCommand.cs index 87ecfa98..419cff47 100644 --- a/BoxCLI/Commands/BoxBaseCommand.cs +++ b/BoxCLI/Commands/BoxBaseCommand.cs @@ -67,7 +67,7 @@ protected virtual void PrintCollaboration(BoxCollaboration c, bool json = false) this.OutputJson(c); return; } - else + else { this.PrintCollaboration(c); } @@ -217,7 +217,7 @@ protected virtual bool WriteResultsToReport(T entity, string fileName, string { try { - using (StreamWriter fs = File.CreateText(filePath)) + using (StreamWriter fs = new StreamWriter(File.Open(filePath, FileMode.OpenOrCreate), System.Text.Encoding.UTF8)) using (var csv = new CsvWriter(fs)) { csv.WriteRecord(entity); @@ -258,7 +258,7 @@ protected virtual bool WriteMetadataCollectionResultsToReport(List en { try { - using (StreamWriter fs = File.CreateText(filePath)) + using (StreamWriter fs = new StreamWriter(File.Open(filePath, FileMode.OpenOrCreate), System.Text.Encoding.UTF8)) using (var csv = new CsvWriter(fs)) { csv.Configuration.RegisterClassMap(typeof(BoxEventMap)); @@ -423,7 +423,7 @@ protected virtual bool WriteListResultsToReport(List entity, string fil { try { - using (StreamWriter fs = File.CreateText(filePath)) + using (StreamWriter fs = new StreamWriter(File.Open(filePath, FileMode.OpenOrCreate), System.Text.Encoding.UTF8)) using (var csv = new CsvWriter(fs)) { csv.Configuration.RegisterClassMap(typeof(M)); @@ -465,7 +465,7 @@ protected virtual bool WriteOffsetCollectionResultsToReport(BoxCollection< { try { - using (StreamWriter fs = File.CreateText(filePath)) + using (StreamWriter fs = new StreamWriter(File.Open(filePath, FileMode.OpenOrCreate), System.Text.Encoding.UTF8)) using (var csv = new CsvWriter(fs)) { csv.Configuration.RegisterClassMap(typeof(M)); @@ -507,7 +507,7 @@ protected virtual bool WriteMarkerCollectionResultsToReport(BoxCollectionM { try { - using (StreamWriter fs = File.CreateText(filePath)) + using (StreamWriter fs = new StreamWriter(File.Open(filePath, FileMode.OpenOrCreate), System.Text.Encoding.UTF8)) using (var csv = new CsvWriter(fs)) { csv.Configuration.RegisterClassMap(typeof(M)); diff --git a/BoxCLI/Commands/EventSubCommands/EventGetCommand.cs b/BoxCLI/Commands/EventSubCommands/EventGetCommand.cs index 7e6d871e..9665f26d 100644 --- a/BoxCLI/Commands/EventSubCommands/EventGetCommand.cs +++ b/BoxCLI/Commands/EventSubCommands/EventGetCommand.cs @@ -33,8 +33,8 @@ public override void Configure(CommandLineApplication command) _app = command; command.Description = "Get events."; _enterprise = command.Option("-e|--enterprise", "Get enterprise events", CommandOptionType.NoValue); - _createdBefore = command.Option("--created-before", "Return enterprise events that occured before a time. Use a timestamp or shorthand syntax 00t, like 05w for 5 weeks", CommandOptionType.SingleValue); - _createdAfter = command.Option("--created-after", "Return enterprise events that occured before a time. Use a timestamp or shorthand syntax 00t, like 05w for 5 weeks", CommandOptionType.SingleValue); + _createdBefore = command.Option("--created-before", "Return enterprise events that occured before a time. Use a timestamp or shorthand syntax 00t, like 05w for 5 weeks. If not used, defaults to now.", CommandOptionType.SingleValue); + _createdAfter = command.Option("--created-after", "Return enterprise events that occured before a time. Use a timestamp or shorthand syntax 00t, like 05w for 5 weeks. If not used, defaults to 5 days ago.", CommandOptionType.SingleValue); _save = SaveOption.ConfigureOption(command); _path = FilePathOption.ConfigureOption(command); _fileFormat = FileFormatOption.ConfigureOption(command); @@ -85,15 +85,21 @@ private async Task RunGet() } if (this._save.HasValue()) { - var fileName = $"{base._names.CommandNames.Events}-{base._names.SubCommandNames.Get}-{DateTime.Now.ToString(GeneralUtilities.GetDateFormatString())}"; + var fileName = $"{base._names.CommandNames.Events}-enterprise-{base._names.SubCommandNames.Get}-{DateTime.Now.ToString(GeneralUtilities.GetDateFormatString())}"; Reporter.WriteInformation("Saving file..."); - var events = await boxClient.EventsManager.EnterpriseEventsAsync(createdAfter: createdAfter, createdBefore: createdBefore); + var events = await BoxCollectionsIterators.ReturnAllEvents((position) => + { + return boxClient.EventsManager.EnterpriseEventsAsync(limit: 1000, createdAfter: createdAfter, createdBefore: createdBefore, streamPosition: position); + }); base.WriteEventListResultsToReport(events.Entries, fileName, _path.Value(), _fileFormat.Value()); return; } if (base._json.HasValue() || this._home.GetBoxHomeSettings().GetOutputJsonSetting()) { - var events = await boxClient.EventsManager.EnterpriseEventsAsync(createdAfter: createdAfter, createdBefore: createdBefore); + var events = await BoxCollectionsIterators.ReturnAllEvents((position) => + { + return boxClient.EventsManager.EnterpriseEventsAsync(limit: 1000, createdAfter: createdAfter, createdBefore: createdBefore, streamPosition: position); + }); base.OutputJson(events); return; } @@ -106,12 +112,24 @@ await BoxCollectionsIterators.ListEventCollectionToConsole((position) => { if (this._save.HasValue()) { - var fileName = $"{base._names.CommandNames.Events}-{base._names.SubCommandNames.Get}-{DateTime.Now.ToString(GeneralUtilities.GetDateFormatString())}"; + var fileName = $"{base._names.CommandNames.Events}-user-{base._names.SubCommandNames.Get}-{DateTime.Now.ToString(GeneralUtilities.GetDateFormatString())}"; Reporter.WriteInformation("Saving file..."); - var events = await boxClient.EventsManager.UserEventsAsync(); + var events = await BoxCollectionsIterators.ReturnAllEvents((position) => + { + return boxClient.EventsManager.UserEventsAsync(limit: 1000, streamPosition: position); + }); base.WriteEventListResultsToReport(events.Entries, fileName, _path.Value(), _fileFormat.Value()); return; } + if (base._json.HasValue() || this._home.GetBoxHomeSettings().GetOutputJsonSetting()) + { + var events = await BoxCollectionsIterators.ReturnAllEvents((position) => + { + return boxClient.EventsManager.UserEventsAsync(limit: 1000, streamPosition: position); + }); + base.OutputJson(events); + return; + } await BoxCollectionsIterators.ListEventCollectionToConsole((position) => { return boxClient.EventsManager.UserEventsAsync(streamPosition: position); diff --git a/BoxCLI/Commands/SharedLinkCommand.cs b/BoxCLI/Commands/SharedLinkCommand.cs index 44ef3335..41092ee7 100644 --- a/BoxCLI/Commands/SharedLinkCommand.cs +++ b/BoxCLI/Commands/SharedLinkCommand.cs @@ -15,15 +15,10 @@ public override void Configure(CommandLineApplication command) _app = command; command.Description = "Manage your shared links."; command.ExtendedHelpText = "You can use this command to create, update, delete, and get information about shared links in your Enterprise."; - if (this._t == BoxType.enterprise) - { - command.Command(base._names.SubCommandNames.Get, _subCommands.CreateSubCommand(_names.SubCommandNames.Get).Configure); - } - else - { - command.Command(base._names.SubCommandNames.Get, _subCommands.CreateSubCommand(_names.SubCommandNames.Get).Configure); - command.Command(base._names.SubCommandNames.Create, _subCommands.CreateSubCommand(_names.SubCommandNames.Create).Configure); - } + command.Command(base._names.SubCommandNames.Get, _subCommands.CreateSubCommand(_names.SubCommandNames.Get).Configure); + command.Command(base._names.SubCommandNames.Create, _subCommands.CreateSubCommand(_names.SubCommandNames.Create).Configure); + command.Command(base._names.SubCommandNames.Update, _subCommands.CreateSubCommand(_names.SubCommandNames.Update).Configure); + command.Command(base._names.SubCommandNames.Delete, _subCommands.CreateSubCommand(_names.SubCommandNames.Delete).Configure); command.OnExecute(async () => { @@ -40,7 +35,7 @@ protected async override Task Execute() private readonly ISubCommandFactory _subCommands; private readonly BoxType _t; - public SharedLinkCommand(IBoxPlatformServiceBuilder boxPlatformBuilder, IBoxHome boxHome, SubCommandFactory factory, + public SharedLinkCommand(IBoxPlatformServiceBuilder boxPlatformBuilder, IBoxHome boxHome, SubCommandFactory factory, LocalizedStringsResource names, BoxType t = BoxType.enterprise) : base(boxPlatformBuilder, boxHome, names) { diff --git a/BoxCLI/Commands/SharedLinkSubCommands/FilesSharedLinkSubCommandFactory.cs b/BoxCLI/Commands/SharedLinkSubCommands/FilesSharedLinkSubCommandFactory.cs index 8af586ce..c5653240 100644 --- a/BoxCLI/Commands/SharedLinkSubCommands/FilesSharedLinkSubCommandFactory.cs +++ b/BoxCLI/Commands/SharedLinkSubCommands/FilesSharedLinkSubCommandFactory.cs @@ -14,7 +14,7 @@ public FilesSharedLinkSubCommandFactory(IBoxPlatformServiceBuilder builder, IBox public override ISubCommand CreateSubCommand(string commandName) { - if (commandName == base._names.SubCommandNames.Get) + if (commandName == base._names.SubCommandNames.Get) { return new SharedLinkGetCommand(_boxPlatformBuilder, _boxHome, _names, BoxType.file); } @@ -22,10 +22,14 @@ public override ISubCommand CreateSubCommand(string commandName) { return new SharedLinkCreateCommand(_boxPlatformBuilder, _boxHome, _names, BoxType.file); } - else if (commandName == base._names.SubCommandNames.Update) - { - return new SharedLinkUpdateCommand(_boxPlatformBuilder, _boxHome, _names, BoxType.file); - } + else if (commandName == base._names.SubCommandNames.Update) + { + return new SharedLinkUpdateCommand(_boxPlatformBuilder, _boxHome, _names, BoxType.file); + } + else if (commandName == base._names.SubCommandNames.Delete) + { + return new SharedLinkDeleteCommand(_boxPlatformBuilder, _boxHome, _names, BoxType.file); + } else { throw new Exception("Command not registered."); diff --git a/BoxCLI/Commands/SharedLinkSubCommands/FoldersSharedLinkSubCommandFactory.cs b/BoxCLI/Commands/SharedLinkSubCommands/FoldersSharedLinkSubCommandFactory.cs index df8c94de..9af2638e 100644 --- a/BoxCLI/Commands/SharedLinkSubCommands/FoldersSharedLinkSubCommandFactory.cs +++ b/BoxCLI/Commands/SharedLinkSubCommands/FoldersSharedLinkSubCommandFactory.cs @@ -25,6 +25,10 @@ public override ISubCommand CreateSubCommand(string commandName) { return new SharedLinkUpdateCommand(_boxPlatformBuilder, _boxHome, _names, BoxType.folder); } + else if (commandName == base._names.SubCommandNames.Delete) + { + return new SharedLinkDeleteCommand(_boxPlatformBuilder, _boxHome, _names, BoxType.folder); + } else { throw new Exception("Command not registered."); diff --git a/BoxCLI/Commands/SharedLinkSubCommands/SharedLinkCreateCommand.cs b/BoxCLI/Commands/SharedLinkSubCommands/SharedLinkCreateCommand.cs index 2669d12e..9c27539c 100644 --- a/BoxCLI/Commands/SharedLinkSubCommands/SharedLinkCreateCommand.cs +++ b/BoxCLI/Commands/SharedLinkSubCommands/SharedLinkCreateCommand.cs @@ -14,6 +14,7 @@ namespace BoxCLI.Commands.SharedLinkSubCommands public class SharedLinkCreateCommand : SharedLinkSubCommandBase { private CommandArgument _id; + private CommandArgument _type; private CommandOption _path; private CommandOption _access; private CommandOption _password; @@ -39,7 +40,10 @@ public override void Configure(CommandLineApplication command) _password = command.Option("--password ", "Shared link password", CommandOptionType.SingleValue); _unsharedAt = command.Option("--unshared-at