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 +4 -4
- data/.github/workflows/ci.yml +32 -0
- data/CHANGELOG.md +15 -0
- data/README.md +10 -14
- data/lib/easy_meli.rb +17 -0
- data/lib/easy_meli/api_client.rb +24 -18
- data/lib/easy_meli/authorization_client.rb +24 -5
- data/lib/easy_meli/errors.rb +59 -3
- data/lib/easy_meli/version.rb +1 -1
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc240e7ae7a827cff6460162be1a9460f5e860676f3800a50d18ae3558f2976e
|
4
|
+
data.tar.gz: 714503d3e3886b1d491d1ea579d72f1d74e2408d476b9ada5ee6446f0efbb467
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/CHANGELOG.md
ADDED
@@ -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
|
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
|
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
|
-
|
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
|
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
|
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
|
66
|
-
EasyMeli
|
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
|
-
###
|
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
|
-
|
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
|
```
|
data/lib/easy_meli.rb
CHANGED
@@ -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
|
data/lib/easy_meli/api_client.rb
CHANGED
@@ -5,19 +5,21 @@ class EasyMeli::ApiClient
|
|
5
5
|
|
6
6
|
API_ROOT_URL = 'https://api.mercadolibre.com'
|
7
7
|
|
8
|
-
|
9
|
-
'
|
10
|
-
'forbidden' =>
|
11
|
-
'
|
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
|
-
|
51
|
+
check_for_errors(response)
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
|
-
def
|
54
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
exception = error_class(response)
|
59
|
+
|
60
|
+
if exception
|
61
|
+
raise exception.new(response)
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
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
|
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
|
data/lib/easy_meli/errors.rb
CHANGED
@@ -2,11 +2,67 @@ module EasyMeli
|
|
2
2
|
class Error < StandardError
|
3
3
|
attr_reader :response
|
4
4
|
|
5
|
-
def initialize(
|
5
|
+
def initialize(response)
|
6
6
|
@response = response
|
7
|
-
super(
|
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
|
-
|
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
|
data/lib/easy_meli/version.rb
CHANGED
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.
|
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:
|
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.
|
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: []
|