lib/jira/oauth_client.rb
require 'oauth'
require 'json'
require 'forwardable'
module JIRA
class OauthClient < RequestClient
DEFAULT_OPTIONS = {
signature_method: 'RSA-SHA1',
request_token_path: '/plugins/servlet/oauth/request-token',
authorize_path: '/plugins/servlet/oauth/authorize',
access_token_path: '/plugins/servlet/oauth/access-token',
private_key_file: 'rsakey.pem',
consumer_key: nil,
consumer_secret: nil
}.freeze
# This exception is thrown when the client is used before the OAuth access token
# has been initialized.
class UninitializedAccessTokenError < StandardError
def message
'init_access_token must be called before using the client'
end
end
extend Forwardable
attr_accessor :consumer
attr_reader :options
def_instance_delegators :@consumer, :key, :secret, :get_request_token
def initialize(options)
@options = DEFAULT_OPTIONS.merge(options)
@consumer = init_oauth_consumer(@options)
end
def init_oauth_consumer(_options)
@options[:request_token_path] = @options[:context_path] + @options[:request_token_path]
@options[:authorize_path] = @options[:context_path] + @options[:authorize_path]
@options[:access_token_path] = @options[:context_path] + @options[:access_token_path]
# proxy_address does not exist in oauth's gem context but proxy does
@options[:proxy] = @options[:proxy_address] if @options[:proxy_address]
OAuth::Consumer.new(@options[:consumer_key], @options[:consumer_secret], @options)
end
# Returns the current request token if it is set, else it creates
# and sets a new token.
def request_token(options = {}, *arguments, &block)
@request_token ||= get_request_token(options, *arguments, &block)
end
# Sets the request token from a given token and secret.
def set_request_token(token, secret)
@request_token = OAuth::RequestToken.new(@consumer, token, secret)
end
# Initialises and returns a new access token from the params hash
# returned by the OAuth transaction.
def init_access_token(params)
@access_token = request_token.get_access_token(params)
end
# Sets the access token from a preexisting token and secret.
def set_access_token(token, secret)
@access_token = OAuth::AccessToken.new(@consumer, token, secret)
@authenticated = true
@access_token
end
# Returns the current access token. Raises an
# JIRA::Client::UninitializedAccessTokenError exception if it is not set.
def access_token
raise UninitializedAccessTokenError unless @access_token
@access_token
end
def make_request(http_method, url, body = '', headers = {})
# When using oauth_2legged we need to add an empty oauth_token parameter to every request.
if @options[:auth_type] == :oauth_2legged
oauth_params_str = 'oauth_token='
uri = URI.parse(url)
uri.query = if uri.query.to_s == ''
oauth_params_str
else
uri.query + '&' + oauth_params_str
end
url = uri.to_s
end
case http_method
when :delete, :get, :head
response = access_token.send http_method, url, headers
when :post, :put
response = access_token.send http_method, url, body, headers
end
@authenticated = true
response
end
def make_multipart_request(url, data, headers = {})
request = Net::HTTP::Post::Multipart.new url, data, headers
access_token.sign! request
response = consumer.http.request(request)
@authenticated = true
response
end
def authenticated?
@authenticated
end
end
end