class Gem::GemcutterUtilities::WebauthnPoller

Constants

TIMEOUT_IN_SECONDS

Attributes

host[R]
options[R]

Public Class Methods

new(options, host) click to toggle source
# File lib/rubygems/gemcutter_utilities/webauthn_poller.rb, line 29
def initialize(options, host)
  @options = options
  @host = host
end
poll_thread(options, host, webauthn_url, credentials) click to toggle source
# File lib/rubygems/gemcutter_utilities/webauthn_poller.rb, line 34
def self.poll_thread(options, host, webauthn_url, credentials)
  Thread.new do
    thread = Thread.current
    thread.abort_on_exception = true
    thread.report_on_exception = false
    thread[:otp] = new(options, host).poll_for_otp(webauthn_url, credentials)
  rescue Gem::WebauthnVerificationError, Timeout::Error => e
    thread[:error] = e
  end
end

Public Instance Methods

poll_for_otp(webauthn_url, credentials) click to toggle source
# File lib/rubygems/gemcutter_utilities/webauthn_poller.rb, line 45
def poll_for_otp(webauthn_url, credentials)
  Timeout.timeout(TIMEOUT_IN_SECONDS) do
    loop do
      response = webauthn_verification_poll_response(webauthn_url, credentials)
      raise Gem::WebauthnVerificationError, response.message unless response.is_a?(Net::HTTPSuccess)

      require "json"
      parsed_response = JSON.parse(response.body)
      case parsed_response["status"]
      when "pending"
        sleep 5
      when "success"
        return parsed_response["code"]
      else
        raise Gem::WebauthnVerificationError, parsed_response.fetch("message", "Invalid response from server")
      end
    end
  end
end

Private Instance Methods

webauthn_verification_poll_response(webauthn_url, credentials) click to toggle source
# File lib/rubygems/gemcutter_utilities/webauthn_poller.rb, line 67
def webauthn_verification_poll_response(webauthn_url, credentials)
  webauthn_token = %r{(?<=\/)[^\/]+(?=$)}.match(webauthn_url)[0]
  rubygems_api_request(:get, "api/v1/webauthn_verification/#{webauthn_token}/status.json") do |request|
    if credentials.empty?
      request.add_field "Authorization", api_key
    else
      request.basic_auth credentials[:email], credentials[:password]
    end
  end
end