diff options
Diffstat (limited to 'test/rubygems/test_gem_commands_owner_command.rb')
-rw-r--r-- | test/rubygems/test_gem_commands_owner_command.rb | 142 |
1 files changed, 119 insertions, 23 deletions
diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb index 32bfbb7a66..eddd8afaf5 100644 --- a/test/rubygems/test_gem_commands_owner_command.rb +++ b/test/rubygems/test_gem_commands_owner_command.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true + require_relative "helper" +require_relative "multifactor_auth_utilities" require "rubygems/commands/owner_command" class TestGemCommandsOwnerCommand < Gem::TestCase @@ -10,7 +12,7 @@ class TestGemCommandsOwnerCommand < Gem::TestCase ENV["RUBYGEMS_HOST"] = nil @stub_ui = Gem::MockGemUi.new - @stub_fetcher = Gem::FakeFetcher.new + @stub_fetcher = Gem::MultifactorAuthFetcher.new Gem::RemoteFetcher.fetcher = @stub_fetcher Gem.configuration = nil Gem.configuration.rubygems_api_key = "ed244fbf2b1a52e012da8616c512fa47f9aa5250" @@ -42,14 +44,14 @@ EOF @cmd.show_owners("freewill") end - assert_equal Net::HTTP::Get, @stub_fetcher.last_request.class + assert_equal Gem::Net::HTTP::Get, @stub_fetcher.last_request.class assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"] - assert_match %r{Owners for gem: freewill}, @stub_ui.output - assert_match %r{- user1@example.com}, @stub_ui.output - assert_match %r{- user2@example.com}, @stub_ui.output - assert_match %r{- user3}, @stub_ui.output - assert_match %r{- 4}, @stub_ui.output + assert_match(/Owners for gem: freewill/, @stub_ui.output) + assert_match(/- user1@example.com/, @stub_ui.output) + assert_match(/- user2@example.com/, @stub_ui.output) + assert_match(/- user3/, @stub_ui.output) + assert_match(/- 4/, @stub_ui.output) end def test_show_owners_dont_load_objects @@ -86,8 +88,8 @@ EOF @cmd.show_owners("freewill") end - assert_match %r{Owners for gem: freewill}, @stub_ui.output - assert_match %r{- user1@example.com}, @stub_ui.output + assert_match(/Owners for gem: freewill/, @stub_ui.output) + assert_match(/- user1@example.com/, @stub_ui.output) end def test_show_owners_setting_up_host @@ -101,8 +103,8 @@ EOF @cmd.show_owners("freewill") end - assert_match %r{Owners for gem: freewill}, @stub_ui.output - assert_match %r{- user1@example.com}, @stub_ui.output + assert_match(/Owners for gem: freewill/, @stub_ui.output) + assert_match(/- user1@example.com/, @stub_ui.output) end def test_show_owners_denied @@ -163,7 +165,7 @@ EOF @cmd.add_owners("freewill", ["user-new1@example.com"]) end - assert_equal Net::HTTP::Post, @stub_fetcher.last_request.class + assert_equal Gem::Net::HTTP::Post, @stub_fetcher.last_request.class assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"] assert_equal "email=user-new1%40example.com", @stub_fetcher.last_request.body @@ -216,8 +218,8 @@ EOF end assert_match add_owner_response, @stub_ui.output - assert_match %r{Owners for gem: freewill}, @stub_ui.output - assert_match %r{- user1@example.com}, @stub_ui.output + assert_match(/Owners for gem: freewill/, @stub_ui.output) + assert_match(/- user1@example.com/, @stub_ui.output) end def test_add_owners_key @@ -242,7 +244,7 @@ EOF @cmd.remove_owners("freewill", ["user-remove1@example.com"]) end - assert_equal Net::HTTP::Delete, @stub_fetcher.last_request.class + assert_equal Gem::Net::HTTP::Delete, @stub_fetcher.last_request.class assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"] assert_equal "email=user-remove1%40example.com", @stub_fetcher.last_request.body @@ -323,13 +325,8 @@ EOF end def test_otp_verified_success - response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." response_success = "Owner added successfully." - - @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [ - HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"), - HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"), - ] + @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success) @otp_ui = Gem::MockGemUi.new "111111\n" use_ui @otp_ui do @@ -345,6 +342,8 @@ EOF def test_otp_verified_failure response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry." @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized") + @stub_fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] = + HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity") @otp_ui = Gem::MockGemUi.new "111111\n" use_ui @otp_ui do @@ -357,6 +356,103 @@ EOF assert_equal "111111", @stub_fetcher.last_request["OTP"] end + def test_with_webauthn_enabled_success + response_success = "Owner added successfully." + server = Gem::MockTCPServer.new + + @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success) + @stub_fetcher.respond_with_webauthn_url + + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + end + + assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output + assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"] + assert_match response_success, @stub_ui.output + end + + def test_with_webauthn_enabled_failure + response_success = "Owner added successfully." + server = Gem::MockTCPServer.new + error = Gem::WebauthnVerificationError.new("Something went wrong") + + @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success) + @stub_fetcher.respond_with_webauthn_url + + TCPServer.stub(:new, server) do + Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + end + + assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key + assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output + assert_match "ERROR: Security device verification failed: Something went wrong", @stub_ui.error + refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + refute_match response_success, @stub_ui.output + end + + def test_with_webauthn_enabled_success_with_polling + response_success = "Owner added successfully." + server = Gem::MockTCPServer.new + + @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success) + @stub_fetcher.respond_with_webauthn_url + @stub_fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo") + + TCPServer.stub(:new, server) do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + + assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \ + "command with the `--otp [your_code]` option.", @stub_ui.output + assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"] + assert_match response_success, @stub_ui.output + end + + def test_with_webauthn_enabled_failure_with_polling + response_success = "Owner added successfully." + server = Gem::MockTCPServer.new + + @stub_fetcher.respond_with_require_otp( + "#{Gem.host}/api/v1/gems/freewill/owners", + response_success + ) + @stub_fetcher.respond_with_webauthn_url + @stub_fetcher.respond_with_webauthn_polling_failure + + TCPServer.stub(:new, server) do + use_ui @stub_ui do + @cmd.add_owners("freewill", ["user-new1@example.com"]) + end + end + + assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key + assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \ + "command with the `--otp [your_code]` option.", @stub_ui.output + assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \ + "or been used already.", @stub_ui.error + refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output + refute_match response_success, @stub_ui.output + end + def test_remove_owners_unathorized_api_key response_forbidden = "The API key doesn't have access" response_success = "Owner removed successfully." @@ -375,7 +471,7 @@ EOF access_notice = "The existing key doesn't have access of remove_owner on RubyGems.org. Please sign in to update access." assert_match access_notice, @stub_ui.output - assert_match "Email:", @stub_ui.output + assert_match "Username/email:", @stub_ui.output assert_match "Password:", @stub_ui.output assert_match "Added remove_owner scope to the existing API key", @stub_ui.output assert_match response_success, @stub_ui.output @@ -399,7 +495,7 @@ EOF access_notice = "The existing key doesn't have access of add_owner on RubyGems.org. Please sign in to update access." assert_match access_notice, @stub_ui.output - assert_match "Email:", @stub_ui.output + assert_match "Username/email:", @stub_ui.output assert_match "Password:", @stub_ui.output assert_match "Added add_owner scope to the existing API key", @stub_ui.output assert_match response_success, @stub_ui.output |