summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-12-01 11:01:00 +0000
committerhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-12-01 11:01:00 +0000
commit7a46a3b94121339cbead211c4497142bee82fddb (patch)
treebc6e9f11a1b60f8c4258e4780b18f952b0a8ec35 /lib
parent5cae104e51be9cbf524b7d953b33d0909c46d006 (diff)
Merge rubygems-3.0.0.beta3.
* [GSoC] Multi-factor feature for RubyGems https://github.com/rubygems/rubygems/pull/2369 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66118 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/rubygems.rb2
-rw-r--r--lib/rubygems/commands/owner_command.rb18
-rw-r--r--lib/rubygems/commands/push_command.rb20
-rw-r--r--lib/rubygems/commands/signin_command.rb2
-rw-r--r--lib/rubygems/gemcutter_utilities.rb31
-rw-r--r--lib/rubygems/test_utilities.rb2
6 files changed, 65 insertions, 10 deletions
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index b335dc321b..048eb9bdda 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -9,7 +9,7 @@
require 'rbconfig'
module Gem
- VERSION = "3.0.0.beta2".freeze
+ VERSION = "3.0.0.beta3".freeze
end
# Must be first since it unloads the prelude from 1.9.2
diff --git a/lib/rubygems/commands/owner_command.rb b/lib/rubygems/commands/owner_command.rb
index 9cfaa241b5..799f31704a 100644
--- a/lib/rubygems/commands/owner_command.rb
+++ b/lib/rubygems/commands/owner_command.rb
@@ -30,6 +30,7 @@ permission to.
super 'owner', 'Manage gem owners of a gem on the push server'
add_proxy_option
add_key_option
+ add_otp_option
defaults.merge! :add => [], :remove => []
add_option '-a', '--add EMAIL', 'Add an owner' do |value, options|
@@ -84,9 +85,10 @@ permission to.
def manage_owners(method, name, owners)
owners.each do |owner|
begin
- response = rubygems_api_request method, "api/v1/gems/#{name}/owners" do |request|
- request.set_form_data 'email' => owner
- request.add_field "Authorization", api_key
+ response = send_owner_request(method, name, owner)
+
+ if need_otp? response
+ response = send_owner_request(method, name, owner, true)
end
action = method == :delete ? "Removing" : "Adding"
@@ -98,4 +100,14 @@ permission to.
end
end
+ private
+
+ def send_owner_request(method, name, owner, use_otp = false)
+ rubygems_api_request method, "api/v1/gems/#{name}/owners" do |request|
+ request.set_form_data 'email' => owner
+ request.add_field "Authorization", api_key
+ request.add_field "OTP", options[:otp] if use_otp
+ end
+ end
+
end
diff --git a/lib/rubygems/commands/push_command.rb b/lib/rubygems/commands/push_command.rb
index 20812368c4..3ea4703a3e 100644
--- a/lib/rubygems/commands/push_command.rb
+++ b/lib/rubygems/commands/push_command.rb
@@ -33,6 +33,7 @@ command. For further discussion see the help for the yank command.
add_proxy_option
add_key_option
+ add_otp_option
add_option('--host HOST',
'Push to another gemcutter-compatible host',
@@ -113,11 +114,10 @@ You can upgrade or downgrade to the latest release version with:
say "Pushing gem to #{@host || Gem.host}..."
- response = rubygems_api_request(*args) do |request|
- request.body = Gem.read_binary name
- request.add_field "Content-Length", request.body.size
- request.add_field "Content-Type", "application/octet-stream"
- request.add_field "Authorization", api_key
+ response = send_push_request(name, args)
+
+ if need_otp? response
+ response = send_push_request(name, args, true)
end
with_response response
@@ -125,6 +125,16 @@ You can upgrade or downgrade to the latest release version with:
private
+ def send_push_request(name, args, use_otp = false)
+ rubygems_api_request(*args) do |request|
+ request.body = Gem.read_binary name
+ request.add_field "Content-Length", request.body.size
+ request.add_field "Content-Type", "application/octet-stream"
+ request.add_field "Authorization", api_key
+ request.add_field "OTP", options[:otp] if use_otp
+ end
+ end
+
def get_hosts_for(name)
gem_metadata = Gem::Package.new(name).spec.metadata
diff --git a/lib/rubygems/commands/signin_command.rb b/lib/rubygems/commands/signin_command.rb
index 64b187f26f..0d527fc339 100644
--- a/lib/rubygems/commands/signin_command.rb
+++ b/lib/rubygems/commands/signin_command.rb
@@ -12,6 +12,8 @@ class Gem::Commands::SigninCommand < Gem::Command
add_option('--host HOST', 'Push to another gemcutter-compatible host') do |value, options|
options[:host] = value
end
+
+ add_otp_option
end
def description # :nodoc:
diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb
index 6fe8455498..3607b61529 100644
--- a/lib/rubygems/gemcutter_utilities.rb
+++ b/lib/rubygems/gemcutter_utilities.rb
@@ -25,6 +25,16 @@ module Gem::GemcutterUtilities
end
##
+ # Add the --otp option
+
+ def add_otp_option
+ add_option('--otp CODE',
+ 'Digit code for multifactor authentication') do |value, options|
+ options[:otp] = value
+ end
+ end
+
+ ##
# The API key from the command options or from the user's configuration.
def api_key
@@ -113,6 +123,13 @@ module Gem::GemcutterUtilities
request.basic_auth email, password
end
+ if need_otp? response
+ response = rubygems_api_request(:get, "api/v1/api_key", sign_in_host) do |request|
+ request.basic_auth email, password
+ request.add_field "OTP", options[:otp]
+ end
+ end
+
with_response response do |resp|
say "Signed in."
set_api_key host, resp.body
@@ -156,6 +173,20 @@ module Gem::GemcutterUtilities
end
end
+ ##
+ # Returns true when the user has enabled multifactor authentication from
+ # +response+ text.
+
+ def need_otp?(response)
+ return unless response.kind_of?(Net::HTTPUnauthorized) &&
+ response.body.start_with?('You have enabled multifactor authentication')
+ return true if options[:otp]
+
+ say 'You have enabled multi-factor authentication. Please enter OTP code.'
+ options[:otp] = ask 'Code: '
+ true
+ end
+
def set_api_key(host, key)
if host == Gem::DEFAULT_HOST
Gem.configuration.rubygems_api_key = key
diff --git a/lib/rubygems/test_utilities.rb b/lib/rubygems/test_utilities.rb
index fe7eff8d8c..d531239812 100644
--- a/lib/rubygems/test_utilities.rb
+++ b/lib/rubygems/test_utilities.rb
@@ -87,7 +87,7 @@ class Gem::FakeFetcher
def request(uri, request_class, last_modified = nil)
data = find_data(uri)
- body, code, msg = data
+ body, code, msg = (data.respond_to?(:call) ? data.call : data)
@last_request = request_class.new uri.request_uri
yield @last_request if block_given?