From 2b1b5a6c8e4f8da7b667f997d1149eb79257ebe3 Mon Sep 17 00:00:00 2001 From: tiget Date: Sat, 16 Sep 2017 18:57:12 +1000 Subject: [PATCH] (GH-1301) Enable removal of API key via CLI Previously there was no way to remove an API key via the CLI. Update the Api Key command to allow for the removal of an API key by using the newly added -rem or -remove flags. --- .../commands/ChocolateyApiKeyCommandSpecs.cs | 43 +++++++++++++++++++ .../commands/ChocolateyApiKeyCommand.cs | 23 +++++++--- .../configuration/ChocolateyConfiguration.cs | 1 + .../ChocolateyConfigSettingsService.cs | 18 ++++++++ .../IChocolateyConfigSettingsService.cs | 1 + 5 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/chocolatey.tests/infrastructure.app/commands/ChocolateyApiKeyCommandSpecs.cs b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyApiKeyCommandSpecs.cs index f067ab6eda..4e16f0794d 100644 --- a/src/chocolatey.tests/infrastructure.app/commands/ChocolateyApiKeyCommandSpecs.cs +++ b/src/chocolatey.tests/infrastructure.app/commands/ChocolateyApiKeyCommandSpecs.cs @@ -108,6 +108,18 @@ public void should_add_short_version_of_apikey_to_the_option_set() { optionSet.Contains("k").ShouldBeTrue(); } + + [Fact] + public void should_add_remove_to_the_option_set() + { + optionSet.Contains("remove").ShouldBeTrue(); + } + + [Fact] + public void should_add_short_version_of_remove_to_the_option_set() + { + optionSet.Contains("rem").ShouldBeTrue(); + } } public class when_handling_validation : ChocolateyApiKeyCommandSpecsBase @@ -154,6 +166,37 @@ public void should_continue_when_both_source_and_key_are_set() configuration.Sources = "bob"; command.handle_validation(configuration); } + + [Fact] + public void should_throw_when_key_is_removed_without_a_source() + { + configuration.ApiKeyCommand.Remove = true; + configuration.Sources = ""; + var errorred = false; + Exception error = null; + + try + { + command.handle_validation(configuration); + } + catch (Exception ex) + { + errorred = true; + error = ex; + } + + errorred.ShouldBeTrue(); + error.ShouldNotBeNull(); + error.ShouldBeType(); + } + + [Fact] + public void should_continue_when_removing_and_source_is_set() + { + configuration.ApiKeyCommand.Remove = true; + configuration.Sources = "bob"; + command.handle_validation(configuration); + } } public class when_noop_is_called : ChocolateyApiKeyCommandSpecsBase diff --git a/src/chocolatey/infrastructure.app/commands/ChocolateyApiKeyCommand.cs b/src/chocolatey/infrastructure.app/commands/ChocolateyApiKeyCommand.cs index 92026dcdb7..622a691c8a 100644 --- a/src/chocolatey/infrastructure.app/commands/ChocolateyApiKeyCommand.cs +++ b/src/chocolatey/infrastructure.app/commands/ChocolateyApiKeyCommand.cs @@ -26,8 +26,8 @@ namespace chocolatey.infrastructure.app.commands using logging; using services; - [CommandFor("apikey", "retrieves or saves an apikey for a particular source")] - [CommandFor("setapikey", "retrieves or saves an apikey for a particular source (alias for apikey)")] + [CommandFor("apikey", "retrieves, saves or deletes an apikey for a particular source")] + [CommandFor("setapikey", "retrieves, saves or deletes an apikey for a particular source (alias for apikey)")] public class ChocolateyApiKeyCommand : ICommand { private readonly IChocolateyConfigSettingsService _configSettingsService; @@ -48,6 +48,9 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon .Add("k=|key=|apikey=|api-key=", "ApiKey - The API key for the source. This is the authentication that identifies you and allows you to push to a source. With some sources this is either a key or it could be a user name and password specified as 'user:password'.", option => configuration.ApiKeyCommand.Key = option.remove_surrounding_quotes()) + .Add("rem|remove", + "Removes an API key from Chocolatey", + option => configuration.ApiKeyCommand.Remove = true) ; } @@ -58,9 +61,15 @@ public virtual void handle_additional_argument_parsing(IList unparsedArg public virtual void handle_validation(ChocolateyConfiguration configuration) { - if (!string.IsNullOrWhiteSpace(configuration.ApiKeyCommand.Key) && string.IsNullOrWhiteSpace(configuration.Sources)) + if (!configuration.ApiKeyCommand.Remove && !string.IsNullOrWhiteSpace(configuration.ApiKeyCommand.Key) + && string.IsNullOrWhiteSpace(configuration.Sources)) { - throw new ApplicationException("You must specify both 'source' and 'key' to set an api key."); + throw new ApplicationException("You must specify both 'source' and 'key' to set an API key."); + } + if (configuration.ApiKeyCommand.Remove && string.IsNullOrWhiteSpace(configuration.Sources)) + { + throw new ApplicationException("You must specify 'source' to remove an API key."); + } } @@ -125,7 +134,11 @@ public virtual void noop(ChocolateyConfiguration configuration) public virtual void run(ChocolateyConfiguration configuration) { - if (string.IsNullOrWhiteSpace(configuration.ApiKeyCommand.Key)) + if (configuration.ApiKeyCommand.Remove) + { + _configSettingsService.remove_api_key(configuration); + } + else if (string.IsNullOrWhiteSpace(configuration.ApiKeyCommand.Key)) { _configSettingsService.get_api_key(configuration, (key) => { diff --git a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs index e50216b4d0..9a129413fb 100644 --- a/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs +++ b/src/chocolatey/infrastructure.app/configuration/ChocolateyConfiguration.cs @@ -510,6 +510,7 @@ public sealed class OutdatedCommandConfiguration public sealed class ApiKeyCommandConfiguration { public string Key { get; set; } + public bool Remove { get; set; } } [Serializable] diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs index 0930cd1feb..da81ed6a48 100644 --- a/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs +++ b/src/chocolatey/infrastructure.app/services/ChocolateyConfigSettingsService.cs @@ -330,6 +330,24 @@ public void set_api_key(ChocolateyConfiguration configuration) } } + public void remove_api_key(ChocolateyConfiguration configuration) + { + var apiKey = configFileSettings.ApiKeys.FirstOrDefault(p => p.Source.is_equal_to(configuration.Sources)); + if (apiKey != null) + { + configFileSettings.ApiKeys.RemoveWhere(x => x.Source.is_equal_to(configuration.Sources)); + + _xmlService.serialize(configFileSettings, ApplicationParameters.GlobalConfigFileLocation); + + this.Log().Info(() => "Removed ApiKey for {0}".format_with(configuration.Sources)); + } + else + { + this.Log().Info(() => "ApiKey was not found for {0}".format_with(configuration.Sources)); + } + + } + public void config_list(ChocolateyConfiguration configuration) { this.Log().Info(ChocolateyLoggers.Important, "Settings"); diff --git a/src/chocolatey/infrastructure.app/services/IChocolateyConfigSettingsService.cs b/src/chocolatey/infrastructure.app/services/IChocolateyConfigSettingsService.cs index 5d3c2c0db0..a45529a329 100644 --- a/src/chocolatey/infrastructure.app/services/IChocolateyConfigSettingsService.cs +++ b/src/chocolatey/infrastructure.app/services/IChocolateyConfigSettingsService.cs @@ -33,6 +33,7 @@ public interface IChocolateyConfigSettingsService void feature_enable(ChocolateyConfiguration configuration); string get_api_key(ChocolateyConfiguration configuration, Action keyAction); void set_api_key(ChocolateyConfiguration configuration); + void remove_api_key(ChocolateyConfiguration configuration); void config_list(ChocolateyConfiguration configuration); void config_get(ChocolateyConfiguration configuration); void config_set(ChocolateyConfiguration configuration);