easy_meli 0.3.0 → 0.6.1

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: d17badfe56ecab178ff6cb784e9d78bb8c0cd4ac9421e5ea356a52212622c76a
4
- data.tar.gz: 4f40821e57261ade83265e971ea8a45a85db038fff68b26744daeaedf80c87fd
3
+ metadata.gz: 8c8dc1140d9368b076baf0a49a9742aea8de95565a90512152c9c58ec2b98723
4
+ data.tar.gz: 543cbed2c4789b0259b62f11d332a02c3b5b281feb2c5b60c5f87fd8640c0754
5
5
  SHA512:
6
- metadata.gz: 8b95637656926bd1b393ed569c136cb5f486b2c76ec46ef733eabb1746ef52a062d4f669c0b068ca93c2dd0dc52641483b9866304fa10a9e8c22847254971387
7
- data.tar.gz: 5c2310fbd9282c91f5777596d05f3504585cd394f3f31a59a1a514a41953593cd5422c87db971f4b3a5ce77b6989e8251676d7bd6257135fff79d24915ca3e30
6
+ metadata.gz: c2a7ecfa32beed3a9329b01312b1cfd4ed70fceb26469dc90e8d0d2c3b42186a9c1ec06f115f1dc5fa15236aa48d99b7e074a089fad7f710bddaf2bcb324680a
7
+ data.tar.gz: dfc01a8544c0f2d23711888fdfa3fb6a6f6f68196782d41cb501c1f50d53900882fb5c1b8d7a9f88e610eb1fafc8112447943ff87b8793af7fccd29e800a6d17
@@ -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,12 @@
1
+ # Changelog
2
+
3
+ ## V 0.6.1
4
+ - Fix a bug in the error raising in the authorization client introduced in V 0.6.0
5
+
6
+ ## V 0.6.0
7
+ - Classify an `invalid_token` response as an `InvalidTokenError`.
8
+ - `Malformed access_token` error changed from `AuthenticationError` to `InvalidTokenError`.
9
+
10
+ ## V 0.5.0
11
+ - `self.api_client` Prevent access_token override when initialize together with a refresh_token.
12
+ - 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
  ```
@@ -1,12 +1,14 @@
1
1
  require 'httparty'
2
2
 
3
3
  require 'easy_meli/version'
4
+ require 'easy_meli/constants'
4
5
  require 'easy_meli/errors'
5
6
  require 'easy_meli/configuration'
6
7
  require 'easy_meli/authorization_client'
7
8
  require 'easy_meli/api_client'
8
9
 
9
10
  module EasyMeli
11
+
10
12
  def self.configuration
11
13
  @configuration ||= Configuration.new
12
14
  end
@@ -14,4 +16,21 @@ module EasyMeli
14
16
  def self.configure
15
17
  yield(configuration)
16
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
17
36
  end
@@ -5,18 +5,24 @@ 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
+ 'invalid_grant' => EasyMeli::InvalidGrantError,
10
+ 'forbidden' => EasyMeli::ForbiddenError,
11
+ 'invalid_token' => EasyMeli::InvalidTokenError,
12
+ 'Malformed access_token' => EasyMeli::MalformedTokenError
12
13
  }
13
14
 
14
- base_uri API_ROOT_URL
15
+ STATUS_ERRORS = {
16
+ 429 => EasyMeli::TooManyRequestsError
17
+ }
18
+
19
+ base_uri API_ROOT_URL
20
+ headers EasyMeli::DEFAULT_HEADERS
15
21
  format :json
16
22
 
17
23
  attr_reader :logger, :access_token
18
24
 
19
- def initialize(access_token, logger: nil)
25
+ def initialize(access_token = nil, logger: nil)
20
26
  @logger = logger
21
27
  @access_token = access_token
22
28
  end
@@ -41,20 +47,23 @@ class EasyMeli::ApiClient
41
47
 
42
48
  def send_request(verb, path = '', params = {})
43
49
  query = params[:query] || params['query'] || {}
44
- query[:access_token] = access_token
50
+ query[:access_token] = access_token if access_token
51
+
45
52
  self.class.send(verb, path, params.merge(query)).tap do |response|
46
53
  logger&.log response
47
54
  check_authentication(response)
55
+ check_status(response)
48
56
  end
49
57
  end
50
58
 
51
59
  def check_authentication(response)
52
- response_message = error_message_from_body(response.to_h)
60
+ response_message = error_message_from_body(response.to_h) if response.parsed_response.is_a? Hash
53
61
  return if response_message.to_s.empty?
54
-
55
- TOKEN_ERRORS.keys.each do |key|
62
+
63
+ ERROR_LIST.keys.each do |key|
56
64
  if response_message.include?(key)
57
- raise EasyMeli::AuthenticationError.new(TOKEN_ERRORS[key], response)
65
+ exception = ERROR_LIST[key]
66
+ raise exception.new(response)
58
67
  end
59
68
  end
60
69
  end
@@ -63,4 +72,9 @@ class EasyMeli::ApiClient
63
72
  return if body.nil?
64
73
  body['error'].to_s.empty? ? body['message'] : body['error']
65
74
  end
66
- end
75
+
76
+ def check_status(response)
77
+ status_error = STATUS_ERRORS[response.code]
78
+ raise status_error.new(response) if status_error
79
+ end
80
+ end
@@ -20,7 +20,9 @@ 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
 
25
+ headers EasyMeli::DEFAULT_HEADERS
24
26
  format :json
25
27
 
26
28
  attr_reader :logger
@@ -33,12 +35,30 @@ class EasyMeli::AuthorizationClient
33
35
  params = {
34
36
  client_id: EasyMeli.configuration.application_id,
35
37
  response_type: 'code',
36
- redirect_uri: redirect_uri
38
+ redirect_uri: redirect_uri
37
39
  }
38
40
  HTTParty::Request.new(:get, country_auth_url(country_code), query: params).uri.to_s
39
41
  end
40
42
 
41
- 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)
42
62
  query_params = merge_auth_params(
43
63
  grant_type: 'authorization_code',
44
64
  code: code,
@@ -47,7 +67,7 @@ class EasyMeli::AuthorizationClient
47
67
  post_auth(query_params)
48
68
  end
49
69
 
50
- def refresh_token(refresh_token)
70
+ def access_token_with_response(refresh_token)
51
71
  query_params = merge_auth_params(
52
72
  grant_type: 'refresh_token',
53
73
  refresh_token: refresh_token
@@ -64,7 +84,7 @@ class EasyMeli::AuthorizationClient
64
84
  end
65
85
 
66
86
  def self.country_auth_url(country_code)
67
- url = BASE_AUTH_URLS[country_code.to_s.upcase.to_sym] ||
87
+ url = BASE_AUTH_URLS[country_code.to_s.upcase.to_sym] ||
68
88
  (raise ArgumentError.new('%s is an invalid country code' % country_code))
69
89
  [url, AUTH_PATH].join
70
90
  end
@@ -75,4 +95,4 @@ class EasyMeli::AuthorizationClient
75
95
  client_secret: EasyMeli.configuration.secret_key
76
96
  )
77
97
  end
78
- end
98
+ end
@@ -0,0 +1,8 @@
1
+ module EasyMeli
2
+ USER_AGENT = "EasyMeli-%s" % VERSION
3
+ DEFAULT_HEADERS = {
4
+ 'Content-Type' => 'application/json',
5
+ 'Accept' => 'application/json',
6
+ 'User-Agent' => USER_AGENT
7
+ }
8
+ 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.0"
2
+ VERSION = "0.6.1"
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.0
4
+ version: 0.6.1
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-15 00:00:00.000000000 Z
11
+ date: 2021-01-27 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
@@ -127,6 +129,7 @@ files:
127
129
  - lib/easy_meli/api_client.rb
128
130
  - lib/easy_meli/authorization_client.rb
129
131
  - lib/easy_meli/configuration.rb
132
+ - lib/easy_meli/constants.rb
130
133
  - lib/easy_meli/errors.rb
131
134
  - lib/easy_meli/version.rb
132
135
  homepage: https://github.com/easybroker/easy_meli
@@ -134,7 +137,7 @@ licenses:
134
137
  - MIT
135
138
  metadata:
136
139
  homepage_uri: https://github.com/easybroker/easy_meli
137
- post_install_message:
140
+ post_install_message:
138
141
  rdoc_options: []
139
142
  require_paths:
140
143
  - lib
@@ -149,8 +152,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
152
  - !ruby/object:Gem::Version
150
153
  version: '0'
151
154
  requirements: []
152
- rubygems_version: 3.0.3
153
- signing_key:
155
+ rubygems_version: 3.1.4
156
+ signing_key:
154
157
  specification_version: 4
155
158
  summary: A simple gem to work with MercadoLibre's API
156
159
  test_files: []