easy_meli 0.3.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89f477f8757f02eec3581b7336db18264543b27dd335b5eda3c532fcf1566cec
4
- data.tar.gz: dc55656ac52fcbe17a58659ce619fd4f20e90a8334f7ab3a3956f13a3a61caf4
3
+ metadata.gz: bc240e7ae7a827cff6460162be1a9460f5e860676f3800a50d18ae3558f2976e
4
+ data.tar.gz: 714503d3e3886b1d491d1ea579d72f1d74e2408d476b9ada5ee6446f0efbb467
5
5
  SHA512:
6
- metadata.gz: 276d56f9e9dbd6fe0f6d544220b7942442fdf372ed8d22c5d6e87c1901dec997d8c6e432041cda289d1e855df08f76b449483ceb0bfc932afe8436d97a23b3e0
7
- data.tar.gz: '0588f3f0451f110057e54ade0e1a68bbaaf8180c4aaf8cdf92e26c9e7616c475c73961d6c5552327bc350620676ce899dc6b21d058a650e719a6442976c1b25e'
6
+ metadata.gz: 7004c03b3ec4be44170bb4ea92c5ac2595ddd5d244a7e680a88e67d5bdc9eec0197ae7a7bd0970ac78d0912e42f04b9b44a65ee907e5333db479f569753853b2
7
+ data.tar.gz: 139f426a07c7782b73ea52959283b70e068f8565d9c5e646790cd7f3373b51eed3f3e179d418a72ddf746012c13f4ea735a133c023b59da4c6d8d24aed38ab91
@@ -0,0 +1,32 @@
1
+ name: CI
2
+ on:
3
+ pull_request:
4
+ branches: [ master ]
5
+ push:
6
+ branches: [ master ]
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ ruby_version: [ '2.6' ]
13
+ steps:
14
+ - name: Checkout
15
+ uses: actions/checkout@v2
16
+ - name: Setup ruby ${{ matrix.ruby_version }}
17
+ uses: actions/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby_version }}
20
+ - name: Setup cache key and directory for gems cache
21
+ uses: actions/cache@v1
22
+ with:
23
+ path: vendor/bundle
24
+ key: ${{ runner.os }}-gem-use-ruby-${{ matrix.ruby_version }}-${{ hashFiles('**/Gemfile.lock') }}
25
+ - name: Bundle install
26
+ run: |
27
+ gem install bundler:1.17.0
28
+ bundle config path vendor/bundle
29
+ bundle install --jobs 4 --retry 3
30
+ - name: Run tests
31
+ run: |
32
+ bundle exec rake test
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ ## V 0.6.2
4
+ - Update Error classification mechanism to use error message as first option
5
+
6
+ ## V 0.6.1
7
+ - Fix a bug in the error raising in the authorization client introduced in V 0.6.0
8
+
9
+ ## V 0.6.0
10
+ - Classify an `invalid_token` response as an `InvalidTokenError`.
11
+ - `Malformed access_token` error changed from `AuthenticationError` to `InvalidTokenError`.
12
+
13
+ ## V 0.5.0
14
+ - `self.api_client` Prevent access_token override when initialize together with a refresh_token.
15
+ - Raises a EasyMeli::TooManyRequestsError if a 429 response status is returned.
data/README.md CHANGED
@@ -32,26 +32,26 @@ end
32
32
  To get the authorization url that the end-user uses to give your app authorization to access MercadoLibre on your part call the `authorization_url` with the desired country and the url to redirect to in order to complete the authorization.
33
33
 
34
34
  ```ruby
35
- EasyMeli::AuthorizationClient.authorization_url('MX', 'your_redirect_url')
35
+ EasyMeli.authorization_url('MX', 'your_redirect_url')
36
36
  ```
37
37
 
38
38
  Once MercadoLibre calls your redirect url you can get a refresh token by calling
39
39
 
40
40
  ```ruby
41
- response = EasyMeli::AuthorizationClient.new.create_token('the_code_in_the_redirect', 'the_same_redirect_url_as_above')
41
+ response = EasyMeli.create_token('the_code_in_the_redirect', 'the_same_redirect_url_as_above')
42
42
  ```
