diff --git a/oa-core/lib/omniauth/version.rb b/oa-core/lib/omniauth/version.rb index 2938a26..0532ca3 100644 --- a/oa-core/lib/omniauth/version.rb +++ b/oa-core/lib/omniauth/version.rb @@ -10,7 +10,7 @@ module OmniAuth PATCH = 2 end unless defined?(::OmniAuth::Version::PRE) - PRE = nil + PRE = "3.copious" end unless defined?(::OmniAuth::Version::STRING) STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.') diff --git a/oa-oauth/lib/omniauth/oauth.rb b/oa-oauth/lib/omniauth/oauth.rb index b9e5923..1136f61 100644 --- a/oa-oauth/lib/omniauth/oauth.rb +++ b/oa-oauth/lib/omniauth/oauth.rb @@ -7,6 +7,7 @@ module OmniAuth autoload :Dopplr, 'omniauth/strategies/oauth/dopplr' autoload :Douban, 'omniauth/strategies/oauth/douban' autoload :Dropbox, 'omniauth/strategies/oauth/dropbox' + autoload :Etsy, 'omniauth/strategies/oauth/etsy' autoload :Evernote, 'omniauth/strategies/oauth/evernote' autoload :Flattr, 'omniauth/strategies/oauth/flattr' autoload :Flickr, 'omniauth/strategies/oauth/flickr' @@ -67,10 +68,7 @@ module OmniAuth autoload :Vkontakte, 'omniauth/strategies/oauth2/vkontakte' autoload :WePay, 'omniauth/strategies/oauth2/we_pay' autoload :Yammer, 'omniauth/strategies/oauth2/yammer' - - autoload :XAuth, 'omniauth/strategies/xauth' autoload :Instapaper, 'omniauth/strategies/xauth/instapaper' - end end diff --git a/oa-oauth/lib/omniauth/strategies/oauth/etsy.rb b/oa-oauth/lib/omniauth/strategies/oauth/etsy.rb new file mode 100644 index 0000000..cf29c19 --- /dev/null +++ b/oa-oauth/lib/omniauth/strategies/oauth/etsy.rb @@ -0,0 +1,106 @@ +require 'omniauth/oauth' +require 'multi_json' + +module OmniAuth + module Strategies + class Etsy < OmniAuth::Strategies::OAuth + + # Cribbed from the etsy gem. + SANDBOX_HOST = 'sandbox.openapi.etsy.com' + PRODUCTION_HOST = 'openapi.etsy.com' + + # Set the environment, accepts either :sandbox or :production. Defaults to :production + # and will raise an exception when set to an unrecognized environment. + def self.environment=(environment) + unless [:sandbox, :production].include?(environment) + raise(ArgumentError, "environment must be set to either :sandbox or :production") + end + @environment = environment + @host = (environment == :sandbox) ? SANDBOX_HOST : PRODUCTION_HOST + end + + # The currently configured environment. + def self.environment + @environment || :production + end + + def self.host # :nodoc: + @host || PRODUCTION_HOST + end + + def self.callback_url + @callback_url || 'oob' + end + + def initialize(app, consumer_key=nil, consumer_secret=nil, options={}, &block) + # Set environment first; this can update our host + OmniAuth::Strategies::Etsy.environment=options[:environment] if options[:environment] + client_options = { + :site => "http://#{OmniAuth::Strategies::Etsy.host}", + :request_token_path => request_token_path(options), + :access_token_path => access_token_path, + :http_method => :get, + :scheme => :query_string + } + + super(app, :etsy, consumer_key, consumer_secret, client_options, options, &block) + end + + def request_phase + request_token = consumer.get_request_token(:oauth_callback => callback_url) + session['oauth'] ||= {} + session['oauth'][name.to_s] = {'callback_confirmed' => true, 'request_token' => request_token.token, 'request_secret' => request_token.secret} + r = Rack::Response.new + if request_token.params[:login_url] + # Already contains token, etc, of the form: + # https://www.etsy.com/oauth/signin?oauth_consumer_key=wg30ji4z8kdzsymfkw9vm333&oauth_token=650a9d4a8d589bb7e6aefed1628885&service=v2_prod + r.redirect(request_token.params[:login_url]) + end + r.finish + end + + def auth_hash + OmniAuth::Utils.deep_merge(super, { + 'uid' => user_hash['user_id'], + 'user_info' => user_info, + 'extra' => { 'user_hash' => user_hash } + }) + end + + def user_info + return {} unless user_hash + { + 'uid' => user_hash['user_id'], + 'nickname' => user_hash['login_name'], + 'email' => user_hash['primary_email'], + 'name' => user_hash['login_name'], + 'feedback_info' => user_hash['feedback_info'] + } + end + + def request_token_path(options) + # Default scope is to read a user's private profile information, including email. Scope is specified + # as a uri-encoded query kv pair, "scope=scope_1+scope_2+...+scope_n" + # For a full list of scope options, see: + # http://www.etsy.com/developers/documentation/getting_started/oauth + "/v2/oauth/request_token?#{to_params({:scope => options.fetch(:scope, 'profile_r+email_r')})}" + end + + def access_token_path + "/v2/oauth/access_token" + end + + def to_params(options) + options.collect{|key, value| "#{key}=#{value}"}.join('&') + end + + def user_hash + @user_hash ||= MultiJson.decode(@access_token.get('/v2/users/__SELF__').body)['results'][0] + rescue ::Errno::ETIMEDOUT + raise ::Timeout::Error + rescue ::OAuth::Error => e + raise e.response.inspect + end + end + end +end diff --git a/oa-oauth/lib/omniauth/version.rb b/oa-oauth/lib/omniauth/version.rb index 2938a26..0532ca3 100644 --- a/oa-oauth/lib/omniauth/version.rb +++ b/oa-oauth/lib/omniauth/version.rb @@ -10,7 +10,7 @@ module OmniAuth PATCH = 2 end unless defined?(::OmniAuth::Version::PRE) - PRE = nil + PRE = "3.copious" end unless defined?(::OmniAuth::Version::STRING) STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.') diff --git a/oa-oauth/spec/omniauth/strategies/oauth/etsy_spec.rb b/oa-oauth/spec/omniauth/strategies/oauth/etsy_spec.rb new file mode 100644 index 0000000..19259fe --- /dev/null +++ b/oa-oauth/spec/omniauth/strategies/oauth/etsy_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe OmniAuth::Strategies::Etsy do + it_should_behave_like "an oauth strategy" +end