From 7892d830ae593d9f2fb28a0f8f33b038a13007aa Mon Sep 17 00:00:00 2001 From: Adam Grare Date: Fri, 10 May 2024 12:33:20 -0400 Subject: [PATCH] Add a common method for asking for a new password When entering an existing password it is sufficient to prompt once since if the user mistyped the password it will fail later on, but when creating a new password it is common to re-prompt them to confirm that they didn't typo the new password. --- .../database_configuration.rb | 27 +------------------ .../appliance_console/database_replication.rb | 23 +++------------- .../message_configuration.rb | 1 + .../message_configuration_server.rb | 2 +- lib/manageiq/appliance_console/prompts.rb | 21 +++++++++++++++ spec/message_configuration_server_spec.rb | 22 +++++++++++---- 6 files changed, 45 insertions(+), 51 deletions(-) diff --git a/lib/manageiq/appliance_console/database_configuration.rb b/lib/manageiq/appliance_console/database_configuration.rb index 203e59c6..f2f48fbc 100644 --- a/lib/manageiq/appliance_console/database_configuration.rb +++ b/lib/manageiq/appliance_console/database_configuration.rb @@ -121,32 +121,7 @@ def ask_for_database_credentials(password_twice = true) self.port = ask_for_integer("port number", nil, port) unless local? self.database = just_ask("name of the database on #{host}", database) unless local? self.username = just_ask("username", username) unless local? - count = 0 - loop do - password1 = ask_for_password("database password on #{host}", password) - # if they took the default, just bail - break if (password1 == password) - - if password1.strip.length == 0 - say("\nPassword can not be empty, please try again") - next - end - if password_twice - password2 = ask_for_password("database password again") - if password1 == password2 - self.password = password1 - break - elsif count > 0 # only reprompt password once - raise "passwords did not match" - else - count += 1 - say("\nThe passwords did not match, please try again") - end - else - self.password = password1 - break - end - end + self.password = ask_for_new_password("database password on #{host}", :default => password, :confirm_password => password_twice) end def friendly_inspect diff --git a/lib/manageiq/appliance_console/database_replication.rb b/lib/manageiq/appliance_console/database_replication.rb index a6e36829..7363fafa 100644 --- a/lib/manageiq/appliance_console/database_replication.rb +++ b/lib/manageiq/appliance_console/database_replication.rb @@ -6,6 +6,7 @@ module ManageIQ module ApplianceConsole class DatabaseReplication include ManageIQ::ApplianceConsole::Logging + include ManageIQ::ApplianceConsole::Prompts PGPASS_FILE = '/var/lib/pgsql/.pgpass'.freeze NETWORK_INTERFACE = 'eth0'.freeze @@ -115,25 +116,9 @@ def write_pgpass_file private def ask_for_cluster_database_credentials - self.database_name = just_ask("cluster database name", database_name) - self.database_user = just_ask("cluster database username", database_user) - - count = 0 - loop do - count += 1 - password1 = ask_for_password("cluster database password", database_password) - # if they took the default, just bail - break if password1 == database_password - password2 = ask_for_password("cluster database password") - if password1 == password2 - self.database_password = password1 - break - elsif count > 1 # only reprompt password once - raise RuntimeError, "passwords did not match" - else - say("\nThe passwords did not match, please try again") - end - end + self.database_name = just_ask("cluster database name", database_name) + self.database_user = just_ask("cluster database username", database_user) + self.database_password = ask_for_new_password("cluster database password", :default => database_password) end def run_repmgr_command(cmd, params = {}) diff --git a/lib/manageiq/appliance_console/message_configuration.rb b/lib/manageiq/appliance_console/message_configuration.rb index e7e0671c..53110248 100644 --- a/lib/manageiq/appliance_console/message_configuration.rb +++ b/lib/manageiq/appliance_console/message_configuration.rb @@ -7,6 +7,7 @@ module ManageIQ module ApplianceConsole class MessageConfiguration include ManageIQ::ApplianceConsole::ManageiqUserMixin + include ManageIQ::ApplianceConsole::Prompts attr_reader :message_keystore_username, :message_keystore_password, :message_server_host, :message_server_port, diff --git a/lib/manageiq/appliance_console/message_configuration_server.rb b/lib/manageiq/appliance_console/message_configuration_server.rb index 90dd57bb..44a4c2ec 100644 --- a/lib/manageiq/appliance_console/message_configuration_server.rb +++ b/lib/manageiq/appliance_console/message_configuration_server.rb @@ -75,7 +75,7 @@ def ask_for_parameters @message_server_host = "127.0.0.1" if @message_server_host.include?("localhost") @message_keystore_username = ask_for_string("Message Keystore Username", message_keystore_username) - @message_keystore_password = ask_for_password("Message Keystore Password") + @message_keystore_password = ask_for_new_password("Message Keystore Password") @message_persistent_disk = ask_for_persistent_disk end diff --git a/lib/manageiq/appliance_console/prompts.rb b/lib/manageiq/appliance_console/prompts.rb index 4ca21b4e..c01429f9 100644 --- a/lib/manageiq/appliance_console/prompts.rb +++ b/lib/manageiq/appliance_console/prompts.rb @@ -113,6 +113,27 @@ def ask_for_password(prompt, default = nil) pass == "********" ? (default || "") : pass end + def ask_for_new_password(prompt, default: nil, allow_empty: false, retry_limit: 1, confirm_password: true) + count = 0 + loop do + password1 = ask_for_password(prompt, default) + if password1.strip.empty? && !allow_empty + say("\nPassword can not be empty, please try again") + next + end + + return password1 if password1 == default || !confirm_password + + password2 = ask_for_password(prompt) + return password1 if password1 == password2 + + raise "passwords did not match" if count >= retry_limit + + count += 1 + say("\nThe passwords did not match, please try again") + end + end + def ask_for_string(prompt, default = nil) just_ask(prompt, default) end diff --git a/spec/message_configuration_server_spec.rb b/spec/message_configuration_server_spec.rb index 0e37525e..6952a7a5 100644 --- a/spec/message_configuration_server_spec.rb +++ b/spec/message_configuration_server_spec.rb @@ -47,7 +47,19 @@ it "should prompt for message_keystore_username and message_keystore_password" do expect(subject).to receive(:ask_for_string).with("Message Server Hostname or IP address", "my-host-name.example.com").and_return("my-host-name.example.com") expect(subject).to receive(:ask_for_string).with("Message Keystore Username", message_keystore_username).and_return("admin") - expect(subject).to receive(:ask_for_password).with("Message Keystore Password").and_return("top_secret") + expect(subject).to receive(:just_ask).with(/Message Keystore Password/i, anything).twice.and_return("top_secret") + + allow(subject).to receive(:say).at_least(5).times + + expect(subject.send(:ask_questions)).to be_truthy + end + + it "should re-prompt when an empty message_keystore_password is given" do + expect(subject).to receive(:ask_for_string).with("Message Server Hostname or IP address", "my-host-name.example.com").and_return("my-host-name.example.com") + expect(subject).to receive(:ask_for_string).with("Message Keystore Username", message_keystore_username).and_return("admin") + expect(subject).to receive(:just_ask).with(/Message Keystore Password/i, anything).and_return("") + expect(subject).to receive(:just_ask).with(/Message Keystore Password/i, anything).twice.and_return("top_secret") + expect(subject).to receive(:say).with("\nPassword can not be empty, please try again") allow(subject).to receive(:say).at_least(5).times @@ -57,7 +69,7 @@ it "should display Server Hostname and Keystore Username" do allow(subject).to receive(:ask_for_string).with("Message Server Hostname or IP address", "my-host-name.example.com").and_return("my-host-name.example.com") allow(subject).to receive(:ask_for_string).with("Message Keystore Username", message_keystore_username).and_return("admin") - allow(subject).to receive(:ask_for_password).with("Message Keystore Password").and_return("top_secret") + expect(subject).to receive(:just_ask).with(/Message Keystore Password/i, anything).twice.and_return("top_secret") expect(subject).to receive(:say).with("\nMessage Server Parameters:\n\n") expect(subject).to receive(:say).with("\nMessage Server Configuration:\n") @@ -78,7 +90,7 @@ message_persistent_disk = LinuxAdmin::Disk.new(:path => "/tmp/disk") expect(subject).to receive(:ask_for_string).with("Message Server Hostname or IP address", "my-host-name.example.com").and_return("my-host-name.example.com") expect(subject).to receive(:ask_for_string).with("Message Keystore Username", message_keystore_username).and_return("admin") - expect(subject).to receive(:ask_for_password).with("Message Keystore Password").and_return("top_secret") + expect(subject).to receive(:just_ask).with(/Message Keystore Password/i, anything).twice.and_return("top_secret") expect(subject).to receive(:ask_for_disk).with("Persistent disk").and_return(message_persistent_disk) allow(subject).to receive(:say).at_least(5).times @@ -366,7 +378,7 @@ expect(subject).to receive(:say).with(/Message Server Parameters/) expect(subject).to receive(:ask_for_string).with("Message Server Hostname or IP address", anything).and_return("localhost") expect(subject).to receive(:ask_for_string).with("Message Keystore Username", anything).and_return("admin") - expect(subject).to receive(:ask_for_password).with("Message Keystore Password").and_return("top_secret") + expect(subject).to receive(:just_ask).with(/Message Keystore Password/i, anything).twice.and_return("top_secret") expect(subject).to receive(:ask_for_disk).with("Persistent disk").and_return("/tmp/disk") subject.ask_for_parameters @@ -377,7 +389,7 @@ expect(subject).to receive(:say).with(/Message Server Parameters/) expect(subject).to receive(:ask_for_string).with("Message Server Hostname or IP address", anything).and_return("localhost.localadmin") expect(subject).to receive(:ask_for_string).with("Message Keystore Username", anything).and_return("admin") - expect(subject).to receive(:ask_for_password).with("Message Keystore Password").and_return("top_secret") + expect(subject).to receive(:just_ask).with(/Message Keystore Password/i, anything).twice.and_return("top_secret") expect(subject).to receive(:ask_for_disk).with("Persistent disk").and_return("/tmp/disk") subject.ask_for_parameters