43
43
  This will return a response object with a json body that you can easily access via `response.to_h`.
44
44
 
45
- If you want to refresh the token call
45
+ If you want to refresh the token call
46
46
 
47
47
  ```ruby
48
- response = EasyMeli::AuthorizationClient.new.refresh_token('a_refresh_token')
48
+ access_token = EasyMeli.access_token('a_refresh_token')
49
49
  ```
50
50
 
51
51
  Once you can have an access token you can create a client and call the supported http verb methods.
52
52
 
53
53
  ```ruby
54
- client = EasyMeli::ApiClient.new(access_token)
54
+ client = EasyMeli.api_client(access_token: access_token)
55
55
 
56
56
  client.get(path, query: { a: 1 })
57
57
  client.post(path, query: { a: 1 }, body: { b: 1 })
@@ -59,25 +59,21 @@ client.put(path, query: { a: 1 }, body: { b: 1 })
59
59
  client.delete(path, query: { a: 1 })
60
60
  ```
61
61
 
62
- You can also pass a logger when instantiating the `EasyMeli::ApiClient` or `EasyMeli::AuthorizationClient`. The logger class must implement a `log` method which will be called with the [HTTParty response](https://www.rubydoc.info/github/jnunemaker/httparty/HTTParty/Response) for every remote request sent.
62
+ You can also pass a logger to any methods that make remote calls. The logger class must implement a `log` method which will be called with the [HTTParty response](https://www.rubydoc.info/github/jnunemaker/httparty/HTTParty/Response) for every remote request sent.
63
63
 
64
64
  ```ruby
65
- EasyMeli::AuthorizationClient.new(logger: my_logger)
66
- EasyMeli::ApiClient.new(access_token, logger: my_logger)
65
+ EasyMeli.create_token('the_code_in_the_redirect', 'the_same_redirect_url_as_above', logger: my_logger)
66
+ EasyMeli.api_client(refresh_token: refresh_token, logger: my_logger)
67
67
  ```
68
68
 
69
- ### Complete example showing how to retrieve a user profile
69
+ ### Example of how to retrieve a user profile
70
70
  ```ruby
71
71
  EasyMeli.configure do |config|
72
72
  config.application_id = "your_app_id"
73
73
  config.secret_key = "your_secret_key"
74
74
  end
75
75
 
76
- authorization_client = EasyMeli::AuthorizationClient.new
77
- token = authorization_client.refresh_token(previously_stored_refresh_token).to_h['access_token']
78
-
79
- api_client = EasyMeli::ApiClient.new(token)
80
-
76
+ api_client = EasyMeli.api_client(refresh_token: refresh_token)
81
77
  response = api_client.get('/users/me')
82
78
 
83
79
  ```
@@ -16,4 +16,21 @@ module EasyMeli
16
16
  def self.configure
17
17
  yield(configuration)
18
18
  end
19
+
20
+ def self.authorization_url(country_code, redirect_uri)
21
+ EasyMeli::AuthorizationClient.authorization_url(country_code, redirect_uri)
22
+ end
23
+
24
+ def self.create_token(code, redirect_uri, logger: nil)
25
+ EasyMeli::AuthorizationClient.create_token(code, redirect_uri, logger: logger)
26
+ end
27
+
28
+ def self.access_token(refresh_token, logger: nil)
29
+ EasyMeli::AuthorizationClient.access_token(refresh_token, logger: logger)
30
+ end
31
+
32
+ def self.api_client(access_token: nil, refresh_token: nil, logger: nil)
33
+ access_token ||= self.access_token(refresh_token, logger: logger) if refresh_token
34
+ EasyMeli::ApiClient.new(access_token, logger: logger)
35
+ end
19
36
  end
@@ -5,19 +5,21 @@ class EasyMeli::ApiClient
5
5
 
6
6
  API_ROOT_URL = 'https://api.mercadolibre.com'
7
7
 
8
- TOKEN_ERRORS = {
9
- 'invalid_grant' => 'Invalid Grant',
10
- 'forbidden' => 'Forbidden',
11
- 'Malformed access_token' => 'Malformed access token'
8
+ ERROR_LIST = {
9
+ 'Error validating grant' => EasyMeli::InvalidGrantError,
10
+ 'forbidden' => EasyMeli::ForbiddenError,
11
+ 'invalid_token' => EasyMeli::InvalidTokenError,
12
+ 'Malformed access_token' => EasyMeli::MalformedTokenError,
13
+ 'too_many_requests' => EasyMeli::TooManyRequestsError
12
14
  }
13
15
 
14
- base_uri API_ROOT_URL
16
+ base_uri API_ROOT_URL
15
17
  headers EasyMeli::DEFAULT_HEADERS
16
18
  format :json
17
19
 
18
20
  attr_reader :logger, :access_token
19
21
 
20
- def initialize(access_token, logger: nil)
22
+ def initialize(access_token = nil, logger: nil)
21
23
  @logger = logger
22
24
  @access_token = access_token
23
25
  end
@@ -42,27 +44,31 @@ class EasyMeli::ApiClient
42
44
 
43
45
  def send_request(verb, path = '', params = {})
44
46
  query = params[:query] || params['query'] || {}
45
- query[:access_token] = access_token
47
+ query[:access_token] = access_token if access_token
46
48
 
47
49
  self.class.send(verb, path, params.merge(query)).tap do |response|
48
50
  logger&.log response
49
- check_authentication(response)
51
+ check_for_errors(response)
50
52
  end
51
53
  end
52
54
 
53
- def check_authentication(response)
54
- response_message = error_message_from_body(response.to_h) if response.parsed_response.is_a? Hash
55
- return if response_message.to_s.empty?
55
+ def check_for_errors(response)
56
+ return unless response.parsed_response.is_a? Hash
56
57
 
57
- TOKEN_ERRORS.keys.each do |key|
58
- if response_message.include?(key)
59
- raise EasyMeli::AuthenticationError.new(TOKEN_ERRORS[key], response)
60
- end
58
+ exception = error_class(response)
59
+
60
+ if exception
61
+ raise exception.new(response)
61
62
  end
62
63
  end
63
64
 
64
- def error_message_from_body(body)
65
- return if body.nil?
66
- body['error'].to_s.empty? ? body['message'] : body['error']
65
+ def error_class(body)
66
+ ERROR_LIST.find { |key, _| error_message_from_body(body).include?(key) }&.last
67
+ end
68
+
69
+ def error_message_from_body(response)
70
+ return if response.body.nil?
71
+
72
+ response['message'].to_s.empty? ? response['error'] : response['message']
67
73
  end
68
74
  end
@@ -20,6 +20,7 @@ class EasyMeli::AuthorizationClient
20
20
  PT: 'https://auth.mercadolibre.com.pt',
21
21
  DO: 'https://auth.mercadolibre.com.do'
22
22
  }
23
+ ACCESS_TOKEN_KEY = 'access_token'
23
24
 
24
25
  headers EasyMeli::DEFAULT_HEADERS
25
26
  format :json
@@ -34,12 +35,30 @@ class EasyMeli::AuthorizationClient
34
35
  params = {
35
36
  client_id: EasyMeli.configuration.application_id,
36
37
  response_type: 'code',
37
- redirect_uri: redirect_uri
38
+ redirect_uri: redirect_uri
38
39
  }
39
40
  HTTParty::Request.new(:get, country_auth_url(country_code), query: params).uri.to_s
40
41
  end
41
42
 
42
- def create_token(code, redirect_uri)
43
+ def self.create_token(code, redirect_uri, logger: nil)
44
+ response = self.new(logger: logger).create_token_with_response(code, redirect_uri)
45
+ if response.success?
46
+ response.to_h
47
+ else
48
+ raise EasyMeli::CreateTokenError.new(response)
49
+ end
50
+ end
51
+
52
+ def self.access_token(refresh_token, logger: nil)
53
+ response = self.new(logger: logger).access_token_with_response(refresh_token)
54
+ if response.success?
55
+ response.to_h[EasyMeli::AuthorizationClient::ACCESS_TOKEN_KEY]
56
+ else
57
+ raise EasyMeli::InvalidTokenError.new(response)
58
+ end
59
+ end
60
+
61
+ def create_token_with_response(code, redirect_uri)
43
62
  query_params = merge_auth_params(
44
63
  grant_type: 'authorization_code',
45
64
  code: code,
@@ -48,7 +67,7 @@ class EasyMeli::AuthorizationClient
48
67
  post_auth(query_params)
49
68
  end
50
69
 
51
- def refresh_token(refresh_token)
70
+ def access_token_with_response(refresh_token)
52
71
  query_params = merge_auth_params(
53
72
  grant_type: 'refresh_token',
54
73
  refresh_token: refresh_token
@@ -65,7 +84,7 @@ class EasyMeli::AuthorizationClient
65
84
  end
66
85
 
67
86
  def self.country_auth_url(country_code)
68
- url = BASE_AUTH_URLS[country_code.to_s.upcase.to_sym] ||
87
+ url = BASE_AUTH_URLS[country_code.to_s.upcase.to_sym] ||
69
88
  (raise ArgumentError.new('%s is an invalid country code' % country_code))
70
89
  [url, AUTH_PATH].join
71
90
  end
@@ -76,4 +95,4 @@ class EasyMeli::AuthorizationClient
76
95
  client_secret: EasyMeli.configuration.secret_key
77
96
  )
78
97
  end
79
- end
98
+ end
@@ -2,11 +2,67 @@ module EasyMeli
2
2
  class Error < StandardError
3
3
  attr_reader :response
4
4
 
5
- def initialize(message, response)
5
+ def initialize(response)
6
6
  @response = response
7
- super(message)
7
+ super(local_message)
8
+ end
9
+
10
+ private
11
+
12
+ def local_message
13
+ raise NotImplementedError
8
14
  end
9
15
  end
10
16
 
11
17
  class AuthenticationError < Error; end
12
- end
18
+
19
+ class CreateTokenError < AuthenticationError
20
+ private
21
+
22
+ def local_message
23
+ 'Error Creating Token'
24
+ end
25
+ end
26
+
27
+ class InvalidGrantError < AuthenticationError
28
+ private
29
+
30
+ def local_message
31
+ 'Invalid Grant'
32
+ end
33
+ end
34
+
35
+ class ForbiddenError < AuthenticationError
36
+ private
37
+
38
+ def local_message
39
+ 'Forbidden'
40
+ end
41
+ end
42
+
43
+ class AccessTokenError < Error; end
44
+
45
+ class InvalidTokenError < AccessTokenError
46
+ private
47
+
48
+ def local_message
49
+ 'Invalid Token'
50
+ end
51
+ end
52
+
53
+ class MalformedTokenError < AccessTokenError
54
+ private
55
+
56
+ def local_message
57
+ 'Malformed access token'
58
+ end
59
+ end
60
+
61
+ class TooManyRequestsError < Error
62
+ private
63
+
64
+ def local_message
65
+ 'Too many requests'
66
+ end
67
+ end
68
+ end
@@ -1,3 +1,3 @@
1
1
  module EasyMeli
2
- VERSION = "0.3.1"
2
+ VERSION = "0.6.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_meli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Northam
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-18 00:00:00.000000000 Z
11
+ date: 2021-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -108,14 +108,16 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
- description:
111
+ description:
112
112
  email:
113
113
  - eric@northam.us
114
114
  executables: []
115
115
  extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
+ - ".github/workflows/ci.yml"
118
119
  - ".gitignore"
120
+ - CHANGELOG.md
119
121
  - Gemfile
120
122
  - LICENSE.txt
121
123
  - README.md
@@ -135,7 +137,7 @@ licenses:
135
137
  - MIT
136
138
  metadata:
137
139
  homepage_uri: https://github.com/easybroker/easy_meli
138
- post_install_message:
140
+ post_install_message:
139
141
  rdoc_options: []
140
142
  require_paths:
141
143
  - lib
@@ -150,8 +152,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
152
  - !ruby/object:Gem::Version
151
153
  version: '0'
152
154
  requirements: []
153
- rubygems_version: 3.0.3
154
- signing_key:
155
+ rubygems_version: 3.1.4
156
+ signing_key:
155
157
  specification_version: 4
156
158
  summary: A simple gem to work with MercadoLibre's API
157
159
  test_files: []