easy_meli 0.3.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []