omniauth-ebay-oauth 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7a3ee3f09f7e2fd936ac49fa1512e29e6e4ed1df
4
+ data.tar.gz: 6d0ce4be65417086d284dd903e6b098aed7cc41e
5
+ SHA512:
6
+ metadata.gz: 33576de1081fb33087a2ea9793e98f25ae29e4ed292ed99c55eba7d92979daca8cfdce4cb25c07947eda3f52f4dcb73847a2660f49f75f0a4df8146b124869b1
7
+ data.tar.gz: a2829309ed789bee85d16296c0641d1229881750ccc5b04324ccf5d2b0d5261fe62a7942208b2fefc56d3b166463780ceaceceb74fb9134edf8c583750a27823
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,10 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - 'spec/**/*.rb'
7
+
8
+ Naming/FileName:
9
+ Exclude:
10
+ - 'lib/*.rb'
@@ -0,0 +1 @@
1
+ 2.3.5
@@ -0,0 +1,6 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.5
5
+ - 2.4.2
6
+ before_install: gem install bundler -v 1.15.4
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Andrey Novikov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,109 @@
1
+ # omniauth-ebay-oauth
2
+
3
+ OmniAuth Strategy for eBay Apps (for using with eBay REST APIs)
4
+
5
+ <a href="https://evilmartians.com/?utm_source=omniauth-ebay-oauth&utm_campaign=project_page">
6
+ <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
7
+ </a>
8
+
9
+ ## Preface
10
+
11
+ > Why do I need it? There are a couple of other gems with OmniAuth strategies for eBay?
12
+
13
+ eBay has two different authorization methods: Auth'n'auth and OAuth. Technically, they are both uses OAuth2 protocol (just to embrace a little confusion).
14
+
15
+ This gem implements authorization with OAuth method while currently available gems (like [ebay_request](https://github.com/gzigzigzeo/ebay_request) or [omniauth-ebay](https://github.com/TheGiftsProject/omniauth-ebay)) implements Auth'n'auth.
16
+
17
+ __What is the difference? Access tokens!__
18
+
19
+ With Auth'n'auth you will get a single token which you can use to access old eBay XML APIs (Trading API, etc.)
20
+
21
+ With OAuth, you will get a pair of access and refresh tokens which can be used to access new eBay REST APIs (Buy API, Sell API, etc.)
22
+
23
+ However, you can use new OAuth tokens to access old APIs by providing an access token in (not yet) documented HTTP header `X-EBAY-API-IAF-TOKEN` (like this gem uses it to obtain information about an authenticated user from Trading API).
24
+
25
+ If you plan to use only old APIs, you can look at [ebay_request](https://github.com/gzigzigzeo/ebay_request) gem.
26
+
27
+ If you plan to use new APIs, you are welcome to use this gem either standalone or together with [ebay_api](https://github.com/nepalez/ebay_api) client get for REST APIs.
28
+
29
+ Now you can read the eBay docs about [REST APIs](https://developer.ebay.com/api-docs/static/ebay-rest-landing.html) and [OAuth](https://developer.ebay.com/api-docs/static/oauth-quick-ref-user-tokens.html) and then proceed to…
30
+
31
+
32
+ ## Installation
33
+
34
+ Add to your Gemfile:
35
+
36
+ ```ruby
37
+ gem 'omniauth-ebay-oauth'
38
+ ```
39
+
40
+ Then execute:
41
+
42
+ ```sh
43
+ bundle install
44
+ ```
45
+
46
+
47
+ ## Usage
48
+
49
+ ```ruby
50
+ use OmniAuth::Builder do
51
+ provider :ebay, CLIENT_ID, CLIENT_SECRET, callback_url: RU_NAME,
52
+ sandbox: false, scope: 'https://api.ebay.com/oauth/api_scope' # redefining additional default options
53
+ end
54
+ ```
55
+
56
+ Required options:
57
+ - __CLIENT_ID__, __CLIENT_SECRET__ - Your application's [OAuth credentials](<https://developer.ebay.com/api-docs/static/oauth-credentials.html>) for the environment you're targeting.
58
+ - __callback_url__ - Your application's [RuName](<https://developer.ebay.com/api-docs/static/oauth-runame.html>) for the environment you're targeting.
59
+
60
+ Additional options:
61
+ - __sandbox__ - Are you running your application in [sandbox mode](<https://developer.ebay.com/api-docs/static/sandbox-landing.html>), default __`true`__.
62
+ - __scope__ - A list of [OAuth scopes](<https://developer.ebay.com/api-docs/static/oauth-details.html#scopes>) that provide access to the interfaces you call, default: __`[]`__. If you want change scopes you could pass it as string or as array of scopes like so: `['https://api.ebay.com/oauth/api_scope/sell.marketing.readonly', 'https://api.ebay.com/oauth/api_scope/sell.account.readonly']`
63
+ - __read_timeout__ - Number of seconds to wait for one block to be read for Auth'n'auth eBay API requests, default is 60.
64
+ - \+ all [OmniAuth](<https://github.com/omniauth/omniauth>) supported options, like: `callback_path`, `provider_ignores_state` and so on.
65
+
66
+ Additional usage information could be found on [OmniAuth README page](<https://github.com/omniauth/omniauth#integrating-omniauth-into-your-application>).
67
+
68
+
69
+ ## Minimal working Sinatra application:
70
+
71
+ ```ruby
72
+ require 'sinatra'
73
+ require 'omniauth-ebay-oauth'
74
+
75
+ use Rack::Session::Cookie
76
+ use OmniAuth::Builder do
77
+ provider :ebay, ENV['EBAY_CLIENT_ID'], ENV['EBAY_CLIENT_SECRET'],
78
+ callback_url: ENV['EBAY_RU_NAME']
79
+ end
80
+
81
+ get '/' do
82
+ redirect '/auth/ebay'
83
+ end
84
+
85
+ get '/auth/ebay/callback' do
86
+ "Hello, #{request.env['omniauth.auth'].dig('info', 'name')}"
87
+ end
88
+ ```
89
+
90
+
91
+ ## Development
92
+
93
+ To pass your code through the all checks you simply need to run:
94
+
95
+ ```
96
+ bundle exec rake
97
+ ```
98
+
99
+ Please, keep in mind [OmniAuth Strategy Contribution Guide](<https://github.com/omniauth/omniauth/wiki/Strategy-Contribution-Guide>) and [eBay developers program](<https://developer.ebay.com/api-docs/static/oauth-tokens.html>).
100
+
101
+
102
+ ## Contributing
103
+
104
+ Bug reports and pull requests are welcome on GitHub at https://github.com/evilmartians/omniauth-ebay-oauth.
105
+
106
+
107
+ ## License
108
+
109
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new do |task|
9
+ task.options = %w[--auto-correct]
10
+ end
11
+
12
+ task default: %i[rubocop spec]
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'omniauth-oauth2'
4
+
5
+ require 'omniauth/ebay-oauth/version'
6
+
7
+ require 'omniauth/ebay-oauth/errors'
8
+ require 'omniauth/ebay-oauth/user_info'
9
+ require 'omniauth/ebay-oauth/user_info_request'
10
+ require 'omniauth/strategies/ebay'
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAuth
4
+ module EbayOauth
5
+ class FailureResponseCode < StandardError; end
6
+ class FailureResponseResult < StandardError; end
7
+ class UnsupportedSchemaError < StandardError; end
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <GetUserRequest xmlns="urn:ebay:apis:eBLBaseComponents">
3
+ <ErrorLanguage>en_US</ErrorLanguage>
4
+ <WarningLevel>High</WarningLevel>
5
+ <DetailLevel>ReturnAll</DetailLevel>
6
+ </GetUserRequest>
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAuth
4
+ module EbayOauth
5
+ # Maps user information from Auth'n'auth eBay API to OmniAuth Auth Hash
6
+ # Schema version 1.0
7
+ # https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema
8
+ class UserInfo
9
+ MAPPING = {
10
+ uid: %w[GetUserResponse User EIASToken],
11
+ name: %w[GetUserResponse User RegistrationAddress Name],
12
+ nickname: %w[GetUserResponse User UserID],
13
+ email: %w[GetUserResponse User Email]
14
+ }.freeze
15
+
16
+ def initialize(body)
17
+ @body = body
18
+ end
19
+
20
+ def uid
21
+ field(:uid, required: true)
22
+ end
23
+
24
+ def info
25
+ {
26
+ name: field(:name, required: true),
27
+ email: field(:email),
28
+ nickname: field(:nickname),
29
+ first_name: field(:name).split.first,
30
+ last_name: field(:name).split.last
31
+ }
32
+ end
33
+
34
+ def extra
35
+ { raw_info: @body.dig('GetUserResponse', 'User') }
36
+ end
37
+
38
+ private
39
+
40
+ def field(name, required: false)
41
+ @body.dig(*MAPPING.fetch(name)).tap do |value|
42
+ if value.nil? && required
43
+ raise UnsupportedSchemaError, "Can't find field #{name}"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAuth
4
+ module EbayOauth
5
+ # Receives user information from Auth'n'auth eBay API
6
+ # https://developer.ebay.com/devzone/xml/docs/reference/ebay/GetUser.html
7
+ class UserInfoRequest
8
+ STATUS_PATH = %w[GetUserResponse Ack].freeze
9
+ SUCCESS_CODE = 'Success'
10
+ USER_REQUEST = File.read(
11
+ File.join(File.dirname(__FILE__), 'get_user.xml')
12
+ )
13
+
14
+ TOKEN_HEADER = 'X-EBAY-API-IAF-TOKEN'
15
+ BASIC_HEADERS = {
16
+ 'Content-Type' => 'text/xml',
17
+ 'X-EBAY-API-COMPATIBILITY-LEVEL' => 967,
18
+ 'X-EBAY-API-SITEID' => 0,
19
+ 'X-EBAY-API-CALL-NAME' => 'GetUser'
20
+ }.freeze
21
+
22
+ def initialize(access_token, request: USER_REQUEST,
23
+ user_info_endpoint:, read_timeout:, **_args)
24
+ @access_token = access_token
25
+ @url = URI(user_info_endpoint)
26
+ @read_timeout = read_timeout
27
+ @request = request
28
+ end
29
+
30
+ def call
31
+ MultiXml.parse(
32
+ http
33
+ .request(ebay_request)
34
+ .tap(&method(:ensure_success_code))
35
+ .read_body
36
+ ).tap(&method(:ensure_success_result))
37
+ end
38
+
39
+ private
40
+
41
+ def ensure_success_code(response)
42
+ return if (200..299).cover?(response.code.to_i)
43
+ raise FailureResponseCode, response
44
+ end
45
+
46
+ def ensure_success_result(body)
47
+ return if body.dig(*STATUS_PATH) == SUCCESS_CODE
48
+ raise FailureResponseResult, body
49
+ end
50
+
51
+ def http
52
+ Net::HTTP.new(@url.host, @url.port).tap do |http|
53
+ http.read_timeout = @read_timeout
54
+ http.use_ssl = true
55
+ end
56
+ end
57
+
58
+ def ebay_request
59
+ Net::HTTP::Post.new(@url).tap do |request|
60
+ BASIC_HEADERS.merge(TOKEN_HEADER => @access_token)
61
+ .each { |header, value| request[header] = value }
62
+ request.body = @request
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAuth
4
+ module EbayOauth
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAuth
4
+ module Strategies
5
+ # OmniAuth strategy for eBay
6
+ class Ebay < OmniAuth::Strategies::OAuth2
7
+ option :production_client_options,
8
+ user_info_endpoint: 'https://api.ebay.com/ws/api.dll',
9
+ token_url: 'https://api.ebay.com/identity/v1/oauth2/token',
10
+ authorize_url: 'https://signin.ebay.com/authorize'
11
+ option :sandbox_client_options,
12
+ user_info_endpoint: 'https://api.sandbox.ebay.com/ws/api.dll',
13
+ token_url: 'https://api.sandbox.ebay.com/identity/v1/oauth2/token',
14
+ authorize_url: 'https://signin.sandbox.ebay.com/authorize'
15
+
16
+ option :name, :ebay
17
+ option :sandbox, true
18
+ option :callback_url
19
+
20
+ option :authorize_options, %i[scope]
21
+ option :client_options, auth_scheme: :basic_auth, read_timeout: 60
22
+
23
+ uid { user_info.uid }
24
+ info { user_info.info }
25
+ extra { user_info.extra }
26
+ credentials { user_credentials }
27
+
28
+ def setup_phase
29
+ options.scope = preprocessed_scopes
30
+ options.client_options.merge!(environment_urls)
31
+ super
32
+ end
33
+
34
+ def callback_url
35
+ options.callback_url
36
+ end
37
+
38
+ private
39
+
40
+ def user_credentials
41
+ self.class.superclass.credentials_stack(self).first.merge(
42
+ 'refresh_token_expires_at' =>
43
+ access_token['refresh_token_expires_in'].to_i + Time.now.to_i
44
+ )
45
+ end
46
+
47
+ def preprocessed_scopes
48
+ Array(options.scope).join(' ')
49
+ end
50
+
51
+ def environment_urls
52
+ if options.sandbox
53
+ options.sandbox_client_options
54
+ else
55
+ options.production_client_options
56
+ end
57
+ end
58
+
59
+ def user_info
60
+ @user_info ||=
61
+ OmniAuth::EbayOauth::UserInfo.new(OmniAuth::EbayOauth::UserInfoRequest
62
+ .new(access_token.token, client.options).call)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'omniauth/ebay-oauth/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'omniauth-ebay-oauth'
9
+ spec.version = OmniAuth::EbayOauth::VERSION
10
+ spec.authors = ['Ignat Zakrevsky']
11
+ spec.email = ['iezakrevsky@gmail.com']
12
+ spec.summary = 'OmniAuth strategy for new eBay OAuth API'
13
+ spec.homepage = 'https://github.com/evilmartians/omniauth-ebay-oauth'
14
+ spec.license = 'MIT'
15
+
16
+ spec.required_ruby_version = '>= 2.3'
17
+
18
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'omniauth', '~> 1.5'
22
+ spec.add_dependency 'omniauth-oauth2', '~> 1.4'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.15'
25
+ spec.add_development_dependency 'rake', '>= 10'
26
+ spec.add_development_dependency 'rspec', '~> 3.5'
27
+ spec.add_development_dependency 'rubocop', '~> 0.42'
28
+ spec.add_development_dependency 'simplecov', '~> 0.10'
29
+ spec.add_development_dependency 'webmock', '~> 2.1'
30
+ end
@@ -0,0 +1,10 @@
1
+ ---
2
+ Accept: "*/*"
3
+ Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
4
+ Content-Type: text/xml
5
+ Host: api.com
6
+ User-Agent: Ruby
7
+ X-Ebay-Api-Call-Name: GetUser
8
+ X-Ebay-Api-Compatibility-Level: '967'
9
+ X-Ebay-Api-Iaf-Token: token
10
+ X-Ebay-Api-Siteid: '0'
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <GetUserResponse xmlns="urn:ebay:apis:eBLBaseComponents">
3
+ <Timestamp>2017-11-03T15:10:16.972Z</Timestamp>
4
+ <Ack>Failure</Ack>
5
+ <Errors>
6
+ <ShortMessage>Expired IAF token.</ShortMessage>
7
+ <LongMessage>IAF token supplied is expired. </LongMessage>
8
+ <ErrorCode>21917053</ErrorCode>
9
+ <SeverityCode>Error</SeverityCode>
10
+ <ErrorClassification>RequestError</ErrorClassification>
11
+ </Errors>
12
+ <Version>1031</Version>
13
+ <Build>E1031_CORE_APISIGNIN_18531943_R1</Build>
14
+ </GetUserResponse>
@@ -0,0 +1,67 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <GetUserResponse xmlns="urn:ebay:apis:eBLBaseComponents">
3
+ <Timestamp>2017-11-03T15:31:05.024Z</Timestamp>
4
+ <Ack>Success</Ack>
5
+ <Version>1031</Version>
6
+ <Build>E1031_CORE_APISIGNIN_18531943_R1</Build>
7
+ <User>
8
+ <AboutMePage>false</AboutMePage>
9
+ <EIASToken>nY+sHZ2PrKoij6wVnY+sEZ2PrA2dj6ACmYChC5WDoQydj6x9nY+seQ==</EIASToken>
10
+ <Email>olegpetrov@mail.com</Email>
11
+ <FeedbackScore>0</FeedbackScore>
12
+ <UniqueNegativeFeedbackCount>0</UniqueNegativeFeedbackCount>
13
+ <UniquePositiveFeedbackCount>0</UniquePositiveFeedbackCount>
14
+ <PositiveFeedbackPercent>0.0</PositiveFeedbackPercent>
15
+ <FeedbackPrivate>false</FeedbackPrivate>
16
+ <FeedbackRatingStar>None</FeedbackRatingStar>
17
+ <IDVerified>false</IDVerified>
18
+ <eBayGoodStanding>true</eBayGoodStanding>
19
+ <NewUser>true</NewUser>
20
+ <RegistrationAddress>
21
+ <Name>Oleg Petrov</Name>
22
+ <Street>Ap #867-859 Sit Rd.</Street>
23
+ <Street1>Sit Rd</Street1>
24
+ <Street2>#867-859</Street2>
25
+ <CityName>Azusa</CityName>
26
+ <Country>US</Country>
27
+ <CountryName>United States</CountryName>
28
+ <Phone>7931516230</Phone>
29
+ <PostalCode>91702</PostalCode>
30
+ </RegistrationAddress>
31
+ <RegistrationDate>2017-11-01T20:21:09.000Z</RegistrationDate>
32
+ <Site>US</Site>
33
+ <Status>Confirmed</Status>
34
+ <UserID>olegpetrov</UserID>
35
+ <UserIDChanged>false</UserIDChanged>
36
+ <VATStatus>NoVATTax</VATStatus>
37
+ <SellerInfo>
38
+ <AllowPaymentEdit>true</AllowPaymentEdit>
39
+ <CheckoutEnabled>true</CheckoutEnabled>
40
+ <CIPBankAccountStored>false</CIPBankAccountStored>
41
+ <GoodStanding>true</GoodStanding>
42
+ <LiveAuctionAuthorized>false</LiveAuctionAuthorized>
43
+ <MerchandizingPref>OptIn</MerchandizingPref>
44
+ <QualifiesForB2BVAT>false</QualifiesForB2BVAT>
45
+ <SellerGuaranteeLevel>NotEligible</SellerGuaranteeLevel>
46
+ <SchedulingInfo>
47
+ <MaxScheduledMinutes>30240</MaxScheduledMinutes>
48
+ <MinScheduledMinutes>0</MinScheduledMinutes>
49
+ <MaxScheduledItems>3000</MaxScheduledItems>
50
+ </SchedulingInfo>
51
+ <StoreOwner>false</StoreOwner>
52
+ <SellerBusinessType>Private</SellerBusinessType>
53
+ <PaymentMethod>NothingOnFile</PaymentMethod>
54
+ <CharityRegistered>false</CharityRegistered>
55
+ <SafePaymentExempt>false</SafePaymentExempt>
56
+ <TransactionPercent>0.0</TransactionPercent>
57
+ <RecoupmentPolicyConsent />
58
+ <DomesticRateTable>false</DomesticRateTable>
59
+ <InternationalRateTable>false</InternationalRateTable>
60
+ </SellerInfo>
61
+ <BusinessRole>FullMarketPlaceParticipant</BusinessRole>
62
+ <eBayWikiReadOnly>false</eBayWikiReadOnly>
63
+ <MotorsDealer>false</MotorsDealer>
64
+ <UniqueNeutralFeedbackCount>0</UniqueNeutralFeedbackCount>
65
+ <EnterpriseSeller>false</EnterpriseSeller>
66
+ </User>
67
+ </GetUserResponse>
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe OmniAuth::EbayOauth::UserInfoRequest do
6
+ subject do
7
+ described_class.new(token, user_info_endpoint: endpoint, read_timeout: 20,
8
+ request: body)
9
+ end
10
+
11
+ let(:endpoint) { 'https://api.com/endpoint' }
12
+ let(:token) { 'token' }
13
+ let(:body) { '<>' }
14
+
15
+ let(:request_headers) { YAML.load_file('spec/fixtures/request_headers.yml') }
16
+ let(:failure_result) { File.read('spec/fixtures/result_failure.xml') }
17
+ let(:success_result) { File.read('spec/fixtures/result_success.xml') }
18
+
19
+ it 'raises error if eBay API request returned non-successful code' do
20
+ stub_request(:post, endpoint)
21
+ .with(body: body, headers: request_headers)
22
+ .to_return(status: 400, body: '', headers: {})
23
+ expect { subject.call }
24
+ .to raise_error(OmniAuth::EbayOauth::FailureResponseCode)
25
+ end
26
+
27
+ it 'raises error if eBay API returned non-successful result' do
28
+ stub_request(:post, endpoint)
29
+ .with(body: body, headers: request_headers)
30
+ .to_return(status: 200, body: failure_result, headers: {})
31
+ expect { subject.call }
32
+ .to raise_error(OmniAuth::EbayOauth::FailureResponseResult)
33
+ end
34
+
35
+ it 'returns parsed result from eBay in case of all is correct' do
36
+ stub_request(:post, endpoint)
37
+ .with(body: body, headers: request_headers)
38
+ .to_return(status: 200, body: success_result, headers: {})
39
+ expect(subject.call.fetch('GetUserResponse').keys)
40
+ .to eql %w[xmlns Timestamp Ack Version Build User]
41
+ end
42
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe OmniAuth::EbayOauth::UserInfo do
6
+ subject { described_class.new(parsed_body) }
7
+
8
+ let(:xml_body) { File.read('spec/fixtures/result_success.xml') }
9
+ let(:parsed_body) { MultiXml.parse(xml_body) }
10
+
11
+ context 'when passed invalid schema' do
12
+ let(:parsed_body) { {} }
13
+
14
+ it "raises error if can't find required uid" do
15
+ expect { subject.uid }
16
+ .to raise_error(OmniAuth::EbayOauth::UnsupportedSchemaError)
17
+ end
18
+
19
+ it "raises error if can't find required name" do
20
+ expect { subject.info }
21
+ .to raise_error(OmniAuth::EbayOauth::UnsupportedSchemaError)
22
+ end
23
+ end
24
+
25
+ describe '#uid' do
26
+ let(:uid) { 'nY+sHZ2PrKoij6wVnY+sEZ2PrA2dj6ACmYChC5WDoQydj6x9nY+seQ==' }
27
+
28
+ it 'returns user unique identification' do
29
+ expect(subject.uid).to eql uid
30
+ end
31
+ end
32
+
33
+ describe '#info' do
34
+ it 'returns user info corresponding to auth schema', :aggregate_failures do
35
+ {
36
+ name: 'Oleg Petrov',
37
+ email: 'olegpetrov@mail.com',
38
+ nickname: 'olegpetrov',
39
+ first_name: 'Oleg',
40
+ last_name: 'Petrov'
41
+ }.each do |key, value|
42
+ expect(subject.info.fetch(key)).to eql(value)
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '#extra' do
48
+ it 'returns user additional information', :aggregate_failures do
49
+ expect(subject.extra.keys).to eql %i[raw_info]
50
+ expect(subject.extra[:raw_info].keys)
51
+ .to eql %w[AboutMePage EIASToken Email FeedbackScore
52
+ UniqueNegativeFeedbackCount UniquePositiveFeedbackCount
53
+ PositiveFeedbackPercent FeedbackPrivate FeedbackRatingStar
54
+ IDVerified eBayGoodStanding NewUser RegistrationAddress
55
+ RegistrationDate Site Status UserID UserIDChanged VATStatus
56
+ SellerInfo BusinessRole eBayWikiReadOnly MotorsDealer
57
+ UniqueNeutralFeedbackCount EnterpriseSeller]
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe OmniAuth::Strategies::Ebay do
6
+ subject { described_class.new(nil, options) }
7
+
8
+ describe '#callback_url' do
9
+ let(:callback_url) { 'https://api.com/callback' }
10
+ let(:options) { { callback_url: callback_url } }
11
+ it 'uses options callback_url' do
12
+ expect(subject.callback_url).to eql(callback_url)
13
+ end
14
+ end
15
+
16
+ describe '#options' do
17
+ let(:options) { {} }
18
+
19
+ before { subject.setup_phase }
20
+
21
+ it 'default mode is sandbox' do
22
+ expect(subject.options.client_options.user_info_endpoint)
23
+ .to eq('https://api.sandbox.ebay.com/ws/api.dll')
24
+ end
25
+
26
+ context 'when setup block passed' do
27
+ let(:block) { proc { |_env| (@result ||= 0) && @result += 1 } }
28
+ let(:options) { { setup: block } }
29
+
30
+ it 'runs the setup block if passed one' do
31
+ expect(block.call).to eql 2
32
+ end
33
+ end
34
+
35
+ context "when scopes aren't passed" do
36
+ let(:options) { {} }
37
+
38
+ it 'uses empty string as scope' do
39
+ expect(subject.options.scope).to eql ''
40
+ end
41
+ end
42
+
43
+ context 'when scopes passed' do
44
+ context 'as array' do
45
+ let(:options) { { scope: %w[array like scopes] } }
46
+
47
+ it 'concatenates passed scopes with space' do
48
+ expect(subject.options.scope).to eql 'array like scopes'
49
+ end
50
+ end
51
+
52
+ context 'as string' do
53
+ let(:options) { { scope: 'scope as string' } }
54
+
55
+ it 'keeps scopes the same' do
56
+ expect(subject.options.scope).to eql 'scope as string'
57
+ end
58
+ end
59
+ end
60
+
61
+ context 'sandbox mode' do
62
+ let(:options) { { sandbox: true } }
63
+
64
+ it 'has correct eBay sandbox user info endpoint' do
65
+ expect(subject.options.client_options.user_info_endpoint)
66
+ .to eq('https://api.sandbox.ebay.com/ws/api.dll')
67
+ end
68
+
69
+ it 'has correct eBay sandbox token url' do
70
+ expect(subject.options.client_options.token_url)
71
+ .to eq('https://api.sandbox.ebay.com/identity/v1/oauth2/token')
72
+ end
73
+
74
+ it 'has correct eBay sandbox authorize url' do
75
+ expect(subject.options.client_options.authorize_url)
76
+ .to eq('https://signin.sandbox.ebay.com/authorize')
77
+ end
78
+ end
79
+
80
+ context 'production mode' do
81
+ let(:options) { { sandbox: false } }
82
+
83
+ it 'has correct eBay production user info endpoint' do
84
+ expect(subject.options.client_options.user_info_endpoint)
85
+ .to eq('https://api.ebay.com/ws/api.dll')
86
+ end
87
+
88
+ it 'has correct eBay production token url' do
89
+ expect(subject.options.client_options.token_url)
90
+ .to eq('https://api.ebay.com/identity/v1/oauth2/token')
91
+ end
92
+
93
+ it 'has correct eBay production authorize url' do
94
+ expect(subject.options.client_options.authorize_url)
95
+ .to eq('https://signin.ebay.com/authorize')
96
+ end
97
+ end
98
+ end
99
+
100
+ describe '#user_info' do
101
+ let(:access_token) { instance_double(OAuth2::AccessToken, token: :token) }
102
+ let(:options) { {} }
103
+ let(:user_info) { instance_double(OmniAuth::EbayOauth::UserInfo) }
104
+ let(:request) do
105
+ instance_double(OmniAuth::EbayOauth::UserInfoRequest, call: {})
106
+ end
107
+
108
+ before do
109
+ expect(subject).to receive(:access_token).and_return(access_token)
110
+ expect(OmniAuth::EbayOauth::UserInfoRequest)
111
+ .to receive(:new).and_return(request)
112
+ expect(OmniAuth::EbayOauth::UserInfo)
113
+ .to receive(:new).with({}).and_return(user_info)
114
+ end
115
+
116
+ it 'returns wrapped user info request' do
117
+ expect(subject.send(:user_info)).to eql(user_info)
118
+ end
119
+ end
120
+
121
+ describe '#credentials' do
122
+ let(:access_token) { OAuth2::AccessToken.new(client, token, opts) }
123
+ let(:options) { {} }
124
+
125
+ let(:client) { instance_double(OAuth2::Client) }
126
+ let(:token) { 'v^1.1#i^1#f^0#I^3#r^0#p^3#t^H4sIAAAAAAAAAOlongstringtoken' }
127
+ let(:opts) do
128
+ {
129
+ 'expires_in' => 7200,
130
+ 'refresh_token' => refresh_token,
131
+ 'refresh_token_expires_in' => expiration_time,
132
+ 'token_type' => 'User Access Token'
133
+ }
134
+ end
135
+
136
+ let(:refresh_token) { 'v^1.1#i^1#r^1#f^0#I^3#p^3#t^Urefreshtoken=' }
137
+ let(:expiration_time) { 47_304_000 }
138
+ let(:current_time) { Time.now.to_i }
139
+
140
+ before { allow(subject).to receive(:access_token).and_return(access_token) }
141
+
142
+ it 'adds refresh_token_expires_at for default OAuth2 credentials hash' do
143
+ expect(subject.credentials['refresh_token_expires_at'])
144
+ .to be_between(current_time, current_time + expiration_time)
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'webmock/rspec'
5
+ require 'simplecov'
6
+
7
+ SimpleCov.start do
8
+ add_filter 'spec/'
9
+ add_filter 'vendor/'
10
+ end
11
+
12
+ require 'omniauth-ebay-oauth'
13
+
14
+ OmniAuth.config.logger = Logger.new('/dev/null')
15
+
16
+ RSpec.configure do |config|
17
+ config.example_status_persistence_file_path = '.rspec_status'
18
+
19
+ config.disable_monkey_patching!
20
+
21
+ config.expect_with :rspec do |c|
22
+ c.syntax = :expect
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,180 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-ebay-oauth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ignat Zakrevsky
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: omniauth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: omniauth-oauth2
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.15'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.15'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '10'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '10'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.42'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.42'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.10'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.10'
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2.1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.1'
125
+ description:
126
+ email:
127
+ - iezakrevsky@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".rspec"
134
+ - ".rubocop.yml"
135
+ - ".ruby-version"
136
+ - ".travis.yml"
137
+ - Gemfile
138
+ - LICENSE
139
+ - README.md
140
+ - Rakefile
141
+ - lib/omniauth-ebay-oauth.rb
142
+ - lib/omniauth/ebay-oauth/errors.rb
143
+ - lib/omniauth/ebay-oauth/get_user.xml
144
+ - lib/omniauth/ebay-oauth/user_info.rb
145
+ - lib/omniauth/ebay-oauth/user_info_request.rb
146
+ - lib/omniauth/ebay-oauth/version.rb
147
+ - lib/omniauth/strategies/ebay.rb
148
+ - omniauth-ebay-oauth.gemspec
149
+ - spec/fixtures/request_headers.yml
150
+ - spec/fixtures/result_failure.xml
151
+ - spec/fixtures/result_success.xml
152
+ - spec/omniauth/ebay-oauth/user_info_request_spec.rb
153
+ - spec/omniauth/ebay-oauth/user_info_spec.rb
154
+ - spec/omniauth/strategies/ebay_spec.rb
155
+ - spec/spec_helper.rb
156
+ homepage: https://github.com/evilmartians/omniauth-ebay-oauth
157
+ licenses:
158
+ - MIT
159
+ metadata: {}
160
+ post_install_message:
161
+ rdoc_options: []
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '2.3'
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ requirements: []
175
+ rubyforge_project:
176
+ rubygems_version: 2.5.2.1
177
+ signing_key:
178
+ specification_version: 4
179
+ summary: OmniAuth strategy for new eBay OAuth API
180
+ test_files: []